Перейти к основному содержимому

Глава 12: Глубокое погружение в CameraCharacteristics

12.1 Технический паспорт в вашем кармане

Прежде чем вы сможете вызвать openCamera(), прежде чем вы сможете создать CaptureRequest, прежде чем вы сможете настроить сеанс — существует CameraCharacteristics. Это неизменяемое, не требующее питания окно во все, что может делать камера. Думайте об этом как о техническом паспорте камеры, представленном в виде структурированного объекта запроса.

CameraCharacteristics — ваш самый важный инструмент для написания приложений, которые работают на более чем 10 000 моделей устройств Android. Вы не можете просто предположить, что ручное ISO работает. Вы не можете предположить, что доступен RAW. Вы даже не можете предположить, что камера поддерживает предпросмотр в 1080p — пока не спросите у CameraCharacteristics.

В главе 6 мы коснулись основ: ориентации линз, размера сенсора, фокусного расстояния. В этом глубоком погружении мы пойдем гораздо дальше:

  • Пять уровней аппаратной поддержки (LEGACY → LIMITED → FULL → LEVEL_3 → EXTERNAL) и что гарантирует каждый из них.
  • Более десяти флагов возможностей (MANUAL_SENSOR, RAW, DEPTH_OUTPUT и т. д.) и какие уровни оборудования их предоставляют.
  • Как ключи метаданных организованы иерархически по подсистемам (android.sensor.*, android.lens.*, android.control.*, ...).
  • Как написать всеобъемлющий запрос возможностей во время выполнения с корректными откатами к базовым функциям.

Приложение Android Camera Parameters (GitHub, Play Store) — это, по сути, браузер CameraCharacteristics на стероидах. Откройте его для любой камеры, и вы увидите именно те ключи, которые мы обсуждаем в этой главе, организованные по категориям, с человекочитаемыми метками и визуализацией значений в реальном времени.

12.2 Что такое CameraCharacteristics на самом деле

Формально CameraCharacteristics — это:

  • Неизменяемый объект — после получения из CameraManager.getCameraCharacteristics(id) объект никогда не меняется (за одним задокументированным исключением: SENSOR_ORIENTATION для складных устройств в API 32+).
  • Не требует питания — запрос к нему не включает сенсор или ISP. Вы можете вызывать его в onCreate() вашей первой Activity без влияния на заряд батареи.
  • Индивидуален для каждой камеры — у каждого идентификатора логической камеры есть свой собственный объект CameraCharacteristics.
  • Типизированный доступ по ключам — данные считываются через <Key<T>> get(Key<T> key), где каждый ключ имеет документированный тип (Int, Long, Float, Rect, Array и т. д.).

Вы получаете его одним вызовом:

val cameraManager = getSystemService(CAMERA_SERVICE) as CameraManager
val cameraIdList = cameraManager.cameraIdList // например, ["0", "1", "2", "3"]

for (id in cameraIdList) {
val characteristics: CameraCharacteristics = cameraManager.getCameraCharacteristics(id)
// Делайте запросы — питание сенсора не используется!
}

В Android 15 (API 35) вы можете использовать CameraManager.getCameraDeviceSetup(id) для легковесных запросов конфигурации сеанса без открытия камеры (подробности о CameraDeviceSetup см. в главе 28).

12.3 Уровень оборудования: INFO_SUPPORTED_HARDWARE_LEVEL

Самым важным ключом в CameraCharacteristics является INFO_SUPPORTED_HARDWARE_LEVEL. Он определяет весь уровень Camera HAL и сообщает вам (в общих чертах), какие функции гарантированно будут работать. Существует пять уровней аппаратной поддержки:

Пять уровней аппаратной поддержки

