blob: cbd10f86ed8d7f8345a79410a32f945e6e7ce798 [file] [log] [blame]
Angus Kong20fad242013-11-11 18:23:46 -08001/*
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
17package com.android.camera.app;
18
19import android.content.Context;
20import android.hardware.Camera;
21import android.os.Handler;
22import android.util.Log;
23
24import com.android.camera.CameraDisabledException;
25import com.android.camera.util.CameraUtil;
26
27/**
28 * A class which implements {@link com.android.camera.app.CameraProvider} used
29 * by {@link com.android.camera.CameraActivity}.
30 * TODO: Make this class package private.
31 */
32public class CameraController implements CameraManager.CameraOpenCallback, CameraProvider {
33 private final String TAG = "CameraController";
Sascha Haeberling846d3ab2014-02-04 12:48:55 +010034 private final Context mContext;
Angus Kong20fad242013-11-11 18:23:46 -080035 private CameraManager.CameraOpenCallback mCallbackReceiver;
Sascha Haeberling846d3ab2014-02-04 12:48:55 +010036 private final Handler mCallbackHandler;
Angus Kong20fad242013-11-11 18:23:46 -080037 private final CameraManager mCameraManager;
38 private final Camera.CameraInfo[] mCameraInfos;
39 private final int mNumberOfCameras;
40 private final int mFirstBackCameraId;
41 private final int mFirstFrontCameraId;
42
43 private CameraManager.CameraProxy mCameraProxy;
44 private int mRequestingCameraId = -1;
45
46 /**
47 * Constructor.
48 *
49 * @param context The {@link android.content.Context} used to check if the
50 * camera is disabled.
51 * @param handler The {@link android.os.Handler} to post the camera
52 * callbacks to.
53 * @param cameraManager Used for camera open/close.
54 */
55 public CameraController(Context context, CameraManager.CameraOpenCallback callbackReceiver,
56 Handler handler, CameraManager cameraManager) {
57 mContext = context;
58 mCallbackReceiver = callbackReceiver;
59 mCallbackHandler = handler;
60 mCameraManager = cameraManager;
61 mNumberOfCameras = Camera.getNumberOfCameras();
62 mCameraInfos = new Camera.CameraInfo[mNumberOfCameras];
63 for (int i = 0; i < mNumberOfCameras; i++) {
64 mCameraInfos[i] = new Camera.CameraInfo();
65 Camera.getCameraInfo(i, mCameraInfos[i]);
66 }
67
68 int firstFront = -1;
69 int firstBack = -1;
70 // Get the first (smallest) back and first front camera id.
Angus Kong18500a42013-11-21 18:14:14 -080071 for (int i = mNumberOfCameras - 1; i >= 0; i--) {
Angus Kong20fad242013-11-11 18:23:46 -080072 if (mCameraInfos[i].facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
73 firstBack = i;
74 } else {
75 if (mCameraInfos[i].facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
76 firstFront = i;
77 }
78 }
79 }
80 mFirstBackCameraId = firstBack;
81 mFirstFrontCameraId = firstFront;
82 }
83
84 @Override
85 public Camera.CameraInfo[] getCameraInfo() {
86 return mCameraInfos;
87 }
88
89 @Override
90 public int getNumberOfCameras() {
91 return mNumberOfCameras;
92 }
93
94 @Override
95 public int getFirstBackCameraId() {
96 return mFirstBackCameraId;
97 }
98
99 @Override
100 public int getFirstFrontCameraId() {
101 return mFirstFrontCameraId;
102 }
103
104 @Override
Angus Kong39b460b2013-12-06 20:55:36 -0800105 public boolean isFrontFacingCamera(int id) {
106 if (id >= mCameraInfos.length || mCameraInfos[id] == null) {
107 Log.e(TAG, "Camera info not available:" + id);
108 return false;
109 }
110 return (mCameraInfos[id].facing == Camera.CameraInfo.CAMERA_FACING_FRONT);
111 }
112
113 @Override
114 public boolean isBackFacingCamera(int id) {
115 if (id >= mCameraInfos.length || mCameraInfos[id] == null) {
116 Log.e(TAG, "Camera info not available:" + id);
117 return false;
118 }
119 return (mCameraInfos[id].facing == Camera.CameraInfo.CAMERA_FACING_BACK);
120 }
121
122 @Override
Angus Kong20fad242013-11-11 18:23:46 -0800123 public void onCameraOpened(CameraManager.CameraProxy camera) {
124 mRequestingCameraId = -1;
125 mCameraProxy = camera;
126 mCallbackReceiver.onCameraOpened(camera);
127 }
128
129 @Override
130 public void onCameraDisabled(int cameraId) {
131 mCallbackReceiver.onCameraDisabled(cameraId);
132 }
133
134 @Override
135 public void onDeviceOpenFailure(int cameraId) {
136 mCallbackReceiver.onDeviceOpenFailure(cameraId);
137 }
138
139 @Override
140 public void onReconnectionFailure(CameraManager mgr) {
141 mCallbackReceiver.onReconnectionFailure(mgr);
142 }
143
144 @Override
145 public void requestCamera(int id) {
146 // Double open is avoided.
147 if (mRequestingCameraId == id) {
148 return;
149 }
150 mRequestingCameraId = id;
151 if (mCameraProxy == null) {
152 // No camera yet.
153 checkAndOpenCamera(mContext, mCameraManager, id, mCallbackHandler, this);
154 } else if (mCameraProxy.getCameraId() != id) {
155 // Already has another camera opened.
156 mCameraProxy.release(false);
157 mCameraProxy = null;
158 checkAndOpenCamera(mContext, mCameraManager, id, mCallbackHandler, this);
159 } else {
160 // The same camera, just do a reconnect.
161 mCameraProxy.reconnect(mCallbackHandler, this);
162 mCameraProxy = null;
163 }
164 }
165
166 @Override
167 public void releaseCamera(int id) {
168 if (mCameraProxy.getCameraId() != id) {
169 throw new IllegalStateException("Trying to release an unopened camera.");
170 }
171 if (mRequestingCameraId != -1) {
172 mRequestingCameraId = -1;
173 }
174 }
175
Sascha Haeberling846d3ab2014-02-04 12:48:55 +0100176 public void removeCallbackReceiver() {
177 mCallbackReceiver = null;
178 }
179
Angus Kong20fad242013-11-11 18:23:46 -0800180 /**
181 * Closes the opened camera device.
182 * TODO: Make this method package private.
183 */
184 public void closeCamera() {
185 Log.v(TAG, "closing camera");
186 if (mCameraProxy == null) {
187 return;
188 }
189 mCameraProxy.release(true);
190 mCameraProxy = null;
191 mRequestingCameraId = -1;
192 }
193
194 private static void checkAndOpenCamera(Context context, CameraManager cameraManager,
195 final int cameraId, Handler handler, final CameraManager.CameraOpenCallback cb) {
196 try {
197 CameraUtil.throwIfCameraDisabled(context);
198 cameraManager.cameraOpen(handler, cameraId, cb);
199 } catch (CameraDisabledException ex) {
200 handler.post(new Runnable() {
201 @Override
202 public void run() {
203 cb.onCameraDisabled(cameraId);
204 }
205 });
206 }
207 }
Doris Liu4d4a4bc2013-12-19 18:55:54 -0800208
209 public void setOneShotPreviewCallback(Handler handler,
210 CameraManager.CameraPreviewDataCallback cb) {
211 mCameraProxy.setOneShotPreviewCallback(handler, cb);
212 }
Angus Kong20fad242013-11-11 18:23:46 -0800213}