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 198b905578b54041f7d0b8dc04dd158d16d28262a1Eino-Ville Talvalaimport android.annotation.RequiresPermission; 208b905578b54041f7d0b8dc04dd158d16d28262a1Eino-Ville Talvalaimport android.annotation.NonNull; 218b905578b54041f7d0b8dc04dd158d16d28262a1Eino-Ville Talvalaimport android.annotation.Nullable; 22e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkinimport android.content.Context; 23e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkinimport android.hardware.ICameraService; 24e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkinimport android.hardware.ICameraServiceListener; 254961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkinimport android.hardware.CameraInfo; 2670c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvalaimport android.hardware.camera2.impl.CameraMetadataNative; 27feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.hardware.camera2.legacy.CameraDeviceUserShim; 284961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkinimport android.hardware.camera2.legacy.LegacyMetadataMapper; 29e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkinimport android.os.IBinder; 30afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chenimport android.os.Binder; 315d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvalaimport android.os.DeadObjectException; 324af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvalaimport android.os.Handler; 334af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvalaimport android.os.Looper; 34e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkinimport android.os.RemoteException; 35e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkinimport android.os.ServiceManager; 365d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvalaimport android.os.ServiceSpecificException; 37e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkinimport android.util.Log; 384af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvalaimport android.util.ArrayMap; 39e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 40e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkinimport java.util.ArrayList; 41e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 42b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala/** 43b67a3b36fd569e63c1b8ca6b2701c34c7a3927c1Eino-Ville Talvala * <p>A system service manager for detecting, characterizing, and connecting to 44b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * {@link CameraDevice CameraDevices}.</p> 45b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * 46b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * <p>You can get an instance of this class by calling 47b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * {@link android.content.Context#getSystemService(String) Context.getSystemService()}.</p> 48b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * 49b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * <pre>CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);</pre> 50b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * 51b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * <p>For more details about communicating with camera devices, read the Camera 522f1a2e423e0fbb64467d6fcfa4e82c6384f31210Eino-Ville Talvala * developer guide or the {@link android.hardware.camera2 camera2} 53b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * package documentation.</p> 54b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala */ 55b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvalapublic final class CameraManager { 56b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala 5785c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk private static final String TAG = "CameraManager"; 58a78791f22af6c6985d186494737468bb19b69540Eino-Ville Talvala private final boolean DEBUG = false; 5985c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk 60e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin private static final int USE_CALLING_UID = -1; 61e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 624961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin @SuppressWarnings("unused") 634961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin private static final int API_VERSION_1 = 1; 644961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin private static final int API_VERSION_2 = 2; 654961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin 665717612ba9ac78021e81f5b45ca7903c318499f9Eino-Ville Talvala private static final int CAMERA_TYPE_BACKWARD_COMPATIBLE = 0; 675717612ba9ac78021e81f5b45ca7903c318499f9Eino-Ville Talvala private static final int CAMERA_TYPE_ALL = 1; 685717612ba9ac78021e81f5b45ca7903c318499f9Eino-Ville Talvala 69e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin private ArrayList<String> mDeviceIdList; 704af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala 71e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin private final Context mContext; 72e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin private final Object mLock = new Object(); 73e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 74e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin /** 75b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * @hide 76b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala */ 77e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin public CameraManager(Context context) { 78bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala synchronized(mLock) { 79bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala mContext = context; 80e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin } 81b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala } 82b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala 83b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala /** 840f2be13dc691ff087d1705b7ea632654cc06c383Ruben Brunk * Return the list of currently connected camera devices by identifier, including 850f2be13dc691ff087d1705b7ea632654cc06c383Ruben Brunk * cameras that may be in use by other camera API clients. 864af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala * 874af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala * <p>Non-removable cameras use integers starting at 0 for their 88b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * identifiers, while removable cameras have a unique identifier for each 89b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * individual device, even if they are the same model.</p> 90b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * 91b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * @return The list of currently connected camera devices. 92b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala */ 938b905578b54041f7d0b8dc04dd158d16d28262a1Eino-Ville Talvala @NonNull 944af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala public String[] getCameraIdList() throws CameraAccessException { 95e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin synchronized (mLock) { 96bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala // ID list creation handles various known failures in device enumeration, so only 97bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala // exceptions it'll throw are unexpected, and should be propagated upward. 98bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala return getOrCreateDeviceIdListLocked().toArray(new String[0]); 99e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin } 100b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala } 101b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala 102b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala /** 103fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala * Register a callback to be notified about camera device availability. 104b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * 105fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala * <p>Registering the same callback again will replace the handler with the 1064af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala * new one provided.</p> 107e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin * 108fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala * <p>The first time a callback is registered, it is immediately called 109bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala * with the availability status of all currently known camera devices.</p> 110bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala * 1110f2be13dc691ff087d1705b7ea632654cc06c383Ruben Brunk * <p>{@link AvailabilityCallback#onCameraUnavailable(String)} will be called whenever a camera 1120f2be13dc691ff087d1705b7ea632654cc06c383Ruben Brunk * device is opened by any camera API client. As of API level 23, other camera API clients may 1130f2be13dc691ff087d1705b7ea632654cc06c383Ruben Brunk * still be able to open such a camera device, evicting the existing client if they have higher 1140f2be13dc691ff087d1705b7ea632654cc06c383Ruben Brunk * priority than the existing client of a camera device. See open() for more details.</p> 1150f2be13dc691ff087d1705b7ea632654cc06c383Ruben Brunk * 1164c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala * <p>Since this callback will be registered with the camera service, remember to unregister it 1174c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala * once it is no longer needed; otherwise the callback will continue to receive events 1184c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala * indefinitely and it may prevent other resources from being released. Specifically, the 1194c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala * callbacks will be invoked independently of the general activity lifecycle and independently 1204c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala * of the state of individual CameraManager instances.</p> 1214c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala * 122fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala * @param callback the new callback to send camera availability notices to 123c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * @param handler The handler on which the callback should be invoked, or {@code null} to use 124c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * the current thread's {@link android.os.Looper looper}. 125c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * 126c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * @throws IllegalArgumentException if the handler is {@code null} but the current thread has 127c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * no looper. 128b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala */ 1298b905578b54041f7d0b8dc04dd158d16d28262a1Eino-Ville Talvala public void registerAvailabilityCallback(@NonNull AvailabilityCallback callback, 1308b905578b54041f7d0b8dc04dd158d16d28262a1Eino-Ville Talvala @Nullable Handler handler) { 1314af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala if (handler == null) { 1324af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala Looper looper = Looper.myLooper(); 1334af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala if (looper == null) { 1344af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala throw new IllegalArgumentException( 1354af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala "No handler given, and current thread has no looper!"); 1364af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala } 1374af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala handler = new Handler(looper); 1384af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala } 1394af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala 1404c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala CameraManagerGlobal.get().registerAvailabilityCallback(callback, handler); 141b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala } 142b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala 143b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala /** 144fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala * Remove a previously-added callback; the callback will no longer receive connection and 145fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala * disconnection callbacks. 146b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * 147fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala * <p>Removing a callback that isn't registered has no effect.</p> 148e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin * 149fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala * @param callback The callback to remove from the notification list 150b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala */ 1518b905578b54041f7d0b8dc04dd158d16d28262a1Eino-Ville Talvala public void unregisterAvailabilityCallback(@NonNull AvailabilityCallback callback) { 1524c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala CameraManagerGlobal.get().unregisterAvailabilityCallback(callback); 153b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala } 154b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala 155b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala /** 156c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * Register a callback to be notified about torch mode status. 157c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * 158c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * <p>Registering the same callback again will replace the handler with the 159c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * new one provided.</p> 160c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * 161c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * <p>The first time a callback is registered, it is immediately called 1625398a676809faaf3c6c2875edc1907ad6b8e1c89Chien-Yu Chen * with the torch mode status of all currently known camera devices with a flash unit.</p> 163c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * 164c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * <p>Since this callback will be registered with the camera service, remember to unregister it 165c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * once it is no longer needed; otherwise the callback will continue to receive events 166c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * indefinitely and it may prevent other resources from being released. Specifically, the 167c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * callbacks will be invoked independently of the general activity lifecycle and independently 168c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * of the state of individual CameraManager instances.</p> 169c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * 170c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * @param callback The new callback to send torch mode status to 171c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * @param handler The handler on which the callback should be invoked, or {@code null} to use 172c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * the current thread's {@link android.os.Looper looper}. 173c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * 174c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * @throws IllegalArgumentException if the handler is {@code null} but the current thread has 175c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * no looper. 176c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen */ 1778b905578b54041f7d0b8dc04dd158d16d28262a1Eino-Ville Talvala public void registerTorchCallback(@NonNull TorchCallback callback, @Nullable Handler handler) { 178afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen if (handler == null) { 179afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen Looper looper = Looper.myLooper(); 180afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen if (looper == null) { 181afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen throw new IllegalArgumentException( 182afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen "No handler given, and current thread has no looper!"); 183afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen } 184afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen handler = new Handler(looper); 185afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen } 186afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen CameraManagerGlobal.get().registerTorchCallback(callback, handler); 187c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen } 188c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen 189c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen /** 190c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * Remove a previously-added callback; the callback will no longer receive torch mode status 191c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * callbacks. 192c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * 193c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * <p>Removing a callback that isn't registered has no effect.</p> 194c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * 195c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * @param callback The callback to remove from the notification list 196c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen */ 1978b905578b54041f7d0b8dc04dd158d16d28262a1Eino-Ville Talvala public void unregisterTorchCallback(@NonNull TorchCallback callback) { 198afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen CameraManagerGlobal.get().unregisterTorchCallback(callback); 199c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen } 200c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen 201c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen /** 202b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * <p>Query the capabilities of a camera device. These capabilities are 203b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * immutable for a given camera.</p> 204b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * 205b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * @param cameraId The id of the camera device to query 206b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * @return The properties of the given camera 207b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * 208b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * @throws IllegalArgumentException if the cameraId does not match any 209bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala * known camera device. 2108b905578b54041f7d0b8dc04dd158d16d28262a1Eino-Ville Talvala * @throws CameraAccessException if the camera device has been disconnected. 211b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * 2124af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala * @see #getCameraIdList 213b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * @see android.app.admin.DevicePolicyManager#setCameraDisabled 214b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala */ 2158b905578b54041f7d0b8dc04dd158d16d28262a1Eino-Ville Talvala @NonNull 2168b905578b54041f7d0b8dc04dd158d16d28262a1Eino-Ville Talvala public CameraCharacteristics getCameraCharacteristics(@NonNull String cameraId) 217b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala throws CameraAccessException { 218bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala CameraCharacteristics characteristics = null; 219e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 220e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin synchronized (mLock) { 221e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin if (!getOrCreateDeviceIdListLocked().contains(cameraId)) { 222e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin throw new IllegalArgumentException(String.format("Camera id %s does not match any" + 223e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin " currently connected camera device", cameraId)); 224e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin } 225e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 226a09b4d2a611a7606e8fc8c73a24bd941b6fc173fNarayan Kamath int id = Integer.parseInt(cameraId); 2274961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin 228bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala /* 229bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala * Get the camera characteristics from the camera service directly if it supports it, 230bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala * otherwise get them from the legacy shim instead. 231bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala */ 2324961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin 2334c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala ICameraService cameraService = CameraManagerGlobal.get().getCameraService(); 234bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala if (cameraService == null) { 235bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala throw new CameraAccessException(CameraAccessException.CAMERA_DISCONNECTED, 236bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala "Camera service is currently unavailable"); 237bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala } 2384961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin try { 239bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala if (!supportsCamera2ApiLocked(cameraId)) { 240bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala // Legacy backwards compatibility path; build static info from the camera 241bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala // parameters 2425d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala String parameters = cameraService.getLegacyParameters(id); 2434961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin 2445d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala CameraInfo info = cameraService.getCameraInfo(id); 2454961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin 246bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala characteristics = LegacyMetadataMapper.createCharacteristics(parameters, info); 247bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala } else { 248bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala // Normal path: Get the camera characteristics directly from the camera service 2495d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala CameraMetadataNative info = cameraService.getCameraCharacteristics(id); 250bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala 251bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala characteristics = new CameraCharacteristics(info); 252bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala } 2535d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala } catch (ServiceSpecificException e) { 2545d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala throwAsPublicException(e); 255bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala } catch (RemoteException e) { 256bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala // Camera service died - act as if the camera was disconnected 257bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala throw new CameraAccessException(CameraAccessException.CAMERA_DISCONNECTED, 258bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala "Camera service is currently unavailable", e); 2594961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin } 2602001188be30649198972a3199a4322d6f7f5f93dZhijun He } 261bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala return characteristics; 262b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala } 263b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala 264b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala /** 2650f2be13dc691ff087d1705b7ea632654cc06c383Ruben Brunk * Helper for opening a connection to a camera with the given ID. 266b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * 267b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * @param cameraId The unique identifier of the camera device to open 268fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala * @param callback The callback for the camera. Must not be null. 269fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala * @param handler The handler to invoke the callback on. Must not be null. 270b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * 271b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * @throws CameraAccessException if the camera is disabled by device policy, 2720f2be13dc691ff087d1705b7ea632654cc06c383Ruben Brunk * too many camera devices are already open, or the cameraId does not match 27366ef64514464a1bb9c7931993cc8db3d7539f39aRuben Brunk * any currently available camera device. 27466ef64514464a1bb9c7931993cc8db3d7539f39aRuben Brunk * 275b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * @throws SecurityException if the application does not have permission to 276b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * access the camera 277fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala * @throws IllegalArgumentException if callback or handler is null. 278cca00c614c24a71dc234c79ad6241efa9f6c7676Eino-Ville Talvala * @return A handle to the newly-created camera device. 279b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * 2804af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala * @see #getCameraIdList 281b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * @see android.app.admin.DevicePolicyManager#setCameraDisabled 282b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala */ 283cca00c614c24a71dc234c79ad6241efa9f6c7676Eino-Ville Talvala private CameraDevice openCameraDeviceUserAsync(String cameraId, 284fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala CameraDevice.StateCallback callback, Handler handler) 285868d904306c6a96d94fa0da03515c51c86eefc63Eino-Ville Talvala throws CameraAccessException { 286574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk CameraCharacteristics characteristics = getCameraCharacteristics(cameraId); 287cca00c614c24a71dc234c79ad6241efa9f6c7676Eino-Ville Talvala CameraDevice device = null; 288e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 2895d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala synchronized (mLock) { 29070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin 2915d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala ICameraDeviceUser cameraUser = null; 29270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin 2935d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala android.hardware.camera2.impl.CameraDeviceImpl deviceImpl = 2945d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala new android.hardware.camera2.impl.CameraDeviceImpl( 2955d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala cameraId, 2965d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala callback, 2975d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala handler, 2985d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala characteristics); 29970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin 3005d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala ICameraDeviceCallbacks callbacks = deviceImpl.getCallbacks(); 301feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 3025d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala int id; 3035d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala try { 3045d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala id = Integer.parseInt(cameraId); 3055d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala } catch (NumberFormatException e) { 3065d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala throw new IllegalArgumentException("Expected cameraId to be numeric, but it was: " 3075d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala + cameraId); 3085d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala } 3095d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala 3105d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala try { 3115d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala if (supportsCamera2ApiLocked(cameraId)) { 3125d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala // Use cameraservice's cameradeviceclient implementation for HAL3.2+ devices 3135d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala ICameraService cameraService = CameraManagerGlobal.get().getCameraService(); 3145d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala if (cameraService == null) { 3155d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala throw new ServiceSpecificException( 3165d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala ICameraService.ERROR_DISCONNECTED, 3175d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala "Camera service is currently unavailable"); 318a1d662716b3da384dfe3a758f079e0cbd089784aIgor Murashkin } 3195d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala cameraUser = cameraService.connectDevice(callbacks, id, 3205d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala mContext.getOpPackageName(), USE_CALLING_UID); 3215d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala } else { 3225d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala // Use legacy camera implementation for HAL1 devices 3235d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala Log.i(TAG, "Using legacy camera HAL."); 3245d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala cameraUser = CameraDeviceUserShim.connectBinderShim(callbacks, id); 3255d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala } 3265d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala } catch (ServiceSpecificException e) { 3275d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala if (e.errorCode == ICameraService.ERROR_DEPRECATED_HAL) { 3285d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala throw new AssertionError("Should've gone down the shim path"); 3295d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala } else if (e.errorCode == ICameraService.ERROR_CAMERA_IN_USE || 3305d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala e.errorCode == ICameraService.ERROR_MAX_CAMERAS_IN_USE || 3315d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala e.errorCode == ICameraService.ERROR_DISABLED || 3325d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala e.errorCode == ICameraService.ERROR_DISCONNECTED || 3335d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala e.errorCode == ICameraService.ERROR_INVALID_OPERATION) { 3345d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala // Received one of the known connection errors 3355d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala // The remote camera device cannot be connected to, so 3365d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala // set the local camera to the startup error state 3375d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala deviceImpl.setRemoteFailure(e); 3385d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala 3395d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala if (e.errorCode == ICameraService.ERROR_DISABLED || 3405d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala e.errorCode == ICameraService.ERROR_DISCONNECTED || 3415d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala e.errorCode == ICameraService.ERROR_CAMERA_IN_USE) { 3425d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala // Per API docs, these failures call onError and throw 3435d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala throwAsPublicException(e); 344feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 3455d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala } else { 3465d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala // Unexpected failure - rethrow 3475d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala throwAsPublicException(e); 348feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 3495d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala } catch (RemoteException e) { 3505d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala // Camera service died - act as if it's a CAMERA_DISCONNECTED case 3515d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala ServiceSpecificException sse = new ServiceSpecificException( 3525d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala ICameraService.ERROR_DISCONNECTED, 3535d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala "Camera service is currently unavailable"); 3545d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala deviceImpl.setRemoteFailure(sse); 3555d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala throwAsPublicException(sse); 356e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin } 357e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 3585d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala // TODO: factor out callback to be non-nested, then move setter to constructor 3595d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala // For now, calling setRemoteDevice will fire initial 3605d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala // onOpened/onUnconfigured callbacks. 361783929368b554b1fc85da81137e1762fb939c4d7Shuzhen Wang // This function call may post onDisconnected and throw CAMERA_DISCONNECTED if 362783929368b554b1fc85da81137e1762fb939c4d7Shuzhen Wang // cameraUser dies during setup. 3635d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala deviceImpl.setRemoteDevice(cameraUser); 3645d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala device = deviceImpl; 365e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin } 3665d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala 367cca00c614c24a71dc234c79ad6241efa9f6c7676Eino-Ville Talvala return device; 368b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala } 369b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala 370b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala /** 3715c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin * Open a connection to a camera with the given ID. 3725c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin * 3735c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin * <p>Use {@link #getCameraIdList} to get the list of available camera 3745c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin * devices. Note that even if an id is listed, open may fail if the device 3755c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin * is disconnected between the calls to {@link #getCameraIdList} and 3760f2be13dc691ff087d1705b7ea632654cc06c383Ruben Brunk * {@link #openCamera}, or if a higher-priority camera API client begins using the 3770f2be13dc691ff087d1705b7ea632654cc06c383Ruben Brunk * camera device.</p> 3780f2be13dc691ff087d1705b7ea632654cc06c383Ruben Brunk * 3790f2be13dc691ff087d1705b7ea632654cc06c383Ruben Brunk * <p>As of API level 23, devices for which the 3800f2be13dc691ff087d1705b7ea632654cc06c383Ruben Brunk * {@link AvailabilityCallback#onCameraUnavailable(String)} callback has been called due to the 3810f2be13dc691ff087d1705b7ea632654cc06c383Ruben Brunk * device being in use by a lower-priority, background camera API client can still potentially 3820f2be13dc691ff087d1705b7ea632654cc06c383Ruben Brunk * be opened by calling this method when the calling camera API client has a higher priority 3830f2be13dc691ff087d1705b7ea632654cc06c383Ruben Brunk * than the current camera API client using this device. In general, if the top, foreground 3840f2be13dc691ff087d1705b7ea632654cc06c383Ruben Brunk * activity is running within your application process, your process will be given the highest 3850f2be13dc691ff087d1705b7ea632654cc06c383Ruben Brunk * priority when accessing the camera, and this method will succeed even if the camera device is 3860f2be13dc691ff087d1705b7ea632654cc06c383Ruben Brunk * in use by another camera API client. Any lower-priority application that loses control of the 3870f2be13dc691ff087d1705b7ea632654cc06c383Ruben Brunk * camera in this way will receive an 3880f2be13dc691ff087d1705b7ea632654cc06c383Ruben Brunk * {@link android.hardware.camera2.CameraDevice.StateCallback#onDisconnected} callback.</p> 3895c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin * 390fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala * <p>Once the camera is successfully opened, {@link CameraDevice.StateCallback#onOpened} will 391cca00c614c24a71dc234c79ad6241efa9f6c7676Eino-Ville Talvala * be invoked with the newly opened {@link CameraDevice}. The camera device can then be set up 392cca00c614c24a71dc234c79ad6241efa9f6c7676Eino-Ville Talvala * for operation by calling {@link CameraDevice#createCaptureSession} and 393cca00c614c24a71dc234c79ad6241efa9f6c7676Eino-Ville Talvala * {@link CameraDevice#createCaptureRequest}</p> 3945c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin * 395cca00c614c24a71dc234c79ad6241efa9f6c7676Eino-Ville Talvala * <!-- 396cca00c614c24a71dc234c79ad6241efa9f6c7676Eino-Ville Talvala * <p>Since the camera device will be opened asynchronously, any asynchronous operations done 397cca00c614c24a71dc234c79ad6241efa9f6c7676Eino-Ville Talvala * on the returned CameraDevice instance will be queued up until the device startup has 398fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala * completed and the callback's {@link CameraDevice.StateCallback#onOpened onOpened} method is 399cca00c614c24a71dc234c79ad6241efa9f6c7676Eino-Ville Talvala * called. The pending operations are then processed in order.</p> 400cca00c614c24a71dc234c79ad6241efa9f6c7676Eino-Ville Talvala * --> 4015c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin * <p>If the camera becomes disconnected during initialization 4025c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin * after this function call returns, 403fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala * {@link CameraDevice.StateCallback#onDisconnected} with a 4045c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin * {@link CameraDevice} in the disconnected state (and 405fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala * {@link CameraDevice.StateCallback#onOpened} will be skipped).</p> 4065c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin * 407fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala * <p>If opening the camera device fails, then the device callback's 408fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala * {@link CameraDevice.StateCallback#onError onError} method will be called, and subsequent 4097fcb357811d4dc1f44624e30ad924e9e580d4cbfEino-Ville Talvala * calls on the camera device will throw a {@link CameraAccessException}.</p> 4105c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin * 4115c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin * @param cameraId 4125c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin * The unique identifier of the camera device to open 413fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala * @param callback 414fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala * The callback which is invoked once the camera is opened 4155c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin * @param handler 416fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala * The handler on which the callback should be invoked, or 4175c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin * {@code null} to use the current thread's {@link android.os.Looper looper}. 4185c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin * 4195c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin * @throws CameraAccessException if the camera is disabled by device policy, 4200f2be13dc691ff087d1705b7ea632654cc06c383Ruben Brunk * has been disconnected, or is being used by a higher-priority camera API client. 4215c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin * 422fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala * @throws IllegalArgumentException if cameraId or the callback was null, 4235c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin * or the cameraId does not match any currently or previously available 4245c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin * camera device. 4255c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin * 4265c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin * @throws SecurityException if the application does not have permission to 4275c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin * access the camera 4285c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin * 4295c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin * @see #getCameraIdList 4305c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin * @see android.app.admin.DevicePolicyManager#setCameraDisabled 4315c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin */ 4328b905578b54041f7d0b8dc04dd158d16d28262a1Eino-Ville Talvala @RequiresPermission(android.Manifest.permission.CAMERA) 4338b905578b54041f7d0b8dc04dd158d16d28262a1Eino-Ville Talvala public void openCamera(@NonNull String cameraId, 4348b905578b54041f7d0b8dc04dd158d16d28262a1Eino-Ville Talvala @NonNull final CameraDevice.StateCallback callback, @Nullable Handler handler) 4355c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin throws CameraAccessException { 4365c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin 4375c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin if (cameraId == null) { 4385c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin throw new IllegalArgumentException("cameraId was null"); 439fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala } else if (callback == null) { 440fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala throw new IllegalArgumentException("callback was null"); 4415c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin } else if (handler == null) { 4425c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin if (Looper.myLooper() != null) { 4435c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin handler = new Handler(); 4445c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin } else { 4455c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin throw new IllegalArgumentException( 4468b905578b54041f7d0b8dc04dd158d16d28262a1Eino-Ville Talvala "Handler argument is null, but no looper exists in the calling thread"); 4475c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin } 4485c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin } 4495c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin 450fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala openCameraDeviceUserAsync(cameraId, callback, handler); 4515c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin } 4525c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin 4535c9eaf6796a4c972710dd5cd23cdfa334fa8ad2eIgor Murashkin /** 454c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * Set the flash unit's torch mode of the camera of the given ID without opening the camera 455c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * device. 456c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * 457c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * <p>Use {@link #getCameraIdList} to get the list of available camera devices and use 458c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * {@link #getCameraCharacteristics} to check whether the camera device has a flash unit. 459c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * Note that even if a camera device has a flash unit, turning on the torch mode may fail 460c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * if the camera device or other camera resources needed to turn on the torch mode are in use. 461c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * </p> 462c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * 463c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * <p> If {@link #setTorchMode} is called to turn on or off the torch mode successfully, 464c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * {@link CameraManager.TorchCallback#onTorchModeChanged} will be invoked. 465c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * However, even if turning on the torch mode is successful, the application does not have the 466c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * exclusive ownership of the flash unit or the camera device. The torch mode will be turned 467c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * off and becomes unavailable when the camera device that the flash unit belongs to becomes 468afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen * unavailable or when other camera resources to keep the torch on become unavailable ( 469c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * {@link CameraManager.TorchCallback#onTorchModeUnavailable} will be invoked). Also, 470c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * other applications are free to call {@link #setTorchMode} to turn off the torch mode ( 471afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen * {@link CameraManager.TorchCallback#onTorchModeChanged} will be invoked). If the latest 472afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen * application that turned on the torch mode exits, the torch mode will be turned off. 473c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * 474c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * @param cameraId 475c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * The unique identifier of the camera device that the flash unit belongs to. 476c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * @param enabled 477c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * The desired state of the torch mode for the target camera device. Set to 478c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * {@code true} to turn on the torch mode. Set to {@code false} to turn off the 479c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * torch mode. 480c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * 481c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * @throws CameraAccessException if it failed to access the flash unit. 482c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * {@link CameraAccessException#CAMERA_IN_USE} will be thrown if the camera device 483c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * is in use. {@link CameraAccessException#MAX_CAMERAS_IN_USE} will be thrown if 484c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * other camera resources needed to turn on the torch mode are in use. 485afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen * {@link CameraAccessException#CAMERA_DISCONNECTED} will be thrown if camera 486afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen * service is not available. 487c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * 488c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * @throws IllegalArgumentException if cameraId was null, cameraId doesn't match any currently 489c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * or previously available camera device, or the camera device doesn't have a 490c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * flash unit. 491c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen */ 4928b905578b54041f7d0b8dc04dd158d16d28262a1Eino-Ville Talvala public void setTorchMode(@NonNull String cameraId, boolean enabled) 4938b905578b54041f7d0b8dc04dd158d16d28262a1Eino-Ville Talvala throws CameraAccessException { 494afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen CameraManagerGlobal.get().setTorchMode(cameraId, enabled); 495c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen } 496c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen 497c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen /** 4980f2be13dc691ff087d1705b7ea632654cc06c383Ruben Brunk * A callback for camera devices becoming available or unavailable to open. 4994af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala * 5004af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala * <p>Cameras become available when they are no longer in use, or when a new 501b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * removable camera is connected. They become unavailable when some 502b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * application or service starts using a camera, or when a removable camera 5034af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala * is disconnected.</p> 5044af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala * 505fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala * <p>Extend this callback and pass an instance of the subclass to 506fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala * {@link CameraManager#registerAvailabilityCallback} to be notified of such availability 507b67a3b36fd569e63c1b8ca6b2701c34c7a3927c1Eino-Ville Talvala * changes.</p> 508b67a3b36fd569e63c1b8ca6b2701c34c7a3927c1Eino-Ville Talvala * 50985e1d5045cfcf88592753ce92fb6510b27445932Philip P. Moltmann * @see #registerAvailabilityCallback 510b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala */ 511fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala public static abstract class AvailabilityCallback { 5124af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala 513b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala /** 514b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * A new camera has become available to use. 515b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * 5164af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala * <p>The default implementation of this method does nothing.</p> 5174af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala * 518b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * @param cameraId The unique identifier of the new camera. 519b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala */ 5208b905578b54041f7d0b8dc04dd158d16d28262a1Eino-Ville Talvala public void onCameraAvailable(@NonNull String cameraId) { 5214af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala // default empty implementation 5224af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala } 523b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala 524b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala /** 5254af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala * A previously-available camera has become unavailable for use. 5264af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala * 5274af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala * <p>If an application had an active CameraDevice instance for the 5284af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala * now-disconnected camera, that application will receive a 529fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala * {@link CameraDevice.StateCallback#onDisconnected disconnection error}.</p> 5304af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala * 5314af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala * <p>The default implementation of this method does nothing.</p> 532b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * 533b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala * @param cameraId The unique identifier of the disconnected camera. 534b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala */ 5358b905578b54041f7d0b8dc04dd158d16d28262a1Eino-Ville Talvala public void onCameraUnavailable(@NonNull String cameraId) { 5364af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala // default empty implementation 5374af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala } 538b2675542c2f414154125b534767ae0903fba581eEino-Ville Talvala } 539e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 540bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala /** 541afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen * A callback for camera flash torch modes becoming unavailable, disabled, or enabled. 542c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * 543afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen * <p>The torch mode becomes unavailable when the camera device it belongs to becomes 5445398a676809faaf3c6c2875edc1907ad6b8e1c89Chien-Yu Chen * unavailable or other camera resources it needs become busy due to other higher priority 545afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen * camera activities. The torch mode becomes disabled when it was turned off or when the camera 546afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen * device it belongs to is no longer in use and other camera resources it needs are no longer 547afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen * busy. A camera's torch mode is turned off when an application calls {@link #setTorchMode} to 548afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen * turn off the camera's torch mode, or when an application turns on another camera's torch mode 549afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen * if keeping multiple torch modes on simultaneously is not supported. The torch mode becomes 550afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen * enabled when it is turned on via {@link #setTorchMode}.</p> 551afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen * 552afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen * <p>The torch mode is available to set via {@link #setTorchMode} only when it's in a disabled 553afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen * or enabled state.</p> 554c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * 555c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * <p>Extend this callback and pass an instance of the subclass to 556c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * {@link CameraManager#registerTorchCallback} to be notified of such status changes. 557c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * </p> 558c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * 5598062d31d27943da4d652878b4c36aeabb8bb8b08Chien-Yu Chen * @see #registerTorchCallback 560c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen */ 561c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen public static abstract class TorchCallback { 562c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen /** 563afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen * A camera's torch mode has become unavailable to set via {@link #setTorchMode}. 564c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * 565c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * <p>If torch mode was previously turned on by calling {@link #setTorchMode}, it will be 566c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * turned off before {@link CameraManager.TorchCallback#onTorchModeUnavailable} is 567afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen * invoked. {@link #setTorchMode} will fail until the torch mode has entered a disabled or 568afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen * enabled state again.</p> 569c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * 570c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * <p>The default implementation of this method does nothing.</p> 571c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * 572c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * @param cameraId The unique identifier of the camera whose torch mode has become 573c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * unavailable. 574c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen */ 5758b905578b54041f7d0b8dc04dd158d16d28262a1Eino-Ville Talvala public void onTorchModeUnavailable(@NonNull String cameraId) { 576c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen // default empty implementation 577c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen } 578c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen 579c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen /** 580afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen * A camera's torch mode has become enabled or disabled and can be changed via 581afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen * {@link #setTorchMode}. 582c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * 583c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * <p>The default implementation of this method does nothing.</p> 584c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * 585c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * @param cameraId The unique identifier of the camera whose torch mode has been changed. 586c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * 587c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen * @param enabled The state that the torch mode of the camera has been changed to. 588afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen * {@code true} when the torch mode has become on and available to be turned 589afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen * off. {@code false} when the torch mode has becomes off and available to 590afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen * be turned on. 591c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen */ 5928b905578b54041f7d0b8dc04dd158d16d28262a1Eino-Ville Talvala public void onTorchModeChanged(@NonNull String cameraId, boolean enabled) { 593c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen // default empty implementation 594c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen } 595c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen } 596c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen 597c8c109b4030c1a80f0572d32311e24d1c4b0e03dChien-Yu Chen /** 5985d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala * Convert ServiceSpecificExceptions and Binder RemoteExceptions from camera binder interfaces 5995d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala * into the correct public exceptions. 6005d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala * 6015d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala * @hide 6025d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala */ 6035d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala public static void throwAsPublicException(Throwable t) throws CameraAccessException { 6045d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala if (t instanceof ServiceSpecificException) { 6055d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala ServiceSpecificException e = (ServiceSpecificException) t; 6065d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala int reason = CameraAccessException.CAMERA_ERROR; 6075d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala switch(e.errorCode) { 6085d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala case ICameraService.ERROR_DISCONNECTED: 6095d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala reason = CameraAccessException.CAMERA_DISCONNECTED; 6105d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala break; 6115d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala case ICameraService.ERROR_DISABLED: 6125d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala reason = CameraAccessException.CAMERA_DISABLED; 6135d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala break; 6145d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala case ICameraService.ERROR_CAMERA_IN_USE: 6155d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala reason = CameraAccessException.CAMERA_IN_USE; 6165d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala break; 6175d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala case ICameraService.ERROR_MAX_CAMERAS_IN_USE: 6185d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala reason = CameraAccessException.MAX_CAMERAS_IN_USE; 6195d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala break; 6205d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala case ICameraService.ERROR_DEPRECATED_HAL: 6215d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala reason = CameraAccessException.CAMERA_DEPRECATED_HAL; 6225d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala break; 6235d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala case ICameraService.ERROR_ILLEGAL_ARGUMENT: 6245d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala case ICameraService.ERROR_ALREADY_EXISTS: 6255d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala throw new IllegalArgumentException(e.getMessage(), e); 6265d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala case ICameraService.ERROR_PERMISSION_DENIED: 6275d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala throw new SecurityException(e.getMessage(), e); 6285d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala case ICameraService.ERROR_TIMED_OUT: 6295d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala case ICameraService.ERROR_INVALID_OPERATION: 6305d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala default: 6315d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala reason = CameraAccessException.CAMERA_ERROR; 6325d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala } 6335d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala throw new CameraAccessException(reason, e.getMessage(), e); 6345d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala } else if (t instanceof DeadObjectException) { 6355d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala throw new CameraAccessException(CameraAccessException.CAMERA_DISCONNECTED, 6365d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala "Camera service has died unexpectedly", 6375d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala t); 6385d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala } else if (t instanceof RemoteException) { 6395d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala throw new UnsupportedOperationException("An unknown RemoteException was thrown" + 6405d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala " which should never happen.", t); 6415d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala } else if (t instanceof RuntimeException) { 6425d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala RuntimeException e = (RuntimeException) t; 6435d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala throw e; 6445d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala } 6455d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala } 6465d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala 6475d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala /** 648bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala * Return or create the list of currently connected camera devices. 649bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala * 650bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala * <p>In case of errors connecting to the camera service, will return an empty list.</p> 651bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala */ 652e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin private ArrayList<String> getOrCreateDeviceIdListLocked() throws CameraAccessException { 653e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin if (mDeviceIdList == null) { 654e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin int numCameras = 0; 6554c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala ICameraService cameraService = CameraManagerGlobal.get().getCameraService(); 656bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala ArrayList<String> deviceIdList = new ArrayList<>(); 657bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala 658bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala // If no camera service, then no devices 659bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala if (cameraService == null) { 660bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala return deviceIdList; 661bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala } 662e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 663e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin try { 6645717612ba9ac78021e81f5b45ca7903c318499f9Eino-Ville Talvala numCameras = cameraService.getNumberOfCameras(CAMERA_TYPE_ALL); 6655d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala } catch(ServiceSpecificException e) { 6665d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala throwAsPublicException(e); 667e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin } catch (RemoteException e) { 668bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala // camera service just died - if no camera service, then no devices 669bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala return deviceIdList; 670e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin } 671e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 672e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin for (int i = 0; i < numCameras; ++i) { 673e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin // Non-removable cameras use integers starting at 0 for their 674e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin // identifiers 67518fe0ae08d49b0fe4b6414a3841bd0fcab5419e8Zhijun He boolean isDeviceSupported = false; 67618fe0ae08d49b0fe4b6414a3841bd0fcab5419e8Zhijun He try { 6775d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala CameraMetadataNative info = cameraService.getCameraCharacteristics(i); 67818fe0ae08d49b0fe4b6414a3841bd0fcab5419e8Zhijun He if (!info.isEmpty()) { 67918fe0ae08d49b0fe4b6414a3841bd0fcab5419e8Zhijun He isDeviceSupported = true; 68018fe0ae08d49b0fe4b6414a3841bd0fcab5419e8Zhijun He } else { 68118fe0ae08d49b0fe4b6414a3841bd0fcab5419e8Zhijun He throw new AssertionError("Expected to get non-empty characteristics"); 68218fe0ae08d49b0fe4b6414a3841bd0fcab5419e8Zhijun He } 6835d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala } catch(ServiceSpecificException e) { 684bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala // DISCONNECTED means that the HAL reported an low-level error getting the 6855d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala // device info; ILLEGAL_ARGUMENT means that this devices is not supported. 6865d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala // Skip listing the device. Other errors, 687bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala // propagate exception onward 6885d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala if (e.errorCode != ICameraService.ERROR_DISCONNECTED || 6895d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala e.errorCode != ICameraService.ERROR_ILLEGAL_ARGUMENT) { 6905d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala throwAsPublicException(e); 691bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala } 69218fe0ae08d49b0fe4b6414a3841bd0fcab5419e8Zhijun He } catch(RemoteException e) { 693bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala // Camera service died - no devices to list 694bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala deviceIdList.clear(); 695bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala return deviceIdList; 69618fe0ae08d49b0fe4b6414a3841bd0fcab5419e8Zhijun He } 69718fe0ae08d49b0fe4b6414a3841bd0fcab5419e8Zhijun He 69818fe0ae08d49b0fe4b6414a3841bd0fcab5419e8Zhijun He if (isDeviceSupported) { 699bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala deviceIdList.add(String.valueOf(i)); 700bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala } else { 701bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala Log.w(TAG, "Error querying camera device " + i + " for listing."); 70218fe0ae08d49b0fe4b6414a3841bd0fcab5419e8Zhijun He } 703e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 704bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala } 705bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala mDeviceIdList = deviceIdList; 706e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin } 707e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin return mDeviceIdList; 708e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin } 709e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 7104961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin /** 7114961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin * Queries the camera service if it supports the camera2 api directly, or needs a shim. 7124961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin * 7134961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin * @param cameraId a non-{@code null} camera identifier 7144961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin * @return {@code false} if the legacy shim needs to be used, {@code true} otherwise. 7154961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin */ 716bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala private boolean supportsCamera2ApiLocked(String cameraId) { 717bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala return supportsCameraApiLocked(cameraId, API_VERSION_2); 7184961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin } 7194961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin 7204961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin /** 7214961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin * Queries the camera service if it supports a camera api directly, or needs a shim. 7224961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin * 7234961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin * @param cameraId a non-{@code null} camera identifier 7244961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin * @param apiVersion the version, i.e. {@code API_VERSION_1} or {@code API_VERSION_2} 7254961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin * @return {@code true} if connecting will work for that device version. 7264961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin */ 727bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala private boolean supportsCameraApiLocked(String cameraId, int apiVersion) { 7284961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin int id = Integer.parseInt(cameraId); 7294961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin 7304961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin /* 7314961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin * Possible return values: 732bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala * - NO_ERROR => CameraX API is supported 733bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala * - CAMERA_DEPRECATED_HAL => CameraX API is *not* supported (thrown as an exception) 734bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala * - Remote exception => If the camera service died 7354961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin * 7364961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin * Anything else is an unexpected error we don't want to recover from. 7374961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin */ 7384961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin try { 7394c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala ICameraService cameraService = CameraManagerGlobal.get().getCameraService(); 740bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala // If no camera service, no support 741bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala if (cameraService == null) return false; 742bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala 7435d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala return cameraService.supportsCameraApi(id, apiVersion); 7444961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin } catch (RemoteException e) { 745bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala // Camera service is now down, no support for any API level 746bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala } 747bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala return false; 748bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala } 749bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala 750bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala /** 7514c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala * A per-process global camera manager instance, to retain a connection to the camera service, 7524c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala * and to distribute camera availability notices to API-registered callbacks 753bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala */ 7544c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala private static final class CameraManagerGlobal extends ICameraServiceListener.Stub 7554c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala implements IBinder.DeathRecipient { 7564c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala 7574c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala private static final String TAG = "CameraManagerGlobal"; 758a78791f22af6c6985d186494737468bb19b69540Eino-Ville Talvala private final boolean DEBUG = false; 759bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala 7600f69b4655f635302fd8ce5653888a397723f3accChien-Yu Chen private final int CAMERA_SERVICE_RECONNECT_DELAY_MS = 1000; 7610f69b4655f635302fd8ce5653888a397723f3accChien-Yu Chen 7624c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala // Singleton instance 7634c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala private static final CameraManagerGlobal gCameraManager = 7644c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala new CameraManagerGlobal(); 765bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala 766bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala /** 7674c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala * This must match the ICameraService definition 768bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala */ 7694c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala private static final String CAMERA_SERVICE_BINDER_NAME = "media.camera"; 770e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 771e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin // Camera ID -> Status map 7724af73c2153747d0624ccc75dfa001cb91982957fEino-Ville Talvala private final ArrayMap<String, Integer> mDeviceStatus = new ArrayMap<String, Integer>(); 773e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 7744c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala // Registered availablility callbacks and their handlers 7754c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala private final ArrayMap<AvailabilityCallback, Handler> mCallbackMap = 7764c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala new ArrayMap<AvailabilityCallback, Handler>(); 7774c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala 778afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen // torch client binder to set the torch mode with. 779afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen private Binder mTorchClientBinder = new Binder(); 780afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen 781afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen // Camera ID -> Torch status map 782afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen private final ArrayMap<String, Integer> mTorchStatus = new ArrayMap<String, Integer>(); 783afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen 784afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen // Registered torch callbacks and their handlers 785afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen private final ArrayMap<TorchCallback, Handler> mTorchCallbackMap = 786afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen new ArrayMap<TorchCallback, Handler>(); 787afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen 7884c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala private final Object mLock = new Object(); 7894c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala 7904c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala // Access only through getCameraService to deal with binder death 7914c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala private ICameraService mCameraService; 7924c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala 7934c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala // Singleton, don't allow construction 7944c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala private CameraManagerGlobal() { 7954c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala } 7964c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala 7974c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala public static CameraManagerGlobal get() { 7984c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala return gCameraManager; 7994c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala } 800e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 801e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin @Override 802e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin public IBinder asBinder() { 803e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin return this; 804e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin } 805e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 8064c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala /** 8074c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala * Return a best-effort ICameraService. 8084c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala * 8094c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala * <p>This will be null if the camera service is not currently available. If the camera 8104c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala * service has died since the last use of the camera service, will try to reconnect to the 8114c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala * service.</p> 8124c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala */ 8134c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala public ICameraService getCameraService() { 8144c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala synchronized(mLock) { 8152ef01737afda0c61ede1035d86771b763dcd8a0fEino-Ville Talvala connectCameraServiceLocked(); 8164c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala if (mCameraService == null) { 8172ef01737afda0c61ede1035d86771b763dcd8a0fEino-Ville Talvala Log.e(TAG, "Camera service is unavailable"); 8184c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala } 8194c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala return mCameraService; 8204c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala } 8214c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala } 8224c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala 8234c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala /** 8244c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala * Connect to the camera service if it's available, and set up listeners. 8252ef01737afda0c61ede1035d86771b763dcd8a0fEino-Ville Talvala * If the service is already connected, do nothing. 8264c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala * 8274c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala * <p>Sets mCameraService to a valid pointer or null if the connection does not succeed.</p> 8284c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala */ 8294c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala private void connectCameraServiceLocked() { 8302ef01737afda0c61ede1035d86771b763dcd8a0fEino-Ville Talvala // Only reconnect if necessary 8312ef01737afda0c61ede1035d86771b763dcd8a0fEino-Ville Talvala if (mCameraService != null) return; 8322ef01737afda0c61ede1035d86771b763dcd8a0fEino-Ville Talvala 8332ef01737afda0c61ede1035d86771b763dcd8a0fEino-Ville Talvala Log.i(TAG, "Connecting to camera service"); 8342ef01737afda0c61ede1035d86771b763dcd8a0fEino-Ville Talvala 8354c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala IBinder cameraServiceBinder = ServiceManager.getService(CAMERA_SERVICE_BINDER_NAME); 8364c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala if (cameraServiceBinder == null) { 8374c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala // Camera service is now down, leave mCameraService as null 8384c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala return; 8394c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala } 8404c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala try { 8414c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala cameraServiceBinder.linkToDeath(this, /*flags*/ 0); 8424c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala } catch (RemoteException e) { 8434c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala // Camera service is now down, leave mCameraService as null 8444c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala return; 8454c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala } 8464c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala 8475d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala ICameraService cameraService = ICameraService.Stub.asInterface(cameraServiceBinder); 8484c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala 8494c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala try { 8505d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala CameraMetadataNative.setupGlobalVendorTagDescriptor(); 8515d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala } catch (ServiceSpecificException e) { 8525d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala handleRecoverableSetupErrors(e); 8534c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala } 8544c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala 8554c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala try { 8564c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala cameraService.addListener(this); 8574c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala mCameraService = cameraService; 8585d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala } catch(ServiceSpecificException e) { 8594c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala // Unexpected failure 8605d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala throw new IllegalStateException("Failed to register a camera service listener", e); 8614c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala } catch (RemoteException e) { 8624c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala // Camera service is now down, leave mCameraService as null 8634c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala } 8644c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala } 8654c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala 866afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen public void setTorchMode(String cameraId, boolean enabled) throws CameraAccessException { 867afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen synchronized(mLock) { 868afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen 869afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen if (cameraId == null) { 870afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen throw new IllegalArgumentException("cameraId was null"); 871afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen } 872afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen 873afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen ICameraService cameraService = getCameraService(); 874afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen if (cameraService == null) { 875afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen throw new CameraAccessException(CameraAccessException.CAMERA_DISCONNECTED, 876afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen "Camera service is currently unavailable"); 877afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen } 878afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen 879afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen try { 8805d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala cameraService.setTorchMode(cameraId, enabled, mTorchClientBinder); 8815d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala } catch(ServiceSpecificException e) { 8825d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala throwAsPublicException(e); 883afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen } catch (RemoteException e) { 884afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen throw new CameraAccessException(CameraAccessException.CAMERA_DISCONNECTED, 885afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen "Camera service is currently unavailable"); 886afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen } 887afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen } 888afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen } 889afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen 8905d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala private void handleRecoverableSetupErrors(ServiceSpecificException e) { 8915d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala switch (e.errorCode) { 8925d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala case ICameraService.ERROR_DISCONNECTED: 8935d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala Log.w(TAG, e.getMessage()); 894afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen break; 895afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen default: 8965d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala throw new IllegalStateException(e); 8974c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala } 8984c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala } 8994c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala 900e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin private boolean isAvailable(int status) { 901e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin switch (status) { 9025d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala case ICameraServiceListener.STATUS_PRESENT: 903e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin return true; 904e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin default: 905e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin return false; 906e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin } 907e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin } 908e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 909e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin private boolean validStatus(int status) { 910e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin switch (status) { 9115d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala case ICameraServiceListener.STATUS_NOT_PRESENT: 9125d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala case ICameraServiceListener.STATUS_PRESENT: 9135d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala case ICameraServiceListener.STATUS_ENUMERATING: 9145d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala case ICameraServiceListener.STATUS_NOT_AVAILABLE: 915e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin return true; 916e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin default: 917e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin return false; 918e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin } 919e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin } 920e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 921afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen private boolean validTorchStatus(int status) { 922afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen switch (status) { 9235d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala case ICameraServiceListener.TORCH_STATUS_NOT_AVAILABLE: 9245d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala case ICameraServiceListener.TORCH_STATUS_AVAILABLE_ON: 9255d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala case ICameraServiceListener.TORCH_STATUS_AVAILABLE_OFF: 926afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen return true; 927afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen default: 928afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen return false; 929afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen } 930afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen } 931afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen 932fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala private void postSingleUpdate(final AvailabilityCallback callback, final Handler handler, 933bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala final String id, final int status) { 934bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala if (isAvailable(status)) { 935bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala handler.post( 936bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala new Runnable() { 937bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala @Override 938bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala public void run() { 939fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala callback.onCameraAvailable(id); 940bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala } 941bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala }); 942bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala } else { 943bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala handler.post( 944bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala new Runnable() { 945bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala @Override 946bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala public void run() { 947fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala callback.onCameraUnavailable(id); 948bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala } 949bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala }); 950bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala } 951bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala } 952bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala 953afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen private void postSingleTorchUpdate(final TorchCallback callback, final Handler handler, 954afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen final String id, final int status) { 955afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen switch(status) { 9565d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala case ICameraServiceListener.TORCH_STATUS_AVAILABLE_ON: 9575d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala case ICameraServiceListener.TORCH_STATUS_AVAILABLE_OFF: 958afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen handler.post( 959afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen new Runnable() { 960afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen @Override 961afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen public void run() { 962afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen callback.onTorchModeChanged(id, status == 9635d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala ICameraServiceListener.TORCH_STATUS_AVAILABLE_ON); 964afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen } 965afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen }); 966afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen break; 967afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen default: 968afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen handler.post( 969afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen new Runnable() { 970afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen @Override 971afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen public void run() { 972afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen callback.onTorchModeUnavailable(id); 973afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen } 974afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen }); 975afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen break; 976afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen } 977afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen } 978afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen 979bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala /** 980bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala * Send the state of all known cameras to the provided listener, to initialize 981bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala * the listener's knowledge of camera state. 982bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala */ 9834c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala private void updateCallbackLocked(AvailabilityCallback callback, Handler handler) { 984bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala for (int i = 0; i < mDeviceStatus.size(); i++) { 985bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala String id = mDeviceStatus.keyAt(i); 986bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala Integer status = mDeviceStatus.valueAt(i); 987fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala postSingleUpdate(callback, handler, id, status); 988bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala } 989bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala } 990bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala 9914c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala private void onStatusChangedLocked(int status, String id) { 992bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala if (DEBUG) { 993e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin Log.v(TAG, 994bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala String.format("Camera id %s has status changed to 0x%x", id, status)); 995bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala } 996e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 997bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala if (!validStatus(status)) { 998bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala Log.e(TAG, String.format("Ignoring invalid device %s status 0x%x", id, 999bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala status)); 1000bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala return; 1001bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala } 1002e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 1003bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala Integer oldStatus = mDeviceStatus.put(id, status); 1004e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 1005bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala if (oldStatus != null && oldStatus == status) { 1006bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala if (DEBUG) { 1007e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin Log.v(TAG, String.format( 1008bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala "Device status changed to 0x%x, which is what it already was", 1009bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala status)); 1010e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin } 1011bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala return; 1012bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala } 1013e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 1014bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala // TODO: consider abstracting out this state minimization + transition 1015bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala // into a separate 1016bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala // more easily testable class 1017bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala // i.e. (new State()).addState(STATE_AVAILABLE) 1018bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala // .addState(STATE_NOT_AVAILABLE) 1019bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala // .addTransition(STATUS_PRESENT, STATE_AVAILABLE), 1020bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala // .addTransition(STATUS_NOT_PRESENT, STATE_NOT_AVAILABLE) 1021bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala // .addTransition(STATUS_ENUMERATING, STATE_NOT_AVAILABLE); 1022bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala // .addTransition(STATUS_NOT_AVAILABLE, STATE_NOT_AVAILABLE); 1023bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala 1024bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala // Translate all the statuses to either 'available' or 'not available' 1025bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala // available -> available => no new update 1026bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala // not available -> not available => no new update 1027bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala if (oldStatus != null && isAvailable(status) == isAvailable(oldStatus)) { 1028bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala if (DEBUG) { 1029e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin Log.v(TAG, 1030e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin String.format( 103102ffb2aad943ae2b16b505ca6b3a772ad6ed4df7Andreas Gampe "Device status was previously available (%b), " + 103202ffb2aad943ae2b16b505ca6b3a772ad6ed4df7Andreas Gampe " and is now again available (%b)" + 1033bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala "so no new client visible update will be sent", 103402ffb2aad943ae2b16b505ca6b3a772ad6ed4df7Andreas Gampe isAvailable(oldStatus), isAvailable(status))); 1035e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin } 1036bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala return; 1037bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala } 1038bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala 1039fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala final int callbackCount = mCallbackMap.size(); 1040fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala for (int i = 0; i < callbackCount; i++) { 1041fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala Handler handler = mCallbackMap.valueAt(i); 1042fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala final AvailabilityCallback callback = mCallbackMap.keyAt(i); 1043bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala 1044fd887436bd111e4d2c7307578a51b5070025b7f2Eino-Ville Talvala postSingleUpdate(callback, handler, id, status); 1045bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala } 1046bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala } // onStatusChangedLocked 1047e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 1048afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen private void updateTorchCallbackLocked(TorchCallback callback, Handler handler) { 1049afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen for (int i = 0; i < mTorchStatus.size(); i++) { 1050afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen String id = mTorchStatus.keyAt(i); 1051afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen Integer status = mTorchStatus.valueAt(i); 1052afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen postSingleTorchUpdate(callback, handler, id, status); 1053afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen } 1054afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen } 1055afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen 1056afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen private void onTorchStatusChangedLocked(int status, String id) { 1057afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen if (DEBUG) { 1058afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen Log.v(TAG, 1059afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen String.format("Camera id %s has torch status changed to 0x%x", id, status)); 1060afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen } 1061afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen 1062afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen if (!validTorchStatus(status)) { 1063afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen Log.e(TAG, String.format("Ignoring invalid device %s torch status 0x%x", id, 1064afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen status)); 1065afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen return; 1066afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen } 1067afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen 1068afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen Integer oldStatus = mTorchStatus.put(id, status); 1069afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen if (oldStatus != null && oldStatus == status) { 1070afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen if (DEBUG) { 1071afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen Log.v(TAG, String.format( 1072afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen "Torch status changed to 0x%x, which is what it already was", 1073afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen status)); 1074afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen } 1075afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen return; 1076afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen } 1077afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen 1078afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen final int callbackCount = mTorchCallbackMap.size(); 1079afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen for (int i = 0; i < callbackCount; i++) { 1080afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen final Handler handler = mTorchCallbackMap.valueAt(i); 1081afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen final TorchCallback callback = mTorchCallbackMap.keyAt(i); 1082afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen postSingleTorchUpdate(callback, handler, id, status); 1083afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen } 1084afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen } // onTorchStatusChangedLocked 1085afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen 10864c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala /** 10874c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala * Register a callback to be notified about camera device availability with the 10884c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala * global listener singleton. 10894c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala * 10904c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala * @param callback the new callback to send camera availability notices to 10914c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala * @param handler The handler on which the callback should be invoked. May not be null. 10924c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala */ 10934c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala public void registerAvailabilityCallback(AvailabilityCallback callback, Handler handler) { 10944c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala synchronized (mLock) { 10952ef01737afda0c61ede1035d86771b763dcd8a0fEino-Ville Talvala connectCameraServiceLocked(); 10962ef01737afda0c61ede1035d86771b763dcd8a0fEino-Ville Talvala 10974c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala Handler oldHandler = mCallbackMap.put(callback, handler); 10984c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala // For new callbacks, provide initial availability information 10994c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala if (oldHandler == null) { 11004c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala updateCallbackLocked(callback, handler); 11014c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala } 11020ac408ef431427b660bc94ef613f006211cead0fChien-Yu Chen 11030ac408ef431427b660bc94ef613f006211cead0fChien-Yu Chen // If not connected to camera service, schedule a reconnect to camera service. 11040ac408ef431427b660bc94ef613f006211cead0fChien-Yu Chen if (mCameraService == null) { 11050ac408ef431427b660bc94ef613f006211cead0fChien-Yu Chen scheduleCameraServiceReconnectionLocked(); 11060ac408ef431427b660bc94ef613f006211cead0fChien-Yu Chen } 11074c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala } 11084c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala } 11094c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala 11104c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala /** 11114c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala * Remove a previously-added callback; the callback will no longer receive connection and 11124c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala * disconnection callbacks, and is no longer referenced by the global listener singleton. 11134c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala * 11144c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala * @param callback The callback to remove from the notification list 11154c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala */ 11164c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala public void unregisterAvailabilityCallback(AvailabilityCallback callback) { 11174c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala synchronized (mLock) { 11184c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala mCallbackMap.remove(callback); 11194c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala } 11204c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala } 11214c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala 1122afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen public void registerTorchCallback(TorchCallback callback, Handler handler) { 1123afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen synchronized(mLock) { 11242ef01737afda0c61ede1035d86771b763dcd8a0fEino-Ville Talvala connectCameraServiceLocked(); 11252ef01737afda0c61ede1035d86771b763dcd8a0fEino-Ville Talvala 1126afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen Handler oldHandler = mTorchCallbackMap.put(callback, handler); 1127afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen // For new callbacks, provide initial torch information 1128afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen if (oldHandler == null) { 1129afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen updateTorchCallbackLocked(callback, handler); 1130afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen } 11310ac408ef431427b660bc94ef613f006211cead0fChien-Yu Chen 11320ac408ef431427b660bc94ef613f006211cead0fChien-Yu Chen // If not connected to camera service, schedule a reconnect to camera service. 11330ac408ef431427b660bc94ef613f006211cead0fChien-Yu Chen if (mCameraService == null) { 11340ac408ef431427b660bc94ef613f006211cead0fChien-Yu Chen scheduleCameraServiceReconnectionLocked(); 11350ac408ef431427b660bc94ef613f006211cead0fChien-Yu Chen } 1136afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen } 1137afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen } 1138afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen 1139afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen public void unregisterTorchCallback(TorchCallback callback) { 1140afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen synchronized(mLock) { 1141afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen mTorchCallbackMap.remove(callback); 1142afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen } 1143afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen } 1144afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen 11454c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala /** 11464c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala * Callback from camera service notifying the process about camera availability changes 11474c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala */ 11484c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala @Override 11494c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala public void onStatusChanged(int status, int cameraId) throws RemoteException { 11504c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala synchronized(mLock) { 11514c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala onStatusChangedLocked(status, String.valueOf(cameraId)); 11524c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala } 11534c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala } 11544c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala 1155afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen @Override 1156afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen public void onTorchStatusChanged(int status, String cameraId) throws RemoteException { 1157afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen synchronized (mLock) { 1158afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen onTorchStatusChangedLocked(status, cameraId); 1159afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen } 1160afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen } 1161afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen 11624c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala /** 11630f69b4655f635302fd8ce5653888a397723f3accChien-Yu Chen * Try to connect to camera service after some delay if any client registered camera 11640f69b4655f635302fd8ce5653888a397723f3accChien-Yu Chen * availability callback or torch status callback. 11650f69b4655f635302fd8ce5653888a397723f3accChien-Yu Chen */ 11660f69b4655f635302fd8ce5653888a397723f3accChien-Yu Chen private void scheduleCameraServiceReconnectionLocked() { 11670f69b4655f635302fd8ce5653888a397723f3accChien-Yu Chen final Handler handler; 11680f69b4655f635302fd8ce5653888a397723f3accChien-Yu Chen 11690f69b4655f635302fd8ce5653888a397723f3accChien-Yu Chen if (mCallbackMap.size() > 0) { 11700f69b4655f635302fd8ce5653888a397723f3accChien-Yu Chen handler = mCallbackMap.valueAt(0); 11710f69b4655f635302fd8ce5653888a397723f3accChien-Yu Chen } else if (mTorchCallbackMap.size() > 0) { 11720f69b4655f635302fd8ce5653888a397723f3accChien-Yu Chen handler = mTorchCallbackMap.valueAt(0); 11730f69b4655f635302fd8ce5653888a397723f3accChien-Yu Chen } else { 11740f69b4655f635302fd8ce5653888a397723f3accChien-Yu Chen // Not necessary to reconnect camera service if no client registers a callback. 11750f69b4655f635302fd8ce5653888a397723f3accChien-Yu Chen return; 11760f69b4655f635302fd8ce5653888a397723f3accChien-Yu Chen } 11770f69b4655f635302fd8ce5653888a397723f3accChien-Yu Chen 11780f69b4655f635302fd8ce5653888a397723f3accChien-Yu Chen if (DEBUG) { 11790f69b4655f635302fd8ce5653888a397723f3accChien-Yu Chen Log.v(TAG, "Reconnecting Camera Service in " + CAMERA_SERVICE_RECONNECT_DELAY_MS + 11800f69b4655f635302fd8ce5653888a397723f3accChien-Yu Chen " ms"); 11810f69b4655f635302fd8ce5653888a397723f3accChien-Yu Chen } 11820f69b4655f635302fd8ce5653888a397723f3accChien-Yu Chen 11830f69b4655f635302fd8ce5653888a397723f3accChien-Yu Chen handler.postDelayed( 11840f69b4655f635302fd8ce5653888a397723f3accChien-Yu Chen new Runnable() { 11850f69b4655f635302fd8ce5653888a397723f3accChien-Yu Chen @Override 11860f69b4655f635302fd8ce5653888a397723f3accChien-Yu Chen public void run() { 11870f69b4655f635302fd8ce5653888a397723f3accChien-Yu Chen ICameraService cameraService = getCameraService(); 11880f69b4655f635302fd8ce5653888a397723f3accChien-Yu Chen if (cameraService == null) { 11890f69b4655f635302fd8ce5653888a397723f3accChien-Yu Chen synchronized(mLock) { 11900f69b4655f635302fd8ce5653888a397723f3accChien-Yu Chen if (DEBUG) { 11910f69b4655f635302fd8ce5653888a397723f3accChien-Yu Chen Log.v(TAG, "Reconnecting Camera Service failed."); 11920f69b4655f635302fd8ce5653888a397723f3accChien-Yu Chen } 11930f69b4655f635302fd8ce5653888a397723f3accChien-Yu Chen scheduleCameraServiceReconnectionLocked(); 11940f69b4655f635302fd8ce5653888a397723f3accChien-Yu Chen } 11950f69b4655f635302fd8ce5653888a397723f3accChien-Yu Chen } 11960f69b4655f635302fd8ce5653888a397723f3accChien-Yu Chen } 11970f69b4655f635302fd8ce5653888a397723f3accChien-Yu Chen }, 11980f69b4655f635302fd8ce5653888a397723f3accChien-Yu Chen CAMERA_SERVICE_RECONNECT_DELAY_MS); 11990f69b4655f635302fd8ce5653888a397723f3accChien-Yu Chen } 12000f69b4655f635302fd8ce5653888a397723f3accChien-Yu Chen 12010f69b4655f635302fd8ce5653888a397723f3accChien-Yu Chen /** 12024c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala * Listener for camera service death. 12034c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala * 12044c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala * <p>The camera service isn't supposed to die under any normal circumstances, but can be 12054c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala * turned off during debug, or crash due to bugs. So detect that and null out the interface 12064c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala * object, so that the next calls to the manager can try to reconnect.</p> 12074c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala */ 12084c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala public void binderDied() { 12094c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala synchronized(mLock) { 12104c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala // Only do this once per service death 12114c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala if (mCameraService == null) return; 12124c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala 12134c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala mCameraService = null; 12144c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala 12150f69b4655f635302fd8ce5653888a397723f3accChien-Yu Chen // Tell listeners that the cameras and torch modes are unavailable and schedule a 12160f69b4655f635302fd8ce5653888a397723f3accChien-Yu Chen // reconnection to camera service. When camera service is reconnected, the camera 12170f69b4655f635302fd8ce5653888a397723f3accChien-Yu Chen // and torch statuses will be updated. 12184c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala for (int i = 0; i < mDeviceStatus.size(); i++) { 12194c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala String cameraId = mDeviceStatus.keyAt(i); 12205d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala onStatusChangedLocked(ICameraServiceListener.STATUS_NOT_PRESENT, cameraId); 12214c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala } 1222afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen for (int i = 0; i < mTorchStatus.size(); i++) { 1223afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen String cameraId = mTorchStatus.keyAt(i); 12245d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala onTorchStatusChangedLocked(ICameraServiceListener.TORCH_STATUS_NOT_AVAILABLE, 12255d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala cameraId); 1226afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen } 1227afa91399fd32ede17d440ec1c3321eee0426123cChien-Yu Chen 12280f69b4655f635302fd8ce5653888a397723f3accChien-Yu Chen scheduleCameraServiceReconnectionLocked(); 12294c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala } 12304c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala } 12314c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala 12324c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala } // CameraManagerGlobal 12334c9c7a58837d0ea9622b2e7b8397eb2f795675b6Eino-Ville Talvala 1234e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin} // CameraManager 1235