CameraController.java revision 6190c36db653e848f29d1caefc4fa1bb61e8a662
1/* 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; 22 23import com.android.camera.CameraDisabledException; 24import com.android.camera.debug.Log; 25import com.android.camera.util.CameraUtil; 26import com.android.ex.camera2.portability.CameraDeviceInfo; 27import com.android.ex.camera2.portability.CameraAgent; 28import com.android.ex.camera2.portability.CameraAgent.CameraExceptionCallback; 29 30/** 31 * A class which implements {@link com.android.camera.app.CameraProvider} used 32 * by {@link com.android.camera.CameraActivity}. 33 * TODO: Make this class package private. 34 */ 35public class CameraController implements CameraAgent.CameraOpenCallback, CameraProvider { 36 private static final Log.Tag TAG = new Log.Tag("CameraController"); 37 private static final int EMPTY_REQUEST = -1; 38 private final Context mContext; 39 private CameraAgent.CameraOpenCallback mCallbackReceiver; 40 private final Handler mCallbackHandler; 41 private final CameraAgent mCameraAgent; 42 private CameraDeviceInfo mInfo; 43 44 private CameraAgent.CameraProxy mCameraProxy; 45 private int mRequestingCameraId = EMPTY_REQUEST; 46 47 /** 48 * Constructor. 49 * 50 * @param context The {@link android.content.Context} used to check if the 51 * camera is disabled. 52 * @param handler The {@link android.os.Handler} to post the camera 53 * callbacks to. 54 * @param cameraManager Used for camera open/close. 55 */ 56 public CameraController(Context context, CameraAgent.CameraOpenCallback callbackReceiver, 57 Handler handler, CameraAgent cameraManager) { 58 mContext = context; 59 mCallbackReceiver = callbackReceiver; 60 mCallbackHandler = handler; 61 mCameraAgent = cameraManager; 62 mInfo = mCameraAgent.getCameraDeviceInfo(); 63 if (mInfo == null && mCallbackReceiver != null) { 64 mCallbackReceiver.onDeviceOpenFailure(-1, "GETTING_CAMERA_INFO"); 65 } 66 } 67 68 @Override 69 public void setCameraDefaultExceptionCallback(CameraExceptionCallback callback, 70 Handler handler) { 71 mCameraAgent.setCameraDefaultExceptionCallback(callback, handler); 72 } 73 74 @Override 75 public Camera.CameraInfo[] getCameraInfo() { 76 if (mInfo == null) { 77 return null; 78 } 79 return mInfo.getCameraInfos(); 80 } 81 82 @Override 83 public int getCurrentCameraId() { 84 if (mCameraProxy != null) { 85 return mCameraProxy.getCameraId(); 86 } else { 87 return -1; 88 } 89 } 90 91 @Override 92 public int getNumberOfCameras() { 93 if (mInfo == null) { 94 return 0; 95 } 96 return mInfo.getNumberOfCameras(); 97 } 98 99 @Override 100 public int getFirstBackCameraId() { 101 if (mInfo == null) { 102 return -1; 103 } 104 return mInfo.getFirstBackCameraId(); 105 } 106 107 @Override 108 public int getFirstFrontCameraId() { 109 if (mInfo == null) { 110 return -1; 111 } 112 return mInfo.getFirstFrontCameraId(); 113 } 114 115 @Override 116 public boolean isFrontFacingCamera(int id) { 117 if (mInfo == null) { 118 return false; 119 } 120 if (id >= mInfo.getCameraInfos().length || mInfo.getCameraInfos()[id] == null) { 121 Log.e(TAG, "Camera info not available:" + id); 122 return false; 123 } 124 return (mInfo.getCameraInfos()[id].facing == Camera.CameraInfo.CAMERA_FACING_FRONT); 125 } 126 127 @Override 128 public boolean isBackFacingCamera(int id) { 129 if (mInfo == null) { 130 return false; 131 } 132 if (id >= mInfo.getCameraInfos().length || mInfo.getCameraInfos()[id] == null) { 133 Log.e(TAG, "Camera info not available:" + id); 134 return false; 135 } 136 return (mInfo.getCameraInfos()[id].facing == Camera.CameraInfo.CAMERA_FACING_BACK); 137 } 138 139 @Override 140 public void onCameraOpened(CameraAgent.CameraProxy camera) { 141 Log.v(TAG, "onCameraOpened"); 142 if (mRequestingCameraId != camera.getCameraId()) { 143 // Not requesting any camera or not waiting for this one. 144 return; 145 } 146 mCameraProxy = camera; 147 mRequestingCameraId = EMPTY_REQUEST; 148 if (mCallbackReceiver != null) { 149 mCallbackReceiver.onCameraOpened(camera); 150 } 151 } 152 153 @Override 154 public void onCameraDisabled(int cameraId) { 155 if (mCallbackReceiver != null) { 156 mCallbackReceiver.onCameraDisabled(cameraId); 157 } 158 } 159 160 @Override 161 public void onDeviceOpenFailure(int cameraId, String info) { 162 if (mCallbackReceiver != null) { 163 mCallbackReceiver.onDeviceOpenFailure(cameraId, info); 164 } 165 } 166 167 @Override 168 public void onDeviceOpenedAlready(int cameraId, String info) { 169 if (mCallbackReceiver != null) { 170 mCallbackReceiver.onDeviceOpenedAlready(cameraId, info); 171 } 172 } 173 174 @Override 175 public void onReconnectionFailure(CameraAgent mgr, String info) { 176 if (mCallbackReceiver != null) { 177 mCallbackReceiver.onReconnectionFailure(mgr, info); 178 } 179 } 180 181 @Override 182 public void requestCamera(int id) { 183 // Based on 184 // (mRequestingCameraId == id, mRequestingCameraId == EMPTY_REQUEST), 185 // we have (T, T), (T, F), (F, T), (F, F). 186 // (T, T): implies id == EMPTY_REQUEST. We don't allow this to happen 187 // here. Return. 188 // (F, F): A previous request hasn't been fulfilled yet. Return. 189 // (T, F): Already requested the same camera. No-op. Return. 190 // (F, T): Nothing is going on. Continue. 191 if (mRequestingCameraId != EMPTY_REQUEST || mRequestingCameraId == id) { 192 return; 193 } 194 if (mInfo == null) { 195 return; 196 } 197 mRequestingCameraId = id; 198 if (mCameraProxy == null) { 199 // No camera yet. 200 checkAndOpenCamera(mContext, mCameraAgent, id, mCallbackHandler, this); 201 } else if (mCameraProxy.getCameraId() != id) { 202 // Already has another camera opened. 203 mCameraAgent.closeCamera(mCameraProxy, false); 204 checkAndOpenCamera(mContext, mCameraAgent, id, mCallbackHandler, this); 205 } else { 206 // The same camera, just do a reconnect. 207 Log.v(TAG, "reconnecting to use the existing camera"); 208 mCameraProxy.reconnect(mCallbackHandler, this); 209 mCameraProxy = null; 210 } 211 } 212 213 @Override 214 public boolean waitingForCamera() { 215 return mRequestingCameraId != EMPTY_REQUEST; 216 } 217 218 @Override 219 public void releaseCamera(int id) { 220 if (mCameraProxy == null) { 221 if (mRequestingCameraId == EMPTY_REQUEST) { 222 // Camera not requested yet. 223 Log.w(TAG, "Trying to release the camera before requesting"); 224 } 225 // Camera requested but not available yet. 226 mRequestingCameraId = EMPTY_REQUEST; 227 return; 228 } 229 if (mCameraProxy.getCameraId() != id) { 230 throw new IllegalStateException("Trying to release an unopened camera."); 231 } 232 mRequestingCameraId = EMPTY_REQUEST; 233 } 234 235 public void removeCallbackReceiver() { 236 mCallbackReceiver = null; 237 } 238 239 /** 240 * Closes the opened camera device. 241 * TODO: Make this method package private. 242 */ 243 public void closeCamera(boolean synced) { 244 Log.v(TAG, "closing camera"); 245 mCameraProxy = null; 246 mCameraAgent.closeCamera(mCameraProxy, synced); 247 mRequestingCameraId = EMPTY_REQUEST; 248 } 249 250 private static void checkAndOpenCamera(Context context, CameraAgent cameraManager, 251 final int cameraId, Handler handler, final CameraAgent.CameraOpenCallback cb) { 252 try { 253 CameraUtil.throwIfCameraDisabled(context); 254 cameraManager.openCamera(handler, cameraId, cb); 255 } catch (CameraDisabledException ex) { 256 handler.post(new Runnable() { 257 @Override 258 public void run() { 259 cb.onCameraDisabled(cameraId); 260 } 261 }); 262 } 263 } 264 265 public void setOneShotPreviewCallback(Handler handler, 266 CameraAgent.CameraPreviewDataCallback cb) { 267 mCameraProxy.setOneShotPreviewCallback(handler, cb); 268 } 269} 270