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