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