Home | History | Annotate | Download | only in legacy
      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 android.hardware.camera2.legacy;
     18 
     19 import android.graphics.Rect;
     20 import android.hardware.Camera;
     21 import android.hardware.Camera.Parameters;
     22 import android.hardware.camera2.CameraCharacteristics;
     23 import android.hardware.camera2.CaptureRequest;
     24 import android.hardware.camera2.params.MeteringRectangle;
     25 import android.hardware.camera2.utils.ListUtils;
     26 import android.hardware.camera2.utils.ParamsUtils;
     27 import android.location.Location;
     28 import android.util.Log;
     29 import android.util.Range;
     30 import android.util.Size;
     31 
     32 import java.util.ArrayList;
     33 import java.util.Arrays;
     34 import java.util.List;
     35 import java.util.Objects;
     36 
     37 import static android.hardware.camera2.CaptureRequest.*;
     38 
     39 /**
     40  * Provide legacy-specific implementations of camera2 CaptureRequest for legacy devices.
     41  */
     42 @SuppressWarnings("deprecation")
     43 public class LegacyRequestMapper {
     44     private static final String TAG = "LegacyRequestMapper";
     45     private static final boolean DEBUG = false;
     46 
     47     /** Default quality for android.jpeg.quality, android.jpeg.thumbnailQuality */
     48     private static final byte DEFAULT_JPEG_QUALITY = 85;
     49 
     50     /**
     51      * Set the legacy parameters using the {@link LegacyRequest legacy request}.
     52      *
     53      * <p>The legacy request's parameters are changed as a side effect of calling this
     54      * method.</p>
     55      *
     56      * @param legacyRequest a non-{@code null} legacy request
     57      */
     58     public static void convertRequestMetadata(LegacyRequest legacyRequest) {
     59         CameraCharacteristics characteristics = legacyRequest.characteristics;
     60         CaptureRequest request = legacyRequest.captureRequest;
     61         Size previewSize = legacyRequest.previewSize;
     62         Camera.Parameters params = legacyRequest.parameters;
     63 
     64         Rect activeArray = characteristics.get(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE);
     65 
     66         /*
     67          * scaler.cropRegion
     68          */
     69         ParameterUtils.ZoomData zoomData;
     70         {
     71             zoomData = ParameterUtils.convertScalerCropRegion(activeArray,
     72                     request.get(SCALER_CROP_REGION),
     73                     previewSize,
     74                     params);
     75 
     76             if (params.isZoomSupported()) {
     77                 params.setZoom(zoomData.zoomIndex);
     78             } else if (DEBUG) {
     79                 Log.v(TAG, "convertRequestToMetadata - zoom is not supported");
     80             }
     81         }
     82 
     83         /*
     84          * colorCorrection.*
     85          */
     86         // colorCorrection.aberrationMode
     87         {
     88             int aberrationMode = ParamsUtils.getOrDefault(request,
     89                     COLOR_CORRECTION_ABERRATION_MODE,
     90                     /*defaultValue*/COLOR_CORRECTION_ABERRATION_MODE_FAST);
     91 
     92             if (aberrationMode != COLOR_CORRECTION_ABERRATION_MODE_FAST &&
     93                     aberrationMode != COLOR_CORRECTION_ABERRATION_MODE_HIGH_QUALITY) {
     94                 Log.w(TAG, "convertRequestToMetadata - Ignoring unsupported " +
     95                         "colorCorrection.aberrationMode = " + aberrationMode);
     96             }
     97         }
     98 
     99         /*
    100          * control.ae*
    101          */
    102         // control.aeAntibandingMode
    103         {
    104         String legacyMode;
    105             Integer antiBandingMode = request.get(CONTROL_AE_ANTIBANDING_MODE);
    106             if (antiBandingMode != null) {
    107                 legacyMode = convertAeAntiBandingModeToLegacy(antiBandingMode);
    108             } else {
    109                 legacyMode = ListUtils.listSelectFirstFrom(params.getSupportedAntibanding(),
    110                         new String[] {
    111                             Parameters.ANTIBANDING_AUTO,
    112                             Parameters.ANTIBANDING_OFF,
    113                             Parameters.ANTIBANDING_50HZ,
    114                             Parameters.ANTIBANDING_60HZ,
    115                         });
    116             }
    117 
    118             if (legacyMode != null) {
    119                 params.setAntibanding(legacyMode);
    120             }
    121         }
    122 
    123         /*
    124          * control.aeRegions, afRegions
    125          */
    126         {
    127             // aeRegions
    128             {
    129                 // Use aeRegions if available, fall back to using awbRegions if present
    130                 MeteringRectangle[] aeRegions = request.get(CONTROL_AE_REGIONS);
    131                 if (request.get(CONTROL_AWB_REGIONS) != null) {
    132                     Log.w(TAG, "convertRequestMetadata - control.awbRegions setting is not " +
    133                             "supported, ignoring value");
    134                 }
    135                 int maxNumMeteringAreas = params.getMaxNumMeteringAreas();
    136                 List<Camera.Area> meteringAreaList = convertMeteringRegionsToLegacy(
    137                         activeArray, zoomData, aeRegions, maxNumMeteringAreas,
    138                         /*regionName*/"AE");
    139 
    140                 // WAR: for b/17252693, some devices can't handle params.setFocusAreas(null).
    141                 if (maxNumMeteringAreas > 0) {
    142                     params.setMeteringAreas(meteringAreaList);
    143                 }
    144             }
    145 
    146             // afRegions
    147             {
    148                 MeteringRectangle[] afRegions = request.get(CONTROL_AF_REGIONS);
    149                 int maxNumFocusAreas = params.getMaxNumFocusAreas();
    150                 List<Camera.Area> focusAreaList = convertMeteringRegionsToLegacy(
    151                         activeArray, zoomData, afRegions, maxNumFocusAreas,
    152                         /*regionName*/"AF");
    153 
    154                 // WAR: for b/17252693, some devices can't handle params.setFocusAreas(null).
    155                 if (maxNumFocusAreas > 0) {
    156                     params.setFocusAreas(focusAreaList);
    157                 }
    158             }
    159         }
    160 
    161         // control.aeTargetFpsRange
    162         Range<Integer> aeFpsRange = request.get(CONTROL_AE_TARGET_FPS_RANGE);
    163         if (aeFpsRange != null) {
    164             int[] legacyFps = convertAeFpsRangeToLegacy(aeFpsRange);
    165 
    166             int[] rangeToApply = null;
    167             for(int[] range : params.getSupportedPreviewFpsRange()) {
    168                 // Round range up/down to integer FPS value
    169                 int intRangeLow = (int) Math.floor(range[0] / 1000.0) * 1000;
    170                 int intRangeHigh = (int) Math.ceil(range[1] / 1000.0) * 1000;
    171                 if (legacyFps[0] == intRangeLow && legacyFps[1] == intRangeHigh) {
    172                     rangeToApply = range;
    173                     break;
    174                 }
    175             }
    176             if (rangeToApply != null) {
    177                 params.setPreviewFpsRange(rangeToApply[Camera.Parameters.PREVIEW_FPS_MIN_INDEX],
    178                         rangeToApply[Camera.Parameters.PREVIEW_FPS_MAX_INDEX]);
    179             } else {
    180                 Log.w(TAG, "Unsupported FPS range set [" + legacyFps[0] + "," + legacyFps[1] + "]");
    181             }
    182         }
    183 
    184         /*
    185          * control
    186          */
    187 
    188         // control.aeExposureCompensation
    189         {
    190             Range<Integer> compensationRange =
    191                     characteristics.get(CameraCharacteristics.CONTROL_AE_COMPENSATION_RANGE);
    192             int compensation = ParamsUtils.getOrDefault(request,
    193                     CONTROL_AE_EXPOSURE_COMPENSATION,
    194                     /*defaultValue*/0);
    195 
    196             if (!compensationRange.contains(compensation)) {
    197                 Log.w(TAG,
    198                         "convertRequestMetadata - control.aeExposureCompensation " +
    199                         "is out of range, ignoring value");
    200                 compensation = 0;
    201             }
    202 
    203             params.setExposureCompensation(compensation);
    204         }
    205 
    206         // control.aeLock
    207         {
    208             Boolean aeLock = getIfSupported(request, CONTROL_AE_LOCK, /*defaultValue*/false,
    209                     params.isAutoExposureLockSupported(),
    210                     /*allowedValue*/false);
    211 
    212             if (aeLock != null) {
    213                 params.setAutoExposureLock(aeLock);
    214             }
    215 
    216             if (DEBUG) {
    217                 Log.v(TAG, "convertRequestToMetadata - control.aeLock set to " + aeLock);
    218             }
    219 
    220             // TODO: Don't add control.aeLock to availableRequestKeys if it's not supported
    221         }
    222 
    223         // control.aeMode, flash.mode
    224         mapAeAndFlashMode(request, /*out*/params);
    225 
    226         // control.afMode
    227         {
    228             int afMode = ParamsUtils.getOrDefault(request, CONTROL_AF_MODE,
    229                     /*defaultValue*/CONTROL_AF_MODE_OFF);
    230             String focusMode = LegacyMetadataMapper.convertAfModeToLegacy(afMode,
    231                     params.getSupportedFocusModes());
    232 
    233             if (focusMode != null) {
    234                 params.setFocusMode(focusMode);
    235             }
    236 
    237             if (DEBUG) {
    238                 Log.v(TAG, "convertRequestToMetadata - control.afMode "
    239                         + afMode + " mapped to " + focusMode);
    240             }
    241         }
    242 
    243         // control.awbMode
    244         {
    245             Integer awbMode = getIfSupported(request, CONTROL_AWB_MODE,
    246                     /*defaultValue*/CONTROL_AWB_MODE_AUTO,
    247                     params.getSupportedWhiteBalance() != null,
    248                     /*allowedValue*/CONTROL_AWB_MODE_AUTO);
    249 
    250             String whiteBalanceMode = null;
    251             if (awbMode != null) { // null iff AWB is not supported by camera1 api
    252                 whiteBalanceMode = convertAwbModeToLegacy(awbMode);
    253                 params.setWhiteBalance(whiteBalanceMode);
    254             }
    255 
    256             if (DEBUG) {
    257                 Log.v(TAG, "convertRequestToMetadata - control.awbMode "
    258                         + awbMode + " mapped to " + whiteBalanceMode);
    259             }
    260         }
    261 
    262         // control.awbLock
    263         {
    264             Boolean awbLock = getIfSupported(request, CONTROL_AWB_LOCK, /*defaultValue*/false,
    265                     params.isAutoWhiteBalanceLockSupported(),
    266                     /*allowedValue*/false);
    267 
    268             if (awbLock != null) {
    269                 params.setAutoWhiteBalanceLock(awbLock);
    270             }
    271 
    272          // TODO: Don't add control.awbLock to availableRequestKeys if it's not supported
    273         }
    274 
    275         // control.captureIntent
    276         {
    277             int captureIntent = ParamsUtils.getOrDefault(request,
    278                     CONTROL_CAPTURE_INTENT,
    279                     /*defaultValue*/CONTROL_CAPTURE_INTENT_PREVIEW);
    280 
    281             captureIntent = filterSupportedCaptureIntent(captureIntent);
    282 
    283             params.setRecordingHint(
    284                     captureIntent == CONTROL_CAPTURE_INTENT_VIDEO_RECORD ||
    285                     captureIntent == CONTROL_CAPTURE_INTENT_VIDEO_SNAPSHOT);
    286         }
    287 
    288         // control.videoStabilizationMode
    289         {
    290             Integer stabMode = getIfSupported(request, CONTROL_VIDEO_STABILIZATION_MODE,
    291                     /*defaultValue*/CONTROL_VIDEO_STABILIZATION_MODE_OFF,
    292                     params.isVideoStabilizationSupported(),
    293                     /*allowedValue*/CONTROL_VIDEO_STABILIZATION_MODE_OFF);
    294 
    295             if (stabMode != null) {
    296                 params.setVideoStabilization(stabMode == CONTROL_VIDEO_STABILIZATION_MODE_ON);
    297             }
    298         }
    299 
    300         // lens.focusDistance
    301         {
    302             boolean infinityFocusSupported =
    303                     ListUtils.listContains(params.getSupportedFocusModes(),
    304                             Parameters.FOCUS_MODE_INFINITY);
    305             Float focusDistance = getIfSupported(request, LENS_FOCUS_DISTANCE,
    306                     /*defaultValue*/0f, infinityFocusSupported, /*allowedValue*/0f);
    307 
    308             if (focusDistance == null || focusDistance != 0f) {
    309                 Log.w(TAG,
    310                         "convertRequestToMetadata - Ignoring android.lens.focusDistance "
    311                                 + infinityFocusSupported + ", only 0.0f is supported");
    312             }
    313         }
    314 
    315         // control.sceneMode, control.mode
    316         {
    317             // TODO: Map FACE_PRIORITY scene mode to face detection.
    318 
    319             if (params.getSupportedSceneModes() != null) {
    320                 int controlMode = ParamsUtils.getOrDefault(request, CONTROL_MODE,
    321                     /*defaultValue*/CONTROL_MODE_AUTO);
    322                 String modeToSet;
    323                 switch (controlMode) {
    324                     case CONTROL_MODE_USE_SCENE_MODE: {
    325                         int sceneMode = ParamsUtils.getOrDefault(request, CONTROL_SCENE_MODE,
    326                                 /*defaultValue*/CONTROL_SCENE_MODE_DISABLED);
    327                         String legacySceneMode = LegacyMetadataMapper.
    328                                 convertSceneModeToLegacy(sceneMode);
    329                         if (legacySceneMode != null) {
    330                             modeToSet = legacySceneMode;
    331                         } else {
    332                             modeToSet = Parameters.SCENE_MODE_AUTO;
    333                             Log.w(TAG, "Skipping unknown requested scene mode: " + sceneMode);
    334                         }
    335                         break;
    336                     }
    337                     case CONTROL_MODE_AUTO: {
    338                         modeToSet = Parameters.SCENE_MODE_AUTO;
    339                         break;
    340                     }
    341                     default: {
    342                         Log.w(TAG, "Control mode " + controlMode +
    343                                 " is unsupported, defaulting to AUTO");
    344                         modeToSet = Parameters.SCENE_MODE_AUTO;
    345                     }
    346                 }
    347                 params.setSceneMode(modeToSet);
    348             }
    349         }
    350 
    351         // control.effectMode
    352         {
    353             if (params.getSupportedColorEffects() != null) {
    354                 int effectMode = ParamsUtils.getOrDefault(request, CONTROL_EFFECT_MODE,
    355                     /*defaultValue*/CONTROL_EFFECT_MODE_OFF);
    356                 String legacyEffectMode = LegacyMetadataMapper.convertEffectModeToLegacy(effectMode);
    357                 if (legacyEffectMode != null) {
    358                     params.setColorEffect(legacyEffectMode);
    359                 } else {
    360                     params.setColorEffect(Parameters.EFFECT_NONE);
    361                     Log.w(TAG, "Skipping unknown requested effect mode: " + effectMode);
    362                 }
    363             }
    364         }
    365 
    366         /*
    367          * sensor
    368          */
    369 
    370         // sensor.testPattern
    371         {
    372             int testPatternMode = ParamsUtils.getOrDefault(request, SENSOR_TEST_PATTERN_MODE,
    373                     /*defaultValue*/SENSOR_TEST_PATTERN_MODE_OFF);
    374             if (testPatternMode != SENSOR_TEST_PATTERN_MODE_OFF) {
    375                 Log.w(TAG, "convertRequestToMetadata - ignoring sensor.testPatternMode "
    376                         + testPatternMode + "; only OFF is supported");
    377             }
    378         }
    379 
    380         /*
    381          * jpeg.*
    382          */
    383 
    384         // jpeg.gpsLocation
    385         {
    386             Location location = request.get(JPEG_GPS_LOCATION);
    387             if (location != null) {
    388                 if (checkForCompleteGpsData(location)) {
    389                     params.setGpsAltitude(location.getAltitude());
    390                     params.setGpsLatitude(location.getLatitude());
    391                     params.setGpsLongitude(location.getLongitude());
    392                     params.setGpsProcessingMethod(location.getProvider().toUpperCase());
    393                     params.setGpsTimestamp(location.getTime());
    394                 } else {
    395                     Log.w(TAG, "Incomplete GPS parameters provided in location " + location);
    396                 }
    397             } else {
    398                 params.removeGpsData();
    399             }
    400         }
    401 
    402         // jpeg.orientation
    403         {
    404             Integer orientation = request.get(CaptureRequest.JPEG_ORIENTATION);
    405             params.setRotation(ParamsUtils.getOrDefault(request, JPEG_ORIENTATION,
    406                     (orientation == null) ? 0 : orientation));
    407         }
    408 
    409         // jpeg.quality
    410         {
    411             params.setJpegQuality(0xFF & ParamsUtils.getOrDefault(request, JPEG_QUALITY,
    412                     DEFAULT_JPEG_QUALITY));
    413         }
    414 
    415         // jpeg.thumbnailQuality
    416         {
    417             params.setJpegThumbnailQuality(0xFF & ParamsUtils.getOrDefault(request,
    418                     JPEG_THUMBNAIL_QUALITY, DEFAULT_JPEG_QUALITY));
    419         }
    420 
    421         // jpeg.thumbnailSize
    422         {
    423             List<Camera.Size> sizes = params.getSupportedJpegThumbnailSizes();
    424 
    425             if (sizes != null && sizes.size() > 0) {
    426                 Size s = request.get(JPEG_THUMBNAIL_SIZE);
    427                 boolean invalidSize = (s == null) ? false : !ParameterUtils.containsSize(sizes,
    428                         s.getWidth(), s.getHeight());
    429                 if (invalidSize) {
    430                     Log.w(TAG, "Invalid JPEG thumbnail size set " + s + ", skipping thumbnail...");
    431                 }
    432                 if (s == null || invalidSize) {
    433                     // (0,0) = "no thumbnail" in Camera API 1
    434                     params.setJpegThumbnailSize(/*width*/0, /*height*/0);
    435                 } else {
    436                     params.setJpegThumbnailSize(s.getWidth(), s.getHeight());
    437                 }
    438             }
    439         }
    440 
    441         /*
    442          * noiseReduction.*
    443          */
    444         // noiseReduction.mode
    445         {
    446             int mode = ParamsUtils.getOrDefault(request,
    447                     NOISE_REDUCTION_MODE,
    448                     /*defaultValue*/NOISE_REDUCTION_MODE_FAST);
    449 
    450             if (mode != NOISE_REDUCTION_MODE_FAST &&
    451                     mode != NOISE_REDUCTION_MODE_HIGH_QUALITY) {
    452                 Log.w(TAG, "convertRequestToMetadata - Ignoring unsupported " +
    453                         "noiseReduction.mode = " + mode);
    454             }
    455         }
    456     }
    457 
    458     private static boolean checkForCompleteGpsData(Location location) {
    459         return location != null && location.getProvider() != null && location.getTime() != 0;
    460     }
    461 
    462     static int filterSupportedCaptureIntent(int captureIntent) {
    463         switch (captureIntent) {
    464             case CONTROL_CAPTURE_INTENT_CUSTOM:
    465             case CONTROL_CAPTURE_INTENT_PREVIEW:
    466             case CONTROL_CAPTURE_INTENT_STILL_CAPTURE:
    467             case CONTROL_CAPTURE_INTENT_VIDEO_RECORD:
    468             case CONTROL_CAPTURE_INTENT_VIDEO_SNAPSHOT:
    469                 break;
    470             case CONTROL_CAPTURE_INTENT_ZERO_SHUTTER_LAG:
    471             case CONTROL_CAPTURE_INTENT_MANUAL:
    472                 captureIntent = CONTROL_CAPTURE_INTENT_PREVIEW;
    473                 Log.w(TAG, "Unsupported control.captureIntent value " + captureIntent
    474                         + "; default to PREVIEW");
    475             default:
    476                 captureIntent = CONTROL_CAPTURE_INTENT_PREVIEW;
    477                 Log.w(TAG, "Unknown control.captureIntent value " + captureIntent
    478                         + "; default to PREVIEW");
    479         }
    480 
    481         return captureIntent;
    482     }
    483 
    484     private static List<Camera.Area> convertMeteringRegionsToLegacy(
    485             Rect activeArray, ParameterUtils.ZoomData zoomData,
    486             MeteringRectangle[] meteringRegions, int maxNumMeteringAreas, String regionName) {
    487         if (meteringRegions == null || maxNumMeteringAreas <= 0) {
    488             if (maxNumMeteringAreas > 0) {
    489                 return Arrays.asList(ParameterUtils.CAMERA_AREA_DEFAULT);
    490             } else {
    491                 return null;
    492             }
    493         }
    494 
    495         // Add all non-zero weight regions to the list
    496         List<MeteringRectangle> meteringRectangleList = new ArrayList<>();
    497         for (MeteringRectangle rect : meteringRegions) {
    498             if (rect.getMeteringWeight() != MeteringRectangle.METERING_WEIGHT_DONT_CARE) {
    499                 meteringRectangleList.add(rect);
    500             }
    501         }
    502 
    503         if (meteringRectangleList.size() == 0) {
    504             Log.w(TAG, "Only received metering rectangles with weight 0.");
    505             return Arrays.asList(ParameterUtils.CAMERA_AREA_DEFAULT);
    506         }
    507 
    508         // Ignore any regions beyond our maximum supported count
    509         int countMeteringAreas =
    510                 Math.min(maxNumMeteringAreas, meteringRectangleList.size());
    511         List<Camera.Area> meteringAreaList = new ArrayList<>(countMeteringAreas);
    512 
    513         for (int i = 0; i < countMeteringAreas; ++i) {
    514             MeteringRectangle rect = meteringRectangleList.get(i);
    515 
    516             ParameterUtils.MeteringData meteringData =
    517                     ParameterUtils.convertMeteringRectangleToLegacy(activeArray, rect, zoomData);
    518             meteringAreaList.add(meteringData.meteringArea);
    519         }
    520 
    521         if (maxNumMeteringAreas < meteringRectangleList.size()) {
    522             Log.w(TAG,
    523                     "convertMeteringRegionsToLegacy - Too many requested " + regionName +
    524                             " regions, ignoring all beyond the first " + maxNumMeteringAreas);
    525         }
    526 
    527         if (DEBUG) {
    528             Log.v(TAG, "convertMeteringRegionsToLegacy - " + regionName + " areas = "
    529                     + ParameterUtils.stringFromAreaList(meteringAreaList));
    530         }
    531 
    532         return meteringAreaList;
    533     }
    534 
    535     private static void mapAeAndFlashMode(CaptureRequest r, /*out*/Parameters p) {
    536         int flashMode = ParamsUtils.getOrDefault(r, FLASH_MODE, FLASH_MODE_OFF);
    537         int aeMode = ParamsUtils.getOrDefault(r, CONTROL_AE_MODE, CONTROL_AE_MODE_ON);
    538 
    539         List<String> supportedFlashModes = p.getSupportedFlashModes();
    540 
    541         String flashModeSetting = null;
    542 
    543         // Flash is OFF by default, on cameras that support flash
    544         if (ListUtils.listContains(supportedFlashModes, Parameters.FLASH_MODE_OFF)) {
    545             flashModeSetting = Parameters.FLASH_MODE_OFF;
    546         }
    547 
    548         /*
    549          * Map all of the control.aeMode* enums, but ignore AE_MODE_OFF since we never support it
    550          */
    551 
    552         // Ignore flash.mode controls unless aeMode == ON
    553         if (aeMode == CONTROL_AE_MODE_ON) {
    554             if (flashMode == FLASH_MODE_TORCH) {
    555                     if (ListUtils.listContains(supportedFlashModes, Parameters.FLASH_MODE_TORCH)) {
    556                         flashModeSetting = Parameters.FLASH_MODE_TORCH;
    557                     } else {
    558                         Log.w(TAG, "mapAeAndFlashMode - Ignore flash.mode == TORCH;" +
    559                                 "camera does not support it");
    560                     }
    561             } else if (flashMode == FLASH_MODE_SINGLE) {
    562                 if (ListUtils.listContains(supportedFlashModes, Parameters.FLASH_MODE_ON)) {
    563                     flashModeSetting = Parameters.FLASH_MODE_ON;
    564                 } else {
    565                     Log.w(TAG, "mapAeAndFlashMode - Ignore flash.mode == SINGLE;" +
    566                             "camera does not support it");
    567                 }
    568             } else {
    569                 // Use the default FLASH_MODE_OFF
    570             }
    571         } else if (aeMode == CONTROL_AE_MODE_ON_ALWAYS_FLASH) {
    572                 if (ListUtils.listContains(supportedFlashModes, Parameters.FLASH_MODE_ON)) {
    573                     flashModeSetting = Parameters.FLASH_MODE_ON;
    574                 } else {
    575                     Log.w(TAG, "mapAeAndFlashMode - Ignore control.aeMode == ON_ALWAYS_FLASH;" +
    576                             "camera does not support it");
    577                 }
    578         } else if (aeMode == CONTROL_AE_MODE_ON_AUTO_FLASH) {
    579             if (ListUtils.listContains(supportedFlashModes, Parameters.FLASH_MODE_AUTO)) {
    580                 flashModeSetting = Parameters.FLASH_MODE_AUTO;
    581             } else {
    582                 Log.w(TAG, "mapAeAndFlashMode - Ignore control.aeMode == ON_AUTO_FLASH;" +
    583                         "camera does not support it");
    584             }
    585         } else if (aeMode == CONTROL_AE_MODE_ON_AUTO_FLASH_REDEYE) {
    586                 if (ListUtils.listContains(supportedFlashModes, Parameters.FLASH_MODE_RED_EYE)) {
    587                     flashModeSetting = Parameters.FLASH_MODE_RED_EYE;
    588                 } else {
    589                     Log.w(TAG, "mapAeAndFlashMode - Ignore control.aeMode == ON_AUTO_FLASH_REDEYE;"
    590                             + "camera does not support it");
    591                 }
    592         } else {
    593             // Default to aeMode == ON, flash = OFF
    594         }
    595 
    596         if (flashModeSetting != null) {
    597             p.setFlashMode(flashModeSetting);
    598         }
    599 
    600         if (DEBUG) {
    601                 Log.v(TAG,
    602                         "mapAeAndFlashMode - set flash.mode (api1) to " + flashModeSetting
    603                         + ", requested (api2) " + flashMode
    604                         + ", supported (api1) " + ListUtils.listToString(supportedFlashModes));
    605         }
    606     }
    607 
    608     /**
    609      * Returns null if the anti-banding mode enum is not supported.
    610      */
    611     private static String convertAeAntiBandingModeToLegacy(int mode) {
    612         switch (mode) {
    613             case CONTROL_AE_ANTIBANDING_MODE_OFF: {
    614                 return Parameters.ANTIBANDING_OFF;
    615             }
    616             case CONTROL_AE_ANTIBANDING_MODE_50HZ: {
    617                 return Parameters.ANTIBANDING_50HZ;
    618             }
    619             case CONTROL_AE_ANTIBANDING_MODE_60HZ: {
    620                 return Parameters.ANTIBANDING_60HZ;
    621             }
    622             case CONTROL_AE_ANTIBANDING_MODE_AUTO: {
    623                 return Parameters.ANTIBANDING_AUTO;
    624             }
    625             default: {
    626                 return null;
    627             }
    628         }
    629     }
    630 
    631     private static int[] convertAeFpsRangeToLegacy(Range<Integer> fpsRange) {
    632         int[] legacyFps = new int[2];
    633         legacyFps[Parameters.PREVIEW_FPS_MIN_INDEX] = fpsRange.getLower() * 1000;
    634         legacyFps[Parameters.PREVIEW_FPS_MAX_INDEX] = fpsRange.getUpper() * 1000;
    635         return legacyFps;
    636     }
    637 
    638     private static String convertAwbModeToLegacy(int mode) {
    639         switch (mode) {
    640             case CONTROL_AWB_MODE_AUTO:
    641                 return Camera.Parameters.WHITE_BALANCE_AUTO;
    642             case CONTROL_AWB_MODE_INCANDESCENT:
    643                 return Camera.Parameters.WHITE_BALANCE_INCANDESCENT;
    644             case CONTROL_AWB_MODE_FLUORESCENT:
    645                 return Camera.Parameters.WHITE_BALANCE_FLUORESCENT;
    646             case CONTROL_AWB_MODE_WARM_FLUORESCENT:
    647                 return Camera.Parameters.WHITE_BALANCE_WARM_FLUORESCENT;
    648             case CONTROL_AWB_MODE_DAYLIGHT:
    649                 return Camera.Parameters.WHITE_BALANCE_DAYLIGHT;
    650             case CONTROL_AWB_MODE_CLOUDY_DAYLIGHT:
    651                 return Camera.Parameters.WHITE_BALANCE_CLOUDY_DAYLIGHT;
    652             case CONTROL_AWB_MODE_TWILIGHT:
    653                 return Camera.Parameters.WHITE_BALANCE_TWILIGHT;
    654             case CONTROL_AWB_MODE_SHADE:
    655                 return Parameters.WHITE_BALANCE_SHADE;
    656             default:
    657                 Log.w(TAG, "convertAwbModeToLegacy - unrecognized control.awbMode" + mode);
    658                 return Camera.Parameters.WHITE_BALANCE_AUTO;
    659         }
    660     }
    661 
    662 
    663     /**
    664      * Return {@code null} if the value is not supported, otherwise return the retrieved key's
    665      * value from the request (or the default value if it wasn't set).
    666      *
    667      * <p>If the fetched value in the request is equivalent to {@code allowedValue},
    668      * then omit the warning (e.g. turning off AF lock on a camera
    669      * that always has the AF lock turned off is a silent no-op), but still return {@code null}.</p>
    670      *
    671      * <p>Logs a warning to logcat if the key is not supported by api1 camera device.</p.
    672      */
    673     private static <T> T getIfSupported(
    674             CaptureRequest r, CaptureRequest.Key<T> key, T defaultValue, boolean isSupported,
    675             T allowedValue) {
    676         T val = ParamsUtils.getOrDefault(r, key, defaultValue);
    677 
    678         if (!isSupported) {
    679             if (!Objects.equals(val, allowedValue)) {
    680                 Log.w(TAG, key.getName() + " is not supported; ignoring requested value " + val);
    681             }
    682             return null;
    683         }
    684 
    685         return val;
    686     }
    687 }
    688