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