УровеньКонстантаТипичные устройстваЧто это означает на практике
LEGACYINFO_SUPPORTED_HARDWARE_LEVEL_LEGACYБюджетные устройства до 2015 года, очень старые чипсетыAPI Camera2 является оберткой над старым API android.hardware.Camera. Нет покадрового управления, нет ручных настроек, RAW невозможен, серийная съемка ненадежна. Относитесь к этим устройствам как к «эпохе Camera1 с синтаксисом Camera2».
LIMITEDINFO_SUPPORTED_HARDWARE_LEVEL_LIMITEDБюджетные телефоны (Android Go, SoC начального уровня, такие как MediaTek Helio, Snapdragon 4xx)Нативный Camera2 HAL, но только с подмножеством функций. 3A (AF/AE/AWB) работает. Предпросмотр + JPEG работают. Но нет ручного управления сенсором, нет RAW, нет гарантированной серийной съемки, нет переобработки YUV. Это «базовый функциональный» уровень камеры Android.
FULLINFO_SUPPORTED_HARDWARE_LEVEL_FULLТелефоны среднего и флагманского уровня (Snapdragon 6xx/7xx/8xx, Exynos mid+, Dimensity 7xxx+)Уровень «профессиональной камеры». Гарантирует MANUAL_SENSOR, MANUAL_POST_PROCESSING, BURST_CAPTURE, покадровые настройки, 30 кадров в секунду в полном разрешении, RAW, все форматы вывода, предсказуемую глубину конвейера. То, что нужно для любого серьезного приложения камеры.
LEVEL_3INFO_SUPPORTED_HARDWARE_LEVEL_3Высококлассные флагманы с продвинутым ISP (Snapdragon 8 Gen 1+, Pixel 6+, Exynos 2xxx+)FULL + дополнительные возможности: переобработка YUV (поддержка входного потока, офлайн-переобработка), частная (private) переобработка, расширенная статистика, одновременный вывод аппаратного JPEG + RAW в максимальном разрешении. Требуется для ZSL с выводом в RAW.
EXTERNALINFO_SUPPORTED_HARDWARE_LEVEL_EXTERNALUSB-камеры, веб-камеры, подключенные через OTGВнешний Camera HAL. Ведет себя как LIMITED или FULL в зависимости от USB-устройства. Ключевой нюанс: камера может быть подключена/отключена в любое время, поэтому слушайте ACTION_CAMERA_DEVICE_STATE_CHANGED.
important

Уровень оборудования — это гарантия, а не флаг «по возможности». Если устройство сообщает о уровне FULL, Google CTS (Compatibility Test Suite) подтвердил, что каждая функция уровня FULL работает. Если устройство сообщает о LIMITED, вы не можете полагаться на функции уровня FULL — даже если они случайно заработают на одном конкретном устройстве LIMITED, они сломаются на другом.

Проверка уровня оборудования во время выполнения

val hardwareLevel = characteristics.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL)

when (hardwareLevel) {
CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY -> {
Log.w("CamCaps", "Оборудование LEGACY — ручное управление/RAW отключены. Откат к базовому JPEG.")
disableManualControls()
disableRawCapture()
}
CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED -> {
Log.i("CamCaps", "Оборудование LIMITED — только базовое фото + предпросмотр.")
disableManualControls()
disableRawCapture()
disableBurstCapture()
}
CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL -> {
Log.i("CamCaps", "Оборудование FULL — включение ручного управления, RAW и серийной съемки.")
enableManualControls()
enableRawCapture()
enableBurstCapture()
}
CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_3 -> {
Log.i("CamCaps", "Оборудование LEVEL_3 — FULL + переобработка + ZSL + расширенная статистика.")
enableManualControls()
enableRawCapture()
enableBurstCapture()
enableReprocessing()
enableZeroShutterLag()
}
CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_EXTERNAL -> {
Log.i("CamCaps", "Внешняя камера — может быть LIMITED или FULL; регистрация слушателя отключения.")
registerHotplugListener()
// Динамическая проверка возможностей вместо предположений
}
else -> {
Log.w("CamCaps", "Неизвестный уровень оборудования $hardwareLevel — принимаем LIMITED для безопасности.")
safeDefaultFeatures()
}
}

12.4 Возможности: REQUEST_AVAILABLE_CAPABILITIES

Уровень оборудования — это грубая градация. Для детального определения функций Camera2 предоставляет REQUEST_AVAILABLE_CAPABILITIES — массив IntArray флагов возможностей. Каждый флаг описывает одну конкретную вещь, которую может делать камера.

Формальная связь между уровнем оборудования и возможностями:

Пояснение флагов возможностей

