LegacyMetadataMapper.java revision 3fe9eba9044c0b20ed349a4b9094bf1fa7942cdf
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.ImageFormat;
20import android.graphics.Rect;
21import android.hardware.Camera;
22import android.hardware.Camera.CameraInfo;
23import android.hardware.Camera.Parameters;
24import android.hardware.camera2.CameraCharacteristics;
25import android.hardware.camera2.CameraDevice;
26import android.hardware.camera2.CameraMetadata;
27import android.hardware.camera2.CaptureRequest;
28import android.hardware.camera2.CaptureResult;
29import android.hardware.camera2.impl.CameraMetadataNative;
30import android.hardware.camera2.params.StreamConfiguration;
31import android.hardware.camera2.params.StreamConfigurationDuration;
32import android.hardware.camera2.utils.ArrayUtils;
33import android.hardware.camera2.utils.ListUtils;
34import android.hardware.camera2.utils.ParamsUtils;
35import android.util.Log;
36import android.util.Range;
37import android.util.Size;
38
39import java.util.ArrayList;
40import java.util.Arrays;
41import java.util.List;
42
43import static com.android.internal.util.Preconditions.*;
44import static android.hardware.camera2.CameraCharacteristics.*;
45import static android.hardware.camera2.legacy.ParameterUtils.*;
46
47/**
48 * Provide legacy-specific implementations of camera2 metadata for legacy devices, such as the
49 * camera characteristics.
50 */
51@SuppressWarnings("deprecation")
52public class LegacyMetadataMapper {
53    private static final String TAG = "LegacyMetadataMapper";
54    private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
55
56    private static final long NS_PER_MS = 1000000;
57
58    // from graphics.h
59    private static final int HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED = 0x22;
60    private static final int HAL_PIXEL_FORMAT_BLOB = 0x21;
61
62    // for metadata
63    private static final float LENS_INFO_MINIMUM_FOCUS_DISTANCE_FIXED_FOCUS = 0.0f;
64
65    private static final int REQUEST_MAX_NUM_OUTPUT_STREAMS_COUNT_RAW = 0; // no raw support
66    private static final int REQUEST_MAX_NUM_OUTPUT_STREAMS_COUNT_PROC = 3; // preview, video, cb
67    private static final int REQUEST_MAX_NUM_OUTPUT_STREAMS_COUNT_PROC_STALL = 1; // 1 jpeg only
68    private static final int REQUEST_MAX_NUM_INPUT_STREAMS_COUNT = 0; // no reprocessing
69
70    /** Assume 3 HAL1 stages: Exposure, Read-out, Post-Processing */
71    private static final int REQUEST_PIPELINE_MAX_DEPTH_HAL1 = 3;
72    /** Assume 3 shim stages: Preview input, Split output, Format conversion for output */
73    private static final int REQUEST_PIPELINE_MAX_DEPTH_OURS = 3;
74    /* TODO: Update above maxDepth values once we do more performance measurements */
75
76    // For approximating JPEG stall durations
77    private static final long APPROXIMATE_CAPTURE_DELAY_MS = 200; // 200 milliseconds
78    private static final long APPROXIMATE_SENSOR_AREA_PX = (1 << 23); // 8 megapixels
79    private static final long APPROXIMATE_JPEG_ENCODE_TIME_MS = 600; // 600 milliseconds
80
81    static final int UNKNOWN_MODE = -1;
82
83    /*
84     * Development hijinks: Lie about not supporting certain capabilities
85     *
86     * - Unblock some CTS tests from running whose main intent is not the metadata itself
87     *
88     * TODO: Remove these constants and strip out any code that previously relied on them
89     * being set to true.
90     */
91    static final boolean LIE_ABOUT_AE_STATE = false;
92    static final boolean LIE_ABOUT_AE_MAX_REGIONS = false;
93    static final boolean LIE_ABOUT_AF = false;
94    static final boolean LIE_ABOUT_AF_MAX_REGIONS = false;
95    static final boolean LIE_ABOUT_AWB_STATE = false;
96    static final boolean LIE_ABOUT_AWB = true;
97
98    /**
99     * Create characteristics for a legacy device by mapping the {@code parameters}
100     * and {@code info}
101     *
102     * @param parameters A non-{@code null} parameters set
103     * @param info Camera info with camera facing direction and angle of orientation
104     *
105     * @return static camera characteristics for a camera device
106     *
107     * @throws NullPointerException if any of the args were {@code null}
108     */
109    public static CameraCharacteristics createCharacteristics(Camera.Parameters parameters,
110            CameraInfo info) {
111        checkNotNull(parameters, "parameters must not be null");
112        checkNotNull(info, "info must not be null");
113
114        String paramStr = parameters.flatten();
115        android.hardware.CameraInfo outerInfo = new android.hardware.CameraInfo();
116        outerInfo.info = info;
117
118        return createCharacteristics(paramStr, outerInfo);
119    }
120
121    /**
122     * Create characteristics for a legacy device by mapping the {@code parameters}
123     * and {@code info}
124     *
125     * @param parameters A string parseable by {@link Camera.Parameters#unflatten}
126     * @param info Camera info with camera facing direction and angle of orientation
127     * @return static camera characteristics for a camera device
128     *
129     * @throws NullPointerException if any of the args were {@code null}
130     */
131    public static CameraCharacteristics createCharacteristics(String parameters,
132            android.hardware.CameraInfo info) {
133        checkNotNull(parameters, "parameters must not be null");
134        checkNotNull(info, "info must not be null");
135        checkNotNull(info.info, "info.info must not be null");
136
137        CameraMetadataNative m = new CameraMetadataNative();
138
139        mapCharacteristicsFromInfo(m, info.info);
140
141        Camera.Parameters params = Camera.getEmptyParameters();
142        params.unflatten(parameters);
143        mapCharacteristicsFromParameters(m, params);
144
145        if (VERBOSE) {
146            Log.v(TAG, "createCharacteristics metadata:");
147            Log.v(TAG, "--------------------------------------------------- (start)");
148            m.dumpToLog();
149            Log.v(TAG, "--------------------------------------------------- (end)");
150        }
151
152        return new CameraCharacteristics(m);
153    }
154
155    private static void mapCharacteristicsFromInfo(CameraMetadataNative m, CameraInfo i) {
156        m.set(LENS_FACING, i.facing == CameraInfo.CAMERA_FACING_BACK ?
157                LENS_FACING_BACK : LENS_FACING_FRONT);
158        m.set(SENSOR_ORIENTATION, i.orientation);
159    }
160
161    private static void mapCharacteristicsFromParameters(CameraMetadataNative m,
162            Camera.Parameters p) {
163        /*
164         * control.ae*
165         */
166        mapControlAe(m, p);
167        /*
168         * control.af*
169         */
170        mapControlAf(m, p);
171        /*
172         * control.awb*
173         */
174        mapControlAwb(m, p);
175        /*
176         * control.*
177         * - Anything that doesn't have a set of related fields
178         */
179        mapControlOther(m, p);
180        /*
181         * lens.*
182         */
183        mapLens(m, p);
184        /*
185         * flash.*
186         */
187        mapFlash(m, p);
188
189        /*
190         * request.*
191         */
192        mapRequest(m, p);
193        // TODO: map other fields
194
195        /*
196         * scaler.*
197         */
198        mapScaler(m, p);
199
200        /*
201         * sensor.*
202         */
203        mapSensor(m, p);
204
205        /*
206         * sync.*
207         */
208        mapSync(m, p);
209
210        /*
211         * info.supportedHardwareLevel
212         */
213        m.set(INFO_SUPPORTED_HARDWARE_LEVEL, INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY);
214
215        /*
216         * scaler.availableStream*, scaler.available*Durations, sensor.info.maxFrameDuration
217         */
218        mapScalerStreamConfigs(m, p);
219
220    }
221
222    private static void mapScalerStreamConfigs(CameraMetadataNative m, Camera.Parameters p) {
223
224        ArrayList<StreamConfiguration> availableStreamConfigs = new ArrayList<>();
225        /*
226         * Implementation-defined (preview, recording, etc) -> use camera1 preview sizes
227         * YUV_420_888 cpu callbacks -> use camera1 preview sizes
228         * Other preview callbacks (CPU) -> use camera1 preview sizes
229         * JPEG still capture -> use camera1 still capture sizes
230         *
231         * Use platform-internal format constants here, since StreamConfigurationMap does the
232         * remapping to public format constants.
233         */
234        List<Camera.Size> previewSizes = p.getSupportedPreviewSizes();
235        appendStreamConfig(availableStreamConfigs,
236                HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, previewSizes);
237        appendStreamConfig(availableStreamConfigs,
238                ImageFormat.YUV_420_888, previewSizes);
239        for (int format : p.getSupportedPreviewFormats()) {
240            if (ImageFormat.isPublicFormat(format)) {
241                appendStreamConfig(availableStreamConfigs, format, previewSizes);
242            } else {
243                /*
244                 *  Do not add any formats unknown to us
245                 * (since it would fail runtime checks in StreamConfigurationMap)
246                 */
247                Log.w(TAG,
248                        String.format("mapStreamConfigs - Skipping non-public format %x", format));
249            }
250        }
251
252        List<Camera.Size> jpegSizes = p.getSupportedPictureSizes();
253        appendStreamConfig(availableStreamConfigs,
254                HAL_PIXEL_FORMAT_BLOB, p.getSupportedPictureSizes());
255        /*
256         * scaler.availableStreamConfigurations
257         */
258        m.set(SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
259                availableStreamConfigs.toArray(new StreamConfiguration[0]));
260
261        /*
262         * scaler.availableMinFrameDurations
263         */
264        // No frame durations available
265        m.set(SCALER_AVAILABLE_MIN_FRAME_DURATIONS, new StreamConfigurationDuration[0]);
266
267        StreamConfigurationDuration[] jpegStalls =
268                new StreamConfigurationDuration[jpegSizes.size()];
269        int i = 0;
270        long longestStallDuration = -1;
271        for (Camera.Size s : jpegSizes) {
272            long stallDuration =  calculateJpegStallDuration(s);
273            jpegStalls[i++] = new StreamConfigurationDuration(HAL_PIXEL_FORMAT_BLOB, s.width,
274                    s.height, stallDuration);
275            if (longestStallDuration < stallDuration) {
276                longestStallDuration = stallDuration;
277            }
278        }
279        /*
280         * scaler.availableStallDurations
281         */
282        // Set stall durations for jpeg, other formats use default stall duration
283        m.set(SCALER_AVAILABLE_STALL_DURATIONS, jpegStalls);
284
285        /*
286         * sensor.info.maxFrameDuration
287         */
288        m.set(SENSOR_INFO_MAX_FRAME_DURATION, longestStallDuration);
289    }
290
291    @SuppressWarnings({"unchecked"})
292    private static void mapControlAe(CameraMetadataNative m, Camera.Parameters p) {
293        /*
294         * control.aeAvailableAntiBandingModes
295         */
296        List<String> antiBandingModes = p.getSupportedAntibanding();
297        if (antiBandingModes != null && antiBandingModes.size() > 0) { // antibanding is optional
298            int[] modes = new int[antiBandingModes.size()];
299            int j = 0;
300            for (String mode : antiBandingModes) {
301                int convertedMode = convertAntiBandingMode(mode);
302                if (convertedMode == -1) {
303                    Log.w(TAG, "Antibanding mode " + ((mode == null) ? "NULL" : mode) +
304                            " not supported, skipping...");
305                } else {
306                    modes[j++] = convertedMode;
307                }
308            }
309            m.set(CONTROL_AE_AVAILABLE_ANTIBANDING_MODES, Arrays.copyOf(modes, j));
310        } else {
311            m.set(CONTROL_AE_AVAILABLE_ANTIBANDING_MODES, new int[0]);
312        }
313
314        /*
315         * control.aeAvailableTargetFpsRanges
316         */
317        {
318            List<int[]> fpsRanges = p.getSupportedPreviewFpsRange();
319            if (fpsRanges == null) {
320                throw new AssertionError("Supported FPS ranges cannot be null.");
321            }
322            int rangesSize = fpsRanges.size();
323            if (rangesSize <= 0) {
324                throw new AssertionError("At least one FPS range must be supported.");
325            }
326            Range<Integer>[] ranges = new Range[rangesSize];
327            int i = 0;
328            for (int[] r : fpsRanges) {
329                ranges[i++] = Range.create(r[Camera.Parameters.PREVIEW_FPS_MIN_INDEX],
330                        r[Camera.Parameters.PREVIEW_FPS_MAX_INDEX]);
331            }
332            m.set(CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES, ranges);
333        }
334
335        /*
336         * control.aeAvailableModes
337         */
338        {
339            List<String> flashModes = p.getSupportedFlashModes();
340
341            String[] flashModeStrings = new String[] {
342                    Camera.Parameters.FLASH_MODE_OFF,
343                    Camera.Parameters.FLASH_MODE_AUTO,
344                    Camera.Parameters.FLASH_MODE_ON,
345                    Camera.Parameters.FLASH_MODE_RED_EYE,
346                    // Map these manually
347                    Camera.Parameters.FLASH_MODE_TORCH,
348            };
349            int[] flashModeInts = new int[] {
350                    CONTROL_AE_MODE_ON,
351                    CONTROL_AE_MODE_ON_AUTO_FLASH,
352                    CONTROL_AE_MODE_ON_ALWAYS_FLASH,
353                    CONTROL_AE_MODE_ON_AUTO_FLASH_REDEYE
354            };
355            int[] aeAvail = ArrayUtils.convertStringListToIntArray(
356                    flashModes, flashModeStrings, flashModeInts);
357
358            // No flash control -> AE is always on
359            if (aeAvail == null || aeAvail.length == 0) {
360                aeAvail = new int[] {
361                        CONTROL_AE_MODE_ON
362                };
363            }
364
365            // Note that AE_MODE_OFF is never available.
366            m.set(CONTROL_AE_AVAILABLE_MODES, aeAvail);
367        }
368
369        /*
370         * control.aeCompensationRanges
371         */
372        {
373            int min = p.getMinExposureCompensation();
374            int max = p.getMaxExposureCompensation();
375
376            m.set(CONTROL_AE_COMPENSATION_RANGE, Range.create(min, max));
377        }
378
379        /*
380         * control.aeCompensationStep
381         */
382        {
383            float step = p.getExposureCompensationStep();
384
385            m.set(CONTROL_AE_COMPENSATION_STEP, ParamsUtils.createRational(step));
386        }
387    }
388
389
390    @SuppressWarnings({"unchecked"})
391    private static void mapControlAf(CameraMetadataNative m, Camera.Parameters p) {
392        /*
393         * control.afAvailableModes
394         */
395        {
396            List<String> focusModes = p.getSupportedFocusModes();
397
398            String[] focusModeStrings = new String[] {
399                    Camera.Parameters.FOCUS_MODE_AUTO,
400                    Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE,
401                    Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO,
402                    Camera.Parameters.FOCUS_MODE_EDOF,
403                    Camera.Parameters.FOCUS_MODE_INFINITY,
404                    Camera.Parameters.FOCUS_MODE_MACRO,
405                    Camera.Parameters.FOCUS_MODE_FIXED,
406            };
407
408            int[] focusModeInts = new int[] {
409                    CONTROL_AF_MODE_AUTO,
410                    CONTROL_AF_MODE_CONTINUOUS_PICTURE,
411                    CONTROL_AF_MODE_CONTINUOUS_VIDEO,
412                    CONTROL_AF_MODE_EDOF,
413                    CONTROL_AF_MODE_OFF,
414                    CONTROL_AF_MODE_MACRO,
415                    CONTROL_AF_MODE_OFF
416            };
417
418            List<Integer> afAvail = ArrayUtils.convertStringListToIntList(
419                    focusModes, focusModeStrings, focusModeInts);
420
421            // No AF modes supported? That's unpossible!
422            if (afAvail == null || afAvail.size() == 0) {
423                Log.w(TAG, "No AF modes supported (HAL bug); defaulting to AF_MODE_OFF only");
424                afAvail = new ArrayList<Integer>(/*capacity*/1);
425                afAvail.add(CONTROL_AF_MODE_OFF);
426            }
427
428            m.set(CONTROL_AF_AVAILABLE_MODES, ArrayUtils.toIntArray(afAvail));
429
430            if (VERBOSE) {
431                Log.v(TAG, "mapControlAf - control.afAvailableModes set to " +
432                        ListUtils.listToString(afAvail));
433            }
434        }
435    }
436
437    private static void mapControlAwb(CameraMetadataNative m, Camera.Parameters p) {
438        if (!LIE_ABOUT_AWB) {
439            throw new AssertionError("Not implemented yet");
440        }
441    }
442
443    private static void mapControlOther(CameraMetadataNative m, Camera.Parameters p) {
444        /*
445         * android.control.maxRegions
446         */
447        final int AE = 0, AWB = 1, AF = 2;
448
449        int[] maxRegions = new int[3];
450        maxRegions[AE] = p.getMaxNumMeteringAreas();
451        maxRegions[AWB] = 0; // AWB regions not supported in API1
452        maxRegions[AF] = p.getMaxNumFocusAreas();
453
454        if (LIE_ABOUT_AE_MAX_REGIONS) {
455            maxRegions[AE] = 0;
456        }
457        if (LIE_ABOUT_AF_MAX_REGIONS) {
458            maxRegions[AF] = 0;
459        }
460
461        m.set(CONTROL_MAX_REGIONS, maxRegions);
462
463        /*
464         * android.control.availableEffects
465         */
466        List<String> effectModes = p.getSupportedColorEffects();
467        int[] supportedEffectModes = (effectModes == null) ? new int[0] :
468                ArrayUtils.convertStringListToIntArray(effectModes, sLegacyEffectMode,
469                        sEffectModes);
470        m.set(CONTROL_AVAILABLE_EFFECTS, supportedEffectModes);
471
472        /*
473         * android.control.availableSceneModes
474         */
475        List<String> sceneModes = p.getSupportedSceneModes();
476        int[] supportedSceneModes = (sceneModes == null) ? new int[0] :
477                ArrayUtils.convertStringListToIntArray(sceneModes, sLegacySceneModes, sSceneModes);
478        m.set(CONTROL_AVAILABLE_SCENE_MODES, supportedSceneModes);
479    }
480
481    private static void mapLens(CameraMetadataNative m, Camera.Parameters p) {
482        /*
483         *  We can tell if the lens is fixed focus;
484         *  but if it's not, we can't tell the minimum focus distance, so leave it null then.
485         */
486        if (p.getFocusMode() == Camera.Parameters.FOCUS_MODE_FIXED) {
487            /*
488             * lens.info.minimumFocusDistance
489             */
490            m.set(LENS_INFO_MINIMUM_FOCUS_DISTANCE, LENS_INFO_MINIMUM_FOCUS_DISTANCE_FIXED_FOCUS);
491        }
492    }
493
494    private static void mapFlash(CameraMetadataNative m, Camera.Parameters p) {
495        boolean flashAvailable = false;
496        List<String> supportedFlashModes = p.getSupportedFlashModes();
497
498        if (supportedFlashModes != null) {
499            // If only 'OFF' is available, we don't really have flash support
500            flashAvailable = !ListUtils.listElementsEqualTo(
501                    supportedFlashModes, Camera.Parameters.FLASH_MODE_OFF);
502        }
503
504        /*
505         * flash.info.available
506         */
507        m.set(FLASH_INFO_AVAILABLE, flashAvailable);
508    }
509
510    private static void mapRequest(CameraMetadataNative m, Parameters p) {
511        /*
512         * request.availableCapabilities
513         */
514        int[] capabilities = { REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE };
515        m.set(REQUEST_AVAILABLE_CAPABILITIES, capabilities);
516
517        /*
518         * request.availableCharacteristicsKeys
519         */
520        {
521            // TODO: check if the underlying key is supported before listing a key as available
522
523            // Note: We only list public keys. Native HALs should list ALL keys regardless of visibility.
524
525            Key<?> availableKeys[] = new Key<?>[] {
526                    CameraCharacteristics.CONTROL_AE_AVAILABLE_ANTIBANDING_MODES          ,
527                    CameraCharacteristics.CONTROL_AE_AVAILABLE_MODES                      ,
528                    CameraCharacteristics.CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES          ,
529                    CameraCharacteristics.CONTROL_AE_COMPENSATION_RANGE                   ,
530                    CameraCharacteristics.CONTROL_AE_COMPENSATION_STEP                    ,
531                    CameraCharacteristics.CONTROL_AF_AVAILABLE_MODES                      ,
532                    CameraCharacteristics.CONTROL_AVAILABLE_EFFECTS                       ,
533                    CameraCharacteristics.CONTROL_AVAILABLE_SCENE_MODES                   ,
534                    CameraCharacteristics.CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES     ,
535                    CameraCharacteristics.CONTROL_AWB_AVAILABLE_MODES                     ,
536                    CameraCharacteristics.CONTROL_MAX_REGIONS                             ,
537                    CameraCharacteristics.FLASH_INFO_AVAILABLE                            ,
538                    CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL                   ,
539                    CameraCharacteristics.JPEG_AVAILABLE_THUMBNAIL_SIZES                  ,
540                    CameraCharacteristics.LENS_FACING                                     ,
541                    CameraCharacteristics.LENS_INFO_AVAILABLE_FOCAL_LENGTHS               ,
542                    CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES                  ,
543                    CameraCharacteristics.REQUEST_MAX_NUM_OUTPUT_STREAMS                  ,
544                    CameraCharacteristics.REQUEST_PARTIAL_RESULT_COUNT                    ,
545                    CameraCharacteristics.REQUEST_PIPELINE_MAX_DEPTH                      ,
546                    CameraCharacteristics.SCALER_AVAILABLE_MAX_DIGITAL_ZOOM               ,
547//                    CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP                 ,
548                    CameraCharacteristics.SCALER_CROPPING_TYPE                            ,
549                    CameraCharacteristics.SENSOR_AVAILABLE_TEST_PATTERN_MODES             ,
550                    CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE                   ,
551                    CameraCharacteristics.SENSOR_INFO_PHYSICAL_SIZE                       ,
552                    CameraCharacteristics.SENSOR_INFO_PIXEL_ARRAY_SIZE                    ,
553                    CameraCharacteristics.SENSOR_ORIENTATION                              ,
554                    CameraCharacteristics.STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES     ,
555                    CameraCharacteristics.STATISTICS_INFO_MAX_FACE_COUNT                  ,
556                    CameraCharacteristics.SYNC_MAX_LATENCY                                ,
557            };
558            m.set(REQUEST_AVAILABLE_CHARACTERISTICS_KEYS, getTagsForKeys(availableKeys));
559        }
560
561        /*
562         * request.availableRequestKeys
563         */
564        {
565            CaptureRequest.Key<?> availableKeys[] = new CaptureRequest.Key<?>[] {
566                    CaptureRequest.CONTROL_AE_ANTIBANDING_MODE,
567                    CaptureRequest.CONTROL_AE_EXPOSURE_COMPENSATION,
568                    CaptureRequest.CONTROL_AE_LOCK,
569                    CaptureRequest.CONTROL_AE_MODE,
570                    CaptureRequest.CONTROL_AE_REGIONS,
571                    CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE,
572                    CaptureRequest.CONTROL_AF_MODE,
573                    CaptureRequest.CONTROL_AF_REGIONS,
574                    CaptureRequest.CONTROL_AF_TRIGGER,
575                    CaptureRequest.CONTROL_AWB_LOCK,
576                    CaptureRequest.CONTROL_AWB_MODE,
577                    CaptureRequest.CONTROL_CAPTURE_INTENT,
578                    CaptureRequest.CONTROL_EFFECT_MODE,
579                    CaptureRequest.CONTROL_MODE,
580                    CaptureRequest.CONTROL_SCENE_MODE,
581                    CaptureRequest.CONTROL_VIDEO_STABILIZATION_MODE,
582                    CaptureRequest.FLASH_MODE,
583                    CaptureRequest.JPEG_GPS_COORDINATES,
584                    CaptureRequest.JPEG_GPS_PROCESSING_METHOD,
585                    CaptureRequest.JPEG_GPS_TIMESTAMP,
586                    CaptureRequest.JPEG_ORIENTATION,
587                    CaptureRequest.JPEG_QUALITY,
588                    CaptureRequest.JPEG_THUMBNAIL_QUALITY,
589                    CaptureRequest.JPEG_THUMBNAIL_SIZE,
590                    CaptureRequest.LENS_FOCAL_LENGTH,
591                    CaptureRequest.SCALER_CROP_REGION,
592                    CaptureRequest.STATISTICS_FACE_DETECT_MODE,
593            };
594            m.set(REQUEST_AVAILABLE_REQUEST_KEYS, getTagsForKeys(availableKeys));
595        }
596
597        /*
598         * request.availableResultKeys
599         */
600        {
601            CaptureResult.Key<?> availableKeys[] = new CaptureResult.Key<?>[] {
602                    CaptureResult.CONTROL_AE_ANTIBANDING_MODE                      ,
603                    CaptureResult.CONTROL_AE_EXPOSURE_COMPENSATION                 ,
604                    CaptureResult.CONTROL_AE_LOCK                                  ,
605                    CaptureResult.CONTROL_AE_MODE                                  ,
606                    CaptureResult.CONTROL_AE_REGIONS                               ,
607                    CaptureResult.CONTROL_AF_MODE                                  ,
608                    CaptureResult.CONTROL_AF_REGIONS                               ,
609                    CaptureResult.CONTROL_AF_STATE                                 ,
610                    CaptureResult.CONTROL_AWB_MODE                                 ,
611                    CaptureResult.CONTROL_AWB_LOCK                                 ,
612                    CaptureResult.CONTROL_MODE                                     ,
613                    CaptureResult.FLASH_MODE                                       ,
614                    CaptureResult.JPEG_GPS_COORDINATES                             ,
615                    CaptureResult.JPEG_GPS_PROCESSING_METHOD                       ,
616                    CaptureResult.JPEG_GPS_TIMESTAMP                               ,
617                    CaptureResult.JPEG_ORIENTATION                                 ,
618                    CaptureResult.JPEG_QUALITY                                     ,
619                    CaptureResult.JPEG_THUMBNAIL_QUALITY                           ,
620                    CaptureResult.LENS_FOCAL_LENGTH                                ,
621                    CaptureResult.REQUEST_PIPELINE_DEPTH                           ,
622                    CaptureResult.SCALER_CROP_REGION                               ,
623                    CaptureResult.SENSOR_TIMESTAMP                                 ,
624                    CaptureResult.STATISTICS_FACE_DETECT_MODE                      ,
625//                    CaptureResult.STATISTICS_FACES                                 ,
626            };
627            m.set(REQUEST_AVAILABLE_RESULT_KEYS, getTagsForKeys(availableKeys));
628        }
629
630        /*
631         * request.maxNumOutputStreams
632         */
633        int[] outputStreams = {
634                /* RAW */
635                REQUEST_MAX_NUM_OUTPUT_STREAMS_COUNT_RAW,
636                /* Processed & Not-Stalling */
637                REQUEST_MAX_NUM_OUTPUT_STREAMS_COUNT_PROC,
638                /* Processed & Stalling */
639                REQUEST_MAX_NUM_OUTPUT_STREAMS_COUNT_PROC_STALL,
640        };
641        m.set(REQUEST_MAX_NUM_OUTPUT_STREAMS, outputStreams);
642
643        /*
644         * request.maxNumInputStreams
645         */
646        m.set(REQUEST_MAX_NUM_INPUT_STREAMS, REQUEST_MAX_NUM_INPUT_STREAMS_COUNT);
647
648        /*
649         * request.pipelineMaxDepth
650         */
651        m.set(REQUEST_PIPELINE_MAX_DEPTH,
652                (byte)(REQUEST_PIPELINE_MAX_DEPTH_HAL1 + REQUEST_PIPELINE_MAX_DEPTH_OURS));
653    }
654
655    private static void mapScaler(CameraMetadataNative m, Parameters p) {
656        /*
657         * scaler.availableMaxDigitalZoom
658         */
659        m.set(SCALER_AVAILABLE_MAX_DIGITAL_ZOOM, ParameterUtils.getMaxZoomRatio(p));
660
661        /*
662         * scaler.croppingType = CENTER_ONLY
663         */
664        m.set(SCALER_CROPPING_TYPE, SCALER_CROPPING_TYPE_CENTER_ONLY);
665    }
666
667    private static void mapSensor(CameraMetadataNative m, Parameters p) {
668        // Use the largest jpeg size (by area) for both active array and pixel array
669        Size largestJpegSize = getLargestSupportedJpegSizeByArea(p);
670        /*
671         * sensor.info.activeArraySize
672         */
673        {
674            Rect activeArrayRect = ParamsUtils.createRect(largestJpegSize);
675            m.set(SENSOR_INFO_ACTIVE_ARRAY_SIZE, activeArrayRect);
676        }
677
678        /*
679         * sensor.info.pixelArraySize
680         */
681        m.set(SENSOR_INFO_PIXEL_ARRAY_SIZE, largestJpegSize);
682    }
683
684    private static void mapSync(CameraMetadataNative m, Parameters p) {
685        /*
686         * sync.maxLatency
687         */
688        m.set(SYNC_MAX_LATENCY, SYNC_MAX_LATENCY_UNKNOWN);
689    }
690
691    private static void appendStreamConfig(
692            ArrayList<StreamConfiguration> configs, int format, List<Camera.Size> sizes) {
693        for (Camera.Size size : sizes) {
694            StreamConfiguration config =
695                    new StreamConfiguration(format, size.width, size.height, /*input*/false);
696            configs.add(config);
697        }
698    }
699
700    private final static String[] sLegacySceneModes = {
701        Parameters.SCENE_MODE_AUTO,
702        Parameters.SCENE_MODE_ACTION,
703        Parameters.SCENE_MODE_PORTRAIT,
704        Parameters.SCENE_MODE_LANDSCAPE,
705        Parameters.SCENE_MODE_NIGHT,
706        Parameters.SCENE_MODE_NIGHT_PORTRAIT,
707        Parameters.SCENE_MODE_THEATRE,
708        Parameters.SCENE_MODE_BEACH,
709        Parameters.SCENE_MODE_SNOW,
710        Parameters.SCENE_MODE_SUNSET,
711        Parameters.SCENE_MODE_STEADYPHOTO,
712        Parameters.SCENE_MODE_FIREWORKS,
713        Parameters.SCENE_MODE_SPORTS,
714        Parameters.SCENE_MODE_PARTY,
715        Parameters.SCENE_MODE_CANDLELIGHT,
716        Parameters.SCENE_MODE_BARCODE,
717    };
718
719    private final static int[] sSceneModes = {
720        CameraCharacteristics.CONTROL_SCENE_MODE_DISABLED,
721        CameraCharacteristics.CONTROL_SCENE_MODE_ACTION,
722        CameraCharacteristics.CONTROL_SCENE_MODE_PORTRAIT,
723        CameraCharacteristics.CONTROL_SCENE_MODE_LANDSCAPE,
724        CameraCharacteristics.CONTROL_SCENE_MODE_NIGHT,
725        CameraCharacteristics.CONTROL_SCENE_MODE_NIGHT_PORTRAIT,
726        CameraCharacteristics.CONTROL_SCENE_MODE_THEATRE,
727        CameraCharacteristics.CONTROL_SCENE_MODE_BEACH,
728        CameraCharacteristics.CONTROL_SCENE_MODE_SNOW,
729        CameraCharacteristics.CONTROL_SCENE_MODE_SUNSET,
730        CameraCharacteristics.CONTROL_SCENE_MODE_STEADYPHOTO,
731        CameraCharacteristics.CONTROL_SCENE_MODE_FIREWORKS,
732        CameraCharacteristics.CONTROL_SCENE_MODE_SPORTS,
733        CameraCharacteristics.CONTROL_SCENE_MODE_PARTY,
734        CameraCharacteristics.CONTROL_SCENE_MODE_CANDLELIGHT,
735        CameraCharacteristics.CONTROL_SCENE_MODE_BARCODE,
736    };
737
738    static int convertSceneModeFromLegacy(String mode) {
739        if (mode == null) {
740            return CameraCharacteristics.CONTROL_SCENE_MODE_DISABLED;
741        }
742        int index = ArrayUtils.getArrayIndex(sLegacySceneModes, mode);
743        if (index < 0) {
744            return UNKNOWN_MODE;
745        }
746        return sSceneModes[index];
747    }
748
749    static String convertSceneModeToLegacy(int mode) {
750        int index = ArrayUtils.getArrayIndex(sSceneModes, mode);
751        if (index < 0) {
752            return null;
753        }
754        return sLegacySceneModes[index];
755    }
756
757    private final static String[] sLegacyEffectMode = {
758        Parameters.EFFECT_NONE,
759        Parameters.EFFECT_MONO,
760        Parameters.EFFECT_NEGATIVE,
761        Parameters.EFFECT_SOLARIZE,
762        Parameters.EFFECT_SEPIA,
763        Parameters.EFFECT_POSTERIZE,
764        Parameters.EFFECT_WHITEBOARD,
765        Parameters.EFFECT_BLACKBOARD,
766        Parameters.EFFECT_AQUA,
767    };
768
769    private final static int[] sEffectModes = {
770        CameraCharacteristics.CONTROL_EFFECT_MODE_OFF,
771        CameraCharacteristics.CONTROL_EFFECT_MODE_MONO,
772        CameraCharacteristics.CONTROL_EFFECT_MODE_NEGATIVE,
773        CameraCharacteristics.CONTROL_EFFECT_MODE_SOLARIZE,
774        CameraCharacteristics.CONTROL_EFFECT_MODE_SEPIA,
775        CameraCharacteristics.CONTROL_EFFECT_MODE_POSTERIZE,
776        CameraCharacteristics.CONTROL_EFFECT_MODE_WHITEBOARD,
777        CameraCharacteristics.CONTROL_EFFECT_MODE_BLACKBOARD,
778        CameraCharacteristics.CONTROL_EFFECT_MODE_AQUA,
779    };
780
781    static int convertEffectModeFromLegacy(String mode) {
782        if (mode == null) {
783            return CameraCharacteristics.CONTROL_EFFECT_MODE_OFF;
784        }
785        int index = ArrayUtils.getArrayIndex(sLegacyEffectMode, mode);
786        if (index < 0) {
787            return UNKNOWN_MODE;
788        }
789        return sEffectModes[index];
790    }
791
792    static String convertEffectModeToLegacy(int mode) {
793        int index = ArrayUtils.getArrayIndex(sEffectModes, mode);
794        if (index < 0) {
795            return null;
796        }
797        return sLegacyEffectMode[index];
798    }
799
800    /**
801     * Convert the ae antibanding mode from api1 into api2.
802     *
803     * @param mode the api1 mode, {@code null} is allowed and will return {@code -1}.
804     *
805     * @return The api2 value, or {@code -1} by default if conversion failed
806     */
807    private static int convertAntiBandingMode(String mode) {
808        if (mode == null) {
809            return -1;
810        }
811
812        switch (mode) {
813            case Camera.Parameters.ANTIBANDING_OFF: {
814                return CONTROL_AE_ANTIBANDING_MODE_OFF;
815            }
816            case Camera.Parameters.ANTIBANDING_50HZ: {
817                return CONTROL_AE_ANTIBANDING_MODE_50HZ;
818            }
819            case Camera.Parameters.ANTIBANDING_60HZ: {
820                return CONTROL_AE_ANTIBANDING_MODE_60HZ;
821            }
822            case Camera.Parameters.ANTIBANDING_AUTO: {
823                return CONTROL_AE_ANTIBANDING_MODE_AUTO;
824            }
825            default: {
826                Log.w(TAG, "convertAntiBandingMode - Unknown antibanding mode " + mode);
827                return -1;
828            }
829        }
830    }
831
832    /**
833     * Convert the ae antibanding mode from api1 into api2.
834     *
835     * @param mode the api1 mode, {@code null} is allowed and will return {@code MODE_OFF}.
836     *
837     * @return The api2 value, or {@code MODE_OFF} by default if conversion failed
838     */
839    static int convertAntiBandingModeOrDefault(String mode) {
840        int antiBandingMode = convertAntiBandingMode(mode);
841        if (antiBandingMode == -1) {
842            return CONTROL_AE_ANTIBANDING_MODE_OFF;
843        }
844
845        return antiBandingMode;
846    }
847
848    private static int[] convertAeFpsRangeToLegacy(Range<Integer> fpsRange) {
849        int[] legacyFps = new int[2];
850        legacyFps[Camera.Parameters.PREVIEW_FPS_MIN_INDEX] = fpsRange.getLower();
851        legacyFps[Camera.Parameters.PREVIEW_FPS_MAX_INDEX] = fpsRange.getUpper();
852        return legacyFps;
853    }
854
855    /**
856     * Return the stall duration for a given output jpeg size in nanoseconds.
857     *
858     * <p>An 8mp image is chosen to have a stall duration of 0.8 seconds.</p>
859     */
860    private static long calculateJpegStallDuration(Camera.Size size) {
861        long baseDuration = APPROXIMATE_CAPTURE_DELAY_MS * NS_PER_MS; // 200ms for capture
862        long area = size.width * (long) size.height;
863        long stallPerArea = APPROXIMATE_JPEG_ENCODE_TIME_MS * NS_PER_MS /
864                APPROXIMATE_SENSOR_AREA_PX; // 600ms stall for 8mp
865        return baseDuration + area * stallPerArea;
866    }
867
868    /**
869     * Set the legacy parameters using the {@link LegacyRequest legacy request}.
870     *
871     * <p>The legacy request's parameters are changed as a side effect of calling this
872     * method.</p>
873     *
874     * @param request a non-{@code null} legacy request
875     */
876    public static void convertRequestMetadata(LegacyRequest request) {
877        LegacyRequestMapper.convertRequestMetadata(request);
878    }
879
880    /**
881     * Create a request template
882     *
883     * @param c a non-{@code null} camera characteristics for this camera
884     * @param templateId a non-negative template ID
885     *
886     * @return a non-{@code null} request template
887     *
888     * @throws IllegalArgumentException if {@code templateId} was invalid
889     *
890     * @see android.hardware.camera2.CameraDevice#TEMPLATE_MANUAL
891     */
892    public static CameraMetadataNative createRequestTemplate(
893            CameraCharacteristics c, int templateId) {
894        if (templateId < 0 || templateId > CameraDevice.TEMPLATE_MANUAL) {
895            throw new IllegalArgumentException("templateId out of range");
896        }
897
898        CameraMetadataNative m = new CameraMetadataNative();
899
900        /*
901         * NOTE: If adding new code here and it needs to query the static info,
902         * query the camera characteristics, so we can reuse this for api2 code later
903         * to create our own templates in the framework
904         */
905
906        if (LIE_ABOUT_AWB) {
907            m.set(CaptureRequest.CONTROL_AWB_MODE, CameraMetadata.CONTROL_AWB_MODE_AUTO);
908        } else {
909            throw new AssertionError("Valid control.awbMode not implemented yet");
910        }
911
912        // control.aeMode
913        m.set(CaptureRequest.CONTROL_AE_MODE, CameraMetadata.CONTROL_AE_MODE_ON);
914        // AE is always unconditionally available in API1 devices
915
916        // control.afMode
917        {
918            Float minimumFocusDistance = c.get(LENS_INFO_MINIMUM_FOCUS_DISTANCE);
919
920            int afMode;
921            if (minimumFocusDistance != null &&
922                    minimumFocusDistance == LENS_INFO_MINIMUM_FOCUS_DISTANCE_FIXED_FOCUS) {
923                // Cannot control auto-focus with fixed-focus cameras
924                afMode = CameraMetadata.CONTROL_AF_MODE_OFF;
925            } else {
926                // If a minimum focus distance is reported; the camera must have AF
927                afMode = CameraMetadata.CONTROL_AF_MODE_AUTO;
928            }
929
930            m.set(CaptureRequest.CONTROL_AF_MODE, afMode);
931        }
932
933        // TODO: map other request template values
934        return m;
935    }
936
937    private static int[] getTagsForKeys(Key<?>[] keys) {
938        int[] tags = new int[keys.length];
939
940        for (int i = 0; i < keys.length; ++i) {
941            tags[i] = keys[i].getNativeKey().getTag();
942        }
943
944        return tags;
945    }
946
947    private static int[] getTagsForKeys(CaptureRequest.Key<?>[] keys) {
948        int[] tags = new int[keys.length];
949
950        for (int i = 0; i < keys.length; ++i) {
951            tags[i] = keys[i].getNativeKey().getTag();
952        }
953
954        return tags;
955    }
956
957    private static int[] getTagsForKeys(CaptureResult.Key<?>[] keys) {
958        int[] tags = new int[keys.length];
959
960        for (int i = 0; i < keys.length; ++i) {
961            tags[i] = keys[i].getNativeKey().getTag();
962        }
963
964        return tags;
965    }
966
967    /**
968     * Convert the requested AF mode into its equivalent supported parameter.
969     *
970     * @param mode {@code CONTROL_AF_MODE}
971     * @param supportedFocusModes list of camera1's supported focus modes
972     * @return the stringified af mode, or {@code null} if its not supported
973     */
974    static String convertAfModeToLegacy(int mode, List<String> supportedFocusModes) {
975        if (supportedFocusModes == null || supportedFocusModes.isEmpty()) {
976            Log.w(TAG, "No focus modes supported; API1 bug");
977            return null;
978        }
979
980        String param = null;
981        switch (mode) {
982            case CONTROL_AF_MODE_AUTO:
983                param = Parameters.FOCUS_MODE_AUTO;
984                break;
985            case CONTROL_AF_MODE_CONTINUOUS_PICTURE:
986                param = Parameters.FOCUS_MODE_CONTINUOUS_PICTURE;
987                break;
988            case CONTROL_AF_MODE_CONTINUOUS_VIDEO:
989                param = Parameters.FOCUS_MODE_CONTINUOUS_VIDEO;
990                break;
991            case CONTROL_AF_MODE_EDOF:
992                param = Parameters.FOCUS_MODE_EDOF;
993                break;
994            case CONTROL_AF_MODE_MACRO:
995                param = Parameters.FOCUS_MODE_MACRO;
996                break;
997            case CONTROL_AF_MODE_OFF:
998                if (supportedFocusModes.contains(Parameters.FOCUS_MODE_FIXED)) {
999                    param = Parameters.FOCUS_MODE_FIXED;
1000                } else {
1001                    param = Parameters.FOCUS_MODE_INFINITY;
1002                }
1003        }
1004
1005        if (!supportedFocusModes.contains(param)) {
1006            // Weed out bad user input by setting to the first arbitrary focus mode
1007            String defaultMode = supportedFocusModes.get(0);
1008            Log.w(TAG,
1009                    String.format(
1010                            "convertAfModeToLegacy - ignoring unsupported mode %d, " +
1011                            "defaulting to %s", mode, defaultMode));
1012            param = defaultMode;
1013        }
1014
1015        return param;
1016    }
1017}
1018