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.FLASH_INFO_AVAILABLE , 775 CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL , 776 CameraCharacteristics.JPEG_AVAILABLE_THUMBNAIL_SIZES , 777 CameraCharacteristics.LENS_FACING , 778 CameraCharacteristics.LENS_INFO_AVAILABLE_FOCAL_LENGTHS , 779 CameraCharacteristics.NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES , 780 CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES , 781 CameraCharacteristics.REQUEST_MAX_NUM_OUTPUT_STREAMS , 782 CameraCharacteristics.REQUEST_PARTIAL_RESULT_COUNT , 783 CameraCharacteristics.REQUEST_PIPELINE_MAX_DEPTH , 784 CameraCharacteristics.SCALER_AVAILABLE_MAX_DIGITAL_ZOOM , 785 // CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP , 786 CameraCharacteristics.SCALER_CROPPING_TYPE , 787 CameraCharacteristics.SENSOR_AVAILABLE_TEST_PATTERN_MODES , 788 CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE , 789 CameraCharacteristics.SENSOR_INFO_PHYSICAL_SIZE , 790 CameraCharacteristics.SENSOR_INFO_PIXEL_ARRAY_SIZE , 791 CameraCharacteristics.SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE , 792 CameraCharacteristics.SENSOR_INFO_TIMESTAMP_SOURCE , 793 CameraCharacteristics.SENSOR_ORIENTATION , 794 CameraCharacteristics.STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES , 795 CameraCharacteristics.STATISTICS_INFO_MAX_FACE_COUNT , 796 CameraCharacteristics.SYNC_MAX_LATENCY , 797 }; 798 List<Key<?>> characteristicsKeys = new ArrayList<>(Arrays.asList(availableKeys)); 799 800 /* 801 * Add the conditional keys 802 */ 803 if (m.get(LENS_INFO_MINIMUM_FOCUS_DISTANCE) != null) { 804 characteristicsKeys.add(LENS_INFO_MINIMUM_FOCUS_DISTANCE); 805 } 806 807 m.set(REQUEST_AVAILABLE_CHARACTERISTICS_KEYS, 808 getTagsForKeys(characteristicsKeys.toArray(new Key<?>[0]))); 809 } 810 811 /* 812 * request.availableRequestKeys 813 */ 814 { 815 CaptureRequest.Key<?> defaultAvailableKeys[] = new CaptureRequest.Key<?>[] { 816 CaptureRequest.COLOR_CORRECTION_ABERRATION_MODE, 817 CaptureRequest.CONTROL_AE_ANTIBANDING_MODE, 818 CaptureRequest.CONTROL_AE_EXPOSURE_COMPENSATION, 819 CaptureRequest.CONTROL_AE_LOCK, 820 CaptureRequest.CONTROL_AE_MODE, 821 CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE, 822 CaptureRequest.CONTROL_AF_MODE, 823 CaptureRequest.CONTROL_AF_TRIGGER, 824 CaptureRequest.CONTROL_AWB_LOCK, 825 CaptureRequest.CONTROL_AWB_MODE, 826 CaptureRequest.CONTROL_CAPTURE_INTENT, 827 CaptureRequest.CONTROL_EFFECT_MODE, 828 CaptureRequest.CONTROL_MODE, 829 CaptureRequest.CONTROL_SCENE_MODE, 830 CaptureRequest.CONTROL_VIDEO_STABILIZATION_MODE, 831 CaptureRequest.FLASH_MODE, 832 CaptureRequest.JPEG_GPS_COORDINATES, 833 CaptureRequest.JPEG_GPS_PROCESSING_METHOD, 834 CaptureRequest.JPEG_GPS_TIMESTAMP, 835 CaptureRequest.JPEG_ORIENTATION, 836 CaptureRequest.JPEG_QUALITY, 837 CaptureRequest.JPEG_THUMBNAIL_QUALITY, 838 CaptureRequest.JPEG_THUMBNAIL_SIZE, 839 CaptureRequest.LENS_FOCAL_LENGTH, 840 CaptureRequest.NOISE_REDUCTION_MODE, 841 CaptureRequest.SCALER_CROP_REGION, 842 CaptureRequest.STATISTICS_FACE_DETECT_MODE, 843 }; 844 ArrayList<CaptureRequest.Key<?>> availableKeys = 845 new ArrayList<CaptureRequest.Key<?>>(Arrays.asList(defaultAvailableKeys)); 846 847 if (p.getMaxNumMeteringAreas() > 0) { 848 availableKeys.add(CaptureRequest.CONTROL_AE_REGIONS); 849 } 850 if (p.getMaxNumFocusAreas() > 0) { 851 availableKeys.add(CaptureRequest.CONTROL_AF_REGIONS); 852 } 853 854 CaptureRequest.Key<?> availableRequestKeys[] = 855 new CaptureRequest.Key<?>[availableKeys.size()]; 856 availableKeys.toArray(availableRequestKeys); 857 m.set(REQUEST_AVAILABLE_REQUEST_KEYS, getTagsForKeys(availableRequestKeys)); 858 } 859 860 /* 861 * request.availableResultKeys 862 */ 863 { 864 CaptureResult.Key<?> defaultAvailableKeys[] = new CaptureResult.Key<?>[] { 865 CaptureResult.COLOR_CORRECTION_ABERRATION_MODE , 866 CaptureResult.CONTROL_AE_ANTIBANDING_MODE , 867 CaptureResult.CONTROL_AE_EXPOSURE_COMPENSATION , 868 CaptureResult.CONTROL_AE_LOCK , 869 CaptureResult.CONTROL_AE_MODE , 870 CaptureResult.CONTROL_AF_MODE , 871 CaptureResult.CONTROL_AF_STATE , 872 CaptureResult.CONTROL_AWB_MODE , 873 CaptureResult.CONTROL_AWB_LOCK , 874 CaptureResult.CONTROL_MODE , 875 CaptureResult.FLASH_MODE , 876 CaptureResult.JPEG_GPS_COORDINATES , 877 CaptureResult.JPEG_GPS_PROCESSING_METHOD , 878 CaptureResult.JPEG_GPS_TIMESTAMP , 879 CaptureResult.JPEG_ORIENTATION , 880 CaptureResult.JPEG_QUALITY , 881 CaptureResult.JPEG_THUMBNAIL_QUALITY , 882 CaptureResult.LENS_FOCAL_LENGTH , 883 CaptureResult.NOISE_REDUCTION_MODE , 884 CaptureResult.REQUEST_PIPELINE_DEPTH , 885 CaptureResult.SCALER_CROP_REGION , 886 CaptureResult.SENSOR_TIMESTAMP , 887 CaptureResult.STATISTICS_FACE_DETECT_MODE , 888 // CaptureResult.STATISTICS_FACES , 889 }; 890 List<CaptureResult.Key<?>> availableKeys = 891 new ArrayList<CaptureResult.Key<?>>(Arrays.asList(defaultAvailableKeys)); 892 893 if (p.getMaxNumMeteringAreas() > 0) { 894 availableKeys.add(CaptureResult.CONTROL_AE_REGIONS); 895 } 896 if (p.getMaxNumFocusAreas() > 0) { 897 availableKeys.add(CaptureResult.CONTROL_AF_REGIONS); 898 } 899 900 CaptureResult.Key<?> availableResultKeys[] = 901 new CaptureResult.Key<?>[availableKeys.size()]; 902 availableKeys.toArray(availableResultKeys); 903 m.set(REQUEST_AVAILABLE_RESULT_KEYS, getTagsForKeys(availableResultKeys)); 904 } 905 906 /* 907 * request.maxNumOutputStreams 908 */ 909 int[] outputStreams = { 910 /* RAW */ 911 REQUEST_MAX_NUM_OUTPUT_STREAMS_COUNT_RAW, 912 /* Processed & Not-Stalling */ 913 REQUEST_MAX_NUM_OUTPUT_STREAMS_COUNT_PROC, 914 /* Processed & Stalling */ 915 REQUEST_MAX_NUM_OUTPUT_STREAMS_COUNT_PROC_STALL, 916 }; 917 m.set(REQUEST_MAX_NUM_OUTPUT_STREAMS, outputStreams); 918 919 /* 920 * request.maxNumInputStreams 921 */ 922 m.set(REQUEST_MAX_NUM_INPUT_STREAMS, REQUEST_MAX_NUM_INPUT_STREAMS_COUNT); 923 924 /* 925 * request.partialResultCount 926 */ 927 m.set(REQUEST_PARTIAL_RESULT_COUNT, 1); // No partial results supported 928 929 /* 930 * request.pipelineMaxDepth 931 */ 932 m.set(REQUEST_PIPELINE_MAX_DEPTH, 933 (byte)(REQUEST_PIPELINE_MAX_DEPTH_HAL1 + REQUEST_PIPELINE_MAX_DEPTH_OURS)); 934 } 935 mapScaler(CameraMetadataNative m, Parameters p)936 private static void mapScaler(CameraMetadataNative m, Parameters p) { 937 /* 938 * scaler.availableMaxDigitalZoom 939 */ 940 m.set(SCALER_AVAILABLE_MAX_DIGITAL_ZOOM, ParameterUtils.getMaxZoomRatio(p)); 941 942 /* 943 * scaler.croppingType = CENTER_ONLY 944 */ 945 m.set(SCALER_CROPPING_TYPE, SCALER_CROPPING_TYPE_CENTER_ONLY); 946 } 947 mapSensor(CameraMetadataNative m, Parameters p)948 private static void mapSensor(CameraMetadataNative m, Parameters p) { 949 // Use the largest jpeg size (by area) for both active array and pixel array 950 Size largestJpegSize = getLargestSupportedJpegSizeByArea(p); 951 /* 952 * sensor.info.activeArraySize, and preCorrectionActiveArraySize 953 */ 954 { 955 Rect activeArrayRect = ParamsUtils.createRect(largestJpegSize); 956 m.set(SENSOR_INFO_ACTIVE_ARRAY_SIZE, activeArrayRect); 957 m.set(SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE, activeArrayRect); 958 } 959 960 /* 961 * sensor.availableTestPatternModes 962 */ 963 { 964 // Only "OFF" test pattern mode is available 965 m.set(SENSOR_AVAILABLE_TEST_PATTERN_MODES, new int[] { SENSOR_TEST_PATTERN_MODE_OFF }); 966 } 967 968 /* 969 * sensor.info.pixelArraySize 970 */ 971 m.set(SENSOR_INFO_PIXEL_ARRAY_SIZE, largestJpegSize); 972 973 /* 974 * sensor.info.physicalSize 975 */ 976 { 977 /* 978 * Assume focal length is at infinity focus and that the lens is rectilinear. 979 */ 980 float focalLength = p.getFocalLength(); // in mm 981 double angleHor = p.getHorizontalViewAngle() * Math.PI / 180; // to radians 982 double angleVer = p.getVerticalViewAngle() * Math.PI / 180; // to radians 983 984 float height = (float)Math.abs(2 * focalLength * Math.tan(angleVer / 2)); 985 float width = (float)Math.abs(2 * focalLength * Math.tan(angleHor / 2)); 986 987 m.set(SENSOR_INFO_PHYSICAL_SIZE, new SizeF(width, height)); // in mm 988 } 989 990 /* 991 * sensor.info.timestampSource 992 */ 993 { 994 m.set(SENSOR_INFO_TIMESTAMP_SOURCE, SENSOR_INFO_TIMESTAMP_SOURCE_UNKNOWN); 995 } 996 } 997 mapStatistics(CameraMetadataNative m, Parameters p)998 private static void mapStatistics(CameraMetadataNative m, Parameters p) { 999 /* 1000 * statistics.info.availableFaceDetectModes 1001 */ 1002 int[] fdModes; 1003 1004 if (p.getMaxNumDetectedFaces() > 0) { 1005 fdModes = new int[] { 1006 STATISTICS_FACE_DETECT_MODE_OFF, 1007 STATISTICS_FACE_DETECT_MODE_SIMPLE 1008 // FULL is never-listed, since we have no way to query it statically 1009 }; 1010 } else { 1011 fdModes = new int[] { 1012 STATISTICS_FACE_DETECT_MODE_OFF 1013 }; 1014 } 1015 m.set(STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES, fdModes); 1016 1017 /* 1018 * statistics.info.maxFaceCount 1019 */ 1020 m.set(STATISTICS_INFO_MAX_FACE_COUNT, p.getMaxNumDetectedFaces()); 1021 } 1022 mapSync(CameraMetadataNative m, Parameters p)1023 private static void mapSync(CameraMetadataNative m, Parameters p) { 1024 /* 1025 * sync.maxLatency 1026 */ 1027 m.set(SYNC_MAX_LATENCY, SYNC_MAX_LATENCY_UNKNOWN); 1028 } 1029 appendStreamConfig( ArrayList<StreamConfiguration> configs, int format, List<Camera.Size> sizes)1030 private static void appendStreamConfig( 1031 ArrayList<StreamConfiguration> configs, int format, List<Camera.Size> sizes) { 1032 for (Camera.Size size : sizes) { 1033 StreamConfiguration config = 1034 new StreamConfiguration(format, size.width, size.height, /*input*/false); 1035 configs.add(config); 1036 } 1037 } 1038 1039 private final static String[] sLegacySceneModes = { 1040 Parameters.SCENE_MODE_AUTO, 1041 Parameters.SCENE_MODE_ACTION, 1042 Parameters.SCENE_MODE_PORTRAIT, 1043 Parameters.SCENE_MODE_LANDSCAPE, 1044 Parameters.SCENE_MODE_NIGHT, 1045 Parameters.SCENE_MODE_NIGHT_PORTRAIT, 1046 Parameters.SCENE_MODE_THEATRE, 1047 Parameters.SCENE_MODE_BEACH, 1048 Parameters.SCENE_MODE_SNOW, 1049 Parameters.SCENE_MODE_SUNSET, 1050 Parameters.SCENE_MODE_STEADYPHOTO, 1051 Parameters.SCENE_MODE_FIREWORKS, 1052 Parameters.SCENE_MODE_SPORTS, 1053 Parameters.SCENE_MODE_PARTY, 1054 Parameters.SCENE_MODE_CANDLELIGHT, 1055 Parameters.SCENE_MODE_BARCODE, 1056 Parameters.SCENE_MODE_HDR, 1057 }; 1058 1059 private final static int[] sSceneModes = { 1060 CameraCharacteristics.CONTROL_SCENE_MODE_DISABLED, 1061 CameraCharacteristics.CONTROL_SCENE_MODE_ACTION, 1062 CameraCharacteristics.CONTROL_SCENE_MODE_PORTRAIT, 1063 CameraCharacteristics.CONTROL_SCENE_MODE_LANDSCAPE, 1064 CameraCharacteristics.CONTROL_SCENE_MODE_NIGHT, 1065 CameraCharacteristics.CONTROL_SCENE_MODE_NIGHT_PORTRAIT, 1066 CameraCharacteristics.CONTROL_SCENE_MODE_THEATRE, 1067 CameraCharacteristics.CONTROL_SCENE_MODE_BEACH, 1068 CameraCharacteristics.CONTROL_SCENE_MODE_SNOW, 1069 CameraCharacteristics.CONTROL_SCENE_MODE_SUNSET, 1070 CameraCharacteristics.CONTROL_SCENE_MODE_STEADYPHOTO, 1071 CameraCharacteristics.CONTROL_SCENE_MODE_FIREWORKS, 1072 CameraCharacteristics.CONTROL_SCENE_MODE_SPORTS, 1073 CameraCharacteristics.CONTROL_SCENE_MODE_PARTY, 1074 CameraCharacteristics.CONTROL_SCENE_MODE_CANDLELIGHT, 1075 CameraCharacteristics.CONTROL_SCENE_MODE_BARCODE, 1076 CameraCharacteristics.CONTROL_SCENE_MODE_HDR, 1077 }; 1078 convertSceneModeFromLegacy(String mode)1079 static int convertSceneModeFromLegacy(String mode) { 1080 if (mode == null) { 1081 return CameraCharacteristics.CONTROL_SCENE_MODE_DISABLED; 1082 } 1083 int index = ArrayUtils.getArrayIndex(sLegacySceneModes, mode); 1084 if (index < 0) { 1085 return UNKNOWN_MODE; 1086 } 1087 return sSceneModes[index]; 1088 } 1089 convertSceneModeToLegacy(int mode)1090 static String convertSceneModeToLegacy(int mode) { 1091 if (mode == CONTROL_SCENE_MODE_FACE_PRIORITY) { 1092 // OK: Let LegacyFaceDetectMapper handle turning face detection on/off 1093 return Parameters.SCENE_MODE_AUTO; 1094 } 1095 1096 int index = ArrayUtils.getArrayIndex(sSceneModes, mode); 1097 if (index < 0) { 1098 return null; 1099 } 1100 return sLegacySceneModes[index]; 1101 } 1102 1103 private final static String[] sLegacyEffectMode = { 1104 Parameters.EFFECT_NONE, 1105 Parameters.EFFECT_MONO, 1106 Parameters.EFFECT_NEGATIVE, 1107 Parameters.EFFECT_SOLARIZE, 1108 Parameters.EFFECT_SEPIA, 1109 Parameters.EFFECT_POSTERIZE, 1110 Parameters.EFFECT_WHITEBOARD, 1111 Parameters.EFFECT_BLACKBOARD, 1112 Parameters.EFFECT_AQUA, 1113 }; 1114 1115 private final static int[] sEffectModes = { 1116 CameraCharacteristics.CONTROL_EFFECT_MODE_OFF, 1117 CameraCharacteristics.CONTROL_EFFECT_MODE_MONO, 1118 CameraCharacteristics.CONTROL_EFFECT_MODE_NEGATIVE, 1119 CameraCharacteristics.CONTROL_EFFECT_MODE_SOLARIZE, 1120 CameraCharacteristics.CONTROL_EFFECT_MODE_SEPIA, 1121 CameraCharacteristics.CONTROL_EFFECT_MODE_POSTERIZE, 1122 CameraCharacteristics.CONTROL_EFFECT_MODE_WHITEBOARD, 1123 CameraCharacteristics.CONTROL_EFFECT_MODE_BLACKBOARD, 1124 CameraCharacteristics.CONTROL_EFFECT_MODE_AQUA, 1125 }; 1126 convertEffectModeFromLegacy(String mode)1127 static int convertEffectModeFromLegacy(String mode) { 1128 if (mode == null) { 1129 return CameraCharacteristics.CONTROL_EFFECT_MODE_OFF; 1130 } 1131 int index = ArrayUtils.getArrayIndex(sLegacyEffectMode, mode); 1132 if (index < 0) { 1133 return UNKNOWN_MODE; 1134 } 1135 return sEffectModes[index]; 1136 } 1137 convertEffectModeToLegacy(int mode)1138 static String convertEffectModeToLegacy(int mode) { 1139 int index = ArrayUtils.getArrayIndex(sEffectModes, mode); 1140 if (index < 0) { 1141 return null; 1142 } 1143 return sLegacyEffectMode[index]; 1144 } 1145 1146 /** 1147 * Convert the ae antibanding mode from api1 into api2. 1148 * 1149 * @param mode the api1 mode, {@code null} is allowed and will return {@code -1}. 1150 * 1151 * @return The api2 value, or {@code -1} by default if conversion failed 1152 */ convertAntiBandingMode(String mode)1153 private static int convertAntiBandingMode(String mode) { 1154 if (mode == null) { 1155 return -1; 1156 } 1157 1158 switch (mode) { 1159 case Camera.Parameters.ANTIBANDING_OFF: { 1160 return CONTROL_AE_ANTIBANDING_MODE_OFF; 1161 } 1162 case Camera.Parameters.ANTIBANDING_50HZ: { 1163 return CONTROL_AE_ANTIBANDING_MODE_50HZ; 1164 } 1165 case Camera.Parameters.ANTIBANDING_60HZ: { 1166 return CONTROL_AE_ANTIBANDING_MODE_60HZ; 1167 } 1168 case Camera.Parameters.ANTIBANDING_AUTO: { 1169 return CONTROL_AE_ANTIBANDING_MODE_AUTO; 1170 } 1171 default: { 1172 Log.w(TAG, "convertAntiBandingMode - Unknown antibanding mode " + mode); 1173 return -1; 1174 } 1175 } 1176 } 1177 1178 /** 1179 * Convert the ae antibanding mode from api1 into api2. 1180 * 1181 * @param mode the api1 mode, {@code null} is allowed and will return {@code MODE_OFF}. 1182 * 1183 * @return The api2 value, or {@code MODE_OFF} by default if conversion failed 1184 */ convertAntiBandingModeOrDefault(String mode)1185 static int convertAntiBandingModeOrDefault(String mode) { 1186 int antiBandingMode = convertAntiBandingMode(mode); 1187 if (antiBandingMode == -1) { 1188 return CONTROL_AE_ANTIBANDING_MODE_OFF; 1189 } 1190 1191 return antiBandingMode; 1192 } 1193 convertAeFpsRangeToLegacy(Range<Integer> fpsRange)1194 private static int[] convertAeFpsRangeToLegacy(Range<Integer> fpsRange) { 1195 int[] legacyFps = new int[2]; 1196 legacyFps[Camera.Parameters.PREVIEW_FPS_MIN_INDEX] = fpsRange.getLower(); 1197 legacyFps[Camera.Parameters.PREVIEW_FPS_MAX_INDEX] = fpsRange.getUpper(); 1198 return legacyFps; 1199 } 1200 1201 /** 1202 * Return the stall duration for a given output jpeg size in nanoseconds. 1203 * 1204 * <p>An 8mp image is chosen to have a stall duration of 0.8 seconds.</p> 1205 */ calculateJpegStallDuration(Camera.Size size)1206 private static long calculateJpegStallDuration(Camera.Size size) { 1207 long baseDuration = APPROXIMATE_CAPTURE_DELAY_MS * NS_PER_MS; // 200ms for capture 1208 long area = size.width * (long) size.height; 1209 long stallPerArea = APPROXIMATE_JPEG_ENCODE_TIME_MS * NS_PER_MS / 1210 APPROXIMATE_SENSOR_AREA_PX; // 600ms stall for 8mp 1211 return baseDuration + area * stallPerArea; 1212 } 1213 1214 /** 1215 * Set the legacy parameters using the {@link LegacyRequest legacy request}. 1216 * 1217 * <p>The legacy request's parameters are changed as a side effect of calling this 1218 * method.</p> 1219 * 1220 * @param request a non-{@code null} legacy request 1221 */ convertRequestMetadata(LegacyRequest request)1222 public static void convertRequestMetadata(LegacyRequest request) { 1223 LegacyRequestMapper.convertRequestMetadata(request); 1224 } 1225 1226 private static final int[] sAllowedTemplates = { 1227 CameraDevice.TEMPLATE_PREVIEW, 1228 CameraDevice.TEMPLATE_STILL_CAPTURE, 1229 CameraDevice.TEMPLATE_RECORD, 1230 // Disallowed templates in legacy mode: 1231 // CameraDevice.TEMPLATE_VIDEO_SNAPSHOT, 1232 // CameraDevice.TEMPLATE_ZERO_SHUTTER_LAG, 1233 // CameraDevice.TEMPLATE_MANUAL 1234 }; 1235 1236 /** 1237 * Create a request template 1238 * 1239 * @param c a non-{@code null} camera characteristics for this camera 1240 * @param templateId a non-negative template ID 1241 * 1242 * @return a non-{@code null} request template 1243 * 1244 * @throws IllegalArgumentException if {@code templateId} was invalid 1245 * 1246 * @see android.hardware.camera2.CameraDevice#TEMPLATE_MANUAL 1247 */ createRequestTemplate( CameraCharacteristics c, int templateId)1248 public static CameraMetadataNative createRequestTemplate( 1249 CameraCharacteristics c, int templateId) { 1250 if (!ArrayUtils.contains(sAllowedTemplates, templateId)) { 1251 throw new IllegalArgumentException("templateId out of range"); 1252 } 1253 1254 CameraMetadataNative m = new CameraMetadataNative(); 1255 1256 /* 1257 * NOTE: If adding new code here and it needs to query the static info, 1258 * query the camera characteristics, so we can reuse this for api2 code later 1259 * to create our own templates in the framework 1260 */ 1261 1262 /* 1263 * control.* 1264 */ 1265 1266 // control.awbMode 1267 m.set(CaptureRequest.CONTROL_AWB_MODE, CameraMetadata.CONTROL_AWB_MODE_AUTO); 1268 // AWB is always unconditionally available in API1 devices 1269 1270 // control.aeAntibandingMode 1271 m.set(CaptureRequest.CONTROL_AE_ANTIBANDING_MODE, CONTROL_AE_ANTIBANDING_MODE_AUTO); 1272 1273 // control.aeExposureCompensation 1274 m.set(CaptureRequest.CONTROL_AE_EXPOSURE_COMPENSATION, 0); 1275 1276 // control.aeLock 1277 m.set(CaptureRequest.CONTROL_AE_LOCK, false); 1278 1279 // control.aePrecaptureTrigger 1280 m.set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER, CONTROL_AE_PRECAPTURE_TRIGGER_IDLE); 1281 1282 // control.afTrigger 1283 m.set(CaptureRequest.CONTROL_AF_TRIGGER, CONTROL_AF_TRIGGER_IDLE); 1284 1285 // control.awbMode 1286 m.set(CaptureRequest.CONTROL_AWB_MODE, CONTROL_AWB_MODE_AUTO); 1287 1288 // control.awbLock 1289 m.set(CaptureRequest.CONTROL_AWB_LOCK, false); 1290 1291 // control.aeRegions, control.awbRegions, control.afRegions 1292 { 1293 Rect activeArray = c.get(SENSOR_INFO_ACTIVE_ARRAY_SIZE); 1294 MeteringRectangle[] activeRegions = new MeteringRectangle[] { 1295 new MeteringRectangle(/*x*/0, /*y*/0, /*width*/activeArray.width() - 1, 1296 /*height*/activeArray.height() - 1,/*weight*/0)}; 1297 m.set(CaptureRequest.CONTROL_AE_REGIONS, activeRegions); 1298 m.set(CaptureRequest.CONTROL_AWB_REGIONS, activeRegions); 1299 m.set(CaptureRequest.CONTROL_AF_REGIONS, activeRegions); 1300 } 1301 1302 // control.captureIntent 1303 { 1304 int captureIntent; 1305 switch (templateId) { 1306 case CameraDevice.TEMPLATE_PREVIEW: 1307 captureIntent = CONTROL_CAPTURE_INTENT_PREVIEW; 1308 break; 1309 case CameraDevice.TEMPLATE_STILL_CAPTURE: 1310 captureIntent = CONTROL_CAPTURE_INTENT_STILL_CAPTURE; 1311 break; 1312 case CameraDevice.TEMPLATE_RECORD: 1313 captureIntent = CONTROL_CAPTURE_INTENT_VIDEO_RECORD; 1314 break; 1315 default: 1316 // Can't get anything else since it's guarded by the IAE check 1317 throw new AssertionError("Impossible; keep in sync with sAllowedTemplates"); 1318 } 1319 m.set(CaptureRequest.CONTROL_CAPTURE_INTENT, captureIntent); 1320 } 1321 1322 // control.aeMode 1323 m.set(CaptureRequest.CONTROL_AE_MODE, CameraMetadata.CONTROL_AE_MODE_ON); 1324 // AE is always unconditionally available in API1 devices 1325 1326 // control.mode 1327 m.set(CaptureRequest.CONTROL_MODE, CONTROL_MODE_AUTO); 1328 1329 // control.afMode 1330 { 1331 Float minimumFocusDistance = c.get(LENS_INFO_MINIMUM_FOCUS_DISTANCE); 1332 1333 int afMode; 1334 if (minimumFocusDistance != null && 1335 minimumFocusDistance == LENS_INFO_MINIMUM_FOCUS_DISTANCE_FIXED_FOCUS) { 1336 // Cannot control auto-focus with fixed-focus cameras 1337 afMode = CameraMetadata.CONTROL_AF_MODE_OFF; 1338 } else { 1339 // If a minimum focus distance is reported; the camera must have AF 1340 afMode = CameraMetadata.CONTROL_AF_MODE_AUTO; 1341 1342 if (templateId == CameraDevice.TEMPLATE_RECORD || 1343 templateId == CameraDevice.TEMPLATE_VIDEO_SNAPSHOT) { 1344 if (ArrayUtils.contains(c.get(CONTROL_AF_AVAILABLE_MODES), 1345 CONTROL_AF_MODE_CONTINUOUS_VIDEO)) { 1346 afMode = CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_VIDEO; 1347 } 1348 } else if (templateId == CameraDevice.TEMPLATE_PREVIEW || 1349 templateId == CameraDevice.TEMPLATE_STILL_CAPTURE) { 1350 if (ArrayUtils.contains(c.get(CONTROL_AF_AVAILABLE_MODES), 1351 CONTROL_AF_MODE_CONTINUOUS_PICTURE)) { 1352 afMode = CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE; 1353 } 1354 } 1355 } 1356 1357 if (DEBUG) { 1358 Log.v(TAG, "createRequestTemplate (templateId=" + templateId + ")," + 1359 " afMode=" + afMode + ", minimumFocusDistance=" + minimumFocusDistance); 1360 } 1361 1362 m.set(CaptureRequest.CONTROL_AF_MODE, afMode); 1363 } 1364 1365 { 1366 // control.aeTargetFpsRange 1367 Range<Integer>[] availableFpsRange = c. 1368 get(CameraCharacteristics.CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES); 1369 1370 // Pick FPS range with highest max value, tiebreak on higher min value 1371 Range<Integer> bestRange = availableFpsRange[0]; 1372 for (Range<Integer> r : availableFpsRange) { 1373 if (bestRange.getUpper() < r.getUpper()) { 1374 bestRange = r; 1375 } else if (bestRange.getUpper() == r.getUpper() && 1376 bestRange.getLower() < r.getLower()) { 1377 bestRange = r; 1378 } 1379 } 1380 m.set(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE, bestRange); 1381 } 1382 1383 // control.sceneMode -- DISABLED is always available 1384 m.set(CaptureRequest.CONTROL_SCENE_MODE, CONTROL_SCENE_MODE_DISABLED); 1385 1386 /* 1387 * statistics.* 1388 */ 1389 1390 // statistics.faceDetectMode 1391 m.set(CaptureRequest.STATISTICS_FACE_DETECT_MODE, STATISTICS_FACE_DETECT_MODE_OFF); 1392 1393 /* 1394 * flash.* 1395 */ 1396 1397 // flash.mode 1398 m.set(CaptureRequest.FLASH_MODE, FLASH_MODE_OFF); 1399 1400 /* 1401 * noiseReduction.* 1402 */ 1403 if (templateId == CameraDevice.TEMPLATE_STILL_CAPTURE) { 1404 m.set(CaptureRequest.NOISE_REDUCTION_MODE, NOISE_REDUCTION_MODE_HIGH_QUALITY); 1405 } else { 1406 m.set(CaptureRequest.NOISE_REDUCTION_MODE, NOISE_REDUCTION_MODE_FAST); 1407 } 1408 1409 /* 1410 * colorCorrection.* 1411 */ 1412 if (templateId == CameraDevice.TEMPLATE_STILL_CAPTURE) { 1413 m.set(CaptureRequest.COLOR_CORRECTION_ABERRATION_MODE, 1414 COLOR_CORRECTION_ABERRATION_MODE_HIGH_QUALITY); 1415 } else { 1416 m.set(CaptureRequest.COLOR_CORRECTION_ABERRATION_MODE, 1417 COLOR_CORRECTION_ABERRATION_MODE_FAST); 1418 } 1419 1420 /* 1421 * lens.* 1422 */ 1423 1424 // lens.focalLength 1425 m.set(CaptureRequest.LENS_FOCAL_LENGTH, 1426 c.get(CameraCharacteristics.LENS_INFO_AVAILABLE_FOCAL_LENGTHS)[0]); 1427 1428 /* 1429 * jpeg.* 1430 */ 1431 1432 // jpeg.thumbnailSize - set smallest non-zero size if possible 1433 Size[] sizes = c.get(CameraCharacteristics.JPEG_AVAILABLE_THUMBNAIL_SIZES); 1434 m.set(CaptureRequest.JPEG_THUMBNAIL_SIZE, (sizes.length > 1) ? sizes[1] : sizes[0]); 1435 1436 // TODO: map other request template values 1437 return m; 1438 } 1439 getTagsForKeys(Key<?>[] keys)1440 private static int[] getTagsForKeys(Key<?>[] keys) { 1441 int[] tags = new int[keys.length]; 1442 1443 for (int i = 0; i < keys.length; ++i) { 1444 tags[i] = keys[i].getNativeKey().getTag(); 1445 } 1446 1447 return tags; 1448 } 1449 getTagsForKeys(CaptureRequest.Key<?>[] keys)1450 private static int[] getTagsForKeys(CaptureRequest.Key<?>[] keys) { 1451 int[] tags = new int[keys.length]; 1452 1453 for (int i = 0; i < keys.length; ++i) { 1454 tags[i] = keys[i].getNativeKey().getTag(); 1455 } 1456 1457 return tags; 1458 } 1459 getTagsForKeys(CaptureResult.Key<?>[] keys)1460 private static int[] getTagsForKeys(CaptureResult.Key<?>[] keys) { 1461 int[] tags = new int[keys.length]; 1462 1463 for (int i = 0; i < keys.length; ++i) { 1464 tags[i] = keys[i].getNativeKey().getTag(); 1465 } 1466 1467 return tags; 1468 } 1469 1470 /** 1471 * Convert the requested AF mode into its equivalent supported parameter. 1472 * 1473 * @param mode {@code CONTROL_AF_MODE} 1474 * @param supportedFocusModes list of camera1's supported focus modes 1475 * @return the stringified af mode, or {@code null} if its not supported 1476 */ convertAfModeToLegacy(int mode, List<String> supportedFocusModes)1477 static String convertAfModeToLegacy(int mode, List<String> supportedFocusModes) { 1478 if (supportedFocusModes == null || supportedFocusModes.isEmpty()) { 1479 Log.w(TAG, "No focus modes supported; API1 bug"); 1480 return null; 1481 } 1482 1483 String param = null; 1484 switch (mode) { 1485 case CONTROL_AF_MODE_AUTO: 1486 param = Parameters.FOCUS_MODE_AUTO; 1487 break; 1488 case CONTROL_AF_MODE_CONTINUOUS_PICTURE: 1489 param = Parameters.FOCUS_MODE_CONTINUOUS_PICTURE; 1490 break; 1491 case CONTROL_AF_MODE_CONTINUOUS_VIDEO: 1492 param = Parameters.FOCUS_MODE_CONTINUOUS_VIDEO; 1493 break; 1494 case CONTROL_AF_MODE_EDOF: 1495 param = Parameters.FOCUS_MODE_EDOF; 1496 break; 1497 case CONTROL_AF_MODE_MACRO: 1498 param = Parameters.FOCUS_MODE_MACRO; 1499 break; 1500 case CONTROL_AF_MODE_OFF: 1501 if (supportedFocusModes.contains(Parameters.FOCUS_MODE_FIXED)) { 1502 param = Parameters.FOCUS_MODE_FIXED; 1503 } else { 1504 param = Parameters.FOCUS_MODE_INFINITY; 1505 } 1506 } 1507 1508 if (!supportedFocusModes.contains(param)) { 1509 // Weed out bad user input by setting to the first arbitrary focus mode 1510 String defaultMode = supportedFocusModes.get(0); 1511 Log.w(TAG, 1512 String.format( 1513 "convertAfModeToLegacy - ignoring unsupported mode %d, " + 1514 "defaulting to %s", mode, defaultMode)); 1515 param = defaultMode; 1516 } 1517 1518 return param; 1519 } 1520 } 1521