Константа флагаЗначениеГарантия уровня оборудованияПрактическое следствие
BACKWARD_COMPATIBLEКамера реализует базовый API Camera2Все 5 уровней (LEGACY–EXTERNAL)Если это отсутствует, устройство камеры фактически нефункционально для вашего приложения.
MANUAL_SENSORПриложение может вручную управлять SENSOR_EXPOSURE_TIME, SENSOR_SENSITIVITY, SENSOR_FRAME_DURATION, LENS_FOCUS_DISTANCE, LENS_APERTUREГарантировано на FULL и LEVEL_3Требуется для режимов Pro и ручных настроек интерфейса. Без этого все слайдеры ISO/выдержки должны быть скрыты.
MANUAL_POST_PROCESSINGПриложение может вручную управлять этапами ISP: шумоподавлением, повышением резкости краев, кривой тона, усилением цветокоррекции, матрицей преобразования цветаГарантировано на FULL и LEVEL_3Нужно для кастомных лутов (LUT), ручного баланса белого через усиление каналов, управления резкостью/размытием.
RAWСенсор выдает «сырые» данные Bayer через форматы ImageFormat.RAW_SENSOR, RAW10 или RAW12Гарантировано на FULL и LEVEL_3Захват DNG, конвейер редактирования RAW-to-JPEG, вычислительная фотография — все начинается здесь.
PRIVATE_REPROCESSINGКамера поддерживает InputSurface + офлайн-переобработку изображений в частном формате HAL в JPEG/YUVГарантировано на LEVEL_3. Редко на FULL.Позволяет реализовать Zero-Shutter-Lag (ZSL): кольцевой буфер прошлых кадров, переобработка недавнего кадра в качественное фото.
YUV_REPROCESSINGКамера поддерживает InputSurface + переобработку предоставленных приложением YUV_420_888 обратно через ISPГарантировано на LEVEL_3Позволяет накладывать «кинематографический LUT» на записанное видео или перефокусировать портрет после съемки.
DEPTH_OUTPUTКамера может выдавать карты глубины (форматы DEPTH16 / DEPTH_POINT_CLOUD)Опционально на ЛЮБОМ уровне. Проверяйте массив явно.Режим портретного боке, AR-измерения, 3D-сканирование. Часто сочетается с LOGICAL_MULTI_CAMERA (стереоглубина из двух камер).
LOGICAL_MULTI_CAMERAЭта логическая камера поддерживается 2+ физическими сенсорами (например, сверхширик + ширик + телеобъектив)Опционально на ЛЮБОМ уровне. Обычно только флагманы.Позволяет реализовать бесшовный оптический зум (см. главу 20). Вы можете запросить LOGICAL_MULTI_CAMERA_PHYSICAL_IDS.
BURST_CAPTUREcaptureBurst() с > 1 кадром работает в полном разрешении без пропуска кадровГарантировано на FULL и LEVEL_3Без этого серийная съемка может тормозить, пропускать кадры или молча падать. Требуется для брекетинга.
CONSTRAINED_HIGH_SPEED_VIDEOПоддержка createHighSpeedRequestList() + скоростное видео (120fps, 240fps)Опционально на FULL/LEVEL_3. Редко на LIMITED.Запись замедленного видео (см. главу 19).
MOTION_TRACKINGКамера может отслеживать объекты / лица с высокой частотой кадров и низкой задержкойОпционально (редко). Есть на Pixel и некоторых флагманах.Отслеживание движения в AR, автофокус на спортивных объектах.
LOGICAL_MULTI_CAMERA_SYNCНесколько физических камер в логическом устройстве могут захватывать синхронизированные кадрыОпционально. Требуется для истинного одновременного захвата несколькими сенсорами.Вычислительная фотография, использующая несколько линз сразу (например, зум со слиянием).

Запрос всех возможностей во время выполнения

val capabilities = characteristics.get(
CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES
) ?: intArrayOf()

fun hasCapability(cap: Int): Boolean = capabilities.contains(cap)

val supportsManualSensor = hasCapability(
CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR
)
val supportsRaw = hasCapability(
CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_RAW
)
val supportsBurst = hasCapability(
CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE
)
val supportsDepth = hasCapability(
CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_DEPTH_OUTPUT
)
val supportsLogicalMultiCam = hasCapability(
CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA
)
val supportsHighSpeed = hasCapability(
CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_CONSTRAINED_HIGH_SPEED_VIDEO
)
val supportsYuvReprocessing = hasCapability(
CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING
)
val supportsPrivateReprocessing = hasCapability(
CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_PRIVATE_REPROCESSING
)

