1b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala/* 2b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * Copyright (C) 2013 The Android Open Source Project 3b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * 4b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * Licensed under the Apache License, Version 2.0 (the "License"); 5b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * you may not use this file except in compliance with the License. 6b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * You may obtain a copy of the License at 7b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * 8b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * http://www.apache.org/licenses/LICENSE-2.0 9b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * 10b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * Unless required by applicable law or agreed to in writing, software 11b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * distributed under the License is distributed on an "AS IS" BASIS, 12b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * See the License for the specific language governing permissions and 14b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * limitations under the License. 15b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala */ 16b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala 172f1a2e423e0fbb64467d6fcfa4e82c6384f31210Eino-Ville Talvalapackage android.hardware.camera2; 18b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala 19e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkinimport android.content.Context; 20e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkinimport android.hardware.ICameraService; 21e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkinimport android.hardware.ICameraServiceListener; 224961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkinimport android.hardware.CameraInfo; 2370c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvalaimport android.hardware.camera2.impl.CameraMetadataNative; 24feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.hardware.camera2.legacy.CameraDeviceUserShim; 254961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkinimport android.hardware.camera2.legacy.LegacyMetadataMapper; 26bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvalaimport android.hardware.camera2.utils.CameraServiceBinderDecorator; 272f1a2e423e0fbb64467d6fcfa4e82c6384f31210Eino-Ville Talvalaimport android.hardware.camera2.utils.CameraRuntimeException; 2866ef64514464a1bb9c7931993cc8db3d7539f39aRuben Brunkimport android.hardware.camera2.utils.BinderHolder; 29e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkinimport android.os.IBinder; 304af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvalaimport android.os.Handler; 314af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvalaimport android.os.Looper; 32e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkinimport android.os.RemoteException; 33e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkinimport android.os.ServiceManager; 34e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkinimport android.util.Log; 354af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvalaimport android.util.ArrayMap; 36e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 37e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkinimport java.util.ArrayList; 38e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 39b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala/** 40b67a3b36fd569e63c1b8ca6b2701c34c7a3927c1Eino-Ville Talvala * <p>A system service manager for detecting, characterizing, and connecting to 41b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * {@link CameraDevice CameraDevices}.</p> 42b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * 43b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * <p>You can get an instance of this class by calling 44b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * {@link android.content.Context#getSystemService(String) Context.getSystemService()}.</p> 45b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * 46b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * <pre>CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);</pre> 47b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * 48b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * <p>For more details about communicating with camera devices, read the Camera 492f1a2e423e0fbb64467d6fcfa4e82c6384f31210Eino-Ville Talvala * developer guide or the {@link android.hardware.camera2 camera2} 50b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * package documentation.</p> 51b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala */ 52b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvalapublic final class CameraManager { 53b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala 5485c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk private static final String TAG = "CameraManager"; 55bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala private final boolean DEBUG; 5685c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk 57b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala /** 58e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin * This should match the ICameraService definition 59e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin */ 60e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin private static final String CAMERA_SERVICE_BINDER_NAME = "media.camera"; 61e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin private static final int USE_CALLING_UID = -1; 62e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 634961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin @SuppressWarnings("unused") 644961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin private static final int API_VERSION_1 = 1; 654961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin private static final int API_VERSION_2 = 2; 664961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin 67bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala // Access only through getCameraServiceLocked to deal with binder death 68bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala private ICameraService mCameraService; 69bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala 70e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin private ArrayList<String> mDeviceIdList; 714af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala 72fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala private final ArrayMap<AvailabilityCallback, Handler> mCallbackMap = 73fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala new ArrayMap<AvailabilityCallback, Handler>(); 744af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala 75e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin private final Context mContext; 76e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin private final Object mLock = new Object(); 77e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 78bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala private final CameraServiceListener mServiceListener = new CameraServiceListener(); 79bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala 80e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin /** 81b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * @hide 82b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala */ 83e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin public CameraManager(Context context) { 84bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala DEBUG = Log.isLoggable(TAG, Log.DEBUG); 85bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala synchronized(mLock) { 86bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala mContext = context; 8785c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk 88bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala connectCameraServiceLocked(); 89e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin } 90b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala } 91b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala 92b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala /** 934af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala * Return the list of currently connected camera devices by 944af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala * identifier. 954af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala * 964af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala * <p>Non-removable cameras use integers starting at 0 for their 97b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * identifiers, while removable cameras have a unique identifier for each 98b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * individual device, even if they are the same model.</p> 99b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * 100b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * @return The list of currently connected camera devices. 101b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala */ 1024af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala public String[] getCameraIdList() throws CameraAccessException { 103e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin synchronized (mLock) { 104bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala // ID list creation handles various known failures in device enumeration, so only 105bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala // exceptions it'll throw are unexpected, and should be propagated upward. 106bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala return getOrCreateDeviceIdListLocked().toArray(new String[0]); 107e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin } 108b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala } 109b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala 110b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala /** 111fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala * Register a callback to be notified about camera device availability. 112b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * 113fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala * <p>Registering the same callback again will replace the handler with the 1144af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala * new one provided.</p> 115e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin * 116fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala * <p>The first time a callback is registered, it is immediately called 117bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala * with the availability status of all currently known camera devices.</p> 118bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala * 119fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala * @param callback the new callback to send camera availability notices to 120fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala * @param handler The handler on which the callback should be invoked, or 1214af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala * {@code null} to use the current thread's {@link android.os.Looper looper}. 122b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala */ 123fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala public void registerAvailabilityCallback(AvailabilityCallback callback, Handler handler) { 1244af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala if (handler == null) { 1254af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala Looper looper = Looper.myLooper(); 1264af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala if (looper == null) { 1274af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala throw new IllegalArgumentException( 1284af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala "No handler given, and current thread has no looper!"); 1294af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala } 1304af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala handler = new Handler(looper); 1314af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala } 1324af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala 133e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin synchronized (mLock) { 134fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala Handler oldHandler = mCallbackMap.put(callback, handler); 135fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala // For new callbacks, provide initial availability information 136bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala if (oldHandler == null) { 137fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala mServiceListener.updateCallbackLocked(callback, handler); 138bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala } 139e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin } 140b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala } 141b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala 142b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala /** 143fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala * Remove a previously-added callback; the callback will no longer receive connection and 144fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala * disconnection callbacks. 145b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * 146fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala * <p>Removing a callback that isn't registered has no effect.</p> 147e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin * 148fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala * @param callback The callback to remove from the notification list 149b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala */ 150fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala public void unregisterAvailabilityCallback(AvailabilityCallback callback) { 151e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin synchronized (mLock) { 152fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala mCallbackMap.remove(callback); 153e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin } 154b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala } 155b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala 156b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala /** 157b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * <p>Query the capabilities of a camera device. These capabilities are 158b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * immutable for a given camera.</p> 159b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * 160b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * @param cameraId The id of the camera device to query 161b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * @return The properties of the given camera 162b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * 163b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * @throws IllegalArgumentException if the cameraId does not match any 164bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala * known camera device. 165bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala * @throws CameraAccessException if the camera is disabled by device policy, or 166bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala * the camera device has been disconnected. 167b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * @throws SecurityException if the application does not have permission to 168bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala * access the camera 169b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * 1704af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala * @see #getCameraIdList 171b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * @see android.app.admin.DevicePolicyManager#setCameraDisabled 172b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala */ 17368f40066c914aefc1f88819dd46dd1135fb9f5bcIgor Murashkin public CameraCharacteristics getCameraCharacteristics(String cameraId) 174b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala throws CameraAccessException { 175bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala CameraCharacteristics characteristics = null; 176e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 177e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin synchronized (mLock) { 178e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin if (!getOrCreateDeviceIdListLocked().contains(cameraId)) { 179e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin throw new IllegalArgumentException(String.format("Camera id %s does not match any" + 180e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin " currently connected camera device", cameraId)); 181e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin } 182e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 183bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala int id = Integer.valueOf(cameraId); 1844961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin 185bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala /* 186bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala * Get the camera characteristics from the camera service directly if it supports it, 187bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala * otherwise get them from the legacy shim instead. 188bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala */ 1894961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin 190bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala ICameraService cameraService = getCameraServiceLocked(); 191bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala if (cameraService == null) { 192bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala throw new CameraAccessException(CameraAccessException.CAMERA_DISCONNECTED, 193bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala "Camera service is currently unavailable"); 194bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala } 1954961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin try { 196bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala if (!supportsCamera2ApiLocked(cameraId)) { 197bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala // Legacy backwards compatibility path; build static info from the camera 198bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala // parameters 199bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala String[] outParameters = new String[1]; 2004961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin 201bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala cameraService.getLegacyParameters(id, /*out*/outParameters); 202bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala String parameters = outParameters[0]; 2034961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin 204bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala CameraInfo info = new CameraInfo(); 205bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala cameraService.getCameraInfo(id, /*out*/info); 2064961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin 207bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala characteristics = LegacyMetadataMapper.createCharacteristics(parameters, info); 208bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala } else { 209bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala // Normal path: Get the camera characteristics directly from the camera service 210bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala CameraMetadataNative info = new CameraMetadataNative(); 2114961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin 212bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala cameraService.getCameraCharacteristics(id, info); 213bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala 214bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala characteristics = new CameraCharacteristics(info); 215bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala } 216bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala } catch (CameraRuntimeException e) { 2174961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin throw e.asChecked(); 218bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala } catch (RemoteException e) { 219bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala // Camera service died - act as if the camera was disconnected 220bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala throw new CameraAccessException(CameraAccessException.CAMERA_DISCONNECTED, 221bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala "Camera service is currently unavailable", e); 2224961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin } 2232001188be30649198972a3199a4322d6f7f5f93dZhijun He } 224bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala return characteristics; 225b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala } 226b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala 227b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala /** 228cca00c614c24a71dc234c79ad6241efa9f6c7676Eino-Ville Talvala * Helper for openning a connection to a camera with the given ID. 229b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * 230b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * @param cameraId The unique identifier of the camera device to open 231fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala * @param callback The callback for the camera. Must not be null. 232fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala * @param handler The handler to invoke the callback on. Must not be null. 233b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * 234b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * @throws CameraAccessException if the camera is disabled by device policy, 23566ef64514464a1bb9c7931993cc8db3d7539f39aRuben Brunk * or too many camera devices are already open, or the cameraId does not match 23666ef64514464a1bb9c7931993cc8db3d7539f39aRuben Brunk * any currently available camera device. 23766ef64514464a1bb9c7931993cc8db3d7539f39aRuben Brunk * 238b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * @throws SecurityException if the application does not have permission to 239b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * access the camera 240fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala * @throws IllegalArgumentException if callback or handler is null. 241cca00c614c24a71dc234c79ad6241efa9f6c7676Eino-Ville Talvala * @return A handle to the newly-created camera device. 242b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * 2434af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala * @see #getCameraIdList 244b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * @see android.app.admin.DevicePolicyManager#setCameraDisabled 245b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala */ 246cca00c614c24a71dc234c79ad6241efa9f6c7676Eino-Ville Talvala private CameraDevice openCameraDeviceUserAsync(String cameraId, 247fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala CameraDevice.StateCallback callback, Handler handler) 248868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala throws CameraAccessException { 249574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk CameraCharacteristics characteristics = getCameraCharacteristics(cameraId); 250cca00c614c24a71dc234c79ad6241efa9f6c7676Eino-Ville Talvala CameraDevice device = null; 251e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin try { 252e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 253e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin synchronized (mLock) { 25470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin 2557fcb357811d4dc1f44624e30ad924e9e580d4cbfEino-Ville Talvala ICameraDeviceUser cameraUser = null; 25670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin 25721547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin android.hardware.camera2.impl.CameraDeviceImpl deviceImpl = 25821547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin new android.hardware.camera2.impl.CameraDeviceImpl( 259868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala cameraId, 260fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala callback, 261574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk handler, 262574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk characteristics); 26370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin 26466ef64514464a1bb9c7931993cc8db3d7539f39aRuben Brunk BinderHolder holder = new BinderHolder(); 265feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 266cca00c614c24a71dc234c79ad6241efa9f6c7676Eino-Ville Talvala ICameraDeviceCallbacks callbacks = deviceImpl.getCallbacks(); 267feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk int id = Integer.parseInt(cameraId); 268feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk try { 269bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala if (supportsCamera2ApiLocked(cameraId)) { 270a1d662716b3da384dfe3a758f079e0cbd089784aIgor Murashkin // Use cameraservice's cameradeviceclient implementation for HAL3.2+ devices 271bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala ICameraService cameraService = getCameraServiceLocked(); 272bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala if (cameraService == null) { 273bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala throw new CameraRuntimeException( 274bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala CameraAccessException.CAMERA_DISCONNECTED, 275bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala "Camera service is currently unavailable"); 276bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala } 277bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala cameraService.connectDevice(callbacks, id, 278bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala mContext.getPackageName(), USE_CALLING_UID, holder); 279a1d662716b3da384dfe3a758f079e0cbd089784aIgor Murashkin cameraUser = ICameraDeviceUser.Stub.asInterface(holder.getBinder()); 280a1d662716b3da384dfe3a758f079e0cbd089784aIgor Murashkin } else { 281feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk // Use legacy camera implementation for HAL1 devices 282feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk Log.i(TAG, "Using legacy camera HAL."); 283feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk cameraUser = CameraDeviceUserShim.connectBinderShim(callbacks, id); 284a1d662716b3da384dfe3a758f079e0cbd089784aIgor Murashkin } 285a1d662716b3da384dfe3a758f079e0cbd089784aIgor Murashkin } catch (CameraRuntimeException e) { 286a1d662716b3da384dfe3a758f079e0cbd089784aIgor Murashkin if (e.getReason() == CameraAccessException.CAMERA_DEPRECATED_HAL) { 287a1d662716b3da384dfe3a758f079e0cbd089784aIgor Murashkin throw new AssertionError("Should've gone down the shim path"); 2887fcb357811d4dc1f44624e30ad924e9e580d4cbfEino-Ville Talvala } else if (e.getReason() == CameraAccessException.CAMERA_IN_USE || 2897fcb357811d4dc1f44624e30ad924e9e580d4cbfEino-Ville Talvala e.getReason() == CameraAccessException.MAX_CAMERAS_IN_USE || 2907fcb357811d4dc1f44624e30ad924e9e580d4cbfEino-Ville Talvala e.getReason() == CameraAccessException.CAMERA_DISABLED || 2917fcb357811d4dc1f44624e30ad924e9e580d4cbfEino-Ville Talvala e.getReason() == CameraAccessException.CAMERA_DISCONNECTED || 2927fcb357811d4dc1f44624e30ad924e9e580d4cbfEino-Ville Talvala e.getReason() == CameraAccessException.CAMERA_ERROR) { 2937fcb357811d4dc1f44624e30ad924e9e580d4cbfEino-Ville Talvala // Received one of the known connection errors 2947fcb357811d4dc1f44624e30ad924e9e580d4cbfEino-Ville Talvala // The remote camera device cannot be connected to, so 2957fcb357811d4dc1f44624e30ad924e9e580d4cbfEino-Ville Talvala // set the local camera to the startup error state 2967fcb357811d4dc1f44624e30ad924e9e580d4cbfEino-Ville Talvala deviceImpl.setRemoteFailure(e); 2977fcb357811d4dc1f44624e30ad924e9e580d4cbfEino-Ville Talvala 2987fcb357811d4dc1f44624e30ad924e9e580d4cbfEino-Ville Talvala if (e.getReason() == CameraAccessException.CAMERA_DISABLED || 2997fcb357811d4dc1f44624e30ad924e9e580d4cbfEino-Ville Talvala e.getReason() == CameraAccessException.CAMERA_DISCONNECTED) { 3007fcb357811d4dc1f44624e30ad924e9e580d4cbfEino-Ville Talvala // Per API docs, these failures call onError and throw 301bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala throw e.asChecked(); 3027fcb357811d4dc1f44624e30ad924e9e580d4cbfEino-Ville Talvala } 303feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } else { 3047fcb357811d4dc1f44624e30ad924e9e580d4cbfEino-Ville Talvala // Unexpected failure - rethrow 305feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk throw e; 306feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 307bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala } catch (RemoteException e) { 308bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala // Camera service died - act as if it's a CAMERA_DISCONNECTED case 309bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala CameraRuntimeException ce = new CameraRuntimeException( 310bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala CameraAccessException.CAMERA_DISCONNECTED, 311bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala "Camera service is currently unavailable", e); 312bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala deviceImpl.setRemoteFailure(ce); 313bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala throw ce.asChecked(); 314feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 31570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin 316fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala // TODO: factor out callback to be non-nested, then move setter to constructor 317868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala // For now, calling setRemoteDevice will fire initial 318868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala // onOpened/onUnconfigured callbacks. 319cca00c614c24a71dc234c79ad6241efa9f6c7676Eino-Ville Talvala deviceImpl.setRemoteDevice(cameraUser); 320cca00c614c24a71dc234c79ad6241efa9f6c7676Eino-Ville Talvala device = deviceImpl; 321e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin } 322e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 323e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin } catch (NumberFormatException e) { 324e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin throw new IllegalArgumentException("Expected cameraId to be numeric, but it was: " 325e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin + cameraId); 326e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin } catch (CameraRuntimeException e) { 32766ef64514464a1bb9c7931993cc8db3d7539f39aRuben Brunk throw e.asChecked(); 328e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin } 329cca00c614c24a71dc234c79ad6241efa9f6c7676Eino-Ville Talvala return device; 330b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala } 331b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala 332b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala /** 3335c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin * Open a connection to a camera with the given ID. 3345c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin * 3355c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin * <p>Use {@link #getCameraIdList} to get the list of available camera 3365c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin * devices. Note that even if an id is listed, open may fail if the device 3375c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin * is disconnected between the calls to {@link #getCameraIdList} and 3385c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin * {@link #openCamera}.</p> 3395c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin * 340fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala * <p>Once the camera is successfully opened, {@link CameraDevice.StateCallback#onOpened} will 341cca00c614c24a71dc234c79ad6241efa9f6c7676Eino-Ville Talvala * be invoked with the newly opened {@link CameraDevice}. The camera device can then be set up 342cca00c614c24a71dc234c79ad6241efa9f6c7676Eino-Ville Talvala * for operation by calling {@link CameraDevice#createCaptureSession} and 343cca00c614c24a71dc234c79ad6241efa9f6c7676Eino-Ville Talvala * {@link CameraDevice#createCaptureRequest}</p> 3445c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin * 345cca00c614c24a71dc234c79ad6241efa9f6c7676Eino-Ville Talvala * <!-- 346cca00c614c24a71dc234c79ad6241efa9f6c7676Eino-Ville Talvala * <p>Since the camera device will be opened asynchronously, any asynchronous operations done 347cca00c614c24a71dc234c79ad6241efa9f6c7676Eino-Ville Talvala * on the returned CameraDevice instance will be queued up until the device startup has 348fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala * completed and the callback's {@link CameraDevice.StateCallback#onOpened onOpened} method is 349cca00c614c24a71dc234c79ad6241efa9f6c7676Eino-Ville Talvala * called. The pending operations are then processed in order.</p> 350cca00c614c24a71dc234c79ad6241efa9f6c7676Eino-Ville Talvala * --> 3515c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin * <p>If the camera becomes disconnected during initialization 3525c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin * after this function call returns, 353fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala * {@link CameraDevice.StateCallback#onDisconnected} with a 3545c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin * {@link CameraDevice} in the disconnected state (and 355fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala * {@link CameraDevice.StateCallback#onOpened} will be skipped).</p> 3565c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin * 357fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala * <p>If opening the camera device fails, then the device callback's 358fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala * {@link CameraDevice.StateCallback#onError onError} method will be called, and subsequent 3597fcb357811d4dc1f44624e30ad924e9e580d4cbfEino-Ville Talvala * calls on the camera device will throw a {@link CameraAccessException}.</p> 3605c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin * 3615c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin * @param cameraId 3625c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin * The unique identifier of the camera device to open 363fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala * @param callback 364fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala * The callback which is invoked once the camera is opened 3655c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin * @param handler 366fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala * The handler on which the callback should be invoked, or 3675c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin * {@code null} to use the current thread's {@link android.os.Looper looper}. 3685c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin * 3695c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin * @throws CameraAccessException if the camera is disabled by device policy, 3705c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin * or the camera has become or was disconnected. 3715c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin * 372fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala * @throws IllegalArgumentException if cameraId or the callback was null, 3735c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin * or the cameraId does not match any currently or previously available 3745c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin * camera device. 3755c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin * 3765c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin * @throws SecurityException if the application does not have permission to 3775c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin * access the camera 3785c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin * 3795c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin * @see #getCameraIdList 3805c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin * @see android.app.admin.DevicePolicyManager#setCameraDisabled 3815c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin */ 382fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala public void openCamera(String cameraId, final CameraDevice.StateCallback callback, 3835c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin Handler handler) 3845c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin throws CameraAccessException { 3855c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin 3865c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin if (cameraId == null) { 3875c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin throw new IllegalArgumentException("cameraId was null"); 388fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala } else if (callback == null) { 389fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala throw new IllegalArgumentException("callback was null"); 3905c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin } else if (handler == null) { 3915c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin if (Looper.myLooper() != null) { 3925c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin handler = new Handler(); 3935c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin } else { 3945c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin throw new IllegalArgumentException( 3955c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin "Looper doesn't exist in the calling thread"); 3965c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin } 3975c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin } 3985c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin 399fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala openCameraDeviceUserAsync(cameraId, callback, handler); 4005c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin } 4015c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin 4025c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin /** 403fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala * A callback for camera devices becoming available or 404b67a3b36fd569e63c1b8ca6b2701c34c7a3927c1Eino-Ville Talvala * unavailable to open. 4054af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala * 4064af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala * <p>Cameras become available when they are no longer in use, or when a new 407b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * removable camera is connected. They become unavailable when some 408b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * application or service starts using a camera, or when a removable camera 4094af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala * is disconnected.</p> 4104af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala * 411fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala * <p>Extend this callback and pass an instance of the subclass to 412fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala * {@link CameraManager#registerAvailabilityCallback} to be notified of such availability 413b67a3b36fd569e63c1b8ca6b2701c34c7a3927c1Eino-Ville Talvala * changes.</p> 414b67a3b36fd569e63c1b8ca6b2701c34c7a3927c1Eino-Ville Talvala * 415fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala * @see registerAvailabilityCallback 416b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala */ 417fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala public static abstract class AvailabilityCallback { 4184af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala 419b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala /** 420b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * A new camera has become available to use. 421b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * 4224af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala * <p>The default implementation of this method does nothing.</p> 4234af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala * 424b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * @param cameraId The unique identifier of the new camera. 425b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala */ 4264af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala public void onCameraAvailable(String cameraId) { 4274af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala // default empty implementation 4284af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala } 429b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala 430b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala /** 4314af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala * A previously-available camera has become unavailable for use. 4324af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala * 4334af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala * <p>If an application had an active CameraDevice instance for the 4344af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala * now-disconnected camera, that application will receive a 435fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala * {@link CameraDevice.StateCallback#onDisconnected disconnection error}.</p> 4364af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala * 4374af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala * <p>The default implementation of this method does nothing.</p> 438b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * 439b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * @param cameraId The unique identifier of the disconnected camera. 440b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala */ 4414af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala public void onCameraUnavailable(String cameraId) { 4424af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala // default empty implementation 4434af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala } 444b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala } 445e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 446bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala /** 447fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala * Temporary for migrating to Callback naming 448fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala * @hide 449fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala */ 450fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala public static abstract class AvailabilityListener extends AvailabilityCallback { 451fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala } 452fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala 453fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala /** 454bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala * Return or create the list of currently connected camera devices. 455bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala * 456bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala * <p>In case of errors connecting to the camera service, will return an empty list.</p> 457bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala */ 458e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin private ArrayList<String> getOrCreateDeviceIdListLocked() throws CameraAccessException { 459e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin if (mDeviceIdList == null) { 460e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin int numCameras = 0; 461bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala ICameraService cameraService = getCameraServiceLocked(); 462bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala ArrayList<String> deviceIdList = new ArrayList<>(); 463bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala 464bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala // If no camera service, then no devices 465bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala if (cameraService == null) { 466bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala return deviceIdList; 467bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala } 468e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 469e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin try { 470bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala numCameras = cameraService.getNumberOfCameras(); 471e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin } catch(CameraRuntimeException e) { 472e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin throw e.asChecked(); 473e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin } catch (RemoteException e) { 474bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala // camera service just died - if no camera service, then no devices 475bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala return deviceIdList; 476e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin } 477e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 47818fe0ae08d49b0fe4b6414a3841bd0fcab5419e8Zhijun He CameraMetadataNative info = new CameraMetadataNative(); 479e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin for (int i = 0; i < numCameras; ++i) { 480e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin // Non-removable cameras use integers starting at 0 for their 481e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin // identifiers 48218fe0ae08d49b0fe4b6414a3841bd0fcab5419e8Zhijun He boolean isDeviceSupported = false; 48318fe0ae08d49b0fe4b6414a3841bd0fcab5419e8Zhijun He try { 484bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala cameraService.getCameraCharacteristics(i, info); 48518fe0ae08d49b0fe4b6414a3841bd0fcab5419e8Zhijun He if (!info.isEmpty()) { 48618fe0ae08d49b0fe4b6414a3841bd0fcab5419e8Zhijun He isDeviceSupported = true; 48718fe0ae08d49b0fe4b6414a3841bd0fcab5419e8Zhijun He } else { 48818fe0ae08d49b0fe4b6414a3841bd0fcab5419e8Zhijun He throw new AssertionError("Expected to get non-empty characteristics"); 48918fe0ae08d49b0fe4b6414a3841bd0fcab5419e8Zhijun He } 49018fe0ae08d49b0fe4b6414a3841bd0fcab5419e8Zhijun He } catch(IllegalArgumentException e) { 49118fe0ae08d49b0fe4b6414a3841bd0fcab5419e8Zhijun He // Got a BAD_VALUE from service, meaning that this 49218fe0ae08d49b0fe4b6414a3841bd0fcab5419e8Zhijun He // device is not supported. 49318fe0ae08d49b0fe4b6414a3841bd0fcab5419e8Zhijun He } catch(CameraRuntimeException e) { 494bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala // DISCONNECTED means that the HAL reported an low-level error getting the 495bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala // device info; skip listing the device. Other errors, 496bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala // propagate exception onward 497bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala if (e.getReason() != CameraAccessException.CAMERA_DISCONNECTED) { 498bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala throw e.asChecked(); 499bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala } 50018fe0ae08d49b0fe4b6414a3841bd0fcab5419e8Zhijun He } catch(RemoteException e) { 501bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala // Camera service died - no devices to list 502bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala deviceIdList.clear(); 503bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala return deviceIdList; 50418fe0ae08d49b0fe4b6414a3841bd0fcab5419e8Zhijun He } 50518fe0ae08d49b0fe4b6414a3841bd0fcab5419e8Zhijun He 50618fe0ae08d49b0fe4b6414a3841bd0fcab5419e8Zhijun He if (isDeviceSupported) { 507bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala deviceIdList.add(String.valueOf(i)); 508bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala } else { 509bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala Log.w(TAG, "Error querying camera device " + i + " for listing."); 51018fe0ae08d49b0fe4b6414a3841bd0fcab5419e8Zhijun He } 511e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 512bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala } 513bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala mDeviceIdList = deviceIdList; 514e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin } 515e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin return mDeviceIdList; 516e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin } 517e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 518b6a781066e6b0f2578cafefdc61c9ba18c0efc2eRuben Brunk private void handleRecoverableSetupErrors(CameraRuntimeException e, String msg) { 519b6a781066e6b0f2578cafefdc61c9ba18c0efc2eRuben Brunk int problem = e.getReason(); 520b6a781066e6b0f2578cafefdc61c9ba18c0efc2eRuben Brunk switch (problem) { 521b6a781066e6b0f2578cafefdc61c9ba18c0efc2eRuben Brunk case CameraAccessException.CAMERA_DISCONNECTED: 522b6a781066e6b0f2578cafefdc61c9ba18c0efc2eRuben Brunk String errorMsg = CameraAccessException.getDefaultMessage(problem); 523b6a781066e6b0f2578cafefdc61c9ba18c0efc2eRuben Brunk Log.w(TAG, msg + ": " + errorMsg); 524b6a781066e6b0f2578cafefdc61c9ba18c0efc2eRuben Brunk break; 525b6a781066e6b0f2578cafefdc61c9ba18c0efc2eRuben Brunk default: 526b6a781066e6b0f2578cafefdc61c9ba18c0efc2eRuben Brunk throw new IllegalStateException(msg, e.asChecked()); 527b6a781066e6b0f2578cafefdc61c9ba18c0efc2eRuben Brunk } 528b6a781066e6b0f2578cafefdc61c9ba18c0efc2eRuben Brunk } 529b6a781066e6b0f2578cafefdc61c9ba18c0efc2eRuben Brunk 5304961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin /** 5314961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin * Queries the camera service if it supports the camera2 api directly, or needs a shim. 5324961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin * 5334961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin * @param cameraId a non-{@code null} camera identifier 5344961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin * @return {@code false} if the legacy shim needs to be used, {@code true} otherwise. 5354961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin */ 536bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala private boolean supportsCamera2ApiLocked(String cameraId) { 537bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala return supportsCameraApiLocked(cameraId, API_VERSION_2); 5384961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin } 5394961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin 5404961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin /** 5414961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin * Queries the camera service if it supports a camera api directly, or needs a shim. 5424961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin * 5434961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin * @param cameraId a non-{@code null} camera identifier 5444961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin * @param apiVersion the version, i.e. {@code API_VERSION_1} or {@code API_VERSION_2} 5454961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin * @return {@code true} if connecting will work for that device version. 5464961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin */ 547bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala private boolean supportsCameraApiLocked(String cameraId, int apiVersion) { 5484961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin int id = Integer.parseInt(cameraId); 5494961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin 5504961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin /* 5514961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin * Possible return values: 552bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala * - NO_ERROR => CameraX API is supported 553bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala * - CAMERA_DEPRECATED_HAL => CameraX API is *not* supported (thrown as an exception) 554bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala * - Remote exception => If the camera service died 5554961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin * 5564961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin * Anything else is an unexpected error we don't want to recover from. 5574961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin */ 5584961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin try { 559bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala ICameraService cameraService = getCameraServiceLocked(); 560bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala // If no camera service, no support 561bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala if (cameraService == null) return false; 562bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala 563bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala int res = cameraService.supportsCameraApi(id, apiVersion); 5644961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin 565bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala if (res != CameraServiceBinderDecorator.NO_ERROR) { 5664961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin throw new AssertionError("Unexpected value " + res); 5674961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin } 5684961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin return true; 5694961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin } catch (CameraRuntimeException e) { 570bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala if (e.getReason() != CameraAccessException.CAMERA_DEPRECATED_HAL) { 5714961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin throw e; 5724961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin } 573bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala // API level is not supported 5744961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin } catch (RemoteException e) { 575bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala // Camera service is now down, no support for any API level 576bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala } 577bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala return false; 578bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala } 579bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala 580bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala /** 581bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala * Connect to the camera service if it's available, and set up listeners. 582bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala * 583bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala * <p>Sets mCameraService to a valid pointer or null if the connection does not succeed.</p> 584bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala */ 585bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala private void connectCameraServiceLocked() { 586bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala mCameraService = null; 587bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala IBinder cameraServiceBinder = ServiceManager.getService(CAMERA_SERVICE_BINDER_NAME); 588bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala if (cameraServiceBinder == null) { 589bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala // Camera service is now down, leave mCameraService as null 590bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala return; 591bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala } 592bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala try { 593bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala cameraServiceBinder.linkToDeath(new CameraServiceDeathListener(), /*flags*/ 0); 594bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala } catch (RemoteException e) { 595bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala // Camera service is now down, leave mCameraService as null 596bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala return; 597bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala } 598bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala 599bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala ICameraService cameraServiceRaw = ICameraService.Stub.asInterface(cameraServiceBinder); 600bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala 601bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala /** 602bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala * Wrap the camera service in a decorator which automatically translates return codes 603bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala * into exceptions. 604bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala */ 605bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala ICameraService cameraService = CameraServiceBinderDecorator.newInstance(cameraServiceRaw); 606bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala 607bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala try { 608bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala CameraServiceBinderDecorator.throwOnError( 609bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala CameraMetadataNative.nativeSetupGlobalVendorTagDescriptor()); 610bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala } catch (CameraRuntimeException e) { 611bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala handleRecoverableSetupErrors(e, "Failed to set up vendor tags"); 612bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala } 613bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala 614bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala try { 615bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala cameraService.addListener(mServiceListener); 616bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala mCameraService = cameraService; 617bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala } catch(CameraRuntimeException e) { 618bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala // Unexpected failure 619bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala throw new IllegalStateException("Failed to register a camera service listener", 620bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala e.asChecked()); 621bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala } catch (RemoteException e) { 622bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala // Camera service is now down, leave mCameraService as null 623bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala } 624bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala } 625bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala 626bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala /** 627bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala * Return a best-effort ICameraService. 628bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala * 629bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala * <p>This will be null if the camera service 630bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala * is not currently available. If the camera service has died since the last 631bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala * use of the camera service, will try to reconnect to the service.</p> 632bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala */ 633bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala private ICameraService getCameraServiceLocked() { 634bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala if (mCameraService == null) { 635bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala Log.i(TAG, "getCameraServiceLocked: Reconnecting to camera service"); 636bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala connectCameraServiceLocked(); 637bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala if (mCameraService == null) { 638bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala Log.e(TAG, "Camera service is unavailable"); 639bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala } 640bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala } 641bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala return mCameraService; 642bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala } 643bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala 644bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala /** 645bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala * Listener for camera service death. 646bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala * 647bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala * <p>The camera service isn't supposed to die under any normal circumstances, but can be turned 648bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala * off during debug, or crash due to bugs. So detect that and null out the interface object, so 649bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala * that the next calls to the manager can try to reconnect.</p> 650bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala */ 651bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala private class CameraServiceDeathListener implements IBinder.DeathRecipient { 652bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala public void binderDied() { 653bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala synchronized(mLock) { 654bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala mCameraService = null; 655bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala // Tell listeners that the cameras are _available_, because any existing clients 656bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala // will have gotten disconnected. This is optimistic under the assumption that the 657bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala // service will be back shortly. 658bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala // 659bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala // Without this, a camera service crash while a camera is open will never signal to 660bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala // listeners that previously in-use cameras are now available. 661bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala for (String cameraId : mDeviceIdList) { 662bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala mServiceListener.onStatusChangedLocked(CameraServiceListener.STATUS_PRESENT, 663bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala cameraId); 664bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala } 665bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala } 6664961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin } 6674961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin } 6684961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin 669e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin // TODO: this class needs unit tests 670e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin // TODO: extract class into top level 671ecb323e3ce94f62411b6799f9a0aa42b052de30dZhijun He private class CameraServiceListener extends ICameraServiceListener.Stub { 672e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 673e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin // Keep up-to-date with ICameraServiceListener.h 674e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 675e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin // Device physically unplugged 676e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin public static final int STATUS_NOT_PRESENT = 0; 677e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin // Device physically has been plugged in 678e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin // and the camera can be used exclusively 679e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin public static final int STATUS_PRESENT = 1; 680e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin // Device physically has been plugged in 681e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin // but it will not be connect-able until enumeration is complete 682e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin public static final int STATUS_ENUMERATING = 2; 683e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin // Camera is in use by another app and cannot be used exclusively 684e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin public static final int STATUS_NOT_AVAILABLE = 0x80000000; 685e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 686e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin // Camera ID -> Status map 6874af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala private final ArrayMap<String, Integer> mDeviceStatus = new ArrayMap<String, Integer>(); 688e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 689e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin private static final String TAG = "CameraServiceListener"; 690e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 691e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin @Override 692e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin public IBinder asBinder() { 693e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin return this; 694e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin } 695e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 696e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin private boolean isAvailable(int status) { 697e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin switch (status) { 698e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin case STATUS_PRESENT: 699e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin return true; 700e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin default: 701e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin return false; 702e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin } 703e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin } 704e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 705e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin private boolean validStatus(int status) { 706e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin switch (status) { 707e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin case STATUS_NOT_PRESENT: 708e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin case STATUS_PRESENT: 709e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin case STATUS_ENUMERATING: 710e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin case STATUS_NOT_AVAILABLE: 711e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin return true; 712e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin default: 713e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin return false; 714e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin } 715e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin } 716e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 717fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala private void postSingleUpdate(final AvailabilityCallback callback, final Handler handler, 718bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala final String id, final int status) { 719bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala if (isAvailable(status)) { 720bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala handler.post( 721bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala new Runnable() { 722bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala @Override 723bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala public void run() { 724fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala callback.onCameraAvailable(id); 725bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala } 726bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala }); 727bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala } else { 728bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala handler.post( 729bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala new Runnable() { 730bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala @Override 731bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala public void run() { 732fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala callback.onCameraUnavailable(id); 733bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala } 734bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala }); 735bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala } 736bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala } 737bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala 738bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala /** 739bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala * Send the state of all known cameras to the provided listener, to initialize 740bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala * the listener's knowledge of camera state. 741bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala */ 742fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala public void updateCallbackLocked(AvailabilityCallback callback, Handler handler) { 743bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala for (int i = 0; i < mDeviceStatus.size(); i++) { 744bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala String id = mDeviceStatus.keyAt(i); 745bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala Integer status = mDeviceStatus.valueAt(i); 746fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala postSingleUpdate(callback, handler, id, status); 747bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala } 748bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala } 749bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala 750e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin @Override 751e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin public void onStatusChanged(int status, int cameraId) throws RemoteException { 75270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin synchronized(CameraManager.this.mLock) { 753bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala onStatusChangedLocked(status, String.valueOf(cameraId)); 754bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala } 755bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala } 756e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 757bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala public void onStatusChangedLocked(int status, String id) { 758bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala if (DEBUG) { 759e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin Log.v(TAG, 760bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala String.format("Camera id %s has status changed to 0x%x", id, status)); 761bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala } 762e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 763bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala if (!validStatus(status)) { 764bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala Log.e(TAG, String.format("Ignoring invalid device %s status 0x%x", id, 765bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala status)); 766bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala return; 767bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala } 768e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 769bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala Integer oldStatus = mDeviceStatus.put(id, status); 770e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 771bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala if (oldStatus != null && oldStatus == status) { 772bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala if (DEBUG) { 773e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin Log.v(TAG, String.format( 774bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala "Device status changed to 0x%x, which is what it already was", 775bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala status)); 776e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin } 777bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala return; 778bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala } 779e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 780bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala // TODO: consider abstracting out this state minimization + transition 781bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala // into a separate 782bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala // more easily testable class 783bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala // i.e. (new State()).addState(STATE_AVAILABLE) 784bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala // .addState(STATE_NOT_AVAILABLE) 785bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala // .addTransition(STATUS_PRESENT, STATE_AVAILABLE), 786bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala // .addTransition(STATUS_NOT_PRESENT, STATE_NOT_AVAILABLE) 787bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala // .addTransition(STATUS_ENUMERATING, STATE_NOT_AVAILABLE); 788bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala // .addTransition(STATUS_NOT_AVAILABLE, STATE_NOT_AVAILABLE); 789bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala 790bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala // Translate all the statuses to either 'available' or 'not available' 791bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala // available -> available => no new update 792bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala // not available -> not available => no new update 793bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala if (oldStatus != null && isAvailable(status) == isAvailable(oldStatus)) { 794bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala if (DEBUG) { 795e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin Log.v(TAG, 796e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin String.format( 797bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala "Device status was previously available (%d), " + 798bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala " and is now again available (%d)" + 799bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala "so no new client visible update will be sent", 800bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala isAvailable(status), isAvailable(status))); 801e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin } 802bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala return; 803bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala } 804bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala 805fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala final int callbackCount = mCallbackMap.size(); 806fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala for (int i = 0; i < callbackCount; i++) { 807fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala Handler handler = mCallbackMap.valueAt(i); 808fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala final AvailabilityCallback callback = mCallbackMap.keyAt(i); 809bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala 810fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala postSingleUpdate(callback, handler, id, status); 811bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala } 812bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala } // onStatusChangedLocked 813e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 814e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin } // CameraServiceListener 815e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin} // CameraManager 816