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