// Создание человекочитаемого отчета
val capabilityReport = buildString {
appendLine("=== Отчет о возможностях камеры ===")
appendLine("BACKWARD_COMPATIBLE: ${hasCapability(
CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE
)}")
appendLine("MANUAL_SENSOR: $supportsManualSensor")
appendLine("MANUAL_POST_PROCESSING: ${hasCapability(
CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING
)}")
appendLine("RAW: $supportsRaw")
appendLine("BURST_CAPTURE: $supportsBurst")
appendLine("YUV_REPROCESSING: $supportsYuvReprocessing")
appendLine("PRIVATE_REPROCESSING: $supportsPrivateReprocessing")
appendLine("DEPTH_OUTPUT: $supportsDepth")
appendLine("LOGICAL_MULTI_CAMERA: $supportsLogicalMultiCam")
appendLine("CONSTRAINED_HIGH_SPEED: $supportsHighSpeed")
}

Log.i("CamCaps", capabilityReport)

// Управление элементами интерфейса
manualIsoSlider.isEnabled = supportsManualSensor
manualExposureSlider.isEnabled = supportsManualSensor
rawCaptureToggle.isEnabled = supportsRaw
burstCaptureButton.isEnabled = supportsBurst
depthPortraitMode.isEnabled = supportsDepth
zoomSwitcher.isEnabled = supportsLogicalMultiCam
slowMoButton.isEnabled = supportsHighSpeed
zslMode.isEnabled = supportsPrivateReprocessing // LEVEL_3
подсказка

Приложение Android Camera Parameters отображает этот запрос в виде цветных флажков в карточке Capabilities. Зеленый = поддерживается, серый = нет. Вы можете сравнивать несколько камер, чтобы увидеть отличия в возможностях между основным модулем и сверхшириком.

12.5 Организация метаданных: Пространство имен android.*

Каждый ключ в CameraCharacteristics, CaptureRequest и CaptureResult следует иерархическому соглашению об именовании: android.<подсистема>.<параметр>. Компоненты, разделенные точками, группируют связанные настройки по подсистеме оборудования или ПО, которой они управляют.

Классы подсистем

Префикс подсистемыКласс метаданных KotlinЧто охватывает
android.sensor.*CameraCharacteristics.SensorInfo*, CaptureRequest.SENSOR_*, CaptureResult.SENSOR_*Считывание сенсора: выдержка, ISO, длительность кадра, метка времени, матрица пикселей, активная матрица, направление подвижного затвора, тестовые режимы
android.lens.*LensInfo*, Lens.*Оптика: дистанция фокусировки, апертура, фокусное расстояние, оптическая стабилизация (OIS), плотность фильтра (ND), диапазон фокуса, доступные апертуры
android.control.*Control*Алгоритмы 3A: режимы/состояние/цели/области AE, режимы/состояние/триггер/области AF, режимы/состояние/области AWB, подавление мерцания, сценарные режимы, эффекты, стабилизация видео (EIS)
android.scaler.*Scaler.*Конфигурация конвейера вывода: область обрезки (цифровой зум), поворот, карта конфигурации потоков (форматы, размеры, длительности), доступные минимальные длительности кадров
android.jpeg.*Jpeg*Кодирование JPEG: качество, ориентация, координаты GPS, размер миниатюры, качество миниатюры
android.request.*Request*Возможности всего конвейера: массив доступных возможностей, макс. глубина конвейера, макс. кол-во выходов RAW/PROC, ключи объектов метаданных, список доступных шаблонов
android.flash.*FlashInfo*, Flash*Блок вспышки: наличие, состояние заряда, цветовая температура, макс. яркость, режим (выкл / один импульс / фонарик)
android.statistics.*Statistics*Вывод статистики ISP: детекция лиц, ID лиц, точки лиц, оценки лиц, гистограмма, карта резкости, карта затенения линз, карта горячих пикселей
android.info.*Info*Статическая информация: уровень оборудования, версия устройства, доступные режимы детекции лиц, доступные режимы шумоподавления
android.black.*BlackLevel*Блокировка уровня черного, паттерн уровня черного (коррекция фиксированного шума)
android.colorCorrection.*ColorCorrection*Цветовой конвейер: матрица преобразования, усиление цветокоррекции (каналы R, G, B), режим коррекции аберраций
android.tonemap.*Tonemap*Тональное отображение: кривая тона (кастомная гамма), режим тонального отображения, контраст, насыщенность
android.edge.*Edge*Повышение резкости краев: режим, сила
android.noiseReduction.*NoiseReduction*Шумоподавление: режим, сила, сила временного шумоподавления
android.shading.*Shading*Коррекция виньетирования: режим, сила
android.hotPixel.*HotPixel*Коррекция горячих пикселей: режим, карта горячих пикселей
android.distortionCorrection.*DistortionCorrection*Коррекция геометрических искажений линз: режим
android.depth.*Depth*Вывод глубины: эксклюзивность глубины, макс. кол-во выборок глубины, формат глубины
android.logicalMultiCamera.*LogicalMultiCamera*Логическая мультикамера: ID физических камер, синхронизация сенсоров

