OSDN Git Service

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