Home | History | Annotate | Download | only in v2
      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 
     55     public OneCameraCharacteristicsImpl(CameraCharacteristics cameraCharacteristics) {
     56         mCameraCharacteristics = cameraCharacteristics;
     57     }
     58 
     59     @Override
     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
     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
     97     public int getSensorOrientation() {
     98         return mCameraCharacteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
     99     }
    100 
    101     @Override
    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
    112     public Rect getSensorInfoActiveArraySize() {
    113         return mCameraCharacteristics.get(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE);
    114     }
    115 
    116     @Override
    117     public float getAvailableMaxDigitalZoom() {
    118         return mCameraCharacteristics.get(CameraCharacteristics.SCALER_AVAILABLE_MAX_DIGITAL_ZOOM);
    119     }
    120 
    121     @Override
    122     public boolean isFlashSupported() {
    123         return mCameraCharacteristics.get(CameraCharacteristics.FLASH_INFO_AVAILABLE);
    124     }
    125 
    126     @Override
    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
    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
    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
    187     public LinearScale getLensFocusRange() {
    188         return LensRangeCalculator.getDiopterToRatioCalculator(mCameraCharacteristics);
    189     }
    190 
    191     @Override
    192     public List<Float> getAvailableFocalLengths() {
    193         return Floats.asList(mCameraCharacteristics.get(CameraCharacteristics.LENS_INFO_AVAILABLE_FOCAL_LENGTHS));
    194     }
    195 
    196     @Override
    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
    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
    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
    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
    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
    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