blob: cc4facb3fd11a842dc10cdf29b80972b8cc1ca83 [file] [log] [blame]
Angus Kong9ef99252013-07-18 18:04:19 -07001/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Angus Kong20fad242013-11-11 18:23:46 -080017package com.android.camera.app;
Angus Kong9ef99252013-07-18 18:04:19 -070018
Angus Kongb50b5cb2013-08-09 14:55:20 -070019import static com.android.camera.util.CameraUtil.Assert;
Angus Kong9ef99252013-07-18 18:04:19 -070020
Sascha Haeberling8e963a52013-08-06 11:43:02 -070021import java.io.IOException;
22
Angus Kong9ef99252013-07-18 18:04:19 -070023import android.annotation.TargetApi;
24import android.graphics.SurfaceTexture;
25import android.hardware.Camera;
26import android.hardware.Camera.AutoFocusCallback;
27import android.hardware.Camera.AutoFocusMoveCallback;
28import android.hardware.Camera.ErrorCallback;
29import android.hardware.Camera.FaceDetectionListener;
30import android.hardware.Camera.OnZoomChangeListener;
31import android.hardware.Camera.Parameters;
32import android.hardware.Camera.PictureCallback;
33import android.hardware.Camera.PreviewCallback;
34import android.hardware.Camera.ShutterCallback;
Sascha Haeberling638e6f02013-09-18 14:28:51 -070035import android.os.Build;
Angus Kong9ef99252013-07-18 18:04:19 -070036import android.os.Handler;
37import android.os.HandlerThread;
38import android.os.Looper;
39import android.os.Message;
40import android.util.Log;
41import android.view.SurfaceHolder;
42
Angus Kong9ef99252013-07-18 18:04:19 -070043/**
44 * A class to implement {@link CameraManager} of the Android camera framework.
45 */
46class AndroidCameraManagerImpl implements CameraManager {
47 private static final String TAG = "CAM_" +
48 AndroidCameraManagerImpl.class.getSimpleName();
49
50 private Parameters mParameters;
51 private boolean mParametersIsDirty;
52 private IOException mReconnectIOException;
53
54 /* Messages used in CameraHandler. */
55 // Camera initialization/finalization
56 private static final int OPEN_CAMERA = 1;
57 private static final int RELEASE = 2;
58 private static final int RECONNECT = 3;
59 private static final int UNLOCK = 4;
60 private static final int LOCK = 5;
Angus Kong20fad242013-11-11 18:23:46 -080061 @Deprecated
62 private static final int OPEN_CAMERA_OLD = 6; // TODO: remove this.
63 @Deprecated
64 private static final int RECONNECT_OLD = 7; // TODO: remove this.
Angus Kong9ef99252013-07-18 18:04:19 -070065 // Preview
66 private static final int SET_PREVIEW_TEXTURE_ASYNC = 101;
67 private static final int START_PREVIEW_ASYNC = 102;
68 private static final int STOP_PREVIEW = 103;
69 private static final int SET_PREVIEW_CALLBACK_WITH_BUFFER = 104;
70 private static final int ADD_CALLBACK_BUFFER = 105;
71 private static final int SET_PREVIEW_DISPLAY_ASYNC = 106;
72 private static final int SET_PREVIEW_CALLBACK = 107;
73 // Parameters
74 private static final int SET_PARAMETERS = 201;
75 private static final int GET_PARAMETERS = 202;
76 private static final int REFRESH_PARAMETERS = 203;
77 // Focus, Zoom
78 private static final int AUTO_FOCUS = 301;
79 private static final int CANCEL_AUTO_FOCUS = 302;
80 private static final int SET_AUTO_FOCUS_MOVE_CALLBACK = 303;
81 private static final int SET_ZOOM_CHANGE_LISTENER = 304;
82 // Face detection
83 private static final int SET_FACE_DETECTION_LISTENER = 461;
84 private static final int START_FACE_DETECTION = 462;
85 private static final int STOP_FACE_DETECTION = 463;
86 private static final int SET_ERROR_CALLBACK = 464;
87 // Presentation
88 private static final int ENABLE_SHUTTER_SOUND = 501;
89 private static final int SET_DISPLAY_ORIENTATION = 502;
90
91 private CameraHandler mCameraHandler;
92 private android.hardware.Camera mCamera;
93
94 // Used to retain a copy of Parameters for setting parameters.
95 private Parameters mParamsToSet;
96
97 AndroidCameraManagerImpl() {
98 HandlerThread ht = new HandlerThread("Camera Handler Thread");
99 ht.start();
100 mCameraHandler = new CameraHandler(ht.getLooper());
101 }
102
103 private class CameraHandler extends Handler {
104 CameraHandler(Looper looper) {
105 super(looper);
106 }
107
Angus Kong9ef99252013-07-18 18:04:19 -0700108 private void startFaceDetection() {
109 mCamera.startFaceDetection();
110 }
111
Angus Kong9ef99252013-07-18 18:04:19 -0700112 private void stopFaceDetection() {
113 mCamera.stopFaceDetection();
114 }
115
Angus Kong9ef99252013-07-18 18:04:19 -0700116 private void setFaceDetectionListener(FaceDetectionListener listener) {
117 mCamera.setFaceDetectionListener(listener);
118 }
119
Angus Kong9ef99252013-07-18 18:04:19 -0700120 private void setPreviewTexture(Object surfaceTexture) {
121 try {
122 mCamera.setPreviewTexture((SurfaceTexture) surfaceTexture);
123 } catch (IOException e) {
Sascha Haeberling464f2202013-10-17 15:29:38 -0700124 Log.e(TAG, "Could not set preview texture", e);
Angus Kong9ef99252013-07-18 18:04:19 -0700125 }
126 }
127
Sascha Haeberling638e6f02013-09-18 14:28:51 -0700128 @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
Angus Kong9ef99252013-07-18 18:04:19 -0700129 private void enableShutterSound(boolean enable) {
130 mCamera.enableShutterSound(enable);
131 }
132
Sascha Haeberling638e6f02013-09-18 14:28:51 -0700133 @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
Angus Kong9ef99252013-07-18 18:04:19 -0700134 private void setAutoFocusMoveCallback(
135 android.hardware.Camera camera, Object cb) {
136 camera.setAutoFocusMoveCallback((AutoFocusMoveCallback) cb);
137 }
138
139 public void requestTakePicture(
140 final ShutterCallback shutter,
141 final PictureCallback raw,
142 final PictureCallback postView,
143 final PictureCallback jpeg) {
144 post(new Runnable() {
145 @Override
146 public void run() {
147 try {
148 mCamera.takePicture(shutter, raw, postView, jpeg);
149 } catch (RuntimeException e) {
150 // TODO: output camera state and focus state for debugging.
151 Log.e(TAG, "take picture failed.");
152 throw e;
153 }
154 }
155 });
156 }
157
158 /**
159 * Waits for all the {@code Message} and {@code Runnable} currently in the queue
160 * are processed.
161 *
162 * @return {@code false} if the wait was interrupted, {@code true} otherwise.
163 */
164 public boolean waitDone() {
165 final Object waitDoneLock = new Object();
166 final Runnable unlockRunnable = new Runnable() {
167 @Override
168 public void run() {
169 synchronized (waitDoneLock) {
170 waitDoneLock.notifyAll();
171 }
172 }
173 };
174
175 synchronized (waitDoneLock) {
176 mCameraHandler.post(unlockRunnable);
177 try {
178 waitDoneLock.wait();
179 } catch (InterruptedException ex) {
180 Log.v(TAG, "waitDone interrupted");
181 return false;
182 }
183 }
184 return true;
185 }
186
187 /**
188 * This method does not deal with the API level check. Everyone should
189 * check first for supported operations before sending message to this handler.
190 */
191 @Override
192 public void handleMessage(final Message msg) {
193 try {
194 switch (msg.what) {
Angus Kong20fad242013-11-11 18:23:46 -0800195 case OPEN_CAMERA: {
196 final CameraOpenCallback openCallback = (CameraOpenCallback) msg.obj;
197 final int cameraId = msg.arg1;
198 mCamera = android.hardware.Camera.open(cameraId);
199 if (mCamera != null) {
200 mParametersIsDirty = true;
201
202 // Get a instance of Camera.Parameters for later use.
203 if (mParamsToSet == null) {
204 mParamsToSet = mCamera.getParameters();
205 }
206
207 if (openCallback != null) {
208 openCallback.onCameraOpened(new AndroidCameraProxyImpl(cameraId));
209 }
210 } else {
211 if (openCallback != null) {
212 openCallback.onDeviceOpenFailure(cameraId);
213 }
214 }
215 return;
216 }
217
218 case OPEN_CAMERA_OLD: {
Angus Kong6d29a642013-07-31 12:46:54 -0700219 mCamera = android.hardware.Camera.open(msg.arg1);
Angus Kong9ef99252013-07-18 18:04:19 -0700220 if (mCamera != null) {
221 mParametersIsDirty = true;
222
223 // Get a instance of Camera.Parameters for later use.
224 if (mParamsToSet == null) {
225 mParamsToSet = mCamera.getParameters();
226 }
Angus Kong4f795b82013-09-16 14:25:35 -0700227 } else {
228 if (msg.obj != null) {
Angus Kong62848152013-11-08 17:25:29 -0800229 ((CameraOpenCallback) msg.obj).onDeviceOpenFailure(msg.arg1);
Angus Kong4f795b82013-09-16 14:25:35 -0700230 }
Angus Kong9ef99252013-07-18 18:04:19 -0700231 }
232 return;
Angus Kong20fad242013-11-11 18:23:46 -0800233 }
Angus Kong9ef99252013-07-18 18:04:19 -0700234
Angus Kong20fad242013-11-11 18:23:46 -0800235 case RELEASE: {
Angus Kong9ef99252013-07-18 18:04:19 -0700236 mCamera.release();
237 mCamera = null;
238 return;
Angus Kong20fad242013-11-11 18:23:46 -0800239 }
Angus Kong9ef99252013-07-18 18:04:19 -0700240
Angus Kong20fad242013-11-11 18:23:46 -0800241 case RECONNECT: {
242 final CameraOpenCallbackForward cbForward =
243 (CameraOpenCallbackForward) msg.obj;
244 final int cameraId = msg.arg1;
245 try {
246 mCamera.reconnect();
247 } catch (IOException ex) {
248 if (cbForward != null) {
249 cbForward.onReconnectionFailure(AndroidCameraManagerImpl.this);
250 }
251 return;
252 }
253
254 if (cbForward != null) {
255 cbForward.onCameraOpened(new AndroidCameraProxyImpl(cameraId));
256 }
257 return;
258 }
259
260 case RECONNECT_OLD: {
Angus Kong9ef99252013-07-18 18:04:19 -0700261 mReconnectIOException = null;
262 try {
263 mCamera.reconnect();
264 } catch (IOException ex) {
265 mReconnectIOException = ex;
266 }
267 return;
Angus Kong20fad242013-11-11 18:23:46 -0800268 }
Angus Kong9ef99252013-07-18 18:04:19 -0700269
Angus Kong20fad242013-11-11 18:23:46 -0800270 case UNLOCK: {
Angus Kong9ef99252013-07-18 18:04:19 -0700271 mCamera.unlock();
272 return;
Angus Kong20fad242013-11-11 18:23:46 -0800273 }
Angus Kong9ef99252013-07-18 18:04:19 -0700274
Angus Kong20fad242013-11-11 18:23:46 -0800275 case LOCK: {
Angus Kong9ef99252013-07-18 18:04:19 -0700276 mCamera.lock();
277 return;
Angus Kong20fad242013-11-11 18:23:46 -0800278 }
Angus Kong9ef99252013-07-18 18:04:19 -0700279
Angus Kong20fad242013-11-11 18:23:46 -0800280 case SET_PREVIEW_TEXTURE_ASYNC: {
Angus Kong9ef99252013-07-18 18:04:19 -0700281 setPreviewTexture(msg.obj);
282 return;
Angus Kong20fad242013-11-11 18:23:46 -0800283 }
Angus Kong9ef99252013-07-18 18:04:19 -0700284
Angus Kong20fad242013-11-11 18:23:46 -0800285 case SET_PREVIEW_DISPLAY_ASYNC: {
Angus Kong9ef99252013-07-18 18:04:19 -0700286 try {
287 mCamera.setPreviewDisplay((SurfaceHolder) msg.obj);
288 } catch (IOException e) {
289 throw new RuntimeException(e);
290 }
291 return;
Angus Kong20fad242013-11-11 18:23:46 -0800292 }
Angus Kong9ef99252013-07-18 18:04:19 -0700293
Angus Kong20fad242013-11-11 18:23:46 -0800294 case START_PREVIEW_ASYNC: {
Angus Kong9ef99252013-07-18 18:04:19 -0700295 mCamera.startPreview();
296 return;
Angus Kong20fad242013-11-11 18:23:46 -0800297 }
Angus Kong9ef99252013-07-18 18:04:19 -0700298
Angus Kong20fad242013-11-11 18:23:46 -0800299 case STOP_PREVIEW: {
Angus Kong9ef99252013-07-18 18:04:19 -0700300 mCamera.stopPreview();
301 return;
Angus Kong20fad242013-11-11 18:23:46 -0800302 }
Angus Kong9ef99252013-07-18 18:04:19 -0700303
Angus Kong20fad242013-11-11 18:23:46 -0800304 case SET_PREVIEW_CALLBACK_WITH_BUFFER: {
Angus Kong9ef99252013-07-18 18:04:19 -0700305 mCamera.setPreviewCallbackWithBuffer(
306 (PreviewCallback) msg.obj);
307 return;
Angus Kong20fad242013-11-11 18:23:46 -0800308 }
Angus Kong9ef99252013-07-18 18:04:19 -0700309
Angus Kong20fad242013-11-11 18:23:46 -0800310 case ADD_CALLBACK_BUFFER: {
Angus Kong9ef99252013-07-18 18:04:19 -0700311 mCamera.addCallbackBuffer((byte[]) msg.obj);
312 return;
Angus Kong20fad242013-11-11 18:23:46 -0800313 }
Angus Kong9ef99252013-07-18 18:04:19 -0700314
Angus Kong20fad242013-11-11 18:23:46 -0800315 case AUTO_FOCUS: {
Angus Kong9ef99252013-07-18 18:04:19 -0700316 mCamera.autoFocus((AutoFocusCallback) msg.obj);
317 return;
Angus Kong20fad242013-11-11 18:23:46 -0800318 }
Angus Kong9ef99252013-07-18 18:04:19 -0700319
Angus Kong20fad242013-11-11 18:23:46 -0800320 case CANCEL_AUTO_FOCUS: {
Angus Kong9ef99252013-07-18 18:04:19 -0700321 mCamera.cancelAutoFocus();
322 return;
Angus Kong20fad242013-11-11 18:23:46 -0800323 }
Angus Kong9ef99252013-07-18 18:04:19 -0700324
Angus Kong20fad242013-11-11 18:23:46 -0800325 case SET_AUTO_FOCUS_MOVE_CALLBACK: {
Angus Kong9ef99252013-07-18 18:04:19 -0700326 setAutoFocusMoveCallback(mCamera, msg.obj);
327 return;
Angus Kong20fad242013-11-11 18:23:46 -0800328 }
Angus Kong9ef99252013-07-18 18:04:19 -0700329
Angus Kong20fad242013-11-11 18:23:46 -0800330 case SET_DISPLAY_ORIENTATION: {
Angus Kong9ef99252013-07-18 18:04:19 -0700331 mCamera.setDisplayOrientation(msg.arg1);
332 return;
Angus Kong20fad242013-11-11 18:23:46 -0800333 }
Angus Kong9ef99252013-07-18 18:04:19 -0700334
Angus Kong20fad242013-11-11 18:23:46 -0800335 case SET_ZOOM_CHANGE_LISTENER: {
Angus Kong9ef99252013-07-18 18:04:19 -0700336 mCamera.setZoomChangeListener(
337 (OnZoomChangeListener) msg.obj);
338 return;
Angus Kong20fad242013-11-11 18:23:46 -0800339 }
Angus Kong9ef99252013-07-18 18:04:19 -0700340
Angus Kong20fad242013-11-11 18:23:46 -0800341 case SET_FACE_DETECTION_LISTENER: {
Angus Kong9ef99252013-07-18 18:04:19 -0700342 setFaceDetectionListener((FaceDetectionListener) msg.obj);
343 return;
Angus Kong20fad242013-11-11 18:23:46 -0800344 }
Angus Kong9ef99252013-07-18 18:04:19 -0700345
Angus Kong20fad242013-11-11 18:23:46 -0800346 case START_FACE_DETECTION: {
Angus Kong9ef99252013-07-18 18:04:19 -0700347 startFaceDetection();
348 return;
Angus Kong20fad242013-11-11 18:23:46 -0800349 }
Angus Kong9ef99252013-07-18 18:04:19 -0700350
Angus Kong20fad242013-11-11 18:23:46 -0800351 case STOP_FACE_DETECTION: {
Angus Kong9ef99252013-07-18 18:04:19 -0700352 stopFaceDetection();
353 return;
Angus Kong20fad242013-11-11 18:23:46 -0800354 }
Angus Kong9ef99252013-07-18 18:04:19 -0700355
Angus Kong20fad242013-11-11 18:23:46 -0800356 case SET_ERROR_CALLBACK: {
Angus Kong9ef99252013-07-18 18:04:19 -0700357 mCamera.setErrorCallback((ErrorCallback) msg.obj);
358 return;
Angus Kong20fad242013-11-11 18:23:46 -0800359 }
Angus Kong9ef99252013-07-18 18:04:19 -0700360
Angus Kong20fad242013-11-11 18:23:46 -0800361 case SET_PARAMETERS: {
Angus Kong9ef99252013-07-18 18:04:19 -0700362 mParametersIsDirty = true;
363 mParamsToSet.unflatten((String) msg.obj);
364 mCamera.setParameters(mParamsToSet);
365 return;
Angus Kong20fad242013-11-11 18:23:46 -0800366 }
Angus Kong9ef99252013-07-18 18:04:19 -0700367
Angus Kong20fad242013-11-11 18:23:46 -0800368 case GET_PARAMETERS: {
Angus Kong9ef99252013-07-18 18:04:19 -0700369 if (mParametersIsDirty) {
370 mParameters = mCamera.getParameters();
371 mParametersIsDirty = false;
372 }
373 return;
Angus Kong20fad242013-11-11 18:23:46 -0800374 }
Angus Kong9ef99252013-07-18 18:04:19 -0700375
Angus Kong20fad242013-11-11 18:23:46 -0800376 case SET_PREVIEW_CALLBACK: {
Angus Kong9ef99252013-07-18 18:04:19 -0700377 mCamera.setPreviewCallback((PreviewCallback) msg.obj);
378 return;
Angus Kong20fad242013-11-11 18:23:46 -0800379 }
Angus Kong9ef99252013-07-18 18:04:19 -0700380
Angus Kong20fad242013-11-11 18:23:46 -0800381 case ENABLE_SHUTTER_SOUND: {
Angus Kong9ef99252013-07-18 18:04:19 -0700382 enableShutterSound((msg.arg1 == 1) ? true : false);
383 return;
Angus Kong20fad242013-11-11 18:23:46 -0800384 }
Angus Kong9ef99252013-07-18 18:04:19 -0700385
Angus Kong20fad242013-11-11 18:23:46 -0800386 case REFRESH_PARAMETERS: {
Angus Kong9ef99252013-07-18 18:04:19 -0700387 mParametersIsDirty = true;
388 return;
Angus Kong20fad242013-11-11 18:23:46 -0800389 }
Angus Kong9ef99252013-07-18 18:04:19 -0700390
Angus Kong20fad242013-11-11 18:23:46 -0800391 default: {
Angus Kong9ef99252013-07-18 18:04:19 -0700392 throw new RuntimeException("Invalid CameraProxy message=" + msg.what);
Angus Kong20fad242013-11-11 18:23:46 -0800393 }
Angus Kong9ef99252013-07-18 18:04:19 -0700394 }
395 } catch (RuntimeException e) {
396 if (msg.what != RELEASE && mCamera != null) {
397 try {
398 mCamera.release();
399 } catch (Exception ex) {
400 Log.e(TAG, "Fail to release the camera.");
401 }
402 mCamera = null;
Sascha Haeberling02db77f2013-09-17 15:36:13 -0700403 } else if (mCamera == null) {
ztenghuicfc148d2013-10-28 15:27:02 -0700404 if (msg.what == OPEN_CAMERA) {
405 if (msg.obj != null) {
Angus Kong62848152013-11-08 17:25:29 -0800406 ((CameraOpenCallback) msg.obj).onDeviceOpenFailure(msg.arg1);
ztenghuicfc148d2013-10-28 15:27:02 -0700407 }
408 } else {
409 Log.w(TAG, "Cannot handle message, mCamera is null.");
410 }
411 return;
Angus Kong9ef99252013-07-18 18:04:19 -0700412 }
413 throw e;
414 }
415 }
416 }
417
418 @Override
Angus Kong20fad242013-11-11 18:23:46 -0800419 public void cameraOpen(Handler handler, int cameraId, CameraOpenCallback callback) {
Angus Kong4f795b82013-09-16 14:25:35 -0700420 mCameraHandler.obtainMessage(OPEN_CAMERA, cameraId, 0,
Angus Kong62848152013-11-08 17:25:29 -0800421 CameraOpenCallbackForward.getNewInstance(handler, callback)).sendToTarget();
Angus Kong20fad242013-11-11 18:23:46 -0800422 }
423
424 @Override
425 public CameraProxy cameraOpenOld(Handler handler, int cameraId, CameraOpenCallback callback) {
426 mCameraHandler.obtainMessage(OPEN_CAMERA_OLD, cameraId, 0,
427 CameraOpenCallbackForward.getNewInstance(handler, callback)).sendToTarget();
Angus Kong9ef99252013-07-18 18:04:19 -0700428 mCameraHandler.waitDone();
429 if (mCamera != null) {
Angus Kong20fad242013-11-11 18:23:46 -0800430 return new AndroidCameraProxyImpl(cameraId);
Angus Kong9ef99252013-07-18 18:04:19 -0700431 } else {
432 return null;
433 }
434 }
435
436 /**
Angus Kong4f795b82013-09-16 14:25:35 -0700437 * A class which implements {@link CameraManager.CameraProxy} and
Angus Kong9ef99252013-07-18 18:04:19 -0700438 * camera handler thread.
Angus Kong4f795b82013-09-16 14:25:35 -0700439 * TODO: Save the handler for the callback here to avoid passing the same
440 * handler multiple times.
Angus Kong9ef99252013-07-18 18:04:19 -0700441 */
442 public class AndroidCameraProxyImpl implements CameraManager.CameraProxy {
Angus Kong20fad242013-11-11 18:23:46 -0800443 private final int mCameraId;
Angus Kong9ef99252013-07-18 18:04:19 -0700444
Angus Kong20fad242013-11-11 18:23:46 -0800445 private AndroidCameraProxyImpl(int cameraId) {
Angus Kong9ef99252013-07-18 18:04:19 -0700446 Assert(mCamera != null);
Angus Kong20fad242013-11-11 18:23:46 -0800447 mCameraId = cameraId;
Angus Kong9ef99252013-07-18 18:04:19 -0700448 }
449
450 @Override
451 public android.hardware.Camera getCamera() {
452 return mCamera;
453 }
454
455 @Override
Angus Kong20fad242013-11-11 18:23:46 -0800456 public int getCameraId() {
457 return mCameraId;
458 }
459
460 // TODO: Make this package private.
461 @Override
462 public void release(boolean sync) {
463 Log.v("DEBUG", "camera manager release");
464 mCameraHandler.removeCallbacksAndMessages(null);
Angus Kong9ef99252013-07-18 18:04:19 -0700465 mCameraHandler.sendEmptyMessage(RELEASE);
Angus Kong20fad242013-11-11 18:23:46 -0800466 if (sync) {
467 mCameraHandler.waitDone();
468 }
Angus Kong9ef99252013-07-18 18:04:19 -0700469 }
470
471 @Override
Angus Kong20fad242013-11-11 18:23:46 -0800472 public void reconnect(Handler handler, CameraOpenCallback cb) {
473 mCameraHandler.obtainMessage(RECONNECT, mCameraId, 0,
474 CameraOpenCallbackForward.getNewInstance(handler, cb)).sendToTarget();
475 }
476
477 @Override
478 public boolean reconnectOld(Handler handler, CameraOpenCallback cb) {
479 mCameraHandler.sendEmptyMessage(RECONNECT_OLD);
Angus Kong9ef99252013-07-18 18:04:19 -0700480 mCameraHandler.waitDone();
Angus Kong62848152013-11-08 17:25:29 -0800481 CameraOpenCallback cbforward =
482 CameraOpenCallbackForward.getNewInstance(handler, cb);
Angus Kong9ef99252013-07-18 18:04:19 -0700483 if (mReconnectIOException != null) {
Angus Kong4f795b82013-09-16 14:25:35 -0700484 if (cbforward != null) {
485 cbforward.onReconnectionFailure(AndroidCameraManagerImpl.this);
Angus Kong20fad242013-11-11 18:23:46 -0800486 }
Angus Kong4f795b82013-09-16 14:25:35 -0700487 return false;
Angus Kong20fad242013-11-11 18:23:46 -0800488 }
Angus Kong4f795b82013-09-16 14:25:35 -0700489 return true;
Angus Kong9ef99252013-07-18 18:04:19 -0700490 }
491
492 @Override
493 public void unlock() {
494 mCameraHandler.sendEmptyMessage(UNLOCK);
495 mCameraHandler.waitDone();
496 }
497
498 @Override
499 public void lock() {
500 mCameraHandler.sendEmptyMessage(LOCK);
501 }
502
Angus Kong9ef99252013-07-18 18:04:19 -0700503 @Override
Angus Kong9e765522013-07-31 14:05:20 -0700504 public void setPreviewTexture(SurfaceTexture surfaceTexture) {
Angus Kong9ef99252013-07-18 18:04:19 -0700505 mCameraHandler.obtainMessage(SET_PREVIEW_TEXTURE_ASYNC, surfaceTexture).sendToTarget();
506 }
507
508 @Override
Angus Kong9e765522013-07-31 14:05:20 -0700509 public void setPreviewDisplay(SurfaceHolder surfaceHolder) {
Angus Kong9ef99252013-07-18 18:04:19 -0700510 mCameraHandler.obtainMessage(SET_PREVIEW_DISPLAY_ASYNC, surfaceHolder).sendToTarget();
511 }
512
513 @Override
514 public void startPreview() {
515 mCameraHandler.sendEmptyMessage(START_PREVIEW_ASYNC);
516 }
517
518 @Override
519 public void stopPreview() {
520 mCameraHandler.sendEmptyMessage(STOP_PREVIEW);
521 mCameraHandler.waitDone();
522 }
523
524 @Override
525 public void setPreviewDataCallback(
Angus Kong9e765522013-07-31 14:05:20 -0700526 Handler handler, CameraPreviewDataCallback cb) {
Angus Kong9ef99252013-07-18 18:04:19 -0700527 mCameraHandler.obtainMessage(
528 SET_PREVIEW_CALLBACK,
Angus Kong9e765522013-07-31 14:05:20 -0700529 PreviewCallbackForward.getNewInstance(handler, this, cb)).sendToTarget();
Angus Kong9ef99252013-07-18 18:04:19 -0700530 }
531
532 @Override
533 public void setPreviewDataCallbackWithBuffer(
Angus Kong9e765522013-07-31 14:05:20 -0700534 Handler handler, CameraPreviewDataCallback cb) {
Angus Kong9ef99252013-07-18 18:04:19 -0700535 mCameraHandler.obtainMessage(
536 SET_PREVIEW_CALLBACK_WITH_BUFFER,
Angus Kong9e765522013-07-31 14:05:20 -0700537 PreviewCallbackForward.getNewInstance(handler, this, cb)).sendToTarget();
Angus Kong9ef99252013-07-18 18:04:19 -0700538 }
539
540 @Override
541 public void addCallbackBuffer(byte[] callbackBuffer) {
542 mCameraHandler.obtainMessage(ADD_CALLBACK_BUFFER, callbackBuffer).sendToTarget();
543 }
544
545 @Override
546 public void autoFocus(Handler handler, CameraAFCallback cb) {
547 mCameraHandler.obtainMessage(
548 AUTO_FOCUS,
Angus Kong9e765522013-07-31 14:05:20 -0700549 AFCallbackForward.getNewInstance(handler, this, cb)).sendToTarget();
Angus Kong9ef99252013-07-18 18:04:19 -0700550 }
551
552 @Override
553 public void cancelAutoFocus() {
554 mCameraHandler.removeMessages(AUTO_FOCUS);
555 mCameraHandler.sendEmptyMessage(CANCEL_AUTO_FOCUS);
556 }
557
Sascha Haeberling638e6f02013-09-18 14:28:51 -0700558 @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
Angus Kong9ef99252013-07-18 18:04:19 -0700559 @Override
560 public void setAutoFocusMoveCallback(
Angus Kong9e765522013-07-31 14:05:20 -0700561 Handler handler, CameraAFMoveCallback cb) {
Angus Kong9ef99252013-07-18 18:04:19 -0700562 mCameraHandler.obtainMessage(
563 SET_AUTO_FOCUS_MOVE_CALLBACK,
Angus Kong9e765522013-07-31 14:05:20 -0700564 AFMoveCallbackForward.getNewInstance(handler, this, cb)).sendToTarget();
Angus Kong9ef99252013-07-18 18:04:19 -0700565 }
566
567 @Override
568 public void takePicture(
Angus Kong9e765522013-07-31 14:05:20 -0700569 Handler handler,
570 CameraShutterCallback shutter,
571 CameraPictureCallback raw,
572 CameraPictureCallback post,
573 CameraPictureCallback jpeg) {
Angus Kong9ef99252013-07-18 18:04:19 -0700574 mCameraHandler.requestTakePicture(
Angus Kong9e765522013-07-31 14:05:20 -0700575 ShutterCallbackForward.getNewInstance(handler, this, shutter),
576 PictureCallbackForward.getNewInstance(handler, this, raw),
577 PictureCallbackForward.getNewInstance(handler, this, post),
578 PictureCallbackForward.getNewInstance(handler, this, jpeg));
Angus Kong9ef99252013-07-18 18:04:19 -0700579 }
580
581 @Override
582 public void setDisplayOrientation(int degrees) {
583 mCameraHandler.obtainMessage(SET_DISPLAY_ORIENTATION, degrees, 0)
584 .sendToTarget();
585 }
586
587 @Override
588 public void setZoomChangeListener(OnZoomChangeListener listener) {
589 mCameraHandler.obtainMessage(SET_ZOOM_CHANGE_LISTENER, listener).sendToTarget();
590 }
591
Angus Kong9e765522013-07-31 14:05:20 -0700592 public void setFaceDetectionCallback(
593 Handler handler, CameraFaceDetectionCallback cb) {
594 mCameraHandler.obtainMessage(
595 SET_FACE_DETECTION_LISTENER,
596 FaceDetectionCallbackForward.getNewInstance(handler, this, cb)).sendToTarget();
Angus Kong9ef99252013-07-18 18:04:19 -0700597 }
598
599 @Override
600 public void startFaceDetection() {
601 mCameraHandler.sendEmptyMessage(START_FACE_DETECTION);
602 }
603
604 @Override
605 public void stopFaceDetection() {
606 mCameraHandler.sendEmptyMessage(STOP_FACE_DETECTION);
607 }
608
609 @Override
610 public void setErrorCallback(ErrorCallback cb) {
611 mCameraHandler.obtainMessage(SET_ERROR_CALLBACK, cb).sendToTarget();
612 }
613
614 @Override
615 public void setParameters(Parameters params) {
616 if (params == null) {
617 Log.v(TAG, "null parameters in setParameters()");
618 return;
619 }
620 mCameraHandler.obtainMessage(SET_PARAMETERS, params.flatten())
621 .sendToTarget();
622 }
623
624 @Override
625 public Parameters getParameters() {
626 mCameraHandler.sendEmptyMessage(GET_PARAMETERS);
627 mCameraHandler.waitDone();
628 return mParameters;
629 }
630
631 @Override
632 public void refreshParameters() {
633 mCameraHandler.sendEmptyMessage(REFRESH_PARAMETERS);
634 }
635
636 @Override
637 public void enableShutterSound(boolean enable) {
638 mCameraHandler.obtainMessage(
639 ENABLE_SHUTTER_SOUND, (enable ? 1 : 0), 0).sendToTarget();
640 }
641 }
642
643 /**
644 * A helper class to forward AutoFocusCallback to another thread.
645 */
646 private static class AFCallbackForward implements AutoFocusCallback {
647 private final Handler mHandler;
648 private final CameraProxy mCamera;
649 private final CameraAFCallback mCallback;
650
651 /**
Angus Kong9e765522013-07-31 14:05:20 -0700652 * Returns a new instance of {@link AFCallbackForward}.
Angus Kong9ef99252013-07-18 18:04:19 -0700653 *
654 * @param handler The handler in which the callback will be invoked in.
655 * @param camera The {@link CameraProxy} which the callback is from.
656 * @param cb The callback to be invoked.
657 * @return The instance of the {@link AFCallbackForward},
Angus Kong9e765522013-07-31 14:05:20 -0700658 * or null if any parameter is null.
Angus Kong9ef99252013-07-18 18:04:19 -0700659 */
Angus Kong9e765522013-07-31 14:05:20 -0700660 public static AFCallbackForward getNewInstance(
Angus Kong9ef99252013-07-18 18:04:19 -0700661 Handler handler, CameraProxy camera, CameraAFCallback cb) {
662 if (handler == null || camera == null || cb == null) return null;
663 return new AFCallbackForward(handler, camera, cb);
664 }
665
666 private AFCallbackForward(
667 Handler h, CameraProxy camera, CameraAFCallback cb) {
668 mHandler = h;
669 mCamera = camera;
670 mCallback = cb;
671 }
672
673 @Override
674 public void onAutoFocus(final boolean b, Camera camera) {
675 mHandler.post(new Runnable() {
676 @Override
677 public void run() {
678 mCallback.onAutoFocus(b, mCamera);
679 }
680 });
681 }
682 }
683
684 /** A helper class to forward AutoFocusMoveCallback to another thread. */
Sascha Haeberling638e6f02013-09-18 14:28:51 -0700685 @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
Angus Kong9ef99252013-07-18 18:04:19 -0700686 private static class AFMoveCallbackForward implements AutoFocusMoveCallback {
687 private final Handler mHandler;
688 private final CameraAFMoveCallback mCallback;
689 private final CameraProxy mCamera;
690
691 /**
Angus Kong9e765522013-07-31 14:05:20 -0700692 * Returns a new instance of {@link AFMoveCallbackForward}.
Angus Kong9ef99252013-07-18 18:04:19 -0700693 *
694 * @param handler The handler in which the callback will be invoked in.
695 * @param camera The {@link CameraProxy} which the callback is from.
696 * @param cb The callback to be invoked.
697 * @return The instance of the {@link AFMoveCallbackForward},
Angus Kong9e765522013-07-31 14:05:20 -0700698 * or null if any parameter is null.
Angus Kong9ef99252013-07-18 18:04:19 -0700699 */
Angus Kong9e765522013-07-31 14:05:20 -0700700 public static AFMoveCallbackForward getNewInstance(
Angus Kong9ef99252013-07-18 18:04:19 -0700701 Handler handler, CameraProxy camera, CameraAFMoveCallback cb) {
702 if (handler == null || camera == null || cb == null) return null;
703 return new AFMoveCallbackForward(handler, camera, cb);
704 }
705
706 private AFMoveCallbackForward(
707 Handler h, CameraProxy camera, CameraAFMoveCallback cb) {
708 mHandler = h;
709 mCamera = camera;
710 mCallback = cb;
711 }
712
713 @Override
714 public void onAutoFocusMoving(
715 final boolean moving, android.hardware.Camera camera) {
716 mHandler.post(new Runnable() {
717 @Override
718 public void run() {
719 mCallback.onAutoFocusMoving(moving, mCamera);
720 }
721 });
722 }
723 }
724
725 /**
726 * A helper class to forward ShutterCallback to to another thread.
727 */
728 private static class ShutterCallbackForward implements ShutterCallback {
729 private final Handler mHandler;
730 private final CameraShutterCallback mCallback;
731 private final CameraProxy mCamera;
732
733 /**
Angus Kong9e765522013-07-31 14:05:20 -0700734 * Returns a new instance of {@link ShutterCallbackForward}.
Angus Kong9ef99252013-07-18 18:04:19 -0700735 *
736 * @param handler The handler in which the callback will be invoked in.
737 * @param camera The {@link CameraProxy} which the callback is from.
738 * @param cb The callback to be invoked.
739 * @return The instance of the {@link ShutterCallbackForward},
Angus Kong9e765522013-07-31 14:05:20 -0700740 * or null if any parameter is null.
Angus Kong9ef99252013-07-18 18:04:19 -0700741 */
Angus Kong9e765522013-07-31 14:05:20 -0700742 public static ShutterCallbackForward getNewInstance(
Angus Kong9ef99252013-07-18 18:04:19 -0700743 Handler handler, CameraProxy camera, CameraShutterCallback cb) {
744 if (handler == null || camera == null || cb == null) return null;
745 return new ShutterCallbackForward(handler, camera, cb);
746 }
747
748 private ShutterCallbackForward(
749 Handler h, CameraProxy camera, CameraShutterCallback cb) {
750 mHandler = h;
751 mCamera = camera;
752 mCallback = cb;
753 }
754
755 @Override
756 public void onShutter() {
757 mHandler.post(new Runnable() {
758 @Override
759 public void run() {
760 mCallback.onShutter(mCamera);
761 }
762 });
763 }
764 }
765
766 /**
767 * A helper class to forward PictureCallback to another thread.
768 */
769 private static class PictureCallbackForward implements PictureCallback {
770 private final Handler mHandler;
771 private final CameraPictureCallback mCallback;
772 private final CameraProxy mCamera;
773
774 /**
Angus Kong9e765522013-07-31 14:05:20 -0700775 * Returns a new instance of {@link PictureCallbackForward}.
Angus Kong9ef99252013-07-18 18:04:19 -0700776 *
777 * @param handler The handler in which the callback will be invoked in.
778 * @param camera The {@link CameraProxy} which the callback is from.
779 * @param cb The callback to be invoked.
780 * @return The instance of the {@link PictureCallbackForward},
Angus Kong9e765522013-07-31 14:05:20 -0700781 * or null if any parameters is null.
Angus Kong9ef99252013-07-18 18:04:19 -0700782 */
Angus Kong9e765522013-07-31 14:05:20 -0700783 public static PictureCallbackForward getNewInstance(
Angus Kong9ef99252013-07-18 18:04:19 -0700784 Handler handler, CameraProxy camera, CameraPictureCallback cb) {
785 if (handler == null || camera == null || cb == null) return null;
786 return new PictureCallbackForward(handler, camera, cb);
787 }
788
789 private PictureCallbackForward(
790 Handler h, CameraProxy camera, CameraPictureCallback cb) {
791 mHandler = h;
792 mCamera = camera;
793 mCallback = cb;
794 }
795
796 @Override
797 public void onPictureTaken(
798 final byte[] data, android.hardware.Camera camera) {
799 mHandler.post(new Runnable() {
800 @Override
801 public void run() {
802 mCallback.onPictureTaken(data, mCamera);
803 }
804 });
805 }
806 }
807
808 /**
809 * A helper class to forward PreviewCallback to another thread.
810 */
811 private static class PreviewCallbackForward implements PreviewCallback {
812 private final Handler mHandler;
813 private final CameraPreviewDataCallback mCallback;
814 private final CameraProxy mCamera;
815
816 /**
Angus Kong9e765522013-07-31 14:05:20 -0700817 * Returns a new instance of {@link PreviewCallbackForward}.
Angus Kong9ef99252013-07-18 18:04:19 -0700818 *
819 * @param handler The handler in which the callback will be invoked in.
820 * @param camera The {@link CameraProxy} which the callback is from.
821 * @param cb The callback to be invoked.
Angus Kong9e765522013-07-31 14:05:20 -0700822 * @return The instance of the {@link PreviewCallbackForward},
823 * or null if any parameters is null.
Angus Kong9ef99252013-07-18 18:04:19 -0700824 */
Angus Kong9e765522013-07-31 14:05:20 -0700825 public static PreviewCallbackForward getNewInstance(
Angus Kong9ef99252013-07-18 18:04:19 -0700826 Handler handler, CameraProxy camera, CameraPreviewDataCallback cb) {
827 if (handler == null || camera == null || cb == null) return null;
828 return new PreviewCallbackForward(handler, camera, cb);
829 }
830
831 private PreviewCallbackForward(
832 Handler h, CameraProxy camera, CameraPreviewDataCallback cb) {
833 mHandler = h;
834 mCamera = camera;
835 mCallback = cb;
836 }
837
838 @Override
839 public void onPreviewFrame(
840 final byte[] data, android.hardware.Camera camera) {
841 mHandler.post(new Runnable() {
842 @Override
843 public void run() {
844 mCallback.onPreviewFrame(data, mCamera);
845 }
846 });
847 }
848 }
Angus Kong9e765522013-07-31 14:05:20 -0700849
850 private static class FaceDetectionCallbackForward implements FaceDetectionListener {
851 private final Handler mHandler;
852 private final CameraFaceDetectionCallback mCallback;
853 private final CameraProxy mCamera;
854
855 /**
856 * Returns a new instance of {@link FaceDetectionCallbackForward}.
857 *
858 * @param handler The handler in which the callback will be invoked in.
859 * @param camera The {@link CameraProxy} which the callback is from.
860 * @param cb The callback to be invoked.
861 * @return The instance of the {@link FaceDetectionCallbackForward},
862 * or null if any parameter is null.
863 */
864 public static FaceDetectionCallbackForward getNewInstance(
865 Handler handler, CameraProxy camera, CameraFaceDetectionCallback cb) {
866 if (handler == null || camera == null || cb == null) return null;
867 return new FaceDetectionCallbackForward(handler, camera, cb);
868 }
869
870 private FaceDetectionCallbackForward(
871 Handler h, CameraProxy camera, CameraFaceDetectionCallback cb) {
872 mHandler = h;
873 mCamera = camera;
874 mCallback = cb;
875 }
876
877 @Override
878 public void onFaceDetection(
879 final Camera.Face[] faces, Camera camera) {
880 mHandler.post(new Runnable() {
881 @Override
882 public void run() {
883 mCallback.onFaceDetection(faces, mCamera);
884 }
885 });
886 }
887 }
Angus Kong4f795b82013-09-16 14:25:35 -0700888
889 /**
890 * A callback helps to invoke the original callback on another
891 * {@link android.os.Handler}.
892 */
Angus Kong62848152013-11-08 17:25:29 -0800893 private static class CameraOpenCallbackForward implements CameraOpenCallback {
Angus Kong4f795b82013-09-16 14:25:35 -0700894 private final Handler mHandler;
Angus Kong62848152013-11-08 17:25:29 -0800895 private final CameraOpenCallback mCallback;
Angus Kong4f795b82013-09-16 14:25:35 -0700896
897 /**
898 * Returns a new instance of {@link FaceDetectionCallbackForward}.
899 *
900 * @param handler The handler in which the callback will be invoked in.
901 * @param cb The callback to be invoked.
902 * @return The instance of the {@link FaceDetectionCallbackForward}, or
903 * null if any parameter is null.
904 */
Angus Kong62848152013-11-08 17:25:29 -0800905 public static CameraOpenCallbackForward getNewInstance(
906 Handler handler, CameraOpenCallback cb) {
Angus Kong4f795b82013-09-16 14:25:35 -0700907 if (handler == null || cb == null) {
908 return null;
909 }
Angus Kong62848152013-11-08 17:25:29 -0800910 return new CameraOpenCallbackForward(handler, cb);
Angus Kong4f795b82013-09-16 14:25:35 -0700911 }
912
Angus Kong62848152013-11-08 17:25:29 -0800913 private CameraOpenCallbackForward(Handler h, CameraOpenCallback cb) {
ztenghuie1aa59b2013-10-25 14:56:32 -0700914 // Given that we are using the main thread handler, we can create it
915 // here instead of holding onto the PhotoModule objects. In this
916 // way, we can avoid memory leak.
917 mHandler = new Handler(Looper.getMainLooper());
Angus Kong4f795b82013-09-16 14:25:35 -0700918 mCallback = cb;
919 }
920
921 @Override
Angus Kong62848152013-11-08 17:25:29 -0800922 public void onCameraOpened(final CameraProxy camera) {
923 mHandler.post(new Runnable() {
924 @Override
925 public void run() {
926 mCallback.onCameraOpened(camera);
927 }
928 });
929 }
930
931 @Override
Angus Kong4f795b82013-09-16 14:25:35 -0700932 public void onCameraDisabled(final int cameraId) {
933 mHandler.post(new Runnable() {
934 @Override
935 public void run() {
936 mCallback.onCameraDisabled(cameraId);
937 }
938 });
939 }
940
941 @Override
942 public void onDeviceOpenFailure(final int cameraId) {
943 mHandler.post(new Runnable() {
944 @Override
945 public void run() {
946 mCallback.onDeviceOpenFailure(cameraId);
947 }
948 });
949 }
950
951 @Override
952 public void onReconnectionFailure(final CameraManager mgr) {
953 mHandler.post(new Runnable() {
954 @Override
955 public void run() {
956 mCallback.onReconnectionFailure(mgr);
957 }
958 });
959 }
960 }
Angus Kong9ef99252013-07-18 18:04:19 -0700961}