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