Примечание о доступности ключей

Не каждый ключ существует на каждом устройстве. Если вы вызовете get(KEY) для ключа, который устройство не поддерживает, вы получите null — отсюда паттерны ?: 0 или ?.let, которые вы видите в этой книге.

Безопасный паттерн: проверяйте, существует ли ключ, перед его чтением, или используйте безопасность null в Kotlin для предоставления значения по умолчанию.

// Безопасный доступ со значениями по умолчанию
val exposureTimeNs: Long = characteristics.get(
CameraCharacteristics.SENSOR_INFO_EXPOSURE_TIME_RANGE
)?.upper ?: 1_000_000L // по умолчанию 1 мс, если ключ отсутствует

// Необязательная обработка, если ключ существует
characteristics.get(CameraCharacteristics.LENS_INFO_AVAILABLE_APERTURES)?.let { apertures ->
Log.d("CamCaps", "Устройство поддерживает ${apertures.size} апертур: ${apertures.contentToString()}")
buildApertureSelector(apertures)
} ?: run {
Log.d("CamCaps", "На этом устройстве нет сменной апертуры")
hideApertureControl()
}

12.6 Полный запрос возможностей (промышленного уровня)

Соберем все вместе. Вот готовый для использования запрос возможностей, который вы можете добавить в любое приложение на Camera2. Он объединяет уровень оборудования, флаги возможностей и проверку отдельных ключей:

data class CameraCapabilityProfile(
val cameraId: String,
val lensFacing: Int,
val hardwareLevel: Int,
val hardwareLevelName: String,
val supportsManualSensor: Boolean,
val supportsManualPostProcessing: Boolean,
val supportsRaw: Boolean,
val supportsBurst: Boolean,
val supportsDepth: Boolean,
val supportsLogicalMultiCam: Boolean,
val supportsHighSpeedVideo: Boolean,
val supportsYuvReprocessing: Boolean,
val supportsPrivateReprocessing: Boolean,
val maxBurstRaw: Int,
val maxBurstProcessed: Int,
val pipelineMaxDepth: Int,
val availableFocalLengths: FloatArray?,
val availableApertures: FloatArray?,
val minFocusDistanceDiopters: Float?,
val maxDigitalZoom: Float?
)

fun buildCapabilityProfile(
cameraManager: CameraManager,
cameraId: String
): CameraCapabilityProfile {
val c = cameraManager.getCameraCharacteristics(cameraId)

val hwLevel = c.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL)
?: CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY

val hwLevelName = when (hwLevel) {
CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY -> "LEGACY"
CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED -> "LIMITED"
CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL -> "FULL"
CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_3 -> "LEVEL_3"
CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_EXTERNAL -> "EXTERNAL"
else -> "UNKNOWN($hwLevel)"
}

val caps = c.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES) ?: intArrayOf()
fun has(cap: Int) = caps.contains(cap)

// Уровень оборудования дает гарантии возможностей, но проверяем флаги для надежности
val atLeastFull = hwLevel == CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL ||
hwLevel == CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_3

return CameraCapabilityProfile(
cameraId = cameraId,
lensFacing = c.get(CameraCharacteristics.LENS_FACING)
?: CameraCharacteristics.LENS_FACING_BACK,
hardwareLevel = hwLevel,
hardwareLevelName = hwLevelName,

// Проверка флагов + гарантия уровня оборудования
supportsManualSensor = has(
CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR
) || atLeastFull,
supportsManualPostProcessing = has(
CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING
) || atLeastFull,
supportsRaw = has(
CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_RAW
) || atLeastFull,
supportsBurst = has(
CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE
) || atLeastFull,
supportsDepth = has(
CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_DEPTH_OUTPUT
),
supportsLogicalMultiCam = has(
CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA
),
supportsHighSpeedVideo = has(
CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_CONSTRAINED_HIGH_SPEED_VIDEO
),
supportsYuvReprocessing = has(
CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING
),
supportsPrivateReprocessing = has(
CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_PRIVATE_REPROCESSING
),

maxBurstRaw = c.get(CameraCharacteristics.REQUEST_MAX_NUM_OUTPUT_RAW) ?: 1,
maxBurstProcessed = c.get(CameraCharacteristics.REQUEST_MAX_NUM_OUTPUT_PROC) ?: 1,
pipelineMaxDepth = c.get(CameraCharacteristics.REQUEST_PIPELINE_MAX_DEPTH) ?: 1,

availableFocalLengths = c.get(CameraCharacteristics.LENS_INFO_AVAILABLE_FOCAL_LENGTHS),
availableApertures = c.get(CameraCharacteristics.LENS_INFO_AVAILABLE_APERTURES),
minFocusDistanceDiopters = c.get(CameraCharacteristics.LENS_INFO_MINIMUM_FOCUS_DISTANCE),
maxDigitalZoom = c.get(CameraCharacteristics.SCALER_AVAILABLE_MAX_DIGITAL_ZOOM)
)
}

