1 /* 2 * Copyright (C) 2015 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 18 package com.android.camera.one.v2; 19 20 import android.annotation.TargetApi; 21 import android.hardware.camera2.CameraAccessException; 22 import android.hardware.camera2.CameraCharacteristics; 23 import android.hardware.camera2.CameraManager; 24 import android.os.Build.VERSION_CODES; 25 26 import com.android.camera.debug.Log; 27 import com.android.camera.debug.Log.Tag; 28 import com.android.camera.device.CameraId; 29 import com.android.camera.one.OneCamera.Facing; 30 import com.android.camera.one.OneCameraAccessException; 31 import com.android.camera.one.OneCameraCharacteristics; 32 import com.android.camera.one.OneCameraManager; 33 import com.android.camera.util.AndroidServices; 34 import com.android.camera.util.ApiHelper; 35 import com.google.common.base.Optional; 36 37 import java.util.Hashtable; 38 39 import javax.annotation.Nonnull; 40 41 /** 42 * Pick camera ids from a list of devices based on defined characteristics. 43 */ 44 @TargetApi(VERSION_CODES.LOLLIPOP) 45 public class Camera2OneCameraManagerImpl implements OneCameraManager { 46 private static final Tag TAG = new Tag("Camera2OneCamMgr"); 47 /** 48 * Create a new camera2 api hardware manager. 49 */ create()50 public static Optional<Camera2OneCameraManagerImpl> create() { 51 if (!ApiHelper.HAS_CAMERA_2_API) { 52 return Optional.absent(); 53 } 54 CameraManager cameraManager; 55 try { 56 cameraManager = AndroidServices.instance().provideCameraManager(); 57 } catch (IllegalStateException ex) { 58 Log.e(TAG, "camera2.CameraManager is not available."); 59 return Optional.absent(); 60 } 61 Camera2OneCameraManagerImpl hardwareManager = 62 new Camera2OneCameraManagerImpl(cameraManager); 63 return Optional.of(hardwareManager); 64 } 65 66 private final CameraManager mCameraManager; 67 private Hashtable<Facing, String> mCameraFacingCache = new Hashtable<Facing, String>(); 68 Camera2OneCameraManagerImpl(CameraManager cameraManger)69 public Camera2OneCameraManagerImpl(CameraManager cameraManger) { 70 mCameraManager = cameraManger; 71 72 //Camera facing queries depending on camera implementation can be 73 //expensive and involve additional IPC with side effects. Cache front& 74 //back camera ids as early as possible. 75 if (mCameraManager != null) { 76 mCameraFacingCache.clear(); 77 findFirstCameraFacing(Facing.BACK); 78 findFirstCameraFacing(Facing.FRONT); 79 } 80 } 81 82 @Override hasCamera()83 public boolean hasCamera() { 84 try { 85 String[] ids = mCameraManager.getCameraIdList(); 86 return ids != null && ids.length > 0; 87 } catch (CameraAccessException ex) { 88 Log.e(TAG, "Unable to read camera list.", ex); 89 return false; 90 } 91 } 92 93 @Override hasCameraFacing(@onnull Facing direction)94 public boolean hasCameraFacing(@Nonnull Facing direction) { 95 return findCameraId(direction) != null; 96 } 97 98 @Override findFirstCamera()99 public CameraId findFirstCamera() { 100 try { 101 String[] ids = mCameraManager.getCameraIdList(); 102 if(ids != null && ids.length > 0) { 103 return CameraId.from(ids[0]); 104 } 105 } catch (CameraAccessException ex) { 106 Log.e(TAG, "Unable to read camera list.", ex); 107 } 108 109 return null; 110 } 111 112 @Override findFirstCameraFacing(@onnull Facing facing)113 public CameraId findFirstCameraFacing(@Nonnull Facing facing) { 114 String cameraId = findCameraId(facing); 115 return (cameraId != null) ? CameraId.from(cameraId) : null; 116 } 117 118 @Override getOneCameraCharacteristics( @onnull CameraId key)119 public OneCameraCharacteristics getOneCameraCharacteristics( 120 @Nonnull CameraId key) 121 throws OneCameraAccessException { 122 return new OneCameraCharacteristicsImpl(getCameraCharacteristics(key)); 123 } 124 getCameraCharacteristics( @onnull CameraId key)125 public CameraCharacteristics getCameraCharacteristics( 126 @Nonnull CameraId key) 127 throws OneCameraAccessException { 128 try { 129 return mCameraManager.getCameraCharacteristics(key.getValue()); 130 } catch (CameraAccessException ex) { 131 throw new OneCameraAccessException("Unable to get camera characteristics", ex); 132 } 133 } 134 135 /** Returns the ID of the first camera facing the given direction. */ findCameraId(Facing facing)136 private String findCameraId(Facing facing) { 137 String id = mCameraFacingCache.get(facing); 138 if (id != null) { 139 return id; 140 } 141 142 if (facing == Facing.FRONT) { 143 id = findFirstFrontCameraId(); 144 } else { 145 id = findFirstBackCameraId(); 146 } 147 148 if (id != null) { 149 mCameraFacingCache.put(facing, id); 150 } 151 return id; 152 } 153 154 /** Returns the ID of the first back-facing camera. */ findFirstBackCameraId()155 private String findFirstBackCameraId() { 156 Log.d(TAG, "Getting First BACK Camera"); 157 String cameraId = findFirstCameraIdFacing(CameraCharacteristics.LENS_FACING_BACK); 158 if (cameraId == null) { 159 Log.w(TAG, "No back-facing camera found."); 160 cameraId = findFirstCameraIdFacing(CameraCharacteristics.LENS_FACING_EXTERNAL); 161 if (cameraId == null) { 162 Log.w(TAG, "No external camera found."); 163 } 164 } 165 return cameraId; 166 } 167 168 /** Returns the ID of the first front-facing camera. */ findFirstFrontCameraId()169 private String findFirstFrontCameraId() { 170 Log.d(TAG, "Getting First FRONT Camera"); 171 String cameraId = findFirstCameraIdFacing(CameraCharacteristics.LENS_FACING_FRONT); 172 if (cameraId == null) { 173 Log.w(TAG, "No front-facing camera found."); 174 cameraId = findFirstCameraIdFacing(CameraCharacteristics.LENS_FACING_EXTERNAL); 175 if (cameraId == null) { 176 Log.w(TAG, "No external camera found."); 177 } 178 } 179 return cameraId; 180 } 181 182 183 /** Returns the ID of the first camera facing the given direction. */ findFirstCameraIdFacing(int facing)184 private String findFirstCameraIdFacing(int facing) { 185 try { 186 String[] cameraIds = mCameraManager.getCameraIdList(); 187 for (String cameraId : cameraIds) { 188 CameraCharacteristics characteristics = mCameraManager 189 .getCameraCharacteristics(cameraId); 190 if (characteristics.get(CameraCharacteristics.LENS_FACING) == facing) { 191 return cameraId; 192 } 193 } 194 } catch (CameraAccessException ex) { 195 Log.w(TAG, "Unable to get camera ID", ex); 196 } 197 return null; 198 } 199 200 } 201