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