1bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong/*
2bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong * Copyright (C) 2012 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.OnZoomChangeListener;
23bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kongimport android.os.Build;
24bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kongimport android.os.Handler;
25cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucherimport android.os.Looper;
266a9babad6eb8ac3e79a5e036d878ed7408e79f26Igor Murashkinimport android.os.Message;
27bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kongimport android.view.SurfaceHolder;
28bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
29a0842b40441db5332a5290f941021636b1182761Sol Boucherimport com.android.ex.camera2.portability.debug.Log;
30a0842b40441db5332a5290f941021636b1182761Sol Boucher
31bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong/**
32bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong * An interface which provides possible camera device operations.
33bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong *
344f425ba476d62b4be7078f2084af37cf306b31c6Sol Boucher * The client should call {@code CameraAgent.openCamera} to get an instance
354f425ba476d62b4be7078f2084af37cf306b31c6Sol Boucher * of {@link CameraAgent.CameraProxy} to control the camera. Classes
36bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong * implementing this interface should have its own one unique {@code Thread}
37bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong * other than the main thread for camera operations. Camera device callbacks
38bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong * are wrapped since the client should not deal with
39bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong * {@code android.hardware.Camera} directly.
40bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong *
41bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong * TODO: provide callback interfaces for:
42bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong * {@code android.hardware.Camera.ErrorCallback},
43bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong * {@code android.hardware.Camera.OnZoomChangeListener}, and
44bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong */
45a0842b40441db5332a5290f941021636b1182761Sol Boucherpublic abstract class CameraAgent {
462d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu    public static final long CAMERA_OPERATION_TIMEOUT_MS = 3500;
47cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher
48a0842b40441db5332a5290f941021636b1182761Sol Boucher    private static final Log.Tag TAG = new Log.Tag("CamAgnt");
49a0842b40441db5332a5290f941021636b1182761Sol Boucher
50cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher    public static class CameraStartPreviewCallbackForward
51cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher            implements CameraStartPreviewCallback {
52cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher        private final Handler mHandler;
53cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher        private final CameraStartPreviewCallback mCallback;
54cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher
55cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher        public static CameraStartPreviewCallbackForward getNewInstance(
56cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                Handler handler, CameraStartPreviewCallback cb) {
57cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher            if (handler == null || cb == null) {
58cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                return null;
59cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher            }
60cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher            return new CameraStartPreviewCallbackForward(handler, cb);
61cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher        }
62cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher
63cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher        private CameraStartPreviewCallbackForward(Handler h,
64cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                CameraStartPreviewCallback cb) {
65cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher            mHandler = h;
66cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher            mCallback = cb;
67cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher        }
68cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher
69cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher        @Override
70cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher        public void onPreviewStarted() {
71cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher            mHandler.post(new Runnable() {
72cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                @Override
73cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                public void run() {
74cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCallback.onPreviewStarted();
75a0842b40441db5332a5290f941021636b1182761Sol Boucher                }});
76cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher        }
77cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher    }
78cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher
79cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher    /**
80cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher     * A callback helps to invoke the original callback on another
81cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher     * {@link android.os.Handler}.
82cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher     */
83cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher    public static class CameraOpenCallbackForward implements CameraOpenCallback {
84cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher        private final Handler mHandler;
85cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher        private final CameraOpenCallback mCallback;
86cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher
87cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher        /**
88cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher         * Returns a new instance of {@link FaceDetectionCallbackForward}.
89cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher         *
90cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher         * @param handler The handler in which the callback will be invoked in.
91cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher         * @param cb The callback to be invoked.
92cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher         * @return The instance of the {@link FaceDetectionCallbackForward}, or
93cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher         *         null if any parameter is null.
94cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher         */
95cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher        public static CameraOpenCallbackForward getNewInstance(
96cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                Handler handler, CameraOpenCallback cb) {
97cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher            if (handler == null || cb == null) {
98cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                return null;
99cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher            }
100cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher            return new CameraOpenCallbackForward(handler, cb);
101cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher        }
102cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher
103cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher        private CameraOpenCallbackForward(Handler h, CameraOpenCallback cb) {
104cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher            // Given that we are using the main thread handler, we can create it
105cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher            // here instead of holding onto the PhotoModule objects. In this
106cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher            // way, we can avoid memory leak.
107cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher            mHandler = new Handler(Looper.getMainLooper());
108cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher            mCallback = cb;
109cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher        }
110cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher
111cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher        @Override
112cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher        public void onCameraOpened(final CameraProxy camera) {
113cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher            mHandler.post(new Runnable() {
114cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                @Override
115cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                public void run() {
116cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCallback.onCameraOpened(camera);
117a0842b40441db5332a5290f941021636b1182761Sol Boucher                }});
118cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher        }
119cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher
120cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher        @Override
121cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher        public void onCameraDisabled(final int cameraId) {
122cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher            mHandler.post(new Runnable() {
123cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                @Override
124cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                public void run() {
125cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCallback.onCameraDisabled(cameraId);
126a0842b40441db5332a5290f941021636b1182761Sol Boucher                }});
127cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher        }
128cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher
129cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher        @Override
130cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher        public void onDeviceOpenFailure(final int cameraId, final String info) {
131cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher            mHandler.post(new Runnable() {
132cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                @Override
133cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                public void run() {
134cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCallback.onDeviceOpenFailure(cameraId, info);
135a0842b40441db5332a5290f941021636b1182761Sol Boucher                }});
136cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher        }
137cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher
138cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher        @Override
139cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher        public void onDeviceOpenedAlready(final int cameraId, final String info) {
140cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher            mHandler.post(new Runnable() {
141cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                @Override
142cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                public void run() {
143cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCallback.onDeviceOpenedAlready(cameraId, info);
144a0842b40441db5332a5290f941021636b1182761Sol Boucher                }});
145cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher        }
146cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher
147cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher        @Override
1484f425ba476d62b4be7078f2084af37cf306b31c6Sol Boucher        public void onReconnectionFailure(final CameraAgent mgr, final String info) {
149cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher            mHandler.post(new Runnable() {
150cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                @Override
151cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                public void run() {
152cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCallback.onReconnectionFailure(mgr, info);
153a0842b40441db5332a5290f941021636b1182761Sol Boucher                }});
154cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher        }
155cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher    }
156bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
157bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    /**
158bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     * An interface which wraps
159bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     * {@link android.hardware.Camera.ErrorCallback}
160bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     */
161a0842b40441db5332a5290f941021636b1182761Sol Boucher    public static interface CameraErrorCallback {
162bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void onError(int error, CameraProxy camera);
163bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
164bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
165bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    /**
166bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     * An interface which wraps
167bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     * {@link android.hardware.Camera.AutoFocusCallback}.
168bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     */
169a0842b40441db5332a5290f941021636b1182761Sol Boucher    public static interface CameraAFCallback {
170bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void onAutoFocus(boolean focused, CameraProxy camera);
171bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
172bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
173bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    /**
174bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     * An interface which wraps
175bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     * {@link android.hardware.Camera.AutoFocusMoveCallback}.
176bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     */
177a0842b40441db5332a5290f941021636b1182761Sol Boucher    public static interface CameraAFMoveCallback {
178bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void onAutoFocusMoving(boolean moving, CameraProxy camera);
179bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
180bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
181bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    /**
182bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     * An interface which wraps
183bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     * {@link android.hardware.Camera.ShutterCallback}.
184bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     */
185a0842b40441db5332a5290f941021636b1182761Sol Boucher    public static interface CameraShutterCallback {
186bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void onShutter(CameraProxy camera);
187bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
188bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
189bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    /**
190bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     * An interface which wraps
191bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     * {@link android.hardware.Camera.PictureCallback}.
192bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     */
193a0842b40441db5332a5290f941021636b1182761Sol Boucher    public static interface CameraPictureCallback {
194bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void onPictureTaken(byte[] data, CameraProxy camera);
195bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
196bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
197bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    /**
198bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     * An interface which wraps
199bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     * {@link android.hardware.Camera.PreviewCallback}.
200bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     */
201a0842b40441db5332a5290f941021636b1182761Sol Boucher    public static interface CameraPreviewDataCallback {
202bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void onPreviewFrame(byte[] data, CameraProxy camera);
203bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
204bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
205bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    /**
206bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     * An interface which wraps
207bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     * {@link android.hardware.Camera.FaceDetectionListener}.
208bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     */
209a0842b40441db5332a5290f941021636b1182761Sol Boucher    public static interface CameraFaceDetectionCallback {
210bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
211bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * Callback for face detection.
212bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *
213bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param faces   Recognized face in the preview.
214bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param camera  The camera which the preview image comes from.
215bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
216bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void onFaceDetection(Camera.Face[] faces, CameraProxy camera);
217bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
218bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
219bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    /**
2207e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong     * An interface to be called when the camera preview has started.
2217e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong     */
222a0842b40441db5332a5290f941021636b1182761Sol Boucher    public static interface CameraStartPreviewCallback {
2237e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        /**
2247e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong         * Callback when the preview starts.
2257e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong         */
2267e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        public void onPreviewStarted();
2277e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong    }
2287e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong
2297e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong    /**
23060520c4df78e595964605cf8acfa21bbafaeba84Angus Kong     * An interface to be called for any events when opening or closing the
231bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     * camera device. This error callback is different from the one defined
232bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     * in the framework, {@link android.hardware.Camera.ErrorCallback}, which
233bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     * is used after the camera is opened.
234bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     */
235a0842b40441db5332a5290f941021636b1182761Sol Boucher    public static interface CameraOpenCallback {
236bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
237bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * Callback when camera open succeeds.
238bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
239bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void onCameraOpened(CameraProxy camera);
240bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
241bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
242bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * Callback when {@link com.android.camera.CameraDisabledException} is
243bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * caught.
244bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *
245bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param cameraId The disabled camera.
246bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
247bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void onCameraDisabled(int cameraId);
248bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
249bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
250bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * Callback when {@link com.android.camera.CameraHardwareException} is
251bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * caught.
252bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *
253bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param cameraId The camera with the hardware failure.
254b00b7a67213ee6868eb792b2a63ba0dca888a01fAngus Kong         * @param info The extra info regarding this failure.
255bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
256b00b7a67213ee6868eb792b2a63ba0dca888a01fAngus Kong        public void onDeviceOpenFailure(int cameraId, String info);
257bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
258bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
259bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * Callback when trying to open the camera which is already opened.
260bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *
261bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param cameraId The camera which is causing the open error.
262bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
26360520c4df78e595964605cf8acfa21bbafaeba84Angus Kong        public void onDeviceOpenedAlready(int cameraId, String info);
264bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
265bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
266bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * Callback when {@link java.io.IOException} is caught during
267bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * {@link android.hardware.Camera#reconnect()}.
268bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *
2694f425ba476d62b4be7078f2084af37cf306b31c6Sol Boucher         * @param mgr The {@link CameraAgent}
270bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *            with the reconnect failure.
271bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
2724f425ba476d62b4be7078f2084af37cf306b31c6Sol Boucher        public void onReconnectionFailure(CameraAgent mgr, String info);
273bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
274bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
275bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    /**
276bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     * Opens the camera of the specified ID asynchronously. The camera device
277bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     * will be opened in the camera handler thread and will be returned through
2784f425ba476d62b4be7078f2084af37cf306b31c6Sol Boucher     * the {@link CameraAgent.CameraOpenCallback#
2794f425ba476d62b4be7078f2084af37cf306b31c6Sol Boucher     * onCameraOpened(com.android.camera.cameradevice.CameraAgent.CameraProxy)}.
280bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     *
281bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     * @param handler The {@link android.os.Handler} in which the callback
282bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     *                was handled.
28360520c4df78e595964605cf8acfa21bbafaeba84Angus Kong     * @param callback The callback for the result.
284bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     * @param cameraId The camera ID to open.
285bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     */
286a0842b40441db5332a5290f941021636b1182761Sol Boucher    public void openCamera(final Handler handler, final int cameraId,
287a0842b40441db5332a5290f941021636b1182761Sol Boucher                           final CameraOpenCallback callback) {
2882d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu        try {
2892d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            getDispatchThread().runJob(new Runnable() {
2902d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                @Override
2912d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                public void run() {
2922d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    getCameraHandler().obtainMessage(CameraActions.OPEN_CAMERA, cameraId, 0,
2932d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                            CameraOpenCallbackForward.getNewInstance(handler, callback)).sendToTarget();
2942d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                }
2952d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            });
2962d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu        } catch (final RuntimeException ex) {
2972d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            getCameraExceptionHandler().onDispatchThreadException(ex);
2982d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu        }
299a0842b40441db5332a5290f941021636b1182761Sol Boucher    }
30060520c4df78e595964605cf8acfa21bbafaeba84Angus Kong
30160520c4df78e595964605cf8acfa21bbafaeba84Angus Kong    /**
30260520c4df78e595964605cf8acfa21bbafaeba84Angus Kong     * Closes the camera device.
30360520c4df78e595964605cf8acfa21bbafaeba84Angus Kong     *
30460520c4df78e595964605cf8acfa21bbafaeba84Angus Kong     * @param camera The camera to close. {@code null} means all.
30560520c4df78e595964605cf8acfa21bbafaeba84Angus Kong     * @param synced Whether this call should be synchronous.
30660520c4df78e595964605cf8acfa21bbafaeba84Angus Kong     */
307a0842b40441db5332a5290f941021636b1182761Sol Boucher    public void closeCamera(CameraProxy camera, boolean synced) {
3082d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu        try {
3092d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            if (synced) {
3102d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                // Don't bother to wait since camera is in bad state.
3112d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                if (getCameraState().isInvalid()) {
3122d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    return;
3132d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                }
3142d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                final WaitDoneBundle bundle = new WaitDoneBundle();
3152d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu
3162d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                getDispatchThread().runJobSync(new Runnable() {
3172d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    @Override
3182d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    public void run() {
3192d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                        getCameraHandler().obtainMessage(CameraActions.RELEASE).sendToTarget();
3202d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                        getCameraHandler().post(bundle.mUnlockRunnable);
3212d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    }}, bundle.mWaitLock, CAMERA_OPERATION_TIMEOUT_MS, "camera release");
3222d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            } else {
3232d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                getDispatchThread().runJob(new Runnable() {
3242d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    @Override
3252d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    public void run() {
3262d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                        getCameraHandler().removeCallbacksAndMessages(null);
3272d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                        getCameraHandler().obtainMessage(CameraActions.RELEASE).sendToTarget();
3282d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    }});
3292d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            }
3302d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu        } catch (final RuntimeException ex) {
3312d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            getCameraExceptionHandler().onDispatchThreadException(ex);
332a0842b40441db5332a5290f941021636b1182761Sol Boucher        }
333a0842b40441db5332a5290f941021636b1182761Sol Boucher    }
334bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
335bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    /**
3367e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong     * Sets a callback for handling camera api runtime exceptions on
3377e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong     * a handler.
3387e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong     */
3392d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu    public abstract void setCameraExceptionHandler(CameraExceptionHandler exceptionHandler);
3407e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong
3417e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong    /**
3424f425ba476d62b4be7078f2084af37cf306b31c6Sol Boucher     * Recycles the resources used by this instance. CameraAgent will be in
3437e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong     * an unusable state after calling this.
3447e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong     */
345a0842b40441db5332a5290f941021636b1182761Sol Boucher    public abstract void recycle();
3467e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong
3477e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong    /**
3487e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong     * @return The camera devices info.
3497e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong     */
350a0842b40441db5332a5290f941021636b1182761Sol Boucher    public abstract CameraDeviceInfo getCameraDeviceInfo();
351a0842b40441db5332a5290f941021636b1182761Sol Boucher
352a0842b40441db5332a5290f941021636b1182761Sol Boucher    /**
353a0842b40441db5332a5290f941021636b1182761Sol Boucher     * @return The handler to which camera tasks should be posted.
354a0842b40441db5332a5290f941021636b1182761Sol Boucher     */
355a0842b40441db5332a5290f941021636b1182761Sol Boucher    protected abstract Handler getCameraHandler();
356a0842b40441db5332a5290f941021636b1182761Sol Boucher
357a0842b40441db5332a5290f941021636b1182761Sol Boucher    /**
358a0842b40441db5332a5290f941021636b1182761Sol Boucher     * @return The thread used on which client callbacks are served.
359a0842b40441db5332a5290f941021636b1182761Sol Boucher     */
360a0842b40441db5332a5290f941021636b1182761Sol Boucher    protected abstract DispatchThread getDispatchThread();
3617e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong
3627e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong    /**
3632d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu     * @return The state machine tracking the camera API's current status.
3642d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu     */
3652d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu    protected abstract CameraStateHolder getCameraState();
3662d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu
3672d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu    /**
3682d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu     * @return The exception handler.
3692d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu     */
3702d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu    protected abstract CameraExceptionHandler getCameraExceptionHandler();
3712d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu
3722d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu    /**
373bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     * An interface that takes camera operation requests and post messages to the
374bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     * camera handler thread. All camera operations made through this interface is
375bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     * asynchronous by default except those mentioned specifically.
376bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     */
3772d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu    public abstract static class CameraProxy {
378bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
379bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
380bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * Returns the underlying {@link android.hardware.Camera} object used
381bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * by this proxy. This method should only be used when handing the
382bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * camera device over to {@link android.media.MediaRecorder} for
383bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * recording.
384bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
385bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Deprecated
386a0842b40441db5332a5290f941021636b1182761Sol Boucher        public abstract android.hardware.Camera getCamera();
387bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
388bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
389c36e3c983c232dc45ed31f3d8e98d8cdd7ac14baAngus Kong         * @return The camera ID associated to by this
3904f425ba476d62b4be7078f2084af37cf306b31c6Sol Boucher         * {@link CameraAgent.CameraProxy}.
391bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
392a0842b40441db5332a5290f941021636b1182761Sol Boucher        public abstract int getCameraId();
393bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
394bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
395b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher         * @return The camera characteristics.
396b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher         */
397a0842b40441db5332a5290f941021636b1182761Sol Boucher        public abstract CameraDeviceInfo.Characteristics getCharacteristics();
398b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher
399b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher        /**
400c36e3c983c232dc45ed31f3d8e98d8cdd7ac14baAngus Kong         * @return The camera capabilities.
401c36e3c983c232dc45ed31f3d8e98d8cdd7ac14baAngus Kong         */
402a0842b40441db5332a5290f941021636b1182761Sol Boucher        public abstract CameraCapabilities getCapabilities();
403c36e3c983c232dc45ed31f3d8e98d8cdd7ac14baAngus Kong
404c36e3c983c232dc45ed31f3d8e98d8cdd7ac14baAngus Kong        /**
4052d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu         * @return The camera agent which creates this proxy.
4062d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu         */
4072d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu        public abstract CameraAgent getAgent();
4082d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu
4092d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu        /**
410bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * Reconnects to the camera device. On success, the camera device will
4114f425ba476d62b4be7078f2084af37cf306b31c6Sol Boucher         * be returned through {@link CameraAgent
4124f425ba476d62b4be7078f2084af37cf306b31c6Sol Boucher         * .CameraOpenCallback#onCameraOpened(com.android.camera.cameradevice.CameraAgent
413bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * .CameraProxy)}.
414bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @see android.hardware.Camera#reconnect()
415bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *
416bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param handler The {@link android.os.Handler} in which the callback
417bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *                was handled.
418bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param cb The callback when any error happens.
419bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
420a0842b40441db5332a5290f941021636b1182761Sol Boucher        public void reconnect(final Handler handler, final CameraOpenCallback cb) {
4212d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            try {
4222d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                getDispatchThread().runJob(new Runnable() {
4232d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    @Override
4242d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    public void run() {
4252d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                        getCameraHandler().obtainMessage(CameraActions.RECONNECT, getCameraId(), 0,
4262d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                                CameraOpenCallbackForward.getNewInstance(handler, cb)).sendToTarget();
4272d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    }});
4282d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            } catch (final RuntimeException ex) {
4292d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                getAgent().getCameraExceptionHandler().onDispatchThreadException(ex);
4302d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            }
431a0842b40441db5332a5290f941021636b1182761Sol Boucher        }
432bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
433bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
434bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * Unlocks the camera device.
435bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *
436bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @see android.hardware.Camera#unlock()
437bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
438a0842b40441db5332a5290f941021636b1182761Sol Boucher        public void unlock() {
4392d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            // Don't bother to wait since camera is in bad state.
4402d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            if (getCameraState().isInvalid()) {
4412d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                return;
4422d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            }
443a0842b40441db5332a5290f941021636b1182761Sol Boucher            final WaitDoneBundle bundle = new WaitDoneBundle();
4442d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            try {
4452d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                getDispatchThread().runJobSync(new Runnable() {
4462d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    @Override
4472d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    public void run() {
4482d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                        getCameraHandler().sendEmptyMessage(CameraActions.UNLOCK);
4492d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                        getCameraHandler().post(bundle.mUnlockRunnable);
4502d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    }
4512d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                }, bundle.mWaitLock, CAMERA_OPERATION_TIMEOUT_MS, "camera unlock");
4522d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            } catch (final RuntimeException ex) {
4532d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                getAgent().getCameraExceptionHandler().onDispatchThreadException(ex);
4542d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            }
455a0842b40441db5332a5290f941021636b1182761Sol Boucher        }
456bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
457bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
458bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * Locks the camera device.
459bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @see android.hardware.Camera#lock()
460bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
461a0842b40441db5332a5290f941021636b1182761Sol Boucher        public void lock() {
4622d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            try {
4632d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                getDispatchThread().runJob(new Runnable() {
4642d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    @Override
4652d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    public void run() {
4662d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                        getCameraHandler().sendEmptyMessage(CameraActions.LOCK);
4672d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    }});
4682d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            } catch (final RuntimeException ex) {
4692d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                getAgent().getCameraExceptionHandler().onDispatchThreadException(ex);
4702d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            }
471a0842b40441db5332a5290f941021636b1182761Sol Boucher        }
472bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
473bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
474bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * Sets the {@link android.graphics.SurfaceTexture} for preview.
475bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *
4762569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher         * <p>Note that, once this operation has been performed, it is no longer
4772569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher         * possible to change the preview or photo sizes in the
4782569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher         * {@link CameraSettings} instance for this camera, and the mutators for
4792569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher         * these fields are allowed to ignore all further invocations until the
4802569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher         * preview is stopped with {@link #stopPreview}.</p>
4812569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher         *
482bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param surfaceTexture The {@link SurfaceTexture} for preview.
4832569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher         *
4842569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher         * @see CameraSettings#setPhotoSize
4852569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher         * @see CameraSettings#setPreviewSize
486bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
4872569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher        // XXX: Despite the above documentation about locking the sizes, the API
4882569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher        // 1 implementation doesn't currently enforce this at all, although the
4892569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher        // Camera class warns that preview sizes shouldn't be changed while a
4902569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher        // preview is running. Furthermore, the API 2 implementation doesn't yet
4912569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher        // unlock the sizes when stopPreview() is invoked (see related FIXME on
4922569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher        // the STOP_PREVIEW case in its handler; in the meantime, changing API 2
4932569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher        // sizes would require closing and reopening the camera.
494a0842b40441db5332a5290f941021636b1182761Sol Boucher        public void setPreviewTexture(final SurfaceTexture surfaceTexture) {
4952d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            try {
4962d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                getDispatchThread().runJob(new Runnable() {
4972d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    @Override
4982d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    public void run() {
4992d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                        getCameraHandler()
5002d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                                .obtainMessage(CameraActions.SET_PREVIEW_TEXTURE_ASYNC, surfaceTexture)
5012d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                                .sendToTarget();
5022d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    }});
5032d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            } catch (final RuntimeException ex) {
5042d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                getAgent().getCameraExceptionHandler().onDispatchThreadException(ex);
5052d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            }
506a0842b40441db5332a5290f941021636b1182761Sol Boucher        }
507bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
508bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
509bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * Blocks until a {@link android.graphics.SurfaceTexture} has been set
510bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * for preview.
511bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *
5122569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher         * <p>Note that, once this operation has been performed, it is no longer
5132569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher         * possible to change the preview or photo sizes in the
5142569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher         * {@link CameraSettings} instance for this camera, and the mutators for
5152569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher         * these fields are allowed to ignore all further invocations.</p>
5162569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher         *
517bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param surfaceTexture The {@link SurfaceTexture} for preview.
5182569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher         *
5192569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher         * @see CameraSettings#setPhotoSize
5202569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher         * @see CameraSettings#setPreviewSize
521bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
522a0842b40441db5332a5290f941021636b1182761Sol Boucher        public void setPreviewTextureSync(final SurfaceTexture surfaceTexture) {
5232d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            // Don't bother to wait since camera is in bad state.
5242d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            if (getCameraState().isInvalid()) {
5252d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                return;
5262d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            }
527a0842b40441db5332a5290f941021636b1182761Sol Boucher            final WaitDoneBundle bundle = new WaitDoneBundle();
5282d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            try {
5292d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                getDispatchThread().runJobSync(new Runnable() {
5302d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    @Override
5312d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    public void run() {
5322d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                        getCameraHandler()
5332d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                                .obtainMessage(CameraActions.SET_PREVIEW_TEXTURE_ASYNC, surfaceTexture)
5342d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                                .sendToTarget();
5352d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                        getCameraHandler().post(bundle.mUnlockRunnable);
5362d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    }}, bundle.mWaitLock, CAMERA_OPERATION_TIMEOUT_MS, "set preview texture");
5372d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            } catch (final RuntimeException ex) {
5382d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                getAgent().getCameraExceptionHandler().onDispatchThreadException(ex);
5392d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            }
540a0842b40441db5332a5290f941021636b1182761Sol Boucher        }
541bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
542bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
543bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * Sets the {@link android.view.SurfaceHolder} for preview.
544bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *
545bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param surfaceHolder The {@link SurfaceHolder} for preview.
546bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
547a0842b40441db5332a5290f941021636b1182761Sol Boucher        public void setPreviewDisplay(final SurfaceHolder surfaceHolder) {
5482d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            try {
5492d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                getDispatchThread().runJob(new Runnable() {
5502d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    @Override
5512d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    public void run() {
5522d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                        getCameraHandler()
5532d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                                .obtainMessage(CameraActions.SET_PREVIEW_DISPLAY_ASYNC, surfaceHolder)
5542d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                                .sendToTarget();
5552d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    }});
5562d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            } catch (final RuntimeException ex) {
5572d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                getAgent().getCameraExceptionHandler().onDispatchThreadException(ex);
5582d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            }
559a0842b40441db5332a5290f941021636b1182761Sol Boucher        }
560bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
561bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
562bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * Starts the camera preview.
563bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
564a0842b40441db5332a5290f941021636b1182761Sol Boucher        public void startPreview() {
5652d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            try {
566a0842b40441db5332a5290f941021636b1182761Sol Boucher            getDispatchThread().runJob(new Runnable() {
567a0842b40441db5332a5290f941021636b1182761Sol Boucher                @Override
568a0842b40441db5332a5290f941021636b1182761Sol Boucher                public void run() {
569a0842b40441db5332a5290f941021636b1182761Sol Boucher                    getCameraHandler()
570a0842b40441db5332a5290f941021636b1182761Sol Boucher                            .obtainMessage(CameraActions.START_PREVIEW_ASYNC, null).sendToTarget();
571a0842b40441db5332a5290f941021636b1182761Sol Boucher                }});
5722d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            } catch (final RuntimeException ex) {
5732d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                getAgent().getCameraExceptionHandler().onDispatchThreadException(ex);
5742d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            }
575a0842b40441db5332a5290f941021636b1182761Sol Boucher        }
576bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
577bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
578bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * Starts the camera preview and executes a callback on a handler once
579bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * the preview starts.
580bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
581a0842b40441db5332a5290f941021636b1182761Sol Boucher        public void startPreviewWithCallback(final Handler h, final CameraStartPreviewCallback cb) {
5822d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            try {
583a0842b40441db5332a5290f941021636b1182761Sol Boucher            getDispatchThread().runJob(new Runnable() {
584a0842b40441db5332a5290f941021636b1182761Sol Boucher                @Override
585a0842b40441db5332a5290f941021636b1182761Sol Boucher                public void run() {
586a0842b40441db5332a5290f941021636b1182761Sol Boucher                    getCameraHandler().obtainMessage(CameraActions.START_PREVIEW_ASYNC,
587a0842b40441db5332a5290f941021636b1182761Sol Boucher                            CameraStartPreviewCallbackForward.getNewInstance(h, cb))
588a0842b40441db5332a5290f941021636b1182761Sol Boucher                                    .sendToTarget();
589a0842b40441db5332a5290f941021636b1182761Sol Boucher                }});
5902d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            } catch (final RuntimeException ex) {
5912d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                getAgent().getCameraExceptionHandler().onDispatchThreadException(ex);
5922d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            }
593a0842b40441db5332a5290f941021636b1182761Sol Boucher        }
594bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
595bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
596bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * Stops the camera preview synchronously.
597bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * {@code stopPreview()} must be synchronous to ensure that the caller can
598bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * continues to release resources related to camera preview.
599bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
600a0842b40441db5332a5290f941021636b1182761Sol Boucher        public void stopPreview() {
6012d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            // Don't bother to wait since camera is in bad state.
6022d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            if (getCameraState().isInvalid()) {
6032d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                return;
6042d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            }
605a0842b40441db5332a5290f941021636b1182761Sol Boucher            final WaitDoneBundle bundle = new WaitDoneBundle();
6062d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            try {
6072d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                getDispatchThread().runJobSync(new Runnable() {
6082d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    @Override
6092d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    public void run() {
6102d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                        getCameraHandler().obtainMessage(CameraActions.STOP_PREVIEW, bundle)
6112d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                                .sendToTarget();
6122d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    }}, bundle.mWaitLock, CAMERA_OPERATION_TIMEOUT_MS, "stop preview");
6132d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            } catch (final RuntimeException ex) {
6142d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                getAgent().getCameraExceptionHandler().onDispatchThreadException(ex);
6152d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            }
616a0842b40441db5332a5290f941021636b1182761Sol Boucher        }
617bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
618bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
619bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * Sets the callback for preview data.
620bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *
621bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param handler    The {@link android.os.Handler} in which the callback was handled.
622bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param cb         The callback to be invoked when the preview data is available.
623bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @see  android.hardware.Camera#setPreviewCallback(android.hardware.Camera.PreviewCallback)
624bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
625a0842b40441db5332a5290f941021636b1182761Sol Boucher        public abstract void setPreviewDataCallback(Handler handler, CameraPreviewDataCallback cb);
626bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
627bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
628bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * Sets the one-time callback for preview data.
629bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *
630bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param handler    The {@link android.os.Handler} in which the callback was handled.
631bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param cb         The callback to be invoked when the preview data for
632bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *                   next frame is available.
633bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @see  android.hardware.Camera#setPreviewCallback(android.hardware.Camera.PreviewCallback)
634bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
635a0842b40441db5332a5290f941021636b1182761Sol Boucher        public abstract void setOneShotPreviewCallback(Handler handler,
636a0842b40441db5332a5290f941021636b1182761Sol Boucher                                                       CameraPreviewDataCallback cb);
637bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
638bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
639bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * Sets the callback for preview data.
640bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *
641bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param handler The handler in which the callback will be invoked.
642bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param cb      The callback to be invoked when the preview data is available.
643bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @see android.hardware.Camera#setPreviewCallbackWithBuffer(android.hardware.Camera.PreviewCallback)
644bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
645a0842b40441db5332a5290f941021636b1182761Sol Boucher        public abstract void setPreviewDataCallbackWithBuffer(Handler handler,
646a0842b40441db5332a5290f941021636b1182761Sol Boucher                                                              CameraPreviewDataCallback cb);
647bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
648bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
649bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * Adds buffer for the preview callback.
650bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *
651bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param callbackBuffer The buffer allocated for the preview data.
652bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
653a0842b40441db5332a5290f941021636b1182761Sol Boucher        public void addCallbackBuffer(final byte[] callbackBuffer) {
6542d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            try {
6552d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                getDispatchThread().runJob(new Runnable() {
6562d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    @Override
6572d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    public void run() {
6582d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                        getCameraHandler()
6592d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                                .obtainMessage(CameraActions.ADD_CALLBACK_BUFFER, callbackBuffer)
6602d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                                .sendToTarget();
6612d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                        }
6622d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    });
6632d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            } catch (final RuntimeException ex) {
6642d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                getAgent().getCameraExceptionHandler().onDispatchThreadException(ex);
6652d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            }
666a0842b40441db5332a5290f941021636b1182761Sol Boucher        }
667bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
668bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
669bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * Starts the auto-focus process. The result will be returned through the callback.
670bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *
671bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param handler The handler in which the callback will be invoked.
672bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param cb      The auto-focus callback.
673bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
674a0842b40441db5332a5290f941021636b1182761Sol Boucher        public abstract void autoFocus(Handler handler, CameraAFCallback cb);
675bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
676bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
677bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * Cancels the auto-focus process.
6786a9babad6eb8ac3e79a5e036d878ed7408e79f26Igor Murashkin         *
6796a9babad6eb8ac3e79a5e036d878ed7408e79f26Igor Murashkin         * <p>This action has the highest priority and will get processed before anything
6806a9babad6eb8ac3e79a5e036d878ed7408e79f26Igor Murashkin         * else that is pending. Moreover, any pending auto-focuses that haven't yet
6816a9babad6eb8ac3e79a5e036d878ed7408e79f26Igor Murashkin         * began will also be ignored.</p>
682bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
683a0842b40441db5332a5290f941021636b1182761Sol Boucher        public void cancelAutoFocus() {
6846a9babad6eb8ac3e79a5e036d878ed7408e79f26Igor Murashkin             // Do not use the dispatch thread since we want to avoid a wait-cycle
6856a9babad6eb8ac3e79a5e036d878ed7408e79f26Igor Murashkin             // between applySettingsHelper which waits until the state is not FOCUSING.
6866a9babad6eb8ac3e79a5e036d878ed7408e79f26Igor Murashkin             // cancelAutoFocus should get executed asap, set the state back to idle.
6876a9babad6eb8ac3e79a5e036d878ed7408e79f26Igor Murashkin            getCameraHandler().sendMessageAtFrontOfQueue(
6886a9babad6eb8ac3e79a5e036d878ed7408e79f26Igor Murashkin                    getCameraHandler().obtainMessage(CameraActions.CANCEL_AUTO_FOCUS));
6896a9babad6eb8ac3e79a5e036d878ed7408e79f26Igor Murashkin            getCameraHandler().sendEmptyMessage(CameraActions.CANCEL_AUTO_FOCUS_FINISH);
690a0842b40441db5332a5290f941021636b1182761Sol Boucher        }
691bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
692bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
693bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * Sets the auto-focus callback
694bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *
695bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param handler The handler in which the callback will be invoked.
696bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param cb      The callback to be invoked when the preview data is available.
697bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
698bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
699a0842b40441db5332a5290f941021636b1182761Sol Boucher        public abstract void setAutoFocusMoveCallback(Handler handler, CameraAFMoveCallback cb);
700bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
701bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
702bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * Instrument the camera to take a picture.
703bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *
704bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param handler   The handler in which the callback will be invoked.
705bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param shutter   The callback for shutter action, may be null.
706bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param raw       The callback for uncompressed data, may be null.
707bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param postview  The callback for postview image data, may be null.
708bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param jpeg      The callback for jpeg image data, may be null.
709bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @see android.hardware.Camera#takePicture(
710bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *         android.hardware.Camera.ShutterCallback,
711bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *         android.hardware.Camera.PictureCallback,
712bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *         android.hardware.Camera.PictureCallback)
713bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
714a0842b40441db5332a5290f941021636b1182761Sol Boucher        public abstract void takePicture(
715bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Handler handler,
716bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                CameraShutterCallback shutter,
717bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                CameraPictureCallback raw,
718bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                CameraPictureCallback postview,
719bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                CameraPictureCallback jpeg);
720bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
721bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
722de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher         * Sets the display orientation for camera to adjust the preview and JPEG orientation.
723bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *
724de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher         * @param degrees The counterclockwise rotation in degrees, relative to the device's natural
725de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher         *                orientation. Should be 0, 90, 180 or 270.
726bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
727a0842b40441db5332a5290f941021636b1182761Sol Boucher        public void setDisplayOrientation(final int degrees) {
728de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher            setDisplayOrientation(degrees, true);
729de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        }
730de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher
731de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        /**
732de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher         * Sets the display orientation for camera to adjust the preview&mdash;and, optionally,
733de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher         * JPEG&mdash;orientations.
734de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher         * <p>If capture rotation is not requested, future captures will be returned in the sensor's
735de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher         * physical rotation, which does not necessarily match the device's natural orientation.</p>
736de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher         *
737de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher         * @param degrees The counterclockwise rotation in degrees, relative to the device's natural
738de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher         *                orientation. Should be 0, 90, 180 or 270.
739de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher         * @param capture Whether to adjust the JPEG capture orientation as well as the preview one.
740de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher         */
741de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        public void setDisplayOrientation(final int degrees, final boolean capture) {
7422d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            try {
7432d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                getDispatchThread().runJob(new Runnable() {
7442d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    @Override
7452d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    public void run() {
7462d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                        getCameraHandler()
7472d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                                .obtainMessage(CameraActions.SET_DISPLAY_ORIENTATION, degrees,
7482d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                                        capture ? 1 : 0)
7492d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                                .sendToTarget();
7502d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    }});
7512d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            } catch (final RuntimeException ex) {
7522d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                getAgent().getCameraExceptionHandler().onDispatchThreadException(ex);
7532d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            }
754a0842b40441db5332a5290f941021636b1182761Sol Boucher        }
755bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
75625ee73acd2dbd6f60deef5306994fbf3a7997936Senpo Hu        public void setJpegOrientation(final int degrees) {
7572d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            try {
7582d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                getDispatchThread().runJob(new Runnable() {
7592d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    @Override
7602d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    public void run() {
7612d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                        getCameraHandler()
7622d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                                .obtainMessage(CameraActions.SET_JPEG_ORIENTATION, degrees, 0)
7632d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                                .sendToTarget();
7642d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    }});
7652d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            } catch (final RuntimeException ex) {
7662d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                getAgent().getCameraExceptionHandler().onDispatchThreadException(ex);
7672d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            }
76825ee73acd2dbd6f60deef5306994fbf3a7997936Senpo Hu        }
76925ee73acd2dbd6f60deef5306994fbf3a7997936Senpo Hu
770bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
771bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * Sets the listener for zoom change.
772bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *
773bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param listener The listener.
774bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
775a0842b40441db5332a5290f941021636b1182761Sol Boucher        public abstract void setZoomChangeListener(OnZoomChangeListener listener);
776bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
777bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
778bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * Sets the face detection listener.
779bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *
780bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param handler  The handler in which the callback will be invoked.
781bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param callback The callback for face detection results.
782bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
783a0842b40441db5332a5290f941021636b1182761Sol Boucher        public abstract void setFaceDetectionCallback(Handler handler,
784a0842b40441db5332a5290f941021636b1182761Sol Boucher                                                      CameraFaceDetectionCallback callback);
785bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
786bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
787bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * Starts the face detection.
788bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
789a0842b40441db5332a5290f941021636b1182761Sol Boucher        public void startFaceDetection() {
7902d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            try {
7912d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                getDispatchThread().runJob(new Runnable() {
7922d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    @Override
7932d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    public void run() {
7942d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                        getCameraHandler().sendEmptyMessage(CameraActions.START_FACE_DETECTION);
7952d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    }});
7962d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            } catch (final RuntimeException ex) {
7972d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                getAgent().getCameraExceptionHandler().onDispatchThreadException(ex);
7982d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            }
799a0842b40441db5332a5290f941021636b1182761Sol Boucher        }
800bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
801bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
802bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * Stops the face detection.
803bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
804a0842b40441db5332a5290f941021636b1182761Sol Boucher        public void stopFaceDetection() {
8052d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            try {
8062d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                getDispatchThread().runJob(new Runnable() {
8072d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    @Override
8082d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    public void run() {
8092d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                        getCameraHandler().sendEmptyMessage(CameraActions.STOP_FACE_DETECTION);
8102d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    }});
8112d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            } catch (final RuntimeException ex) {
8122d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                getAgent().getCameraExceptionHandler().onDispatchThreadException(ex);
8132d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            }
814a0842b40441db5332a5290f941021636b1182761Sol Boucher        }
815bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
816bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
817bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * Sets the camera parameters.
818bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *
819bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param params The camera parameters to use.
820bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
8218097973089420749dcd1ab4974a629c2466b31ccAngus Kong        @Deprecated
822a0842b40441db5332a5290f941021636b1182761Sol Boucher        public abstract void setParameters(Camera.Parameters params);
823bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
824bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
825bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * Gets the current camera parameters synchronously. This method is
826bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * synchronous since the caller has to wait for the camera to return
827bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * the parameters. If the parameters are already cached, it returns
828bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * immediately.
829bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
8308097973089420749dcd1ab4974a629c2466b31ccAngus Kong        @Deprecated
831a0842b40441db5332a5290f941021636b1182761Sol Boucher        public abstract Camera.Parameters getParameters();
832bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
833bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
8348097973089420749dcd1ab4974a629c2466b31ccAngus Kong         * Gets the current camera settings synchronously.
8358097973089420749dcd1ab4974a629c2466b31ccAngus Kong         * <p>This method is synchronous since the caller has to wait for the
8368097973089420749dcd1ab4974a629c2466b31ccAngus Kong         * camera to return the parameters. If the parameters are already
8378097973089420749dcd1ab4974a629c2466b31ccAngus Kong         * cached, it returns immediately.</p>
8388097973089420749dcd1ab4974a629c2466b31ccAngus Kong         */
839a0842b40441db5332a5290f941021636b1182761Sol Boucher        public abstract CameraSettings getSettings();
840a0842b40441db5332a5290f941021636b1182761Sol Boucher
841a0842b40441db5332a5290f941021636b1182761Sol Boucher        /**
842a0842b40441db5332a5290f941021636b1182761Sol Boucher         * Default implementation of {@link #applySettings(CameraSettings)}
843a0842b40441db5332a5290f941021636b1182761Sol Boucher         * that is only missing the set of states it needs to wait for
844a0842b40441db5332a5290f941021636b1182761Sol Boucher         * before applying the settings.
845a0842b40441db5332a5290f941021636b1182761Sol Boucher         *
846a0842b40441db5332a5290f941021636b1182761Sol Boucher         * @param settings The settings to use on the device.
847a0842b40441db5332a5290f941021636b1182761Sol Boucher         * @param statesToAwait Bitwise OR of the required camera states.
848a0842b40441db5332a5290f941021636b1182761Sol Boucher         * @return Whether the settings can be applied.
849a0842b40441db5332a5290f941021636b1182761Sol Boucher         */
850de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        protected boolean applySettingsHelper(CameraSettings settings,
851a0842b40441db5332a5290f941021636b1182761Sol Boucher                                              final int statesToAwait) {
852a0842b40441db5332a5290f941021636b1182761Sol Boucher            if (settings == null) {
8539d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher                Log.v(TAG, "null argument in applySettings()");
854a0842b40441db5332a5290f941021636b1182761Sol Boucher                return false;
855a0842b40441db5332a5290f941021636b1182761Sol Boucher            }
856a0842b40441db5332a5290f941021636b1182761Sol Boucher            if (!getCapabilities().supports(settings)) {
8579d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher                Log.w(TAG, "Unsupported settings in applySettings()");
858a0842b40441db5332a5290f941021636b1182761Sol Boucher                return false;
859a0842b40441db5332a5290f941021636b1182761Sol Boucher            }
860a0842b40441db5332a5290f941021636b1182761Sol Boucher
861de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher            final CameraSettings copyOfSettings = settings.copy();
8622d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            try {
8632d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                getDispatchThread().runJob(new Runnable() {
8642d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    @Override
8652d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    public void run() {
8662d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                        CameraStateHolder cameraState = getCameraState();
8672d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                        // Don't bother to wait since camera is in bad state.
8682d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                        if (cameraState.isInvalid()) {
8692d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                            return;
8702d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                        }
8712d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                        cameraState.waitForStates(statesToAwait);
8722d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                        getCameraHandler().obtainMessage(CameraActions.APPLY_SETTINGS, copyOfSettings)
8732d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                                .sendToTarget();
8742d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    }});
8752d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            } catch (final RuntimeException ex) {
8762d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                getAgent().getCameraExceptionHandler().onDispatchThreadException(ex);
8772d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            }
878a0842b40441db5332a5290f941021636b1182761Sol Boucher            return true;
879a0842b40441db5332a5290f941021636b1182761Sol Boucher        }
8808097973089420749dcd1ab4974a629c2466b31ccAngus Kong
8818097973089420749dcd1ab4974a629c2466b31ccAngus Kong        /**
8828097973089420749dcd1ab4974a629c2466b31ccAngus Kong         * Applies the settings to the camera device.
8838097973089420749dcd1ab4974a629c2466b31ccAngus Kong         *
8846a9babad6eb8ac3e79a5e036d878ed7408e79f26Igor Murashkin         * <p>If the camera is either focusing or capturing; settings applications
8856a9babad6eb8ac3e79a5e036d878ed7408e79f26Igor Murashkin         * will be (asynchronously) deferred until those operations complete.</p>
8866a9babad6eb8ac3e79a5e036d878ed7408e79f26Igor Murashkin         *
8878097973089420749dcd1ab4974a629c2466b31ccAngus Kong         * @param settings The settings to use on the device.
8888097973089420749dcd1ab4974a629c2466b31ccAngus Kong         * @return Whether the settings can be applied.
8898097973089420749dcd1ab4974a629c2466b31ccAngus Kong         */
890a0842b40441db5332a5290f941021636b1182761Sol Boucher        public abstract boolean applySettings(CameraSettings settings);
8918097973089420749dcd1ab4974a629c2466b31ccAngus Kong
8928097973089420749dcd1ab4974a629c2466b31ccAngus Kong        /**
893bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * Forces {@code CameraProxy} to update the cached version of the camera
8948097973089420749dcd1ab4974a629c2466b31ccAngus Kong         * settings regardless of the dirty bit.
895bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
896a0842b40441db5332a5290f941021636b1182761Sol Boucher        public void refreshSettings() {
8972d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            try {
8982d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                getDispatchThread().runJob(new Runnable() {
8992d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    @Override
9002d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    public void run() {
9012d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                        getCameraHandler().sendEmptyMessage(CameraActions.REFRESH_PARAMETERS);
9022d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    }});
9032d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            } catch (final RuntimeException ex) {
9042d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                getAgent().getCameraExceptionHandler().onDispatchThreadException(ex);
9052d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            }
906a0842b40441db5332a5290f941021636b1182761Sol Boucher        }
907bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
908bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
909bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * Enables/Disables the camera shutter sound.
910bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *
911bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param enable   {@code true} to enable the shutter sound,
912bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *                 {@code false} to disable it.
913bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
914a0842b40441db5332a5290f941021636b1182761Sol Boucher        public void enableShutterSound(final boolean enable) {
9152d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            try {
9162d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                getDispatchThread().runJob(new Runnable() {
9172d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    @Override
9182d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    public void run() {
9192d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                        getCameraHandler()
9202d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                                .obtainMessage(CameraActions.ENABLE_SHUTTER_SOUND, (enable ? 1 : 0), 0)
9212d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                                .sendToTarget();
9222d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    }});
9232d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            } catch (final RuntimeException ex) {
9242d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                getAgent().getCameraExceptionHandler().onDispatchThreadException(ex);
9252d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            }
926a0842b40441db5332a5290f941021636b1182761Sol Boucher        }
92701e7c02174ef268b6d6daaa5a5bb4f752d55964cAngus Kong
92801e7c02174ef268b6d6daaa5a5bb4f752d55964cAngus Kong        /**
92901e7c02174ef268b6d6daaa5a5bb4f752d55964cAngus Kong         * Dumps the current settings of the camera device.
93001e7c02174ef268b6d6daaa5a5bb4f752d55964cAngus Kong         *
93101e7c02174ef268b6d6daaa5a5bb4f752d55964cAngus Kong         * <p>The content varies based on the underlying camera API settings
93201e7c02174ef268b6d6daaa5a5bb4f752d55964cAngus Kong         * implementation.</p>
93301e7c02174ef268b6d6daaa5a5bb4f752d55964cAngus Kong         *
93401e7c02174ef268b6d6daaa5a5bb4f752d55964cAngus Kong         * @return The content of the device settings represented by a string.
93501e7c02174ef268b6d6daaa5a5bb4f752d55964cAngus Kong         */
936a0842b40441db5332a5290f941021636b1182761Sol Boucher        public abstract String dumpDeviceSettings();
937a0842b40441db5332a5290f941021636b1182761Sol Boucher
938a0842b40441db5332a5290f941021636b1182761Sol Boucher        /**
939a0842b40441db5332a5290f941021636b1182761Sol Boucher         * @return The handler to which camera tasks should be posted.
940a0842b40441db5332a5290f941021636b1182761Sol Boucher         */
941a0842b40441db5332a5290f941021636b1182761Sol Boucher        public abstract Handler getCameraHandler();
942a0842b40441db5332a5290f941021636b1182761Sol Boucher
943a0842b40441db5332a5290f941021636b1182761Sol Boucher        /**
944a0842b40441db5332a5290f941021636b1182761Sol Boucher         * @return The thread used on which client callbacks are served.
945a0842b40441db5332a5290f941021636b1182761Sol Boucher         */
946a0842b40441db5332a5290f941021636b1182761Sol Boucher        public abstract DispatchThread getDispatchThread();
947a0842b40441db5332a5290f941021636b1182761Sol Boucher
948a0842b40441db5332a5290f941021636b1182761Sol Boucher        /**
949a0842b40441db5332a5290f941021636b1182761Sol Boucher         * @return The state machine tracking the camera API's current mode.
950a0842b40441db5332a5290f941021636b1182761Sol Boucher         */
951a0842b40441db5332a5290f941021636b1182761Sol Boucher        public abstract CameraStateHolder getCameraState();
952a0842b40441db5332a5290f941021636b1182761Sol Boucher    }
953a0842b40441db5332a5290f941021636b1182761Sol Boucher
954a0842b40441db5332a5290f941021636b1182761Sol Boucher    public static class WaitDoneBundle {
955a0842b40441db5332a5290f941021636b1182761Sol Boucher        public final Runnable mUnlockRunnable;
956a0842b40441db5332a5290f941021636b1182761Sol Boucher        public final Object mWaitLock;
957a0842b40441db5332a5290f941021636b1182761Sol Boucher
958a0842b40441db5332a5290f941021636b1182761Sol Boucher        WaitDoneBundle() {
959a0842b40441db5332a5290f941021636b1182761Sol Boucher            mWaitLock = new Object();
960a0842b40441db5332a5290f941021636b1182761Sol Boucher            mUnlockRunnable = new Runnable() {
961a0842b40441db5332a5290f941021636b1182761Sol Boucher                @Override
962a0842b40441db5332a5290f941021636b1182761Sol Boucher                public void run() {
963a0842b40441db5332a5290f941021636b1182761Sol Boucher                    synchronized (mWaitLock) {
964a0842b40441db5332a5290f941021636b1182761Sol Boucher                        mWaitLock.notifyAll();
965a0842b40441db5332a5290f941021636b1182761Sol Boucher                    }
966a0842b40441db5332a5290f941021636b1182761Sol Boucher                }};
967a0842b40441db5332a5290f941021636b1182761Sol Boucher        }
9686a9babad6eb8ac3e79a5e036d878ed7408e79f26Igor Murashkin
9696a9babad6eb8ac3e79a5e036d878ed7408e79f26Igor Murashkin        /**
9706a9babad6eb8ac3e79a5e036d878ed7408e79f26Igor Murashkin         * Notify all synchronous waiters waiting on message completion with {@link #mWaitLock}.
9716a9babad6eb8ac3e79a5e036d878ed7408e79f26Igor Murashkin         *
9726a9babad6eb8ac3e79a5e036d878ed7408e79f26Igor Murashkin         * <p>This assumes that the message was sent with {@code this} as the {@code Message#obj}.
9736a9babad6eb8ac3e79a5e036d878ed7408e79f26Igor Murashkin         * Otherwise the message is ignored.</p>
9746a9babad6eb8ac3e79a5e036d878ed7408e79f26Igor Murashkin         */
9756a9babad6eb8ac3e79a5e036d878ed7408e79f26Igor Murashkin        /*package*/ static void unblockSyncWaiters(Message msg) {
9766a9babad6eb8ac3e79a5e036d878ed7408e79f26Igor Murashkin            if (msg == null) return;
9776a9babad6eb8ac3e79a5e036d878ed7408e79f26Igor Murashkin
9786a9babad6eb8ac3e79a5e036d878ed7408e79f26Igor Murashkin            if (msg.obj instanceof WaitDoneBundle) {
9796a9babad6eb8ac3e79a5e036d878ed7408e79f26Igor Murashkin                WaitDoneBundle bundle = (WaitDoneBundle)msg.obj;
9806a9babad6eb8ac3e79a5e036d878ed7408e79f26Igor Murashkin                bundle.mUnlockRunnable.run();
9816a9babad6eb8ac3e79a5e036d878ed7408e79f26Igor Murashkin            }
9826a9babad6eb8ac3e79a5e036d878ed7408e79f26Igor Murashkin        }
983bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
984bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong}
985