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.v2; 18 19 import static com.google.common.base.Preconditions.checkNotNull; 20 21 import android.annotation.TargetApi; 22 import android.graphics.Rect; 23 import android.graphics.SurfaceTexture; 24 import android.hardware.camera2.CameraCharacteristics; 25 import android.hardware.camera2.CameraMetadata; 26 import android.hardware.camera2.params.StreamConfigurationMap; 27 import android.os.Build; 28 import android.util.Range; 29 import android.util.Rational; 30 31 import com.android.camera.debug.Log; 32 import com.android.camera.one.OneCamera; 33 import com.android.camera.one.OneCameraCharacteristics; 34 import com.android.camera.ui.focus.LensRangeCalculator; 35 import com.android.camera.ui.motion.LinearScale; 36 import com.android.camera.util.ApiHelper; 37 import com.android.camera.util.Size; 38 import com.google.common.primitives.Floats; 39 40 import java.util.ArrayList; 41 import java.util.List; 42 43 /** 44 * Describes a OneCamera device which is on top of camera2 API. This is 45 * essential a wrapper for #{link 46 * android.hardware.camera2.CameraCharacteristics}. 47 */ 48 @TargetApi(Build.VERSION_CODES.LOLLIPOP) 49 public class OneCameraCharacteristicsImpl implements OneCameraCharacteristics { 50 private static final int CONTROL_SCENE_MODE_HDR = 0x12; 51 private static final Log.Tag TAG = new Log.Tag("OneCamCharImpl"); 52 53 private final CameraCharacteristics mCameraCharacteristics; 54 OneCameraCharacteristicsImpl(CameraCharacteristics cameraCharacteristics)55 public OneCameraCharacteristicsImpl(CameraCharacteristics cameraCharacteristics) { 56 mCameraCharacteristics = cameraCharacteristics; 57 } 58 59 @Override getSupportedPictureSizes(int imageFormat)60 public List<Size> getSupportedPictureSizes(int imageFormat) { 61 StreamConfigurationMap configMap; 62 try { 63 configMap = mCameraCharacteristics.get( 64 CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); 65 } catch (Exception ex) { 66 Log.e(TAG, "Unable to obtain picture sizes.", ex); 67 // See b/19623115 where java.lang.AssertionError can be thrown due to HAL error 68 return new ArrayList<>(0); 69 } 70 71 ArrayList<Size> supportedPictureSizes = new ArrayList<>(); 72 for (android.util.Size androidSize : configMap.getOutputSizes(imageFormat)) { 73 supportedPictureSizes.add(new Size(androidSize)); 74 } 75 return supportedPictureSizes; 76 } 77 78 @Override getSupportedPreviewSizes()79 public List<Size> getSupportedPreviewSizes() { 80 StreamConfigurationMap configMap; 81 try { 82 configMap = mCameraCharacteristics.get( 83 CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); 84 } catch (Exception ex) { 85 Log.e(TAG, "Unable to obtain preview sizes.", ex); 86 // See b/19623115 where java.lang.AssertionError can be thrown due to HAL error 87 return new ArrayList<>(0); 88 } 89 ArrayList<Size> supportedPictureSizes = new ArrayList<>(); 90 for (android.util.Size androidSize : configMap.getOutputSizes(SurfaceTexture.class)) { 91 supportedPictureSizes.add(new Size(androidSize)); 92 } 93 return supportedPictureSizes; 94 } 95 96 @Override getSensorOrientation()97 public int getSensorOrientation() { 98 return mCameraCharacteristics.get(CameraCharacteristics.SENSOR_ORIENTATION); 99 } 100 101 @Override getCameraDirection()102 public OneCamera.Facing getCameraDirection() { 103 int direction = mCameraCharacteristics.get(CameraCharacteristics.LENS_FACING); 104 if (direction == CameraCharacteristics.LENS_FACING_BACK) { 105 return OneCamera.Facing.BACK; 106 } else { 107 return OneCamera.Facing.FRONT; 108 } 109 } 110 111 @Override getSensorInfoActiveArraySize()112 public Rect getSensorInfoActiveArraySize() { 113 return mCameraCharacteristics.get(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE); 114 } 115 116 @Override getAvailableMaxDigitalZoom()117 public float getAvailableMaxDigitalZoom() { 118 return mCameraCharacteristics.get(CameraCharacteristics.SCALER_AVAILABLE_MAX_DIGITAL_ZOOM); 119 } 120 121 @Override isFlashSupported()122 public boolean isFlashSupported() { 123 return mCameraCharacteristics.get(CameraCharacteristics.FLASH_INFO_AVAILABLE); 124 } 125 126 @Override isHdrSceneSupported()127 public boolean isHdrSceneSupported() { 128 // API 21 omitted this constant officially, but kept it around as a hidden constant 129 // MR1 brings it back officially as the same int value. 130 int[] availableSceneModes = mCameraCharacteristics.get( 131 CameraCharacteristics.CONTROL_AVAILABLE_SCENE_MODES); 132 for (int availableSceneMode : availableSceneModes) { 133 if (availableSceneMode == CONTROL_SCENE_MODE_HDR) { 134 return true; 135 } 136 } 137 return false; 138 } 139 140 @Override getSupportedHardwareLevel()141 public SupportedHardwareLevel getSupportedHardwareLevel() { 142 Integer supportedHardwareLevel = mCameraCharacteristics 143 .get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL); 144 // If this fails, it is a framework bug, per API documentation. 145 checkNotNull(supportedHardwareLevel, "INFO_SUPPORTED_HARDWARE_LEVEL not found"); 146 switch (supportedHardwareLevel) { 147 case CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL: 148 return SupportedHardwareLevel.FULL; 149 case CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED: 150 return SupportedHardwareLevel.LIMITED; 151 case CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY: 152 return SupportedHardwareLevel.LEGACY; 153 default: 154 if (supportedHardwareLevel > 155 CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL) { 156 Log.i(TAG, "Unknown higher hardware level mapped to FULL: " 157 + supportedHardwareLevel); 158 return SupportedHardwareLevel.FULL; 159 } 160 throw new IllegalStateException("Invalid value for INFO_SUPPORTED_HARDWARE_LEVEL"); 161 } 162 } 163 164 @Override getSupportedFaceDetectModes()165 public List<FaceDetectMode> getSupportedFaceDetectModes() { 166 int[] modes = mCameraCharacteristics.get( 167 CameraCharacteristics.STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES); 168 169 List<FaceDetectMode> oneModes = new ArrayList<>(modes.length); 170 171 for(int i=0; i < modes.length; i++) { 172 if (modes[i] == CameraMetadata.STATISTICS_FACE_DETECT_MODE_FULL) { 173 oneModes.add(FaceDetectMode.FULL); 174 } 175 if (modes[i] == CameraMetadata.STATISTICS_FACE_DETECT_MODE_SIMPLE) { 176 oneModes.add(FaceDetectMode.SIMPLE); 177 } 178 if (modes[i] == CameraMetadata.STATISTICS_FACE_DETECT_MODE_OFF) { 179 oneModes.add(FaceDetectMode.NONE); 180 } 181 } 182 183 return oneModes; 184 } 185 186 @Override getLensFocusRange()187 public LinearScale getLensFocusRange() { 188 return LensRangeCalculator.getDiopterToRatioCalculator(mCameraCharacteristics); 189 } 190 191 @Override getAvailableFocalLengths()192 public List<Float> getAvailableFocalLengths() { 193 return Floats.asList(mCameraCharacteristics.get(CameraCharacteristics.LENS_INFO_AVAILABLE_FOCAL_LENGTHS)); 194 } 195 196 @Override isExposureCompensationSupported()197 public boolean isExposureCompensationSupported() { 198 // Turn off exposure compensation for Nexus 6 on L (API level 21) 199 // because the bug in framework b/19219128. 200 if (ApiHelper.IS_NEXUS_6 && ApiHelper.isLollipop()) { 201 return false; 202 } 203 Range<Integer> compensationRange = 204 mCameraCharacteristics.get(CameraCharacteristics.CONTROL_AE_COMPENSATION_RANGE); 205 return compensationRange.getLower() != 0 || compensationRange.getUpper() != 0; 206 } 207 208 @Override getMinExposureCompensation()209 public int getMinExposureCompensation() { 210 if (!isExposureCompensationSupported()) { 211 return -1; 212 } 213 Range<Integer> compensationRange = 214 mCameraCharacteristics.get(CameraCharacteristics.CONTROL_AE_COMPENSATION_RANGE); 215 return compensationRange.getLower(); 216 } 217 218 @Override getMaxExposureCompensation()219 public int getMaxExposureCompensation() { 220 if (!isExposureCompensationSupported()) { 221 return -1; 222 } 223 Range<Integer> compensationRange = 224 mCameraCharacteristics.get(CameraCharacteristics.CONTROL_AE_COMPENSATION_RANGE); 225 return compensationRange.getUpper(); 226 } 227 228 @Override getExposureCompensationStep()229 public float getExposureCompensationStep() { 230 if (!isExposureCompensationSupported()) { 231 return -1.0f; 232 } 233 Rational compensationStep = mCameraCharacteristics.get( 234 CameraCharacteristics.CONTROL_AE_COMPENSATION_STEP); 235 return (float) compensationStep.getNumerator() / compensationStep.getDenominator(); 236 } 237 238 @Override isAutoFocusSupported()239 public boolean isAutoFocusSupported() { 240 Integer maxAfRegions = mCameraCharacteristics.get( 241 CameraCharacteristics.CONTROL_MAX_REGIONS_AF); 242 // Auto-Focus is supported if the device supports one or more AF regions 243 return maxAfRegions != null && maxAfRegions > 0; 244 } 245 246 @Override isAutoExposureSupported()247 public boolean isAutoExposureSupported() { 248 Integer maxAeRegions = mCameraCharacteristics.get( 249 CameraCharacteristics.CONTROL_MAX_REGIONS_AE); 250 // Auto-Exposure is supported if the device supports one or more AE regions 251 return maxAeRegions != null && maxAeRegions > 0; 252 } 253 } 254