120fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong/* 220fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong * Copyright (C) 2013 The Android Open Source Project 320fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong * 420fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong * Licensed under the Apache License, Version 2.0 (the "License"); 520fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong * you may not use this file except in compliance with the License. 620fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong * You may obtain a copy of the License at 720fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong * 820fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong * http://www.apache.org/licenses/LICENSE-2.0 920fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong * 1020fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong * Unless required by applicable law or agreed to in writing, software 1120fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong * distributed under the License is distributed on an "AS IS" BASIS, 1220fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1320fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong * See the License for the specific language governing permissions and 1420fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong * limitations under the License. 1520fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong */ 1620fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong 1720fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kongpackage com.android.camera.app; 1820fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong 1920fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kongimport android.content.Context; 2020fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kongimport android.os.Handler; 2120fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong 2220fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kongimport com.android.camera.CameraDisabledException; 235596b4c902dcb685928b43678f428746ca5ffd08Angus Kongimport com.android.camera.debug.Log; 2420fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kongimport com.android.camera.util.CameraUtil; 2545f316bcecb8713cbb217507981fd657fcdaa274Alan Newbergerimport com.android.camera.util.GservicesHelper; 265a344964cb003525727c31d295ca3a592c245606Sol Boucherimport com.android.ex.camera2.portability.CameraAgent; 275a344964cb003525727c31d295ca3a592c245606Sol Boucherimport com.android.ex.camera2.portability.CameraAgent.CameraExceptionCallback; 2829a009c974f153f72cd5e28851a8cb85a691e215Alan Newbergerimport com.android.ex.camera2.portability.CameraDeviceInfo; 2920fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong 3020fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong/** 3120fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong * A class which implements {@link com.android.camera.app.CameraProvider} used 3220fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong * by {@link com.android.camera.CameraActivity}. 3320fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong * TODO: Make this class package private. 3420fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong */ 355a344964cb003525727c31d295ca3a592c245606Sol Boucherpublic class CameraController implements CameraAgent.CameraOpenCallback, CameraProvider { 365596b4c902dcb685928b43678f428746ca5ffd08Angus Kong private static final Log.Tag TAG = new Log.Tag("CameraController"); 37432c964bb528a28600f19e18e81ff2b6407bb22dAngus Kong private static final int EMPTY_REQUEST = -1; 38846d3abfe3da2fa2a5593c7d40a196005408bed1Sascha Haeberling private final Context mContext; 395a344964cb003525727c31d295ca3a592c245606Sol Boucher private CameraAgent.CameraOpenCallback mCallbackReceiver; 40846d3abfe3da2fa2a5593c7d40a196005408bed1Sascha Haeberling private final Handler mCallbackHandler; 415a344964cb003525727c31d295ca3a592c245606Sol Boucher private final CameraAgent mCameraAgent; 4244ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher private final CameraAgent mCameraAgentNg; 4344ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher 4444ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher /** The one for the API that is currently in use (deprecated one by default). */ 4544ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher private CameraDeviceInfo mInfo; 4620fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong 475a344964cb003525727c31d295ca3a592c245606Sol Boucher private CameraAgent.CameraProxy mCameraProxy; 48432c964bb528a28600f19e18e81ff2b6407bb22dAngus Kong private int mRequestingCameraId = EMPTY_REQUEST; 4920fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong 5020fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong /** 5144ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher * Determines which of mCameraAgent and mCameraAgentNg is currently in use. 5244ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher * <p>It's only possible to enable this if the new API is actually 5344ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher * supported.</p> 5444ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher */ 5544ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher private boolean mUsingNewApi = false; 5644ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher 5744ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher /** 5820fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong * Constructor. 5920fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong * 6020fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong * @param context The {@link android.content.Context} used to check if the 6120fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong * camera is disabled. 6220fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong * @param handler The {@link android.os.Handler} to post the camera 6320fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong * callbacks to. 6420fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong * @param cameraManager Used for camera open/close. 6544ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher * @param cameraManagerNg Used for camera open/close with the new API. If 6644ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher * {@code null} or the same object as 6744ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher * {@code cameraManager}, the new API will not be 6844ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher * exposed and requests for it will get the old one. 6920fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong */ 705a344964cb003525727c31d295ca3a592c245606Sol Boucher public CameraController(Context context, CameraAgent.CameraOpenCallback callbackReceiver, 7144ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher Handler handler, CameraAgent cameraManager, CameraAgent cameraManagerNg) { 7220fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong mContext = context; 7320fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong mCallbackReceiver = callbackReceiver; 7420fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong mCallbackHandler = handler; 755a344964cb003525727c31d295ca3a592c245606Sol Boucher mCameraAgent = cameraManager; 7644ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher // If the new implementation is the same as the old, the 7744ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher // CameraAgentFactory decided this device doesn't support the new API. 7844ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher mCameraAgentNg = cameraManagerNg != cameraManager ? cameraManagerNg : null; 795a344964cb003525727c31d295ca3a592c245606Sol Boucher mInfo = mCameraAgent.getCameraDeviceInfo(); 80c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong if (mInfo == null && mCallbackReceiver != null) { 81c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong mCallbackReceiver.onDeviceOpenFailure(-1, "GETTING_CAMERA_INFO"); 82c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong } 8320fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong } 8420fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong 8520fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong @Override 86630d55ba8111357730119899565026be503264c0Erin Dahlgren public void setCameraDefaultExceptionCallback(CameraExceptionCallback callback, 87630d55ba8111357730119899565026be503264c0Erin Dahlgren Handler handler) { 885a344964cb003525727c31d295ca3a592c245606Sol Boucher mCameraAgent.setCameraDefaultExceptionCallback(callback, handler); 8944ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher if (mCameraAgentNg != null) { 9044ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher mCameraAgentNg.setCameraDefaultExceptionCallback(callback, handler); 9144ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher } 92630d55ba8111357730119899565026be503264c0Erin Dahlgren } 93630d55ba8111357730119899565026be503264c0Erin Dahlgren 94630d55ba8111357730119899565026be503264c0Erin Dahlgren @Override 9543e1813a5d4a59ef107768eb523d76ae2781cb02Sol Boucher public CameraDeviceInfo.Characteristics getCharacteristics(int cameraId) { 96c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong if (mInfo == null) { 97c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong return null; 98c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong } 9943e1813a5d4a59ef107768eb523d76ae2781cb02Sol Boucher return mInfo.getCharacteristics(cameraId); 10020fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong } 10120fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong 10220fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong @Override 1036190c36db653e848f29d1caefc4fa1bb61e8a662Erin Dahlgren public int getCurrentCameraId() { 1046190c36db653e848f29d1caefc4fa1bb61e8a662Erin Dahlgren if (mCameraProxy != null) { 1056190c36db653e848f29d1caefc4fa1bb61e8a662Erin Dahlgren return mCameraProxy.getCameraId(); 1066190c36db653e848f29d1caefc4fa1bb61e8a662Erin Dahlgren } else { 107395bc17b71d13d97b3fd9f258fcf4d5748e66e5eSol Boucher Log.v(TAG, "getCurrentCameraId without an open camera... returning requested id"); 108395bc17b71d13d97b3fd9f258fcf4d5748e66e5eSol Boucher return mRequestingCameraId; 1096190c36db653e848f29d1caefc4fa1bb61e8a662Erin Dahlgren } 1106190c36db653e848f29d1caefc4fa1bb61e8a662Erin Dahlgren } 1116190c36db653e848f29d1caefc4fa1bb61e8a662Erin Dahlgren 1126190c36db653e848f29d1caefc4fa1bb61e8a662Erin Dahlgren @Override 11320fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong public int getNumberOfCameras() { 114c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong if (mInfo == null) { 115c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong return 0; 116c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong } 117c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong return mInfo.getNumberOfCameras(); 11820fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong } 11920fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong 12020fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong @Override 12120fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong public int getFirstBackCameraId() { 122c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong if (mInfo == null) { 123c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong return -1; 124c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong } 125c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong return mInfo.getFirstBackCameraId(); 12620fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong } 12720fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong 12820fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong @Override 12920fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong public int getFirstFrontCameraId() { 130c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong if (mInfo == null) { 131c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong return -1; 132c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong } 133c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong return mInfo.getFirstFrontCameraId(); 13420fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong } 13520fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong 13620fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong @Override 13739b460b805adaa54f310d8637868b3a5c792b2f5Angus Kong public boolean isFrontFacingCamera(int id) { 138c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong if (mInfo == null) { 139c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong return false; 140c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong } 14143e1813a5d4a59ef107768eb523d76ae2781cb02Sol Boucher if (id >= mInfo.getNumberOfCameras() || mInfo.getCharacteristics(id) == null) { 14239b460b805adaa54f310d8637868b3a5c792b2f5Angus Kong Log.e(TAG, "Camera info not available:" + id); 14339b460b805adaa54f310d8637868b3a5c792b2f5Angus Kong return false; 14439b460b805adaa54f310d8637868b3a5c792b2f5Angus Kong } 14543e1813a5d4a59ef107768eb523d76ae2781cb02Sol Boucher return mInfo.getCharacteristics(id).isFacingFront(); 14639b460b805adaa54f310d8637868b3a5c792b2f5Angus Kong } 14739b460b805adaa54f310d8637868b3a5c792b2f5Angus Kong 14839b460b805adaa54f310d8637868b3a5c792b2f5Angus Kong @Override 14939b460b805adaa54f310d8637868b3a5c792b2f5Angus Kong public boolean isBackFacingCamera(int id) { 150c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong if (mInfo == null) { 151c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong return false; 152c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong } 15343e1813a5d4a59ef107768eb523d76ae2781cb02Sol Boucher if (id >= mInfo.getNumberOfCameras() || mInfo.getCharacteristics(id) == null) { 15439b460b805adaa54f310d8637868b3a5c792b2f5Angus Kong Log.e(TAG, "Camera info not available:" + id); 15539b460b805adaa54f310d8637868b3a5c792b2f5Angus Kong return false; 15639b460b805adaa54f310d8637868b3a5c792b2f5Angus Kong } 15743e1813a5d4a59ef107768eb523d76ae2781cb02Sol Boucher return mInfo.getCharacteristics(id).isFacingBack(); 15839b460b805adaa54f310d8637868b3a5c792b2f5Angus Kong } 15939b460b805adaa54f310d8637868b3a5c792b2f5Angus Kong 16039b460b805adaa54f310d8637868b3a5c792b2f5Angus Kong @Override 1615a344964cb003525727c31d295ca3a592c245606Sol Boucher public void onCameraOpened(CameraAgent.CameraProxy camera) { 1620b9eb5bb8d2ef409e8c88196c0c82c8ece65728bAngus Kong Log.v(TAG, "onCameraOpened"); 1630b9eb5bb8d2ef409e8c88196c0c82c8ece65728bAngus Kong if (mRequestingCameraId != camera.getCameraId()) { 1640b9eb5bb8d2ef409e8c88196c0c82c8ece65728bAngus Kong // Not requesting any camera or not waiting for this one. 165f578829a0f9a298fd5e4fdd9081b768f25811599Angus Kong return; 166f578829a0f9a298fd5e4fdd9081b768f25811599Angus Kong } 1670b9eb5bb8d2ef409e8c88196c0c82c8ece65728bAngus Kong mCameraProxy = camera; 168432c964bb528a28600f19e18e81ff2b6407bb22dAngus Kong mRequestingCameraId = EMPTY_REQUEST; 1690fed7e62bfa0d8351b91d3531228a113637963a3Sascha Haeberling if (mCallbackReceiver != null) { 1700fed7e62bfa0d8351b91d3531228a113637963a3Sascha Haeberling mCallbackReceiver.onCameraOpened(camera); 1710fed7e62bfa0d8351b91d3531228a113637963a3Sascha Haeberling } 17220fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong } 17320fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong 17420fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong @Override 17520fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong public void onCameraDisabled(int cameraId) { 1760fed7e62bfa0d8351b91d3531228a113637963a3Sascha Haeberling if (mCallbackReceiver != null) { 1770fed7e62bfa0d8351b91d3531228a113637963a3Sascha Haeberling mCallbackReceiver.onCameraDisabled(cameraId); 1780fed7e62bfa0d8351b91d3531228a113637963a3Sascha Haeberling } 17920fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong } 18020fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong 18120fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong @Override 1821b9d4fb6f649262e491c0fa743229b4930a87802Angus Kong public void onDeviceOpenFailure(int cameraId, String info) { 1830fed7e62bfa0d8351b91d3531228a113637963a3Sascha Haeberling if (mCallbackReceiver != null) { 1841b9d4fb6f649262e491c0fa743229b4930a87802Angus Kong mCallbackReceiver.onDeviceOpenFailure(cameraId, info); 1850fed7e62bfa0d8351b91d3531228a113637963a3Sascha Haeberling } 18620fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong } 18720fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong 18820fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong @Override 1890b9eb5bb8d2ef409e8c88196c0c82c8ece65728bAngus Kong public void onDeviceOpenedAlready(int cameraId, String info) { 1900fed7e62bfa0d8351b91d3531228a113637963a3Sascha Haeberling if (mCallbackReceiver != null) { 1910b9eb5bb8d2ef409e8c88196c0c82c8ece65728bAngus Kong mCallbackReceiver.onDeviceOpenedAlready(cameraId, info); 1920fed7e62bfa0d8351b91d3531228a113637963a3Sascha Haeberling } 19362753ae94be2ae7c08bf24ebcf1c462975af230fAngus Kong } 19462753ae94be2ae7c08bf24ebcf1c462975af230fAngus Kong 19562753ae94be2ae7c08bf24ebcf1c462975af230fAngus Kong @Override 1965a344964cb003525727c31d295ca3a592c245606Sol Boucher public void onReconnectionFailure(CameraAgent mgr, String info) { 1970fed7e62bfa0d8351b91d3531228a113637963a3Sascha Haeberling if (mCallbackReceiver != null) { 1980b9eb5bb8d2ef409e8c88196c0c82c8ece65728bAngus Kong mCallbackReceiver.onReconnectionFailure(mgr, info); 1990fed7e62bfa0d8351b91d3531228a113637963a3Sascha Haeberling } 20020fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong } 20120fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong 20220fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong @Override 20320fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong public void requestCamera(int id) { 20444ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher requestCamera(id, false); 20544ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher } 20644ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher 20744ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher @Override 20844ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher public void requestCamera(int id, boolean useNewApi) { 20929a009c974f153f72cd5e28851a8cb85a691e215Alan Newberger Log.v(TAG, "requestCamera"); 210432c964bb528a28600f19e18e81ff2b6407bb22dAngus Kong // Based on 211432c964bb528a28600f19e18e81ff2b6407bb22dAngus Kong // (mRequestingCameraId == id, mRequestingCameraId == EMPTY_REQUEST), 212432c964bb528a28600f19e18e81ff2b6407bb22dAngus Kong // we have (T, T), (T, F), (F, T), (F, F). 213432c964bb528a28600f19e18e81ff2b6407bb22dAngus Kong // (T, T): implies id == EMPTY_REQUEST. We don't allow this to happen 214432c964bb528a28600f19e18e81ff2b6407bb22dAngus Kong // here. Return. 215432c964bb528a28600f19e18e81ff2b6407bb22dAngus Kong // (F, F): A previous request hasn't been fulfilled yet. Return. 216432c964bb528a28600f19e18e81ff2b6407bb22dAngus Kong // (T, F): Already requested the same camera. No-op. Return. 217432c964bb528a28600f19e18e81ff2b6407bb22dAngus Kong // (F, T): Nothing is going on. Continue. 218432c964bb528a28600f19e18e81ff2b6407bb22dAngus Kong if (mRequestingCameraId != EMPTY_REQUEST || mRequestingCameraId == id) { 21920fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong return; 22020fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong } 221c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong if (mInfo == null) { 222c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong return; 223c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong } 22420fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong mRequestingCameraId = id; 22544ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher 22644ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher // Only actually use the new API if it's supported on this device. 22744ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher useNewApi = mCameraAgentNg != null && useNewApi; 22844ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher CameraAgent cameraManager = useNewApi ? mCameraAgentNg : mCameraAgent; 22944ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher 23020fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong if (mCameraProxy == null) { 23120fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong // No camera yet. 23244ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher checkAndOpenCamera(mContext, cameraManager, id, mCallbackHandler, this); 23344ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher } else if (mCameraProxy.getCameraId() != id || mUsingNewApi != useNewApi) { 23445f316bcecb8713cbb217507981fd657fcdaa274Alan Newberger boolean syncClose = GservicesHelper.useCamera2ApiThroughPortabilityLayer(mContext); 23529a009c974f153f72cd5e28851a8cb85a691e215Alan Newberger Log.v(TAG, "different camera already opened, closing then reopening"); 23644ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher // Already has camera opened, and is switching cameras and/or APIs. 23744ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher if (mUsingNewApi) { 23845f316bcecb8713cbb217507981fd657fcdaa274Alan Newberger mCameraAgentNg.closeCamera(mCameraProxy, true); 23944ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher } else { 24045f316bcecb8713cbb217507981fd657fcdaa274Alan Newberger // if using API2 ensure API1 usage is also synced 24145f316bcecb8713cbb217507981fd657fcdaa274Alan Newberger mCameraAgent.closeCamera(mCameraProxy, syncClose); 24244ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher } 24344ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher checkAndOpenCamera(mContext, cameraManager, id, mCallbackHandler, this); 24420fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong } else { 24520fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong // The same camera, just do a reconnect. 2460b9eb5bb8d2ef409e8c88196c0c82c8ece65728bAngus Kong Log.v(TAG, "reconnecting to use the existing camera"); 24720fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong mCameraProxy.reconnect(mCallbackHandler, this); 24820fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong mCameraProxy = null; 24920fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong } 25044ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher 25144ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher mUsingNewApi = useNewApi; 25244ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher mInfo = cameraManager.getCameraDeviceInfo(); 25320fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong } 25420fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong 25520fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong @Override 25697e282a3764215ac193726e0d259e55bf94369feAngus Kong public boolean waitingForCamera() { 25797e282a3764215ac193726e0d259e55bf94369feAngus Kong return mRequestingCameraId != EMPTY_REQUEST; 25897e282a3764215ac193726e0d259e55bf94369feAngus Kong } 25997e282a3764215ac193726e0d259e55bf94369feAngus Kong 26097e282a3764215ac193726e0d259e55bf94369feAngus Kong @Override 26120fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong public void releaseCamera(int id) { 262f578829a0f9a298fd5e4fdd9081b768f25811599Angus Kong if (mCameraProxy == null) { 263432c964bb528a28600f19e18e81ff2b6407bb22dAngus Kong if (mRequestingCameraId == EMPTY_REQUEST) { 264f578829a0f9a298fd5e4fdd9081b768f25811599Angus Kong // Camera not requested yet. 265f578829a0f9a298fd5e4fdd9081b768f25811599Angus Kong Log.w(TAG, "Trying to release the camera before requesting"); 266f578829a0f9a298fd5e4fdd9081b768f25811599Angus Kong } 267f578829a0f9a298fd5e4fdd9081b768f25811599Angus Kong // Camera requested but not available yet. 268432c964bb528a28600f19e18e81ff2b6407bb22dAngus Kong mRequestingCameraId = EMPTY_REQUEST; 269f578829a0f9a298fd5e4fdd9081b768f25811599Angus Kong return; 270f578829a0f9a298fd5e4fdd9081b768f25811599Angus Kong } 27120fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong if (mCameraProxy.getCameraId() != id) { 27220fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong throw new IllegalStateException("Trying to release an unopened camera."); 27320fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong } 274432c964bb528a28600f19e18e81ff2b6407bb22dAngus Kong mRequestingCameraId = EMPTY_REQUEST; 27520fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong } 27620fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong 277846d3abfe3da2fa2a5593c7d40a196005408bed1Sascha Haeberling public void removeCallbackReceiver() { 278846d3abfe3da2fa2a5593c7d40a196005408bed1Sascha Haeberling mCallbackReceiver = null; 279846d3abfe3da2fa2a5593c7d40a196005408bed1Sascha Haeberling } 280846d3abfe3da2fa2a5593c7d40a196005408bed1Sascha Haeberling 28120fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong /** 28220fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong * Closes the opened camera device. 28320fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong * TODO: Make this method package private. 28420fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong */ 2850b9eb5bb8d2ef409e8c88196c0c82c8ece65728bAngus Kong public void closeCamera(boolean synced) { 286dcea7639255d5bc4b17a5976bb84de1f6dba0ed1Sascha Haeberling if (mCameraProxy == null) { 287dcea7639255d5bc4b17a5976bb84de1f6dba0ed1Sascha Haeberling Log.v(TAG, "No camera open, not closing"); 288dcea7639255d5bc4b17a5976bb84de1f6dba0ed1Sascha Haeberling return; 289dcea7639255d5bc4b17a5976bb84de1f6dba0ed1Sascha Haeberling } 290dcea7639255d5bc4b17a5976bb84de1f6dba0ed1Sascha Haeberling Log.v(TAG, "Closing camera"); 29120fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong mCameraProxy = null; 29244ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher if (mUsingNewApi) { 29344ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher mCameraAgentNg.closeCamera(mCameraProxy, synced); 29444ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher } else { 29544ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher mCameraAgent.closeCamera(mCameraProxy, synced); 29644ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher } 297432c964bb528a28600f19e18e81ff2b6407bb22dAngus Kong mRequestingCameraId = EMPTY_REQUEST; 29844ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher mUsingNewApi = false; 29920fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong } 30020fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong 3015a344964cb003525727c31d295ca3a592c245606Sol Boucher private static void checkAndOpenCamera(Context context, CameraAgent cameraManager, 3025a344964cb003525727c31d295ca3a592c245606Sol Boucher final int cameraId, Handler handler, final CameraAgent.CameraOpenCallback cb) { 30329a009c974f153f72cd5e28851a8cb85a691e215Alan Newberger Log.v(TAG, "checkAndOpenCamera"); 30420fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong try { 30520fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong CameraUtil.throwIfCameraDisabled(context); 3060b9eb5bb8d2ef409e8c88196c0c82c8ece65728bAngus Kong cameraManager.openCamera(handler, cameraId, cb); 30720fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong } catch (CameraDisabledException ex) { 30820fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong handler.post(new Runnable() { 30920fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong @Override 31020fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong public void run() { 31120fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong cb.onCameraDisabled(cameraId); 31220fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong } 31320fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong }); 31420fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong } 31520fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong } 3164d4a4bc8891bbfc5a7ca842f2981829ac3a716e8Doris Liu 3174d4a4bc8891bbfc5a7ca842f2981829ac3a716e8Doris Liu public void setOneShotPreviewCallback(Handler handler, 3185a344964cb003525727c31d295ca3a592c245606Sol Boucher CameraAgent.CameraPreviewDataCallback cb) { 3194d4a4bc8891bbfc5a7ca842f2981829ac3a716e8Doris Liu mCameraProxy.setOneShotPreviewCallback(handler, cb); 3204d4a4bc8891bbfc5a7ca842f2981829ac3a716e8Doris Liu } 32120fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong} 322