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