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