1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License 15 */ 16 17 package com.android.incallui; 18 19 import android.content.Context; 20 import android.hardware.camera2.CameraAccessException; 21 import android.hardware.camera2.CameraCharacteristics; 22 import android.hardware.camera2.CameraManager; 23 import java.util.Collections; 24 import java.util.Set; 25 import java.util.concurrent.ConcurrentHashMap; 26 27 /** Used to track which camera is used for outgoing video. */ 28 public class InCallCameraManager { 29 30 private final Set<Listener> cameraSelectionListeners = 31 Collections.newSetFromMap(new ConcurrentHashMap<Listener, Boolean>(8, 0.9f, 1)); 32 /** The camera ID for the front facing camera. */ 33 private String frontFacingCameraId; 34 /** The camera ID for the rear facing camera. */ 35 private String rearFacingCameraId; 36 /** The currently active camera. */ 37 private boolean useFrontFacingCamera; 38 /** 39 * Indicates whether the list of cameras has been initialized yet. Initialization is delayed until 40 * a video call is present. 41 */ 42 private boolean isInitialized = false; 43 /** The context. */ 44 private Context context; 45 46 /** 47 * Initializes the InCall CameraManager. 48 * 49 * @param context The current context. 50 */ InCallCameraManager(Context context)51 public InCallCameraManager(Context context) { 52 useFrontFacingCamera = true; 53 this.context = context; 54 } 55 56 /** 57 * Sets whether the front facing camera should be used or not. 58 * 59 * @param useFrontFacingCamera {@code True} if the front facing camera is to be used. 60 */ setUseFrontFacingCamera(boolean useFrontFacingCamera)61 public void setUseFrontFacingCamera(boolean useFrontFacingCamera) { 62 this.useFrontFacingCamera = useFrontFacingCamera; 63 for (Listener listener : cameraSelectionListeners) { 64 listener.onActiveCameraSelectionChanged(this.useFrontFacingCamera); 65 } 66 } 67 68 /** 69 * Determines whether the front facing camera is currently in use. 70 * 71 * @return {@code True} if the front facing camera is in use. 72 */ isUsingFrontFacingCamera()73 public boolean isUsingFrontFacingCamera() { 74 return useFrontFacingCamera; 75 } 76 77 /** 78 * Determines the active camera ID. 79 * 80 * @return The active camera ID. 81 */ getActiveCameraId()82 public String getActiveCameraId() { 83 maybeInitializeCameraList(context); 84 85 if (useFrontFacingCamera) { 86 return frontFacingCameraId; 87 } else { 88 return rearFacingCameraId; 89 } 90 } 91 92 /** Calls when camera permission is granted by user. */ onCameraPermissionGranted()93 public void onCameraPermissionGranted() { 94 for (Listener listener : cameraSelectionListeners) { 95 listener.onCameraPermissionGranted(); 96 } 97 } 98 99 /** 100 * Get the list of cameras available for use. 101 * 102 * @param context The context. 103 */ maybeInitializeCameraList(Context context)104 private void maybeInitializeCameraList(Context context) { 105 if (isInitialized || context == null) { 106 return; 107 } 108 109 Log.v(this, "initializeCameraList"); 110 111 CameraManager cameraManager = null; 112 try { 113 cameraManager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE); 114 } catch (Exception e) { 115 Log.e(this, "Could not get camera service."); 116 return; 117 } 118 119 if (cameraManager == null) { 120 return; 121 } 122 123 String[] cameraIds = {}; 124 try { 125 cameraIds = cameraManager.getCameraIdList(); 126 } catch (CameraAccessException e) { 127 Log.d(this, "Could not access camera: " + e); 128 // Camera disabled by device policy. 129 return; 130 } 131 132 for (int i = 0; i < cameraIds.length; i++) { 133 CameraCharacteristics c = null; 134 try { 135 c = cameraManager.getCameraCharacteristics(cameraIds[i]); 136 } catch (IllegalArgumentException e) { 137 // Device Id is unknown. 138 } catch (CameraAccessException e) { 139 // Camera disabled by device policy. 140 } 141 if (c != null) { 142 int facingCharacteristic = c.get(CameraCharacteristics.LENS_FACING); 143 if (facingCharacteristic == CameraCharacteristics.LENS_FACING_FRONT) { 144 frontFacingCameraId = cameraIds[i]; 145 } else if (facingCharacteristic == CameraCharacteristics.LENS_FACING_BACK) { 146 rearFacingCameraId = cameraIds[i]; 147 } 148 } 149 } 150 151 isInitialized = true; 152 Log.v(this, "initializeCameraList : done"); 153 } 154 addCameraSelectionListener(Listener listener)155 public void addCameraSelectionListener(Listener listener) { 156 if (listener != null) { 157 cameraSelectionListeners.add(listener); 158 } 159 } 160 removeCameraSelectionListener(Listener listener)161 public void removeCameraSelectionListener(Listener listener) { 162 if (listener != null) { 163 cameraSelectionListeners.remove(listener); 164 } 165 } 166 167 public interface Listener { 168 onActiveCameraSelectionChanged(boolean isUsingFrontFacingCamera)169 void onActiveCameraSelectionChanged(boolean isUsingFrontFacingCamera); 170 onCameraPermissionGranted()171 void onCameraPermissionGranted(); 172 } 173 } 174