OSDN Git Service

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