LegacyRequestMapper.java revision 72a23d7b50afe2c2eba999da718864dce79f44bd
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
17package android.hardware.camera2.legacy;
18
19import android.graphics.Rect;
20import android.hardware.Camera;
21import android.hardware.Camera.Parameters;
22import android.hardware.camera2.CameraCharacteristics;
23import android.hardware.camera2.CaptureRequest;
24import android.hardware.camera2.params.MeteringRectangle;
25import android.hardware.camera2.utils.ListUtils;
26import android.hardware.camera2.utils.ParamsUtils;
27import android.location.Location;
28import android.util.Log;
29import android.util.Range;
30import android.util.Size;
31
32import java.util.ArrayList;
33import java.util.Arrays;
34import java.util.List;
35import java.util.Objects;
36
37import static com.android.internal.util.Preconditions.*;
38import static android.hardware.camera2.CaptureRequest.*;
39
40/**
41 * Provide legacy-specific implementations of camera2 CaptureRequest for legacy devices.
42 */
43@SuppressWarnings("deprecation")
44public 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            Integer orientation = request.get(CaptureRequest.JPEG_ORIENTATION);
403            params.setRotation(ParamsUtils.getOrDefault(request, JPEG_ORIENTATION,
404                    (orientation == null) ? 0 : orientation));
405        }
406
407        // jpeg.quality
408        {
409            params.setJpegQuality(0xFF & ParamsUtils.getOrDefault(request, JPEG_QUALITY,
410                    DEFAULT_JPEG_QUALITY));
411        }
412
413        // jpeg.thumbnailQuality
414        {
415            params.setJpegThumbnailQuality(0xFF & ParamsUtils.getOrDefault(request,
416                    JPEG_THUMBNAIL_QUALITY, DEFAULT_JPEG_QUALITY));
417        }
418
419        // jpeg.thumbnailSize
420        {
421            List<Camera.Size> sizes = params.getSupportedJpegThumbnailSizes();
422
423            if (sizes != null && sizes.size() > 0) {
424                Size s = request.get(JPEG_THUMBNAIL_SIZE);
425                boolean invalidSize = (s == null) ? false : !ParameterUtils.containsSize(sizes,
426                        s.getWidth(), s.getHeight());
427                if (invalidSize) {
428                    Log.w(TAG, "Invalid JPEG thumbnail size set " + s + ", skipping thumbnail...");
429                }
430                if (s == null || invalidSize) {
431                    // (0,0) = "no thumbnail" in Camera API 1
432                    params.setJpegThumbnailSize(/*width*/0, /*height*/0);
433                } else {
434                    params.setJpegThumbnailSize(s.getWidth(), s.getHeight());
435                }
436            }
437        }
438
439        /*
440         * noiseReduction.*
441         */
442        // noiseReduction.mode
443        {
444            int mode = ParamsUtils.getOrDefault(request,
445                    NOISE_REDUCTION_MODE,
446                    /*defaultValue*/NOISE_REDUCTION_MODE_FAST);
447
448            if (mode != NOISE_REDUCTION_MODE_FAST) {
449                Log.w(TAG, "convertRequestToMetadata - Ignoring unsupported " +
450                        "noiseReduction.mode = " + mode);
451            }
452        }
453    }
454
455    private static boolean checkForCompleteGpsData(Location location) {
456        return location != null && location.getProvider() != null && location.getTime() != 0;
457    }
458
459    static int filterSupportedCaptureIntent(int captureIntent) {
460        switch (captureIntent) {
461            case CONTROL_CAPTURE_INTENT_CUSTOM:
462            case CONTROL_CAPTURE_INTENT_PREVIEW:
463            case CONTROL_CAPTURE_INTENT_STILL_CAPTURE:
464            case CONTROL_CAPTURE_INTENT_VIDEO_RECORD:
465            case CONTROL_CAPTURE_INTENT_VIDEO_SNAPSHOT:
466                break;
467            case CONTROL_CAPTURE_INTENT_ZERO_SHUTTER_LAG:
468            case CONTROL_CAPTURE_INTENT_MANUAL:
469                captureIntent = CONTROL_CAPTURE_INTENT_PREVIEW;
470                Log.w(TAG, "Unsupported control.captureIntent value " + captureIntent
471                        + "; default to PREVIEW");
472            default:
473                captureIntent = CONTROL_CAPTURE_INTENT_PREVIEW;
474                Log.w(TAG, "Unknown control.captureIntent value " + captureIntent
475                        + "; default to PREVIEW");
476        }
477
478        return captureIntent;
479    }
480
481    private static List<Camera.Area> convertMeteringRegionsToLegacy(
482            Rect activeArray, ParameterUtils.ZoomData zoomData,
483            MeteringRectangle[] meteringRegions, int maxNumMeteringAreas, String regionName) {
484        if (meteringRegions == null || maxNumMeteringAreas <= 0) {
485            if (maxNumMeteringAreas > 0) {
486                return Arrays.asList(ParameterUtils.CAMERA_AREA_DEFAULT);
487            } else {
488                return null;
489            }
490        }
491
492        // Add all non-zero weight regions to the list
493        List<MeteringRectangle> meteringRectangleList = new ArrayList<>();
494        for (MeteringRectangle rect : meteringRegions) {
495            if (rect.getMeteringWeight() != MeteringRectangle.METERING_WEIGHT_DONT_CARE) {
496                meteringRectangleList.add(rect);
497            }
498        }
499
500        if (meteringRectangleList.size() == 0) {
501            Log.w(TAG, "Only received metering rectangles with weight 0.");
502            return Arrays.asList(ParameterUtils.CAMERA_AREA_DEFAULT);
503        }
504
505        // Ignore any regions beyond our maximum supported count
506        int countMeteringAreas =
507                Math.min(maxNumMeteringAreas, meteringRectangleList.size());
508        List<Camera.Area> meteringAreaList = new ArrayList<>(countMeteringAreas);
509
510        for (int i = 0; i < countMeteringAreas; ++i) {
511            MeteringRectangle rect = meteringRectangleList.get(i);
512
513            ParameterUtils.MeteringData meteringData =
514                    ParameterUtils.convertMeteringRectangleToLegacy(activeArray, rect, zoomData);
515            meteringAreaList.add(meteringData.meteringArea);
516        }
517
518        if (maxNumMeteringAreas < meteringRectangleList.size()) {
519            Log.w(TAG,
520                    "convertMeteringRegionsToLegacy - Too many requested " + regionName +
521                            " regions, ignoring all beyond the first " + maxNumMeteringAreas);
522        }
523
524        if (VERBOSE) {
525            Log.v(TAG, "convertMeteringRegionsToLegacy - " + regionName + " areas = "
526                    + ParameterUtils.stringFromAreaList(meteringAreaList));
527        }
528
529        return meteringAreaList;
530    }
531
532    private static void mapAeAndFlashMode(CaptureRequest r, /*out*/Parameters p) {
533        int flashMode = ParamsUtils.getOrDefault(r, FLASH_MODE, FLASH_MODE_OFF);
534        int aeMode = ParamsUtils.getOrDefault(r, CONTROL_AE_MODE, CONTROL_AE_MODE_ON);
535
536        List<String> supportedFlashModes = p.getSupportedFlashModes();
537
538        String flashModeSetting = null;
539
540        // Flash is OFF by default, on cameras that support flash
541        if (ListUtils.listContains(supportedFlashModes, Parameters.FLASH_MODE_OFF)) {
542            flashModeSetting = Parameters.FLASH_MODE_OFF;
543        }
544
545        /*
546         * Map all of the control.aeMode* enums, but ignore AE_MODE_OFF since we never support it
547         */
548
549        // Ignore flash.mode controls unless aeMode == ON
550        if (aeMode == CONTROL_AE_MODE_ON) {
551            if (flashMode == FLASH_MODE_TORCH) {
552                    if (ListUtils.listContains(supportedFlashModes, Parameters.FLASH_MODE_TORCH)) {
553                        flashModeSetting = Parameters.FLASH_MODE_TORCH;
554                    } else {
555                        Log.w(TAG, "mapAeAndFlashMode - Ignore flash.mode == TORCH;" +
556                                "camera does not support it");
557                    }
558            } else if (flashMode == FLASH_MODE_SINGLE) {
559                if (ListUtils.listContains(supportedFlashModes, Parameters.FLASH_MODE_ON)) {
560                    flashModeSetting = Parameters.FLASH_MODE_ON;
561                } else {
562                    Log.w(TAG, "mapAeAndFlashMode - Ignore flash.mode == SINGLE;" +
563                            "camera does not support it");
564                }
565            } else {
566                // Use the default FLASH_MODE_OFF
567            }
568        } else if (aeMode == CONTROL_AE_MODE_ON_ALWAYS_FLASH) {
569                if (ListUtils.listContains(supportedFlashModes, Parameters.FLASH_MODE_ON)) {
570                    flashModeSetting = Parameters.FLASH_MODE_ON;
571                } else {
572                    Log.w(TAG, "mapAeAndFlashMode - Ignore control.aeMode == ON_ALWAYS_FLASH;" +
573                            "camera does not support it");
574                }
575        } else if (aeMode == CONTROL_AE_MODE_ON_AUTO_FLASH) {
576            if (ListUtils.listContains(supportedFlashModes, Parameters.FLASH_MODE_AUTO)) {
577                flashModeSetting = Parameters.FLASH_MODE_AUTO;
578            } else {
579                Log.w(TAG, "mapAeAndFlashMode - Ignore control.aeMode == ON_AUTO_FLASH;" +
580                        "camera does not support it");
581            }
582        } else if (aeMode == CONTROL_AE_MODE_ON_AUTO_FLASH_REDEYE) {
583                if (ListUtils.listContains(supportedFlashModes, Parameters.FLASH_MODE_RED_EYE)) {
584                    flashModeSetting = Parameters.FLASH_MODE_RED_EYE;
585                } else {
586                    Log.w(TAG, "mapAeAndFlashMode - Ignore control.aeMode == ON_AUTO_FLASH_REDEYE;"
587                            + "camera does not support it");
588                }
589        } else {
590            // Default to aeMode == ON, flash = OFF
591        }
592
593        if (flashModeSetting != null) {
594            p.setFlashMode(flashModeSetting);
595        }
596
597        if (VERBOSE) {
598                Log.v(TAG,
599                        "mapAeAndFlashMode - set flash.mode (api1) to " + flashModeSetting
600                        + ", requested (api2) " + flashMode
601                        + ", supported (api1) " + ListUtils.listToString(supportedFlashModes));
602        }
603    }
604
605    /**
606     * Returns null if the anti-banding mode enum is not supported.
607     */
608    private static String convertAeAntiBandingModeToLegacy(int mode) {
609        switch (mode) {
610            case CONTROL_AE_ANTIBANDING_MODE_OFF: {
611                return Parameters.ANTIBANDING_OFF;
612            }
613            case CONTROL_AE_ANTIBANDING_MODE_50HZ: {
614                return Parameters.ANTIBANDING_50HZ;
615            }
616            case CONTROL_AE_ANTIBANDING_MODE_60HZ: {
617                return Parameters.ANTIBANDING_60HZ;
618            }
619            case CONTROL_AE_ANTIBANDING_MODE_AUTO: {
620                return Parameters.ANTIBANDING_AUTO;
621            }
622            default: {
623                return null;
624            }
625        }
626    }
627
628    private static int[] convertAeFpsRangeToLegacy(Range<Integer> fpsRange) {
629        int[] legacyFps = new int[2];
630        legacyFps[Parameters.PREVIEW_FPS_MIN_INDEX] = fpsRange.getLower();
631        legacyFps[Parameters.PREVIEW_FPS_MAX_INDEX] = fpsRange.getUpper();
632        return legacyFps;
633    }
634
635    private static String convertAwbModeToLegacy(int mode) {
636        switch (mode) {
637            case CONTROL_AWB_MODE_AUTO:
638                return Camera.Parameters.WHITE_BALANCE_AUTO;
639            case CONTROL_AWB_MODE_INCANDESCENT:
640                return Camera.Parameters.WHITE_BALANCE_INCANDESCENT;
641            case CONTROL_AWB_MODE_FLUORESCENT:
642                return Camera.Parameters.WHITE_BALANCE_FLUORESCENT;
643            case CONTROL_AWB_MODE_WARM_FLUORESCENT:
644                return Camera.Parameters.WHITE_BALANCE_WARM_FLUORESCENT;
645            case CONTROL_AWB_MODE_DAYLIGHT:
646                return Camera.Parameters.WHITE_BALANCE_DAYLIGHT;
647            case CONTROL_AWB_MODE_CLOUDY_DAYLIGHT:
648                return Camera.Parameters.WHITE_BALANCE_CLOUDY_DAYLIGHT;
649            case CONTROL_AWB_MODE_TWILIGHT:
650                return Camera.Parameters.WHITE_BALANCE_TWILIGHT;
651            case CONTROL_AWB_MODE_SHADE:
652                return Parameters.WHITE_BALANCE_SHADE;
653            default:
654                Log.w(TAG, "convertAwbModeToLegacy - unrecognized control.awbMode" + mode);
655                return Camera.Parameters.WHITE_BALANCE_AUTO;
656        }
657    }
658
659
660    /**
661     * Return {@code null} if the value is not supported, otherwise return the retrieved key's
662     * value from the request (or the default value if it wasn't set).
663     *
664     * <p>If the fetched value in the request is equivalent to {@code allowedValue},
665     * then omit the warning (e.g. turning off AF lock on a camera
666     * that always has the AF lock turned off is a silent no-op), but still return {@code null}.</p>
667     *
668     * <p>Logs a warning to logcat if the key is not supported by api1 camera device.</p.
669     */
670    private static <T> T getIfSupported(
671            CaptureRequest r, CaptureRequest.Key<T> key, T defaultValue, boolean isSupported,
672            T allowedValue) {
673        T val = ParamsUtils.getOrDefault(r, key, defaultValue);
674
675        if (!isSupported) {
676            if (!Objects.equals(val, allowedValue)) {
677                Log.w(TAG, key.getName() + " is not supported; ignoring requested value " + val);
678            }
679            return null;
680        }
681
682        return val;
683    }
684}
685