2 * Copyright (C) 2014 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package android.hardware.camera2.legacy;
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;
42 import java.util.ArrayList;
43 import java.util.Arrays;
44 import java.util.Collections;
45 import java.util.List;
47 import static com.android.internal.util.Preconditions.*;
48 import static android.hardware.camera2.CameraCharacteristics.*;
49 import static android.hardware.camera2.legacy.ParameterUtils.*;
52 * Provide legacy-specific implementations of camera2 metadata for legacy devices, such as the
53 * camera characteristics.
55 @SuppressWarnings("deprecation")
56 public class LegacyMetadataMapper {
57 private static final String TAG = "LegacyMetadataMapper";
58 private static final boolean DEBUG = false;
60 private static final long NS_PER_MS = 1000000;
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;
69 private static final float LENS_INFO_MINIMUM_FOCUS_DISTANCE_FIXED_FOCUS = 0.0f;
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
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 */
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
87 static final int UNKNOWN_MODE = -1;
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;
93 * Development hijinks: Lie about not supporting certain capabilities
95 * - Unblock some CTS tests from running whose main intent is not the metadata itself
97 * TODO: Remove these constants and strip out any code that previously relied on them
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;
109 * Create characteristics for a legacy device by mapping the {@code parameters}
112 * @param parameters A non-{@code null} parameters set
113 * @param info Camera info with camera facing direction and angle of orientation
115 * @return static camera characteristics for a camera device
117 * @throws NullPointerException if any of the args were {@code null}
119 public static CameraCharacteristics createCharacteristics(Camera.Parameters parameters,
121 checkNotNull(parameters, "parameters must not be null");
122 checkNotNull(info, "info must not be null");
124 String paramStr = parameters.flatten();
125 android.hardware.CameraInfo outerInfo = new android.hardware.CameraInfo();
126 outerInfo.info = info;
128 return createCharacteristics(paramStr, outerInfo);
132 * Create characteristics for a legacy device by mapping the {@code parameters}
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
139 * @throws NullPointerException if any of the args were {@code null}
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");
147 CameraMetadataNative m = new CameraMetadataNative();
149 mapCharacteristicsFromInfo(m, info.info);
151 Camera.Parameters params = Camera.getEmptyParameters();
152 params.unflatten(parameters);
153 mapCharacteristicsFromParameters(m, params);
156 Log.v(TAG, "createCharacteristics metadata:");
157 Log.v(TAG, "--------------------------------------------------- (start)");
159 Log.v(TAG, "--------------------------------------------------- (end)");
162 return new CameraCharacteristics(m);
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);
171 private static void mapCharacteristicsFromParameters(CameraMetadataNative m,
172 Camera.Parameters p) {
177 m.set(COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES,
178 new int[] { COLOR_CORRECTION_ABERRATION_MODE_FAST,
179 COLOR_CORRECTION_ABERRATION_MODE_HIGH_QUALITY });
194 * - Anything that doesn't have a set of related fields
196 mapControlOther(m, p);
213 m.set(NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES,
214 new int[] { NOISE_REDUCTION_MODE_FAST,
215 NOISE_REDUCTION_MODE_HIGH_QUALITY});
238 * info.supportedHardwareLevel
240 m.set(INFO_SUPPORTED_HARDWARE_LEVEL, INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY);
243 * scaler.availableStream*, scaler.available*Durations, sensor.info.maxFrameDuration
245 mapScalerStreamConfigs(m, p);
247 // Order matters below: Put this last so that we can read the metadata set previously
256 private static void mapScalerStreamConfigs(CameraMetadataNative m, Camera.Parameters p) {
258 ArrayList<StreamConfiguration> availableStreamConfigs = new ArrayList<>();
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
265 * Use platform-internal format constants here, since StreamConfigurationMap does the
266 * remapping to public format constants.
268 List<Camera.Size> previewSizes = p.getSupportedPreviewSizes();
269 List<Camera.Size> jpegSizes = p.getSupportedPictureSizes();
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.
281 SizeAreaComparator areaComparator = new SizeAreaComparator();
283 // Sort preview to min->max
284 Collections.sort(previewSizes, areaComparator);
286 Camera.Size maxJpegSize = SizeAreaComparator.findLargestByArea(jpegSizes);
287 float jpegAspectRatio = maxJpegSize.width * 1.0f / maxJpegSize.height;
290 Log.v(TAG, String.format("mapScalerStreamConfigs - largest JPEG area %dx%d, AR=%f",
291 maxJpegSize.width, maxJpegSize.height, jpegAspectRatio));
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);
299 float previewAspectRatio = size.width * 1.0f / size.height;
301 if (Math.abs(jpegAspectRatio - previewAspectRatio) >=
302 PREVIEW_ASPECT_RATIO_TOLERANCE) {
303 previewSizes.remove(index); // Assume removing from end is O(1)
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));
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();
323 // Sort again, this time in descending order max->min
324 Collections.sort(previewSizes, Collections.reverseOrder(areaComparator));
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);
336 * Do not add any formats unknown to us
337 * (since it would fail runtime checks in StreamConfigurationMap)
340 String.format("mapStreamConfigs - Skipping format %x", format));
344 appendStreamConfig(availableStreamConfigs,
345 HAL_PIXEL_FORMAT_BLOB, p.getSupportedPictureSizes());
347 * scaler.availableStreamConfigurations
349 m.set(SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
350 availableStreamConfigs.toArray(new StreamConfiguration[0]));
353 * scaler.availableMinFrameDurations
355 // No frame durations available
356 m.set(SCALER_AVAILABLE_MIN_FRAME_DURATIONS, new StreamConfigurationDuration[0]);
358 StreamConfigurationDuration[] jpegStalls =
359 new StreamConfigurationDuration[jpegSizes.size()];
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;
371 * scaler.availableStallDurations
373 // Set stall durations for jpeg, other formats use default stall duration
374 m.set(SCALER_AVAILABLE_STALL_DURATIONS, jpegStalls);
377 * sensor.info.maxFrameDuration
379 m.set(SENSOR_INFO_MAX_FRAME_DURATION, longestStallDuration);
382 @SuppressWarnings({"unchecked"})
383 private static void mapControlAe(CameraMetadataNative m, Camera.Parameters p) {
385 * control.aeAvailableAntiBandingModes
387 List<String> antiBandingModes = p.getSupportedAntibanding();
388 if (antiBandingModes != null && antiBandingModes.size() > 0) { // antibanding is optional
389 int[] modes = new int[antiBandingModes.size()];
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...");
397 modes[j++] = convertedMode;
400 m.set(CONTROL_AE_AVAILABLE_ANTIBANDING_MODES, Arrays.copyOf(modes, j));
402 m.set(CONTROL_AE_AVAILABLE_ANTIBANDING_MODES, new int[0]);
406 * control.aeAvailableTargetFpsRanges
409 List<int[]> fpsRanges = p.getSupportedPreviewFpsRange();
410 if (fpsRanges == null) {
411 throw new AssertionError("Supported FPS ranges cannot be null.");
413 int rangesSize = fpsRanges.size();
414 if (rangesSize <= 0) {
415 throw new AssertionError("At least one FPS range must be supported.");
417 Range<Integer>[] ranges = new Range[rangesSize];
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));
424 m.set(CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES, ranges);
425 } catch (Exception e) {
426 Log.d(TAG, "ignore any error from getSupportedPreviewFpsRange: ", e);
430 * control.aeAvailableModes
433 List<String> flashModes = p.getSupportedFlashModes();
435 String[] flashModeStrings = new String[] {
436 Camera.Parameters.FLASH_MODE_OFF,
437 Camera.Parameters.FLASH_MODE_AUTO,
438 Camera.Parameters.FLASH_MODE_ON,
439 Camera.Parameters.FLASH_MODE_RED_EYE,
440 // Map these manually
441 Camera.Parameters.FLASH_MODE_TORCH,
443 int[] flashModeInts = new int[] {
445 CONTROL_AE_MODE_ON_AUTO_FLASH,
446 CONTROL_AE_MODE_ON_ALWAYS_FLASH,
447 CONTROL_AE_MODE_ON_AUTO_FLASH_REDEYE
449 int[] aeAvail = ArrayUtils.convertStringListToIntArray(
450 flashModes, flashModeStrings, flashModeInts);
452 // No flash control -> AE is always on
453 if (aeAvail == null || aeAvail.length == 0) {
454 aeAvail = new int[] {
459 // Note that AE_MODE_OFF is never available.
460 m.set(CONTROL_AE_AVAILABLE_MODES, aeAvail);
464 * control.aeCompensationRanges
467 int min = p.getMinExposureCompensation();
468 int max = p.getMaxExposureCompensation();
470 m.set(CONTROL_AE_COMPENSATION_RANGE, Range.create(min, max));
474 * control.aeCompensationStep
477 float step = p.getExposureCompensationStep();
479 m.set(CONTROL_AE_COMPENSATION_STEP, ParamsUtils.createRational(step));
483 * control.aeLockAvailable
486 boolean aeLockAvailable = p.isAutoExposureLockSupported();
488 m.set(CONTROL_AE_LOCK_AVAILABLE, aeLockAvailable);
493 @SuppressWarnings({"unchecked"})
494 private static void mapControlAf(CameraMetadataNative m, Camera.Parameters p) {
496 * control.afAvailableModes
499 List<String> focusModes = p.getSupportedFocusModes();
501 String[] focusModeStrings = new String[] {
502 Camera.Parameters.FOCUS_MODE_AUTO,
503 Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE,
504 Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO,
505 Camera.Parameters.FOCUS_MODE_EDOF,
506 Camera.Parameters.FOCUS_MODE_INFINITY,
507 Camera.Parameters.FOCUS_MODE_MACRO,
508 Camera.Parameters.FOCUS_MODE_FIXED,
511 int[] focusModeInts = new int[] {
512 CONTROL_AF_MODE_AUTO,
513 CONTROL_AF_MODE_CONTINUOUS_PICTURE,
514 CONTROL_AF_MODE_CONTINUOUS_VIDEO,
515 CONTROL_AF_MODE_EDOF,
517 CONTROL_AF_MODE_MACRO,
521 List<Integer> afAvail = ArrayUtils.convertStringListToIntList(
522 focusModes, focusModeStrings, focusModeInts);
524 // No AF modes supported? That's unpossible!
525 if (afAvail == null || afAvail.size() == 0) {
526 Log.w(TAG, "No AF modes supported (HAL bug); defaulting to AF_MODE_OFF only");
527 afAvail = new ArrayList<Integer>(/*capacity*/1);
528 afAvail.add(CONTROL_AF_MODE_OFF);
531 m.set(CONTROL_AF_AVAILABLE_MODES, ArrayUtils.toIntArray(afAvail));
534 Log.v(TAG, "mapControlAf - control.afAvailableModes set to " +
535 ListUtils.listToString(afAvail));
540 private static void mapControlAwb(CameraMetadataNative m, Camera.Parameters p) {
542 * control.awbAvailableModes
546 List<String> wbModes = p.getSupportedWhiteBalance();
548 String[] wbModeStrings = new String[] {
549 Camera.Parameters.WHITE_BALANCE_AUTO ,
550 Camera.Parameters.WHITE_BALANCE_INCANDESCENT ,
551 Camera.Parameters.WHITE_BALANCE_FLUORESCENT ,
552 Camera.Parameters.WHITE_BALANCE_WARM_FLUORESCENT ,
553 Camera.Parameters.WHITE_BALANCE_DAYLIGHT ,
554 Camera.Parameters.WHITE_BALANCE_CLOUDY_DAYLIGHT ,
555 Camera.Parameters.WHITE_BALANCE_TWILIGHT ,
556 Camera.Parameters.WHITE_BALANCE_SHADE ,
559 int[] wbModeInts = new int[] {
560 CONTROL_AWB_MODE_AUTO,
561 CONTROL_AWB_MODE_INCANDESCENT ,
562 CONTROL_AWB_MODE_FLUORESCENT ,
563 CONTROL_AWB_MODE_WARM_FLUORESCENT ,
564 CONTROL_AWB_MODE_DAYLIGHT ,
565 CONTROL_AWB_MODE_CLOUDY_DAYLIGHT ,
566 CONTROL_AWB_MODE_TWILIGHT ,
567 CONTROL_AWB_MODE_SHADE ,
568 // Note that CONTROL_AWB_MODE_OFF is unsupported
571 List<Integer> awbAvail = ArrayUtils.convertStringListToIntList(
572 wbModes, wbModeStrings, wbModeInts);
574 // No AWB modes supported? That's unpossible!
575 if (awbAvail == null || awbAvail.size() == 0) {
576 Log.w(TAG, "No AWB modes supported (HAL bug); defaulting to AWB_MODE_AUTO only");
577 awbAvail = new ArrayList<Integer>(/*capacity*/1);
578 awbAvail.add(CONTROL_AWB_MODE_AUTO);
581 m.set(CONTROL_AWB_AVAILABLE_MODES, ArrayUtils.toIntArray(awbAvail));
584 Log.v(TAG, "mapControlAwb - control.awbAvailableModes set to " +
585 ListUtils.listToString(awbAvail));
590 * control.awbLockAvailable
593 boolean awbLockAvailable = p.isAutoWhiteBalanceLockSupported();
595 m.set(CONTROL_AWB_LOCK_AVAILABLE, awbLockAvailable);
600 private static void mapControlOther(CameraMetadataNative m, Camera.Parameters p) {
602 * android.control.availableVideoStabilizationModes
605 int stabModes[] = p.isVideoStabilizationSupported() ?
606 new int[] { CONTROL_VIDEO_STABILIZATION_MODE_OFF,
607 CONTROL_VIDEO_STABILIZATION_MODE_ON } :
608 new int[] { CONTROL_VIDEO_STABILIZATION_MODE_OFF };
610 m.set(CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES, stabModes);
614 * android.control.maxRegions
616 final int AE = 0, AWB = 1, AF = 2;
618 int[] maxRegions = new int[3];
619 maxRegions[AE] = p.getMaxNumMeteringAreas();
620 maxRegions[AWB] = 0; // AWB regions not supported in API1
621 maxRegions[AF] = p.getMaxNumFocusAreas();
623 if (LIE_ABOUT_AE_MAX_REGIONS) {
626 if (LIE_ABOUT_AF_MAX_REGIONS) {
630 m.set(CONTROL_MAX_REGIONS, maxRegions);
633 * android.control.availableEffects
635 List<String> effectModes = p.getSupportedColorEffects();
636 int[] supportedEffectModes = (effectModes == null) ? new int[0] :
637 ArrayUtils.convertStringListToIntArray(effectModes, sLegacyEffectMode,
639 m.set(CONTROL_AVAILABLE_EFFECTS, supportedEffectModes);
642 * android.control.availableSceneModes
644 int maxNumDetectedFaces = p.getMaxNumDetectedFaces();
645 List<String> sceneModes = p.getSupportedSceneModes();
646 List<Integer> supportedSceneModes =
647 ArrayUtils.convertStringListToIntList(sceneModes, sLegacySceneModes, sSceneModes);
649 // Special case where the only scene mode listed is AUTO => no scene mode
650 if (sceneModes != null && sceneModes.size() == 1 &&
651 sceneModes.get(0) == Parameters.SCENE_MODE_AUTO) {
652 supportedSceneModes = null;
655 boolean sceneModeSupported = true;
656 if (supportedSceneModes == null && maxNumDetectedFaces == 0) {
657 sceneModeSupported = false;
660 if (sceneModeSupported) {
661 if (supportedSceneModes == null) {
662 supportedSceneModes = new ArrayList<Integer>();
664 if (maxNumDetectedFaces > 0) { // always supports FACE_PRIORITY when face detecting
665 supportedSceneModes.add(CONTROL_SCENE_MODE_FACE_PRIORITY);
667 // Remove all DISABLED occurrences
668 if (supportedSceneModes.contains(CONTROL_SCENE_MODE_DISABLED)) {
669 while(supportedSceneModes.remove(new Integer(CONTROL_SCENE_MODE_DISABLED))) {}
671 m.set(CONTROL_AVAILABLE_SCENE_MODES, ArrayUtils.toIntArray(supportedSceneModes));
673 m.set(CONTROL_AVAILABLE_SCENE_MODES, new int[] {CONTROL_SCENE_MODE_DISABLED});
677 * android.control.availableModes
679 m.set(CONTROL_AVAILABLE_MODES, sceneModeSupported ?
680 new int[] { CONTROL_MODE_AUTO, CONTROL_MODE_USE_SCENE_MODE } :
681 new int[] { CONTROL_MODE_AUTO });
684 private static void mapLens(CameraMetadataNative m, Camera.Parameters p) {
686 * We can tell if the lens is fixed focus;
687 * but if it's not, we can't tell the minimum focus distance, so leave it null then.
690 Log.v(TAG, "mapLens - focus-mode='" + p.getFocusMode() + "'");
693 if (Camera.Parameters.FOCUS_MODE_FIXED.equals(p.getFocusMode())) {
695 * lens.info.minimumFocusDistance
697 m.set(LENS_INFO_MINIMUM_FOCUS_DISTANCE, LENS_INFO_MINIMUM_FOCUS_DISTANCE_FIXED_FOCUS);
700 Log.v(TAG, "mapLens - lens.info.minimumFocusDistance = 0");
704 Log.v(TAG, "mapLens - lens.info.minimumFocusDistance is unknown");
708 float[] focalLengths = new float[] { p.getFocalLength() };
709 m.set(LENS_INFO_AVAILABLE_FOCAL_LENGTHS, focalLengths);
712 private static void mapFlash(CameraMetadataNative m, Camera.Parameters p) {
713 boolean flashAvailable = false;
714 List<String> supportedFlashModes = p.getSupportedFlashModes();
716 if (supportedFlashModes != null) {
717 // If only 'OFF' is available, we don't really have flash support
718 flashAvailable = !ListUtils.listElementsEqualTo(
719 supportedFlashModes, Camera.Parameters.FLASH_MODE_OFF);
723 * flash.info.available
725 m.set(FLASH_INFO_AVAILABLE, flashAvailable);
728 private static void mapJpeg(CameraMetadataNative m, Camera.Parameters p) {
729 List<Camera.Size> thumbnailSizes = p.getSupportedJpegThumbnailSizes();
731 if (thumbnailSizes != null) {
732 Size[] sizes = convertSizeListToArray(thumbnailSizes);
733 Arrays.sort(sizes, new android.hardware.camera2.utils.SizeAreaComparator());
734 m.set(JPEG_AVAILABLE_THUMBNAIL_SIZES, sizes);
738 private static void mapRequest(CameraMetadataNative m, Parameters p) {
740 * request.availableCapabilities
742 int[] capabilities = { REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE };
743 m.set(REQUEST_AVAILABLE_CAPABILITIES, capabilities);
746 * request.availableCharacteristicsKeys
749 // TODO: check if the underlying key is supported before listing a key as available
751 // Note: We only list public keys. Native HALs should list ALL keys regardless of visibility.
753 Key<?> availableKeys[] = new Key<?>[] {
754 CameraCharacteristics.COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES ,
755 CameraCharacteristics.CONTROL_AE_AVAILABLE_ANTIBANDING_MODES ,
756 CameraCharacteristics.CONTROL_AE_AVAILABLE_MODES ,
757 CameraCharacteristics.CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES ,
758 CameraCharacteristics.CONTROL_AE_COMPENSATION_RANGE ,
759 CameraCharacteristics.CONTROL_AE_COMPENSATION_STEP ,
760 CameraCharacteristics.CONTROL_AE_LOCK_AVAILABLE ,
761 CameraCharacteristics.CONTROL_AF_AVAILABLE_MODES ,
762 CameraCharacteristics.CONTROL_AVAILABLE_EFFECTS ,
763 CameraCharacteristics.CONTROL_AVAILABLE_MODES ,
764 CameraCharacteristics.CONTROL_AVAILABLE_SCENE_MODES ,
765 CameraCharacteristics.CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES ,
766 CameraCharacteristics.CONTROL_AWB_AVAILABLE_MODES ,
767 CameraCharacteristics.CONTROL_AWB_LOCK_AVAILABLE ,
768 CameraCharacteristics.CONTROL_MAX_REGIONS ,
769 CameraCharacteristics.FLASH_INFO_AVAILABLE ,
770 CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL ,
771 CameraCharacteristics.JPEG_AVAILABLE_THUMBNAIL_SIZES ,
772 CameraCharacteristics.LENS_FACING ,
773 CameraCharacteristics.LENS_INFO_AVAILABLE_FOCAL_LENGTHS ,
774 CameraCharacteristics.NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES ,
775 CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES ,
776 CameraCharacteristics.REQUEST_MAX_NUM_OUTPUT_STREAMS ,
777 CameraCharacteristics.REQUEST_PARTIAL_RESULT_COUNT ,
778 CameraCharacteristics.REQUEST_PIPELINE_MAX_DEPTH ,
779 CameraCharacteristics.SCALER_AVAILABLE_MAX_DIGITAL_ZOOM ,
780 // CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP ,
781 CameraCharacteristics.SCALER_CROPPING_TYPE ,
782 CameraCharacteristics.SENSOR_AVAILABLE_TEST_PATTERN_MODES ,
783 CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE ,
784 CameraCharacteristics.SENSOR_INFO_PHYSICAL_SIZE ,
785 CameraCharacteristics.SENSOR_INFO_PIXEL_ARRAY_SIZE ,
786 CameraCharacteristics.SENSOR_INFO_TIMESTAMP_SOURCE ,
787 CameraCharacteristics.SENSOR_ORIENTATION ,
788 CameraCharacteristics.STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES ,
789 CameraCharacteristics.STATISTICS_INFO_MAX_FACE_COUNT ,
790 CameraCharacteristics.SYNC_MAX_LATENCY ,
792 List<Key<?>> characteristicsKeys = new ArrayList<>(Arrays.asList(availableKeys));
795 * Add the conditional keys
797 if (m.get(LENS_INFO_MINIMUM_FOCUS_DISTANCE) != null) {
798 characteristicsKeys.add(LENS_INFO_MINIMUM_FOCUS_DISTANCE);
801 m.set(REQUEST_AVAILABLE_CHARACTERISTICS_KEYS,
802 getTagsForKeys(characteristicsKeys.toArray(new Key<?>[0])));
806 * request.availableRequestKeys
809 CaptureRequest.Key<?> defaultAvailableKeys[] = new CaptureRequest.Key<?>[] {
810 CaptureRequest.COLOR_CORRECTION_ABERRATION_MODE,
811 CaptureRequest.CONTROL_AE_ANTIBANDING_MODE,
812 CaptureRequest.CONTROL_AE_EXPOSURE_COMPENSATION,
813 CaptureRequest.CONTROL_AE_LOCK,
814 CaptureRequest.CONTROL_AE_MODE,
815 CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE,
816 CaptureRequest.CONTROL_AF_MODE,
817 CaptureRequest.CONTROL_AF_TRIGGER,
818 CaptureRequest.CONTROL_AWB_LOCK,
819 CaptureRequest.CONTROL_AWB_MODE,
820 CaptureRequest.CONTROL_CAPTURE_INTENT,
821 CaptureRequest.CONTROL_EFFECT_MODE,
822 CaptureRequest.CONTROL_MODE,
823 CaptureRequest.CONTROL_SCENE_MODE,
824 CaptureRequest.CONTROL_VIDEO_STABILIZATION_MODE,
825 CaptureRequest.FLASH_MODE,
826 CaptureRequest.JPEG_GPS_COORDINATES,
827 CaptureRequest.JPEG_GPS_PROCESSING_METHOD,
828 CaptureRequest.JPEG_GPS_TIMESTAMP,
829 CaptureRequest.JPEG_ORIENTATION,
830 CaptureRequest.JPEG_QUALITY,
831 CaptureRequest.JPEG_THUMBNAIL_QUALITY,
832 CaptureRequest.JPEG_THUMBNAIL_SIZE,
833 CaptureRequest.LENS_FOCAL_LENGTH,
834 CaptureRequest.NOISE_REDUCTION_MODE,
835 CaptureRequest.SCALER_CROP_REGION,
836 CaptureRequest.STATISTICS_FACE_DETECT_MODE,
838 ArrayList<CaptureRequest.Key<?>> availableKeys =
839 new ArrayList<CaptureRequest.Key<?>>(Arrays.asList(defaultAvailableKeys));
841 if (p.getMaxNumMeteringAreas() > 0) {
842 availableKeys.add(CaptureRequest.CONTROL_AE_REGIONS);
844 if (p.getMaxNumFocusAreas() > 0) {
845 availableKeys.add(CaptureRequest.CONTROL_AF_REGIONS);
848 CaptureRequest.Key<?> availableRequestKeys[] =
849 new CaptureRequest.Key<?>[availableKeys.size()];
850 availableKeys.toArray(availableRequestKeys);
851 m.set(REQUEST_AVAILABLE_REQUEST_KEYS, getTagsForKeys(availableRequestKeys));
855 * request.availableResultKeys
858 CaptureResult.Key<?> defaultAvailableKeys[] = new CaptureResult.Key<?>[] {
859 CaptureResult.COLOR_CORRECTION_ABERRATION_MODE ,
860 CaptureResult.CONTROL_AE_ANTIBANDING_MODE ,
861 CaptureResult.CONTROL_AE_EXPOSURE_COMPENSATION ,
862 CaptureResult.CONTROL_AE_LOCK ,
863 CaptureResult.CONTROL_AE_MODE ,
864 CaptureResult.CONTROL_AF_MODE ,
865 CaptureResult.CONTROL_AF_STATE ,
866 CaptureResult.CONTROL_AWB_MODE ,
867 CaptureResult.CONTROL_AWB_LOCK ,
868 CaptureResult.CONTROL_MODE ,
869 CaptureResult.FLASH_MODE ,
870 CaptureResult.JPEG_GPS_COORDINATES ,
871 CaptureResult.JPEG_GPS_PROCESSING_METHOD ,
872 CaptureResult.JPEG_GPS_TIMESTAMP ,
873 CaptureResult.JPEG_ORIENTATION ,
874 CaptureResult.JPEG_QUALITY ,
875 CaptureResult.JPEG_THUMBNAIL_QUALITY ,
876 CaptureResult.LENS_FOCAL_LENGTH ,
877 CaptureResult.NOISE_REDUCTION_MODE ,
878 CaptureResult.REQUEST_PIPELINE_DEPTH ,
879 CaptureResult.SCALER_CROP_REGION ,
880 CaptureResult.SENSOR_TIMESTAMP ,
881 CaptureResult.STATISTICS_FACE_DETECT_MODE ,
882 // CaptureResult.STATISTICS_FACES ,
884 List<CaptureResult.Key<?>> availableKeys =
885 new ArrayList<CaptureResult.Key<?>>(Arrays.asList(defaultAvailableKeys));
887 if (p.getMaxNumMeteringAreas() > 0) {
888 availableKeys.add(CaptureResult.CONTROL_AE_REGIONS);
890 if (p.getMaxNumFocusAreas() > 0) {
891 availableKeys.add(CaptureResult.CONTROL_AF_REGIONS);
894 CaptureResult.Key<?> availableResultKeys[] =
895 new CaptureResult.Key<?>[availableKeys.size()];
896 availableKeys.toArray(availableResultKeys);
897 m.set(REQUEST_AVAILABLE_RESULT_KEYS, getTagsForKeys(availableResultKeys));
901 * request.maxNumOutputStreams
903 int[] outputStreams = {
905 REQUEST_MAX_NUM_OUTPUT_STREAMS_COUNT_RAW,
906 /* Processed & Not-Stalling */
907 REQUEST_MAX_NUM_OUTPUT_STREAMS_COUNT_PROC,
908 /* Processed & Stalling */
909 REQUEST_MAX_NUM_OUTPUT_STREAMS_COUNT_PROC_STALL,
911 m.set(REQUEST_MAX_NUM_OUTPUT_STREAMS, outputStreams);
914 * request.maxNumInputStreams
916 m.set(REQUEST_MAX_NUM_INPUT_STREAMS, REQUEST_MAX_NUM_INPUT_STREAMS_COUNT);
919 * request.partialResultCount
921 m.set(REQUEST_PARTIAL_RESULT_COUNT, 1); // No partial results supported
924 * request.pipelineMaxDepth
926 m.set(REQUEST_PIPELINE_MAX_DEPTH,
927 (byte)(REQUEST_PIPELINE_MAX_DEPTH_HAL1 + REQUEST_PIPELINE_MAX_DEPTH_OURS));
930 private static void mapScaler(CameraMetadataNative m, Parameters p) {
932 * scaler.availableMaxDigitalZoom
934 m.set(SCALER_AVAILABLE_MAX_DIGITAL_ZOOM, ParameterUtils.getMaxZoomRatio(p));
937 * scaler.croppingType = CENTER_ONLY
939 m.set(SCALER_CROPPING_TYPE, SCALER_CROPPING_TYPE_CENTER_ONLY);
942 private static void mapSensor(CameraMetadataNative m, Parameters p) {
943 // Use the largest jpeg size (by area) for both active array and pixel array
944 Size largestJpegSize = getLargestSupportedJpegSizeByArea(p);
946 * sensor.info.activeArraySize
949 Rect activeArrayRect = ParamsUtils.createRect(largestJpegSize);
950 m.set(SENSOR_INFO_ACTIVE_ARRAY_SIZE, activeArrayRect);
954 * sensor.availableTestPatternModes
957 // Only "OFF" test pattern mode is available
958 m.set(SENSOR_AVAILABLE_TEST_PATTERN_MODES, new int[] { SENSOR_TEST_PATTERN_MODE_OFF });
962 * sensor.info.pixelArraySize
964 m.set(SENSOR_INFO_PIXEL_ARRAY_SIZE, largestJpegSize);
967 * sensor.info.physicalSize
971 * Assume focal length is at infinity focus and that the lens is rectilinear.
973 float focalLength = p.getFocalLength(); // in mm
974 double angleHor = p.getHorizontalViewAngle() * Math.PI / 180; // to radians
975 double angleVer = p.getVerticalViewAngle() * Math.PI / 180; // to radians
977 float height = (float)Math.abs(2 * focalLength * Math.tan(angleVer / 2));
978 float width = (float)Math.abs(2 * focalLength * Math.tan(angleHor / 2));
980 m.set(SENSOR_INFO_PHYSICAL_SIZE, new SizeF(width, height)); // in mm
984 * sensor.info.timestampSource
987 m.set(SENSOR_INFO_TIMESTAMP_SOURCE, SENSOR_INFO_TIMESTAMP_SOURCE_UNKNOWN);
991 private static void mapStatistics(CameraMetadataNative m, Parameters p) {
993 * statistics.info.availableFaceDetectModes
997 if (p.getMaxNumDetectedFaces() > 0) {
998 fdModes = new int[] {
999 STATISTICS_FACE_DETECT_MODE_OFF,
1000 STATISTICS_FACE_DETECT_MODE_SIMPLE
1001 // FULL is never-listed, since we have no way to query it statically
1004 fdModes = new int[] {
1005 STATISTICS_FACE_DETECT_MODE_OFF
1008 m.set(STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES, fdModes);
1011 * statistics.info.maxFaceCount
1013 m.set(STATISTICS_INFO_MAX_FACE_COUNT, p.getMaxNumDetectedFaces());
1016 private static void mapSync(CameraMetadataNative m, Parameters p) {
1020 m.set(SYNC_MAX_LATENCY, SYNC_MAX_LATENCY_UNKNOWN);
1023 private static void appendStreamConfig(
1024 ArrayList<StreamConfiguration> configs, int format, List<Camera.Size> sizes) {
1025 for (Camera.Size size : sizes) {
1026 StreamConfiguration config =
1027 new StreamConfiguration(format, size.width, size.height, /*input*/false);
1028 configs.add(config);
1032 private final static String[] sLegacySceneModes = {
1033 Parameters.SCENE_MODE_AUTO,
1034 Parameters.SCENE_MODE_ACTION,
1035 Parameters.SCENE_MODE_PORTRAIT,
1036 Parameters.SCENE_MODE_LANDSCAPE,
1037 Parameters.SCENE_MODE_NIGHT,
1038 Parameters.SCENE_MODE_NIGHT_PORTRAIT,
1039 Parameters.SCENE_MODE_THEATRE,
1040 Parameters.SCENE_MODE_BEACH,
1041 Parameters.SCENE_MODE_SNOW,
1042 Parameters.SCENE_MODE_SUNSET,
1043 Parameters.SCENE_MODE_STEADYPHOTO,
1044 Parameters.SCENE_MODE_FIREWORKS,
1045 Parameters.SCENE_MODE_SPORTS,
1046 Parameters.SCENE_MODE_PARTY,
1047 Parameters.SCENE_MODE_CANDLELIGHT,
1048 Parameters.SCENE_MODE_BARCODE,
1049 Parameters.SCENE_MODE_HDR,
1052 private final static int[] sSceneModes = {
1053 CameraCharacteristics.CONTROL_SCENE_MODE_DISABLED,
1054 CameraCharacteristics.CONTROL_SCENE_MODE_ACTION,
1055 CameraCharacteristics.CONTROL_SCENE_MODE_PORTRAIT,
1056 CameraCharacteristics.CONTROL_SCENE_MODE_LANDSCAPE,
1057 CameraCharacteristics.CONTROL_SCENE_MODE_NIGHT,
1058 CameraCharacteristics.CONTROL_SCENE_MODE_NIGHT_PORTRAIT,
1059 CameraCharacteristics.CONTROL_SCENE_MODE_THEATRE,
1060 CameraCharacteristics.CONTROL_SCENE_MODE_BEACH,
1061 CameraCharacteristics.CONTROL_SCENE_MODE_SNOW,
1062 CameraCharacteristics.CONTROL_SCENE_MODE_SUNSET,
1063 CameraCharacteristics.CONTROL_SCENE_MODE_STEADYPHOTO,
1064 CameraCharacteristics.CONTROL_SCENE_MODE_FIREWORKS,
1065 CameraCharacteristics.CONTROL_SCENE_MODE_SPORTS,
1066 CameraCharacteristics.CONTROL_SCENE_MODE_PARTY,
1067 CameraCharacteristics.CONTROL_SCENE_MODE_CANDLELIGHT,
1068 CameraCharacteristics.CONTROL_SCENE_MODE_BARCODE,
1069 CameraCharacteristics.CONTROL_SCENE_MODE_HDR,
1072 static int convertSceneModeFromLegacy(String mode) {
1074 return CameraCharacteristics.CONTROL_SCENE_MODE_DISABLED;
1076 int index = ArrayUtils.getArrayIndex(sLegacySceneModes, mode);
1078 return UNKNOWN_MODE;
1080 return sSceneModes[index];
1083 static String convertSceneModeToLegacy(int mode) {
1084 if (mode == CONTROL_SCENE_MODE_FACE_PRIORITY) {
1085 // OK: Let LegacyFaceDetectMapper handle turning face detection on/off
1086 return Parameters.SCENE_MODE_AUTO;
1089 int index = ArrayUtils.getArrayIndex(sSceneModes, mode);
1093 return sLegacySceneModes[index];
1096 private final static String[] sLegacyEffectMode = {
1097 Parameters.EFFECT_NONE,
1098 Parameters.EFFECT_MONO,
1099 Parameters.EFFECT_NEGATIVE,
1100 Parameters.EFFECT_SOLARIZE,
1101 Parameters.EFFECT_SEPIA,
1102 Parameters.EFFECT_POSTERIZE,
1103 Parameters.EFFECT_WHITEBOARD,
1104 Parameters.EFFECT_BLACKBOARD,
1105 Parameters.EFFECT_AQUA,
1108 private final static int[] sEffectModes = {
1109 CameraCharacteristics.CONTROL_EFFECT_MODE_OFF,
1110 CameraCharacteristics.CONTROL_EFFECT_MODE_MONO,
1111 CameraCharacteristics.CONTROL_EFFECT_MODE_NEGATIVE,
1112 CameraCharacteristics.CONTROL_EFFECT_MODE_SOLARIZE,
1113 CameraCharacteristics.CONTROL_EFFECT_MODE_SEPIA,
1114 CameraCharacteristics.CONTROL_EFFECT_MODE_POSTERIZE,
1115 CameraCharacteristics.CONTROL_EFFECT_MODE_WHITEBOARD,
1116 CameraCharacteristics.CONTROL_EFFECT_MODE_BLACKBOARD,
1117 CameraCharacteristics.CONTROL_EFFECT_MODE_AQUA,
1120 static int convertEffectModeFromLegacy(String mode) {
1122 return CameraCharacteristics.CONTROL_EFFECT_MODE_OFF;
1124 int index = ArrayUtils.getArrayIndex(sLegacyEffectMode, mode);
1126 return UNKNOWN_MODE;
1128 return sEffectModes[index];
1131 static String convertEffectModeToLegacy(int mode) {
1132 int index = ArrayUtils.getArrayIndex(sEffectModes, mode);
1136 return sLegacyEffectMode[index];
1140 * Convert the ae antibanding mode from api1 into api2.
1142 * @param mode the api1 mode, {@code null} is allowed and will return {@code -1}.
1144 * @return The api2 value, or {@code -1} by default if conversion failed
1146 private static int convertAntiBandingMode(String mode) {
1152 case Camera.Parameters.ANTIBANDING_OFF: {
1153 return CONTROL_AE_ANTIBANDING_MODE_OFF;
1155 case Camera.Parameters.ANTIBANDING_50HZ: {
1156 return CONTROL_AE_ANTIBANDING_MODE_50HZ;
1158 case Camera.Parameters.ANTIBANDING_60HZ: {
1159 return CONTROL_AE_ANTIBANDING_MODE_60HZ;
1161 case Camera.Parameters.ANTIBANDING_AUTO: {
1162 return CONTROL_AE_ANTIBANDING_MODE_AUTO;
1165 Log.w(TAG, "convertAntiBandingMode - Unknown antibanding mode " + mode);
1172 * Convert the ae antibanding mode from api1 into api2.
1174 * @param mode the api1 mode, {@code null} is allowed and will return {@code MODE_OFF}.
1176 * @return The api2 value, or {@code MODE_OFF} by default if conversion failed
1178 static int convertAntiBandingModeOrDefault(String mode) {
1179 int antiBandingMode = convertAntiBandingMode(mode);
1180 if (antiBandingMode == -1) {
1181 return CONTROL_AE_ANTIBANDING_MODE_OFF;
1184 return antiBandingMode;
1187 private static int[] convertAeFpsRangeToLegacy(Range<Integer> fpsRange) {
1188 int[] legacyFps = new int[2];
1189 legacyFps[Camera.Parameters.PREVIEW_FPS_MIN_INDEX] = fpsRange.getLower();
1190 legacyFps[Camera.Parameters.PREVIEW_FPS_MAX_INDEX] = fpsRange.getUpper();
1195 * Return the stall duration for a given output jpeg size in nanoseconds.
1197 * <p>An 8mp image is chosen to have a stall duration of 0.8 seconds.</p>
1199 private static long calculateJpegStallDuration(Camera.Size size) {
1200 long baseDuration = APPROXIMATE_CAPTURE_DELAY_MS * NS_PER_MS; // 200ms for capture
1201 long area = size.width * (long) size.height;
1202 long stallPerArea = APPROXIMATE_JPEG_ENCODE_TIME_MS * NS_PER_MS /
1203 APPROXIMATE_SENSOR_AREA_PX; // 600ms stall for 8mp
1204 return baseDuration + area * stallPerArea;
1208 * Set the legacy parameters using the {@link LegacyRequest legacy request}.
1210 * <p>The legacy request's parameters are changed as a side effect of calling this
1213 * @param request a non-{@code null} legacy request
1215 public static void convertRequestMetadata(LegacyRequest request) {
1216 LegacyRequestMapper.convertRequestMetadata(request);
1219 private static final int[] sAllowedTemplates = {
1220 CameraDevice.TEMPLATE_PREVIEW,
1221 CameraDevice.TEMPLATE_STILL_CAPTURE,
1222 CameraDevice.TEMPLATE_RECORD,
1223 // Disallowed templates in legacy mode:
1224 // CameraDevice.TEMPLATE_VIDEO_SNAPSHOT,
1225 // CameraDevice.TEMPLATE_ZERO_SHUTTER_LAG,
1226 // CameraDevice.TEMPLATE_MANUAL
1230 * Create a request template
1232 * @param c a non-{@code null} camera characteristics for this camera
1233 * @param templateId a non-negative template ID
1235 * @return a non-{@code null} request template
1237 * @throws IllegalArgumentException if {@code templateId} was invalid
1239 * @see android.hardware.camera2.CameraDevice#TEMPLATE_MANUAL
1241 public static CameraMetadataNative createRequestTemplate(
1242 CameraCharacteristics c, int templateId) {
1243 if (!ArrayUtils.contains(sAllowedTemplates, templateId)) {
1244 throw new IllegalArgumentException("templateId out of range");
1247 CameraMetadataNative m = new CameraMetadataNative();
1250 * NOTE: If adding new code here and it needs to query the static info,
1251 * query the camera characteristics, so we can reuse this for api2 code later
1252 * to create our own templates in the framework
1260 m.set(CaptureRequest.CONTROL_AWB_MODE, CameraMetadata.CONTROL_AWB_MODE_AUTO);
1261 // AWB is always unconditionally available in API1 devices
1263 // control.aeAntibandingMode
1264 m.set(CaptureRequest.CONTROL_AE_ANTIBANDING_MODE, CONTROL_AE_ANTIBANDING_MODE_AUTO);
1266 // control.aeExposureCompensation
1267 m.set(CaptureRequest.CONTROL_AE_EXPOSURE_COMPENSATION, 0);
1270 m.set(CaptureRequest.CONTROL_AE_LOCK, false);
1272 // control.aePrecaptureTrigger
1273 m.set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER, CONTROL_AE_PRECAPTURE_TRIGGER_IDLE);
1275 // control.afTrigger
1276 m.set(CaptureRequest.CONTROL_AF_TRIGGER, CONTROL_AF_TRIGGER_IDLE);
1279 m.set(CaptureRequest.CONTROL_AWB_MODE, CONTROL_AWB_MODE_AUTO);
1282 m.set(CaptureRequest.CONTROL_AWB_LOCK, false);
1284 // control.aeRegions, control.awbRegions, control.afRegions
1286 Rect activeArray = c.get(SENSOR_INFO_ACTIVE_ARRAY_SIZE);
1287 MeteringRectangle[] activeRegions = new MeteringRectangle[] {
1288 new MeteringRectangle(/*x*/0, /*y*/0, /*width*/activeArray.width() - 1,
1289 /*height*/activeArray.height() - 1,/*weight*/0)};
1290 m.set(CaptureRequest.CONTROL_AE_REGIONS, activeRegions);
1291 m.set(CaptureRequest.CONTROL_AWB_REGIONS, activeRegions);
1292 m.set(CaptureRequest.CONTROL_AF_REGIONS, activeRegions);
1295 // control.captureIntent
1298 switch (templateId) {
1299 case CameraDevice.TEMPLATE_PREVIEW:
1300 captureIntent = CONTROL_CAPTURE_INTENT_PREVIEW;
1302 case CameraDevice.TEMPLATE_STILL_CAPTURE:
1303 captureIntent = CONTROL_CAPTURE_INTENT_STILL_CAPTURE;
1305 case CameraDevice.TEMPLATE_RECORD:
1306 captureIntent = CONTROL_CAPTURE_INTENT_VIDEO_RECORD;
1309 // Can't get anything else since it's guarded by the IAE check
1310 throw new AssertionError("Impossible; keep in sync with sAllowedTemplates");
1312 m.set(CaptureRequest.CONTROL_CAPTURE_INTENT, captureIntent);
1316 m.set(CaptureRequest.CONTROL_AE_MODE, CameraMetadata.CONTROL_AE_MODE_ON);
1317 // AE is always unconditionally available in API1 devices
1320 m.set(CaptureRequest.CONTROL_MODE, CONTROL_MODE_AUTO);
1324 Float minimumFocusDistance = c.get(LENS_INFO_MINIMUM_FOCUS_DISTANCE);
1327 if (minimumFocusDistance != null &&
1328 minimumFocusDistance == LENS_INFO_MINIMUM_FOCUS_DISTANCE_FIXED_FOCUS) {
1329 // Cannot control auto-focus with fixed-focus cameras
1330 afMode = CameraMetadata.CONTROL_AF_MODE_OFF;
1332 // If a minimum focus distance is reported; the camera must have AF
1333 afMode = CameraMetadata.CONTROL_AF_MODE_AUTO;
1335 if (templateId == CameraDevice.TEMPLATE_RECORD ||
1336 templateId == CameraDevice.TEMPLATE_VIDEO_SNAPSHOT) {
1337 if (ArrayUtils.contains(c.get(CONTROL_AF_AVAILABLE_MODES),
1338 CONTROL_AF_MODE_CONTINUOUS_VIDEO)) {
1339 afMode = CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_VIDEO;
1341 } else if (templateId == CameraDevice.TEMPLATE_PREVIEW ||
1342 templateId == CameraDevice.TEMPLATE_STILL_CAPTURE) {
1343 if (ArrayUtils.contains(c.get(CONTROL_AF_AVAILABLE_MODES),
1344 CONTROL_AF_MODE_CONTINUOUS_PICTURE)) {
1345 afMode = CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE;
1351 Log.v(TAG, "createRequestTemplate (templateId=" + templateId + ")," +
1352 " afMode=" + afMode + ", minimumFocusDistance=" + minimumFocusDistance);
1355 m.set(CaptureRequest.CONTROL_AF_MODE, afMode);
1359 // control.aeTargetFpsRange
1360 Range<Integer>[] availableFpsRange = c.
1361 get(CameraCharacteristics.CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES);
1363 // Pick FPS range with highest max value, tiebreak on higher min value
1364 Range<Integer> bestRange = availableFpsRange[0];
1365 for (Range<Integer> r : availableFpsRange) {
1366 if (bestRange.getUpper() < r.getUpper()) {
1368 } else if (bestRange.getUpper() == r.getUpper() &&
1369 bestRange.getLower() < r.getLower()) {
1373 m.set(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE, bestRange);
1376 // control.sceneMode -- DISABLED is always available
1377 m.set(CaptureRequest.CONTROL_SCENE_MODE, CONTROL_SCENE_MODE_DISABLED);
1383 // statistics.faceDetectMode
1384 m.set(CaptureRequest.STATISTICS_FACE_DETECT_MODE, STATISTICS_FACE_DETECT_MODE_OFF);
1391 m.set(CaptureRequest.FLASH_MODE, FLASH_MODE_OFF);
1396 if (templateId == CameraDevice.TEMPLATE_STILL_CAPTURE) {
1397 m.set(CaptureRequest.NOISE_REDUCTION_MODE, NOISE_REDUCTION_MODE_HIGH_QUALITY);
1399 m.set(CaptureRequest.NOISE_REDUCTION_MODE, NOISE_REDUCTION_MODE_FAST);
1405 if (templateId == CameraDevice.TEMPLATE_STILL_CAPTURE) {
1406 m.set(CaptureRequest.COLOR_CORRECTION_ABERRATION_MODE,
1407 COLOR_CORRECTION_ABERRATION_MODE_HIGH_QUALITY);
1409 m.set(CaptureRequest.COLOR_CORRECTION_ABERRATION_MODE,
1410 COLOR_CORRECTION_ABERRATION_MODE_FAST);
1418 m.set(CaptureRequest.LENS_FOCAL_LENGTH,
1419 c.get(CameraCharacteristics.LENS_INFO_AVAILABLE_FOCAL_LENGTHS)[0]);
1425 // jpeg.thumbnailSize - set smallest non-zero size if possible
1426 Size[] sizes = c.get(CameraCharacteristics.JPEG_AVAILABLE_THUMBNAIL_SIZES);
1427 m.set(CaptureRequest.JPEG_THUMBNAIL_SIZE, (sizes.length > 1) ? sizes[1] : sizes[0]);
1429 // TODO: map other request template values
1433 private static int[] getTagsForKeys(Key<?>[] keys) {
1434 int[] tags = new int[keys.length];
1436 for (int i = 0; i < keys.length; ++i) {
1437 tags[i] = keys[i].getNativeKey().getTag();
1443 private static int[] getTagsForKeys(CaptureRequest.Key<?>[] keys) {
1444 int[] tags = new int[keys.length];
1446 for (int i = 0; i < keys.length; ++i) {
1447 tags[i] = keys[i].getNativeKey().getTag();
1453 private static int[] getTagsForKeys(CaptureResult.Key<?>[] keys) {
1454 int[] tags = new int[keys.length];
1456 for (int i = 0; i < keys.length; ++i) {
1457 tags[i] = keys[i].getNativeKey().getTag();
1464 * Convert the requested AF mode into its equivalent supported parameter.
1466 * @param mode {@code CONTROL_AF_MODE}
1467 * @param supportedFocusModes list of camera1's supported focus modes
1468 * @return the stringified af mode, or {@code null} if its not supported
1470 static String convertAfModeToLegacy(int mode, List<String> supportedFocusModes) {
1471 if (supportedFocusModes == null || supportedFocusModes.isEmpty()) {
1472 Log.w(TAG, "No focus modes supported; API1 bug");
1476 String param = null;
1478 case CONTROL_AF_MODE_AUTO:
1479 param = Parameters.FOCUS_MODE_AUTO;
1481 case CONTROL_AF_MODE_CONTINUOUS_PICTURE:
1482 param = Parameters.FOCUS_MODE_CONTINUOUS_PICTURE;
1484 case CONTROL_AF_MODE_CONTINUOUS_VIDEO:
1485 param = Parameters.FOCUS_MODE_CONTINUOUS_VIDEO;
1487 case CONTROL_AF_MODE_EDOF:
1488 param = Parameters.FOCUS_MODE_EDOF;
1490 case CONTROL_AF_MODE_MACRO:
1491 param = Parameters.FOCUS_MODE_MACRO;
1493 case CONTROL_AF_MODE_OFF:
1494 if (supportedFocusModes.contains(Parameters.FOCUS_MODE_FIXED)) {
1495 param = Parameters.FOCUS_MODE_FIXED;
1497 param = Parameters.FOCUS_MODE_INFINITY;
1501 if (!supportedFocusModes.contains(param)) {
1502 // Weed out bad user input by setting to the first arbitrary focus mode
1503 String defaultMode = supportedFocusModes.get(0);
1506 "convertAfModeToLegacy - ignoring unsupported mode %d, " +
1507 "defaulting to %s", mode, defaultMode));
1508 param = defaultMode;