LegacyRequestMapper.java revision ec743ee9a4b3111056b0ba9d2fa8e11d8c6c51aa
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 android.hardware.camera2.CaptureRequest.*;
38
39/**
40 * Provide legacy-specific implementations of camera2 CaptureRequest for legacy devices.
41 */
42@SuppressWarnings("deprecation")
43public class LegacyRequestMapper {
44    private static final String TAG = "LegacyRequestMapper";
45    private static final boolean DEBUG = false;
46
47    /** Default quality for android.jpeg.quality, android.jpeg.thumbnailQuality */
48    private static final byte DEFAULT_JPEG_QUALITY = 85;
49
50    /**
51     * Set the legacy parameters using the {@link LegacyRequest legacy request}.
52     *
53     * <p>The legacy request's parameters are changed as a side effect of calling this
54     * method.</p>
55     *
56     * @param legacyRequest a non-{@code null} legacy request
57     */
58    public static void convertRequestMetadata(LegacyRequest legacyRequest) {
59        CameraCharacteristics characteristics = legacyRequest.characteristics;
60        CaptureRequest request = legacyRequest.captureRequest;
61        Size previewSize = legacyRequest.previewSize;
62        Camera.Parameters params = legacyRequest.parameters;
63
64        Rect activeArray = characteristics.get(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE);
65
66        /*
67         * scaler.cropRegion
68         */
69        ParameterUtils.ZoomData zoomData;
70        {
71            zoomData = ParameterUtils.convertScalerCropRegion(activeArray,
72                    request.get(SCALER_CROP_REGION),
73                    previewSize,
74                    params);
75
76            if (params.isZoomSupported()) {
77                params.setZoom(zoomData.zoomIndex);
78            } else if (DEBUG) {
79                Log.v(TAG, "convertRequestToMetadata - zoom is not supported");
80            }
81        }
82
83        /*
84         * colorCorrection.*
85         */
86        // colorCorrection.aberrationMode
87        {
88            int aberrationMode = ParamsUtils.getOrDefault(request,
89                    COLOR_CORRECTION_ABERRATION_MODE,
90                    /*defaultValue*/COLOR_CORRECTION_ABERRATION_MODE_FAST);
91
92            if (aberrationMode != COLOR_CORRECTION_ABERRATION_MODE_FAST) {
93                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
456    private static boolean checkForCompleteGpsData(Location location) {
457        return location != null && location.getProvider() != null && location.getTime() != 0;
458    }
459
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
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
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     */
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
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
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     */
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