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; 241d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohdeimport com.android.camera.device.ActiveCameraDeviceTracker; 251d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohdeimport com.android.camera.device.CameraId; 2620fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kongimport com.android.camera.util.CameraUtil; 2745f316bcecb8713cbb217507981fd657fcdaa274Alan Newbergerimport com.android.camera.util.GservicesHelper; 285a344964cb003525727c31d295ca3a592c245606Sol Boucherimport com.android.ex.camera2.portability.CameraAgent; 2929a009c974f153f72cd5e28851a8cb85a691e215Alan Newbergerimport com.android.ex.camera2.portability.CameraDeviceInfo; 302a0e18e280dfe541d4740345511ad299099cda79Senpo Huimport com.android.ex.camera2.portability.CameraExceptionHandler; 3120fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong 321d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohdeimport javax.annotation.Nonnull; 331d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohdeimport javax.annotation.Nullable; 341d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde 3520fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong/** 3620fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong * A class which implements {@link com.android.camera.app.CameraProvider} used 3720fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong * by {@link com.android.camera.CameraActivity}. 3820fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong * TODO: Make this class package private. 3920fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong */ 405a344964cb003525727c31d295ca3a592c245606Sol Boucherpublic class CameraController implements CameraAgent.CameraOpenCallback, CameraProvider { 415596b4c902dcb685928b43678f428746ca5ffd08Angus Kong private static final Log.Tag TAG = new Log.Tag("CameraController"); 42432c964bb528a28600f19e18e81ff2b6407bb22dAngus Kong private static final int EMPTY_REQUEST = -1; 43846d3abfe3da2fa2a5593c7d40a196005408bed1Sascha Haeberling private final Context mContext; 44846d3abfe3da2fa2a5593c7d40a196005408bed1Sascha Haeberling private final Handler mCallbackHandler; 455a344964cb003525727c31d295ca3a592c245606Sol Boucher private final CameraAgent mCameraAgent; 4644ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher private final CameraAgent mCameraAgentNg; 471d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde private final ActiveCameraDeviceTracker mActiveCameraDeviceTracker; 481d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde 491d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde private CameraAgent.CameraOpenCallback mCallbackReceiver; 5044ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher 5144ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher /** The one for the API that is currently in use (deprecated one by default). */ 5244ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher private CameraDeviceInfo mInfo; 5320fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong 545a344964cb003525727c31d295ca3a592c245606Sol Boucher private CameraAgent.CameraProxy mCameraProxy; 55432c964bb528a28600f19e18e81ff2b6407bb22dAngus Kong private int mRequestingCameraId = EMPTY_REQUEST; 5620fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong 5720fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong /** 5844ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher * Determines which of mCameraAgent and mCameraAgentNg is currently in use. 5944ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher * <p>It's only possible to enable this if the new API is actually 6044ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher * supported.</p> 6144ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher */ 6244ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher private boolean mUsingNewApi = false; 6344ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher 6444ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher /** 6520fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong * Constructor. 6620fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong * 6720fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong * @param context The {@link android.content.Context} used to check if the 6820fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong * camera is disabled. 6920fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong * @param handler The {@link android.os.Handler} to post the camera 7020fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong * callbacks to. 7120fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong * @param cameraManager Used for camera open/close. 7244ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher * @param cameraManagerNg Used for camera open/close with the new API. If 7344ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher * {@code null} or the same object as 7444ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher * {@code cameraManager}, the new API will not be 7544ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher * exposed and requests for it will get the old one. 761d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde * @param activeCameraDeviceTracker Tracks the active device across multiple 771d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde * api versions and implementations. 7820fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong */ 791d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde public CameraController(@Nonnull Context context, 801d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde @Nullable CameraAgent.CameraOpenCallback callbackReceiver, 811d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde @Nonnull Handler handler, 821d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde @Nonnull CameraAgent cameraManager, 831d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde @Nonnull CameraAgent cameraManagerNg, 841d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde @Nonnull ActiveCameraDeviceTracker activeCameraDeviceTracker) { 8520fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong mContext = context; 8620fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong mCallbackReceiver = callbackReceiver; 8720fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong mCallbackHandler = handler; 885a344964cb003525727c31d295ca3a592c245606Sol Boucher mCameraAgent = cameraManager; 8944ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher // If the new implementation is the same as the old, the 9044ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher // CameraAgentFactory decided this device doesn't support the new API. 9144ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher mCameraAgentNg = cameraManagerNg != cameraManager ? cameraManagerNg : null; 921d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde mActiveCameraDeviceTracker = activeCameraDeviceTracker; 935a344964cb003525727c31d295ca3a592c245606Sol Boucher mInfo = mCameraAgent.getCameraDeviceInfo(); 94c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong if (mInfo == null && mCallbackReceiver != null) { 95c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong mCallbackReceiver.onDeviceOpenFailure(-1, "GETTING_CAMERA_INFO"); 96c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong } 9720fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong } 9820fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong 9920fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong @Override 1002a0e18e280dfe541d4740345511ad299099cda79Senpo Hu public void setCameraExceptionHandler(CameraExceptionHandler exceptionHandler) { 1012a0e18e280dfe541d4740345511ad299099cda79Senpo Hu mCameraAgent.setCameraExceptionHandler(exceptionHandler); 10244ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher if (mCameraAgentNg != null) { 1032a0e18e280dfe541d4740345511ad299099cda79Senpo Hu mCameraAgentNg.setCameraExceptionHandler(exceptionHandler); 10444ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher } 105630d55ba8111357730119899565026be503264c0Erin Dahlgren } 106630d55ba8111357730119899565026be503264c0Erin Dahlgren 107630d55ba8111357730119899565026be503264c0Erin Dahlgren @Override 10843e1813a5d4a59ef107768eb523d76ae2781cb02Sol Boucher public CameraDeviceInfo.Characteristics getCharacteristics(int cameraId) { 109c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong if (mInfo == null) { 110c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong return null; 111c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong } 11243e1813a5d4a59ef107768eb523d76ae2781cb02Sol Boucher return mInfo.getCharacteristics(cameraId); 11320fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong } 11420fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong 11520fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong @Override 116d46ac0034a0fe7b700c4f39499dd22c2c5da5300Paul Rohde @Deprecated 1171d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde public CameraId getCurrentCameraId() { 1181d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde return mActiveCameraDeviceTracker.getActiveOrPreviousCamera(); 1196190c36db653e848f29d1caefc4fa1bb61e8a662Erin Dahlgren } 1206190c36db653e848f29d1caefc4fa1bb61e8a662Erin Dahlgren 1216190c36db653e848f29d1caefc4fa1bb61e8a662Erin Dahlgren @Override 12220fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong public int getNumberOfCameras() { 123c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong if (mInfo == null) { 124c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong return 0; 125c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong } 126c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong return mInfo.getNumberOfCameras(); 12720fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong } 12820fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong 12920fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong @Override 13020fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong public int getFirstBackCameraId() { 131c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong if (mInfo == null) { 132c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong return -1; 133c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong } 134c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong return mInfo.getFirstBackCameraId(); 13520fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong } 13620fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong 13720fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong @Override 13820fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong public int getFirstFrontCameraId() { 139c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong if (mInfo == null) { 140c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong return -1; 141c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong } 142c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong return mInfo.getFirstFrontCameraId(); 14320fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong } 14420fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong 14520fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong @Override 14639b460b805adaa54f310d8637868b3a5c792b2f5Angus Kong public boolean isFrontFacingCamera(int id) { 147c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong if (mInfo == null) { 148c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong return false; 149c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong } 15043e1813a5d4a59ef107768eb523d76ae2781cb02Sol Boucher if (id >= mInfo.getNumberOfCameras() || mInfo.getCharacteristics(id) == null) { 15139b460b805adaa54f310d8637868b3a5c792b2f5Angus Kong Log.e(TAG, "Camera info not available:" + id); 15239b460b805adaa54f310d8637868b3a5c792b2f5Angus Kong return false; 15339b460b805adaa54f310d8637868b3a5c792b2f5Angus Kong } 15443e1813a5d4a59ef107768eb523d76ae2781cb02Sol Boucher return mInfo.getCharacteristics(id).isFacingFront(); 15539b460b805adaa54f310d8637868b3a5c792b2f5Angus Kong } 15639b460b805adaa54f310d8637868b3a5c792b2f5Angus Kong 15739b460b805adaa54f310d8637868b3a5c792b2f5Angus Kong @Override 15839b460b805adaa54f310d8637868b3a5c792b2f5Angus Kong public boolean isBackFacingCamera(int id) { 159c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong if (mInfo == null) { 160c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong return false; 161c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong } 16243e1813a5d4a59ef107768eb523d76ae2781cb02Sol Boucher if (id >= mInfo.getNumberOfCameras() || mInfo.getCharacteristics(id) == null) { 16339b460b805adaa54f310d8637868b3a5c792b2f5Angus Kong Log.e(TAG, "Camera info not available:" + id); 16439b460b805adaa54f310d8637868b3a5c792b2f5Angus Kong return false; 16539b460b805adaa54f310d8637868b3a5c792b2f5Angus Kong } 16643e1813a5d4a59ef107768eb523d76ae2781cb02Sol Boucher return mInfo.getCharacteristics(id).isFacingBack(); 16739b460b805adaa54f310d8637868b3a5c792b2f5Angus Kong } 16839b460b805adaa54f310d8637868b3a5c792b2f5Angus Kong 16939b460b805adaa54f310d8637868b3a5c792b2f5Angus Kong @Override 1705a344964cb003525727c31d295ca3a592c245606Sol Boucher public void onCameraOpened(CameraAgent.CameraProxy camera) { 1710b9eb5bb8d2ef409e8c88196c0c82c8ece65728bAngus Kong Log.v(TAG, "onCameraOpened"); 1720b9eb5bb8d2ef409e8c88196c0c82c8ece65728bAngus Kong if (mRequestingCameraId != camera.getCameraId()) { 173f578829a0f9a298fd5e4fdd9081b768f25811599Angus Kong return; 174f578829a0f9a298fd5e4fdd9081b768f25811599Angus Kong } 1750b9eb5bb8d2ef409e8c88196c0c82c8ece65728bAngus Kong mCameraProxy = camera; 176432c964bb528a28600f19e18e81ff2b6407bb22dAngus Kong mRequestingCameraId = EMPTY_REQUEST; 1770fed7e62bfa0d8351b91d3531228a113637963a3Sascha Haeberling if (mCallbackReceiver != null) { 1780fed7e62bfa0d8351b91d3531228a113637963a3Sascha Haeberling mCallbackReceiver.onCameraOpened(camera); 1790fed7e62bfa0d8351b91d3531228a113637963a3Sascha Haeberling } 18020fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong } 18120fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong 18220fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong @Override 18320fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong public void onCameraDisabled(int cameraId) { 1840fed7e62bfa0d8351b91d3531228a113637963a3Sascha Haeberling if (mCallbackReceiver != null) { 1850fed7e62bfa0d8351b91d3531228a113637963a3Sascha Haeberling mCallbackReceiver.onCameraDisabled(cameraId); 1860fed7e62bfa0d8351b91d3531228a113637963a3Sascha Haeberling } 18720fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong } 18820fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong 18920fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong @Override 1901b9d4fb6f649262e491c0fa743229b4930a87802Angus Kong public void onDeviceOpenFailure(int cameraId, String info) { 1910fed7e62bfa0d8351b91d3531228a113637963a3Sascha Haeberling if (mCallbackReceiver != null) { 1921b9d4fb6f649262e491c0fa743229b4930a87802Angus Kong mCallbackReceiver.onDeviceOpenFailure(cameraId, info); 1930fed7e62bfa0d8351b91d3531228a113637963a3Sascha Haeberling } 19420fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong } 19520fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong 19620fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong @Override 1970b9eb5bb8d2ef409e8c88196c0c82c8ece65728bAngus Kong public void onDeviceOpenedAlready(int cameraId, String info) { 1980fed7e62bfa0d8351b91d3531228a113637963a3Sascha Haeberling if (mCallbackReceiver != null) { 1990b9eb5bb8d2ef409e8c88196c0c82c8ece65728bAngus Kong mCallbackReceiver.onDeviceOpenedAlready(cameraId, info); 2000fed7e62bfa0d8351b91d3531228a113637963a3Sascha Haeberling } 20162753ae94be2ae7c08bf24ebcf1c462975af230fAngus Kong } 20262753ae94be2ae7c08bf24ebcf1c462975af230fAngus Kong 20362753ae94be2ae7c08bf24ebcf1c462975af230fAngus Kong @Override 2045a344964cb003525727c31d295ca3a592c245606Sol Boucher public void onReconnectionFailure(CameraAgent mgr, String info) { 2050fed7e62bfa0d8351b91d3531228a113637963a3Sascha Haeberling if (mCallbackReceiver != null) { 2060b9eb5bb8d2ef409e8c88196c0c82c8ece65728bAngus Kong mCallbackReceiver.onReconnectionFailure(mgr, info); 2070fed7e62bfa0d8351b91d3531228a113637963a3Sascha Haeberling } 20820fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong } 20920fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong 21020fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong @Override 21120fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong public void requestCamera(int id) { 21244ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher requestCamera(id, false); 21344ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher } 21444ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher 21544ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher @Override 21644ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher public void requestCamera(int id, boolean useNewApi) { 21729a009c974f153f72cd5e28851a8cb85a691e215Alan Newberger Log.v(TAG, "requestCamera"); 218432c964bb528a28600f19e18e81ff2b6407bb22dAngus Kong // Based on 219432c964bb528a28600f19e18e81ff2b6407bb22dAngus Kong // (mRequestingCameraId == id, mRequestingCameraId == EMPTY_REQUEST), 220432c964bb528a28600f19e18e81ff2b6407bb22dAngus Kong // we have (T, T), (T, F), (F, T), (F, F). 221432c964bb528a28600f19e18e81ff2b6407bb22dAngus Kong // (T, T): implies id == EMPTY_REQUEST. We don't allow this to happen 222432c964bb528a28600f19e18e81ff2b6407bb22dAngus Kong // here. Return. 223432c964bb528a28600f19e18e81ff2b6407bb22dAngus Kong // (F, F): A previous request hasn't been fulfilled yet. Return. 224432c964bb528a28600f19e18e81ff2b6407bb22dAngus Kong // (T, F): Already requested the same camera. No-op. Return. 225432c964bb528a28600f19e18e81ff2b6407bb22dAngus Kong // (F, T): Nothing is going on. Continue. 226432c964bb528a28600f19e18e81ff2b6407bb22dAngus Kong if (mRequestingCameraId != EMPTY_REQUEST || mRequestingCameraId == id) { 22720fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong return; 22820fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong } 229c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong if (mInfo == null) { 230c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong return; 231c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong } 23220fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong mRequestingCameraId = id; 2331d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde mActiveCameraDeviceTracker.onCameraOpening(CameraId.fromLegacyId(id)); 23444ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher 23544ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher // Only actually use the new API if it's supported on this device. 23644ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher useNewApi = mCameraAgentNg != null && useNewApi; 23744ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher CameraAgent cameraManager = useNewApi ? mCameraAgentNg : mCameraAgent; 23844ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher 23920fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong if (mCameraProxy == null) { 24020fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong // No camera yet. 2411d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde checkAndOpenCamera(cameraManager, id, mCallbackHandler, this); 24244ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher } else if (mCameraProxy.getCameraId() != id || mUsingNewApi != useNewApi) { 2438f51086c8177056345de996963515c4bd3415254Sascha Haeberling boolean syncClose = GservicesHelper.useCamera2ApiThroughPortabilityLayer(mContext 2448f51086c8177056345de996963515c4bd3415254Sascha Haeberling .getContentResolver()); 24529a009c974f153f72cd5e28851a8cb85a691e215Alan Newberger Log.v(TAG, "different camera already opened, closing then reopening"); 24644ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher // Already has camera opened, and is switching cameras and/or APIs. 24744ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher if (mUsingNewApi) { 24845f316bcecb8713cbb217507981fd657fcdaa274Alan Newberger mCameraAgentNg.closeCamera(mCameraProxy, true); 24944ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher } else { 25045f316bcecb8713cbb217507981fd657fcdaa274Alan Newberger // if using API2 ensure API1 usage is also synced 25145f316bcecb8713cbb217507981fd657fcdaa274Alan Newberger mCameraAgent.closeCamera(mCameraProxy, syncClose); 25244ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher } 2531d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde checkAndOpenCamera(cameraManager, id, mCallbackHandler, this); 25420fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong } else { 25520fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong // The same camera, just do a reconnect. 2560b9eb5bb8d2ef409e8c88196c0c82c8ece65728bAngus Kong Log.v(TAG, "reconnecting to use the existing camera"); 25720fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong mCameraProxy.reconnect(mCallbackHandler, this); 25820fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong mCameraProxy = null; 25920fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong } 26044ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher 26144ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher mUsingNewApi = useNewApi; 26244ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher mInfo = cameraManager.getCameraDeviceInfo(); 26320fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong } 26420fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong 26520fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong @Override 26697e282a3764215ac193726e0d259e55bf94369feAngus Kong public boolean waitingForCamera() { 26797e282a3764215ac193726e0d259e55bf94369feAngus Kong return mRequestingCameraId != EMPTY_REQUEST; 26897e282a3764215ac193726e0d259e55bf94369feAngus Kong } 26997e282a3764215ac193726e0d259e55bf94369feAngus Kong 27097e282a3764215ac193726e0d259e55bf94369feAngus Kong @Override 27120fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong public void releaseCamera(int id) { 272f578829a0f9a298fd5e4fdd9081b768f25811599Angus Kong if (mCameraProxy == null) { 273432c964bb528a28600f19e18e81ff2b6407bb22dAngus Kong if (mRequestingCameraId == EMPTY_REQUEST) { 274f578829a0f9a298fd5e4fdd9081b768f25811599Angus Kong // Camera not requested yet. 275f578829a0f9a298fd5e4fdd9081b768f25811599Angus Kong Log.w(TAG, "Trying to release the camera before requesting"); 276f578829a0f9a298fd5e4fdd9081b768f25811599Angus Kong } 277f578829a0f9a298fd5e4fdd9081b768f25811599Angus Kong // Camera requested but not available yet. 278432c964bb528a28600f19e18e81ff2b6407bb22dAngus Kong mRequestingCameraId = EMPTY_REQUEST; 279f578829a0f9a298fd5e4fdd9081b768f25811599Angus Kong return; 280f578829a0f9a298fd5e4fdd9081b768f25811599Angus Kong } 281662082d70ce8dc5f679a25322a00c2733f0339f2Alan Newberger int currentId = mCameraProxy.getCameraId(); 282662082d70ce8dc5f679a25322a00c2733f0339f2Alan Newberger if (currentId != id) { 283662082d70ce8dc5f679a25322a00c2733f0339f2Alan Newberger if (mRequestingCameraId == id) { 284662082d70ce8dc5f679a25322a00c2733f0339f2Alan Newberger Log.w(TAG, "Releasing camera which was requested but not yet " 285662082d70ce8dc5f679a25322a00c2733f0339f2Alan Newberger + "opened (current:requested): " + currentId + ":" + id); 286662082d70ce8dc5f679a25322a00c2733f0339f2Alan Newberger } else { 287662082d70ce8dc5f679a25322a00c2733f0339f2Alan Newberger throw new IllegalStateException("Trying to release a camera neither opened" 288662082d70ce8dc5f679a25322a00c2733f0339f2Alan Newberger + "nor requested (current:requested:for-release): " 289662082d70ce8dc5f679a25322a00c2733f0339f2Alan Newberger + currentId + ":" + mRequestingCameraId + ":" + id); 290662082d70ce8dc5f679a25322a00c2733f0339f2Alan Newberger } 29120fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong } 2921d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde 2931d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde mActiveCameraDeviceTracker.onCameraClosed(CameraId.fromLegacyId(id)); 294432c964bb528a28600f19e18e81ff2b6407bb22dAngus Kong mRequestingCameraId = EMPTY_REQUEST; 29520fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong } 29620fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong 297846d3abfe3da2fa2a5593c7d40a196005408bed1Sascha Haeberling public void removeCallbackReceiver() { 298846d3abfe3da2fa2a5593c7d40a196005408bed1Sascha Haeberling mCallbackReceiver = null; 299846d3abfe3da2fa2a5593c7d40a196005408bed1Sascha Haeberling } 300846d3abfe3da2fa2a5593c7d40a196005408bed1Sascha Haeberling 30120fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong /** 30220fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong * Closes the opened camera device. 30320fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong * TODO: Make this method package private. 30420fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong */ 3050b9eb5bb8d2ef409e8c88196c0c82c8ece65728bAngus Kong public void closeCamera(boolean synced) { 306dcea7639255d5bc4b17a5976bb84de1f6dba0ed1Sascha Haeberling Log.v(TAG, "Closing camera"); 30720fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong mCameraProxy = null; 30844ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher if (mUsingNewApi) { 30944ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher mCameraAgentNg.closeCamera(mCameraProxy, synced); 31044ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher } else { 31144ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher mCameraAgent.closeCamera(mCameraProxy, synced); 31244ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher } 313432c964bb528a28600f19e18e81ff2b6407bb22dAngus Kong mRequestingCameraId = EMPTY_REQUEST; 31444ce4b26614f85518d548a6750c7a08908ae3596Sol Boucher mUsingNewApi = false; 31520fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong } 31620fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong 3171d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde private static void checkAndOpenCamera(CameraAgent cameraManager, 3185a344964cb003525727c31d295ca3a592c245606Sol Boucher final int cameraId, Handler handler, final CameraAgent.CameraOpenCallback cb) { 31929a009c974f153f72cd5e28851a8cb85a691e215Alan Newberger Log.v(TAG, "checkAndOpenCamera"); 32020fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong try { 3218be316c7a8caf962cf3fcf5e49d332fb2718319fPaul Rohde CameraUtil.throwIfCameraDisabled(); 3220b9eb5bb8d2ef409e8c88196c0c82c8ece65728bAngus Kong cameraManager.openCamera(handler, cameraId, cb); 32320fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong } catch (CameraDisabledException ex) { 32420fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong handler.post(new Runnable() { 32520fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong @Override 32620fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong public void run() { 32720fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong cb.onCameraDisabled(cameraId); 32820fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong } 32920fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong }); 33020fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong } 33120fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong } 3324d4a4bc8891bbfc5a7ca842f2981829ac3a716e8Doris Liu 3334d4a4bc8891bbfc5a7ca842f2981829ac3a716e8Doris Liu public void setOneShotPreviewCallback(Handler handler, 3345a344964cb003525727c31d295ca3a592c245606Sol Boucher CameraAgent.CameraPreviewDataCallback cb) { 3354d4a4bc8891bbfc5a7ca842f2981829ac3a716e8Doris Liu mCameraProxy.setOneShotPreviewCallback(handler, cb); 3364d4a4bc8891bbfc5a7ca842f2981829ac3a716e8Doris Liu } 33720fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong} 338