OSDN Git Service

Merge "DO NOT MERGE. No direct Uri grants from system." into lmp-mr1-dev am: 6d3573e530
[android-x86/frameworks-base.git] / core / java / android / hardware / camera2 / legacy / LegacyMetadataMapper.java
1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package android.hardware.camera2.legacy;
18
19 import android.graphics.ImageFormat;
20 import android.graphics.PixelFormat;
21 import android.graphics.Rect;
22 import android.hardware.Camera;
23 import android.hardware.Camera.CameraInfo;
24 import android.hardware.Camera.Parameters;
25 import android.hardware.camera2.CameraCharacteristics;
26 import android.hardware.camera2.CameraDevice;
27 import android.hardware.camera2.CameraMetadata;
28 import android.hardware.camera2.CaptureRequest;
29 import android.hardware.camera2.CaptureResult;
30 import android.hardware.camera2.impl.CameraMetadataNative;
31 import android.hardware.camera2.params.MeteringRectangle;
32 import android.hardware.camera2.params.StreamConfiguration;
33 import android.hardware.camera2.params.StreamConfigurationDuration;
34 import android.hardware.camera2.utils.ArrayUtils;
35 import android.hardware.camera2.utils.ListUtils;
36 import android.hardware.camera2.utils.ParamsUtils;
37 import android.util.Log;
38 import android.util.Range;
39 import android.util.Size;
40 import android.util.SizeF;
41
42 import java.util.ArrayList;
43 import java.util.Arrays;
44 import java.util.Collections;
45 import java.util.List;
46
47 import static com.android.internal.util.Preconditions.*;
48 import static android.hardware.camera2.CameraCharacteristics.*;
49 import static android.hardware.camera2.legacy.ParameterUtils.*;
50
51 /**
52  * Provide legacy-specific implementations of camera2 metadata for legacy devices, such as the
53  * camera characteristics.
54  */
55 @SuppressWarnings("deprecation")
56 public class LegacyMetadataMapper {
57     private static final String TAG = "LegacyMetadataMapper";
58     private static final boolean DEBUG = false;
59
60     private static final long NS_PER_MS = 1000000;
61
62     // from graphics.h
63     public static final int HAL_PIXEL_FORMAT_RGBA_8888 = PixelFormat.RGBA_8888;
64     public static final int HAL_PIXEL_FORMAT_BGRA_8888 = 0x5;
65     public static final int HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED = 0x22;
66     public static final int HAL_PIXEL_FORMAT_BLOB = 0x21;
67
68     // for metadata
69     private static final float LENS_INFO_MINIMUM_FOCUS_DISTANCE_FIXED_FOCUS = 0.0f;
70
71     private static final int REQUEST_MAX_NUM_OUTPUT_STREAMS_COUNT_RAW = 0; // no raw support
72     private static final int REQUEST_MAX_NUM_OUTPUT_STREAMS_COUNT_PROC = 3; // preview, video, cb
73     private static final int REQUEST_MAX_NUM_OUTPUT_STREAMS_COUNT_PROC_STALL = 1; // 1 jpeg only
74     private static final int REQUEST_MAX_NUM_INPUT_STREAMS_COUNT = 0; // no reprocessing
75
76     /** Assume 3 HAL1 stages: Exposure, Read-out, Post-Processing */
77     private static final int REQUEST_PIPELINE_MAX_DEPTH_HAL1 = 3;
78     /** Assume 3 shim stages: Preview input, Split output, Format conversion for output */
79     private static final int REQUEST_PIPELINE_MAX_DEPTH_OURS = 3;
80     /* TODO: Update above maxDepth values once we do more performance measurements */
81
82     // For approximating JPEG stall durations
83     private static final long APPROXIMATE_CAPTURE_DELAY_MS = 200; // 200 milliseconds
84     private static final long APPROXIMATE_SENSOR_AREA_PX = (1 << 23); // 8 megapixels
85     private static final long APPROXIMATE_JPEG_ENCODE_TIME_MS = 600; // 600 milliseconds
86
87     static final int UNKNOWN_MODE = -1;
88
89     // Maximum difference between a preview size aspect ratio and a jpeg size aspect ratio
90     private static final float PREVIEW_ASPECT_RATIO_TOLERANCE = 0.01f;
91
92     /*
93      * Development hijinks: Lie about not supporting certain capabilities
94      *
95      * - Unblock some CTS tests from running whose main intent is not the metadata itself
96      *
97      * TODO: Remove these constants and strip out any code that previously relied on them
98      * being set to true.
99      */
100     static final boolean LIE_ABOUT_AE_STATE = false;
101     static final boolean LIE_ABOUT_AE_MAX_REGIONS = false;
102     static final boolean LIE_ABOUT_AF = false;
103     static final boolean LIE_ABOUT_AF_MAX_REGIONS = false;
104     static final boolean LIE_ABOUT_AWB_STATE = false;
105     static final boolean LIE_ABOUT_AWB = false;
106
107
108     /**
109      * Create characteristics for a legacy device by mapping the {@code parameters}
110      * and {@code info}
111      *
112      * @param parameters A non-{@code null} parameters set
113      * @param info Camera info with camera facing direction and angle of orientation
114      *
115      * @return static camera characteristics for a camera device
116      *
117      * @throws NullPointerException if any of the args were {@code null}
118      */
119     public static CameraCharacteristics createCharacteristics(Camera.Parameters parameters,
120             CameraInfo info) {
121         checkNotNull(parameters, "parameters must not be null");
122         checkNotNull(info, "info must not be null");
123
124         String paramStr = parameters.flatten();
125         android.hardware.CameraInfo outerInfo = new android.hardware.CameraInfo();
126         outerInfo.info = info;
127
128         return createCharacteristics(paramStr, outerInfo);
129     }
130
131     /**
132      * Create characteristics for a legacy device by mapping the {@code parameters}
133      * and {@code info}
134      *
135      * @param parameters A string parseable by {@link Camera.Parameters#unflatten}
136      * @param info Camera info with camera facing direction and angle of orientation
137      * @return static camera characteristics for a camera device
138      *
139      * @throws NullPointerException if any of the args were {@code null}
140      */
141     public static CameraCharacteristics createCharacteristics(String parameters,
142             android.hardware.CameraInfo info) {
143         checkNotNull(parameters, "parameters must not be null");
144         checkNotNull(info, "info must not be null");
145         checkNotNull(info.info, "info.info must not be null");
146
147         CameraMetadataNative m = new CameraMetadataNative();
148
149         mapCharacteristicsFromInfo(m, info.info);
150
151         Camera.Parameters params = Camera.getEmptyParameters();
152         params.unflatten(parameters);
153         mapCharacteristicsFromParameters(m, params);
154
155         if (DEBUG) {
156             Log.v(TAG, "createCharacteristics metadata:");
157             Log.v(TAG, "--------------------------------------------------- (start)");
158             m.dumpToLog();
159             Log.v(TAG, "--------------------------------------------------- (end)");
160         }
161
162         return new CameraCharacteristics(m);
163     }
164
165     private static void mapCharacteristicsFromInfo(CameraMetadataNative m, CameraInfo i) {
166         m.set(LENS_FACING, i.facing == CameraInfo.CAMERA_FACING_BACK ?
167                 LENS_FACING_BACK : LENS_FACING_FRONT);
168         m.set(SENSOR_ORIENTATION, i.orientation);
169     }
170
171     private static void mapCharacteristicsFromParameters(CameraMetadataNative m,
172             Camera.Parameters p) {
173
174         /*
175          * colorCorrection.*
176          */
177         m.set(COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES,
178                 new int[] { COLOR_CORRECTION_ABERRATION_MODE_FAST });
179         /*
180          * control.ae*
181          */
182         mapControlAe(m, p);
183         /*
184          * control.af*
185          */
186         mapControlAf(m, p);
187         /*
188          * control.awb*
189          */
190         mapControlAwb(m, p);
191         /*
192          * control.*
193          * - Anything that doesn't have a set of related fields
194          */
195         mapControlOther(m, p);
196         /*
197          * lens.*
198          */
199         mapLens(m, p);
200         /*
201          * flash.*
202          */
203         mapFlash(m, p);
204         /*
205          * jpeg.*
206          */
207         mapJpeg(m, p);
208
209         /*
210          * noiseReduction.*
211          */
212         m.set(NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES,
213                 new int[] { NOISE_REDUCTION_MODE_FAST });
214
215         /*
216          * scaler.*
217          */
218         mapScaler(m, p);
219
220         /*
221          * sensor.*
222          */
223         mapSensor(m, p);
224
225         /*
226          * statistics.*
227          */
228         mapStatistics(m, p);
229
230         /*
231          * sync.*
232          */
233         mapSync(m, p);
234
235         /*
236          * info.supportedHardwareLevel
237          */
238         m.set(INFO_SUPPORTED_HARDWARE_LEVEL, INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY);
239
240         /*
241          * scaler.availableStream*, scaler.available*Durations, sensor.info.maxFrameDuration
242          */
243         mapScalerStreamConfigs(m, p);
244
245         // Order matters below: Put this last so that we can read the metadata set previously
246
247         /*
248          * request.*
249          */
250         mapRequest(m, p);
251
252     }
253
254     private static void mapScalerStreamConfigs(CameraMetadataNative m, Camera.Parameters p) {
255
256         ArrayList<StreamConfiguration> availableStreamConfigs = new ArrayList<>();
257         /*
258          * Implementation-defined (preview, recording, etc) -> use camera1 preview sizes
259          * YUV_420_888 cpu callbacks -> use camera1 preview sizes
260          * Other preview callbacks (CPU) -> use camera1 preview sizes
261          * JPEG still capture -> use camera1 still capture sizes
262          *
263          * Use platform-internal format constants here, since StreamConfigurationMap does the
264          * remapping to public format constants.
265          */
266         List<Camera.Size> previewSizes = p.getSupportedPreviewSizes();
267         List<Camera.Size> jpegSizes = p.getSupportedPictureSizes();
268         /*
269          * Work-around for b/17589233:
270          * - Some HALs's largest preview size aspect ratio does not match the largest JPEG size AR
271          * - This causes a large amount of problems with focus/metering because it's relative to
272          *   preview, making the difference between the JPEG and preview viewport inaccessible
273          * - This boils down to metering or focusing areas being "arbitrarily" cropped
274          *   in the capture result.
275          * - Work-around the HAL limitations by removing all of the largest preview sizes
276          *   until we get one with the same aspect ratio as the jpeg size.
277          */
278         {
279             SizeAreaComparator areaComparator = new SizeAreaComparator();
280
281             // Sort preview to min->max
282             Collections.sort(previewSizes, areaComparator);
283
284             Camera.Size maxJpegSize = SizeAreaComparator.findLargestByArea(jpegSizes);
285             float jpegAspectRatio = maxJpegSize.width * 1.0f / maxJpegSize.height;
286
287             if (DEBUG) {
288                 Log.v(TAG, String.format("mapScalerStreamConfigs - largest JPEG area %dx%d, AR=%f",
289                         maxJpegSize.width, maxJpegSize.height, jpegAspectRatio));
290             }
291
292             // Now remove preview sizes from the end (largest->smallest) until aspect ratio matches
293             while (!previewSizes.isEmpty()) {
294                 int index = previewSizes.size() - 1; // max is always at the end
295                 Camera.Size size = previewSizes.get(index);
296
297                 float previewAspectRatio = size.width * 1.0f / size.height;
298
299                 if (Math.abs(jpegAspectRatio - previewAspectRatio) >=
300                         PREVIEW_ASPECT_RATIO_TOLERANCE) {
301                     previewSizes.remove(index); // Assume removing from end is O(1)
302
303                     if (DEBUG) {
304                         Log.v(TAG, String.format(
305                                 "mapScalerStreamConfigs - removed preview size %dx%d, AR=%f "
306                                         + "was not the same",
307                                 size.width, size.height, previewAspectRatio));
308                     }
309                 } else {
310                     break;
311                 }
312             }
313
314             if (previewSizes.isEmpty()) {
315                 // Fall-back to the original faulty behavior, but at least work
316                 Log.w(TAG, "mapScalerStreamConfigs - failed to find any preview size matching " +
317                         "JPEG aspect ratio " + jpegAspectRatio);
318                 previewSizes = p.getSupportedPreviewSizes();
319             }
320
321             // Sort again, this time in descending order max->min
322             Collections.sort(previewSizes, Collections.reverseOrder(areaComparator));
323         }
324
325         appendStreamConfig(availableStreamConfigs,
326                 HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, previewSizes);
327         appendStreamConfig(availableStreamConfigs,
328                 ImageFormat.YUV_420_888, previewSizes);
329         for (int format : p.getSupportedPreviewFormats()) {
330             if (ImageFormat.isPublicFormat(format) && format != ImageFormat.NV21) {
331                 appendStreamConfig(availableStreamConfigs, format, previewSizes);
332             } else if (DEBUG) {
333                 /*
334                  *  Do not add any formats unknown to us
335                  * (since it would fail runtime checks in StreamConfigurationMap)
336                  */
337                 Log.v(TAG,
338                         String.format("mapStreamConfigs - Skipping format %x", format));
339             }
340         }
341
342         appendStreamConfig(availableStreamConfigs,
343                 HAL_PIXEL_FORMAT_BLOB, p.getSupportedPictureSizes());
344         /*
345          * scaler.availableStreamConfigurations
346          */
347         m.set(SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
348                 availableStreamConfigs.toArray(new StreamConfiguration[0]));
349
350         /*
351          * scaler.availableMinFrameDurations
352          */
353         // No frame durations available
354         m.set(SCALER_AVAILABLE_MIN_FRAME_DURATIONS, new StreamConfigurationDuration[0]);
355
356         StreamConfigurationDuration[] jpegStalls =
357                 new StreamConfigurationDuration[jpegSizes.size()];
358         int i = 0;
359         long longestStallDuration = -1;
360         for (Camera.Size s : jpegSizes) {
361             long stallDuration =  calculateJpegStallDuration(s);
362             jpegStalls[i++] = new StreamConfigurationDuration(HAL_PIXEL_FORMAT_BLOB, s.width,
363                     s.height, stallDuration);
364             if (longestStallDuration < stallDuration) {
365                 longestStallDuration = stallDuration;
366             }
367         }
368         /*
369          * scaler.availableStallDurations
370          */
371         // Set stall durations for jpeg, other formats use default stall duration
372         m.set(SCALER_AVAILABLE_STALL_DURATIONS, jpegStalls);
373
374         /*
375          * sensor.info.maxFrameDuration
376          */
377         m.set(SENSOR_INFO_MAX_FRAME_DURATION, longestStallDuration);
378     }
379
380     @SuppressWarnings({"unchecked"})
381     private static void mapControlAe(CameraMetadataNative m, Camera.Parameters p) {
382         /*
383          * control.aeAvailableAntiBandingModes
384          */
385         List<String> antiBandingModes = p.getSupportedAntibanding();
386         if (antiBandingModes != null && antiBandingModes.size() > 0) { // antibanding is optional
387             int[] modes = new int[antiBandingModes.size()];
388             int j = 0;
389             for (String mode : antiBandingModes) {
390                 int convertedMode = convertAntiBandingMode(mode);
391                 if (DEBUG && convertedMode == -1) {
392                     Log.v(TAG, "Antibanding mode " + ((mode == null) ? "NULL" : mode) +
393                             " not supported, skipping...");
394                 } else {
395                     modes[j++] = convertedMode;
396                 }
397             }
398             m.set(CONTROL_AE_AVAILABLE_ANTIBANDING_MODES, Arrays.copyOf(modes, j));
399         } else {
400             m.set(CONTROL_AE_AVAILABLE_ANTIBANDING_MODES, new int[0]);
401         }
402
403         /*
404          * control.aeAvailableTargetFpsRanges
405          */
406         {
407             List<int[]> fpsRanges = p.getSupportedPreviewFpsRange();
408             if (fpsRanges == null) {
409                 throw new AssertionError("Supported FPS ranges cannot be null.");
410             }
411             int rangesSize = fpsRanges.size();
412             if (rangesSize <= 0) {
413                 throw new AssertionError("At least one FPS range must be supported.");
414             }
415             Range<Integer>[] ranges = new Range[rangesSize];
416             int i = 0;
417             for (int[] r : fpsRanges) {
418                 ranges[i++] = Range.create(
419                         (int) Math.floor(r[Camera.Parameters.PREVIEW_FPS_MIN_INDEX] / 1000.0),
420                         (int) Math.ceil(r[Camera.Parameters.PREVIEW_FPS_MAX_INDEX] / 1000.0));
421             }
422             m.set(CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES, ranges);
423         }
424
425         /*
426          * control.aeAvailableModes
427          */
428         {
429             List<String> flashModes = p.getSupportedFlashModes();
430
431             String[] flashModeStrings = new String[] {
432                     Camera.Parameters.FLASH_MODE_OFF,
433                     Camera.Parameters.FLASH_MODE_AUTO,
434                     Camera.Parameters.FLASH_MODE_ON,
435                     Camera.Parameters.FLASH_MODE_RED_EYE,
436                     // Map these manually
437                     Camera.Parameters.FLASH_MODE_TORCH,
438             };
439             int[] flashModeInts = new int[] {
440                     CONTROL_AE_MODE_ON,
441                     CONTROL_AE_MODE_ON_AUTO_FLASH,
442                     CONTROL_AE_MODE_ON_ALWAYS_FLASH,
443                     CONTROL_AE_MODE_ON_AUTO_FLASH_REDEYE
444             };
445             int[] aeAvail = ArrayUtils.convertStringListToIntArray(
446                     flashModes, flashModeStrings, flashModeInts);
447
448             // No flash control -> AE is always on
449             if (aeAvail == null || aeAvail.length == 0) {
450                 aeAvail = new int[] {
451                         CONTROL_AE_MODE_ON
452                 };
453             }
454
455             // Note that AE_MODE_OFF is never available.
456             m.set(CONTROL_AE_AVAILABLE_MODES, aeAvail);
457         }
458
459         /*
460          * control.aeCompensationRanges
461          */
462         {
463             int min = p.getMinExposureCompensation();
464             int max = p.getMaxExposureCompensation();
465
466             m.set(CONTROL_AE_COMPENSATION_RANGE, Range.create(min, max));
467         }
468
469         /*
470          * control.aeCompensationStep
471          */
472         {
473             float step = p.getExposureCompensationStep();
474
475             m.set(CONTROL_AE_COMPENSATION_STEP, ParamsUtils.createRational(step));
476         }
477
478         /*
479          * control.aeLockAvailable
480          */
481         {
482             boolean aeLockAvailable = p.isAutoExposureLockSupported();
483
484             m.set(CONTROL_AE_LOCK_AVAILABLE, aeLockAvailable);
485         }
486     }
487
488
489     @SuppressWarnings({"unchecked"})
490     private static void mapControlAf(CameraMetadataNative m, Camera.Parameters p) {
491         /*
492          * control.afAvailableModes
493          */
494         {
495             List<String> focusModes = p.getSupportedFocusModes();
496
497             String[] focusModeStrings = new String[] {
498                     Camera.Parameters.FOCUS_MODE_AUTO,
499                     Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE,
500                     Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO,
501                     Camera.Parameters.FOCUS_MODE_EDOF,
502                     Camera.Parameters.FOCUS_MODE_INFINITY,
503                     Camera.Parameters.FOCUS_MODE_MACRO,
504                     Camera.Parameters.FOCUS_MODE_FIXED,
505             };
506
507             int[] focusModeInts = new int[] {
508                     CONTROL_AF_MODE_AUTO,
509                     CONTROL_AF_MODE_CONTINUOUS_PICTURE,
510                     CONTROL_AF_MODE_CONTINUOUS_VIDEO,
511                     CONTROL_AF_MODE_EDOF,
512                     CONTROL_AF_MODE_OFF,
513                     CONTROL_AF_MODE_MACRO,
514                     CONTROL_AF_MODE_OFF
515             };
516
517             List<Integer> afAvail = ArrayUtils.convertStringListToIntList(
518                     focusModes, focusModeStrings, focusModeInts);
519
520             // No AF modes supported? That's unpossible!
521             if (afAvail == null || afAvail.size() == 0) {
522                 Log.w(TAG, "No AF modes supported (HAL bug); defaulting to AF_MODE_OFF only");
523                 afAvail = new ArrayList<Integer>(/*capacity*/1);
524                 afAvail.add(CONTROL_AF_MODE_OFF);
525             }
526
527             m.set(CONTROL_AF_AVAILABLE_MODES, ArrayUtils.toIntArray(afAvail));
528
529             if (DEBUG) {
530                 Log.v(TAG, "mapControlAf - control.afAvailableModes set to " +
531                         ListUtils.listToString(afAvail));
532             }
533         }
534     }
535
536     private static void mapControlAwb(CameraMetadataNative m, Camera.Parameters p) {
537         /*
538          * control.awbAvailableModes
539          */
540
541         {
542             List<String> wbModes = p.getSupportedWhiteBalance();
543
544             String[] wbModeStrings = new String[] {
545                     Camera.Parameters.WHITE_BALANCE_AUTO                    ,
546                     Camera.Parameters.WHITE_BALANCE_INCANDESCENT            ,
547                     Camera.Parameters.WHITE_BALANCE_FLUORESCENT             ,
548                     Camera.Parameters.WHITE_BALANCE_WARM_FLUORESCENT        ,
549                     Camera.Parameters.WHITE_BALANCE_DAYLIGHT                ,
550                     Camera.Parameters.WHITE_BALANCE_CLOUDY_DAYLIGHT         ,
551                     Camera.Parameters.WHITE_BALANCE_TWILIGHT                ,
552                     Camera.Parameters.WHITE_BALANCE_SHADE                   ,
553             };
554
555             int[] wbModeInts = new int[] {
556                     CONTROL_AWB_MODE_AUTO,
557                     CONTROL_AWB_MODE_INCANDESCENT            ,
558                     CONTROL_AWB_MODE_FLUORESCENT             ,
559                     CONTROL_AWB_MODE_WARM_FLUORESCENT        ,
560                     CONTROL_AWB_MODE_DAYLIGHT                ,
561                     CONTROL_AWB_MODE_CLOUDY_DAYLIGHT         ,
562                     CONTROL_AWB_MODE_TWILIGHT                ,
563                     CONTROL_AWB_MODE_SHADE                   ,
564                     // Note that CONTROL_AWB_MODE_OFF is unsupported
565             };
566
567             List<Integer> awbAvail = ArrayUtils.convertStringListToIntList(
568                         wbModes, wbModeStrings, wbModeInts);
569
570             // No AWB modes supported? That's unpossible!
571             if (awbAvail == null || awbAvail.size() == 0) {
572                 Log.w(TAG, "No AWB modes supported (HAL bug); defaulting to AWB_MODE_AUTO only");
573                 awbAvail = new ArrayList<Integer>(/*capacity*/1);
574                 awbAvail.add(CONTROL_AWB_MODE_AUTO);
575             }
576
577             m.set(CONTROL_AWB_AVAILABLE_MODES, ArrayUtils.toIntArray(awbAvail));
578
579             if (DEBUG) {
580                 Log.v(TAG, "mapControlAwb - control.awbAvailableModes set to " +
581                         ListUtils.listToString(awbAvail));
582             }
583
584
585             /*
586              * control.awbLockAvailable
587              */
588             {
589                 boolean awbLockAvailable = p.isAutoWhiteBalanceLockSupported();
590
591                 m.set(CONTROL_AWB_LOCK_AVAILABLE, awbLockAvailable);
592             }
593         }
594     }
595
596     private static void mapControlOther(CameraMetadataNative m, Camera.Parameters p) {
597         /*
598          * android.control.availableVideoStabilizationModes
599          */
600         {
601             int stabModes[] = p.isVideoStabilizationSupported() ?
602                     new int[] { CONTROL_VIDEO_STABILIZATION_MODE_OFF,
603                                 CONTROL_VIDEO_STABILIZATION_MODE_ON } :
604                     new int[] { CONTROL_VIDEO_STABILIZATION_MODE_OFF };
605
606             m.set(CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES, stabModes);
607         }
608
609         /*
610          * android.control.maxRegions
611          */
612         final int AE = 0, AWB = 1, AF = 2;
613
614         int[] maxRegions = new int[3];
615         maxRegions[AE] = p.getMaxNumMeteringAreas();
616         maxRegions[AWB] = 0; // AWB regions not supported in API1
617         maxRegions[AF] = p.getMaxNumFocusAreas();
618
619         if (LIE_ABOUT_AE_MAX_REGIONS) {
620             maxRegions[AE] = 0;
621         }
622         if (LIE_ABOUT_AF_MAX_REGIONS) {
623             maxRegions[AF] = 0;
624         }
625
626         m.set(CONTROL_MAX_REGIONS, maxRegions);
627
628         /*
629          * android.control.availableEffects
630          */
631         List<String> effectModes = p.getSupportedColorEffects();
632         int[] supportedEffectModes = (effectModes == null) ? new int[0] :
633                 ArrayUtils.convertStringListToIntArray(effectModes, sLegacyEffectMode,
634                         sEffectModes);
635         m.set(CONTROL_AVAILABLE_EFFECTS, supportedEffectModes);
636
637         /*
638          * android.control.availableSceneModes
639          */
640         int maxNumDetectedFaces = p.getMaxNumDetectedFaces();
641         List<String> sceneModes = p.getSupportedSceneModes();
642         List<Integer> supportedSceneModes =
643                 ArrayUtils.convertStringListToIntList(sceneModes, sLegacySceneModes, sSceneModes);
644
645         // Special case where the only scene mode listed is AUTO => no scene mode
646         if (sceneModes != null && sceneModes.size() == 1 &&
647                 sceneModes.get(0) == Parameters.SCENE_MODE_AUTO) {
648             supportedSceneModes = null;
649         }
650
651         boolean sceneModeSupported = true;
652         if (supportedSceneModes == null && maxNumDetectedFaces == 0) {
653             sceneModeSupported = false;
654         }
655
656         if (sceneModeSupported) {
657             if (supportedSceneModes == null) {
658                 supportedSceneModes = new ArrayList<Integer>();
659             }
660             if (maxNumDetectedFaces > 0) { // always supports FACE_PRIORITY when face detecting
661                 supportedSceneModes.add(CONTROL_SCENE_MODE_FACE_PRIORITY);
662             }
663             // Remove all DISABLED occurrences
664             if (supportedSceneModes.contains(CONTROL_SCENE_MODE_DISABLED)) {
665                 while(supportedSceneModes.remove(new Integer(CONTROL_SCENE_MODE_DISABLED))) {}
666             }
667             m.set(CONTROL_AVAILABLE_SCENE_MODES, ArrayUtils.toIntArray(supportedSceneModes));
668         } else {
669             m.set(CONTROL_AVAILABLE_SCENE_MODES, new int[] {CONTROL_SCENE_MODE_DISABLED});
670         }
671
672         /*
673          * android.control.availableModes
674          */
675         m.set(CONTROL_AVAILABLE_MODES, sceneModeSupported ?
676                 new int[] { CONTROL_MODE_AUTO, CONTROL_MODE_USE_SCENE_MODE } :
677                 new int[] { CONTROL_MODE_AUTO });
678     }
679
680     private static void mapLens(CameraMetadataNative m, Camera.Parameters p) {
681         /*
682          *  We can tell if the lens is fixed focus;
683          *  but if it's not, we can't tell the minimum focus distance, so leave it null then.
684          */
685         if (DEBUG) {
686             Log.v(TAG, "mapLens - focus-mode='" + p.getFocusMode() + "'");
687         }
688
689         if (Camera.Parameters.FOCUS_MODE_FIXED.equals(p.getFocusMode())) {
690             /*
691              * lens.info.minimumFocusDistance
692              */
693             m.set(LENS_INFO_MINIMUM_FOCUS_DISTANCE, LENS_INFO_MINIMUM_FOCUS_DISTANCE_FIXED_FOCUS);
694
695             if (DEBUG) {
696                 Log.v(TAG, "mapLens - lens.info.minimumFocusDistance = 0");
697             }
698         } else {
699             if (DEBUG) {
700                 Log.v(TAG, "mapLens - lens.info.minimumFocusDistance is unknown");
701             }
702         }
703
704         float[] focalLengths = new float[] { p.getFocalLength() };
705         m.set(LENS_INFO_AVAILABLE_FOCAL_LENGTHS, focalLengths);
706     }
707
708     private static void mapFlash(CameraMetadataNative m, Camera.Parameters p) {
709         boolean flashAvailable = false;
710         List<String> supportedFlashModes = p.getSupportedFlashModes();
711
712         if (supportedFlashModes != null) {
713             // If only 'OFF' is available, we don't really have flash support
714             flashAvailable = !ListUtils.listElementsEqualTo(
715                     supportedFlashModes, Camera.Parameters.FLASH_MODE_OFF);
716         }
717
718         /*
719          * flash.info.available
720          */
721         m.set(FLASH_INFO_AVAILABLE, flashAvailable);
722     }
723
724     private static void mapJpeg(CameraMetadataNative m, Camera.Parameters p) {
725         List<Camera.Size> thumbnailSizes = p.getSupportedJpegThumbnailSizes();
726
727         if (thumbnailSizes != null) {
728             Size[] sizes = convertSizeListToArray(thumbnailSizes);
729             Arrays.sort(sizes, new android.hardware.camera2.utils.SizeAreaComparator());
730             m.set(JPEG_AVAILABLE_THUMBNAIL_SIZES, sizes);
731         }
732     }
733
734     private static void mapRequest(CameraMetadataNative m, Parameters p) {
735         /*
736          * request.availableCapabilities
737          */
738         int[] capabilities = { REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE };
739         m.set(REQUEST_AVAILABLE_CAPABILITIES, capabilities);
740
741         /*
742          * request.availableCharacteristicsKeys
743          */
744         {
745             // TODO: check if the underlying key is supported before listing a key as available
746
747             // Note: We only list public keys. Native HALs should list ALL keys regardless of visibility.
748
749             Key<?> availableKeys[] = new Key<?>[] {
750                     CameraCharacteristics.COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES     ,
751                     CameraCharacteristics.CONTROL_AE_AVAILABLE_ANTIBANDING_MODES          ,
752                     CameraCharacteristics.CONTROL_AE_AVAILABLE_MODES                      ,
753                     CameraCharacteristics.CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES          ,
754                     CameraCharacteristics.CONTROL_AE_COMPENSATION_RANGE                   ,
755                     CameraCharacteristics.CONTROL_AE_COMPENSATION_STEP                    ,
756                     CameraCharacteristics.CONTROL_AE_LOCK_AVAILABLE                       ,
757                     CameraCharacteristics.CONTROL_AF_AVAILABLE_MODES                      ,
758                     CameraCharacteristics.CONTROL_AVAILABLE_EFFECTS                       ,
759                     CameraCharacteristics.CONTROL_AVAILABLE_MODES                         ,
760                     CameraCharacteristics.CONTROL_AVAILABLE_SCENE_MODES                   ,
761                     CameraCharacteristics.CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES     ,
762                     CameraCharacteristics.CONTROL_AWB_AVAILABLE_MODES                     ,
763                     CameraCharacteristics.CONTROL_AWB_LOCK_AVAILABLE                      ,
764                     CameraCharacteristics.CONTROL_MAX_REGIONS                             ,
765                     CameraCharacteristics.FLASH_INFO_AVAILABLE                            ,
766                     CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL                   ,
767                     CameraCharacteristics.JPEG_AVAILABLE_THUMBNAIL_SIZES                  ,
768                     CameraCharacteristics.LENS_FACING                                     ,
769                     CameraCharacteristics.LENS_INFO_AVAILABLE_FOCAL_LENGTHS               ,
770                     CameraCharacteristics.NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES ,
771                     CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES                  ,
772                     CameraCharacteristics.REQUEST_MAX_NUM_OUTPUT_STREAMS                  ,
773                     CameraCharacteristics.REQUEST_PARTIAL_RESULT_COUNT                    ,
774                     CameraCharacteristics.REQUEST_PIPELINE_MAX_DEPTH                      ,
775                     CameraCharacteristics.SCALER_AVAILABLE_MAX_DIGITAL_ZOOM               ,
776 //                    CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP                 ,
777                     CameraCharacteristics.SCALER_CROPPING_TYPE                            ,
778                     CameraCharacteristics.SENSOR_AVAILABLE_TEST_PATTERN_MODES             ,
779                     CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE                   ,
780                     CameraCharacteristics.SENSOR_INFO_PHYSICAL_SIZE                       ,
781                     CameraCharacteristics.SENSOR_INFO_PIXEL_ARRAY_SIZE                    ,
782                     CameraCharacteristics.SENSOR_INFO_TIMESTAMP_SOURCE                    ,
783                     CameraCharacteristics.SENSOR_ORIENTATION                              ,
784                     CameraCharacteristics.STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES     ,
785                     CameraCharacteristics.STATISTICS_INFO_MAX_FACE_COUNT                  ,
786                     CameraCharacteristics.SYNC_MAX_LATENCY                                ,
787             };
788             List<Key<?>> characteristicsKeys = new ArrayList<>(Arrays.asList(availableKeys));
789
790             /*
791              * Add the conditional keys
792              */
793             if (m.get(LENS_INFO_MINIMUM_FOCUS_DISTANCE) != null) {
794                 characteristicsKeys.add(LENS_INFO_MINIMUM_FOCUS_DISTANCE);
795             }
796
797             m.set(REQUEST_AVAILABLE_CHARACTERISTICS_KEYS,
798                     getTagsForKeys(characteristicsKeys.toArray(new Key<?>[0])));
799         }
800
801         /*
802          * request.availableRequestKeys
803          */
804         {
805             CaptureRequest.Key<?> defaultAvailableKeys[] = new CaptureRequest.Key<?>[] {
806                     CaptureRequest.COLOR_CORRECTION_ABERRATION_MODE,
807                     CaptureRequest.CONTROL_AE_ANTIBANDING_MODE,
808                     CaptureRequest.CONTROL_AE_EXPOSURE_COMPENSATION,
809                     CaptureRequest.CONTROL_AE_LOCK,
810                     CaptureRequest.CONTROL_AE_MODE,
811                     CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE,
812                     CaptureRequest.CONTROL_AF_MODE,
813                     CaptureRequest.CONTROL_AF_TRIGGER,
814                     CaptureRequest.CONTROL_AWB_LOCK,
815                     CaptureRequest.CONTROL_AWB_MODE,
816                     CaptureRequest.CONTROL_CAPTURE_INTENT,
817                     CaptureRequest.CONTROL_EFFECT_MODE,
818                     CaptureRequest.CONTROL_MODE,
819                     CaptureRequest.CONTROL_SCENE_MODE,
820                     CaptureRequest.CONTROL_VIDEO_STABILIZATION_MODE,
821                     CaptureRequest.FLASH_MODE,
822                     CaptureRequest.JPEG_GPS_COORDINATES,
823                     CaptureRequest.JPEG_GPS_PROCESSING_METHOD,
824                     CaptureRequest.JPEG_GPS_TIMESTAMP,
825                     CaptureRequest.JPEG_ORIENTATION,
826                     CaptureRequest.JPEG_QUALITY,
827                     CaptureRequest.JPEG_THUMBNAIL_QUALITY,
828                     CaptureRequest.JPEG_THUMBNAIL_SIZE,
829                     CaptureRequest.LENS_FOCAL_LENGTH,
830                     CaptureRequest.NOISE_REDUCTION_MODE,
831                     CaptureRequest.SCALER_CROP_REGION,
832                     CaptureRequest.STATISTICS_FACE_DETECT_MODE,
833             };
834             ArrayList<CaptureRequest.Key<?>> availableKeys =
835                     new ArrayList<CaptureRequest.Key<?>>(Arrays.asList(defaultAvailableKeys));
836
837             if (p.getMaxNumMeteringAreas() > 0) {
838                 availableKeys.add(CaptureRequest.CONTROL_AE_REGIONS);
839             }
840             if (p.getMaxNumFocusAreas() > 0) {
841                 availableKeys.add(CaptureRequest.CONTROL_AF_REGIONS);
842             }
843
844             CaptureRequest.Key<?> availableRequestKeys[] =
845                     new CaptureRequest.Key<?>[availableKeys.size()];
846             availableKeys.toArray(availableRequestKeys);
847             m.set(REQUEST_AVAILABLE_REQUEST_KEYS, getTagsForKeys(availableRequestKeys));
848         }
849
850         /*
851          * request.availableResultKeys
852          */
853         {
854             CaptureResult.Key<?> defaultAvailableKeys[] = new CaptureResult.Key<?>[] {
855                     CaptureResult.COLOR_CORRECTION_ABERRATION_MODE                 ,
856                     CaptureResult.CONTROL_AE_ANTIBANDING_MODE                      ,
857                     CaptureResult.CONTROL_AE_EXPOSURE_COMPENSATION                 ,
858                     CaptureResult.CONTROL_AE_LOCK                                  ,
859                     CaptureResult.CONTROL_AE_MODE                                  ,
860                     CaptureResult.CONTROL_AF_MODE                                  ,
861                     CaptureResult.CONTROL_AF_STATE                                 ,
862                     CaptureResult.CONTROL_AWB_MODE                                 ,
863                     CaptureResult.CONTROL_AWB_LOCK                                 ,
864                     CaptureResult.CONTROL_MODE                                     ,
865                     CaptureResult.FLASH_MODE                                       ,
866                     CaptureResult.JPEG_GPS_COORDINATES                             ,
867                     CaptureResult.JPEG_GPS_PROCESSING_METHOD                       ,
868                     CaptureResult.JPEG_GPS_TIMESTAMP                               ,
869                     CaptureResult.JPEG_ORIENTATION                                 ,
870                     CaptureResult.JPEG_QUALITY                                     ,
871                     CaptureResult.JPEG_THUMBNAIL_QUALITY                           ,
872                     CaptureResult.LENS_FOCAL_LENGTH                                ,
873                     CaptureResult.NOISE_REDUCTION_MODE                             ,
874                     CaptureResult.REQUEST_PIPELINE_DEPTH                           ,
875                     CaptureResult.SCALER_CROP_REGION                               ,
876                     CaptureResult.SENSOR_TIMESTAMP                                 ,
877                     CaptureResult.STATISTICS_FACE_DETECT_MODE                      ,
878 //                    CaptureResult.STATISTICS_FACES                                 ,
879             };
880             List<CaptureResult.Key<?>> availableKeys =
881                     new ArrayList<CaptureResult.Key<?>>(Arrays.asList(defaultAvailableKeys));
882
883             if (p.getMaxNumMeteringAreas() > 0) {
884                 availableKeys.add(CaptureResult.CONTROL_AE_REGIONS);
885             }
886             if (p.getMaxNumFocusAreas() > 0) {
887                 availableKeys.add(CaptureResult.CONTROL_AF_REGIONS);
888             }
889
890             CaptureResult.Key<?> availableResultKeys[] =
891                     new CaptureResult.Key<?>[availableKeys.size()];
892             availableKeys.toArray(availableResultKeys);
893             m.set(REQUEST_AVAILABLE_RESULT_KEYS, getTagsForKeys(availableResultKeys));
894         }
895
896         /*
897          * request.maxNumOutputStreams
898          */
899         int[] outputStreams = {
900                 /* RAW */
901                 REQUEST_MAX_NUM_OUTPUT_STREAMS_COUNT_RAW,
902                 /* Processed & Not-Stalling */
903                 REQUEST_MAX_NUM_OUTPUT_STREAMS_COUNT_PROC,
904                 /* Processed & Stalling */
905                 REQUEST_MAX_NUM_OUTPUT_STREAMS_COUNT_PROC_STALL,
906         };
907         m.set(REQUEST_MAX_NUM_OUTPUT_STREAMS, outputStreams);
908
909         /*
910          * request.maxNumInputStreams
911          */
912         m.set(REQUEST_MAX_NUM_INPUT_STREAMS, REQUEST_MAX_NUM_INPUT_STREAMS_COUNT);
913
914         /*
915          * request.partialResultCount
916          */
917         m.set(REQUEST_PARTIAL_RESULT_COUNT, 1); // No partial results supported
918
919         /*
920          * request.pipelineMaxDepth
921          */
922         m.set(REQUEST_PIPELINE_MAX_DEPTH,
923                 (byte)(REQUEST_PIPELINE_MAX_DEPTH_HAL1 + REQUEST_PIPELINE_MAX_DEPTH_OURS));
924     }
925
926     private static void mapScaler(CameraMetadataNative m, Parameters p) {
927         /*
928          * scaler.availableMaxDigitalZoom
929          */
930         m.set(SCALER_AVAILABLE_MAX_DIGITAL_ZOOM, ParameterUtils.getMaxZoomRatio(p));
931
932         /*
933          * scaler.croppingType = CENTER_ONLY
934          */
935         m.set(SCALER_CROPPING_TYPE, SCALER_CROPPING_TYPE_CENTER_ONLY);
936     }
937
938     private static void mapSensor(CameraMetadataNative m, Parameters p) {
939         // Use the largest jpeg size (by area) for both active array and pixel array
940         Size largestJpegSize = getLargestSupportedJpegSizeByArea(p);
941         /*
942          * sensor.info.activeArraySize
943          */
944         {
945             Rect activeArrayRect = ParamsUtils.createRect(largestJpegSize);
946             m.set(SENSOR_INFO_ACTIVE_ARRAY_SIZE, activeArrayRect);
947         }
948
949         /*
950          * sensor.availableTestPatternModes
951          */
952         {
953             // Only "OFF" test pattern mode is available
954             m.set(SENSOR_AVAILABLE_TEST_PATTERN_MODES, new int[] { SENSOR_TEST_PATTERN_MODE_OFF });
955         }
956
957         /*
958          * sensor.info.pixelArraySize
959          */
960         m.set(SENSOR_INFO_PIXEL_ARRAY_SIZE, largestJpegSize);
961
962         /*
963          * sensor.info.physicalSize
964          */
965         {
966             /*
967              * Assume focal length is at infinity focus and that the lens is rectilinear.
968              */
969             float focalLength = p.getFocalLength(); // in mm
970             double angleHor = p.getHorizontalViewAngle() * Math.PI / 180; // to radians
971             double angleVer = p.getVerticalViewAngle() * Math.PI / 180; // to radians
972
973             float height = (float)Math.abs(2 * focalLength * Math.tan(angleVer / 2));
974             float width = (float)Math.abs(2 * focalLength * Math.tan(angleHor / 2));
975
976             m.set(SENSOR_INFO_PHYSICAL_SIZE, new SizeF(width, height)); // in mm
977         }
978
979         /*
980          * sensor.info.timestampSource
981          */
982         {
983             m.set(SENSOR_INFO_TIMESTAMP_SOURCE, SENSOR_INFO_TIMESTAMP_SOURCE_UNKNOWN);
984         }
985     }
986
987     private static void mapStatistics(CameraMetadataNative m, Parameters p) {
988         /*
989          * statistics.info.availableFaceDetectModes
990          */
991         int[] fdModes;
992
993         if (p.getMaxNumDetectedFaces() > 0) {
994             fdModes = new int[] {
995                 STATISTICS_FACE_DETECT_MODE_OFF,
996                 STATISTICS_FACE_DETECT_MODE_SIMPLE
997                 // FULL is never-listed, since we have no way to query it statically
998             };
999         } else {
1000             fdModes = new int[] {
1001                 STATISTICS_FACE_DETECT_MODE_OFF
1002             };
1003         }
1004         m.set(STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES, fdModes);
1005
1006         /*
1007          * statistics.info.maxFaceCount
1008          */
1009         m.set(STATISTICS_INFO_MAX_FACE_COUNT, p.getMaxNumDetectedFaces());
1010     }
1011
1012     private static void mapSync(CameraMetadataNative m, Parameters p) {
1013         /*
1014          * sync.maxLatency
1015          */
1016         m.set(SYNC_MAX_LATENCY, SYNC_MAX_LATENCY_UNKNOWN);
1017     }
1018
1019     private static void appendStreamConfig(
1020             ArrayList<StreamConfiguration> configs, int format, List<Camera.Size> sizes) {
1021         for (Camera.Size size : sizes) {
1022             StreamConfiguration config =
1023                     new StreamConfiguration(format, size.width, size.height, /*input*/false);
1024             configs.add(config);
1025         }
1026     }
1027
1028     private final static String[] sLegacySceneModes = {
1029         Parameters.SCENE_MODE_AUTO,
1030         Parameters.SCENE_MODE_ACTION,
1031         Parameters.SCENE_MODE_PORTRAIT,
1032         Parameters.SCENE_MODE_LANDSCAPE,
1033         Parameters.SCENE_MODE_NIGHT,
1034         Parameters.SCENE_MODE_NIGHT_PORTRAIT,
1035         Parameters.SCENE_MODE_THEATRE,
1036         Parameters.SCENE_MODE_BEACH,
1037         Parameters.SCENE_MODE_SNOW,
1038         Parameters.SCENE_MODE_SUNSET,
1039         Parameters.SCENE_MODE_STEADYPHOTO,
1040         Parameters.SCENE_MODE_FIREWORKS,
1041         Parameters.SCENE_MODE_SPORTS,
1042         Parameters.SCENE_MODE_PARTY,
1043         Parameters.SCENE_MODE_CANDLELIGHT,
1044         Parameters.SCENE_MODE_BARCODE,
1045         Parameters.SCENE_MODE_HDR,
1046     };
1047
1048     private final static int[] sSceneModes = {
1049         CameraCharacteristics.CONTROL_SCENE_MODE_DISABLED,
1050         CameraCharacteristics.CONTROL_SCENE_MODE_ACTION,
1051         CameraCharacteristics.CONTROL_SCENE_MODE_PORTRAIT,
1052         CameraCharacteristics.CONTROL_SCENE_MODE_LANDSCAPE,
1053         CameraCharacteristics.CONTROL_SCENE_MODE_NIGHT,
1054         CameraCharacteristics.CONTROL_SCENE_MODE_NIGHT_PORTRAIT,
1055         CameraCharacteristics.CONTROL_SCENE_MODE_THEATRE,
1056         CameraCharacteristics.CONTROL_SCENE_MODE_BEACH,
1057         CameraCharacteristics.CONTROL_SCENE_MODE_SNOW,
1058         CameraCharacteristics.CONTROL_SCENE_MODE_SUNSET,
1059         CameraCharacteristics.CONTROL_SCENE_MODE_STEADYPHOTO,
1060         CameraCharacteristics.CONTROL_SCENE_MODE_FIREWORKS,
1061         CameraCharacteristics.CONTROL_SCENE_MODE_SPORTS,
1062         CameraCharacteristics.CONTROL_SCENE_MODE_PARTY,
1063         CameraCharacteristics.CONTROL_SCENE_MODE_CANDLELIGHT,
1064         CameraCharacteristics.CONTROL_SCENE_MODE_BARCODE,
1065         CameraCharacteristics.CONTROL_SCENE_MODE_HDR,
1066     };
1067
1068     static int convertSceneModeFromLegacy(String mode) {
1069         if (mode == null) {
1070             return CameraCharacteristics.CONTROL_SCENE_MODE_DISABLED;
1071         }
1072         int index = ArrayUtils.getArrayIndex(sLegacySceneModes, mode);
1073         if (index < 0) {
1074             return UNKNOWN_MODE;
1075         }
1076         return sSceneModes[index];
1077     }
1078
1079     static String convertSceneModeToLegacy(int mode) {
1080         if (mode == CONTROL_SCENE_MODE_FACE_PRIORITY) {
1081             // OK: Let LegacyFaceDetectMapper handle turning face detection on/off
1082             return Parameters.SCENE_MODE_AUTO;
1083         }
1084
1085         int index = ArrayUtils.getArrayIndex(sSceneModes, mode);
1086         if (index < 0) {
1087             return null;
1088         }
1089         return sLegacySceneModes[index];
1090     }
1091
1092     private final static String[] sLegacyEffectMode = {
1093         Parameters.EFFECT_NONE,
1094         Parameters.EFFECT_MONO,
1095         Parameters.EFFECT_NEGATIVE,
1096         Parameters.EFFECT_SOLARIZE,
1097         Parameters.EFFECT_SEPIA,
1098         Parameters.EFFECT_POSTERIZE,
1099         Parameters.EFFECT_WHITEBOARD,
1100         Parameters.EFFECT_BLACKBOARD,
1101         Parameters.EFFECT_AQUA,
1102     };
1103
1104     private final static int[] sEffectModes = {
1105         CameraCharacteristics.CONTROL_EFFECT_MODE_OFF,
1106         CameraCharacteristics.CONTROL_EFFECT_MODE_MONO,
1107         CameraCharacteristics.CONTROL_EFFECT_MODE_NEGATIVE,
1108         CameraCharacteristics.CONTROL_EFFECT_MODE_SOLARIZE,
1109         CameraCharacteristics.CONTROL_EFFECT_MODE_SEPIA,
1110         CameraCharacteristics.CONTROL_EFFECT_MODE_POSTERIZE,
1111         CameraCharacteristics.CONTROL_EFFECT_MODE_WHITEBOARD,
1112         CameraCharacteristics.CONTROL_EFFECT_MODE_BLACKBOARD,
1113         CameraCharacteristics.CONTROL_EFFECT_MODE_AQUA,
1114     };
1115
1116     static int convertEffectModeFromLegacy(String mode) {
1117         if (mode == null) {
1118             return CameraCharacteristics.CONTROL_EFFECT_MODE_OFF;
1119         }
1120         int index = ArrayUtils.getArrayIndex(sLegacyEffectMode, mode);
1121         if (index < 0) {
1122             return UNKNOWN_MODE;
1123         }
1124         return sEffectModes[index];
1125     }
1126
1127     static String convertEffectModeToLegacy(int mode) {
1128         int index = ArrayUtils.getArrayIndex(sEffectModes, mode);
1129         if (index < 0) {
1130             return null;
1131         }
1132         return sLegacyEffectMode[index];
1133     }
1134
1135     /**
1136      * Convert the ae antibanding mode from api1 into api2.
1137      *
1138      * @param mode the api1 mode, {@code null} is allowed and will return {@code -1}.
1139      *
1140      * @return The api2 value, or {@code -1} by default if conversion failed
1141      */
1142     private static int convertAntiBandingMode(String mode) {
1143         if (mode == null) {
1144             return -1;
1145         }
1146
1147         switch (mode) {
1148             case Camera.Parameters.ANTIBANDING_OFF: {
1149                 return CONTROL_AE_ANTIBANDING_MODE_OFF;
1150             }
1151             case Camera.Parameters.ANTIBANDING_50HZ: {
1152                 return CONTROL_AE_ANTIBANDING_MODE_50HZ;
1153             }
1154             case Camera.Parameters.ANTIBANDING_60HZ: {
1155                 return CONTROL_AE_ANTIBANDING_MODE_60HZ;
1156             }
1157             case Camera.Parameters.ANTIBANDING_AUTO: {
1158                 return CONTROL_AE_ANTIBANDING_MODE_AUTO;
1159             }
1160             default: {
1161                 Log.w(TAG, "convertAntiBandingMode - Unknown antibanding mode " + mode);
1162                 return -1;
1163             }
1164         }
1165     }
1166
1167     /**
1168      * Convert the ae antibanding mode from api1 into api2.
1169      *
1170      * @param mode the api1 mode, {@code null} is allowed and will return {@code MODE_OFF}.
1171      *
1172      * @return The api2 value, or {@code MODE_OFF} by default if conversion failed
1173      */
1174     static int convertAntiBandingModeOrDefault(String mode) {
1175         int antiBandingMode = convertAntiBandingMode(mode);
1176         if (antiBandingMode == -1) {
1177             return CONTROL_AE_ANTIBANDING_MODE_OFF;
1178         }
1179
1180         return antiBandingMode;
1181     }
1182
1183     private static int[] convertAeFpsRangeToLegacy(Range<Integer> fpsRange) {
1184         int[] legacyFps = new int[2];
1185         legacyFps[Camera.Parameters.PREVIEW_FPS_MIN_INDEX] = fpsRange.getLower();
1186         legacyFps[Camera.Parameters.PREVIEW_FPS_MAX_INDEX] = fpsRange.getUpper();
1187         return legacyFps;
1188     }
1189
1190     /**
1191      * Return the stall duration for a given output jpeg size in nanoseconds.
1192      *
1193      * <p>An 8mp image is chosen to have a stall duration of 0.8 seconds.</p>
1194      */
1195     private static long calculateJpegStallDuration(Camera.Size size) {
1196         long baseDuration = APPROXIMATE_CAPTURE_DELAY_MS * NS_PER_MS; // 200ms for capture
1197         long area = size.width * (long) size.height;
1198         long stallPerArea = APPROXIMATE_JPEG_ENCODE_TIME_MS * NS_PER_MS /
1199                 APPROXIMATE_SENSOR_AREA_PX; // 600ms stall for 8mp
1200         return baseDuration + area * stallPerArea;
1201     }
1202
1203     /**
1204      * Set the legacy parameters using the {@link LegacyRequest legacy request}.
1205      *
1206      * <p>The legacy request's parameters are changed as a side effect of calling this
1207      * method.</p>
1208      *
1209      * @param request a non-{@code null} legacy request
1210      */
1211     public static void convertRequestMetadata(LegacyRequest request) {
1212         LegacyRequestMapper.convertRequestMetadata(request);
1213     }
1214
1215     private static final int[] sAllowedTemplates = {
1216             CameraDevice.TEMPLATE_PREVIEW,
1217             CameraDevice.TEMPLATE_STILL_CAPTURE,
1218             CameraDevice.TEMPLATE_RECORD,
1219             // Disallowed templates in legacy mode:
1220             // CameraDevice.TEMPLATE_VIDEO_SNAPSHOT,
1221             // CameraDevice.TEMPLATE_ZERO_SHUTTER_LAG,
1222             // CameraDevice.TEMPLATE_MANUAL
1223     };
1224
1225     /**
1226      * Create a request template
1227      *
1228      * @param c a non-{@code null} camera characteristics for this camera
1229      * @param templateId a non-negative template ID
1230      *
1231      * @return a non-{@code null} request template
1232      *
1233      * @throws IllegalArgumentException if {@code templateId} was invalid
1234      *
1235      * @see android.hardware.camera2.CameraDevice#TEMPLATE_MANUAL
1236      */
1237     public static CameraMetadataNative createRequestTemplate(
1238             CameraCharacteristics c, int templateId) {
1239         if (!ArrayUtils.contains(sAllowedTemplates, templateId)) {
1240             throw new IllegalArgumentException("templateId out of range");
1241         }
1242
1243         CameraMetadataNative m = new CameraMetadataNative();
1244
1245         /*
1246          * NOTE: If adding new code here and it needs to query the static info,
1247          * query the camera characteristics, so we can reuse this for api2 code later
1248          * to create our own templates in the framework
1249          */
1250
1251         /*
1252          * control.*
1253          */
1254
1255         // control.awbMode
1256         m.set(CaptureRequest.CONTROL_AWB_MODE, CameraMetadata.CONTROL_AWB_MODE_AUTO);
1257         // AWB is always unconditionally available in API1 devices
1258
1259         // control.aeAntibandingMode
1260         m.set(CaptureRequest.CONTROL_AE_ANTIBANDING_MODE, CONTROL_AE_ANTIBANDING_MODE_AUTO);
1261
1262         // control.aeExposureCompensation
1263         m.set(CaptureRequest.CONTROL_AE_EXPOSURE_COMPENSATION, 0);
1264
1265         // control.aeLock
1266         m.set(CaptureRequest.CONTROL_AE_LOCK, false);
1267
1268         // control.aePrecaptureTrigger
1269         m.set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER, CONTROL_AE_PRECAPTURE_TRIGGER_IDLE);
1270
1271         // control.afTrigger
1272         m.set(CaptureRequest.CONTROL_AF_TRIGGER, CONTROL_AF_TRIGGER_IDLE);
1273
1274         // control.awbMode
1275         m.set(CaptureRequest.CONTROL_AWB_MODE, CONTROL_AWB_MODE_AUTO);
1276
1277         // control.awbLock
1278         m.set(CaptureRequest.CONTROL_AWB_LOCK, false);
1279
1280         // control.aeRegions, control.awbRegions, control.afRegions
1281         {
1282             Rect activeArray = c.get(SENSOR_INFO_ACTIVE_ARRAY_SIZE);
1283             MeteringRectangle[] activeRegions =  new MeteringRectangle[] {
1284                     new MeteringRectangle(/*x*/0, /*y*/0, /*width*/activeArray.width() - 1,
1285                     /*height*/activeArray.height() - 1,/*weight*/0)};
1286             m.set(CaptureRequest.CONTROL_AE_REGIONS, activeRegions);
1287             m.set(CaptureRequest.CONTROL_AWB_REGIONS, activeRegions);
1288             m.set(CaptureRequest.CONTROL_AF_REGIONS, activeRegions);
1289         }
1290
1291         // control.captureIntent
1292         {
1293             int captureIntent;
1294             switch (templateId) {
1295                 case CameraDevice.TEMPLATE_PREVIEW:
1296                     captureIntent = CONTROL_CAPTURE_INTENT_PREVIEW;
1297                     break;
1298                 case CameraDevice.TEMPLATE_STILL_CAPTURE:
1299                     captureIntent = CONTROL_CAPTURE_INTENT_STILL_CAPTURE;
1300                     break;
1301                 case CameraDevice.TEMPLATE_RECORD:
1302                     captureIntent = CONTROL_CAPTURE_INTENT_VIDEO_RECORD;
1303                     break;
1304                 default:
1305                     // Can't get anything else since it's guarded by the IAE check
1306                     throw new AssertionError("Impossible; keep in sync with sAllowedTemplates");
1307             }
1308             m.set(CaptureRequest.CONTROL_CAPTURE_INTENT, captureIntent);
1309         }
1310
1311         // control.aeMode
1312         m.set(CaptureRequest.CONTROL_AE_MODE, CameraMetadata.CONTROL_AE_MODE_ON);
1313         // AE is always unconditionally available in API1 devices
1314
1315         // control.mode
1316         m.set(CaptureRequest.CONTROL_MODE, CONTROL_MODE_AUTO);
1317
1318         // control.afMode
1319         {
1320             Float minimumFocusDistance = c.get(LENS_INFO_MINIMUM_FOCUS_DISTANCE);
1321
1322             int afMode;
1323             if (minimumFocusDistance != null &&
1324                     minimumFocusDistance == LENS_INFO_MINIMUM_FOCUS_DISTANCE_FIXED_FOCUS) {
1325                 // Cannot control auto-focus with fixed-focus cameras
1326                 afMode = CameraMetadata.CONTROL_AF_MODE_OFF;
1327             } else {
1328                 // If a minimum focus distance is reported; the camera must have AF
1329                 afMode = CameraMetadata.CONTROL_AF_MODE_AUTO;
1330
1331                 if (templateId == CameraDevice.TEMPLATE_RECORD ||
1332                         templateId == CameraDevice.TEMPLATE_VIDEO_SNAPSHOT) {
1333                     if (ArrayUtils.contains(c.get(CONTROL_AF_AVAILABLE_MODES),
1334                             CONTROL_AF_MODE_CONTINUOUS_VIDEO)) {
1335                         afMode = CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_VIDEO;
1336                     }
1337                 } else if (templateId == CameraDevice.TEMPLATE_PREVIEW ||
1338                         templateId == CameraDevice.TEMPLATE_STILL_CAPTURE) {
1339                     if (ArrayUtils.contains(c.get(CONTROL_AF_AVAILABLE_MODES),
1340                             CONTROL_AF_MODE_CONTINUOUS_PICTURE)) {
1341                         afMode = CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE;
1342                     }
1343                 }
1344             }
1345
1346             if (DEBUG) {
1347                 Log.v(TAG, "createRequestTemplate (templateId=" + templateId + ")," +
1348                         " afMode=" + afMode + ", minimumFocusDistance=" + minimumFocusDistance);
1349             }
1350
1351             m.set(CaptureRequest.CONTROL_AF_MODE, afMode);
1352         }
1353
1354         {
1355             // control.aeTargetFpsRange
1356             Range<Integer>[] availableFpsRange = c.
1357                     get(CameraCharacteristics.CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES);
1358
1359             // Pick FPS range with highest max value, tiebreak on higher min value
1360             Range<Integer> bestRange = availableFpsRange[0];
1361             for (Range<Integer> r : availableFpsRange) {
1362                 if (bestRange.getUpper() < r.getUpper()) {
1363                     bestRange = r;
1364                 } else if (bestRange.getUpper() == r.getUpper() &&
1365                         bestRange.getLower() < r.getLower()) {
1366                     bestRange = r;
1367                 }
1368             }
1369             m.set(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE, bestRange);
1370         }
1371
1372         // control.sceneMode -- DISABLED is always available
1373         m.set(CaptureRequest.CONTROL_SCENE_MODE, CONTROL_SCENE_MODE_DISABLED);
1374
1375         /*
1376          * statistics.*
1377          */
1378
1379         // statistics.faceDetectMode
1380         m.set(CaptureRequest.STATISTICS_FACE_DETECT_MODE, STATISTICS_FACE_DETECT_MODE_OFF);
1381
1382         /*
1383          * flash.*
1384          */
1385
1386         // flash.mode
1387         m.set(CaptureRequest.FLASH_MODE, FLASH_MODE_OFF);
1388
1389         /*
1390          * noiseReduction.*
1391          */
1392         m.set(CaptureRequest.NOISE_REDUCTION_MODE, NOISE_REDUCTION_MODE_FAST);
1393
1394         /*
1395          * lens.*
1396          */
1397
1398         // lens.focalLength
1399         m.set(CaptureRequest.LENS_FOCAL_LENGTH,
1400                 c.get(CameraCharacteristics.LENS_INFO_AVAILABLE_FOCAL_LENGTHS)[0]);
1401
1402         /*
1403          * jpeg.*
1404          */
1405
1406         // jpeg.thumbnailSize - set smallest non-zero size if possible
1407         Size[] sizes = c.get(CameraCharacteristics.JPEG_AVAILABLE_THUMBNAIL_SIZES);
1408         m.set(CaptureRequest.JPEG_THUMBNAIL_SIZE, (sizes.length > 1) ? sizes[1] : sizes[0]);
1409
1410         // TODO: map other request template values
1411         return m;
1412     }
1413
1414     private static int[] getTagsForKeys(Key<?>[] keys) {
1415         int[] tags = new int[keys.length];
1416
1417         for (int i = 0; i < keys.length; ++i) {
1418             tags[i] = keys[i].getNativeKey().getTag();
1419         }
1420
1421         return tags;
1422     }
1423
1424     private static int[] getTagsForKeys(CaptureRequest.Key<?>[] keys) {
1425         int[] tags = new int[keys.length];
1426
1427         for (int i = 0; i < keys.length; ++i) {
1428             tags[i] = keys[i].getNativeKey().getTag();
1429         }
1430
1431         return tags;
1432     }
1433
1434     private static int[] getTagsForKeys(CaptureResult.Key<?>[] keys) {
1435         int[] tags = new int[keys.length];
1436
1437         for (int i = 0; i < keys.length; ++i) {
1438             tags[i] = keys[i].getNativeKey().getTag();
1439         }
1440
1441         return tags;
1442     }
1443
1444     /**
1445      * Convert the requested AF mode into its equivalent supported parameter.
1446      *
1447      * @param mode {@code CONTROL_AF_MODE}
1448      * @param supportedFocusModes list of camera1's supported focus modes
1449      * @return the stringified af mode, or {@code null} if its not supported
1450      */
1451     static String convertAfModeToLegacy(int mode, List<String> supportedFocusModes) {
1452         if (supportedFocusModes == null || supportedFocusModes.isEmpty()) {
1453             Log.w(TAG, "No focus modes supported; API1 bug");
1454             return null;
1455         }
1456
1457         String param = null;
1458         switch (mode) {
1459             case CONTROL_AF_MODE_AUTO:
1460                 param = Parameters.FOCUS_MODE_AUTO;
1461                 break;
1462             case CONTROL_AF_MODE_CONTINUOUS_PICTURE:
1463                 param = Parameters.FOCUS_MODE_CONTINUOUS_PICTURE;
1464                 break;
1465             case CONTROL_AF_MODE_CONTINUOUS_VIDEO:
1466                 param = Parameters.FOCUS_MODE_CONTINUOUS_VIDEO;
1467                 break;
1468             case CONTROL_AF_MODE_EDOF:
1469                 param = Parameters.FOCUS_MODE_EDOF;
1470                 break;
1471             case CONTROL_AF_MODE_MACRO:
1472                 param = Parameters.FOCUS_MODE_MACRO;
1473                 break;
1474             case CONTROL_AF_MODE_OFF:
1475                 if (supportedFocusModes.contains(Parameters.FOCUS_MODE_FIXED)) {
1476                     param = Parameters.FOCUS_MODE_FIXED;
1477                 } else {
1478                     param = Parameters.FOCUS_MODE_INFINITY;
1479                 }
1480         }
1481
1482         if (!supportedFocusModes.contains(param)) {
1483             // Weed out bad user input by setting to the first arbitrary focus mode
1484             String defaultMode = supportedFocusModes.get(0);
1485             Log.w(TAG,
1486                     String.format(
1487                             "convertAfModeToLegacy - ignoring unsupported mode %d, " +
1488                             "defaulting to %s", mode, defaultMode));
1489             param = defaultMode;
1490         }
1491
1492         return param;
1493     }
1494 }