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