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