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.camera.one;
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 android.os.Handler;
24 import android.util.DisplayMetrics;
25 import android.view.WindowManager;
26 
27 import com.android.camera.CameraActivity;
28 import com.android.camera.debug.Log;
29 import com.android.camera.debug.Log.Tag;
30 import com.android.camera.one.OneCamera.Facing;
31 import com.android.camera.one.OneCamera.OpenCallback;
32 import com.android.camera.util.ApiHelper;
33 import com.android.camera.util.Size;
34 
35 /**
36  * The camera manager is responsible for instantiating {@link OneCamera}
37  * instances.
38  */
39 public abstract class OneCameraManager {
40     private static Tag TAG = new Tag("OneCameraManager");
41 
42     /**
43      * Attempts to open the camera facing the given direction with the given
44      * capture size.
45      *
46      * Exactly one call will always be made to a single method in the provided
47      * {@link OpenCallback}.
48      *
49      * @param facing which camera to open. The first camera found in the given
50      *            direction will be opened.
51      * @param enableHdr if an HDR feature exists, open a camera that supports it
52      * @param captureSize the capture size. This must be one of the supported
53      *            sizes.
54      * @param callback this listener is called when the camera was opened or
55      *            when it failed to open.
56      * @param handler the handler on which callback methods are invoked.
57      */
open(Facing facing, boolean enableHdr, Size captureSize, OpenCallback callback, Handler handler)58     public abstract void open(Facing facing, boolean enableHdr, Size captureSize,
59             OpenCallback callback, Handler handler);
60 
61     /**
62      * Returns whether the device has a camera facing the given direction.
63      */
hasCameraFacing(Facing facing)64     public abstract boolean hasCameraFacing(Facing facing);
65 
66     /**
67      * Creates a camera manager that is based on Camera2 API, if available, or
68      * otherwise uses the portability layer API.
69      *
70      * @throws OneCameraException Thrown if an error occurred while trying to
71      *             access the camera.
72      */
get(CameraActivity activity)73     public static OneCameraManager get(CameraActivity activity) throws OneCameraException {
74         return create(activity);
75     }
76 
77     /**
78      * Creates a new camera manager that is based on Camera2 API, if available,
79      * or otherwise uses the portability API.
80      *
81      * @throws OneCameraException Thrown if an error occurred while trying to
82      *             access the camera.
83      */
create(CameraActivity activity)84     private static OneCameraManager create(CameraActivity activity) throws OneCameraException {
85         DisplayMetrics displayMetrics = getDisplayMetrics(activity);
86         CameraManager cameraManager = null;
87 
88         try {
89             cameraManager = ApiHelper.HAS_CAMERA_2_API ? (CameraManager) activity
90                     .getSystemService(Context.CAMERA_SERVICE) : null;
91         } catch (IllegalStateException ex) {
92             cameraManager = null;
93             Log.e(TAG, "Could not get camera service v2", ex);
94         }
95         if (cameraManager != null && isCamera2Supported(cameraManager)) {
96             int maxMemoryMB = activity.getServices().getMemoryManager()
97                     .getMaxAllowedNativeMemoryAllocation();
98             return new com.android.camera.one.v2.OneCameraManagerImpl(
99                     activity.getAndroidContext(), cameraManager, maxMemoryMB,
100                     displayMetrics, activity.getSoundPlayer());
101         } else {
102             return new com.android.camera.one.v1.OneCameraManagerImpl();
103         }
104     }
105 
106     /**
107      * Returns whether the device fully supports API2
108      *
109      * @param cameraManager the Camera2 API manager.
110      * @return If this device is only emulating Camera2 API on top of an older
111      *         HAL (such as the Nexus 4, 7 or 10), this method returns false. It
112      *         only returns true, if Camera2 is fully supported through newer
113      *         HALs.
114      * @throws OneCameraException Thrown if an error occurred while trying to
115      *             access the camera.
116      */
isCamera2Supported(CameraManager cameraManager)117     private static boolean isCamera2Supported(CameraManager cameraManager)
118             throws OneCameraException {
119         if (!ApiHelper.HAS_CAMERA_2_API) {
120             return false;
121         }
122         try {
123             String[] cameraIds = cameraManager.getCameraIdList();
124             if (cameraIds.length == 0) {
125                 throw new OneCameraException("Camera 2 API supported but no devices available.");
126             }
127             final String id = cameraIds[0];
128             // TODO: We should check for all the flags we need to ensure the
129             // device is capable of taking Camera2 API shots. For now, let's
130             // accept all device that are either 'partial' or 'full' devices
131             // (but not legacy).
132             return cameraManager.getCameraCharacteristics(id).get(
133                     CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL)
134                 != CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY;
135         } catch (CameraAccessException ex) {
136             Log.e(TAG, "Could not access camera to determine hardware-level API support.");
137             return false;
138         }
139     }
140 
getDisplayMetrics(Context context)141     private static DisplayMetrics getDisplayMetrics(Context context) {
142         DisplayMetrics displayMetrics = new DisplayMetrics();
143         WindowManager wm = (WindowManager)
144                 context.getSystemService(Context.WINDOW_SERVICE);
145         if (wm != null) {
146             displayMetrics = new DisplayMetrics();
147             wm.getDefaultDisplay().getMetrics(displayMetrics);
148         }
149         return displayMetrics;
150     }
151 }
152