1350fff554bf7ed5b9e91985935488771156953abTyler Gunn/*
2350fff554bf7ed5b9e91985935488771156953abTyler Gunn * Copyright (C) 2014 The Android Open Source Project
3350fff554bf7ed5b9e91985935488771156953abTyler Gunn *
4350fff554bf7ed5b9e91985935488771156953abTyler Gunn * Licensed under the Apache License, Version 2.0 (the "License");
5350fff554bf7ed5b9e91985935488771156953abTyler Gunn * you may not use this file except in compliance with the License.
6350fff554bf7ed5b9e91985935488771156953abTyler Gunn * You may obtain a copy of the License at
7350fff554bf7ed5b9e91985935488771156953abTyler Gunn *
8350fff554bf7ed5b9e91985935488771156953abTyler Gunn *      http://www.apache.org/licenses/LICENSE-2.0
9350fff554bf7ed5b9e91985935488771156953abTyler Gunn *
10350fff554bf7ed5b9e91985935488771156953abTyler Gunn * Unless required by applicable law or agreed to in writing, software
11350fff554bf7ed5b9e91985935488771156953abTyler Gunn * distributed under the License is distributed on an "AS IS" BASIS,
12350fff554bf7ed5b9e91985935488771156953abTyler Gunn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13350fff554bf7ed5b9e91985935488771156953abTyler Gunn * See the License for the specific language governing permissions and
14350fff554bf7ed5b9e91985935488771156953abTyler Gunn * limitations under the License
15350fff554bf7ed5b9e91985935488771156953abTyler Gunn */
16350fff554bf7ed5b9e91985935488771156953abTyler Gunn
17350fff554bf7ed5b9e91985935488771156953abTyler Gunnpackage com.android.incallui;
18350fff554bf7ed5b9e91985935488771156953abTyler Gunn
19350fff554bf7ed5b9e91985935488771156953abTyler Gunnimport android.content.Context;
20350fff554bf7ed5b9e91985935488771156953abTyler Gunnimport android.graphics.SurfaceTexture;
21350fff554bf7ed5b9e91985935488771156953abTyler Gunnimport android.hardware.camera2.CameraAccessException;
22350fff554bf7ed5b9e91985935488771156953abTyler Gunnimport android.hardware.camera2.CameraCharacteristics;
23350fff554bf7ed5b9e91985935488771156953abTyler Gunnimport android.hardware.camera2.CameraManager;
24350fff554bf7ed5b9e91985935488771156953abTyler Gunnimport android.hardware.camera2.params.StreamConfigurationMap;
25350fff554bf7ed5b9e91985935488771156953abTyler Gunnimport android.util.Size;
26350fff554bf7ed5b9e91985935488771156953abTyler Gunn
27350fff554bf7ed5b9e91985935488771156953abTyler Gunnimport java.lang.String;
2818c0feda76fe333f3db1bf7bd307458a9e6b6005Rekha Kumarimport java.util.Collections;
2918c0feda76fe333f3db1bf7bd307458a9e6b6005Rekha Kumarimport java.util.concurrent.ConcurrentHashMap;
3018c0feda76fe333f3db1bf7bd307458a9e6b6005Rekha Kumarimport java.util.Set;
31350fff554bf7ed5b9e91985935488771156953abTyler Gunn
32350fff554bf7ed5b9e91985935488771156953abTyler Gunn/**
33350fff554bf7ed5b9e91985935488771156953abTyler Gunn * Used to track which camera is used for outgoing video.
34350fff554bf7ed5b9e91985935488771156953abTyler Gunn */
35350fff554bf7ed5b9e91985935488771156953abTyler Gunnpublic class InCallCameraManager {
36350fff554bf7ed5b9e91985935488771156953abTyler Gunn
3718c0feda76fe333f3db1bf7bd307458a9e6b6005Rekha Kumar    public interface Listener {
3818c0feda76fe333f3db1bf7bd307458a9e6b6005Rekha Kumar        void onActiveCameraSelectionChanged(boolean isUsingFrontFacingCamera);
3918c0feda76fe333f3db1bf7bd307458a9e6b6005Rekha Kumar    }
4018c0feda76fe333f3db1bf7bd307458a9e6b6005Rekha Kumar
4118c0feda76fe333f3db1bf7bd307458a9e6b6005Rekha Kumar    private final Set<Listener> mCameraSelectionListeners = Collections.
4218c0feda76fe333f3db1bf7bd307458a9e6b6005Rekha Kumar        newSetFromMap(new ConcurrentHashMap<Listener, Boolean>(8,0.9f,1));
4318c0feda76fe333f3db1bf7bd307458a9e6b6005Rekha Kumar
44350fff554bf7ed5b9e91985935488771156953abTyler Gunn    /**
45350fff554bf7ed5b9e91985935488771156953abTyler Gunn     * The camera ID for the front facing camera.
46350fff554bf7ed5b9e91985935488771156953abTyler Gunn     */
47350fff554bf7ed5b9e91985935488771156953abTyler Gunn    private String mFrontFacingCameraId;
48350fff554bf7ed5b9e91985935488771156953abTyler Gunn
49350fff554bf7ed5b9e91985935488771156953abTyler Gunn    /**
50350fff554bf7ed5b9e91985935488771156953abTyler Gunn     * The camera ID for the rear facing camera.
51350fff554bf7ed5b9e91985935488771156953abTyler Gunn     */
52350fff554bf7ed5b9e91985935488771156953abTyler Gunn    private String mRearFacingCameraId;
53350fff554bf7ed5b9e91985935488771156953abTyler Gunn
54350fff554bf7ed5b9e91985935488771156953abTyler Gunn    /**
55350fff554bf7ed5b9e91985935488771156953abTyler Gunn     * The currently active camera.
56350fff554bf7ed5b9e91985935488771156953abTyler Gunn     */
57350fff554bf7ed5b9e91985935488771156953abTyler Gunn    private boolean mUseFrontFacingCamera;
58350fff554bf7ed5b9e91985935488771156953abTyler Gunn
59350fff554bf7ed5b9e91985935488771156953abTyler Gunn    /**
60d6ebc55e383a986a3b32b94186282a0af94bea2dTyler Gunn     * Indicates whether the list of cameras has been initialized yet.  Initialization is delayed
61d6ebc55e383a986a3b32b94186282a0af94bea2dTyler Gunn     * until a video call is present.
62350fff554bf7ed5b9e91985935488771156953abTyler Gunn     */
63d6ebc55e383a986a3b32b94186282a0af94bea2dTyler Gunn    private boolean mIsInitialized = false;
64350fff554bf7ed5b9e91985935488771156953abTyler Gunn
65350fff554bf7ed5b9e91985935488771156953abTyler Gunn    /**
66d6ebc55e383a986a3b32b94186282a0af94bea2dTyler Gunn     * The context.
67350fff554bf7ed5b9e91985935488771156953abTyler Gunn     */
68d6ebc55e383a986a3b32b94186282a0af94bea2dTyler Gunn    private Context mContext;
69350fff554bf7ed5b9e91985935488771156953abTyler Gunn
70350fff554bf7ed5b9e91985935488771156953abTyler Gunn    /**
71350fff554bf7ed5b9e91985935488771156953abTyler Gunn     * Initializes the InCall CameraManager.
72350fff554bf7ed5b9e91985935488771156953abTyler Gunn     *
73350fff554bf7ed5b9e91985935488771156953abTyler Gunn     * @param context The current context.
74350fff554bf7ed5b9e91985935488771156953abTyler Gunn     */
75350fff554bf7ed5b9e91985935488771156953abTyler Gunn    public InCallCameraManager(Context context) {
76350fff554bf7ed5b9e91985935488771156953abTyler Gunn        mUseFrontFacingCamera = true;
77d6ebc55e383a986a3b32b94186282a0af94bea2dTyler Gunn        mContext = context;
78350fff554bf7ed5b9e91985935488771156953abTyler Gunn    }
79350fff554bf7ed5b9e91985935488771156953abTyler Gunn
80350fff554bf7ed5b9e91985935488771156953abTyler Gunn    /**
81350fff554bf7ed5b9e91985935488771156953abTyler Gunn     * Sets whether the front facing camera should be used or not.
82350fff554bf7ed5b9e91985935488771156953abTyler Gunn     *
83350fff554bf7ed5b9e91985935488771156953abTyler Gunn     * @param useFrontFacingCamera {@code True} if the front facing camera is to be used.
84350fff554bf7ed5b9e91985935488771156953abTyler Gunn     */
85350fff554bf7ed5b9e91985935488771156953abTyler Gunn    public void setUseFrontFacingCamera(boolean useFrontFacingCamera) {
86350fff554bf7ed5b9e91985935488771156953abTyler Gunn        mUseFrontFacingCamera = useFrontFacingCamera;
8718c0feda76fe333f3db1bf7bd307458a9e6b6005Rekha Kumar        for (Listener listener : mCameraSelectionListeners) {
8818c0feda76fe333f3db1bf7bd307458a9e6b6005Rekha Kumar            listener.onActiveCameraSelectionChanged(mUseFrontFacingCamera);
8918c0feda76fe333f3db1bf7bd307458a9e6b6005Rekha Kumar        }
90350fff554bf7ed5b9e91985935488771156953abTyler Gunn    }
91350fff554bf7ed5b9e91985935488771156953abTyler Gunn
92350fff554bf7ed5b9e91985935488771156953abTyler Gunn    /**
93350fff554bf7ed5b9e91985935488771156953abTyler Gunn     * Determines whether the front facing camera is currently in use.
94350fff554bf7ed5b9e91985935488771156953abTyler Gunn     *
95350fff554bf7ed5b9e91985935488771156953abTyler Gunn     * @return {@code True} if the front facing camera is in use.
96350fff554bf7ed5b9e91985935488771156953abTyler Gunn     */
97350fff554bf7ed5b9e91985935488771156953abTyler Gunn    public boolean isUsingFrontFacingCamera() {
98350fff554bf7ed5b9e91985935488771156953abTyler Gunn        return mUseFrontFacingCamera;
99350fff554bf7ed5b9e91985935488771156953abTyler Gunn    }
100350fff554bf7ed5b9e91985935488771156953abTyler Gunn
101350fff554bf7ed5b9e91985935488771156953abTyler Gunn    /**
102350fff554bf7ed5b9e91985935488771156953abTyler Gunn     * Determines the active camera ID.
103350fff554bf7ed5b9e91985935488771156953abTyler Gunn     *
104350fff554bf7ed5b9e91985935488771156953abTyler Gunn     * @return The active camera ID.
105350fff554bf7ed5b9e91985935488771156953abTyler Gunn     */
106350fff554bf7ed5b9e91985935488771156953abTyler Gunn    public String getActiveCameraId() {
107d6ebc55e383a986a3b32b94186282a0af94bea2dTyler Gunn        maybeInitializeCameraList(mContext);
108d6ebc55e383a986a3b32b94186282a0af94bea2dTyler Gunn
109350fff554bf7ed5b9e91985935488771156953abTyler Gunn        if (mUseFrontFacingCamera) {
110350fff554bf7ed5b9e91985935488771156953abTyler Gunn            return mFrontFacingCameraId;
111350fff554bf7ed5b9e91985935488771156953abTyler Gunn        } else {
112350fff554bf7ed5b9e91985935488771156953abTyler Gunn            return mRearFacingCameraId;
113350fff554bf7ed5b9e91985935488771156953abTyler Gunn        }
114350fff554bf7ed5b9e91985935488771156953abTyler Gunn    }
115350fff554bf7ed5b9e91985935488771156953abTyler Gunn
116350fff554bf7ed5b9e91985935488771156953abTyler Gunn    /**
117d6ebc55e383a986a3b32b94186282a0af94bea2dTyler Gunn     * Get the list of cameras available for use.
118350fff554bf7ed5b9e91985935488771156953abTyler Gunn     *
119350fff554bf7ed5b9e91985935488771156953abTyler Gunn     * @param context The context.
120350fff554bf7ed5b9e91985935488771156953abTyler Gunn     */
121d6ebc55e383a986a3b32b94186282a0af94bea2dTyler Gunn    private void maybeInitializeCameraList(Context context) {
122d6ebc55e383a986a3b32b94186282a0af94bea2dTyler Gunn        if (mIsInitialized || context == null) {
1237fc046b0f29e78d0cf5a4066c69f826ef4eda6fdTyler Gunn            return;
1247fc046b0f29e78d0cf5a4066c69f826ef4eda6fdTyler Gunn        }
1257fc046b0f29e78d0cf5a4066c69f826ef4eda6fdTyler Gunn
126d6ebc55e383a986a3b32b94186282a0af94bea2dTyler Gunn        Log.v(this, "initializeCameraList");
127d6ebc55e383a986a3b32b94186282a0af94bea2dTyler Gunn
1287fc046b0f29e78d0cf5a4066c69f826ef4eda6fdTyler Gunn        CameraManager cameraManager = null;
1297fc046b0f29e78d0cf5a4066c69f826ef4eda6fdTyler Gunn        try {
1307fc046b0f29e78d0cf5a4066c69f826ef4eda6fdTyler Gunn            cameraManager = (CameraManager) context.getSystemService(
1317fc046b0f29e78d0cf5a4066c69f826ef4eda6fdTyler Gunn                    Context.CAMERA_SERVICE);
1327fc046b0f29e78d0cf5a4066c69f826ef4eda6fdTyler Gunn        } catch (Exception e) {
1337fc046b0f29e78d0cf5a4066c69f826ef4eda6fdTyler Gunn            Log.e(this, "Could not get camera service.");
1347fc046b0f29e78d0cf5a4066c69f826ef4eda6fdTyler Gunn            return;
1357fc046b0f29e78d0cf5a4066c69f826ef4eda6fdTyler Gunn        }
1367fc046b0f29e78d0cf5a4066c69f826ef4eda6fdTyler Gunn
1377fc046b0f29e78d0cf5a4066c69f826ef4eda6fdTyler Gunn        if (cameraManager == null) {
1387fc046b0f29e78d0cf5a4066c69f826ef4eda6fdTyler Gunn            return;
1397fc046b0f29e78d0cf5a4066c69f826ef4eda6fdTyler Gunn        }
140350fff554bf7ed5b9e91985935488771156953abTyler Gunn
141350fff554bf7ed5b9e91985935488771156953abTyler Gunn        String[] cameraIds = {};
142350fff554bf7ed5b9e91985935488771156953abTyler Gunn        try {
143350fff554bf7ed5b9e91985935488771156953abTyler Gunn            cameraIds = cameraManager.getCameraIdList();
144350fff554bf7ed5b9e91985935488771156953abTyler Gunn        } catch (CameraAccessException e) {
145350fff554bf7ed5b9e91985935488771156953abTyler Gunn            Log.d(this, "Could not access camera: "+e);
146350fff554bf7ed5b9e91985935488771156953abTyler Gunn            // Camera disabled by device policy.
147350fff554bf7ed5b9e91985935488771156953abTyler Gunn            return;
148350fff554bf7ed5b9e91985935488771156953abTyler Gunn        }
149350fff554bf7ed5b9e91985935488771156953abTyler Gunn
150350fff554bf7ed5b9e91985935488771156953abTyler Gunn        for (int i = 0; i < cameraIds.length; i++) {
151350fff554bf7ed5b9e91985935488771156953abTyler Gunn            CameraCharacteristics c = null;
152350fff554bf7ed5b9e91985935488771156953abTyler Gunn            try {
153350fff554bf7ed5b9e91985935488771156953abTyler Gunn                c = cameraManager.getCameraCharacteristics(cameraIds[i]);
154350fff554bf7ed5b9e91985935488771156953abTyler Gunn            } catch (IllegalArgumentException e) {
155350fff554bf7ed5b9e91985935488771156953abTyler Gunn                // Device Id is unknown.
156350fff554bf7ed5b9e91985935488771156953abTyler Gunn            } catch (CameraAccessException e) {
157350fff554bf7ed5b9e91985935488771156953abTyler Gunn                // Camera disabled by device policy.
158350fff554bf7ed5b9e91985935488771156953abTyler Gunn            }
159350fff554bf7ed5b9e91985935488771156953abTyler Gunn            if (c != null) {
160350fff554bf7ed5b9e91985935488771156953abTyler Gunn                int facingCharacteristic = c.get(CameraCharacteristics.LENS_FACING);
161350fff554bf7ed5b9e91985935488771156953abTyler Gunn                if (facingCharacteristic == CameraCharacteristics.LENS_FACING_FRONT) {
162350fff554bf7ed5b9e91985935488771156953abTyler Gunn                    mFrontFacingCameraId = cameraIds[i];
163350fff554bf7ed5b9e91985935488771156953abTyler Gunn                } else if (facingCharacteristic == CameraCharacteristics.LENS_FACING_BACK) {
164350fff554bf7ed5b9e91985935488771156953abTyler Gunn                    mRearFacingCameraId = cameraIds[i];
165350fff554bf7ed5b9e91985935488771156953abTyler Gunn                }
166350fff554bf7ed5b9e91985935488771156953abTyler Gunn            }
167350fff554bf7ed5b9e91985935488771156953abTyler Gunn        }
168d6ebc55e383a986a3b32b94186282a0af94bea2dTyler Gunn
169d6ebc55e383a986a3b32b94186282a0af94bea2dTyler Gunn        mIsInitialized = true;
170d6ebc55e383a986a3b32b94186282a0af94bea2dTyler Gunn        Log.v(this, "initializeCameraList : done");
171350fff554bf7ed5b9e91985935488771156953abTyler Gunn    }
17218c0feda76fe333f3db1bf7bd307458a9e6b6005Rekha Kumar
17318c0feda76fe333f3db1bf7bd307458a9e6b6005Rekha Kumar    public void addCameraSelectionListener(Listener listener) {
17418c0feda76fe333f3db1bf7bd307458a9e6b6005Rekha Kumar        if (listener != null) {
17518c0feda76fe333f3db1bf7bd307458a9e6b6005Rekha Kumar            mCameraSelectionListeners.add(listener);
17618c0feda76fe333f3db1bf7bd307458a9e6b6005Rekha Kumar        }
17718c0feda76fe333f3db1bf7bd307458a9e6b6005Rekha Kumar    }
17818c0feda76fe333f3db1bf7bd307458a9e6b6005Rekha Kumar
17918c0feda76fe333f3db1bf7bd307458a9e6b6005Rekha Kumar    public void removeCameraSelectionListener(Listener listener) {
18018c0feda76fe333f3db1bf7bd307458a9e6b6005Rekha Kumar        if (listener != null) {
18118c0feda76fe333f3db1bf7bd307458a9e6b6005Rekha Kumar            mCameraSelectionListeners.remove(listener);
18218c0feda76fe333f3db1bf7bd307458a9e6b6005Rekha Kumar        }
18318c0feda76fe333f3db1bf7bd307458a9e6b6005Rekha Kumar    }
184350fff554bf7ed5b9e91985935488771156953abTyler Gunn}
185