// Использование:
val profile = buildCapabilityProfile(cameraManager, "0")
Log.d("CamCaps", "Профиль камеры 0: ${profile.hardwareLevelName}, " +
"Manual=${profile.supportsManualSensor}, RAW=${profile.supportsRaw}, " +
"Burst=${profile.supportsBurst}, Depth=${profile.supportsDepth}, " +
"Zoom=${profile.maxDigitalZoom}x")

12.7 Визуализация в приложении Android Camera Parameters

Приложение Android Camera Parameters (GitHub, Play Store) — идеальное дополнение к этой главе. Оно превращает сырые пары ключ/значение CameraCharacteristics в удобный интерфейс:

  • Карточка сводки (Summary card) — уровень оборудования (с цветным значком: красный=LEGACY, оранжевый=LIMITED, зеленый=FULL, бирюзовый=LEVEL_3, синий=EXTERNAL), ориентация линз, разрешение сенсора, фокусные расстояния.
  • Карточка возможностей (Capabilities card) — список всех флагов REQUEST_AVAILABLE_CAPABILITIES с галочками, зелеными, если возможность есть.
  • Вкладки категорий — организованы в точности по подсистемам android.*: Sensor, Lens, Control, Scaler, Jpeg, Flash, Statistics, Info, Request.
  • Вкладка Raw JSON — полный сериализованный объект CameraCharacteristics для копирования в отчеты об ошибках.
  • Режим сравнения — переключайтесь между камерами (0, 1, 2, 3), чтобы увидеть отличия в уровнях оборудования и возможностях.

12.8 Резюме

КонцепцияКлючевой вывод
Уровень оборудования5 уровней: LEGACY (обертка) → LIMITED (базовый) → FULL (про + manual/RAW) → LEVEL_3 (FULL + переобработка) → EXTERNAL (USB). FULL — минимум для серьезной работы. Гарантии, проверенные CTS.
Флаги возможностейДетальное определение функций через REQUEST_AVAILABLE_CAPABILITIES. Ключевые флаги: MANUAL_SENSOR, MANUAL_POST_PROCESSING, RAW, BURST_CAPTURE, DEPTH_OUTPUT, LOGICAL_MULTI_CAMERA, PRIVATE_REPROCESSING, YUV_REPROCESSING, CONSTRAINED_HIGH_SPEED_VIDEO.
Связь Уровень → ВозможностьFULL гарантирует MANUAL_SENSOR, MANUAL_POST_PROCESSING, RAW, BURST. LEVEL_3 добавляет YUV/PRIVATE_REPROCESSING. DEPTH и LOGICAL_MULTI_CAMERA опциональны на всех уровнях.
Пространство имен метаданныхКлючи организованы как android.<подсистема>.<параметр>. Основные подсистемы: sensor, lens, control, scaler, jpeg, request, flash, statistics, info. Каждая имеет статику (Characteristics), вход запроса (Request) и выход результата (Result).
Безопасные запросыВсегда используйте значения по умолчанию для get() — многие ключи опциональны. Используйте уровень оборудования как грубый фильтр, флаги возможностей как точный, и наличие отдельных ключей для тонкой настройки под конкретное устройство.

Что дальше

Теперь, когда вы понимаете, что может делать камера (характеристики) и как ею управлять (конвейер + типы захвата), у вас есть фундамент для части IV.

В главе 13: Ручное ISO и выдержка, вы научитесь использовать возможность MANUAL_SENSOR для ручного управления SENSOR_EXPOSURE_TIME и SENSOR_SENSITIVITY — реализуя слайдер экспозиции в режиме Pro с живым предпросмотром, компенсацией экспозиции и пониманием компромиссов треугольника экспозиции.