19ef9925131835743f5316393758c14532c06277dAngus Kong/*
29ef9925131835743f5316393758c14532c06277dAngus Kong * Copyright (C) 2013 The Android Open Source Project
39ef9925131835743f5316393758c14532c06277dAngus Kong *
49ef9925131835743f5316393758c14532c06277dAngus Kong * Licensed under the Apache License, Version 2.0 (the "License");
59ef9925131835743f5316393758c14532c06277dAngus Kong * you may not use this file except in compliance with the License.
69ef9925131835743f5316393758c14532c06277dAngus Kong * You may obtain a copy of the License at
79ef9925131835743f5316393758c14532c06277dAngus Kong *
89ef9925131835743f5316393758c14532c06277dAngus Kong *      http://www.apache.org/licenses/LICENSE-2.0
99ef9925131835743f5316393758c14532c06277dAngus Kong *
109ef9925131835743f5316393758c14532c06277dAngus Kong * Unless required by applicable law or agreed to in writing, software
119ef9925131835743f5316393758c14532c06277dAngus Kong * distributed under the License is distributed on an "AS IS" BASIS,
129ef9925131835743f5316393758c14532c06277dAngus Kong * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139ef9925131835743f5316393758c14532c06277dAngus Kong * See the License for the specific language governing permissions and
149ef9925131835743f5316393758c14532c06277dAngus Kong * limitations under the License.
159ef9925131835743f5316393758c14532c06277dAngus Kong */
169ef9925131835743f5316393758c14532c06277dAngus Kong
179ef9925131835743f5316393758c14532c06277dAngus Kongpackage com.android.camera;
189ef9925131835743f5316393758c14532c06277dAngus Kong
19b50b5cbfbc0a67db6fc43373363b10381c9c61a3Angus Kongimport static com.android.camera.util.CameraUtil.Assert;
209ef9925131835743f5316393758c14532c06277dAngus Kong
218e963a5a6016d246184ed65906f9d103e92b17e2Sascha Haeberlingimport java.io.IOException;
228e963a5a6016d246184ed65906f9d103e92b17e2Sascha Haeberling
239ef9925131835743f5316393758c14532c06277dAngus Kongimport android.annotation.TargetApi;
249ef9925131835743f5316393758c14532c06277dAngus Kongimport android.graphics.SurfaceTexture;
259ef9925131835743f5316393758c14532c06277dAngus Kongimport android.hardware.Camera;
269ef9925131835743f5316393758c14532c06277dAngus Kongimport android.hardware.Camera.AutoFocusCallback;
279ef9925131835743f5316393758c14532c06277dAngus Kongimport android.hardware.Camera.AutoFocusMoveCallback;
289ef9925131835743f5316393758c14532c06277dAngus Kongimport android.hardware.Camera.ErrorCallback;
299ef9925131835743f5316393758c14532c06277dAngus Kongimport android.hardware.Camera.FaceDetectionListener;
309ef9925131835743f5316393758c14532c06277dAngus Kongimport android.hardware.Camera.OnZoomChangeListener;
319ef9925131835743f5316393758c14532c06277dAngus Kongimport android.hardware.Camera.Parameters;
329ef9925131835743f5316393758c14532c06277dAngus Kongimport android.hardware.Camera.PictureCallback;
339ef9925131835743f5316393758c14532c06277dAngus Kongimport android.hardware.Camera.PreviewCallback;
349ef9925131835743f5316393758c14532c06277dAngus Kongimport android.hardware.Camera.ShutterCallback;
35638e6f06c877d90b907f66ea9c22b3c6b73c7384Sascha Haeberlingimport android.os.Build;
369ef9925131835743f5316393758c14532c06277dAngus Kongimport android.os.Handler;
379ef9925131835743f5316393758c14532c06277dAngus Kongimport android.os.HandlerThread;
389ef9925131835743f5316393758c14532c06277dAngus Kongimport android.os.Looper;
399ef9925131835743f5316393758c14532c06277dAngus Kongimport android.os.Message;
409ef9925131835743f5316393758c14532c06277dAngus Kongimport android.util.Log;
419ef9925131835743f5316393758c14532c06277dAngus Kongimport android.view.SurfaceHolder;
429ef9925131835743f5316393758c14532c06277dAngus Kong
439ef9925131835743f5316393758c14532c06277dAngus Kong/**
449ef9925131835743f5316393758c14532c06277dAngus Kong * A class to implement {@link CameraManager} of the Android camera framework.
459ef9925131835743f5316393758c14532c06277dAngus Kong */
469ef9925131835743f5316393758c14532c06277dAngus Kongclass AndroidCameraManagerImpl implements CameraManager {
479ef9925131835743f5316393758c14532c06277dAngus Kong    private static final String TAG = "CAM_" +
489ef9925131835743f5316393758c14532c06277dAngus Kong            AndroidCameraManagerImpl.class.getSimpleName();
499ef9925131835743f5316393758c14532c06277dAngus Kong
509ef9925131835743f5316393758c14532c06277dAngus Kong    private Parameters mParameters;
519ef9925131835743f5316393758c14532c06277dAngus Kong    private boolean mParametersIsDirty;
529ef9925131835743f5316393758c14532c06277dAngus Kong    private IOException mReconnectIOException;
539ef9925131835743f5316393758c14532c06277dAngus Kong
549ef9925131835743f5316393758c14532c06277dAngus Kong    /* Messages used in CameraHandler. */
559ef9925131835743f5316393758c14532c06277dAngus Kong    // Camera initialization/finalization
569ef9925131835743f5316393758c14532c06277dAngus Kong    private static final int OPEN_CAMERA = 1;
579ef9925131835743f5316393758c14532c06277dAngus Kong    private static final int RELEASE =     2;
589ef9925131835743f5316393758c14532c06277dAngus Kong    private static final int RECONNECT =   3;
599ef9925131835743f5316393758c14532c06277dAngus Kong    private static final int UNLOCK =      4;
609ef9925131835743f5316393758c14532c06277dAngus Kong    private static final int LOCK =        5;
619ef9925131835743f5316393758c14532c06277dAngus Kong    // Preview
629ef9925131835743f5316393758c14532c06277dAngus Kong    private static final int SET_PREVIEW_TEXTURE_ASYNC =        101;
639ef9925131835743f5316393758c14532c06277dAngus Kong    private static final int START_PREVIEW_ASYNC =              102;
649ef9925131835743f5316393758c14532c06277dAngus Kong    private static final int STOP_PREVIEW =                     103;
659ef9925131835743f5316393758c14532c06277dAngus Kong    private static final int SET_PREVIEW_CALLBACK_WITH_BUFFER = 104;
669ef9925131835743f5316393758c14532c06277dAngus Kong    private static final int ADD_CALLBACK_BUFFER =              105;
679ef9925131835743f5316393758c14532c06277dAngus Kong    private static final int SET_PREVIEW_DISPLAY_ASYNC =        106;
689ef9925131835743f5316393758c14532c06277dAngus Kong    private static final int SET_PREVIEW_CALLBACK =             107;
699ef9925131835743f5316393758c14532c06277dAngus Kong    // Parameters
709ef9925131835743f5316393758c14532c06277dAngus Kong    private static final int SET_PARAMETERS =     201;
719ef9925131835743f5316393758c14532c06277dAngus Kong    private static final int GET_PARAMETERS =     202;
729ef9925131835743f5316393758c14532c06277dAngus Kong    private static final int REFRESH_PARAMETERS = 203;
739ef9925131835743f5316393758c14532c06277dAngus Kong    // Focus, Zoom
749ef9925131835743f5316393758c14532c06277dAngus Kong    private static final int AUTO_FOCUS =                   301;
759ef9925131835743f5316393758c14532c06277dAngus Kong    private static final int CANCEL_AUTO_FOCUS =            302;
769ef9925131835743f5316393758c14532c06277dAngus Kong    private static final int SET_AUTO_FOCUS_MOVE_CALLBACK = 303;
779ef9925131835743f5316393758c14532c06277dAngus Kong    private static final int SET_ZOOM_CHANGE_LISTENER =     304;
789ef9925131835743f5316393758c14532c06277dAngus Kong    // Face detection
799ef9925131835743f5316393758c14532c06277dAngus Kong    private static final int SET_FACE_DETECTION_LISTENER = 461;
809ef9925131835743f5316393758c14532c06277dAngus Kong    private static final int START_FACE_DETECTION =        462;
819ef9925131835743f5316393758c14532c06277dAngus Kong    private static final int STOP_FACE_DETECTION =         463;
829ef9925131835743f5316393758c14532c06277dAngus Kong    private static final int SET_ERROR_CALLBACK =          464;
839ef9925131835743f5316393758c14532c06277dAngus Kong    // Presentation
849ef9925131835743f5316393758c14532c06277dAngus Kong    private static final int ENABLE_SHUTTER_SOUND =    501;
859ef9925131835743f5316393758c14532c06277dAngus Kong    private static final int SET_DISPLAY_ORIENTATION = 502;
869ef9925131835743f5316393758c14532c06277dAngus Kong
879ef9925131835743f5316393758c14532c06277dAngus Kong    private CameraHandler mCameraHandler;
889ef9925131835743f5316393758c14532c06277dAngus Kong    private android.hardware.Camera mCamera;
899ef9925131835743f5316393758c14532c06277dAngus Kong
909ef9925131835743f5316393758c14532c06277dAngus Kong    // Used to retain a copy of Parameters for setting parameters.
919ef9925131835743f5316393758c14532c06277dAngus Kong    private Parameters mParamsToSet;
929ef9925131835743f5316393758c14532c06277dAngus Kong
939ef9925131835743f5316393758c14532c06277dAngus Kong    AndroidCameraManagerImpl() {
949ef9925131835743f5316393758c14532c06277dAngus Kong        HandlerThread ht = new HandlerThread("Camera Handler Thread");
959ef9925131835743f5316393758c14532c06277dAngus Kong        ht.start();
969ef9925131835743f5316393758c14532c06277dAngus Kong        mCameraHandler = new CameraHandler(ht.getLooper());
979ef9925131835743f5316393758c14532c06277dAngus Kong    }
989ef9925131835743f5316393758c14532c06277dAngus Kong
999ef9925131835743f5316393758c14532c06277dAngus Kong    private class CameraHandler extends Handler {
1009ef9925131835743f5316393758c14532c06277dAngus Kong        CameraHandler(Looper looper) {
1019ef9925131835743f5316393758c14532c06277dAngus Kong            super(looper);
1029ef9925131835743f5316393758c14532c06277dAngus Kong        }
1039ef9925131835743f5316393758c14532c06277dAngus Kong
1049ef9925131835743f5316393758c14532c06277dAngus Kong        private void startFaceDetection() {
1059ef9925131835743f5316393758c14532c06277dAngus Kong            mCamera.startFaceDetection();
1069ef9925131835743f5316393758c14532c06277dAngus Kong        }
1079ef9925131835743f5316393758c14532c06277dAngus Kong
1089ef9925131835743f5316393758c14532c06277dAngus Kong        private void stopFaceDetection() {
1099ef9925131835743f5316393758c14532c06277dAngus Kong            mCamera.stopFaceDetection();
1109ef9925131835743f5316393758c14532c06277dAngus Kong        }
1119ef9925131835743f5316393758c14532c06277dAngus Kong
1129ef9925131835743f5316393758c14532c06277dAngus Kong        private void setFaceDetectionListener(FaceDetectionListener listener) {
1139ef9925131835743f5316393758c14532c06277dAngus Kong            mCamera.setFaceDetectionListener(listener);
1149ef9925131835743f5316393758c14532c06277dAngus Kong        }
1159ef9925131835743f5316393758c14532c06277dAngus Kong
1169ef9925131835743f5316393758c14532c06277dAngus Kong        private void setPreviewTexture(Object surfaceTexture) {
1179ef9925131835743f5316393758c14532c06277dAngus Kong            try {
1189ef9925131835743f5316393758c14532c06277dAngus Kong                mCamera.setPreviewTexture((SurfaceTexture) surfaceTexture);
1199ef9925131835743f5316393758c14532c06277dAngus Kong            } catch (IOException e) {
120464f22013750a416f9fc9a1e32007576d0b655d6Sascha Haeberling                Log.e(TAG, "Could not set preview texture", e);
1219ef9925131835743f5316393758c14532c06277dAngus Kong            }
1229ef9925131835743f5316393758c14532c06277dAngus Kong        }
1239ef9925131835743f5316393758c14532c06277dAngus Kong
124638e6f06c877d90b907f66ea9c22b3c6b73c7384Sascha Haeberling        @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
1259ef9925131835743f5316393758c14532c06277dAngus Kong        private void enableShutterSound(boolean enable) {
1269ef9925131835743f5316393758c14532c06277dAngus Kong            mCamera.enableShutterSound(enable);
1279ef9925131835743f5316393758c14532c06277dAngus Kong        }
1289ef9925131835743f5316393758c14532c06277dAngus Kong
129638e6f06c877d90b907f66ea9c22b3c6b73c7384Sascha Haeberling        @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
1309ef9925131835743f5316393758c14532c06277dAngus Kong        private void setAutoFocusMoveCallback(
1319ef9925131835743f5316393758c14532c06277dAngus Kong                android.hardware.Camera camera, Object cb) {
1329ef9925131835743f5316393758c14532c06277dAngus Kong            camera.setAutoFocusMoveCallback((AutoFocusMoveCallback) cb);
1339ef9925131835743f5316393758c14532c06277dAngus Kong        }
1349ef9925131835743f5316393758c14532c06277dAngus Kong
1359ef9925131835743f5316393758c14532c06277dAngus Kong        public void requestTakePicture(
1369ef9925131835743f5316393758c14532c06277dAngus Kong                final ShutterCallback shutter,
1379ef9925131835743f5316393758c14532c06277dAngus Kong                final PictureCallback raw,
1389ef9925131835743f5316393758c14532c06277dAngus Kong                final PictureCallback postView,
1399ef9925131835743f5316393758c14532c06277dAngus Kong                final PictureCallback jpeg) {
1409ef9925131835743f5316393758c14532c06277dAngus Kong            post(new Runnable() {
1419ef9925131835743f5316393758c14532c06277dAngus Kong                @Override
1429ef9925131835743f5316393758c14532c06277dAngus Kong                public void run() {
1439ef9925131835743f5316393758c14532c06277dAngus Kong                    try {
1449ef9925131835743f5316393758c14532c06277dAngus Kong                        mCamera.takePicture(shutter, raw, postView, jpeg);
1459ef9925131835743f5316393758c14532c06277dAngus Kong                    } catch (RuntimeException e) {
1469ef9925131835743f5316393758c14532c06277dAngus Kong                        // TODO: output camera state and focus state for debugging.
1479ef9925131835743f5316393758c14532c06277dAngus Kong                        Log.e(TAG, "take picture failed.");
1489ef9925131835743f5316393758c14532c06277dAngus Kong                        throw e;
1499ef9925131835743f5316393758c14532c06277dAngus Kong                    }
1509ef9925131835743f5316393758c14532c06277dAngus Kong                }
1519ef9925131835743f5316393758c14532c06277dAngus Kong            });
1529ef9925131835743f5316393758c14532c06277dAngus Kong        }
1539ef9925131835743f5316393758c14532c06277dAngus Kong
1549ef9925131835743f5316393758c14532c06277dAngus Kong        /**
1559ef9925131835743f5316393758c14532c06277dAngus Kong         * Waits for all the {@code Message} and {@code Runnable} currently in the queue
1569ef9925131835743f5316393758c14532c06277dAngus Kong         * are processed.
1579ef9925131835743f5316393758c14532c06277dAngus Kong         *
1589ef9925131835743f5316393758c14532c06277dAngus Kong         * @return {@code false} if the wait was interrupted, {@code true} otherwise.
1599ef9925131835743f5316393758c14532c06277dAngus Kong         */
1609ef9925131835743f5316393758c14532c06277dAngus Kong        public boolean waitDone() {
1619ef9925131835743f5316393758c14532c06277dAngus Kong            final Object waitDoneLock = new Object();
1629ef9925131835743f5316393758c14532c06277dAngus Kong            final Runnable unlockRunnable = new Runnable() {
1639ef9925131835743f5316393758c14532c06277dAngus Kong                @Override
1649ef9925131835743f5316393758c14532c06277dAngus Kong                public void run() {
1659ef9925131835743f5316393758c14532c06277dAngus Kong                    synchronized (waitDoneLock) {
1669ef9925131835743f5316393758c14532c06277dAngus Kong                        waitDoneLock.notifyAll();
1679ef9925131835743f5316393758c14532c06277dAngus Kong                    }
1689ef9925131835743f5316393758c14532c06277dAngus Kong                }
1699ef9925131835743f5316393758c14532c06277dAngus Kong            };
1709ef9925131835743f5316393758c14532c06277dAngus Kong
1719ef9925131835743f5316393758c14532c06277dAngus Kong            synchronized (waitDoneLock) {
1729ef9925131835743f5316393758c14532c06277dAngus Kong                mCameraHandler.post(unlockRunnable);
1739ef9925131835743f5316393758c14532c06277dAngus Kong                try {
1749ef9925131835743f5316393758c14532c06277dAngus Kong                    waitDoneLock.wait();
1759ef9925131835743f5316393758c14532c06277dAngus Kong                } catch (InterruptedException ex) {
1769ef9925131835743f5316393758c14532c06277dAngus Kong                    Log.v(TAG, "waitDone interrupted");
1779ef9925131835743f5316393758c14532c06277dAngus Kong                    return false;
1789ef9925131835743f5316393758c14532c06277dAngus Kong                }
1799ef9925131835743f5316393758c14532c06277dAngus Kong            }
1809ef9925131835743f5316393758c14532c06277dAngus Kong            return true;
1819ef9925131835743f5316393758c14532c06277dAngus Kong        }
1829ef9925131835743f5316393758c14532c06277dAngus Kong
1839ef9925131835743f5316393758c14532c06277dAngus Kong        /**
1849ef9925131835743f5316393758c14532c06277dAngus Kong         * This method does not deal with the API level check.  Everyone should
1859ef9925131835743f5316393758c14532c06277dAngus Kong         * check first for supported operations before sending message to this handler.
1869ef9925131835743f5316393758c14532c06277dAngus Kong         */
1879ef9925131835743f5316393758c14532c06277dAngus Kong        @Override
1889ef9925131835743f5316393758c14532c06277dAngus Kong        public void handleMessage(final Message msg) {
1899ef9925131835743f5316393758c14532c06277dAngus Kong            try {
1909ef9925131835743f5316393758c14532c06277dAngus Kong                switch (msg.what) {
1919ef9925131835743f5316393758c14532c06277dAngus Kong                    case OPEN_CAMERA:
1926d29a648f497f827d623d7af0b679e98ea58bf90Angus Kong                        mCamera = android.hardware.Camera.open(msg.arg1);
1939ef9925131835743f5316393758c14532c06277dAngus Kong                        if (mCamera != null) {
1949ef9925131835743f5316393758c14532c06277dAngus Kong                            mParametersIsDirty = true;
1959ef9925131835743f5316393758c14532c06277dAngus Kong
1969ef9925131835743f5316393758c14532c06277dAngus Kong                            // Get a instance of Camera.Parameters for later use.
1979ef9925131835743f5316393758c14532c06277dAngus Kong                            if (mParamsToSet == null) {
1989ef9925131835743f5316393758c14532c06277dAngus Kong                                mParamsToSet = mCamera.getParameters();
1999ef9925131835743f5316393758c14532c06277dAngus Kong                            }
2004f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong                        } else {
2014f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong                            if (msg.obj != null) {
2024f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong                                ((CameraOpenErrorCallback) msg.obj).onDeviceOpenFailure(msg.arg1);
2034f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong                            }
2049ef9925131835743f5316393758c14532c06277dAngus Kong                        }
2059ef9925131835743f5316393758c14532c06277dAngus Kong                        return;
2069ef9925131835743f5316393758c14532c06277dAngus Kong
2079ef9925131835743f5316393758c14532c06277dAngus Kong                    case RELEASE:
2089ef9925131835743f5316393758c14532c06277dAngus Kong                        mCamera.release();
2099ef9925131835743f5316393758c14532c06277dAngus Kong                        mCamera = null;
2109ef9925131835743f5316393758c14532c06277dAngus Kong                        return;
2119ef9925131835743f5316393758c14532c06277dAngus Kong
2129ef9925131835743f5316393758c14532c06277dAngus Kong                    case RECONNECT:
2139ef9925131835743f5316393758c14532c06277dAngus Kong                        mReconnectIOException = null;
2149ef9925131835743f5316393758c14532c06277dAngus Kong                        try {
2159ef9925131835743f5316393758c14532c06277dAngus Kong                            mCamera.reconnect();
2169ef9925131835743f5316393758c14532c06277dAngus Kong                        } catch (IOException ex) {
2179ef9925131835743f5316393758c14532c06277dAngus Kong                            mReconnectIOException = ex;
2189ef9925131835743f5316393758c14532c06277dAngus Kong                        }
2199ef9925131835743f5316393758c14532c06277dAngus Kong                        return;
2209ef9925131835743f5316393758c14532c06277dAngus Kong
2219ef9925131835743f5316393758c14532c06277dAngus Kong                    case UNLOCK:
2229ef9925131835743f5316393758c14532c06277dAngus Kong                        mCamera.unlock();
2239ef9925131835743f5316393758c14532c06277dAngus Kong                        return;
2249ef9925131835743f5316393758c14532c06277dAngus Kong
2259ef9925131835743f5316393758c14532c06277dAngus Kong                    case LOCK:
2269ef9925131835743f5316393758c14532c06277dAngus Kong                        mCamera.lock();
2279ef9925131835743f5316393758c14532c06277dAngus Kong                        return;
2289ef9925131835743f5316393758c14532c06277dAngus Kong
2299ef9925131835743f5316393758c14532c06277dAngus Kong                    case SET_PREVIEW_TEXTURE_ASYNC:
2309ef9925131835743f5316393758c14532c06277dAngus Kong                        setPreviewTexture(msg.obj);
2319ef9925131835743f5316393758c14532c06277dAngus Kong                        return;
2329ef9925131835743f5316393758c14532c06277dAngus Kong
2339ef9925131835743f5316393758c14532c06277dAngus Kong                    case SET_PREVIEW_DISPLAY_ASYNC:
2349ef9925131835743f5316393758c14532c06277dAngus Kong                        try {
2359ef9925131835743f5316393758c14532c06277dAngus Kong                            mCamera.setPreviewDisplay((SurfaceHolder) msg.obj);
2369ef9925131835743f5316393758c14532c06277dAngus Kong                        } catch (IOException e) {
2379ef9925131835743f5316393758c14532c06277dAngus Kong                            throw new RuntimeException(e);
2389ef9925131835743f5316393758c14532c06277dAngus Kong                        }
2399ef9925131835743f5316393758c14532c06277dAngus Kong                        return;
2409ef9925131835743f5316393758c14532c06277dAngus Kong
2419ef9925131835743f5316393758c14532c06277dAngus Kong                    case START_PREVIEW_ASYNC:
2429ef9925131835743f5316393758c14532c06277dAngus Kong                        mCamera.startPreview();
2439ef9925131835743f5316393758c14532c06277dAngus Kong                        return;
2449ef9925131835743f5316393758c14532c06277dAngus Kong
2459ef9925131835743f5316393758c14532c06277dAngus Kong                    case STOP_PREVIEW:
2469ef9925131835743f5316393758c14532c06277dAngus Kong                        mCamera.stopPreview();
2479ef9925131835743f5316393758c14532c06277dAngus Kong                        return;
2489ef9925131835743f5316393758c14532c06277dAngus Kong
2499ef9925131835743f5316393758c14532c06277dAngus Kong                    case SET_PREVIEW_CALLBACK_WITH_BUFFER:
2509ef9925131835743f5316393758c14532c06277dAngus Kong                        mCamera.setPreviewCallbackWithBuffer(
2519ef9925131835743f5316393758c14532c06277dAngus Kong                            (PreviewCallback) msg.obj);
2529ef9925131835743f5316393758c14532c06277dAngus Kong                        return;
2539ef9925131835743f5316393758c14532c06277dAngus Kong
2549ef9925131835743f5316393758c14532c06277dAngus Kong                    case ADD_CALLBACK_BUFFER:
2559ef9925131835743f5316393758c14532c06277dAngus Kong                        mCamera.addCallbackBuffer((byte[]) msg.obj);
2569ef9925131835743f5316393758c14532c06277dAngus Kong                        return;
2579ef9925131835743f5316393758c14532c06277dAngus Kong
2589ef9925131835743f5316393758c14532c06277dAngus Kong                    case AUTO_FOCUS:
2599ef9925131835743f5316393758c14532c06277dAngus Kong                        mCamera.autoFocus((AutoFocusCallback) msg.obj);
2609ef9925131835743f5316393758c14532c06277dAngus Kong                        return;
2619ef9925131835743f5316393758c14532c06277dAngus Kong
2629ef9925131835743f5316393758c14532c06277dAngus Kong                    case CANCEL_AUTO_FOCUS:
2639ef9925131835743f5316393758c14532c06277dAngus Kong                        mCamera.cancelAutoFocus();
2649ef9925131835743f5316393758c14532c06277dAngus Kong                        return;
2659ef9925131835743f5316393758c14532c06277dAngus Kong
2669ef9925131835743f5316393758c14532c06277dAngus Kong                    case SET_AUTO_FOCUS_MOVE_CALLBACK:
2679ef9925131835743f5316393758c14532c06277dAngus Kong                        setAutoFocusMoveCallback(mCamera, msg.obj);
2689ef9925131835743f5316393758c14532c06277dAngus Kong                        return;
2699ef9925131835743f5316393758c14532c06277dAngus Kong
2709ef9925131835743f5316393758c14532c06277dAngus Kong                    case SET_DISPLAY_ORIENTATION:
2719ef9925131835743f5316393758c14532c06277dAngus Kong                        mCamera.setDisplayOrientation(msg.arg1);
2729ef9925131835743f5316393758c14532c06277dAngus Kong                        return;
2739ef9925131835743f5316393758c14532c06277dAngus Kong
2749ef9925131835743f5316393758c14532c06277dAngus Kong                    case SET_ZOOM_CHANGE_LISTENER:
2759ef9925131835743f5316393758c14532c06277dAngus Kong                        mCamera.setZoomChangeListener(
2769ef9925131835743f5316393758c14532c06277dAngus Kong                            (OnZoomChangeListener) msg.obj);
2779ef9925131835743f5316393758c14532c06277dAngus Kong                        return;
2789ef9925131835743f5316393758c14532c06277dAngus Kong
2799ef9925131835743f5316393758c14532c06277dAngus Kong                    case SET_FACE_DETECTION_LISTENER:
2809ef9925131835743f5316393758c14532c06277dAngus Kong                        setFaceDetectionListener((FaceDetectionListener) msg.obj);
2819ef9925131835743f5316393758c14532c06277dAngus Kong                        return;
2829ef9925131835743f5316393758c14532c06277dAngus Kong
2839ef9925131835743f5316393758c14532c06277dAngus Kong                    case START_FACE_DETECTION:
2849ef9925131835743f5316393758c14532c06277dAngus Kong                        startFaceDetection();
2859ef9925131835743f5316393758c14532c06277dAngus Kong                        return;
2869ef9925131835743f5316393758c14532c06277dAngus Kong
2879ef9925131835743f5316393758c14532c06277dAngus Kong                    case STOP_FACE_DETECTION:
2889ef9925131835743f5316393758c14532c06277dAngus Kong                        stopFaceDetection();
2899ef9925131835743f5316393758c14532c06277dAngus Kong                        return;
2909ef9925131835743f5316393758c14532c06277dAngus Kong
2919ef9925131835743f5316393758c14532c06277dAngus Kong                    case SET_ERROR_CALLBACK:
2929ef9925131835743f5316393758c14532c06277dAngus Kong                        mCamera.setErrorCallback((ErrorCallback) msg.obj);
2939ef9925131835743f5316393758c14532c06277dAngus Kong                        return;
2949ef9925131835743f5316393758c14532c06277dAngus Kong
2959ef9925131835743f5316393758c14532c06277dAngus Kong                    case SET_PARAMETERS:
2969ef9925131835743f5316393758c14532c06277dAngus Kong                        mParametersIsDirty = true;
2979ef9925131835743f5316393758c14532c06277dAngus Kong                        mParamsToSet.unflatten((String) msg.obj);
2989ef9925131835743f5316393758c14532c06277dAngus Kong                        mCamera.setParameters(mParamsToSet);
2999ef9925131835743f5316393758c14532c06277dAngus Kong                        return;
3009ef9925131835743f5316393758c14532c06277dAngus Kong
3019ef9925131835743f5316393758c14532c06277dAngus Kong                    case GET_PARAMETERS:
3029ef9925131835743f5316393758c14532c06277dAngus Kong                        if (mParametersIsDirty) {
3039ef9925131835743f5316393758c14532c06277dAngus Kong                            mParameters = mCamera.getParameters();
3049ef9925131835743f5316393758c14532c06277dAngus Kong                            mParametersIsDirty = false;
3059ef9925131835743f5316393758c14532c06277dAngus Kong                        }
3069ef9925131835743f5316393758c14532c06277dAngus Kong                        return;
3079ef9925131835743f5316393758c14532c06277dAngus Kong
3089ef9925131835743f5316393758c14532c06277dAngus Kong                    case SET_PREVIEW_CALLBACK:
3099ef9925131835743f5316393758c14532c06277dAngus Kong                        mCamera.setPreviewCallback((PreviewCallback) msg.obj);
3109ef9925131835743f5316393758c14532c06277dAngus Kong                        return;
3119ef9925131835743f5316393758c14532c06277dAngus Kong
3129ef9925131835743f5316393758c14532c06277dAngus Kong                    case ENABLE_SHUTTER_SOUND:
3139ef9925131835743f5316393758c14532c06277dAngus Kong                        enableShutterSound((msg.arg1 == 1) ? true : false);
3149ef9925131835743f5316393758c14532c06277dAngus Kong                        return;
3159ef9925131835743f5316393758c14532c06277dAngus Kong
3169ef9925131835743f5316393758c14532c06277dAngus Kong                    case REFRESH_PARAMETERS:
3179ef9925131835743f5316393758c14532c06277dAngus Kong                        mParametersIsDirty = true;
3189ef9925131835743f5316393758c14532c06277dAngus Kong                        return;
3199ef9925131835743f5316393758c14532c06277dAngus Kong
3209ef9925131835743f5316393758c14532c06277dAngus Kong                    default:
3219ef9925131835743f5316393758c14532c06277dAngus Kong                        throw new RuntimeException("Invalid CameraProxy message=" + msg.what);
3229ef9925131835743f5316393758c14532c06277dAngus Kong                }
3239ef9925131835743f5316393758c14532c06277dAngus Kong            } catch (RuntimeException e) {
3249ef9925131835743f5316393758c14532c06277dAngus Kong                if (msg.what != RELEASE && mCamera != null) {
3259ef9925131835743f5316393758c14532c06277dAngus Kong                    try {
3269ef9925131835743f5316393758c14532c06277dAngus Kong                        mCamera.release();
3279ef9925131835743f5316393758c14532c06277dAngus Kong                    } catch (Exception ex) {
3289ef9925131835743f5316393758c14532c06277dAngus Kong                        Log.e(TAG, "Fail to release the camera.");
3299ef9925131835743f5316393758c14532c06277dAngus Kong                    }
3309ef9925131835743f5316393758c14532c06277dAngus Kong                    mCamera = null;
33102db77fc8bdcd6aeb1b36217d939bc11355822e6Sascha Haeberling                } else if (mCamera == null) {
332cfc148d8373ab69d352c274374ffb34caf4a8d2cztenghui                    if (msg.what == OPEN_CAMERA) {
333cfc148d8373ab69d352c274374ffb34caf4a8d2cztenghui                        if (msg.obj != null) {
334cfc148d8373ab69d352c274374ffb34caf4a8d2cztenghui                            ((CameraOpenErrorCallback) msg.obj).onDeviceOpenFailure(msg.arg1);
335cfc148d8373ab69d352c274374ffb34caf4a8d2cztenghui                        }
336cfc148d8373ab69d352c274374ffb34caf4a8d2cztenghui                    } else {
337cfc148d8373ab69d352c274374ffb34caf4a8d2cztenghui                        Log.w(TAG, "Cannot handle message, mCamera is null.");
338cfc148d8373ab69d352c274374ffb34caf4a8d2cztenghui                    }
339cfc148d8373ab69d352c274374ffb34caf4a8d2cztenghui                    return;
3409ef9925131835743f5316393758c14532c06277dAngus Kong                }
3419ef9925131835743f5316393758c14532c06277dAngus Kong                throw e;
3429ef9925131835743f5316393758c14532c06277dAngus Kong            }
3439ef9925131835743f5316393758c14532c06277dAngus Kong        }
3449ef9925131835743f5316393758c14532c06277dAngus Kong    }
3459ef9925131835743f5316393758c14532c06277dAngus Kong
3469ef9925131835743f5316393758c14532c06277dAngus Kong    @Override
3474f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong    public CameraManager.CameraProxy cameraOpen(
3484f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong        Handler handler, int cameraId, CameraOpenErrorCallback callback) {
3494f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong        mCameraHandler.obtainMessage(OPEN_CAMERA, cameraId, 0,
3504f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong                CameraOpenErrorCallbackForward.getNewInstance(
3514f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong                        handler, callback)).sendToTarget();
3529ef9925131835743f5316393758c14532c06277dAngus Kong        mCameraHandler.waitDone();
3539ef9925131835743f5316393758c14532c06277dAngus Kong        if (mCamera != null) {
3549ef9925131835743f5316393758c14532c06277dAngus Kong            return new AndroidCameraProxyImpl();
3559ef9925131835743f5316393758c14532c06277dAngus Kong        } else {
3569ef9925131835743f5316393758c14532c06277dAngus Kong            return null;
3579ef9925131835743f5316393758c14532c06277dAngus Kong        }
3589ef9925131835743f5316393758c14532c06277dAngus Kong    }
3599ef9925131835743f5316393758c14532c06277dAngus Kong
3609ef9925131835743f5316393758c14532c06277dAngus Kong    /**
3614f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong     * A class which implements {@link CameraManager.CameraProxy} and
3629ef9925131835743f5316393758c14532c06277dAngus Kong     * camera handler thread.
3634f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong     * TODO: Save the handler for the callback here to avoid passing the same
3644f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong     * handler multiple times.
3659ef9925131835743f5316393758c14532c06277dAngus Kong     */
3669ef9925131835743f5316393758c14532c06277dAngus Kong    public class AndroidCameraProxyImpl implements CameraManager.CameraProxy {
3679ef9925131835743f5316393758c14532c06277dAngus Kong
3689ef9925131835743f5316393758c14532c06277dAngus Kong        private AndroidCameraProxyImpl() {
3699ef9925131835743f5316393758c14532c06277dAngus Kong            Assert(mCamera != null);
3709ef9925131835743f5316393758c14532c06277dAngus Kong        }
3719ef9925131835743f5316393758c14532c06277dAngus Kong
3729ef9925131835743f5316393758c14532c06277dAngus Kong        @Override
3739ef9925131835743f5316393758c14532c06277dAngus Kong        public android.hardware.Camera getCamera() {
3749ef9925131835743f5316393758c14532c06277dAngus Kong            return mCamera;
3759ef9925131835743f5316393758c14532c06277dAngus Kong        }
3769ef9925131835743f5316393758c14532c06277dAngus Kong
3779ef9925131835743f5316393758c14532c06277dAngus Kong        @Override
3789ef9925131835743f5316393758c14532c06277dAngus Kong        public void release() {
3799ef9925131835743f5316393758c14532c06277dAngus Kong            // release() must be synchronous so we know exactly when the camera
3809ef9925131835743f5316393758c14532c06277dAngus Kong            // is released and can continue on.
3819ef9925131835743f5316393758c14532c06277dAngus Kong            mCameraHandler.sendEmptyMessage(RELEASE);
3829ef9925131835743f5316393758c14532c06277dAngus Kong            mCameraHandler.waitDone();
3839ef9925131835743f5316393758c14532c06277dAngus Kong        }
3849ef9925131835743f5316393758c14532c06277dAngus Kong
3859ef9925131835743f5316393758c14532c06277dAngus Kong        @Override
3864f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong        public boolean reconnect(Handler handler, CameraOpenErrorCallback cb) {
3879ef9925131835743f5316393758c14532c06277dAngus Kong            mCameraHandler.sendEmptyMessage(RECONNECT);
3889ef9925131835743f5316393758c14532c06277dAngus Kong            mCameraHandler.waitDone();
3894f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong            CameraOpenErrorCallback cbforward =
3904f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong                    CameraOpenErrorCallbackForward.getNewInstance(handler, cb);
3919ef9925131835743f5316393758c14532c06277dAngus Kong            if (mReconnectIOException != null) {
3924f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong                if (cbforward != null) {
3934f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong                    cbforward.onReconnectionFailure(AndroidCameraManagerImpl.this);
3944f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong                }
3954f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong                return false;
3969ef9925131835743f5316393758c14532c06277dAngus Kong            }
3974f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong            return true;
3989ef9925131835743f5316393758c14532c06277dAngus Kong        }
3999ef9925131835743f5316393758c14532c06277dAngus Kong
4009ef9925131835743f5316393758c14532c06277dAngus Kong        @Override
4019ef9925131835743f5316393758c14532c06277dAngus Kong        public void unlock() {
4029ef9925131835743f5316393758c14532c06277dAngus Kong            mCameraHandler.sendEmptyMessage(UNLOCK);
4039ef9925131835743f5316393758c14532c06277dAngus Kong            mCameraHandler.waitDone();
4049ef9925131835743f5316393758c14532c06277dAngus Kong        }
4059ef9925131835743f5316393758c14532c06277dAngus Kong
4069ef9925131835743f5316393758c14532c06277dAngus Kong        @Override
4079ef9925131835743f5316393758c14532c06277dAngus Kong        public void lock() {
4089ef9925131835743f5316393758c14532c06277dAngus Kong            mCameraHandler.sendEmptyMessage(LOCK);
4099ef9925131835743f5316393758c14532c06277dAngus Kong        }
4109ef9925131835743f5316393758c14532c06277dAngus Kong
4119ef9925131835743f5316393758c14532c06277dAngus Kong        @Override
4129e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong        public void setPreviewTexture(SurfaceTexture surfaceTexture) {
4139ef9925131835743f5316393758c14532c06277dAngus Kong            mCameraHandler.obtainMessage(SET_PREVIEW_TEXTURE_ASYNC, surfaceTexture).sendToTarget();
4149ef9925131835743f5316393758c14532c06277dAngus Kong        }
4159ef9925131835743f5316393758c14532c06277dAngus Kong
4169ef9925131835743f5316393758c14532c06277dAngus Kong        @Override
4179e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong        public void setPreviewDisplay(SurfaceHolder surfaceHolder) {
4189ef9925131835743f5316393758c14532c06277dAngus Kong            mCameraHandler.obtainMessage(SET_PREVIEW_DISPLAY_ASYNC, surfaceHolder).sendToTarget();
4199ef9925131835743f5316393758c14532c06277dAngus Kong        }
4209ef9925131835743f5316393758c14532c06277dAngus Kong
4219ef9925131835743f5316393758c14532c06277dAngus Kong        @Override
4229ef9925131835743f5316393758c14532c06277dAngus Kong        public void startPreview() {
4239ef9925131835743f5316393758c14532c06277dAngus Kong            mCameraHandler.sendEmptyMessage(START_PREVIEW_ASYNC);
4249ef9925131835743f5316393758c14532c06277dAngus Kong        }
4259ef9925131835743f5316393758c14532c06277dAngus Kong
4269ef9925131835743f5316393758c14532c06277dAngus Kong        @Override
4279ef9925131835743f5316393758c14532c06277dAngus Kong        public void stopPreview() {
4289ef9925131835743f5316393758c14532c06277dAngus Kong            mCameraHandler.sendEmptyMessage(STOP_PREVIEW);
4299ef9925131835743f5316393758c14532c06277dAngus Kong            mCameraHandler.waitDone();
4309ef9925131835743f5316393758c14532c06277dAngus Kong        }
4319ef9925131835743f5316393758c14532c06277dAngus Kong
4329ef9925131835743f5316393758c14532c06277dAngus Kong        @Override
4339ef9925131835743f5316393758c14532c06277dAngus Kong        public void setPreviewDataCallback(
4349e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong                Handler handler, CameraPreviewDataCallback cb) {
4359ef9925131835743f5316393758c14532c06277dAngus Kong            mCameraHandler.obtainMessage(
4369ef9925131835743f5316393758c14532c06277dAngus Kong                    SET_PREVIEW_CALLBACK,
4379e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong                    PreviewCallbackForward.getNewInstance(handler, this, cb)).sendToTarget();
4389ef9925131835743f5316393758c14532c06277dAngus Kong        }
4399ef9925131835743f5316393758c14532c06277dAngus Kong
4409ef9925131835743f5316393758c14532c06277dAngus Kong        @Override
4419ef9925131835743f5316393758c14532c06277dAngus Kong        public void setPreviewDataCallbackWithBuffer(
4429e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong                Handler handler, CameraPreviewDataCallback cb) {
4439ef9925131835743f5316393758c14532c06277dAngus Kong            mCameraHandler.obtainMessage(
4449ef9925131835743f5316393758c14532c06277dAngus Kong                    SET_PREVIEW_CALLBACK_WITH_BUFFER,
4459e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong                    PreviewCallbackForward.getNewInstance(handler, this, cb)).sendToTarget();
4469ef9925131835743f5316393758c14532c06277dAngus Kong        }
4479ef9925131835743f5316393758c14532c06277dAngus Kong
4489ef9925131835743f5316393758c14532c06277dAngus Kong        @Override
4499ef9925131835743f5316393758c14532c06277dAngus Kong        public void addCallbackBuffer(byte[] callbackBuffer) {
4509ef9925131835743f5316393758c14532c06277dAngus Kong            mCameraHandler.obtainMessage(ADD_CALLBACK_BUFFER, callbackBuffer).sendToTarget();
4519ef9925131835743f5316393758c14532c06277dAngus Kong        }
4529ef9925131835743f5316393758c14532c06277dAngus Kong
4539ef9925131835743f5316393758c14532c06277dAngus Kong        @Override
4549ef9925131835743f5316393758c14532c06277dAngus Kong        public void autoFocus(Handler handler, CameraAFCallback cb) {
4559ef9925131835743f5316393758c14532c06277dAngus Kong            mCameraHandler.obtainMessage(
4569ef9925131835743f5316393758c14532c06277dAngus Kong                    AUTO_FOCUS,
4579e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong                    AFCallbackForward.getNewInstance(handler, this, cb)).sendToTarget();
4589ef9925131835743f5316393758c14532c06277dAngus Kong        }
4599ef9925131835743f5316393758c14532c06277dAngus Kong
4609ef9925131835743f5316393758c14532c06277dAngus Kong        @Override
4619ef9925131835743f5316393758c14532c06277dAngus Kong        public void cancelAutoFocus() {
4629ef9925131835743f5316393758c14532c06277dAngus Kong            mCameraHandler.removeMessages(AUTO_FOCUS);
4639ef9925131835743f5316393758c14532c06277dAngus Kong            mCameraHandler.sendEmptyMessage(CANCEL_AUTO_FOCUS);
4649ef9925131835743f5316393758c14532c06277dAngus Kong        }
4659ef9925131835743f5316393758c14532c06277dAngus Kong
466638e6f06c877d90b907f66ea9c22b3c6b73c7384Sascha Haeberling        @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
4679ef9925131835743f5316393758c14532c06277dAngus Kong        @Override
4689ef9925131835743f5316393758c14532c06277dAngus Kong        public void setAutoFocusMoveCallback(
4699e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong                Handler handler, CameraAFMoveCallback cb) {
4709ef9925131835743f5316393758c14532c06277dAngus Kong            mCameraHandler.obtainMessage(
4719ef9925131835743f5316393758c14532c06277dAngus Kong                    SET_AUTO_FOCUS_MOVE_CALLBACK,
4729e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong                    AFMoveCallbackForward.getNewInstance(handler, this, cb)).sendToTarget();
4739ef9925131835743f5316393758c14532c06277dAngus Kong        }
4749ef9925131835743f5316393758c14532c06277dAngus Kong
4759ef9925131835743f5316393758c14532c06277dAngus Kong        @Override
4769ef9925131835743f5316393758c14532c06277dAngus Kong        public void takePicture(
4779e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong                Handler handler,
4789e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong                CameraShutterCallback shutter,
4799e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong                CameraPictureCallback raw,
4809e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong                CameraPictureCallback post,
4819e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong                CameraPictureCallback jpeg) {
4829ef9925131835743f5316393758c14532c06277dAngus Kong            mCameraHandler.requestTakePicture(
4839e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong                    ShutterCallbackForward.getNewInstance(handler, this, shutter),
4849e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong                    PictureCallbackForward.getNewInstance(handler, this, raw),
4859e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong                    PictureCallbackForward.getNewInstance(handler, this, post),
4869e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong                    PictureCallbackForward.getNewInstance(handler, this, jpeg));
4879ef9925131835743f5316393758c14532c06277dAngus Kong        }
4889ef9925131835743f5316393758c14532c06277dAngus Kong
4899ef9925131835743f5316393758c14532c06277dAngus Kong        @Override
4909ef9925131835743f5316393758c14532c06277dAngus Kong        public void setDisplayOrientation(int degrees) {
4919ef9925131835743f5316393758c14532c06277dAngus Kong            mCameraHandler.obtainMessage(SET_DISPLAY_ORIENTATION, degrees, 0)
4929ef9925131835743f5316393758c14532c06277dAngus Kong                    .sendToTarget();
4939ef9925131835743f5316393758c14532c06277dAngus Kong        }
4949ef9925131835743f5316393758c14532c06277dAngus Kong
4959ef9925131835743f5316393758c14532c06277dAngus Kong        @Override
4969ef9925131835743f5316393758c14532c06277dAngus Kong        public void setZoomChangeListener(OnZoomChangeListener listener) {
4979ef9925131835743f5316393758c14532c06277dAngus Kong            mCameraHandler.obtainMessage(SET_ZOOM_CHANGE_LISTENER, listener).sendToTarget();
4989ef9925131835743f5316393758c14532c06277dAngus Kong        }
4999ef9925131835743f5316393758c14532c06277dAngus Kong
5009e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong        public void setFaceDetectionCallback(
5019e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong                Handler handler, CameraFaceDetectionCallback cb) {
5029e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong            mCameraHandler.obtainMessage(
5039e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong                    SET_FACE_DETECTION_LISTENER,
5049e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong                    FaceDetectionCallbackForward.getNewInstance(handler, this, cb)).sendToTarget();
5059ef9925131835743f5316393758c14532c06277dAngus Kong        }
5069ef9925131835743f5316393758c14532c06277dAngus Kong
5079ef9925131835743f5316393758c14532c06277dAngus Kong        @Override
5089ef9925131835743f5316393758c14532c06277dAngus Kong        public void startFaceDetection() {
5099ef9925131835743f5316393758c14532c06277dAngus Kong            mCameraHandler.sendEmptyMessage(START_FACE_DETECTION);
5109ef9925131835743f5316393758c14532c06277dAngus Kong        }
5119ef9925131835743f5316393758c14532c06277dAngus Kong
5129ef9925131835743f5316393758c14532c06277dAngus Kong        @Override
5139ef9925131835743f5316393758c14532c06277dAngus Kong        public void stopFaceDetection() {
5149ef9925131835743f5316393758c14532c06277dAngus Kong            mCameraHandler.sendEmptyMessage(STOP_FACE_DETECTION);
5159ef9925131835743f5316393758c14532c06277dAngus Kong        }
5169ef9925131835743f5316393758c14532c06277dAngus Kong
5179ef9925131835743f5316393758c14532c06277dAngus Kong        @Override
5189ef9925131835743f5316393758c14532c06277dAngus Kong        public void setErrorCallback(ErrorCallback cb) {
5199ef9925131835743f5316393758c14532c06277dAngus Kong            mCameraHandler.obtainMessage(SET_ERROR_CALLBACK, cb).sendToTarget();
5209ef9925131835743f5316393758c14532c06277dAngus Kong        }
5219ef9925131835743f5316393758c14532c06277dAngus Kong
5229ef9925131835743f5316393758c14532c06277dAngus Kong        @Override
5239ef9925131835743f5316393758c14532c06277dAngus Kong        public void setParameters(Parameters params) {
5249ef9925131835743f5316393758c14532c06277dAngus Kong            if (params == null) {
5259ef9925131835743f5316393758c14532c06277dAngus Kong                Log.v(TAG, "null parameters in setParameters()");
5269ef9925131835743f5316393758c14532c06277dAngus Kong                return;
5279ef9925131835743f5316393758c14532c06277dAngus Kong            }
5289ef9925131835743f5316393758c14532c06277dAngus Kong            mCameraHandler.obtainMessage(SET_PARAMETERS, params.flatten())
5299ef9925131835743f5316393758c14532c06277dAngus Kong                    .sendToTarget();
5309ef9925131835743f5316393758c14532c06277dAngus Kong        }
5319ef9925131835743f5316393758c14532c06277dAngus Kong
5329ef9925131835743f5316393758c14532c06277dAngus Kong        @Override
5339ef9925131835743f5316393758c14532c06277dAngus Kong        public Parameters getParameters() {
5349ef9925131835743f5316393758c14532c06277dAngus Kong            mCameraHandler.sendEmptyMessage(GET_PARAMETERS);
5359ef9925131835743f5316393758c14532c06277dAngus Kong            mCameraHandler.waitDone();
5369ef9925131835743f5316393758c14532c06277dAngus Kong            return mParameters;
5379ef9925131835743f5316393758c14532c06277dAngus Kong        }
5389ef9925131835743f5316393758c14532c06277dAngus Kong
5399ef9925131835743f5316393758c14532c06277dAngus Kong        @Override
5409ef9925131835743f5316393758c14532c06277dAngus Kong        public void refreshParameters() {
5419ef9925131835743f5316393758c14532c06277dAngus Kong            mCameraHandler.sendEmptyMessage(REFRESH_PARAMETERS);
5429ef9925131835743f5316393758c14532c06277dAngus Kong        }
5439ef9925131835743f5316393758c14532c06277dAngus Kong
5449ef9925131835743f5316393758c14532c06277dAngus Kong        @Override
5459ef9925131835743f5316393758c14532c06277dAngus Kong        public void enableShutterSound(boolean enable) {
5469ef9925131835743f5316393758c14532c06277dAngus Kong            mCameraHandler.obtainMessage(
5479ef9925131835743f5316393758c14532c06277dAngus Kong                    ENABLE_SHUTTER_SOUND, (enable ? 1 : 0), 0).sendToTarget();
5489ef9925131835743f5316393758c14532c06277dAngus Kong        }
5499ef9925131835743f5316393758c14532c06277dAngus Kong    }
5509ef9925131835743f5316393758c14532c06277dAngus Kong
5519ef9925131835743f5316393758c14532c06277dAngus Kong    /**
5529ef9925131835743f5316393758c14532c06277dAngus Kong     * A helper class to forward AutoFocusCallback to another thread.
5539ef9925131835743f5316393758c14532c06277dAngus Kong     */
5549ef9925131835743f5316393758c14532c06277dAngus Kong    private static class AFCallbackForward implements AutoFocusCallback {
5559ef9925131835743f5316393758c14532c06277dAngus Kong        private final Handler mHandler;
5569ef9925131835743f5316393758c14532c06277dAngus Kong        private final CameraProxy mCamera;
5579ef9925131835743f5316393758c14532c06277dAngus Kong        private final CameraAFCallback mCallback;
5589ef9925131835743f5316393758c14532c06277dAngus Kong
5599ef9925131835743f5316393758c14532c06277dAngus Kong        /**
5609e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong         * Returns a new instance of {@link AFCallbackForward}.
5619ef9925131835743f5316393758c14532c06277dAngus Kong         *
5629ef9925131835743f5316393758c14532c06277dAngus Kong         * @param handler The handler in which the callback will be invoked in.
5639ef9925131835743f5316393758c14532c06277dAngus Kong         * @param camera  The {@link CameraProxy} which the callback is from.
5649ef9925131835743f5316393758c14532c06277dAngus Kong         * @param cb      The callback to be invoked.
5659ef9925131835743f5316393758c14532c06277dAngus Kong         * @return        The instance of the {@link AFCallbackForward},
5669e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong         *                or null if any parameter is null.
5679ef9925131835743f5316393758c14532c06277dAngus Kong         */
5689e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong        public static AFCallbackForward getNewInstance(
5699ef9925131835743f5316393758c14532c06277dAngus Kong                Handler handler, CameraProxy camera, CameraAFCallback cb) {
5709ef9925131835743f5316393758c14532c06277dAngus Kong            if (handler == null || camera == null || cb == null) return null;
5719ef9925131835743f5316393758c14532c06277dAngus Kong            return new AFCallbackForward(handler, camera, cb);
5729ef9925131835743f5316393758c14532c06277dAngus Kong        }
5739ef9925131835743f5316393758c14532c06277dAngus Kong
5749ef9925131835743f5316393758c14532c06277dAngus Kong        private AFCallbackForward(
5759ef9925131835743f5316393758c14532c06277dAngus Kong                Handler h, CameraProxy camera, CameraAFCallback cb) {
5769ef9925131835743f5316393758c14532c06277dAngus Kong            mHandler = h;
5779ef9925131835743f5316393758c14532c06277dAngus Kong            mCamera = camera;
5789ef9925131835743f5316393758c14532c06277dAngus Kong            mCallback = cb;
5799ef9925131835743f5316393758c14532c06277dAngus Kong        }
5809ef9925131835743f5316393758c14532c06277dAngus Kong
5819ef9925131835743f5316393758c14532c06277dAngus Kong        @Override
5829ef9925131835743f5316393758c14532c06277dAngus Kong        public void onAutoFocus(final boolean b, Camera camera) {
5839ef9925131835743f5316393758c14532c06277dAngus Kong            mHandler.post(new Runnable() {
5849ef9925131835743f5316393758c14532c06277dAngus Kong                @Override
5859ef9925131835743f5316393758c14532c06277dAngus Kong                public void run() {
5869ef9925131835743f5316393758c14532c06277dAngus Kong                    mCallback.onAutoFocus(b, mCamera);
5879ef9925131835743f5316393758c14532c06277dAngus Kong                }
5889ef9925131835743f5316393758c14532c06277dAngus Kong            });
5899ef9925131835743f5316393758c14532c06277dAngus Kong        }
5909ef9925131835743f5316393758c14532c06277dAngus Kong    }
5919ef9925131835743f5316393758c14532c06277dAngus Kong
5929ef9925131835743f5316393758c14532c06277dAngus Kong    /** A helper class to forward AutoFocusMoveCallback to another thread. */
593638e6f06c877d90b907f66ea9c22b3c6b73c7384Sascha Haeberling    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
5949ef9925131835743f5316393758c14532c06277dAngus Kong    private static class AFMoveCallbackForward implements AutoFocusMoveCallback {
5959ef9925131835743f5316393758c14532c06277dAngus Kong        private final Handler mHandler;
5969ef9925131835743f5316393758c14532c06277dAngus Kong        private final CameraAFMoveCallback mCallback;
5979ef9925131835743f5316393758c14532c06277dAngus Kong        private final CameraProxy mCamera;
5989ef9925131835743f5316393758c14532c06277dAngus Kong
5999ef9925131835743f5316393758c14532c06277dAngus Kong        /**
6009e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong         * Returns a new instance of {@link AFMoveCallbackForward}.
6019ef9925131835743f5316393758c14532c06277dAngus Kong         *
6029ef9925131835743f5316393758c14532c06277dAngus Kong         * @param handler The handler in which the callback will be invoked in.
6039ef9925131835743f5316393758c14532c06277dAngus Kong         * @param camera  The {@link CameraProxy} which the callback is from.
6049ef9925131835743f5316393758c14532c06277dAngus Kong         * @param cb      The callback to be invoked.
6059ef9925131835743f5316393758c14532c06277dAngus Kong         * @return        The instance of the {@link AFMoveCallbackForward},
6069e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong         *                or null if any parameter is null.
6079ef9925131835743f5316393758c14532c06277dAngus Kong         */
6089e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong        public static AFMoveCallbackForward getNewInstance(
6099ef9925131835743f5316393758c14532c06277dAngus Kong                Handler handler, CameraProxy camera, CameraAFMoveCallback cb) {
6109ef9925131835743f5316393758c14532c06277dAngus Kong            if (handler == null || camera == null || cb == null) return null;
6119ef9925131835743f5316393758c14532c06277dAngus Kong            return new AFMoveCallbackForward(handler, camera, cb);
6129ef9925131835743f5316393758c14532c06277dAngus Kong        }
6139ef9925131835743f5316393758c14532c06277dAngus Kong
6149ef9925131835743f5316393758c14532c06277dAngus Kong        private AFMoveCallbackForward(
6159ef9925131835743f5316393758c14532c06277dAngus Kong                Handler h, CameraProxy camera, CameraAFMoveCallback cb) {
6169ef9925131835743f5316393758c14532c06277dAngus Kong            mHandler = h;
6179ef9925131835743f5316393758c14532c06277dAngus Kong            mCamera = camera;
6189ef9925131835743f5316393758c14532c06277dAngus Kong            mCallback = cb;
6199ef9925131835743f5316393758c14532c06277dAngus Kong        }
6209ef9925131835743f5316393758c14532c06277dAngus Kong
6219ef9925131835743f5316393758c14532c06277dAngus Kong        @Override
6229ef9925131835743f5316393758c14532c06277dAngus Kong        public void onAutoFocusMoving(
6239ef9925131835743f5316393758c14532c06277dAngus Kong                final boolean moving, android.hardware.Camera camera) {
6249ef9925131835743f5316393758c14532c06277dAngus Kong            mHandler.post(new Runnable() {
6259ef9925131835743f5316393758c14532c06277dAngus Kong                @Override
6269ef9925131835743f5316393758c14532c06277dAngus Kong                public void run() {
6279ef9925131835743f5316393758c14532c06277dAngus Kong                    mCallback.onAutoFocusMoving(moving, mCamera);
6289ef9925131835743f5316393758c14532c06277dAngus Kong                }
6299ef9925131835743f5316393758c14532c06277dAngus Kong            });
6309ef9925131835743f5316393758c14532c06277dAngus Kong        }
6319ef9925131835743f5316393758c14532c06277dAngus Kong    }
6329ef9925131835743f5316393758c14532c06277dAngus Kong
6339ef9925131835743f5316393758c14532c06277dAngus Kong    /**
6349ef9925131835743f5316393758c14532c06277dAngus Kong     * A helper class to forward ShutterCallback to to another thread.
6359ef9925131835743f5316393758c14532c06277dAngus Kong     */
6369ef9925131835743f5316393758c14532c06277dAngus Kong    private static class ShutterCallbackForward implements ShutterCallback {
6379ef9925131835743f5316393758c14532c06277dAngus Kong        private final Handler mHandler;
6389ef9925131835743f5316393758c14532c06277dAngus Kong        private final CameraShutterCallback mCallback;
6399ef9925131835743f5316393758c14532c06277dAngus Kong        private final CameraProxy mCamera;
6409ef9925131835743f5316393758c14532c06277dAngus Kong
6419ef9925131835743f5316393758c14532c06277dAngus Kong        /**
6429e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong         * Returns a new instance of {@link ShutterCallbackForward}.
6439ef9925131835743f5316393758c14532c06277dAngus Kong         *
6449ef9925131835743f5316393758c14532c06277dAngus Kong         * @param handler The handler in which the callback will be invoked in.
6459ef9925131835743f5316393758c14532c06277dAngus Kong         * @param camera  The {@link CameraProxy} which the callback is from.
6469ef9925131835743f5316393758c14532c06277dAngus Kong         * @param cb      The callback to be invoked.
6479ef9925131835743f5316393758c14532c06277dAngus Kong         * @return        The instance of the {@link ShutterCallbackForward},
6489e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong         *                or null if any parameter is null.
6499ef9925131835743f5316393758c14532c06277dAngus Kong         */
6509e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong        public static ShutterCallbackForward getNewInstance(
6519ef9925131835743f5316393758c14532c06277dAngus Kong                Handler handler, CameraProxy camera, CameraShutterCallback cb) {
6529ef9925131835743f5316393758c14532c06277dAngus Kong            if (handler == null || camera == null || cb == null) return null;
6539ef9925131835743f5316393758c14532c06277dAngus Kong            return new ShutterCallbackForward(handler, camera, cb);
6549ef9925131835743f5316393758c14532c06277dAngus Kong        }
6559ef9925131835743f5316393758c14532c06277dAngus Kong
6569ef9925131835743f5316393758c14532c06277dAngus Kong        private ShutterCallbackForward(
6579ef9925131835743f5316393758c14532c06277dAngus Kong                Handler h, CameraProxy camera, CameraShutterCallback cb) {
6589ef9925131835743f5316393758c14532c06277dAngus Kong            mHandler = h;
6599ef9925131835743f5316393758c14532c06277dAngus Kong            mCamera = camera;
6609ef9925131835743f5316393758c14532c06277dAngus Kong            mCallback = cb;
6619ef9925131835743f5316393758c14532c06277dAngus Kong        }
6629ef9925131835743f5316393758c14532c06277dAngus Kong
6639ef9925131835743f5316393758c14532c06277dAngus Kong        @Override
6649ef9925131835743f5316393758c14532c06277dAngus Kong        public void onShutter() {
6659ef9925131835743f5316393758c14532c06277dAngus Kong            mHandler.post(new Runnable() {
6669ef9925131835743f5316393758c14532c06277dAngus Kong                @Override
6679ef9925131835743f5316393758c14532c06277dAngus Kong                public void run() {
6689ef9925131835743f5316393758c14532c06277dAngus Kong                    mCallback.onShutter(mCamera);
6699ef9925131835743f5316393758c14532c06277dAngus Kong                }
6709ef9925131835743f5316393758c14532c06277dAngus Kong            });
6719ef9925131835743f5316393758c14532c06277dAngus Kong        }
6729ef9925131835743f5316393758c14532c06277dAngus Kong    }
6739ef9925131835743f5316393758c14532c06277dAngus Kong
6749ef9925131835743f5316393758c14532c06277dAngus Kong    /**
6759ef9925131835743f5316393758c14532c06277dAngus Kong     * A helper class to forward PictureCallback to another thread.
6769ef9925131835743f5316393758c14532c06277dAngus Kong     */
6779ef9925131835743f5316393758c14532c06277dAngus Kong    private static class PictureCallbackForward implements PictureCallback {
6789ef9925131835743f5316393758c14532c06277dAngus Kong        private final Handler mHandler;
6799ef9925131835743f5316393758c14532c06277dAngus Kong        private final CameraPictureCallback mCallback;
6809ef9925131835743f5316393758c14532c06277dAngus Kong        private final CameraProxy mCamera;
6819ef9925131835743f5316393758c14532c06277dAngus Kong
6829ef9925131835743f5316393758c14532c06277dAngus Kong        /**
6839e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong         * Returns a new instance of {@link PictureCallbackForward}.
6849ef9925131835743f5316393758c14532c06277dAngus Kong         *
6859ef9925131835743f5316393758c14532c06277dAngus Kong         * @param handler The handler in which the callback will be invoked in.
6869ef9925131835743f5316393758c14532c06277dAngus Kong         * @param camera  The {@link CameraProxy} which the callback is from.
6879ef9925131835743f5316393758c14532c06277dAngus Kong         * @param cb      The callback to be invoked.
6889ef9925131835743f5316393758c14532c06277dAngus Kong         * @return        The instance of the {@link PictureCallbackForward},
6899e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong         *                or null if any parameters is null.
6909ef9925131835743f5316393758c14532c06277dAngus Kong         */
6919e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong        public static PictureCallbackForward getNewInstance(
6929ef9925131835743f5316393758c14532c06277dAngus Kong                Handler handler, CameraProxy camera, CameraPictureCallback cb) {
6939ef9925131835743f5316393758c14532c06277dAngus Kong            if (handler == null || camera == null || cb == null) return null;
6949ef9925131835743f5316393758c14532c06277dAngus Kong            return new PictureCallbackForward(handler, camera, cb);
6959ef9925131835743f5316393758c14532c06277dAngus Kong        }
6969ef9925131835743f5316393758c14532c06277dAngus Kong
6979ef9925131835743f5316393758c14532c06277dAngus Kong        private PictureCallbackForward(
6989ef9925131835743f5316393758c14532c06277dAngus Kong                Handler h, CameraProxy camera, CameraPictureCallback cb) {
6999ef9925131835743f5316393758c14532c06277dAngus Kong            mHandler = h;
7009ef9925131835743f5316393758c14532c06277dAngus Kong            mCamera = camera;
7019ef9925131835743f5316393758c14532c06277dAngus Kong            mCallback = cb;
7029ef9925131835743f5316393758c14532c06277dAngus Kong        }
7039ef9925131835743f5316393758c14532c06277dAngus Kong
7049ef9925131835743f5316393758c14532c06277dAngus Kong        @Override
7059ef9925131835743f5316393758c14532c06277dAngus Kong        public void onPictureTaken(
7069ef9925131835743f5316393758c14532c06277dAngus Kong                final byte[] data, android.hardware.Camera camera) {
7079ef9925131835743f5316393758c14532c06277dAngus Kong            mHandler.post(new Runnable() {
7089ef9925131835743f5316393758c14532c06277dAngus Kong                @Override
7099ef9925131835743f5316393758c14532c06277dAngus Kong                public void run() {
7109ef9925131835743f5316393758c14532c06277dAngus Kong                    mCallback.onPictureTaken(data, mCamera);
7119ef9925131835743f5316393758c14532c06277dAngus Kong                }
7129ef9925131835743f5316393758c14532c06277dAngus Kong            });
7139ef9925131835743f5316393758c14532c06277dAngus Kong        }
7149ef9925131835743f5316393758c14532c06277dAngus Kong    }
7159ef9925131835743f5316393758c14532c06277dAngus Kong
7169ef9925131835743f5316393758c14532c06277dAngus Kong    /**
7179ef9925131835743f5316393758c14532c06277dAngus Kong     * A helper class to forward PreviewCallback to another thread.
7189ef9925131835743f5316393758c14532c06277dAngus Kong     */
7199ef9925131835743f5316393758c14532c06277dAngus Kong    private static class PreviewCallbackForward implements PreviewCallback {
7209ef9925131835743f5316393758c14532c06277dAngus Kong        private final Handler mHandler;
7219ef9925131835743f5316393758c14532c06277dAngus Kong        private final CameraPreviewDataCallback mCallback;
7229ef9925131835743f5316393758c14532c06277dAngus Kong        private final CameraProxy mCamera;
7239ef9925131835743f5316393758c14532c06277dAngus Kong
7249ef9925131835743f5316393758c14532c06277dAngus Kong        /**
7259e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong         * Returns a new instance of {@link PreviewCallbackForward}.
7269ef9925131835743f5316393758c14532c06277dAngus Kong         *
7279ef9925131835743f5316393758c14532c06277dAngus Kong         * @param handler The handler in which the callback will be invoked in.
7289ef9925131835743f5316393758c14532c06277dAngus Kong         * @param camera  The {@link CameraProxy} which the callback is from.
7299ef9925131835743f5316393758c14532c06277dAngus Kong         * @param cb      The callback to be invoked.
7309e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong         * @return        The instance of the {@link PreviewCallbackForward},
7319e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong         *                or null if any parameters is null.
7329ef9925131835743f5316393758c14532c06277dAngus Kong         */
7339e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong        public static PreviewCallbackForward getNewInstance(
7349ef9925131835743f5316393758c14532c06277dAngus Kong                Handler handler, CameraProxy camera, CameraPreviewDataCallback cb) {
7359ef9925131835743f5316393758c14532c06277dAngus Kong            if (handler == null || camera == null || cb == null) return null;
7369ef9925131835743f5316393758c14532c06277dAngus Kong            return new PreviewCallbackForward(handler, camera, cb);
7379ef9925131835743f5316393758c14532c06277dAngus Kong        }
7389ef9925131835743f5316393758c14532c06277dAngus Kong
7399ef9925131835743f5316393758c14532c06277dAngus Kong        private PreviewCallbackForward(
7409ef9925131835743f5316393758c14532c06277dAngus Kong                Handler h, CameraProxy camera, CameraPreviewDataCallback cb) {
7419ef9925131835743f5316393758c14532c06277dAngus Kong            mHandler = h;
7429ef9925131835743f5316393758c14532c06277dAngus Kong            mCamera = camera;
7439ef9925131835743f5316393758c14532c06277dAngus Kong            mCallback = cb;
7449ef9925131835743f5316393758c14532c06277dAngus Kong        }
7459ef9925131835743f5316393758c14532c06277dAngus Kong
7469ef9925131835743f5316393758c14532c06277dAngus Kong        @Override
7479ef9925131835743f5316393758c14532c06277dAngus Kong        public void onPreviewFrame(
7489ef9925131835743f5316393758c14532c06277dAngus Kong                final byte[] data, android.hardware.Camera camera) {
7499ef9925131835743f5316393758c14532c06277dAngus Kong            mHandler.post(new Runnable() {
7509ef9925131835743f5316393758c14532c06277dAngus Kong                @Override
7519ef9925131835743f5316393758c14532c06277dAngus Kong                public void run() {
7529ef9925131835743f5316393758c14532c06277dAngus Kong                    mCallback.onPreviewFrame(data, mCamera);
7539ef9925131835743f5316393758c14532c06277dAngus Kong                }
7549ef9925131835743f5316393758c14532c06277dAngus Kong            });
7559ef9925131835743f5316393758c14532c06277dAngus Kong        }
7569ef9925131835743f5316393758c14532c06277dAngus Kong    }
7579e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong
7589e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong    private static class FaceDetectionCallbackForward implements FaceDetectionListener {
7599e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong        private final Handler mHandler;
7609e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong        private final CameraFaceDetectionCallback mCallback;
7619e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong        private final CameraProxy mCamera;
7629e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong
7639e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong        /**
7649e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong         * Returns a new instance of {@link FaceDetectionCallbackForward}.
7659e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong         *
7669e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong         * @param handler The handler in which the callback will be invoked in.
7679e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong         * @param camera  The {@link CameraProxy} which the callback is from.
7689e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong         * @param cb      The callback to be invoked.
7699e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong         * @return        The instance of the {@link FaceDetectionCallbackForward},
7709e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong         *                or null if any parameter is null.
7719e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong         */
7729e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong        public static FaceDetectionCallbackForward getNewInstance(
7739e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong                Handler handler, CameraProxy camera, CameraFaceDetectionCallback cb) {
7749e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong            if (handler == null || camera == null || cb == null) return null;
7759e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong            return new FaceDetectionCallbackForward(handler, camera, cb);
7769e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong        }
7779e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong
7789e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong        private FaceDetectionCallbackForward(
7799e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong                Handler h, CameraProxy camera, CameraFaceDetectionCallback cb) {
7809e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong            mHandler = h;
7819e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong            mCamera = camera;
7829e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong            mCallback = cb;
7839e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong        }
7849e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong
7859e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong        @Override
7869e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong        public void onFaceDetection(
7879e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong                final Camera.Face[] faces, Camera camera) {
7889e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong            mHandler.post(new Runnable() {
7899e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong                @Override
7909e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong                public void run() {
7919e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong                    mCallback.onFaceDetection(faces, mCamera);
7929e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong                }
7939e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong            });
7949e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong        }
7959e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong    }
7964f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong
7974f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong    /**
7984f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong     * A callback helps to invoke the original callback on another
7994f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong     * {@link android.os.Handler}.
8004f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong     */
8014f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong    private static class CameraOpenErrorCallbackForward implements CameraOpenErrorCallback {
8024f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong        private final Handler mHandler;
8034f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong        private final CameraOpenErrorCallback mCallback;
8044f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong
8054f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong        /**
8064f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong         * Returns a new instance of {@link FaceDetectionCallbackForward}.
8074f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong         *
8084f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong         * @param handler The handler in which the callback will be invoked in.
8094f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong         * @param cb The callback to be invoked.
8104f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong         * @return The instance of the {@link FaceDetectionCallbackForward}, or
8114f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong         *         null if any parameter is null.
8124f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong         */
8134f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong        public static CameraOpenErrorCallbackForward getNewInstance(
8144f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong                Handler handler, CameraOpenErrorCallback cb) {
8154f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong            if (handler == null || cb == null) {
8164f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong                return null;
8174f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong            }
8184f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong            return new CameraOpenErrorCallbackForward(handler, cb);
8194f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong        }
8204f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong
8214f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong        private CameraOpenErrorCallbackForward(
8224f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong                Handler h, CameraOpenErrorCallback cb) {
823e1aa59ba7b3a9fb578995ee8ffcd232c11a97842ztenghui            // Given that we are using the main thread handler, we can create it
824e1aa59ba7b3a9fb578995ee8ffcd232c11a97842ztenghui            // here instead of holding onto the PhotoModule objects. In this
825e1aa59ba7b3a9fb578995ee8ffcd232c11a97842ztenghui            // way, we can avoid memory leak.
826e1aa59ba7b3a9fb578995ee8ffcd232c11a97842ztenghui            mHandler = new Handler(Looper.getMainLooper());
8274f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong            mCallback = cb;
8284f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong        }
8294f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong
8304f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong        @Override
8314f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong        public void onCameraDisabled(final int cameraId) {
8324f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong            mHandler.post(new Runnable() {
8334f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong                @Override
8344f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong                public void run() {
8354f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong                    mCallback.onCameraDisabled(cameraId);
8364f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong                }
8374f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong            });
8384f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong        }
8394f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong
8404f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong        @Override
8414f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong        public void onDeviceOpenFailure(final int cameraId) {
8424f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong            mHandler.post(new Runnable() {
8434f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong                @Override
8444f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong                public void run() {
8454f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong                    mCallback.onDeviceOpenFailure(cameraId);
8464f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong                }
8474f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong            });
8484f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong        }
8494f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong
8504f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong        @Override
8514f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong        public void onReconnectionFailure(final CameraManager mgr) {
8524f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong            mHandler.post(new Runnable() {
8534f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong                @Override
8544f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong                public void run() {
8554f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong                    mCallback.onReconnectionFailure(mgr);
8564f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong                }
8574f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong            });
8584f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong        }
8594f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong    }
8609ef9925131835743f5316393758c14532c06277dAngus Kong}
861