LegacyRequestMapper.java revision 442395751d46aa0f569ad479202a84713a260be0
109109567e9816d20f51b5ce0175751116836635fDaichi Hirono/*
209109567e9816d20f51b5ce0175751116836635fDaichi Hirono * Copyright (C) 2014 The Android Open Source Project
309109567e9816d20f51b5ce0175751116836635fDaichi Hirono *
409109567e9816d20f51b5ce0175751116836635fDaichi Hirono * Licensed under the Apache License, Version 2.0 (the "License");
509109567e9816d20f51b5ce0175751116836635fDaichi Hirono * you may not use this file except in compliance with the License.
609109567e9816d20f51b5ce0175751116836635fDaichi Hirono * You may obtain a copy of the License at
709109567e9816d20f51b5ce0175751116836635fDaichi Hirono *
809109567e9816d20f51b5ce0175751116836635fDaichi Hirono *      http://www.apache.org/licenses/LICENSE-2.0
909109567e9816d20f51b5ce0175751116836635fDaichi Hirono *
1009109567e9816d20f51b5ce0175751116836635fDaichi Hirono * Unless required by applicable law or agreed to in writing, software
1109109567e9816d20f51b5ce0175751116836635fDaichi Hirono * distributed under the License is distributed on an "AS IS" BASIS,
1209109567e9816d20f51b5ce0175751116836635fDaichi Hirono * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1309109567e9816d20f51b5ce0175751116836635fDaichi Hirono * See the License for the specific language governing permissions and
1409109567e9816d20f51b5ce0175751116836635fDaichi Hirono * limitations under the License.
1509109567e9816d20f51b5ce0175751116836635fDaichi Hirono */
1609109567e9816d20f51b5ce0175751116836635fDaichi Hirono
1709109567e9816d20f51b5ce0175751116836635fDaichi Hironopackage android.hardware.camera2.legacy;
1809109567e9816d20f51b5ce0175751116836635fDaichi Hirono
1909109567e9816d20f51b5ce0175751116836635fDaichi Hironoimport android.graphics.Rect;
20b80a3cfd05fc7492dd59b7f8d4337eb5e29088c2Tomasz Mikolajewskiimport android.hardware.Camera;
2152652ac7a5f479f7f5e24f78778203bd88c0c4f4Tomasz Mikolajewskiimport android.hardware.Camera.Parameters;
2220754c5a112e418c11cc88176283db2c4bf2efd6Daichi Hironoimport android.hardware.camera2.CameraCharacteristics;
2309109567e9816d20f51b5ce0175751116836635fDaichi Hironoimport android.hardware.camera2.CaptureRequest;
2409109567e9816d20f51b5ce0175751116836635fDaichi Hironoimport android.hardware.camera2.params.MeteringRectangle;
250f32537e40ee2662d4f0b7b625ee280ca9c02066Daichi Hironoimport android.hardware.camera2.utils.ListUtils;
26e5323b7493f2bc1537d7e6b2d4595d69fd01d72eDaichi Hironoimport android.hardware.camera2.utils.ParamsUtils;
2709109567e9816d20f51b5ce0175751116836635fDaichi Hironoimport android.location.Location;
2809109567e9816d20f51b5ce0175751116836635fDaichi Hironoimport android.util.Log;
2935b2ec551f670562a779925fe152307f20ad67cdDaichi Hironoimport android.util.Range;
3009109567e9816d20f51b5ce0175751116836635fDaichi Hironoimport android.util.Size;
316ee4a1c1247e2a1d3032bcd432f843cbb7227dccDaichi Hirono
32b80a3cfd05fc7492dd59b7f8d4337eb5e29088c2Tomasz Mikolajewskiimport java.util.ArrayList;
33b80a3cfd05fc7492dd59b7f8d4337eb5e29088c2Tomasz Mikolajewskiimport java.util.Arrays;
346baa16e9109046661fef8dcc25b8754ac68bcdaeDaichi Hironoimport java.util.List;
35e5323b7493f2bc1537d7e6b2d4595d69fd01d72eDaichi Hironoimport java.util.Objects;
36e5323b7493f2bc1537d7e6b2d4595d69fd01d72eDaichi Hirono
37e5323b7493f2bc1537d7e6b2d4595d69fd01d72eDaichi Hironoimport static com.android.internal.util.Preconditions.*;
3820754c5a112e418c11cc88176283db2c4bf2efd6Daichi Hironoimport static android.hardware.camera2.CaptureRequest.*;
39bb430fa930fa0d0700e46e7b4881de2a252223ddTomasz Mikolajewski
40124d060bc980c7555616ff9d07a4dc3b8f3cd341Daichi Hirono/**
41124d060bc980c7555616ff9d07a4dc3b8f3cd341Daichi Hirono * Provide legacy-specific implementations of camera2 CaptureRequest for legacy devices.
42124d060bc980c7555616ff9d07a4dc3b8f3cd341Daichi Hirono */
4364111e08d905525c7f4fe27e69953eb71bd62511Daichi Hirono@SuppressWarnings("deprecation")
4409109567e9816d20f51b5ce0175751116836635fDaichi Hironopublic class LegacyRequestMapper {
456ee4a1c1247e2a1d3032bcd432f843cbb7227dccDaichi Hirono    private static final String TAG = "LegacyRequestMapper";
4609109567e9816d20f51b5ce0175751116836635fDaichi Hirono    private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
4709109567e9816d20f51b5ce0175751116836635fDaichi Hirono
4809109567e9816d20f51b5ce0175751116836635fDaichi Hirono    private static final byte DEFAULT_JPEG_QUALITY = 85;
4920754c5a112e418c11cc88176283db2c4bf2efd6Daichi Hirono
5020754c5a112e418c11cc88176283db2c4bf2efd6Daichi Hirono    /**
5109109567e9816d20f51b5ce0175751116836635fDaichi Hirono     * Set the legacy parameters using the {@link LegacyRequest legacy request}.
5209109567e9816d20f51b5ce0175751116836635fDaichi Hirono     *
53bb430fa930fa0d0700e46e7b4881de2a252223ddTomasz Mikolajewski     * <p>The legacy request's parameters are changed as a side effect of calling this
54bb430fa930fa0d0700e46e7b4881de2a252223ddTomasz Mikolajewski     * method.</p>
55124d060bc980c7555616ff9d07a4dc3b8f3cd341Daichi Hirono     *
56124d060bc980c7555616ff9d07a4dc3b8f3cd341Daichi Hirono     * @param legacyRequest a non-{@code null} legacy request
57bb430fa930fa0d0700e46e7b4881de2a252223ddTomasz Mikolajewski     */
58bb430fa930fa0d0700e46e7b4881de2a252223ddTomasz Mikolajewski    public static void convertRequestMetadata(LegacyRequest legacyRequest) {
59e5323b7493f2bc1537d7e6b2d4595d69fd01d72eDaichi Hirono        CameraCharacteristics characteristics = legacyRequest.characteristics;
60e5323b7493f2bc1537d7e6b2d4595d69fd01d72eDaichi Hirono        CaptureRequest request = legacyRequest.captureRequest;
6152652ac7a5f479f7f5e24f78778203bd88c0c4f4Tomasz Mikolajewski        Size previewSize = legacyRequest.previewSize;
6252652ac7a5f479f7f5e24f78778203bd88c0c4f4Tomasz Mikolajewski        Camera.Parameters params = legacyRequest.parameters;
638ba419119d50a031160cab54bef6899bd0051ea9Daichi Hirono
648ba419119d50a031160cab54bef6899bd0051ea9Daichi Hirono        Rect activeArray = characteristics.get(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE);
65b80a3cfd05fc7492dd59b7f8d4337eb5e29088c2Tomasz Mikolajewski
66b80a3cfd05fc7492dd59b7f8d4337eb5e29088c2Tomasz Mikolajewski        /*
67b80a3cfd05fc7492dd59b7f8d4337eb5e29088c2Tomasz Mikolajewski         * scaler.cropRegion
68b80a3cfd05fc7492dd59b7f8d4337eb5e29088c2Tomasz Mikolajewski         */
693faa43a4a6f270e2e1e2ec55b77508084af16757Daichi Hirono        ParameterUtils.ZoomData zoomData;
703faa43a4a6f270e2e1e2ec55b77508084af16757Daichi Hirono        {
713faa43a4a6f270e2e1e2ec55b77508084af16757Daichi Hirono            zoomData = ParameterUtils.convertScalerCropRegion(activeArray,
723faa43a4a6f270e2e1e2ec55b77508084af16757Daichi Hirono                    request.get(SCALER_CROP_REGION),
7364111e08d905525c7f4fe27e69953eb71bd62511Daichi Hirono                    previewSize,
7464111e08d905525c7f4fe27e69953eb71bd62511Daichi Hirono                    params);
7564111e08d905525c7f4fe27e69953eb71bd62511Daichi Hirono
7664111e08d905525c7f4fe27e69953eb71bd62511Daichi Hirono            if (params.isZoomSupported()) {
7709109567e9816d20f51b5ce0175751116836635fDaichi Hirono                params.setZoom(zoomData.zoomIndex);
78f20e49ecb954ffc3cb93499cb789a567125998ceDaichi Hirono            } else if (VERBOSE) {
7920754c5a112e418c11cc88176283db2c4bf2efd6Daichi Hirono                Log.v(TAG, "convertRequestToMetadata - zoom is not supported");
8020754c5a112e418c11cc88176283db2c4bf2efd6Daichi Hirono            }
8120754c5a112e418c11cc88176283db2c4bf2efd6Daichi Hirono        }
8220754c5a112e418c11cc88176283db2c4bf2efd6Daichi Hirono
8320754c5a112e418c11cc88176283db2c4bf2efd6Daichi Hirono        /*
8420754c5a112e418c11cc88176283db2c4bf2efd6Daichi Hirono         * colorCorrection.*
8520754c5a112e418c11cc88176283db2c4bf2efd6Daichi Hirono         */
86ebd24051599280443435606cab220de33b9356adDaichi Hirono        // colorCorrection.aberrationMode
87ebd24051599280443435606cab220de33b9356adDaichi Hirono        {
8820754c5a112e418c11cc88176283db2c4bf2efd6Daichi Hirono            int aberrationMode = ParamsUtils.getOrDefault(request,
8909109567e9816d20f51b5ce0175751116836635fDaichi Hirono                    COLOR_CORRECTION_ABERRATION_MODE,
9020754c5a112e418c11cc88176283db2c4bf2efd6Daichi Hirono                    /*defaultValue*/COLOR_CORRECTION_ABERRATION_MODE_FAST);
9109109567e9816d20f51b5ce0175751116836635fDaichi Hirono
9209109567e9816d20f51b5ce0175751116836635fDaichi Hirono            if (aberrationMode != COLOR_CORRECTION_ABERRATION_MODE_FAST) {
9309109567e9816d20f51b5ce0175751116836635fDaichi Hirono                Log.w(TAG, "convertRequestToMetadata - Ignoring unsupported " +
94f20e49ecb954ffc3cb93499cb789a567125998ceDaichi Hirono                        "colorCorrection.aberrationMode = " + aberrationMode);
9520754c5a112e418c11cc88176283db2c4bf2efd6Daichi Hirono            }
964e94b8deaa646f176bad9b80d5924ce64142743eDaichi Hirono        }
9709109567e9816d20f51b5ce0175751116836635fDaichi Hirono
9809109567e9816d20f51b5ce0175751116836635fDaichi Hirono        /*
990f32537e40ee2662d4f0b7b625ee280ca9c02066Daichi Hirono         * control.ae*
1000f32537e40ee2662d4f0b7b625ee280ca9c02066Daichi Hirono         */
1010f32537e40ee2662d4f0b7b625ee280ca9c02066Daichi Hirono        // control.aeAntibandingMode
1020f32537e40ee2662d4f0b7b625ee280ca9c02066Daichi Hirono        {
1030f32537e40ee2662d4f0b7b625ee280ca9c02066Daichi Hirono        String legacyMode;
10409109567e9816d20f51b5ce0175751116836635fDaichi Hirono            Integer antiBandingMode = request.get(CONTROL_AE_ANTIBANDING_MODE);
10509109567e9816d20f51b5ce0175751116836635fDaichi Hirono            if (antiBandingMode != null) {
10609109567e9816d20f51b5ce0175751116836635fDaichi Hirono                legacyMode = convertAeAntiBandingModeToLegacy(antiBandingMode);
107f20e49ecb954ffc3cb93499cb789a567125998ceDaichi Hirono            } else {
10820754c5a112e418c11cc88176283db2c4bf2efd6Daichi Hirono                legacyMode = ListUtils.listSelectFirstFrom(params.getSupportedAntibanding(),
1094e94b8deaa646f176bad9b80d5924ce64142743eDaichi Hirono                        new String[] {
11020754c5a112e418c11cc88176283db2c4bf2efd6Daichi Hirono                            Parameters.ANTIBANDING_AUTO,
11109109567e9816d20f51b5ce0175751116836635fDaichi Hirono                            Parameters.ANTIBANDING_OFF,
11220754c5a112e418c11cc88176283db2c4bf2efd6Daichi Hirono                            Parameters.ANTIBANDING_50HZ,
11320754c5a112e418c11cc88176283db2c4bf2efd6Daichi Hirono                            Parameters.ANTIBANDING_60HZ,
114ebd24051599280443435606cab220de33b9356adDaichi Hirono                        });
11537a655aac1d61ce2fe346531f78cbcfbf51388e9Daichi Hirono            }
11609109567e9816d20f51b5ce0175751116836635fDaichi Hirono
11709109567e9816d20f51b5ce0175751116836635fDaichi Hirono            if (legacyMode != null) {
11809109567e9816d20f51b5ce0175751116836635fDaichi Hirono                params.setAntibanding(legacyMode);
119bb430fa930fa0d0700e46e7b4881de2a252223ddTomasz Mikolajewski            }
120124d060bc980c7555616ff9d07a4dc3b8f3cd341Daichi Hirono        }
121bb430fa930fa0d0700e46e7b4881de2a252223ddTomasz Mikolajewski
122bb430fa930fa0d0700e46e7b4881de2a252223ddTomasz Mikolajewski        /*
123124d060bc980c7555616ff9d07a4dc3b8f3cd341Daichi Hirono         * control.aeRegions, afRegions
124bb430fa930fa0d0700e46e7b4881de2a252223ddTomasz Mikolajewski         */
125124d060bc980c7555616ff9d07a4dc3b8f3cd341Daichi Hirono        {
126124d060bc980c7555616ff9d07a4dc3b8f3cd341Daichi Hirono            // aeRegions
127124d060bc980c7555616ff9d07a4dc3b8f3cd341Daichi Hirono            {
128124d060bc980c7555616ff9d07a4dc3b8f3cd341Daichi Hirono                // Use aeRegions if available, fall back to using awbRegions if present
129124d060bc980c7555616ff9d07a4dc3b8f3cd341Daichi Hirono                MeteringRectangle[] aeRegions = request.get(CONTROL_AE_REGIONS);
130124d060bc980c7555616ff9d07a4dc3b8f3cd341Daichi Hirono                if (request.get(CONTROL_AWB_REGIONS) != null) {
131124d060bc980c7555616ff9d07a4dc3b8f3cd341Daichi Hirono                    Log.w(TAG, "convertRequestMetadata - control.awbRegions setting is not " +
132124d060bc980c7555616ff9d07a4dc3b8f3cd341Daichi Hirono                            "supported, ignoring value");
133124d060bc980c7555616ff9d07a4dc3b8f3cd341Daichi Hirono                }
134124d060bc980c7555616ff9d07a4dc3b8f3cd341Daichi Hirono                int maxNumMeteringAreas = params.getMaxNumMeteringAreas();
135124d060bc980c7555616ff9d07a4dc3b8f3cd341Daichi Hirono                List<Camera.Area> meteringAreaList = convertMeteringRegionsToLegacy(
136e5323b7493f2bc1537d7e6b2d4595d69fd01d72eDaichi Hirono                        activeArray, zoomData, aeRegions, maxNumMeteringAreas,
137e5323b7493f2bc1537d7e6b2d4595d69fd01d72eDaichi Hirono                        /*regionName*/"AE");
138e5323b7493f2bc1537d7e6b2d4595d69fd01d72eDaichi Hirono
139b80a3cfd05fc7492dd59b7f8d4337eb5e29088c2Tomasz Mikolajewski                // WAR: for b/17252693, some devices can't handle params.setFocusAreas(null).
140b80a3cfd05fc7492dd59b7f8d4337eb5e29088c2Tomasz Mikolajewski                if (maxNumMeteringAreas > 0) {
141b80a3cfd05fc7492dd59b7f8d4337eb5e29088c2Tomasz Mikolajewski                    params.setMeteringAreas(meteringAreaList);
14252652ac7a5f479f7f5e24f78778203bd88c0c4f4Tomasz Mikolajewski                }
14352652ac7a5f479f7f5e24f78778203bd88c0c4f4Tomasz Mikolajewski            }
14452652ac7a5f479f7f5e24f78778203bd88c0c4f4Tomasz Mikolajewski
14552652ac7a5f479f7f5e24f78778203bd88c0c4f4Tomasz Mikolajewski            // afRegions
14652652ac7a5f479f7f5e24f78778203bd88c0c4f4Tomasz Mikolajewski            {
1478ba419119d50a031160cab54bef6899bd0051ea9Daichi Hirono                MeteringRectangle[] afRegions = request.get(CONTROL_AF_REGIONS);
14852652ac7a5f479f7f5e24f78778203bd88c0c4f4Tomasz Mikolajewski                int maxNumFocusAreas = params.getMaxNumFocusAreas();
1498ba419119d50a031160cab54bef6899bd0051ea9Daichi Hirono                List<Camera.Area> focusAreaList = convertMeteringRegionsToLegacy(
1508ba419119d50a031160cab54bef6899bd0051ea9Daichi Hirono                        activeArray, zoomData, afRegions, maxNumFocusAreas,
1518ba419119d50a031160cab54bef6899bd0051ea9Daichi Hirono                        /*regionName*/"AF");
1528ba419119d50a031160cab54bef6899bd0051ea9Daichi Hirono
153df544176b10f536969de1ed143b0ba57123fcb93Tomasz Mikolajewski                // WAR: for b/17252693, some devices can't handle params.setFocusAreas(null).
154b80a3cfd05fc7492dd59b7f8d4337eb5e29088c2Tomasz Mikolajewski                if (maxNumFocusAreas > 0) {
15535b2ec551f670562a779925fe152307f20ad67cdDaichi Hirono                    params.setFocusAreas(focusAreaList);
15635b2ec551f670562a779925fe152307f20ad67cdDaichi Hirono                }
15735b2ec551f670562a779925fe152307f20ad67cdDaichi Hirono            }
158df544176b10f536969de1ed143b0ba57123fcb93Tomasz Mikolajewski        }
159df544176b10f536969de1ed143b0ba57123fcb93Tomasz Mikolajewski
160b80a3cfd05fc7492dd59b7f8d4337eb5e29088c2Tomasz Mikolajewski        // control.aeTargetFpsRange
161b80a3cfd05fc7492dd59b7f8d4337eb5e29088c2Tomasz Mikolajewski        Range<Integer> aeFpsRange = request.get(CONTROL_AE_TARGET_FPS_RANGE);
162f578fa275a535016f5322c88ad7a92e517d04a12Daichi Hirono        if (aeFpsRange != null) {
163f578fa275a535016f5322c88ad7a92e517d04a12Daichi Hirono            int[] legacyFps = convertAeFpsRangeToLegacy(aeFpsRange);
164f578fa275a535016f5322c88ad7a92e517d04a12Daichi Hirono
165df544176b10f536969de1ed143b0ba57123fcb93Tomasz Mikolajewski            // TODO - Should we enforce that all HAL1 devices must include (30, 30) FPS range?
166df544176b10f536969de1ed143b0ba57123fcb93Tomasz Mikolajewski            boolean supported = false;
167df544176b10f536969de1ed143b0ba57123fcb93Tomasz Mikolajewski            for(int[] range : params.getSupportedPreviewFpsRange()) {
168df544176b10f536969de1ed143b0ba57123fcb93Tomasz Mikolajewski                if (legacyFps[0] == range[0] && legacyFps[1] == range[1]) {
169df544176b10f536969de1ed143b0ba57123fcb93Tomasz Mikolajewski                    supported = true;
170df544176b10f536969de1ed143b0ba57123fcb93Tomasz Mikolajewski                    break;
171df544176b10f536969de1ed143b0ba57123fcb93Tomasz Mikolajewski                }
172df544176b10f536969de1ed143b0ba57123fcb93Tomasz Mikolajewski            }
173df544176b10f536969de1ed143b0ba57123fcb93Tomasz Mikolajewski            if (supported) {
174df544176b10f536969de1ed143b0ba57123fcb93Tomasz Mikolajewski                params.setPreviewFpsRange(legacyFps[Camera.Parameters.PREVIEW_FPS_MIN_INDEX],
175df544176b10f536969de1ed143b0ba57123fcb93Tomasz Mikolajewski                        legacyFps[Camera.Parameters.PREVIEW_FPS_MAX_INDEX]);
176b80a3cfd05fc7492dd59b7f8d4337eb5e29088c2Tomasz Mikolajewski            } else {
177df544176b10f536969de1ed143b0ba57123fcb93Tomasz Mikolajewski                Log.w(TAG, "Unsupported FPS range set [" + legacyFps[0] + "," + legacyFps[1] + "]");
178b80a3cfd05fc7492dd59b7f8d4337eb5e29088c2Tomasz Mikolajewski            }
179b80a3cfd05fc7492dd59b7f8d4337eb5e29088c2Tomasz Mikolajewski        }
180b80a3cfd05fc7492dd59b7f8d4337eb5e29088c2Tomasz Mikolajewski
1813faa43a4a6f270e2e1e2ec55b77508084af16757Daichi Hirono        /*
1823faa43a4a6f270e2e1e2ec55b77508084af16757Daichi Hirono         * control
1833faa43a4a6f270e2e1e2ec55b77508084af16757Daichi Hirono         */
1843faa43a4a6f270e2e1e2ec55b77508084af16757Daichi Hirono
1853faa43a4a6f270e2e1e2ec55b77508084af16757Daichi Hirono        // control.aeExposureCompensation
1863faa43a4a6f270e2e1e2ec55b77508084af16757Daichi Hirono        {
1873faa43a4a6f270e2e1e2ec55b77508084af16757Daichi Hirono            Range<Integer> compensationRange =
1883faa43a4a6f270e2e1e2ec55b77508084af16757Daichi Hirono                    characteristics.get(CameraCharacteristics.CONTROL_AE_COMPENSATION_RANGE);
1893faa43a4a6f270e2e1e2ec55b77508084af16757Daichi Hirono            int compensation = ParamsUtils.getOrDefault(request,
1903faa43a4a6f270e2e1e2ec55b77508084af16757Daichi Hirono                    CONTROL_AE_EXPOSURE_COMPENSATION,
1915fecc6cf032bbbc2616dd2342a50656bf2857832Daichi Hirono                    /*defaultValue*/0);
1925fecc6cf032bbbc2616dd2342a50656bf2857832Daichi Hirono
193bb430fa930fa0d0700e46e7b4881de2a252223ddTomasz Mikolajewski            if (!compensationRange.contains(compensation)) {
194bb430fa930fa0d0700e46e7b4881de2a252223ddTomasz Mikolajewski                Log.w(TAG,
1955fecc6cf032bbbc2616dd2342a50656bf2857832Daichi Hirono                        "convertRequestMetadata - control.aeExposureCompensation " +
1965fecc6cf032bbbc2616dd2342a50656bf2857832Daichi Hirono                        "is out of range, ignoring value");
1975fecc6cf032bbbc2616dd2342a50656bf2857832Daichi Hirono                compensation = 0;
1985fecc6cf032bbbc2616dd2342a50656bf2857832Daichi Hirono            }
1995fecc6cf032bbbc2616dd2342a50656bf2857832Daichi Hirono
2005fecc6cf032bbbc2616dd2342a50656bf2857832Daichi Hirono            params.setExposureCompensation(compensation);
201ab65d363bbff29b3d46a5b0a5e73b8ed20140287Tomasz Mikolajewski        }
2025fecc6cf032bbbc2616dd2342a50656bf2857832Daichi Hirono
203ab65d363bbff29b3d46a5b0a5e73b8ed20140287Tomasz Mikolajewski        // control.aeLock
204ab65d363bbff29b3d46a5b0a5e73b8ed20140287Tomasz Mikolajewski        {
2055fecc6cf032bbbc2616dd2342a50656bf2857832Daichi Hirono            Boolean aeLock = getIfSupported(request, CONTROL_AE_LOCK, /*defaultValue*/false,
2065fecc6cf032bbbc2616dd2342a50656bf2857832Daichi Hirono                    params.isAutoExposureLockSupported(),
2075fecc6cf032bbbc2616dd2342a50656bf2857832Daichi Hirono                    /*allowedValue*/false);
2085fecc6cf032bbbc2616dd2342a50656bf2857832Daichi Hirono
2095fecc6cf032bbbc2616dd2342a50656bf2857832Daichi Hirono            if (aeLock != null) {
2105fecc6cf032bbbc2616dd2342a50656bf2857832Daichi Hirono                params.setAutoExposureLock(aeLock);
211cc9a7d78d519aa25b4afbc96afd401be75696ddaDaichi Hirono            }
212cc9a7d78d519aa25b4afbc96afd401be75696ddaDaichi Hirono
213cc9a7d78d519aa25b4afbc96afd401be75696ddaDaichi Hirono            if (VERBOSE) {
214b36b15586a5d3d0de590773ce4392fa3a82af66aDaichi Hirono                Log.v(TAG, "convertRequestToMetadata - control.aeLock set to " + aeLock);
215b36b15586a5d3d0de590773ce4392fa3a82af66aDaichi Hirono            }
216b36b15586a5d3d0de590773ce4392fa3a82af66aDaichi Hirono
217b36b15586a5d3d0de590773ce4392fa3a82af66aDaichi Hirono            // TODO: Don't add control.aeLock to availableRequestKeys if it's not supported
218b36b15586a5d3d0de590773ce4392fa3a82af66aDaichi Hirono        }
219b36b15586a5d3d0de590773ce4392fa3a82af66aDaichi Hirono
220b36b15586a5d3d0de590773ce4392fa3a82af66aDaichi Hirono        // control.aeMode, flash.mode
221b36b15586a5d3d0de590773ce4392fa3a82af66aDaichi Hirono        mapAeAndFlashMode(request, /*out*/params);
222b36b15586a5d3d0de590773ce4392fa3a82af66aDaichi Hirono
223b36b15586a5d3d0de590773ce4392fa3a82af66aDaichi Hirono        // control.afMode
224b36b15586a5d3d0de590773ce4392fa3a82af66aDaichi Hirono        {
225b36b15586a5d3d0de590773ce4392fa3a82af66aDaichi Hirono            int afMode = ParamsUtils.getOrDefault(request, CONTROL_AF_MODE,
22664111e08d905525c7f4fe27e69953eb71bd62511Daichi Hirono                    /*defaultValue*/CONTROL_AF_MODE_OFF);
22764111e08d905525c7f4fe27e69953eb71bd62511Daichi Hirono            String focusMode = LegacyMetadataMapper.convertAfModeToLegacy(afMode,
22864111e08d905525c7f4fe27e69953eb71bd62511Daichi Hirono                    params.getSupportedFocusModes());
22964111e08d905525c7f4fe27e69953eb71bd62511Daichi Hirono
23064111e08d905525c7f4fe27e69953eb71bd62511Daichi Hirono            if (focusMode != null) {
23164111e08d905525c7f4fe27e69953eb71bd62511Daichi Hirono                params.setFocusMode(focusMode);
23264111e08d905525c7f4fe27e69953eb71bd62511Daichi Hirono            }
23364111e08d905525c7f4fe27e69953eb71bd62511Daichi Hirono
23464111e08d905525c7f4fe27e69953eb71bd62511Daichi Hirono            if (VERBOSE) {
23564111e08d905525c7f4fe27e69953eb71bd62511Daichi Hirono                Log.v(TAG, "convertRequestToMetadata - control.afMode "
23609109567e9816d20f51b5ce0175751116836635fDaichi Hirono                        + afMode + " mapped to " + focusMode);
237            }
238        }
239
240        // control.awbMode
241        {
242            Integer awbMode = getIfSupported(request, CONTROL_AWB_MODE,
243                    /*defaultValue*/CONTROL_AWB_MODE_AUTO,
244                    params.getSupportedWhiteBalance() != null,
245                    /*allowedValue*/CONTROL_AWB_MODE_AUTO);
246
247            String whiteBalanceMode = null;
248            if (awbMode != null) { // null iff AWB is not supported by camera1 api
249                whiteBalanceMode = convertAwbModeToLegacy(awbMode);
250                params.setWhiteBalance(whiteBalanceMode);
251            }
252
253            if (VERBOSE) {
254                Log.v(TAG, "convertRequestToMetadata - control.awbMode "
255                        + awbMode + " mapped to " + whiteBalanceMode);
256            }
257        }
258
259        // control.awbLock
260        {
261            Boolean awbLock = getIfSupported(request, CONTROL_AWB_LOCK, /*defaultValue*/false,
262                    params.isAutoWhiteBalanceLockSupported(),
263                    /*allowedValue*/false);
264
265            if (awbLock != null) {
266                params.setAutoWhiteBalanceLock(awbLock);
267            }
268
269         // TODO: Don't add control.awbLock to availableRequestKeys if it's not supported
270        }
271
272        // control.captureIntent
273        {
274            int captureIntent = ParamsUtils.getOrDefault(request,
275                    CONTROL_CAPTURE_INTENT,
276                    /*defaultValue*/CONTROL_CAPTURE_INTENT_PREVIEW);
277
278            captureIntent = filterSupportedCaptureIntent(captureIntent);
279
280            params.setRecordingHint(
281                    captureIntent == CONTROL_CAPTURE_INTENT_VIDEO_RECORD ||
282                    captureIntent == CONTROL_CAPTURE_INTENT_VIDEO_SNAPSHOT);
283        }
284
285        // control.videoStabilizationMode
286        {
287            Integer stabMode = getIfSupported(request, CONTROL_VIDEO_STABILIZATION_MODE,
288                    /*defaultValue*/CONTROL_VIDEO_STABILIZATION_MODE_OFF,
289                    params.isVideoStabilizationSupported(),
290                    /*allowedValue*/CONTROL_VIDEO_STABILIZATION_MODE_OFF);
291
292            if (stabMode != null) {
293                params.setVideoStabilization(stabMode == CONTROL_VIDEO_STABILIZATION_MODE_ON);
294            }
295        }
296
297        // lens.focusDistance
298        {
299            boolean infinityFocusSupported =
300                    ListUtils.listContains(params.getSupportedFocusModes(),
301                            Parameters.FOCUS_MODE_INFINITY);
302            Float focusDistance = getIfSupported(request, LENS_FOCUS_DISTANCE,
303                    /*defaultValue*/0f, infinityFocusSupported, /*allowedValue*/0f);
304
305            if (focusDistance == null || focusDistance != 0f) {
306                Log.w(TAG,
307                        "convertRequestToMetadata - Ignoring android.lens.focusDistance "
308                                + infinityFocusSupported + ", only 0.0f is supported");
309            }
310        }
311
312        // control.sceneMode, control.mode
313        {
314            // TODO: Map FACE_PRIORITY scene mode to face detection.
315
316            if (params.getSupportedSceneModes() != null) {
317                int controlMode = ParamsUtils.getOrDefault(request, CONTROL_MODE,
318                    /*defaultValue*/CONTROL_MODE_AUTO);
319                String modeToSet;
320                switch (controlMode) {
321                    case CONTROL_MODE_USE_SCENE_MODE: {
322                        int sceneMode = ParamsUtils.getOrDefault(request, CONTROL_SCENE_MODE,
323                                /*defaultValue*/CONTROL_SCENE_MODE_DISABLED);
324                        String legacySceneMode = LegacyMetadataMapper.
325                                convertSceneModeToLegacy(sceneMode);
326                        if (legacySceneMode != null) {
327                            modeToSet = legacySceneMode;
328                        } else {
329                            modeToSet = Parameters.SCENE_MODE_AUTO;
330                            Log.w(TAG, "Skipping unknown requested scene mode: " + sceneMode);
331                        }
332                        break;
333                    }
334                    case CONTROL_MODE_AUTO: {
335                        modeToSet = Parameters.SCENE_MODE_AUTO;
336                        break;
337                    }
338                    default: {
339                        Log.w(TAG, "Control mode " + controlMode +
340                                " is unsupported, defaulting to AUTO");
341                        modeToSet = Parameters.SCENE_MODE_AUTO;
342                    }
343                }
344                params.setSceneMode(modeToSet);
345            }
346        }
347
348        // control.effectMode
349        {
350            if (params.getSupportedColorEffects() != null) {
351                int effectMode = ParamsUtils.getOrDefault(request, CONTROL_EFFECT_MODE,
352                    /*defaultValue*/CONTROL_EFFECT_MODE_OFF);
353                String legacyEffectMode = LegacyMetadataMapper.convertEffectModeToLegacy(effectMode);
354                if (legacyEffectMode != null) {
355                    params.setColorEffect(legacyEffectMode);
356                } else {
357                    params.setColorEffect(Parameters.EFFECT_NONE);
358                    Log.w(TAG, "Skipping unknown requested effect mode: " + effectMode);
359                }
360            }
361        }
362
363        /*
364         * sensor
365         */
366
367        // sensor.testPattern
368        {
369            int testPatternMode = ParamsUtils.getOrDefault(request, SENSOR_TEST_PATTERN_MODE,
370                    /*defaultValue*/SENSOR_TEST_PATTERN_MODE_OFF);
371            if (testPatternMode != SENSOR_TEST_PATTERN_MODE_OFF) {
372                Log.w(TAG, "convertRequestToMetadata - ignoring sensor.testPatternMode "
373                        + testPatternMode + "; only OFF is supported");
374            }
375        }
376
377        /*
378         * jpeg.*
379         */
380
381        // jpeg.gpsLocation
382        {
383            Location location = request.get(JPEG_GPS_LOCATION);
384            if (location != null) {
385                if (checkForCompleteGpsData(location)) {
386                    params.setGpsAltitude(location.getAltitude());
387                    params.setGpsLatitude(location.getLatitude());
388                    params.setGpsLongitude(location.getLongitude());
389                    params.setGpsProcessingMethod(location.getProvider().toUpperCase());
390                    params.setGpsTimestamp(location.getTime());
391                } else {
392                    Log.w(TAG, "Incomplete GPS parameters provided in location " + location);
393                }
394            } else {
395                params.removeGpsData();
396            }
397        }
398
399        // jpeg.orientation
400        {
401            int orientation = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
402            params.setRotation(ParamsUtils.getOrDefault(request, JPEG_ORIENTATION, orientation));
403        }
404
405        // jpeg.quality
406        {
407            params.setJpegQuality(0xFF & ParamsUtils.getOrDefault(request, JPEG_QUALITY,
408                    DEFAULT_JPEG_QUALITY));
409        }
410
411        // jpeg.thumbnailQuality
412        {
413            params.setJpegQuality(0xFF & ParamsUtils.getOrDefault(request, JPEG_THUMBNAIL_QUALITY,
414                    DEFAULT_JPEG_QUALITY));
415        }
416
417        // jpeg.thumbnailSize
418        {
419            List<Camera.Size> sizes = params.getSupportedJpegThumbnailSizes();
420
421            if (sizes != null && sizes.size() > 0) {
422                Size s = request.get(JPEG_THUMBNAIL_SIZE);
423                boolean invalidSize = (s == null) ? false : !ParameterUtils.containsSize(sizes,
424                        s.getWidth(), s.getHeight());
425                if (invalidSize) {
426                    Log.w(TAG, "Invalid JPEG thumbnail size set " + s + ", skipping thumbnail...");
427                }
428                if (s == null || invalidSize) {
429                    // (0,0) = "no thumbnail" in Camera API 1
430                    params.setJpegThumbnailSize(/*width*/0, /*height*/0);
431                } else {
432                    params.setJpegThumbnailSize(s.getWidth(), s.getHeight());
433                }
434            }
435        }
436
437        /*
438         * noiseReduction.*
439         */
440        // noiseReduction.mode
441        {
442            int mode = ParamsUtils.getOrDefault(request,
443                    NOISE_REDUCTION_MODE,
444                    /*defaultValue*/NOISE_REDUCTION_MODE_FAST);
445
446            if (mode != NOISE_REDUCTION_MODE_FAST) {
447                Log.w(TAG, "convertRequestToMetadata - Ignoring unsupported " +
448                        "noiseReduction.mode = " + mode);
449            }
450        }
451    }
452
453    private static boolean checkForCompleteGpsData(Location location) {
454        return location != null && location.getProvider() != null && location.getTime() != 0;
455    }
456
457    static int filterSupportedCaptureIntent(int captureIntent) {
458        switch (captureIntent) {
459            case CONTROL_CAPTURE_INTENT_CUSTOM:
460            case CONTROL_CAPTURE_INTENT_PREVIEW:
461            case CONTROL_CAPTURE_INTENT_STILL_CAPTURE:
462            case CONTROL_CAPTURE_INTENT_VIDEO_RECORD:
463            case CONTROL_CAPTURE_INTENT_VIDEO_SNAPSHOT:
464                break;
465            case CONTROL_CAPTURE_INTENT_ZERO_SHUTTER_LAG:
466            case CONTROL_CAPTURE_INTENT_MANUAL:
467                captureIntent = CONTROL_CAPTURE_INTENT_PREVIEW;
468                Log.w(TAG, "Unsupported control.captureIntent value " + captureIntent
469                        + "; default to PREVIEW");
470            default:
471                captureIntent = CONTROL_CAPTURE_INTENT_PREVIEW;
472                Log.w(TAG, "Unknown control.captureIntent value " + captureIntent
473                        + "; default to PREVIEW");
474        }
475
476        return captureIntent;
477    }
478
479    private static List<Camera.Area> convertMeteringRegionsToLegacy(
480            Rect activeArray, ParameterUtils.ZoomData zoomData,
481            MeteringRectangle[] meteringRegions, int maxNumMeteringAreas, String regionName) {
482        if (meteringRegions == null || maxNumMeteringAreas <= 0) {
483            if (maxNumMeteringAreas > 0) {
484                return Arrays.asList(ParameterUtils.CAMERA_AREA_DEFAULT);
485            } else {
486                return null;
487            }
488        }
489
490        // Add all non-zero weight regions to the list
491        List<MeteringRectangle> meteringRectangleList = new ArrayList<>();
492        for (MeteringRectangle rect : meteringRegions) {
493            if (rect.getMeteringWeight() != MeteringRectangle.METERING_WEIGHT_DONT_CARE) {
494                meteringRectangleList.add(rect);
495            }
496        }
497
498        // Ignore any regions beyond our maximum supported count
499        int countMeteringAreas =
500                Math.min(maxNumMeteringAreas, meteringRectangleList.size());
501        List<Camera.Area> meteringAreaList = new ArrayList<>(countMeteringAreas);
502
503        for (int i = 0; i < countMeteringAreas; ++i) {
504            MeteringRectangle rect = meteringRectangleList.get(i);
505
506            ParameterUtils.MeteringData meteringData =
507                    ParameterUtils.convertMeteringRectangleToLegacy(activeArray, rect, zoomData);
508            meteringAreaList.add(meteringData.meteringArea);
509        }
510
511        if (maxNumMeteringAreas < meteringRectangleList.size()) {
512            Log.w(TAG,
513                    "convertMeteringRegionsToLegacy - Too many requested " + regionName +
514                            " regions, ignoring all beyond the first " + maxNumMeteringAreas);
515        }
516
517        if (VERBOSE) {
518            Log.v(TAG, "convertMeteringRegionsToLegacy - " + regionName + " areas = "
519                    + ParameterUtils.stringFromAreaList(meteringAreaList));
520        }
521
522        return meteringAreaList;
523    }
524
525    private static void mapAeAndFlashMode(CaptureRequest r, /*out*/Parameters p) {
526        int flashMode = ParamsUtils.getOrDefault(r, FLASH_MODE, FLASH_MODE_OFF);
527        int aeMode = ParamsUtils.getOrDefault(r, CONTROL_AE_MODE, CONTROL_AE_MODE_ON);
528
529        List<String> supportedFlashModes = p.getSupportedFlashModes();
530
531        String flashModeSetting = null;
532
533        // Flash is OFF by default, on cameras that support flash
534        if (ListUtils.listContains(supportedFlashModes, Parameters.FLASH_MODE_OFF)) {
535            flashModeSetting = Parameters.FLASH_MODE_OFF;
536        }
537
538        /*
539         * Map all of the control.aeMode* enums, but ignore AE_MODE_OFF since we never support it
540         */
541
542        // Ignore flash.mode controls unless aeMode == ON
543        if (aeMode == CONTROL_AE_MODE_ON) {
544            if (flashMode == FLASH_MODE_TORCH) {
545                    if (ListUtils.listContains(supportedFlashModes, Parameters.FLASH_MODE_TORCH)) {
546                        flashModeSetting = Parameters.FLASH_MODE_TORCH;
547                    } else {
548                        Log.w(TAG, "mapAeAndFlashMode - Ignore flash.mode == TORCH;" +
549                                "camera does not support it");
550                    }
551            } else if (flashMode == FLASH_MODE_SINGLE) {
552                if (ListUtils.listContains(supportedFlashModes, Parameters.FLASH_MODE_ON)) {
553                    flashModeSetting = Parameters.FLASH_MODE_ON;
554                } else {
555                    Log.w(TAG, "mapAeAndFlashMode - Ignore flash.mode == SINGLE;" +
556                            "camera does not support it");
557                }
558            } else {
559                // Use the default FLASH_MODE_OFF
560            }
561        } else if (aeMode == CONTROL_AE_MODE_ON_ALWAYS_FLASH) {
562                if (ListUtils.listContains(supportedFlashModes, Parameters.FLASH_MODE_ON)) {
563                    flashModeSetting = Parameters.FLASH_MODE_ON;
564                } else {
565                    Log.w(TAG, "mapAeAndFlashMode - Ignore control.aeMode == ON_ALWAYS_FLASH;" +
566                            "camera does not support it");
567                }
568        } else if (aeMode == CONTROL_AE_MODE_ON_AUTO_FLASH) {
569            if (ListUtils.listContains(supportedFlashModes, Parameters.FLASH_MODE_AUTO)) {
570                flashModeSetting = Parameters.FLASH_MODE_AUTO;
571            } else {
572                Log.w(TAG, "mapAeAndFlashMode - Ignore control.aeMode == ON_AUTO_FLASH;" +
573                        "camera does not support it");
574            }
575        } else if (aeMode == CONTROL_AE_MODE_ON_AUTO_FLASH_REDEYE) {
576                if (ListUtils.listContains(supportedFlashModes, Parameters.FLASH_MODE_RED_EYE)) {
577                    flashModeSetting = Parameters.FLASH_MODE_RED_EYE;
578                } else {
579                    Log.w(TAG, "mapAeAndFlashMode - Ignore control.aeMode == ON_AUTO_FLASH_REDEYE;"
580                            + "camera does not support it");
581                }
582        } else {
583            // Default to aeMode == ON, flash = OFF
584        }
585
586        if (flashModeSetting != null) {
587            p.setFlashMode(flashModeSetting);
588        }
589
590        if (VERBOSE) {
591                Log.v(TAG,
592                        "mapAeAndFlashMode - set flash.mode (api1) to " + flashModeSetting
593                        + ", requested (api2) " + flashMode
594                        + ", supported (api1) " + ListUtils.listToString(supportedFlashModes));
595        }
596    }
597
598    /**
599     * Returns null if the anti-banding mode enum is not supported.
600     */
601    private static String convertAeAntiBandingModeToLegacy(int mode) {
602        switch (mode) {
603            case CONTROL_AE_ANTIBANDING_MODE_OFF: {
604                return Parameters.ANTIBANDING_OFF;
605            }
606            case CONTROL_AE_ANTIBANDING_MODE_50HZ: {
607                return Parameters.ANTIBANDING_50HZ;
608            }
609            case CONTROL_AE_ANTIBANDING_MODE_60HZ: {
610                return Parameters.ANTIBANDING_60HZ;
611            }
612            case CONTROL_AE_ANTIBANDING_MODE_AUTO: {
613                return Parameters.ANTIBANDING_AUTO;
614            }
615            default: {
616                return null;
617            }
618        }
619    }
620
621    private static int[] convertAeFpsRangeToLegacy(Range<Integer> fpsRange) {
622        int[] legacyFps = new int[2];
623        legacyFps[Parameters.PREVIEW_FPS_MIN_INDEX] = fpsRange.getLower();
624        legacyFps[Parameters.PREVIEW_FPS_MAX_INDEX] = fpsRange.getUpper();
625        return legacyFps;
626    }
627
628    private static String convertAwbModeToLegacy(int mode) {
629        switch (mode) {
630            case CONTROL_AWB_MODE_AUTO:
631                return Camera.Parameters.WHITE_BALANCE_AUTO;
632            case CONTROL_AWB_MODE_INCANDESCENT:
633                return Camera.Parameters.WHITE_BALANCE_INCANDESCENT;
634            case CONTROL_AWB_MODE_FLUORESCENT:
635                return Camera.Parameters.WHITE_BALANCE_FLUORESCENT;
636            case CONTROL_AWB_MODE_WARM_FLUORESCENT:
637                return Camera.Parameters.WHITE_BALANCE_WARM_FLUORESCENT;
638            case CONTROL_AWB_MODE_DAYLIGHT:
639                return Camera.Parameters.WHITE_BALANCE_DAYLIGHT;
640            case CONTROL_AWB_MODE_CLOUDY_DAYLIGHT:
641                return Camera.Parameters.WHITE_BALANCE_CLOUDY_DAYLIGHT;
642            case CONTROL_AWB_MODE_TWILIGHT:
643                return Camera.Parameters.WHITE_BALANCE_TWILIGHT;
644            default:
645                Log.w(TAG, "convertAwbModeToLegacy - unrecognized control.awbMode" + mode);
646                return Camera.Parameters.WHITE_BALANCE_AUTO;
647        }
648    }
649
650
651    /**
652     * Return {@code null} if the value is not supported, otherwise return the retrieved key's
653     * value from the request (or the default value if it wasn't set).
654     *
655     * <p>If the fetched value in the request is equivalent to {@code allowedValue},
656     * then omit the warning (e.g. turning off AF lock on a camera
657     * that always has the AF lock turned off is a silent no-op), but still return {@code null}.</p>
658     *
659     * <p>Logs a warning to logcat if the key is not supported by api1 camera device.</p.
660     */
661    private static <T> T getIfSupported(
662            CaptureRequest r, CaptureRequest.Key<T> key, T defaultValue, boolean isSupported,
663            T allowedValue) {
664        T val = ParamsUtils.getOrDefault(r, key, defaultValue);
665
666        if (!isSupported) {
667            if (!Objects.equals(val, allowedValue)) {
668                Log.w(TAG, key.getName() + " is not supported; ignoring requested value " + val);
669            }
670            return null;
671        }
672
673        return val;
674    }
675}
676