From 794f2afa17ced199354f8ea2b5376264d9287a63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A4=A9=E8=BE=B9=E4=B8=80=E6=9C=B5=E4=BA=91?= Date: Mon, 1 Sep 2025 02:28:38 +0000 Subject: [PATCH] !93 enable camera --- .../google/coral/media_profiles_V1_0.xml | 524 ++ .../services/camera/virtualcamera/Android.bp | 98 + .../camera/virtualcamera/google_camera.hal.rc | 11 + .../devices/EmulatedCamera/hwl/Android.bp | 128 + .../hwl/EmulatedCameraProviderHWLImpl.cpp | 964 ++++ .../EmulatedCamera/hwl/EmulatedSensor.cpp | 2059 ++++++++ .../EmulatedCamera/hwl/EmulatedSensor.h | 477 ++ .../EmulatedCamera/hwl/apex/Android.bp | 87 + .../hwl/apex/apex_manifest.json | 5 + .../com.google.camera.provider.hal.avbpubkey | Bin 0 -> 1032 bytes .../apex/com.google.camera.provider.hal.pem | 51 + .../apex/com.google.camera.provider.hal.pk8 | Bin 0 -> 2376 bytes .../apex/com.google.camera.provider.hal.rc | 11 + .../com.google.camera.provider.hal.x509.pem | 34 + .../EmulatedCamera/hwl/configs/Android.bp | 51 + .../hwl/configs/google_camera_back.json | 1038 ++++ .../hwl/configs/google_camera_depth.json | 532 ++ .../hwl/configs/google_camera_external.json | 498 ++ .../hwl/configs/google_camera_front.json | 4525 +++++++++++++++++ aosp/vendor/common/prebuild/Android.bp | 35 +- .../common/prebuild/include/PacketQueue.h | 132 + .../vendor/common/prebuild/include/VmiAgent.h | 62 + .../common/prebuild/include/VmiCamera.h | 37 + .../common/prebuild/include/VmiMsgHeader.h | 274 + aosp/vendor/isula/common.mk | 2 + aosp/vendor/isula/copyfiles.mk | 2 +- aosp/vendor/isula/packages.mk | 2 + 27 files changed, 11637 insertions(+), 2 deletions(-) create mode 100644 aosp/device/google/coral/media_profiles_V1_0.xml create mode 100644 aosp/frameworks/av/services/camera/virtualcamera/Android.bp create mode 100644 aosp/frameworks/av/services/camera/virtualcamera/google_camera.hal.rc create mode 100644 aosp/hardware/google/camera/devices/EmulatedCamera/hwl/Android.bp create mode 100644 aosp/hardware/google/camera/devices/EmulatedCamera/hwl/EmulatedCameraProviderHWLImpl.cpp create mode 100644 aosp/hardware/google/camera/devices/EmulatedCamera/hwl/EmulatedSensor.cpp create mode 100644 aosp/hardware/google/camera/devices/EmulatedCamera/hwl/EmulatedSensor.h create mode 100644 aosp/hardware/google/camera/devices/EmulatedCamera/hwl/apex/Android.bp create mode 100644 aosp/hardware/google/camera/devices/EmulatedCamera/hwl/apex/apex_manifest.json create mode 100644 aosp/hardware/google/camera/devices/EmulatedCamera/hwl/apex/com.google.camera.provider.hal.avbpubkey create mode 100644 aosp/hardware/google/camera/devices/EmulatedCamera/hwl/apex/com.google.camera.provider.hal.pem create mode 100644 aosp/hardware/google/camera/devices/EmulatedCamera/hwl/apex/com.google.camera.provider.hal.pk8 create mode 100644 aosp/hardware/google/camera/devices/EmulatedCamera/hwl/apex/com.google.camera.provider.hal.rc create mode 100644 aosp/hardware/google/camera/devices/EmulatedCamera/hwl/apex/com.google.camera.provider.hal.x509.pem create mode 100644 aosp/hardware/google/camera/devices/EmulatedCamera/hwl/configs/Android.bp create mode 100644 aosp/hardware/google/camera/devices/EmulatedCamera/hwl/configs/google_camera_back.json create mode 100644 aosp/hardware/google/camera/devices/EmulatedCamera/hwl/configs/google_camera_depth.json create mode 100644 aosp/hardware/google/camera/devices/EmulatedCamera/hwl/configs/google_camera_external.json create mode 100644 aosp/hardware/google/camera/devices/EmulatedCamera/hwl/configs/google_camera_front.json create mode 100644 aosp/vendor/common/prebuild/include/PacketQueue.h create mode 100644 aosp/vendor/common/prebuild/include/VmiAgent.h create mode 100644 aosp/vendor/common/prebuild/include/VmiCamera.h create mode 100644 aosp/vendor/common/prebuild/include/VmiMsgHeader.h diff --git a/aosp/device/google/coral/media_profiles_V1_0.xml b/aosp/device/google/coral/media_profiles_V1_0.xml new file mode 100644 index 000000000..dc4e08f94 --- /dev/null +++ b/aosp/device/google/coral/media_profiles_V1_0.xml @@ -0,0 +1,524 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/aosp/frameworks/av/services/camera/virtualcamera/Android.bp b/aosp/frameworks/av/services/camera/virtualcamera/Android.bp new file mode 100644 index 000000000..4b861ae2e --- /dev/null +++ b/aosp/frameworks/av/services/camera/virtualcamera/Android.bp @@ -0,0 +1,98 @@ +package { + default_team: "trendy_team_xr_framework", + // See: http://go/android-license-faq + default_applicable_licenses: ["Android-Apache-2.0"], +} + +cc_defaults { + name: "libvirtualcamera_defaults", + shared_libs: [ + "android.hardware.common-V2-ndk", + "android.hardware.common.fmq-V1-ndk", + "libbinder", + "libbinder_ndk", + "libcamera_metadata", + "libexif", + "liblog", + "libfmq", + "libgui", + "libjpeg", + "libnativewindow", + "libbase", + "libcutils", + "libui", + "libutils", + "libEGL", + "libGLESv2", + "libGLESv3", + ], + static_libs: [ + "android.hardware.camera.common@1.0-helper", + "android.hardware.camera.common-V1-ndk", + "android.hardware.camera.device-V2-ndk", + "android.hardware.camera.metadata-V2-ndk", + "android.hardware.camera.provider-V2-ndk", + "libaidlcommonsupport", + "virtual_camera_service_aidl-ndk", + ], + cflags: [ + "-DANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION", + "-Wall", + "-Werror", + "-Wformat", + "-Wthread-safety", + ], +} + +cc_library_static { + name: "libvirtualcamera_utils", + srcs: [ + "util/JpegUtil.cc", + "util/MetadataUtil.cc", + "util/Util.cc", + "util/TestPatternHelper.cc", + "util/EglDisplayContext.cc", + "util/EglFramebuffer.cc", + "util/EglProgram.cc", + "util/EglSurfaceTexture.cc", + "util/EglUtil.cc", + "util/Permissions.cc", + ], + defaults: [ + "libvirtualcamera_defaults", + ], +} + +cc_library_static { + name: "libvirtualcamera", + srcs: [ + "VirtualCameraProvider.cc", + "VirtualCameraDevice.cc", + "VirtualCameraSession.cc", + "VirtualCameraStream.cc", + "VirtualCameraService.cc", + "VirtualCameraSessionContext.cc", + "VirtualCameraRenderThread.cc", + ], + defaults: [ + "libvirtualcamera_defaults", + ], + static_libs: [ + "libvirtualcamera_utils", + ], + export_include_dirs: ["."], + min_sdk_version: "current", +} + +cc_binary { + name: "google_camera", + srcs: ["main.cc"], + defaults: [ + "libvirtualcamera_defaults", + ], + static_libs: [ + "libvirtualcamera", + "libvirtualcamera_utils", + ], + init_rc: ["google_camera.hal.rc"], +} diff --git a/aosp/frameworks/av/services/camera/virtualcamera/google_camera.hal.rc b/aosp/frameworks/av/services/camera/virtualcamera/google_camera.hal.rc new file mode 100644 index 000000000..5726a0076 --- /dev/null +++ b/aosp/frameworks/av/services/camera/virtualcamera/google_camera.hal.rc @@ -0,0 +1,11 @@ +service google_camera /system/bin/google_camera + class core + user system + group system + capabilities SYS_NICE + rlimit rtprio 10 10 + task_profiles CameraServiceCapacity CameraServicePerformance + interface aidl virtual_camera + interface aidl android.hardware.camera.provider.ICameraProvider/virtual/0 + oneshot + disabled diff --git a/aosp/hardware/google/camera/devices/EmulatedCamera/hwl/Android.bp b/aosp/hardware/google/camera/devices/EmulatedCamera/hwl/Android.bp new file mode 100644 index 000000000..b7330693f --- /dev/null +++ b/aosp/hardware/google/camera/devices/EmulatedCamera/hwl/Android.bp @@ -0,0 +1,128 @@ +package { + // See: http://go/android-license-faq + default_applicable_licenses: ["Android-Apache-2.0"], +} + +cc_defaults { + name: "libgooglecamerahwl_impl_defaults", + owner: "google", + proprietary: true, + srcs: [ + "EmulatedCameraProviderHWLImpl.cpp", + "EmulatedCameraDeviceInfo.cpp", + "EmulatedCameraDeviceHWLImpl.cpp", + "EmulatedCameraDeviceSessionHWLImpl.cpp", + "EmulatedLogicalRequestState.cpp", + "EmulatedRequestProcessor.cpp", + "EmulatedRequestState.cpp", + "EmulatedTorchState.cpp", + "GrallocSensorBuffer.cpp", + ], + cflags: [ + "-Werror", + "-Wextra", + "-Wall", + ], + shared_libs: [ + "android.frameworks.sensorservice@1.0", + "android.hardware.graphics.mapper@2.0", + "android.hardware.graphics.mapper@3.0", + "android.hardware.graphics.mapper@4.0", + "android.hardware.camera.provider@2.4", + "android.hardware.camera.provider@2.5", + "android.hardware.camera.provider@2.6", + "android.hardware.camera.provider@2.7", + "android.hardware.sensors@1.0", + "android.hidl.allocator@1.0", + "lib_profiler", + "libbase", + "libcamera_metadata", + "libcutils", + "libexif", + "libgralloctypes", + "libhardware", + "libhidlbase", + "libgooglecamerahalutils", + "libjpeg", + "libjsoncpp", + "liblog", + "libsync", + "libui", + "libutils", + "libyuv", + "libvmicamera", + ], + static_libs: [ + "android.hardware.camera.common@1.0-helper", + "libgooglecamerahwl_sensor_impl", + ], + include_dirs: [ + "system/media/private/camera/include", + ], + header_libs: [ + "libgooglecamerahal_headers", + ], +} + +cc_library_shared { + name: "libgooglecamerahwl_impl", + defaults: ["libgooglecamerahwl_impl_defaults"], +} + +cc_library_shared { + name: "libgooglecamerahwl_impl_fast_scene_cycle", + defaults: ["libgooglecamerahwl_impl_defaults"], + stem: "libgooglecamerahwl_impl", + cflags: ["-DFAST_SCENE_CYCLE"], + // Never installed to /vendor, only used inside an APEX. + installable: false, +} + +cc_library_static { + name: "libgooglecamerahwl_sensor_impl", + owner: "google", + proprietary: true, + + srcs: [ + "EmulatedScene.cpp", + "EmulatedSensor.cpp", + "JpegCompressor.cpp", + "utils/ExifUtils.cpp", + "utils/HWLUtils.cpp", + "utils/StreamConfigurationMap.cpp", + ], + + header_libs: [ + "libhardware_headers", + ], + + shared_libs: [ + "libcamera_metadata", + "libcutils", + "libexif", + "libjpeg", + "liblog", + "libyuv", + "libvmicamera", + ], + + static_libs: [ + "android.hardware.graphics.common@1.1", + "android.hardware.graphics.common@1.2", + ], + + include_dirs: [ + "system/media/private/camera/include", + "hardware/google/camera/common/hal/common", + "hardware/google/camera/common/hal/hwl_interface", + "hardware/google/camera/common/hal/utils", + ], + + export_include_dirs: ["."], + + cflags: [ + "-Werror", + "-Wextra", + "-Wall", + ], +} diff --git a/aosp/hardware/google/camera/devices/EmulatedCamera/hwl/EmulatedCameraProviderHWLImpl.cpp b/aosp/hardware/google/camera/devices/EmulatedCamera/hwl/EmulatedCameraProviderHWLImpl.cpp new file mode 100644 index 000000000..25eeb98dc --- /dev/null +++ b/aosp/hardware/google/camera/devices/EmulatedCamera/hwl/EmulatedCameraProviderHWLImpl.cpp @@ -0,0 +1,964 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//#define LOG_NDEBUG 0 +#define LOG_TAG "EmulatedCameraProviderHwlImpl" +#include "EmulatedCameraProviderHWLImpl.h" + +#include +#include +#include +#include +#include + +#include "EmulatedCameraDeviceHWLImpl.h" +#include "EmulatedCameraDeviceSessionHWLImpl.h" +#include "EmulatedLogicalRequestState.h" +#include "EmulatedSensor.h" +#include "EmulatedTorchState.h" +#include "utils/HWLUtils.h" +#include "vendor_tag_defs.h" +#include "VmiAgent.h" + +namespace android { + +// Location of the camera configuration files. +constexpr std::string_view kCameraConfigBack = "google_camera_back.json"; +constexpr std::string_view kCameraConfigFront = "google_camera_front.json"; +constexpr std::string_view kCameraConfigExternal = "google_camera_external.json"; +constexpr std::string_view kCameraConfigDepth = "google_camera_depth.json"; +constexpr std::string_view kCameraConfigFiles[] = { + kCameraConfigBack, kCameraConfigFront, kCameraConfigExternal, + kCameraConfigDepth}; + +constexpr std::string_view kConfigurationFileDirVendor = "/vendor/etc/config/"; +constexpr std::string_view kConfigurationFileDirApex = + "/apex/com.google.camera.provider.hal/etc/config/"; + +constexpr StreamSize s240pStreamSize = std::pair(240, 180); +constexpr StreamSize s720pStreamSize = std::pair(1280, 720); +constexpr StreamSize s1440pStreamSize = std::pair(1920, 1440); + +std::unique_ptr +EmulatedCameraProviderHwlImpl::Create() { + auto provider = std::unique_ptr( + new EmulatedCameraProviderHwlImpl()); + + if (provider == nullptr) { + ALOGE("%s: Creating EmulatedCameraProviderHwlImpl failed.", __FUNCTION__); + return nullptr; + } + + status_t res = provider->Initialize(); + if (res != OK) { + ALOGE("%s: Initializing EmulatedCameraProviderHwlImpl failed: %s (%d).", + __FUNCTION__, strerror(-res), res); + return nullptr; + } + + ALOGI("%s: Created EmulatedCameraProviderHwlImpl", __FUNCTION__); + + return provider; +} + +status_t EmulatedCameraProviderHwlImpl::GetTagFromName(const char* name, + uint32_t* tag) { + if (name == nullptr || tag == nullptr) { + return BAD_VALUE; + } + + size_t name_length = strlen(name); + // First, find the section by the longest string match + const char* section = NULL; + size_t section_index = 0; + size_t section_length = 0; + for (size_t i = 0; i < ANDROID_SECTION_COUNT; ++i) { + const char* str = camera_metadata_section_names[i]; + + ALOGV("%s: Trying to match against section '%s'", __FUNCTION__, str); + + if (strstr(name, str) == name) { // name begins with the section name + size_t str_length = strlen(str); + + ALOGV("%s: Name begins with section name", __FUNCTION__); + + // section name is the longest we've found so far + if (section == NULL || section_length < str_length) { + section = str; + section_index = i; + section_length = str_length; + + ALOGV("%s: Found new best section (%s)", __FUNCTION__, section); + } + } + } + + if (section == NULL) { + return NAME_NOT_FOUND; + } else { + ALOGV("%s: Found matched section '%s' (%zu)", __FUNCTION__, section, + section_index); + } + + // Get the tag name component of the name + const char* name_tag_name = name + section_length + 1; // x.y.z -> z + if (section_length + 1 >= name_length) { + return BAD_VALUE; + } + + // Match rest of name against the tag names in that section only + uint32_t candidate_tag = 0; + // Match built-in tags (typically android.*) + uint32_t tag_begin, tag_end; // [tag_begin, tag_end) + tag_begin = camera_metadata_section_bounds[section_index][0]; + tag_end = camera_metadata_section_bounds[section_index][1]; + + for (candidate_tag = tag_begin; candidate_tag < tag_end; ++candidate_tag) { + const char* tag_name = get_camera_metadata_tag_name(candidate_tag); + + if (strcmp(name_tag_name, tag_name) == 0) { + ALOGV("%s: Found matched tag '%s' (%d)", __FUNCTION__, tag_name, + candidate_tag); + break; + } + } + + if (candidate_tag == tag_end) { + return NAME_NOT_FOUND; + } + + *tag = candidate_tag; + return OK; +} + +static bool IsMaxSupportedSizeGreaterThanOrEqual( + const std::set& stream_sizes, StreamSize compare_size) { + for (const auto& stream_size : stream_sizes) { + if (stream_size.first * stream_size.second >= + compare_size.first * compare_size.second) { + return true; + } + } + return false; +} + +static bool SupportsCapability(const uint32_t camera_id, + const HalCameraMetadata& static_metadata, + uint8_t cap) { + camera_metadata_ro_entry_t entry; + auto ret = static_metadata.Get(ANDROID_REQUEST_AVAILABLE_CAPABILITIES, &entry); + if (ret != OK || (entry.count == 0)) { + ALOGE("Error getting capabilities for camera id %u", camera_id); + return false; + } + for (size_t i = 0; i < entry.count; i++) { + if (entry.data.u8[i] == cap) { + return true; + } + } + return false; +} + +bool EmulatedCameraProviderHwlImpl::SupportsMandatoryConcurrentStreams( + uint32_t camera_id) { + HalCameraMetadata& static_metadata = *(static_metadata_[camera_id]); + auto map = std::make_unique(static_metadata); + auto yuv_output_sizes = map->GetOutputSizes(HAL_PIXEL_FORMAT_YCBCR_420_888); + auto blob_output_sizes = map->GetOutputSizes(HAL_PIXEL_FORMAT_BLOB); + auto depth16_output_sizes = map->GetOutputSizes(HAL_PIXEL_FORMAT_Y16); + auto priv_output_sizes = + map->GetOutputSizes(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED); + + if (!SupportsCapability( + camera_id, static_metadata, + ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE) && + IsMaxSupportedSizeGreaterThanOrEqual(depth16_output_sizes, + s240pStreamSize)) { + ALOGI("%s: Depth only output supported by camera id %u", __FUNCTION__, + camera_id); + return true; + } + if (yuv_output_sizes.empty()) { + ALOGW("%s: No YUV output supported by camera id %u", __FUNCTION__, + camera_id); + return false; + } + + if (priv_output_sizes.empty()) { + ALOGW("No PRIV output supported by camera id %u", camera_id); + return false; + } + + if (blob_output_sizes.empty()) { + ALOGW("No BLOB output supported by camera id %u", camera_id); + return false; + } + + // According to the HAL spec, if a device supports format sizes > 1440p and + // 720p, it must support both 1440p and 720p streams for PRIV, JPEG and YUV + // formats. Otherwise it must support 2 streams (YUV / PRIV + JPEG) of the max + // supported size. + + // Check for YUV output sizes + if (IsMaxSupportedSizeGreaterThanOrEqual(yuv_output_sizes, s1440pStreamSize) && + (yuv_output_sizes.find(s1440pStreamSize) == yuv_output_sizes.end() || + yuv_output_sizes.find(s720pStreamSize) == yuv_output_sizes.end())) { + ALOGW("%s: 1440p+720p YUV outputs not found for camera id %u", __FUNCTION__, + camera_id); + return false; + } else if (IsMaxSupportedSizeGreaterThanOrEqual(yuv_output_sizes, + s720pStreamSize) && + yuv_output_sizes.find(s720pStreamSize) == yuv_output_sizes.end()) { + ALOGW("%s: 720p YUV output not found for camera id %u", __FUNCTION__, + camera_id); + return false; + } + + // Check for PRIV output sizes + if (IsMaxSupportedSizeGreaterThanOrEqual(priv_output_sizes, s1440pStreamSize) && + (priv_output_sizes.find(s1440pStreamSize) == priv_output_sizes.end() || + priv_output_sizes.find(s720pStreamSize) == priv_output_sizes.end())) { + ALOGW("%s: 1440p + 720p PRIV outputs not found for camera id %u", + __FUNCTION__, camera_id); + return false; + } else if (IsMaxSupportedSizeGreaterThanOrEqual(priv_output_sizes, + s720pStreamSize) && + priv_output_sizes.find(s720pStreamSize) == priv_output_sizes.end()) { + ALOGW("%s: 720p PRIV output not found for camera id %u", __FUNCTION__, + camera_id); + return false; + } + + // Check for BLOB output sizes + if (IsMaxSupportedSizeGreaterThanOrEqual(blob_output_sizes, s1440pStreamSize) && + (blob_output_sizes.find(s1440pStreamSize) == blob_output_sizes.end() || + blob_output_sizes.find(s720pStreamSize) == blob_output_sizes.end())) { + ALOGW("%s: 1440p + 720p BLOB outputs not found for camera id %u", + __FUNCTION__, camera_id); + return false; + } else if (IsMaxSupportedSizeGreaterThanOrEqual(blob_output_sizes, + s720pStreamSize) && + blob_output_sizes.find(s720pStreamSize) == blob_output_sizes.end()) { + ALOGW("%s: 720p BLOB output not found for camera id %u", __FUNCTION__, + camera_id); + return false; + } + + return true; +} + +status_t EmulatedCameraProviderHwlImpl::GetConcurrentStreamingCameraIds( + std::vector>* combinations) { + if (combinations == nullptr) { + return BAD_VALUE; + } + // Collect all camera ids that support the guaranteed stream combinations + // (720p YUV and IMPLEMENTATION_DEFINED) and put them in one set. We don't + // make all possible combinations since it should be possible to stream all + // of them at once in the emulated camera. + std::unordered_set candidate_ids; + for (auto& entry : camera_id_map_) { + if (SupportsMandatoryConcurrentStreams(entry.first)) { + candidate_ids.insert(entry.first); + } + } + combinations->emplace_back(std::move(candidate_ids)); + return OK; +} + +status_t EmulatedCameraProviderHwlImpl::IsConcurrentStreamCombinationSupported( + const std::vector& configs, + bool* is_supported) { + *is_supported = false; + + // Go through the given camera ids, get their sensor characteristics, stream + // config maps and call EmulatedSensor::IsStreamCombinationSupported() + for (auto& config : configs) { + // TODO: Consider caching sensor characteristics and StreamConfigurationMap + if (camera_id_map_.find(config.camera_id) == camera_id_map_.end()) { + ALOGE("%s: Camera id %u does not exist", __FUNCTION__, config.camera_id); + return BAD_VALUE; + } + + auto stream_configuration_map = std::make_unique( + *(static_metadata_[config.camera_id])); + auto stream_configuration_map_max_resolution = + std::make_unique( + *(static_metadata_[config.camera_id]), /*maxResolution*/ true); + + LogicalCharacteristics sensor_chars; + status_t ret = + GetSensorCharacteristics((static_metadata_[config.camera_id]).get(), + &sensor_chars[config.camera_id]); + if (ret != OK) { + ALOGE("%s: Unable to extract sensor chars for camera id %u", __FUNCTION__, + config.camera_id); + return UNKNOWN_ERROR; + } + + PhysicalStreamConfigurationMap physical_stream_configuration_map; + PhysicalStreamConfigurationMap physical_stream_configuration_map_max_resolution; + auto const& physicalCameraInfo = camera_id_map_[config.camera_id]; + for (size_t i = 0; i < physicalCameraInfo.size(); i++) { + uint32_t physical_camera_id = physicalCameraInfo[i].second; + physical_stream_configuration_map.emplace( + physical_camera_id, std::make_unique( + *(static_metadata_[physical_camera_id]))); + + physical_stream_configuration_map_max_resolution.emplace( + physical_camera_id, + std::make_unique( + *(static_metadata_[physical_camera_id]), /*maxResolution*/ true)); + + ret = GetSensorCharacteristics(static_metadata_[physical_camera_id].get(), + &sensor_chars[physical_camera_id]); + if (ret != OK) { + ALOGE("%s: Unable to extract camera %d sensor characteristics %s (%d)", + __FUNCTION__, physical_camera_id, strerror(-ret), ret); + return ret; + } + } + + if (!EmulatedSensor::IsStreamCombinationSupported( + config.camera_id, config.stream_configuration, + *stream_configuration_map, *stream_configuration_map_max_resolution, + physical_stream_configuration_map, + physical_stream_configuration_map_max_resolution, sensor_chars)) { + return OK; + } + } + + *is_supported = true; + return OK; +} + +bool IsDigit(const std::string& value) { + if (value.empty()) { + return false; + } + + for (const auto& c : value) { + if (!std::isdigit(c) && (!std::ispunct(c))) { + return false; + } + } + + return true; +} + +template +status_t GetEnumValue(uint32_t tag_id, const char* cstring, T* result /*out*/) { + if ((result == nullptr) || (cstring == nullptr)) { + return BAD_VALUE; + } + + uint32_t enum_value; + auto ret = + camera_metadata_enum_value(tag_id, cstring, strlen(cstring), &enum_value); + if (ret != OK) { + ALOGE("%s: Failed to match tag id: 0x%x value: %s", __FUNCTION__, tag_id, + cstring); + return ret; + } + *result = enum_value; + + return OK; +} + +status_t GetUInt8Value(const Json::Value& value, uint32_t tag_id, + uint8_t* result /*out*/) { + if (result == nullptr) { + return BAD_VALUE; + } + + if (value.isString()) { + errno = 0; + if (IsDigit(value.asString())) { + auto int_value = strtol(value.asCString(), nullptr, 10); + if ((int_value >= 0) && (int_value <= UINT8_MAX) && (errno == 0)) { + *result = int_value; + } else { + ALOGE("%s: Failed parsing tag id 0x%x", __func__, tag_id); + return BAD_VALUE; + } + } else { + return GetEnumValue(tag_id, value.asCString(), result); + } + } else { + ALOGE( + "%s: Unexpected json type: %d! All value types are expected to be " + "strings!", + __FUNCTION__, value.type()); + return BAD_VALUE; + } + + return OK; +} + +status_t GetInt32Value(const Json::Value& value, uint32_t tag_id, + int32_t* result /*out*/) { + if (result == nullptr) { + return BAD_VALUE; + } + + if (value.isString()) { + errno = 0; + if (IsDigit(value.asString())) { + auto int_value = strtol(value.asCString(), nullptr, 10); + if ((int_value >= INT32_MIN) && (int_value <= INT32_MAX) && (errno == 0)) { + *result = int_value; + } else { + ALOGE("%s: Failed parsing tag id 0x%x", __func__, tag_id); + return BAD_VALUE; + } + } else { + return GetEnumValue(tag_id, value.asCString(), result); + } + } else { + ALOGE( + "%s: Unexpected json type: %d! All value types are expected to be " + "strings!", + __FUNCTION__, value.type()); + return BAD_VALUE; + } + + return OK; +} + +status_t GetInt64Value(const Json::Value& value, uint32_t tag_id, + int64_t* result /*out*/) { + if (result == nullptr) { + return BAD_VALUE; + } + + if (value.isString()) { + errno = 0; + auto int_value = strtoll(value.asCString(), nullptr, 10); + if ((int_value >= INT64_MIN) && (int_value <= INT64_MAX) && (errno == 0)) { + *result = int_value; + } else { + ALOGE("%s: Failed parsing tag id 0x%x", __func__, tag_id); + return BAD_VALUE; + } + } else { + ALOGE( + "%s: Unexpected json type: %d! All value types are expected to be " + "strings!", + __FUNCTION__, value.type()); + return BAD_VALUE; + } + + return OK; +} + +status_t GetFloatValue(const Json::Value& value, uint32_t tag_id, + float* result /*out*/) { + if (result == nullptr) { + return BAD_VALUE; + } + + if (value.isString()) { + errno = 0; + auto float_value = strtof(value.asCString(), nullptr); + if (errno == 0) { + *result = float_value; + } else { + ALOGE("%s: Failed parsing tag id 0x%x", __func__, tag_id); + return BAD_VALUE; + } + } else { + ALOGE( + "%s: Unexpected json type: %d! All value types are expected to be " + "strings!", + __FUNCTION__, value.type()); + return BAD_VALUE; + } + + return OK; +} + +status_t GetDoubleValue(const Json::Value& value, uint32_t tag_id, + double* result /*out*/) { + if (result == nullptr) { + return BAD_VALUE; + } + + if (value.isString()) { + errno = 0; + auto double_value = strtod(value.asCString(), nullptr); + if (errno == 0) { + *result = double_value; + } else { + ALOGE("%s: Failed parsing tag id 0x%x", __func__, tag_id); + return BAD_VALUE; + } + } else { + ALOGE( + "%s: Unexpected json type: %d! All value types are expected to be " + "strings!", + __FUNCTION__, value.type()); + return BAD_VALUE; + } + + return OK; +} + +template +void FilterVendorKeys(uint32_t tag_id, std::vector* values) { + if ((values == nullptr) || (values->empty())) { + return; + } + + switch (tag_id) { + case ANDROID_REQUEST_AVAILABLE_REQUEST_KEYS: + case ANDROID_REQUEST_AVAILABLE_RESULT_KEYS: + case ANDROID_REQUEST_AVAILABLE_SESSION_KEYS: + case ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS: { + auto it = values->begin(); + while (it != values->end()) { + // Per spec. the tags we are handling here will be "int32_t". + // In this case all vendor defined values will be negative. + if (*it < 0) { + it = values->erase(it); + } else { + it++; + } + } + } break; + default: + // no-op + break; + } +} + +template +status_t InsertTag(const Json::Value& json_value, uint32_t tag_id, + func_type get_val_func, HalCameraMetadata* meta /*out*/) { + if (meta == nullptr) { + return BAD_VALUE; + } + + std::vector values; + T result; + status_t ret = -1; + values.reserve(json_value.size()); + for (const auto& val : json_value) { + ret = get_val_func(val, tag_id, &result); + if (ret != OK) { + break; + } + + values.push_back(result); + } + + if (ret == OK) { + FilterVendorKeys(tag_id, &values); + ret = meta->Set(tag_id, values.data(), values.size()); + } + + return ret; +} + +status_t InsertRationalTag(const Json::Value& json_value, uint32_t tag_id, + HalCameraMetadata* meta /*out*/) { + if (meta == nullptr) { + return BAD_VALUE; + } + + std::vector values; + status_t ret = OK; + if (json_value.isArray() && ((json_value.size() % 2) == 0)) { + values.reserve(json_value.size() / 2); + auto it = json_value.begin(); + while (it != json_value.end()) { + camera_metadata_rational_t result; + ret = GetInt32Value((*it), tag_id, &result.numerator); + it++; + ret |= GetInt32Value((*it), tag_id, &result.denominator); + it++; + if (ret != OK) { + break; + } + values.push_back(result); + } + } else { + ALOGE("%s: json type: %d doesn't match with rational tag type", + __FUNCTION__, json_value.type()); + return BAD_VALUE; + } + + if (ret == OK) { + ret = meta->Set(tag_id, values.data(), values.size()); + } + + return ret; +} + +uint32_t EmulatedCameraProviderHwlImpl::ParseCharacteristics( + const Json::Value& value, ssize_t id) { + if (!value.isObject()) { + ALOGE("%s: Configuration root is not an object", __FUNCTION__); + return BAD_VALUE; + } + + auto static_meta = HalCameraMetadata::Create(1, 10); + auto members = value.getMemberNames(); + for (const auto& member : members) { + uint32_t tag_id; + auto stat = GetTagFromName(member.c_str(), &tag_id); + if (stat != OK) { + ALOGE("%s: tag %s not supported, skipping!", __func__, member.c_str()); + continue; + } + + auto tag_type = get_camera_metadata_tag_type(tag_id); + auto tag_value = value[member.c_str()]; + switch (tag_type) { + case TYPE_BYTE: + InsertTag(tag_value, tag_id, GetUInt8Value, static_meta.get()); + break; + case TYPE_INT32: + InsertTag(tag_value, tag_id, GetInt32Value, static_meta.get()); + break; + case TYPE_INT64: + InsertTag(tag_value, tag_id, GetInt64Value, static_meta.get()); + break; + case TYPE_FLOAT: + InsertTag(tag_value, tag_id, GetFloatValue, static_meta.get()); + break; + case TYPE_DOUBLE: + InsertTag(tag_value, tag_id, GetDoubleValue, static_meta.get()); + break; + case TYPE_RATIONAL: + InsertRationalTag(tag_value, tag_id, static_meta.get()); + break; + default: + ALOGE("%s: Unsupported tag type: %d!", __FUNCTION__, tag_type); + } + } + + SensorCharacteristics sensor_characteristics; + auto ret = + GetSensorCharacteristics(static_meta.get(), &sensor_characteristics); + if (ret != OK) { + ALOGE("%s: Unable to extract sensor characteristics!", __FUNCTION__); + return ret; + } + + if (!EmulatedSensor::AreCharacteristicsSupported(sensor_characteristics)) { + ALOGE("%s: Sensor characteristics not supported!", __FUNCTION__); + return BAD_VALUE; + } + + // Although we don't support HdrPlus, this data is still required by HWL + int32_t payload_frames = 0; + static_meta->Set(google_camera_hal::kHdrplusPayloadFrames, &payload_frames, 1); + + if (id < 0) { + static_metadata_.push_back(std::move(static_meta)); + id = static_metadata_.size() - 1; + } else { + static_metadata_[id] = std::move(static_meta); + } + + return id; +} + +status_t EmulatedCameraProviderHwlImpl::WaitForQemuSfFakeCameraPropertyAvailable() { + // Camera service may start running before qemu-props sets + // vendor.qemu.sf.fake_camera to any of the following four values: + // "none,front,back,both"; so we need to wait. + int num_attempts = 100; + char prop[PROPERTY_VALUE_MAX]; + bool timeout = true; + for (int i = 0; i < num_attempts; ++i) { + if (property_get("vendor.qemu.sf.fake_camera", prop, nullptr) != 0) { + timeout = false; + break; + } + usleep(5000); + } + if (timeout) { + ALOGE("timeout (%dms) waiting for property vendor.qemu.sf.fake_camera to be set\n", + 5 * num_attempts); + return BAD_VALUE; + } + return OK; +} + +status_t EmulatedCameraProviderHwlImpl::Initialize() { + // GCH expects all physical ids to be bigger than the logical ones. + // Resize 'static_metadata_' to fit all logical devices and insert them + // accordingly, push any remaining physical cameras in the back. + std::string config; + size_t logical_id = 0; + std::vector config_file_locations; + std::string config_dir = ""; + struct stat st; + if (stat(kConfigurationFileDirApex.data(), &st) == 0) { + config_dir += kConfigurationFileDirApex.data(); + } else { + config_dir += kConfigurationFileDirVendor.data(); + } + char prop[PROPERTY_VALUE_MAX]; + if (!property_get_bool("ro.boot.qemu", false)) { + // Cuttlefish + property_get("ro.vendor.camera.config", prop, nullptr); + if (strcmp(prop, "external") == 0) { + config_file_locations.emplace_back(config_dir + + kCameraConfigExternal.data()); + logical_id = 1; + } else { + // Default phone layout. + config_file_locations.emplace_back(config_dir + kCameraConfigBack.data()); + config_file_locations.emplace_back(config_dir + kCameraConfigFront.data()); + config_file_locations.emplace_back(config_dir + kCameraConfigDepth.data()); + } + } else { + // Android Studio Emulator + if (!property_get_bool("ro.boot.qemu.legacy_fake_camera", false)) { + if (WaitForQemuSfFakeCameraPropertyAvailable() == OK) { + property_get("vendor.qemu.sf.fake_camera", prop, nullptr); + if (strcmp(prop, "both") == 0) { + config_file_locations.emplace_back(config_dir + + kCameraConfigBack.data()); + config_file_locations.emplace_back(config_dir + + kCameraConfigFront.data()); + } else if (strcmp(prop, "front") == 0) { + config_file_locations.emplace_back(config_dir + + kCameraConfigFront.data()); + logical_id = 1; + } else if (strcmp(prop, "back") == 0) { + config_file_locations.emplace_back(config_dir + + kCameraConfigBack.data()); + logical_id = 1; + } + } + } + } + static_metadata_.resize(ARRAY_SIZE(kCameraConfigFiles)); + + for (const auto& config_path : config_file_locations) { + if (!android::base::ReadFileToString(config_path, &config)) { + ALOGW("%s: Could not open configuration file: %s", __FUNCTION__, + config_path.c_str()); + continue; + } + + Json::CharReaderBuilder builder; + std::unique_ptr config_reader(builder.newCharReader()); + Json::Value root; + std::string error_message; + if (!config_reader->parse(&*config.begin(), &*config.end(), &root, + &error_message)) { + ALOGE("Could not parse configuration file: %s", error_message.c_str()); + return BAD_VALUE; + } + + if (root.isArray()) { + auto device_iter = root.begin(); + auto result_id = ParseCharacteristics(*device_iter, logical_id); + if (logical_id != result_id) { + return result_id; + } + device_iter++; + + // The first device entry is always the logical camera followed by the + // physical devices. They must be at least 2. + camera_id_map_.emplace(logical_id, std::vector>()); + if (root.size() >= 3) { + camera_id_map_[logical_id].reserve(root.size() - 1); + size_t current_physical_device = 0; + while (device_iter != root.end()) { + auto physical_id = ParseCharacteristics(*device_iter, /*id*/ -1); + if (physical_id < 0) { + return physical_id; + } + // Only notify unavailable physical camera if there are more than 2 + // physical cameras backing the logical camera + auto device_status = (current_physical_device < 2) ? CameraDeviceStatus::kPresent : + CameraDeviceStatus::kNotPresent; + camera_id_map_[logical_id].push_back(std::make_pair(device_status, physical_id)); + device_iter++; current_physical_device++; + } + + auto physical_devices = std::make_unique(); + for (const auto& physical_device : camera_id_map_[logical_id]) { + physical_devices->emplace( + physical_device.second, std::make_pair(physical_device.first, + HalCameraMetadata::Clone( + static_metadata_[physical_device.second].get()))); + } + auto updated_logical_chars = + EmulatedLogicalRequestState::AdaptLogicalCharacteristics( + HalCameraMetadata::Clone(static_metadata_[logical_id].get()), + std::move(physical_devices)); + if (updated_logical_chars.get() != nullptr) { + static_metadata_[logical_id].swap(updated_logical_chars); + } else { + ALOGE("%s: Failed to updating logical camera characteristics!", + __FUNCTION__); + return BAD_VALUE; + } + } + } else { + auto result_id = ParseCharacteristics(root, logical_id); + if (result_id != logical_id) { + return result_id; + } + camera_id_map_.emplace(logical_id, std::vector>()); + } + + logical_id++; + } + + android::VmiAgent::GetInstance()->Init("VIRTUAL_CAMERA"); + return OK; +} + +status_t EmulatedCameraProviderHwlImpl::SetCallback( + const HwlCameraProviderCallback& callback) { + torch_cb_ = callback.torch_mode_status_change; + physical_camera_status_cb_ = callback.physical_camera_device_status_change; + + return OK; +} + +status_t EmulatedCameraProviderHwlImpl::TriggerDeferredCallbacks() { + std::lock_guard lock(status_callback_future_lock_); + if (status_callback_future_.valid()) { + return OK; + } + + status_callback_future_ = std::async( + std::launch::async, + &EmulatedCameraProviderHwlImpl::NotifyPhysicalCameraUnavailable, this); + return OK; +} + +void EmulatedCameraProviderHwlImpl::WaitForStatusCallbackFuture() { + { + std::lock_guard lock(status_callback_future_lock_); + if (!status_callback_future_.valid()) { + // If there is no future pending, construct a dummy one. + status_callback_future_ = std::async([]() { return; }); + } + } + status_callback_future_.wait(); +} + +void EmulatedCameraProviderHwlImpl::NotifyPhysicalCameraUnavailable() { + for (const auto& one_map : camera_id_map_) { + for (const auto& physical_device : one_map.second) { + if (physical_device.first != CameraDeviceStatus::kNotPresent) { + continue; + } + + uint32_t logical_camera_id = one_map.first; + uint32_t physical_camera_id = physical_device.second; + physical_camera_status_cb_( + logical_camera_id, physical_camera_id, + CameraDeviceStatus::kNotPresent); + } + } +} + +status_t EmulatedCameraProviderHwlImpl::GetVendorTags( + std::vector* vendor_tag_sections) { + if (vendor_tag_sections == nullptr) { + ALOGE("%s: vendor_tag_sections is nullptr.", __FUNCTION__); + return BAD_VALUE; + } + + // No vendor specific tags as of now + return OK; +} + +status_t EmulatedCameraProviderHwlImpl::GetVisibleCameraIds( + std::vector* camera_ids) { + if (camera_ids == nullptr) { + ALOGE("%s: camera_ids is nullptr.", __FUNCTION__); + return BAD_VALUE; + } + + for (const auto& device : camera_id_map_) { + camera_ids->push_back(device.first); + } + + return OK; +} + +status_t EmulatedCameraProviderHwlImpl::CreateCameraDeviceHwl( + uint32_t camera_id, std::unique_ptr* camera_device_hwl) { + if (camera_device_hwl == nullptr) { + ALOGE("%s: camera_device_hwl is nullptr.", __FUNCTION__); + return BAD_VALUE; + } + + if (camera_id_map_.find(camera_id) == camera_id_map_.end()) { + ALOGE("%s: Invalid camera id: %u", __func__, camera_id); + return BAD_VALUE; + } + + std::unique_ptr meta = + HalCameraMetadata::Clone(static_metadata_[camera_id].get()); + + std::shared_ptr torch_state; + camera_metadata_ro_entry entry; + bool flash_supported = false; + auto ret = meta->Get(ANDROID_FLASH_INFO_AVAILABLE, &entry); + if ((ret == OK) && (entry.count == 1)) { + if (entry.data.u8[0] == ANDROID_FLASH_INFO_AVAILABLE_TRUE) { + flash_supported = true; + } + } + + if (flash_supported) { + torch_state = std::make_shared(camera_id, torch_cb_); + } + + auto physical_devices = std::make_unique(); + for (const auto& physical_device : camera_id_map_[camera_id]) { + physical_devices->emplace( + physical_device.second, std::make_pair(physical_device.first, + HalCameraMetadata::Clone(static_metadata_[physical_device.second].get()))); + } + *camera_device_hwl = EmulatedCameraDeviceHwlImpl::Create( + camera_id, std::move(meta), std::move(physical_devices), torch_state); + if (*camera_device_hwl == nullptr) { + ALOGE("%s: Cannot create EmulatedCameraDeviceHWlImpl.", __FUNCTION__); + return BAD_VALUE; + } + + return OK; +} + +status_t EmulatedCameraProviderHwlImpl::CreateBufferAllocatorHwl( + std::unique_ptr* camera_buffer_allocator_hwl) { + if (camera_buffer_allocator_hwl == nullptr) { + ALOGE("%s: camera_buffer_allocator_hwl is nullptr.", __FUNCTION__); + return BAD_VALUE; + } + + // Currently not supported + return INVALID_OPERATION; +} + +status_t EmulatedCameraProviderHwlImpl::NotifyDeviceStateChange( + DeviceState /*device_state*/) { + return OK; +} +} // namespace android diff --git a/aosp/hardware/google/camera/devices/EmulatedCamera/hwl/EmulatedSensor.cpp b/aosp/hardware/google/camera/devices/EmulatedCamera/hwl/EmulatedSensor.cpp new file mode 100644 index 000000000..95091e4bd --- /dev/null +++ b/aosp/hardware/google/camera/devices/EmulatedCamera/hwl/EmulatedSensor.cpp @@ -0,0 +1,2059 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//#define LOG_NDEBUG 0 +//#define LOG_NNDEBUG 0 +#include "system/graphics-base-v1.1.h" +#define LOG_TAG "EmulatedSensor" +#define ATRACE_TAG ATRACE_TAG_CAMERA + +#ifdef LOG_NNDEBUG +#define ALOGVV(...) ALOGV(__VA_ARGS__) +#else +#define ALOGVV(...) ((void)0) +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "EmulatedSensor.h" +#include "utils/ExifUtils.h" +#include "utils/HWLUtils.h" + +namespace android { + +using android::google_camera_hal::ErrorCode; +using google_camera_hal::HalCameraMetadata; +using google_camera_hal::MessageType; +using google_camera_hal::NotifyMessage; + +using android::hardware::graphics::common::V1_2::Dataspace; + +// Copied from ColorSpace.java (see Named) +enum ColorSpaceNamed { + SRGB, + LINEAR_SRGB, + EXTENDED_SRGB, + LINEAR_EXTENDED_SRGB, + BT709, + BT2020, + DCI_P3, + DISPLAY_P3, + NTSC_1953, + SMPTE_C, + ADOBE_RGB, + PRO_PHOTO_RGB, + ACES, + ACESCG, + CIE_XYZ, + CIE_LAB +}; + +const uint32_t EmulatedSensor::kRegularSceneHandshake = 1; // Scene handshake divider +const uint32_t EmulatedSensor::kReducedSceneHandshake = 2; // Scene handshake divider + +// 1 us - 30 sec +const nsecs_t EmulatedSensor::kSupportedExposureTimeRange[2] = {1000LL, + 30000000000LL}; + +// ~1/30 s - 30 sec +const nsecs_t EmulatedSensor::kSupportedFrameDurationRange[2] = {33331760LL, + 30000000000LL}; + +const int32_t EmulatedSensor::kSupportedSensitivityRange[2] = {100, 1600}; +const int32_t EmulatedSensor::kDefaultSensitivity = 100; // ISO +const nsecs_t EmulatedSensor::kDefaultExposureTime = ms2ns(15); +const nsecs_t EmulatedSensor::kDefaultFrameDuration = ms2ns(33); +// Deadline within we should return the results as soon as possible to +// avoid skewing the frame cycle due to external delays. +const nsecs_t EmulatedSensor::kReturnResultThreshod = 3 * kDefaultFrameDuration; + +// Sensor defaults +const uint8_t EmulatedSensor::kSupportedColorFilterArrangement = + ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_RGGB; +const uint32_t EmulatedSensor::kDefaultMaxRawValue = 4000; +const uint32_t EmulatedSensor::kDefaultBlackLevelPattern[4] = {1000, 1000, 1000, + 1000}; + +const nsecs_t EmulatedSensor::kMinVerticalBlank = 10000L; + +// Sensor sensitivity +const float EmulatedSensor::kSaturationVoltage = 0.520f; +const uint32_t EmulatedSensor::kSaturationElectrons = 2000; +const float EmulatedSensor::kVoltsPerLuxSecond = 0.100f; + +const float EmulatedSensor::kElectronsPerLuxSecond = + EmulatedSensor::kSaturationElectrons / EmulatedSensor::kSaturationVoltage * + EmulatedSensor::kVoltsPerLuxSecond; + +const float EmulatedSensor::kReadNoiseStddevBeforeGain = 1.177; // in electrons +const float EmulatedSensor::kReadNoiseStddevAfterGain = + 2.100; // in digital counts +const float EmulatedSensor::kReadNoiseVarBeforeGain = + EmulatedSensor::kReadNoiseStddevBeforeGain * + EmulatedSensor::kReadNoiseStddevBeforeGain; +const float EmulatedSensor::kReadNoiseVarAfterGain = + EmulatedSensor::kReadNoiseStddevAfterGain * + EmulatedSensor::kReadNoiseStddevAfterGain; + +const uint32_t EmulatedSensor::kMaxRAWStreams = 1; +const uint32_t EmulatedSensor::kMaxProcessedStreams = 3; +const uint32_t EmulatedSensor::kMaxStallingStreams = 2; +const uint32_t EmulatedSensor::kMaxInputStreams = 1; + +const uint32_t EmulatedSensor::kMaxLensShadingMapSize[2]{64, 64}; +const int32_t EmulatedSensor::kFixedBitPrecision = 64; // 6-bit +// In fixed-point math, saturation point of sensor after gain +const int32_t EmulatedSensor::kSaturationPoint = kFixedBitPrecision * 255; +const camera_metadata_rational EmulatedSensor::kNeutralColorPoint[3] = { + {255, 1}, {255, 1}, {255, 1}}; +const float EmulatedSensor::kGreenSplit = 1.f; // No divergence +// Reduce memory usage by allowing only one buffer in sensor, one in jpeg +// compressor and one pending request to avoid stalls. +const uint8_t EmulatedSensor::kPipelineDepth = 3; + +const camera_metadata_rational EmulatedSensor::kDefaultColorTransform[9] = { + {1, 1}, {0, 1}, {0, 1}, {0, 1}, {1, 1}, {0, 1}, {0, 1}, {0, 1}, {1, 1}}; +const float EmulatedSensor::kDefaultColorCorrectionGains[4] = {1.0f, 1.0f, 1.0f, + 1.0f}; + +const float EmulatedSensor::kDefaultToneMapCurveRed[4] = {.0f, .0f, 1.f, 1.f}; +const float EmulatedSensor::kDefaultToneMapCurveGreen[4] = {.0f, .0f, 1.f, 1.f}; +const float EmulatedSensor::kDefaultToneMapCurveBlue[4] = {.0f, .0f, 1.f, 1.f}; + +// All XY matrix coefficients sourced from +// https://developer.android.com/reference/kotlin/android/graphics/ColorSpace.Named +// and XYZ coefficients calculated using the method found in +// ColorSpace.Rgb.computeXyzMatrix +struct XyzMatrix { + float xR = 3.2406f; + float yR = -1.5372f; + float zR = -0.4986f; + float xG = -0.9689f; + float yG = 1.8758f; + float zG = 0.0415f; + float xB = 0.0557f; + float yB = -0.2040f; + float zB = 1.0570f; +}; + +static const XyzMatrix kSrgbXyzMatrix = {3.2406f, -1.5372f, -0.4986f, + -0.9689f, 1.8758f, 0.0415f, + 0.0557f, -0.2040f, 1.0570f}; + +static const XyzMatrix kDisplayP3Matrix = {2.4931f, -0.9316f, -0.4023f, + -0.8291f, 1.7627f, 0.0234f, + 0.0361f, -0.0761f, 0.9570f}; + +static const XyzMatrix kBt709Matrix = {3.2410f, -1.5374f, -0.4986f, + -0.9692f, 1.8760f, 0.0416f, + 0.0556f, -0.2040f, 1.0570f}; + +static const XyzMatrix kBt2020Matrix = {1.7167f, -0.3556f, -0.2534f, + -0.6666f, 1.6164f, 0.0158f, + 0.0177f, -0.0428f, 0.9421f}; + +/** A few utility functions for math, normal distributions */ + +// Take advantage of IEEE floating-point format to calculate an approximate +// square root. Accurate to within +-3.6% +float sqrtf_approx(float r) { + // Modifier is based on IEEE floating-point representation; the + // manipulations boil down to finding approximate log2, dividing by two, and + // then inverting the log2. A bias is added to make the relative error + // symmetric about the real answer. + const int32_t modifier = 0x1FBB4000; + + int32_t r_i = *(int32_t*)(&r); + r_i = (r_i >> 1) + modifier; + + return *(float*)(&r_i); +} + +EmulatedSensor::EmulatedSensor() : Thread(false), got_vsync_(false) { + gamma_table_sRGB_.resize(kSaturationPoint + 1); + gamma_table_smpte170m_.resize(kSaturationPoint + 1); + gamma_table_hlg_.resize(kSaturationPoint + 1); + for (int32_t i = 0; i <= kSaturationPoint; i++) { + gamma_table_sRGB_[i] = ApplysRGBGamma(i, kSaturationPoint); + gamma_table_smpte170m_[i] = ApplySMPTE170MGamma(i, kSaturationPoint); + gamma_table_hlg_[i] = ApplyHLGGamma(i, kSaturationPoint); + } +} + +EmulatedSensor::~EmulatedSensor() { + ShutDown(); +} + +bool EmulatedSensor::AreCharacteristicsSupported( + const SensorCharacteristics& characteristics) { + if ((characteristics.width == 0) || (characteristics.height == 0)) { + ALOGE("%s: Invalid sensor size %zux%zu", __FUNCTION__, + characteristics.width, characteristics.height); + return false; + } + + if ((characteristics.full_res_width == 0) || + (characteristics.full_res_height == 0)) { + ALOGE("%s: Invalid sensor full res size %zux%zu", __FUNCTION__, + characteristics.full_res_width, characteristics.full_res_height); + return false; + } + + if (characteristics.is_10bit_dynamic_range_capable) { + // We support only HLG10 at the moment + const auto& hlg10_entry = characteristics.dynamic_range_profiles.find( + ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HLG10); + if ((characteristics.dynamic_range_profiles.size() != 1) || + (hlg10_entry == characteristics.dynamic_range_profiles.end())) { + ALOGE("%s: Only support for HLG10 is available!", __FUNCTION__); + return false; + } + } + + if ((characteristics.exposure_time_range[0] >= + characteristics.exposure_time_range[1]) || + ((characteristics.exposure_time_range[0] < kSupportedExposureTimeRange[0]) || + (characteristics.exposure_time_range[1] > + kSupportedExposureTimeRange[1]))) { + ALOGE("%s: Unsupported exposure range", __FUNCTION__); + return false; + } + + if ((characteristics.frame_duration_range[0] >= + characteristics.frame_duration_range[1]) || + ((characteristics.frame_duration_range[0] < + kSupportedFrameDurationRange[0]) || + (characteristics.frame_duration_range[1] > + kSupportedFrameDurationRange[1]))) { + ALOGE("%s: Unsupported frame duration range", __FUNCTION__); + return false; + } + + if ((characteristics.sensitivity_range[0] >= + characteristics.sensitivity_range[1]) || + ((characteristics.sensitivity_range[0] < kSupportedSensitivityRange[0]) || + (characteristics.sensitivity_range[1] > kSupportedSensitivityRange[1])) || + (!((kDefaultSensitivity >= characteristics.sensitivity_range[0]) && + (kDefaultSensitivity <= characteristics.sensitivity_range[1])))) { + ALOGE("%s: Unsupported sensitivity range", __FUNCTION__); + return false; + } + + if (characteristics.color_arangement != kSupportedColorFilterArrangement) { + ALOGE("%s: Unsupported color arrangement!", __FUNCTION__); + return false; + } + + for (const auto& blackLevel : characteristics.black_level_pattern) { + if (blackLevel >= characteristics.max_raw_value) { + ALOGE("%s: Black level matches or exceeds max RAW value!", __FUNCTION__); + return false; + } + } + + if ((characteristics.frame_duration_range[0] / characteristics.height) == 0) { + ALOGE("%s: Zero row readout time!", __FUNCTION__); + return false; + } + + if (characteristics.max_raw_streams > kMaxRAWStreams) { + ALOGE("%s: RAW streams maximum %u exceeds supported maximum %u", + __FUNCTION__, characteristics.max_raw_streams, kMaxRAWStreams); + return false; + } + + if (characteristics.max_processed_streams > kMaxProcessedStreams) { + ALOGE("%s: Processed streams maximum %u exceeds supported maximum %u", + __FUNCTION__, characteristics.max_processed_streams, + kMaxProcessedStreams); + return false; + } + + if (characteristics.max_stalling_streams > kMaxStallingStreams) { + ALOGE("%s: Stalling streams maximum %u exceeds supported maximum %u", + __FUNCTION__, characteristics.max_stalling_streams, + kMaxStallingStreams); + return false; + } + + if (characteristics.max_input_streams > kMaxInputStreams) { + ALOGE("%s: Input streams maximum %u exceeds supported maximum %u", + __FUNCTION__, characteristics.max_input_streams, kMaxInputStreams); + return false; + } + + if ((characteristics.lens_shading_map_size[0] > kMaxLensShadingMapSize[0]) || + (characteristics.lens_shading_map_size[1] > kMaxLensShadingMapSize[1])) { + ALOGE("%s: Lens shading map [%dx%d] exceeds supprorted maximum [%dx%d]", + __FUNCTION__, characteristics.lens_shading_map_size[0], + characteristics.lens_shading_map_size[1], kMaxLensShadingMapSize[0], + kMaxLensShadingMapSize[1]); + return false; + } + + if (characteristics.max_pipeline_depth < kPipelineDepth) { + ALOGE("%s: Pipeline depth %d smaller than supprorted minimum %d", + __FUNCTION__, characteristics.max_pipeline_depth, kPipelineDepth); + return false; + } + + return true; +} + +static void SplitStreamCombination( + const StreamConfiguration& original_config, + StreamConfiguration* default_mode_config, + StreamConfiguration* max_resolution_mode_config, + StreamConfiguration* input_stream_config) { + // Go through the streams + if (default_mode_config == nullptr || max_resolution_mode_config == nullptr || + input_stream_config == nullptr) { + ALOGE("%s: Input stream / output stream configs are nullptr", __FUNCTION__); + return; + } + for (const auto& stream : original_config.streams) { + if (stream.stream_type == google_camera_hal::StreamType::kInput) { + input_stream_config->streams.push_back(stream); + continue; + } + if (stream.intended_for_default_resolution_mode) { + default_mode_config->streams.push_back(stream); + } + if (stream.intended_for_max_resolution_mode) { + max_resolution_mode_config->streams.push_back(stream); + } + } +} + +bool EmulatedSensor::IsStreamCombinationSupported( + uint32_t logical_id, const StreamConfiguration& config, + StreamConfigurationMap& default_config_map, + StreamConfigurationMap& max_resolution_config_map, + const PhysicalStreamConfigurationMap& physical_map, + const PhysicalStreamConfigurationMap& physical_map_max_resolution, + const LogicalCharacteristics& sensor_chars) { + StreamConfiguration default_mode_config, max_resolution_mode_config, + input_stream_config; + SplitStreamCombination(config, &default_mode_config, + &max_resolution_mode_config, &input_stream_config); + + return IsStreamCombinationSupported(logical_id, default_mode_config, + default_config_map, physical_map, + sensor_chars) && + IsStreamCombinationSupported( + logical_id, max_resolution_mode_config, max_resolution_config_map, + physical_map_max_resolution, sensor_chars, /*is_max_res*/ true) && + + (IsStreamCombinationSupported(logical_id, input_stream_config, + default_config_map, physical_map, + sensor_chars) || + IsStreamCombinationSupported( + logical_id, input_stream_config, max_resolution_config_map, + physical_map_max_resolution, sensor_chars, /*is_max_res*/ true)); +} + +bool EmulatedSensor::IsStreamCombinationSupported( + uint32_t logical_id, const StreamConfiguration& config, + StreamConfigurationMap& config_map, + const PhysicalStreamConfigurationMap& physical_map, + const LogicalCharacteristics& sensor_chars, bool is_max_res) { + uint32_t input_stream_count = 0; + // Map from physical camera id to number of streams for that physical camera + std::map raw_stream_count; + std::map processed_stream_count; + std::map stalling_stream_count; + + // Only allow the stream configurations specified in + // dynamicSizeStreamConfigurations. + for (const auto& stream : config.streams) { + bool is_dynamic_output = + (stream.is_physical_camera_stream && stream.group_id != -1); + if (stream.rotation != google_camera_hal::StreamRotation::kRotation0) { + ALOGE("%s: Stream rotation: 0x%x not supported!", __FUNCTION__, + stream.rotation); + return false; + } + + if (stream.stream_type == google_camera_hal::StreamType::kInput) { + if (sensor_chars.at(logical_id).max_input_streams == 0) { + ALOGE("%s: Input streams are not supported on this device!", + __FUNCTION__); + return false; + } + + auto const& supported_outputs = + config_map.GetValidOutputFormatsForInput(stream.format); + if (supported_outputs.empty()) { + ALOGE("%s: Input stream with format: 0x%x no supported on this device!", + __FUNCTION__, stream.format); + return false; + } + + input_stream_count++; + } else { + if (stream.is_physical_camera_stream && + physical_map.find(stream.physical_camera_id) == physical_map.end()) { + ALOGE("%s: Invalid physical camera id %d", __FUNCTION__, + stream.physical_camera_id); + return false; + } + + if (is_dynamic_output) { + auto dynamic_physical_output_formats = + physical_map.at(stream.physical_camera_id) + ->GetDynamicPhysicalStreamOutputFormats(); + if (dynamic_physical_output_formats.find(stream.format) == + dynamic_physical_output_formats.end()) { + ALOGE("%s: Unsupported physical stream format %d", __FUNCTION__, + stream.format); + return false; + } + } + + if (stream.dynamic_profile != + ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD) { + const SensorCharacteristics& sensor_char = + stream.is_physical_camera_stream + ? sensor_chars.at(stream.physical_camera_id) + : sensor_chars.at(logical_id); + if (!sensor_char.is_10bit_dynamic_range_capable) { + ALOGE("%s: 10-bit dynamic range output not supported on this device!", + __FUNCTION__); + return false; + } + + if ((stream.format != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) && + (static_cast(stream.format) != + HAL_PIXEL_FORMAT_YCBCR_P010)) { + ALOGE( + "%s: 10-bit dynamic range profile 0x%x not supported on a non " + "10-bit output stream" + " pixel format 0x%x", + __FUNCTION__, stream.dynamic_profile, stream.format); + return false; + } + + if ((static_cast(stream.format) == + HAL_PIXEL_FORMAT_YCBCR_P010) && + ((stream.data_space != + static_cast(Dataspace::BT2020_ITU_HLG)) && + (stream.data_space != + static_cast(Dataspace::BT2020_HLG)) && + (stream.data_space != + static_cast(Dataspace::UNKNOWN)))) { + ALOGE( + "%s: Unsupported stream data space 0x%x for 10-bit YUV " + "output", + __FUNCTION__, stream.data_space); + return false; + } + } + + switch (stream.format) { + case HAL_PIXEL_FORMAT_BLOB: + if ((stream.data_space != HAL_DATASPACE_V0_JFIF) && + (stream.data_space != HAL_DATASPACE_UNKNOWN)) { + ALOGE("%s: Unsupported Blob dataspace 0x%x", __FUNCTION__, + stream.data_space); + return false; + } + if (stream.is_physical_camera_stream) { + stalling_stream_count[stream.physical_camera_id]++; + } else { + for (const auto& p : physical_map) { + stalling_stream_count[p.first]++; + } + } + break; + case HAL_PIXEL_FORMAT_RAW16: { + const SensorCharacteristics& sensor_char = + stream.is_physical_camera_stream + ? sensor_chars.at(stream.physical_camera_id) + : sensor_chars.at(logical_id); + auto sensor_height = + is_max_res ? sensor_char.full_res_height : sensor_char.height; + auto sensor_width = + is_max_res ? sensor_char.full_res_width : sensor_char.width; + if (stream.height != sensor_height || stream.width != sensor_width) { + ALOGE( + "%s, RAW16 buffer height %d and width %d must match sensor " + "height: %zu" + " and width: %zu", + __FUNCTION__, stream.height, stream.width, sensor_height, + sensor_width); + return false; + } + if (stream.is_physical_camera_stream) { + raw_stream_count[stream.physical_camera_id]++; + } else { + for (const auto& p : physical_map) { + raw_stream_count[p.first]++; + } + } + } break; + default: + if (stream.is_physical_camera_stream) { + processed_stream_count[stream.physical_camera_id]++; + } else { + for (const auto& p : physical_map) { + processed_stream_count[p.first]++; + } + } + } + + auto output_sizes = + is_dynamic_output + ? physical_map.at(stream.physical_camera_id) + ->GetDynamicPhysicalStreamOutputSizes(stream.format) + : stream.is_physical_camera_stream + ? physical_map.at(stream.physical_camera_id) + ->GetOutputSizes(stream.format) + : config_map.GetOutputSizes(stream.format); + + auto stream_size = std::make_pair(stream.width, stream.height); + if (output_sizes.find(stream_size) == output_sizes.end()) { + ALOGE("%s: Stream with size %dx%d and format 0x%x is not supported!", + __FUNCTION__, stream.width, stream.height, stream.format); + return false; + } + } + + if (!sensor_chars.at(logical_id).support_stream_use_case) { + if (stream.use_case != ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT) { + ALOGE("%s: Camera device doesn't support non-default stream use case!", + __FUNCTION__); + return false; + } + } else if (stream.use_case > + sensor_chars.at(logical_id).end_valid_stream_use_case) { + ALOGE("%s: Stream with use case %d is not supported!", __FUNCTION__, + stream.use_case); + return false; + } else if (stream.use_case != + ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT) { + if (stream.use_case == + ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_STILL_CAPTURE) { + if (stream.format != HAL_PIXEL_FORMAT_YCBCR_420_888 && + stream.format != HAL_PIXEL_FORMAT_BLOB) { + ALOGE("%s: Stream with use case %d isn't compatible with format %d", + __FUNCTION__, stream.use_case, stream.format); + return false; + } + } else if ((stream.format == HAL_PIXEL_FORMAT_RAW16) ^ + (stream.use_case == + ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_CROPPED_RAW)) { + // Either both stream use case == CROPPED_RAW and format == RAW16, or + // stream use case != CROPPED_RAW and format != RAW16 for the + // combination to be valid. + ALOGE( + "%s: Stream with use case CROPPED_RAW isn't compatible with non " + "RAW_SENSOR formats", + __FUNCTION__); + return false; + + } else if (stream.format != HAL_PIXEL_FORMAT_YCBCR_420_888 && + stream.format != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED && + stream.format != HAL_PIXEL_FORMAT_RAW16) { + ALOGE("%s: Stream with use case %d isn't compatible with format %d", + __FUNCTION__, stream.use_case, stream.format); + return false; + } + } + } + + for (const auto& raw_count : raw_stream_count) { + unsigned int max_raw_streams = + sensor_chars.at(raw_count.first).max_raw_streams + + (is_max_res + ? 1 + : 0); // The extra raw stream is allowed for remosaic reprocessing. + if (raw_count.second > max_raw_streams) { + ALOGE("%s: RAW streams maximum %u exceeds supported maximum %u", + __FUNCTION__, raw_count.second, max_raw_streams); + return false; + } + } + + for (const auto& stalling_count : stalling_stream_count) { + if (stalling_count.second > + sensor_chars.at(stalling_count.first).max_stalling_streams) { + ALOGE("%s: Stalling streams maximum %u exceeds supported maximum %u", + __FUNCTION__, stalling_count.second, + sensor_chars.at(stalling_count.first).max_stalling_streams); + return false; + } + } + + for (const auto& processed_count : processed_stream_count) { + if (processed_count.second > + sensor_chars.at(processed_count.first).max_processed_streams) { + ALOGE("%s: Processed streams maximum %u exceeds supported maximum %u", + __FUNCTION__, processed_count.second, + sensor_chars.at(processed_count.first).max_processed_streams); + return false; + } + } + + if (input_stream_count > sensor_chars.at(logical_id).max_input_streams) { + ALOGE("%s: Input stream maximum %u exceeds supported maximum %u", + __FUNCTION__, input_stream_count, + sensor_chars.at(logical_id).max_input_streams); + return false; + } + + // TODO: Check session parameters. For now assuming all combinations + // are supported. + + return true; +} + +status_t EmulatedSensor::StartUp( + uint32_t logical_camera_id, + std::unique_ptr logical_chars) { + if (isRunning()) { + return OK; + } + + if (logical_chars.get() == nullptr) { + return BAD_VALUE; + } + + chars_ = std::move(logical_chars); + auto device_chars = chars_->find(logical_camera_id); + if (device_chars == chars_->end()) { + ALOGE( + "%s: Logical camera id: %u absent from logical camera characteristics!", + __FUNCTION__, logical_camera_id); + return BAD_VALUE; + } + + for (const auto& it : *chars_) { + if (!AreCharacteristicsSupported(it.second)) { + ALOGE("%s: Sensor characteristics for camera id: %u not supported!", + __FUNCTION__, it.first); + return BAD_VALUE; + } + } + + logical_camera_id_ = logical_camera_id; + scene_ = std::make_unique( + device_chars->second.full_res_width, device_chars->second.full_res_height, + kElectronsPerLuxSecond, device_chars->second.orientation, + device_chars->second.is_front_facing); + jpeg_compressor_ = std::make_unique(); + int orientation = device_chars->second.orientation; + + vmi_camera_ = VmiCameraFactory::CreateVmiCamera(logical_camera_id_, orientation); + vmi_camera_->Init(); + + auto res = run(LOG_TAG, ANDROID_PRIORITY_URGENT_DISPLAY); + if (res != OK) { + ALOGE("Unable to start up sensor capture thread: %d", res); + } + + return res; +} + +status_t EmulatedSensor::ShutDown() { + int res; + res = requestExitAndWait(); + if (res != OK) { + ALOGE("Unable to shut down sensor capture thread: %d", res); + } + vmi_camera_->StopPreview(); + start_preview_done_ = false; + return res; +} + +void EmulatedSensor::SetCurrentRequest( + std::unique_ptr logical_settings, + std::unique_ptr result, + std::unique_ptr partial_result, + std::unique_ptr input_buffers, + std::unique_ptr output_buffers) { + Mutex::Autolock lock(control_mutex_); + current_settings_ = std::move(logical_settings); + current_result_ = std::move(result); + current_input_buffers_ = std::move(input_buffers); + current_output_buffers_ = std::move(output_buffers); + partial_result_ = std::move(partial_result); +} + +bool EmulatedSensor::WaitForVSyncLocked(nsecs_t reltime) { + got_vsync_ = false; + while (!got_vsync_) { + auto res = vsync_.waitRelative(control_mutex_, reltime); + if (res != OK && res != TIMED_OUT) { + ALOGE("%s: Error waiting for VSync signal: %d", __FUNCTION__, res); + return false; + } + } + + return got_vsync_; +} + +bool EmulatedSensor::WaitForVSync(nsecs_t reltime) { + Mutex::Autolock lock(control_mutex_); + + return WaitForVSyncLocked(reltime); +} + +status_t EmulatedSensor::Flush() { + Mutex::Autolock lock(control_mutex_); + auto ret = WaitForVSyncLocked(kSupportedFrameDurationRange[1]); + + // First recreate the jpeg compressor. This will abort any ongoing processing + // and flush any pending jobs. + jpeg_compressor_ = std::make_unique(); + + // Then return any pending frames here + if ((current_input_buffers_.get() != nullptr) && + (!current_input_buffers_->empty())) { + current_input_buffers_->clear(); + } + if ((current_output_buffers_.get() != nullptr) && + (!current_output_buffers_->empty())) { + for (const auto& buffer : *current_output_buffers_) { + buffer->stream_buffer.status = BufferStatus::kError; + } + + if ((current_result_.get() != nullptr) && + (current_result_->result_metadata.get() != nullptr)) { + if (current_output_buffers_->at(0)->callback.notify != nullptr) { + NotifyMessage msg{ + .type = MessageType::kError, + .message.error = { + .frame_number = current_output_buffers_->at(0)->frame_number, + .error_stream_id = -1, + .error_code = ErrorCode::kErrorResult, + }}; + + current_output_buffers_->at(0)->callback.notify( + current_result_->pipeline_id, msg); + } + } + + current_output_buffers_->clear(); + } + + return ret ? OK : TIMED_OUT; +} + +nsecs_t EmulatedSensor::getSystemTimeWithSource(uint32_t timestamp_source) { + if (timestamp_source == ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE_REALTIME) { + return systemTime(SYSTEM_TIME_BOOTTIME); + } + return systemTime(SYSTEM_TIME_MONOTONIC); +} + +bool EmulatedSensor::threadLoop() { + ATRACE_CALL(); + /** + * Sensor capture operation main loop. + * + */ + + /** + * Stage 1: Read in latest control parameters + */ + std::unique_ptr next_buffers; + std::unique_ptr next_input_buffer; + std::unique_ptr next_result; + std::unique_ptr partial_result; + std::unique_ptr settings; + HwlPipelineCallback callback = { + .process_pipeline_result = nullptr, + .process_pipeline_batch_result = nullptr, + .notify = nullptr, + }; + { + Mutex::Autolock lock(control_mutex_); + std::swap(settings, current_settings_); + std::swap(next_buffers, current_output_buffers_); + std::swap(next_input_buffer, current_input_buffers_); + std::swap(next_result, current_result_); + std::swap(partial_result, partial_result_); + + // Signal VSync for start of readout + ALOGVV("Sensor VSync"); + got_vsync_ = true; + vsync_.signal(); + } + + auto frame_duration = EmulatedSensor::kSupportedFrameDurationRange[0]; + auto exposure_time = EmulatedSensor::kSupportedExposureTimeRange[0]; + uint32_t timestamp_source = ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE_UNKNOWN; + // Frame duration must always be the same among all physical devices + if ((settings.get() != nullptr) && (!settings->empty())) { + frame_duration = settings->begin()->second.frame_duration; + exposure_time = settings->begin()->second.exposure_time; + timestamp_source = settings->begin()->second.timestamp_source; + } + + nsecs_t start_real_time = getSystemTimeWithSource(timestamp_source); + // Stagefright cares about system time for timestamps, so base simulated + // time on that. + nsecs_t frame_end_real_time = start_real_time + frame_duration; + + /** + * Stage 2: Capture new image + */ + next_capture_time_ = frame_end_real_time; + next_readout_time_ = frame_end_real_time + exposure_time; + + sensor_binning_factor_info_.clear(); + + bool reprocess_request = false; + if ((next_input_buffer.get() != nullptr) && (!next_input_buffer->empty())) { + if (next_input_buffer->size() > 1) { + ALOGW("%s: Reprocess supports only single input!", __FUNCTION__); + } + + camera_metadata_ro_entry_t entry; + auto ret = + next_result->result_metadata->Get(ANDROID_SENSOR_TIMESTAMP, &entry); + if ((ret == OK) && (entry.count == 1)) { + next_capture_time_ = entry.data.i64[0]; + } else { + ALOGW("%s: Reprocess timestamp absent!", __FUNCTION__); + } + + ret = next_result->result_metadata->Get(ANDROID_SENSOR_EXPOSURE_TIME, + &entry); + if ((ret == OK) && (entry.count == 1)) { + next_readout_time_ = next_capture_time_ + entry.data.i64[0]; + } else { + next_readout_time_ = next_capture_time_; + } + + reprocess_request = true; + } + + if ((next_buffers != nullptr) && (settings != nullptr)) { + callback = next_buffers->at(0)->callback; + if (callback.notify != nullptr) { + NotifyMessage msg{ + .type = MessageType::kShutter, + .message.shutter = { + .frame_number = next_buffers->at(0)->frame_number, + .timestamp_ns = static_cast(next_capture_time_), + .readout_timestamp_ns = + static_cast(next_readout_time_)}}; + callback.notify(next_result->pipeline_id, msg); + } + auto b = next_buffers->begin(); + while (b != next_buffers->end()) { + auto device_settings = settings->find((*b)->camera_id); + if (device_settings == settings->end()) { + ALOGE("%s: Sensor settings absent for device: %d", __func__, + (*b)->camera_id); + b = next_buffers->erase(b); + continue; + } + + auto device_chars = chars_->find((*b)->camera_id); + if (device_chars == chars_->end()) { + ALOGE("%s: Sensor characteristics absent for device: %d", __func__, + (*b)->camera_id); + b = next_buffers->erase(b); + continue; + } + + sensor_binning_factor_info_[(*b)->camera_id].quad_bayer_sensor = + device_chars->second.quad_bayer_sensor; + + ALOGVV("Starting next capture: Exposure: %" PRIu64 " ms, gain: %d", + ns2ms(device_settings->second.exposure_time), + device_settings->second.gain); + + scene_->Initialize(device_chars->second.full_res_width, + device_chars->second.full_res_height, + kElectronsPerLuxSecond); + scene_->SetExposureDuration((float)device_settings->second.exposure_time / + 1e9); + scene_->SetColorFilterXYZ(device_chars->second.color_filter.rX, + device_chars->second.color_filter.rY, + device_chars->second.color_filter.rZ, + device_chars->second.color_filter.grX, + device_chars->second.color_filter.grY, + device_chars->second.color_filter.grZ, + device_chars->second.color_filter.gbX, + device_chars->second.color_filter.gbY, + device_chars->second.color_filter.gbZ, + device_chars->second.color_filter.bX, + device_chars->second.color_filter.bY, + device_chars->second.color_filter.bZ); + scene_->SetTestPattern(device_settings->second.test_pattern_mode == + ANDROID_SENSOR_TEST_PATTERN_MODE_SOLID_COLOR); + scene_->SetTestPatternData(device_settings->second.test_pattern_data); + scene_->SetScreenRotation(device_settings->second.screen_rotation); + + uint32_t handshake_divider = + (device_settings->second.video_stab == + ANDROID_CONTROL_VIDEO_STABILIZATION_MODE_ON) || + (device_settings->second.video_stab == + ANDROID_CONTROL_VIDEO_STABILIZATION_MODE_PREVIEW_STABILIZATION) + ? kReducedSceneHandshake + : kRegularSceneHandshake; + scene_->CalculateScene(next_capture_time_, handshake_divider); + + (*b)->stream_buffer.status = BufferStatus::kOk; + bool max_res_mode = device_settings->second.sensor_pixel_mode; + sensor_binning_factor_info_[(*b)->camera_id].max_res_request = + max_res_mode; + switch ((*b)->format) { + case PixelFormat::RAW16: + sensor_binning_factor_info_[(*b)->camera_id].has_raw_stream = true; + if (!sensor_binning_factor_info_[(*b)->camera_id] + .has_cropped_raw_stream && + (*b)->use_case == + ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_CROPPED_RAW) { + sensor_binning_factor_info_[(*b)->camera_id].has_cropped_raw_stream = + true; + } + break; + default: + sensor_binning_factor_info_[(*b)->camera_id].has_non_raw_stream = true; + } + + // TODO: remove hack. Implement RAW -> YUV / JPEG reprocessing http://b/192382904 + bool treat_as_reprocess = + (device_chars->second.quad_bayer_sensor && reprocess_request && + (*next_input_buffer->begin())->format == PixelFormat::RAW16) + ? false + : reprocess_request; + ProcessType process_type = treat_as_reprocess ? REPROCESS + : (device_settings->second.edge_mode == + ANDROID_EDGE_MODE_HIGH_QUALITY) + ? HIGH_QUALITY + : REGULAR; + + if ((*b)->color_space != + ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_UNSPECIFIED) { + CalculateRgbRgbMatrix((*b)->color_space, device_chars->second); + } + + switch ((*b)->format) { + case PixelFormat::RAW16: + if (!reprocess_request) { + uint64_t min_full_res_raw_size = + 2 * device_chars->second.full_res_width * + device_chars->second.full_res_height; + uint64_t min_default_raw_size = + 2 * device_chars->second.width * device_chars->second.height; + bool default_mode_for_qb = + device_chars->second.quad_bayer_sensor && !max_res_mode; + size_t buffer_size = (*b)->plane.img.buffer_size; + if (default_mode_for_qb) { + if (buffer_size < min_default_raw_size) { + ALOGE( + "%s: Output buffer size too small for RAW capture in " + "default " + "mode, " + "expected %" PRIu64 ", got %zu, for camera id %d", + __FUNCTION__, min_default_raw_size, buffer_size, + (*b)->camera_id); + (*b)->stream_buffer.status = BufferStatus::kError; + break; + } + } else if (buffer_size < min_full_res_raw_size) { + ALOGE( + "%s: Output buffer size too small for RAW capture in max res " + "mode, " + "expected %" PRIu64 ", got %zu, for camera id %d", + __FUNCTION__, min_full_res_raw_size, buffer_size, + (*b)->camera_id); + (*b)->stream_buffer.status = BufferStatus::kError; + break; + } + if (default_mode_for_qb) { + if (device_settings->second.zoom_ratio > 2.0f && + ((*b)->use_case == + ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_CROPPED_RAW)) { + sensor_binning_factor_info_[(*b)->camera_id] + .raw_in_sensor_zoom_applied = true; + CaptureRawInSensorZoom( + (*b)->plane.img.img, (*b)->plane.img.stride_in_bytes, + device_settings->second.gain, device_chars->second); + + } else { + CaptureRawBinned( + (*b)->plane.img.img, (*b)->plane.img.stride_in_bytes, + device_settings->second.gain, device_chars->second); + } + } else { + CaptureRawFullRes( + (*b)->plane.img.img, (*b)->plane.img.stride_in_bytes, + device_settings->second.gain, device_chars->second); + } + } else { + if (!device_chars->second.quad_bayer_sensor) { + ALOGE( + "%s: Reprocess requests with output format %x no supported!", + __FUNCTION__, (*b)->format); + (*b)->stream_buffer.status = BufferStatus::kError; + break; + } + // Remosaic the RAW input buffer + if ((*next_input_buffer->begin())->width != (*b)->width || + (*next_input_buffer->begin())->height != (*b)->height) { + ALOGE( + "%s: RAW16 input dimensions %dx%d don't match output buffer " + "dimensions %dx%d", + __FUNCTION__, (*next_input_buffer->begin())->width, + (*next_input_buffer->begin())->height, (*b)->width, + (*b)->height); + (*b)->stream_buffer.status = BufferStatus::kError; + break; + } + ALOGV("%s remosaic Raw16 Image", __FUNCTION__); + RemosaicRAW16Image( + (uint16_t*)(*next_input_buffer->begin())->plane.img.img, + (uint16_t*)(*b)->plane.img.img, (*b)->plane.img.stride_in_bytes, + device_chars->second); + } + break; + case PixelFormat::RGB_888: + if (!reprocess_request) { + CaptureRGB((*b)->plane.img.img, (*b)->width, (*b)->height, + (*b)->plane.img.stride_in_bytes, RGBLayout::RGB, + device_settings->second.gain, (*b)->color_space, + device_chars->second); + } else { + ALOGE("%s: Reprocess requests with output format %x no supported!", + __FUNCTION__, (*b)->format); + (*b)->stream_buffer.status = BufferStatus::kError; + } + break; + case PixelFormat::RGBA_8888: + if (!reprocess_request) { + CaptureRGB((*b)->plane.img.img, (*b)->width, (*b)->height, + (*b)->plane.img.stride_in_bytes, RGBLayout::RGBA, + device_settings->second.gain, (*b)->color_space, + device_chars->second); + } else { + ALOGE("%s: Reprocess requests with output format %x no supported!", + __FUNCTION__, (*b)->format); + (*b)->stream_buffer.status = BufferStatus::kError; + } + break; + case PixelFormat::BLOB: + if ((*b)->dataSpace == HAL_DATASPACE_V0_JFIF) { + YUV420Frame yuv_input{ + .width = treat_as_reprocess + ? (*next_input_buffer->begin())->width + : 0, + .height = treat_as_reprocess + ? (*next_input_buffer->begin())->height + : 0, + .planes = treat_as_reprocess + ? (*next_input_buffer->begin())->plane.img_y_crcb + : YCbCrPlanes{}}; + auto jpeg_input = std::make_unique(); + jpeg_input->width = (*b)->width; + jpeg_input->height = (*b)->height; + jpeg_input->color_space = (*b)->color_space; + auto img = + new uint8_t[(jpeg_input->width * jpeg_input->height * 3) / 2]; + jpeg_input->yuv_planes = { + .img_y = img, + .img_cb = img + jpeg_input->width * jpeg_input->height, + .img_cr = img + (jpeg_input->width * jpeg_input->height * 5) / 4, + .y_stride = jpeg_input->width, + .cbcr_stride = jpeg_input->width / 2, + .cbcr_step = 1}; + jpeg_input->buffer_owner = true; + YUV420Frame yuv_output{.width = jpeg_input->width, + .height = jpeg_input->height, + .planes = jpeg_input->yuv_planes}; + + bool rotate = device_settings->second.rotate_and_crop == + ANDROID_SCALER_ROTATE_AND_CROP_90; + auto ret = ProcessYUV420(yuv_input, yuv_output, + device_settings->second.gain, process_type, + device_settings->second.zoom_ratio, rotate, + (*b)->color_space, device_chars->second); + if (ret != 0) { + (*b)->stream_buffer.status = BufferStatus::kError; + break; + } + + auto jpeg_job = std::make_unique(); + jpeg_job->exif_utils = std::unique_ptr( + ExifUtils::Create(device_chars->second)); + jpeg_job->input = std::move(jpeg_input); + // If jpeg compression is successful, then the jpeg compressor + // must set the corresponding status. + (*b)->stream_buffer.status = BufferStatus::kError; + std::swap(jpeg_job->output, *b); + jpeg_job->result_metadata = + HalCameraMetadata::Clone(next_result->result_metadata.get()); + + Mutex::Autolock lock(control_mutex_); + jpeg_compressor_->QueueYUV420(std::move(jpeg_job)); + } else { + ALOGE("%s: Format %x with dataspace %x is TODO", __FUNCTION__, + (*b)->format, (*b)->dataSpace); + (*b)->stream_buffer.status = BufferStatus::kError; + } + break; + case PixelFormat::YCRCB_420_SP: + case PixelFormat::YCBCR_420_888: { + YUV420Frame yuv_input{ + .width = + treat_as_reprocess ? (*next_input_buffer->begin())->width : 0, + .height = + treat_as_reprocess ? (*next_input_buffer->begin())->height : 0, + .planes = treat_as_reprocess + ? (*next_input_buffer->begin())->plane.img_y_crcb + : YCbCrPlanes{}}; + YUV420Frame yuv_output{.width = (*b)->width, + .height = (*b)->height, + .planes = (*b)->plane.img_y_crcb}; + bool rotate = device_settings->second.rotate_and_crop == + ANDROID_SCALER_ROTATE_AND_CROP_90; + int fps = 1000000000LL / frame_duration; + auto ret = + ProcessYUV420(yuv_input, yuv_output, device_settings->second.gain, + process_type, device_settings->second.zoom_ratio, + rotate, (*b)->color_space, device_chars->second, fps); + if (ret != 0) { + (*b)->stream_buffer.status = BufferStatus::kError; + } + } break; + case PixelFormat::Y16: + if (!reprocess_request) { + if ((*b)->dataSpace == HAL_DATASPACE_DEPTH) { + CaptureDepth((*b)->plane.img.img, device_settings->second.gain, + (*b)->width, (*b)->height, + (*b)->plane.img.stride_in_bytes, + device_chars->second); + } else { + ALOGE("%s: Format %x with dataspace %x is TODO", __FUNCTION__, + (*b)->format, (*b)->dataSpace); + (*b)->stream_buffer.status = BufferStatus::kError; + } + } else { + ALOGE("%s: Reprocess requests with output format %x no supported!", + __FUNCTION__, (*b)->format); + (*b)->stream_buffer.status = BufferStatus::kError; + } + break; + case PixelFormat::YCBCR_P010: + if (!reprocess_request) { + bool rotate = device_settings->second.rotate_and_crop == + ANDROID_SCALER_ROTATE_AND_CROP_90; + YUV420Frame yuv_input{}; + YUV420Frame yuv_output{.width = (*b)->width, + .height = (*b)->height, + .planes = (*b)->plane.img_y_crcb}; + ProcessYUV420(yuv_input, yuv_output, device_settings->second.gain, + process_type, device_settings->second.zoom_ratio, + rotate, (*b)->color_space, device_chars->second); + } else { + ALOGE( + "%s: Reprocess requests with output format %x no supported!", + __FUNCTION__, (*b)->format); + (*b)->stream_buffer.status = BufferStatus::kError; + } + break; + default: + ALOGE("%s: Unknown format %x, no output", __FUNCTION__, (*b)->format); + (*b)->stream_buffer.status = BufferStatus::kError; + break; + } + + b = next_buffers->erase(b); + } + } + + if (reprocess_request) { + auto input_buffer = next_input_buffer->begin(); + while (input_buffer != next_input_buffer->end()) { + (*input_buffer++)->stream_buffer.status = BufferStatus::kOk; + } + next_input_buffer->clear(); + } + + nsecs_t work_done_real_time = getSystemTimeWithSource(timestamp_source); + // Returning the results at this point is not entirely correct from timing + // perspective. Under ideal conditions where 'ReturnResults' completes + // in less than 'time_accuracy' we need to return the results after the + // frame cycle expires. However under real conditions various system + // components like SurfaceFlinger, Encoder, LMK etc. could be consuming most + // of the resources and the duration of "ReturnResults" can get comparable to + // 'kDefaultFrameDuration'. This will skew the frame cycle and can result in + // potential frame drops. To avoid this scenario when we are running under + // tight deadlines (less than 'kReturnResultThreshod') try to return the + // results immediately. In all other cases with more relaxed deadlines + // the occasional bump during 'ReturnResults' should not have any + // noticeable effect. + if ((work_done_real_time + kReturnResultThreshod) > frame_end_real_time) { + ReturnResults(callback, std::move(settings), std::move(next_result), + reprocess_request, std::move(partial_result)); + } + + work_done_real_time = getSystemTimeWithSource(timestamp_source); + ALOGVV("Sensor vertical blanking interval"); + const nsecs_t time_accuracy = 2e6; // 2 ms of imprecision is ok + if (work_done_real_time < frame_end_real_time - time_accuracy) { + timespec t; + t.tv_sec = (frame_end_real_time - work_done_real_time) / 1000000000L; + t.tv_nsec = (frame_end_real_time - work_done_real_time) % 1000000000L; + + int ret; + do { + ret = nanosleep(&t, &t); + } while (ret != 0); + } + + ReturnResults(callback, std::move(settings), std::move(next_result), + reprocess_request, std::move(partial_result)); + + return true; +}; + +void EmulatedSensor::ReturnResults( + HwlPipelineCallback callback, + std::unique_ptr settings, + std::unique_ptr result, bool reprocess_request, + std::unique_ptr partial_result) { + if ((callback.process_pipeline_result != nullptr) && + (result.get() != nullptr) && (result->result_metadata.get() != nullptr)) { + auto logical_settings = settings->find(logical_camera_id_); + if (logical_settings == settings->end()) { + ALOGE("%s: Logical camera id: %u not found in settings!", __FUNCTION__, + logical_camera_id_); + return; + } + auto device_chars = chars_->find(logical_camera_id_); + if (device_chars == chars_->end()) { + ALOGE("%s: Sensor characteristics absent for device: %d", __func__, + logical_camera_id_); + return; + } + result->result_metadata->Set(ANDROID_SENSOR_TIMESTAMP, &next_capture_time_, + 1); + + camera_metadata_ro_entry_t lensEntry; + auto lensRet = result->result_metadata->Get( + ANDROID_STATISTICS_LENS_INTRINSIC_SAMPLES, &lensEntry); + if ((lensRet == OK) && (lensEntry.count > 0)) { + result->result_metadata->Set(ANDROID_STATISTICS_LENS_INTRINSIC_TIMESTAMPS, + &next_capture_time_, 1); + } + + uint8_t raw_binned_factor_used = false; + if (sensor_binning_factor_info_.find(logical_camera_id_) != + sensor_binning_factor_info_.end()) { + auto& info = sensor_binning_factor_info_[logical_camera_id_]; + // Logical stream was included in the request + if (!reprocess_request && info.quad_bayer_sensor && info.max_res_request && + info.has_raw_stream && !info.has_non_raw_stream) { + raw_binned_factor_used = true; + } + result->result_metadata->Set(ANDROID_SENSOR_RAW_BINNING_FACTOR_USED, + &raw_binned_factor_used, 1); + if (info.has_cropped_raw_stream) { + if (info.raw_in_sensor_zoom_applied) { + result->result_metadata->Set( + ANDROID_SCALER_RAW_CROP_REGION, + device_chars->second.raw_crop_region_zoomed, 4); + + } else { + result->result_metadata->Set( + ANDROID_SCALER_RAW_CROP_REGION, + device_chars->second.raw_crop_region_unzoomed, 4); + } + } + } + if (logical_settings->second.lens_shading_map_mode == + ANDROID_STATISTICS_LENS_SHADING_MAP_MODE_ON) { + if ((device_chars->second.lens_shading_map_size[0] > 0) && + (device_chars->second.lens_shading_map_size[1] > 0)) { + // Perfect lens, no actual shading needed. + std::vector lens_shading_map( + device_chars->second.lens_shading_map_size[0] * + device_chars->second.lens_shading_map_size[1] * 4, + 1.f); + + result->result_metadata->Set(ANDROID_STATISTICS_LENS_SHADING_MAP, + lens_shading_map.data(), + lens_shading_map.size()); + } + } + if (logical_settings->second.report_video_stab) { + result->result_metadata->Set(ANDROID_CONTROL_VIDEO_STABILIZATION_MODE, + &logical_settings->second.video_stab, 1); + } + if (logical_settings->second.report_edge_mode) { + result->result_metadata->Set(ANDROID_EDGE_MODE, + &logical_settings->second.edge_mode, 1); + } + if (logical_settings->second.report_neutral_color_point) { + result->result_metadata->Set(ANDROID_SENSOR_NEUTRAL_COLOR_POINT, + kNeutralColorPoint, + ARRAY_SIZE(kNeutralColorPoint)); + } + if (logical_settings->second.report_green_split) { + result->result_metadata->Set(ANDROID_SENSOR_GREEN_SPLIT, &kGreenSplit, 1); + } + if (logical_settings->second.report_noise_profile) { + CalculateAndAppendNoiseProfile( + logical_settings->second.gain, + GetBaseGainFactor(device_chars->second.max_raw_value), + result->result_metadata.get()); + } + if (logical_settings->second.report_rotate_and_crop) { + result->result_metadata->Set(ANDROID_SCALER_ROTATE_AND_CROP, + &logical_settings->second.rotate_and_crop, 1); + } + + if (!result->physical_camera_results.empty()) { + for (auto& it : result->physical_camera_results) { + auto physical_settings = settings->find(it.first); + if (physical_settings == settings->end()) { + ALOGE("%s: Physical settings for camera id: %u are absent!", + __FUNCTION__, it.first); + continue; + } + uint8_t raw_binned_factor_used = false; + if (sensor_binning_factor_info_.find(it.first) != + sensor_binning_factor_info_.end()) { + auto& info = sensor_binning_factor_info_[it.first]; + // physical stream was included in the request + if (!reprocess_request && info.quad_bayer_sensor && + info.max_res_request && info.has_raw_stream && + !info.has_non_raw_stream) { + raw_binned_factor_used = true; + } + it.second->Set(ANDROID_SENSOR_RAW_BINNING_FACTOR_USED, + &raw_binned_factor_used, 1); + } + // Sensor timestamp for all physical devices must be the same. + it.second->Set(ANDROID_SENSOR_TIMESTAMP, &next_capture_time_, 1); + if (physical_settings->second.report_neutral_color_point) { + it.second->Set(ANDROID_SENSOR_NEUTRAL_COLOR_POINT, kNeutralColorPoint, + ARRAY_SIZE(kNeutralColorPoint)); + } + if (physical_settings->second.report_green_split) { + it.second->Set(ANDROID_SENSOR_GREEN_SPLIT, &kGreenSplit, 1); + } + if (physical_settings->second.report_noise_profile) { + auto device_chars = chars_->find(it.first); + if (device_chars == chars_->end()) { + ALOGE("%s: Sensor characteristics absent for device: %d", __func__, + it.first); + } + CalculateAndAppendNoiseProfile( + physical_settings->second.gain, + GetBaseGainFactor(device_chars->second.max_raw_value), + it.second.get()); + } + } + } + + // Partial result count for partial result is set to a value + // only when partial results are supported + if (partial_result->partial_result != 0) { + callback.process_pipeline_result(std::move(partial_result)); + } + callback.process_pipeline_result(std::move(result)); + } +} + +void EmulatedSensor::CalculateAndAppendNoiseProfile( + float gain /*in ISO*/, float base_gain_factor, + HalCameraMetadata* result /*out*/) { + if (result != nullptr) { + float total_gain = gain / 100.0 * base_gain_factor; + float noise_var_gain = total_gain * total_gain; + float read_noise_var = + kReadNoiseVarBeforeGain * noise_var_gain + kReadNoiseVarAfterGain; + // Noise profile is the same across all 4 CFA channels + double noise_profile[2 * 4] = { + noise_var_gain, read_noise_var, noise_var_gain, read_noise_var, + noise_var_gain, read_noise_var, noise_var_gain, read_noise_var}; + result->Set(ANDROID_SENSOR_NOISE_PROFILE, noise_profile, + ARRAY_SIZE(noise_profile)); + } +} + +EmulatedScene::ColorChannels EmulatedSensor::GetQuadBayerColor(uint32_t x, + uint32_t y) { + // Row within larger set of quad bayer filter + uint32_t row_mod = y % 4; + // Column within larger set of quad bayer filter + uint32_t col_mod = x % 4; + + // Row is within the left quadrants of a quad bayer sensor + if (row_mod < 2) { + if (col_mod < 2) { + return EmulatedScene::ColorChannels::R; + } + return EmulatedScene::ColorChannels::Gr; + } else { + if (col_mod < 2) { + return EmulatedScene::ColorChannels::Gb; + } + return EmulatedScene::ColorChannels::B; + } +} + +void EmulatedSensor::RemosaicQuadBayerBlock(uint16_t* img_in, uint16_t* img_out, + int xstart, int ystart, + int row_stride_in_bytes) { + uint32_t quad_block_copy_idx_map[16] = {0, 2, 1, 3, 8, 10, 6, 11, + 4, 9, 5, 7, 12, 14, 13, 15}; + uint16_t quad_block_copy[16]; + uint32_t i = 0; + for (uint32_t row = 0; row < 4; row++) { + uint16_t* quad_bayer_row = + img_in + (ystart + row) * (row_stride_in_bytes / 2) + xstart; + for (uint32_t j = 0; j < 4; j++, i++) { + quad_block_copy[i] = quad_bayer_row[j]; + } + } + + for (uint32_t row = 0; row < 4; row++) { + uint16_t* regular_bayer_row = + img_out + (ystart + row) * (row_stride_in_bytes / 2) + xstart; + for (uint32_t j = 0; j < 4; j++, i++) { + uint32_t idx = quad_block_copy_idx_map[row + 4 * j]; + regular_bayer_row[j] = quad_block_copy[idx]; + } + } +} + +status_t EmulatedSensor::RemosaicRAW16Image(uint16_t* img_in, uint16_t* img_out, + size_t row_stride_in_bytes, + const SensorCharacteristics& chars) { + if (chars.full_res_width % 2 != 0 || chars.full_res_height % 2 != 0) { + ALOGE( + "%s RAW16 Image with quad CFA, height %zu and width %zu, not multiples " + "of 4", + __FUNCTION__, chars.full_res_height, chars.full_res_width); + return BAD_VALUE; + } + for (uint32_t i = 0; i < chars.full_res_width; i += 4) { + for (uint32_t j = 0; j < chars.full_res_height; j += 4) { + RemosaicQuadBayerBlock(img_in, img_out, i, j, row_stride_in_bytes); + } + } + return OK; +} + +void EmulatedSensor::CaptureRawBinned(uint8_t* img, size_t row_stride_in_bytes, + uint32_t gain, + const SensorCharacteristics& chars) { + CaptureRaw(img, row_stride_in_bytes, gain, chars, /*in_sensor_zoom*/ false, + /*binned*/ true); + return; +} + +void EmulatedSensor::CaptureRawInSensorZoom(uint8_t* img, + size_t row_stride_in_bytes, + uint32_t gain, + const SensorCharacteristics& chars) { + CaptureRaw(img, row_stride_in_bytes, gain, chars, /*in_sensor_zoom*/ true, + /*binned*/ false); + return; +} + +void EmulatedSensor::CaptureRawFullRes(uint8_t* img, size_t row_stride_in_bytes, + uint32_t gain, + const SensorCharacteristics& chars) { + CaptureRaw(img, row_stride_in_bytes, gain, chars, /*inSensorZoom*/ false, + /*binned*/ false); + return; +} + +void EmulatedSensor::CaptureRaw(uint8_t* img, size_t row_stride_in_bytes, + uint32_t gain, + const SensorCharacteristics& chars, + bool in_sensor_zoom, bool binned) { + ATRACE_CALL(); + if (in_sensor_zoom && binned) { + ALOGE("%s: Can't perform in-sensor zoom in binned mode", __FUNCTION__); + return; + } + float total_gain = gain / 100.0 * GetBaseGainFactor(chars.max_raw_value); + float noise_var_gain = total_gain * total_gain; + float read_noise_var = + kReadNoiseVarBeforeGain * noise_var_gain + kReadNoiseVarAfterGain; + + scene_->SetReadoutPixel(0, 0); + // RGGB + int bayer_select[4] = {EmulatedScene::R, EmulatedScene::Gr, EmulatedScene::Gb, + EmulatedScene::B}; + const float raw_zoom_ratio = in_sensor_zoom ? 2.0f : 1.0f; + unsigned int image_width = + in_sensor_zoom || binned ? chars.width : chars.full_res_width; + unsigned int image_height = + in_sensor_zoom || binned ? chars.height : chars.full_res_height; + const float norm_left_top = 0.5f - 0.5f / raw_zoom_ratio; + for (unsigned int out_y = 0; out_y < image_height; out_y++) { + int* bayer_row = bayer_select + (out_y & 0x1) * 2; + uint16_t* px = (uint16_t*)img + out_y * (row_stride_in_bytes / 2); + + float norm_y = out_y / (image_height * raw_zoom_ratio); + int y = static_cast(chars.full_res_height * (norm_left_top + norm_y)); + y = std::min(std::max(y, 0), (int)chars.full_res_height - 1); + + for (unsigned int out_x = 0; out_x < image_width; out_x++) { + int color_idx = chars.quad_bayer_sensor && !(in_sensor_zoom || binned) + ? GetQuadBayerColor(out_x, out_y) + : bayer_row[out_x & 0x1]; + float norm_x = out_x / (image_width * raw_zoom_ratio); + int x = static_cast(chars.full_res_width * (norm_left_top + norm_x)); + x = std::min(std::max(x, 0), (int)chars.full_res_width - 1); + + uint32_t electron_count; + scene_->SetReadoutPixel(x, y); + electron_count = scene_->GetPixelElectrons()[color_idx]; + + // TODO: Better pixel saturation curve? + electron_count = (electron_count < kSaturationElectrons) + ? electron_count + : kSaturationElectrons; + + // TODO: Better A/D saturation curve? + uint16_t raw_count = electron_count * total_gain; + raw_count = + (raw_count < chars.max_raw_value) ? raw_count : chars.max_raw_value; + + // Calculate noise value + // TODO: Use more-correct Gaussian instead of uniform noise + float photon_noise_var = electron_count * noise_var_gain; + float noise_stddev = sqrtf_approx(read_noise_var + photon_noise_var); + // Scaled to roughly match gaussian/uniform noise stddev + float noise_sample = rand_r(&rand_seed_) * (2.5 / (1.0 + RAND_MAX)) - 1.25; + + raw_count += chars.black_level_pattern[color_idx]; + raw_count += noise_stddev * noise_sample; + + *px++ = raw_count; + } + // TODO: Handle this better + // simulatedTime += mRowReadoutTime; + } + ALOGVV("Raw sensor image captured"); +} + +void EmulatedSensor::CaptureRGB(uint8_t* img, uint32_t width, uint32_t height, + uint32_t stride, RGBLayout layout, + uint32_t gain, int32_t color_space, + const SensorCharacteristics& chars) { + ATRACE_CALL(); + float total_gain = gain / 100.0 * GetBaseGainFactor(chars.max_raw_value); + // In fixed-point math, calculate total scaling from electrons to 8bpp + int scale64x = 64 * total_gain * 255 / chars.max_raw_value; + uint32_t inc_h = ceil((float)chars.full_res_width / width); + uint32_t inc_v = ceil((float)chars.full_res_height / height); + + for (unsigned int y = 0, outy = 0; y < chars.full_res_height; + y += inc_v, outy++) { + scene_->SetReadoutPixel(0, y); + uint8_t* px = img + outy * stride; + for (unsigned int x = 0; x < chars.full_res_width; x += inc_h) { + uint32_t r_count, g_count, b_count; + // TODO: Perfect demosaicing is a cheat + const uint32_t* pixel = scene_->GetPixelElectrons(); + r_count = pixel[EmulatedScene::R] * scale64x; + g_count = pixel[EmulatedScene::Gr] * scale64x; + b_count = pixel[EmulatedScene::B] * scale64x; + + if (color_space != + ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_UNSPECIFIED) { + RgbToRgb(&r_count, &g_count, &b_count); + } + + uint8_t r = r_count < 255 * 64 ? r_count / 64 : 255; + uint8_t g = g_count < 255 * 64 ? g_count / 64 : 255; + uint8_t b = b_count < 255 * 64 ? b_count / 64 : 255; + switch (layout) { + case RGB: + *px++ = r; + *px++ = g; + *px++ = b; + break; + case RGBA: + *px++ = r; + *px++ = g; + *px++ = b; + *px++ = 255; + break; + case ARGB: + *px++ = 255; + *px++ = r; + *px++ = g; + *px++ = b; + break; + default: + ALOGE("%s: RGB layout: %d not supported", __FUNCTION__, layout); + return; + } + for (unsigned int j = 1; j < inc_h; j++) scene_->GetPixelElectrons(); + } + } + ALOGVV("RGB sensor image captured"); +} + +void EmulatedSensor::CaptureYUV420(YCbCrPlanes yuv_layout, uint32_t width, + uint32_t height, uint32_t gain, + float zoom_ratio, bool rotate, + int32_t color_space, + const SensorCharacteristics& chars) { + ATRACE_CALL(); + float total_gain = gain / 100.0 * GetBaseGainFactor(chars.max_raw_value); + // Using fixed-point math with 6 bits of fractional precision. + // In fixed-point math, calculate total scaling from electrons to 8bpp + const int scale64x = + kFixedBitPrecision * total_gain * 255 / chars.max_raw_value; + // Fixed-point coefficients for RGB-YUV transform + // Based on JFIF RGB->YUV transform. + // Cb/Cr offset scaled by 64x twice since they're applied post-multiply + const int rgb_to_y[] = {19, 37, 7}; + const int rgb_to_cb[] = {-10, -21, 32, 524288}; + const int rgb_to_cr[] = {32, -26, -5, 524288}; + // Scale back to 8bpp non-fixed-point + const int scale_out = 64; + const int scale_out_sq = scale_out * scale_out; // after multiplies + + // inc = how many pixels to skip while reading every next pixel + const float aspect_ratio = static_cast(width) / height; + + // precalculate normalized coordinates and dimensions + const float norm_left_top = 0.5f - 0.5f / zoom_ratio; + const float norm_rot_top = norm_left_top; + const float norm_width = 1 / zoom_ratio; + const float norm_rot_width = norm_width / aspect_ratio; + const float norm_rot_height = norm_width; + const float norm_rot_left = + norm_left_top + (norm_width + norm_rot_width) * 0.5f; + + for (unsigned int out_y = 0; out_y < height; out_y++) { + uint8_t* px_y = yuv_layout.img_y + out_y * yuv_layout.y_stride; + uint8_t* px_cb = yuv_layout.img_cb + (out_y / 2) * yuv_layout.cbcr_stride; + uint8_t* px_cr = yuv_layout.img_cr + (out_y / 2) * yuv_layout.cbcr_stride; + + for (unsigned int out_x = 0; out_x < width; out_x++) { + int x, y; + float norm_x = out_x / (width * zoom_ratio); + float norm_y = out_y / (height * zoom_ratio); + if (rotate) { + x = static_cast(chars.full_res_width * + (norm_rot_left - norm_y * norm_rot_width)); + y = static_cast(chars.full_res_height * + (norm_rot_top + norm_x * norm_rot_height)); + } else { + x = static_cast(chars.full_res_width * (norm_left_top + norm_x)); + y = static_cast(chars.full_res_height * (norm_left_top + norm_y)); + } + x = std::min(std::max(x, 0), (int)chars.full_res_width - 1); + y = std::min(std::max(y, 0), (int)chars.full_res_height - 1); + scene_->SetReadoutPixel(x, y); + + uint32_t r_count, g_count, b_count; + // TODO: Perfect demosaicing is a cheat + const uint32_t* pixel = rotate ? scene_->GetPixelElectronsColumn() + : scene_->GetPixelElectrons(); + r_count = pixel[EmulatedScene::R] * scale64x; + g_count = pixel[EmulatedScene::Gr] * scale64x; + b_count = pixel[EmulatedScene::B] * scale64x; + + if (color_space != + ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_UNSPECIFIED) { + RgbToRgb(&r_count, &g_count, &b_count); + } + + r_count = r_count < kSaturationPoint ? r_count : kSaturationPoint; + g_count = g_count < kSaturationPoint ? g_count : kSaturationPoint; + b_count = b_count < kSaturationPoint ? b_count : kSaturationPoint; + + // Gamma correction + r_count = GammaTable(r_count, color_space); + g_count = GammaTable(g_count, color_space); + b_count = GammaTable(b_count, color_space); + + uint8_t y8 = (rgb_to_y[0] * r_count + rgb_to_y[1] * g_count + + rgb_to_y[2] * b_count) / + scale_out_sq; + if (yuv_layout.bytesPerPixel == 1) { + *px_y = y8; + } else if (yuv_layout.bytesPerPixel == 2) { + *(reinterpret_cast(px_y)) = htole16(y8 << 8); + } else { + ALOGE("%s: Unsupported bytes per pixel value: %zu", __func__, + yuv_layout.bytesPerPixel); + return; + } + px_y += yuv_layout.bytesPerPixel; + + if (out_y % 2 == 0 && out_x % 2 == 0) { + uint8_t cb8 = (rgb_to_cb[0] * r_count + rgb_to_cb[1] * g_count + + rgb_to_cb[2] * b_count + rgb_to_cb[3]) / + scale_out_sq; + uint8_t cr8 = (rgb_to_cr[0] * r_count + rgb_to_cr[1] * g_count + + rgb_to_cr[2] * b_count + rgb_to_cr[3]) / + scale_out_sq; + if (yuv_layout.bytesPerPixel == 1) { + *px_cb = cb8; + *px_cr = cr8; + } else if (yuv_layout.bytesPerPixel == 2) { + *(reinterpret_cast(px_cb)) = htole16(cb8 << 8); + *(reinterpret_cast(px_cr)) = htole16(cr8 << 8); + } else { + ALOGE("%s: Unsupported bytes per pixel value: %zu", __func__, + yuv_layout.bytesPerPixel); + return; + } + px_cr += yuv_layout.cbcr_step; + px_cb += yuv_layout.cbcr_step; + } + } + } + ALOGVV("YUV420 sensor image captured"); +} + +void EmulatedSensor::CaptureDepth(uint8_t* img, uint32_t gain, uint32_t width, + uint32_t height, uint32_t stride, + const SensorCharacteristics& chars) { + ATRACE_CALL(); + float total_gain = gain / 100.0 * GetBaseGainFactor(chars.max_raw_value); + // In fixed-point math, calculate scaling factor to 13bpp millimeters + int scale64x = 64 * total_gain * 8191 / chars.max_raw_value; + uint32_t inc_h = ceil((float)chars.full_res_width / width); + uint32_t inc_v = ceil((float)chars.full_res_height / height); + + for (unsigned int y = 0, out_y = 0; y < chars.full_res_height; + y += inc_v, out_y++) { + scene_->SetReadoutPixel(0, y); + uint16_t* px = (uint16_t*)(img + (out_y * stride)); + for (unsigned int x = 0; x < chars.full_res_width; x += inc_h) { + uint32_t depth_count; + // TODO: Make up real depth scene instead of using green channel + // as depth + const uint32_t* pixel = scene_->GetPixelElectrons(); + depth_count = pixel[EmulatedScene::Gr] * scale64x; + + *px++ = depth_count < 8191 * 64 ? depth_count / 64 : 0; + for (unsigned int j = 1; j < inc_h; j++) scene_->GetPixelElectrons(); + } + // TODO: Handle this better + // simulatedTime += mRowReadoutTime; + } + ALOGVV("Depth sensor image captured"); +} + +status_t EmulatedSensor::ProcessYUV420(const YUV420Frame& input, + const YUV420Frame& output, uint32_t gain, + ProcessType process_type, + float zoom_ratio, bool rotate_and_crop, + int32_t color_space, + const SensorCharacteristics& chars, int fps) { + ATRACE_CALL(); + size_t input_width, input_height; + YCbCrPlanes input_planes, output_planes; + std::vector temp_output_uv, temp_input_uv; + std::unique_ptr buffer = nullptr; + + // Overwrite HIGH_QUALITY to REGULAR for Emulator if property + // ro.boot.qemu.camera_hq_edge_processing is false; + if (process_type == HIGH_QUALITY && + !property_get_bool("ro.boot.qemu.camera_hq_edge_processing", true)) { + process_type = REGULAR; + } + + process_type = REGULAR; + + size_t bytes_per_pixel = output.planes.bytesPerPixel; + switch (process_type) { + case HIGH_QUALITY: + CaptureYUV420(output.planes, output.width, output.height, gain, + zoom_ratio, rotate_and_crop, color_space, chars); + return OK; + case REPROCESS: + input_width = input.width; + input_height = input.height; + input_planes = input.planes; + + // libyuv only supports planar YUV420 during scaling. + // Split the input U/V plane in separate planes if needed. + if (input_planes.cbcr_step == 2) { + temp_input_uv.resize(input_width * input_height / 2); + auto temp_uv_buffer = temp_input_uv.data(); + input_planes.img_cb = temp_uv_buffer; + input_planes.img_cr = temp_uv_buffer + (input_width * input_height) / 4; + input_planes.cbcr_stride = input_width / 2; + if (input.planes.img_cb < input.planes.img_cr) { + libyuv::SplitUVPlane(input.planes.img_cb, input.planes.cbcr_stride, + input_planes.img_cb, input_planes.cbcr_stride, + input_planes.img_cr, input_planes.cbcr_stride, + input_width / 2, input_height / 2); + } else { + libyuv::SplitUVPlane(input.planes.img_cr, input.planes.cbcr_stride, + input_planes.img_cr, input_planes.cbcr_stride, + input_planes.img_cb, input_planes.cbcr_stride, + input_width / 2, input_height / 2); + } + } + break; + case REGULAR: + default: + // Generate the smallest possible frame with the expected AR and + // then scale using libyuv. + float aspect_ratio = static_cast(output.width) / output.height; + zoom_ratio = std::max(1.f, zoom_ratio); + input_width = EmulatedScene::kSceneWidth * aspect_ratio; + input_height = EmulatedScene::kSceneHeight; + if (!start_preview_done_) { + if (vmi_camera_->StartPreview(output.width, output.height, fps) < 0) { + ALOGI("StartPreview fail!"); + return -1; + } + start_preview_done_ = true; + } + buffer = vmi_camera_->GetFrame(input_width, input_height, bytes_per_pixel); + if (buffer == nullptr) { + ALOGI("GetFrame fail!"); + return -1; + } + auto temp_yuv_buffer = buffer.get(); + input_planes = { + .img_y = temp_yuv_buffer, + .img_cb = + temp_yuv_buffer + input_width * input_height * bytes_per_pixel, + .img_cr = temp_yuv_buffer + + (input_width * input_height * bytes_per_pixel * 5) / 4, + .y_stride = static_cast(input_width * bytes_per_pixel), + .cbcr_stride = + static_cast(input_width * bytes_per_pixel) / 2, + .cbcr_step = 1, + .bytesPerPixel = bytes_per_pixel}; + if (vmi_camera_->Simulate()) { + CaptureYUV420(input_planes, input_width, input_height, gain, zoom_ratio, + rotate_and_crop, color_space, chars); + } + } + + output_planes = output.planes; + // libyuv only supports planar YUV420 during scaling. + // Treat the output UV space as planar first and then + // interleave in the second step. + if (output_planes.cbcr_step == 2) { + temp_output_uv.resize(output.width * output.height * bytes_per_pixel / 2); + auto temp_uv_buffer = temp_output_uv.data(); + output_planes.img_cb = temp_uv_buffer; + output_planes.img_cr = + temp_uv_buffer + output.width * output.height * bytes_per_pixel / 4; + output_planes.cbcr_stride = output.width * bytes_per_pixel / 2; + } + + // NOTE: libyuv takes strides in pixels, not bytes. + int ret = 0; + if (bytes_per_pixel == 2) { + ret = I420Scale_16((const uint16_t*)input_planes.img_y, + input_planes.y_stride / bytes_per_pixel, + (const uint16_t*)input_planes.img_cb, + input_planes.cbcr_stride / bytes_per_pixel, + (const uint16_t*)input_planes.img_cr, + input_planes.cbcr_stride / bytes_per_pixel, input_width, + input_height, (uint16_t*)output_planes.img_y, + output_planes.y_stride / bytes_per_pixel, + (uint16_t*)output_planes.img_cb, + output_planes.cbcr_stride / bytes_per_pixel, + (uint16_t*)output_planes.img_cr, + output_planes.cbcr_stride / bytes_per_pixel, + output.width, output.height, libyuv::kFilterNone); + } else { + ret = I420Scale(input_planes.img_y, input_planes.y_stride, + input_planes.img_cb, input_planes.cbcr_stride, + input_planes.img_cr, input_planes.cbcr_stride, input_width, + input_height, output_planes.img_y, output_planes.y_stride, + output_planes.img_cb, output_planes.cbcr_stride, + output_planes.img_cr, output_planes.cbcr_stride, + output.width, output.height, libyuv::kFilterNone); + } + if (ret != 0) { + ALOGE("%s: Failed during YUV scaling: %d", __FUNCTION__, ret); + return ret; + } + + // Merge U/V Planes for the interleaved case + if (output_planes.cbcr_step == 2) { + if (output.planes.img_cb < output.planes.img_cr) { + if (bytes_per_pixel == 2) { + libyuv::MergeUVPlane_16((const uint16_t*)output_planes.img_cb, + output_planes.cbcr_stride / bytes_per_pixel, + (const uint16_t*)output_planes.img_cr, + output_planes.cbcr_stride / bytes_per_pixel, + (uint16_t*)output.planes.img_cb, + output.planes.cbcr_stride / bytes_per_pixel, + output.width / 2, output.height / 2, + /*depth*/ 16); + } else { + libyuv::MergeUVPlane(output_planes.img_cb, output_planes.cbcr_stride, + output_planes.img_cr, output_planes.cbcr_stride, + output.planes.img_cb, output.planes.cbcr_stride, + output.width / 2, output.height / 2); + } + } else { + if (bytes_per_pixel == 2) { + libyuv::MergeUVPlane_16((const uint16_t*)output_planes.img_cr, + output_planes.cbcr_stride / bytes_per_pixel, + (const uint16_t*)output_planes.img_cb, + output_planes.cbcr_stride / bytes_per_pixel, + (uint16_t*)output.planes.img_cr, + output.planes.cbcr_stride / bytes_per_pixel, + output.width / 2, output.height / 2, + /*depth*/ 16); + } else { + libyuv::MergeUVPlane(output_planes.img_cr, output_planes.cbcr_stride, + output_planes.img_cb, output_planes.cbcr_stride, + output.planes.img_cr, output.planes.cbcr_stride, + output.width / 2, output.height / 2); + } + } + } + + return ret; +} + +int32_t EmulatedSensor::ApplysRGBGamma(int32_t value, int32_t saturation) { + float n_value = (static_cast(value) / saturation); + n_value = (n_value <= 0.0031308f) + ? n_value * 12.92f + : 1.055f * pow(n_value, 0.4166667f) - 0.055f; + return n_value * saturation; +} + +int32_t EmulatedSensor::ApplySMPTE170MGamma(int32_t value, int32_t saturation) { + float n_value = (static_cast(value) / saturation); + n_value = (n_value <= 0.018f) ? n_value * 4.5f + : 1.099f * pow(n_value, 0.45f) - 0.099f; + return n_value * saturation; +} + +int32_t EmulatedSensor::ApplyST2084Gamma(int32_t value, int32_t saturation) { + float n_value = (static_cast(value) / saturation); + float c2 = 32.f * 2413.f / 4096.f; + float c3 = 32.f * 2392.f / 4096.f; + float c1 = c3 - c2 + 1.f; + float m = 128.f * 2523.f / 4096.f; + float n = 0.25f * 2610.f / 4096.f; + n_value = pow((c1 + c2 * pow(n_value, n)) / (1 + c3 * pow(n_value, n)), m); + return n_value * saturation; +} + +int32_t EmulatedSensor::ApplyHLGGamma(int32_t value, int32_t saturation) { + float n_value = (static_cast(value) / saturation); + // The full HLG gamma curve has additional parameters for n_value > 1, but n_value + // in the emulated camera is always <= 1 due to lack of HDR display features. + n_value = 0.5f * pow(n_value, 0.5f); + return n_value * saturation; +} + +int32_t EmulatedSensor::GammaTable(int32_t value, int32_t color_space) { + switch (color_space) { + case ColorSpaceNamed::BT709: + return gamma_table_smpte170m_[value]; + case ColorSpaceNamed::BT2020: + return gamma_table_hlg_[value]; // Assume HLG + case ColorSpaceNamed::DISPLAY_P3: + case ColorSpaceNamed::SRGB: + default: + return gamma_table_sRGB_[value]; + } + + return 0; +} + +void EmulatedSensor::RgbToRgb(uint32_t* r_count, uint32_t* g_count, + uint32_t* b_count) { + uint32_t r = *r_count; + uint32_t g = *g_count; + uint32_t b = *b_count; + *r_count = (uint32_t)std::max( + r * rgb_rgb_matrix_.rR + g * rgb_rgb_matrix_.gR + b * rgb_rgb_matrix_.bR, + 0.0f); + *g_count = (uint32_t)std::max( + r * rgb_rgb_matrix_.rG + g * rgb_rgb_matrix_.gG + b * rgb_rgb_matrix_.bG, + 0.0f); + *b_count = (uint32_t)std::max( + r * rgb_rgb_matrix_.rB + g * rgb_rgb_matrix_.gB + b * rgb_rgb_matrix_.bB, + 0.0f); +} + +void EmulatedSensor::CalculateRgbRgbMatrix(int32_t color_space, + const SensorCharacteristics& chars) { + const XyzMatrix* xyzMatrix; + switch (color_space) { + case ColorSpaceNamed::DISPLAY_P3: + xyzMatrix = &kDisplayP3Matrix; + break; + case ColorSpaceNamed::BT709: + xyzMatrix = &kBt709Matrix; + break; + case ColorSpaceNamed::BT2020: + xyzMatrix = &kBt2020Matrix; + break; + case ColorSpaceNamed::SRGB: + default: + xyzMatrix = &kSrgbXyzMatrix; + break; + } + + rgb_rgb_matrix_.rR = xyzMatrix->xR * chars.forward_matrix.rX + + xyzMatrix->yR * chars.forward_matrix.rY + + xyzMatrix->zR * chars.forward_matrix.rZ; + rgb_rgb_matrix_.gR = xyzMatrix->xR * chars.forward_matrix.gX + + xyzMatrix->yR * chars.forward_matrix.gY + + xyzMatrix->zR * chars.forward_matrix.gZ; + rgb_rgb_matrix_.bR = xyzMatrix->xR * chars.forward_matrix.bX + + xyzMatrix->yR * chars.forward_matrix.bY + + xyzMatrix->zR * chars.forward_matrix.bZ; + rgb_rgb_matrix_.rG = xyzMatrix->xG * chars.forward_matrix.rX + + xyzMatrix->yG * chars.forward_matrix.rY + + xyzMatrix->zG * chars.forward_matrix.rZ; + rgb_rgb_matrix_.gG = xyzMatrix->xG * chars.forward_matrix.gX + + xyzMatrix->yG * chars.forward_matrix.gY + + xyzMatrix->zG * chars.forward_matrix.gZ; + rgb_rgb_matrix_.bG = xyzMatrix->xG * chars.forward_matrix.bX + + xyzMatrix->yG * chars.forward_matrix.bY + + xyzMatrix->zG * chars.forward_matrix.bZ; + rgb_rgb_matrix_.rB = xyzMatrix->xB * chars.forward_matrix.rX + + xyzMatrix->yB * chars.forward_matrix.rY + + xyzMatrix->zB * chars.forward_matrix.rZ; + rgb_rgb_matrix_.gB = xyzMatrix->xB * chars.forward_matrix.gX + + xyzMatrix->yB * chars.forward_matrix.gY + + xyzMatrix->zB * chars.forward_matrix.gZ; + rgb_rgb_matrix_.bB = xyzMatrix->xB * chars.forward_matrix.bX + + xyzMatrix->yB * chars.forward_matrix.bY + + xyzMatrix->zB * chars.forward_matrix.bZ; +} + +} // namespace android diff --git a/aosp/hardware/google/camera/devices/EmulatedCamera/hwl/EmulatedSensor.h b/aosp/hardware/google/camera/devices/EmulatedCamera/hwl/EmulatedSensor.h new file mode 100644 index 000000000..df0282b9d --- /dev/null +++ b/aosp/hardware/google/camera/devices/EmulatedCamera/hwl/EmulatedSensor.h @@ -0,0 +1,477 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * This class is a simple simulation of a typical CMOS cellphone imager chip, + * which outputs 12-bit Bayer-mosaic raw images. + * + * Unlike most real image sensors, this one's native color space is linear sRGB. + * + * The sensor is abstracted as operating as a pipeline 3 stages deep; + * conceptually, each frame to be captured goes through these three stages. The + * processing step for the sensor is marked off by vertical sync signals, which + * indicate the start of readout of the oldest frame. The interval between + * processing steps depends on the frame duration of the frame currently being + * captured. The stages are 1) configure, 2) capture, and 3) readout. During + * configuration, the sensor's registers for settings such as exposure time, + * frame duration, and gain are set for the next frame to be captured. In stage + * 2, the image data for the frame is actually captured by the sensor. Finally, + * in stage 3, the just-captured data is read out and sent to the rest of the + * system. + * + * The sensor is assumed to be rolling-shutter, so low-numbered rows of the + * sensor are exposed earlier in time than larger-numbered rows, with the time + * offset between each row being equal to the row readout time. + * + * The characteristics of this sensor don't correspond to any actual sensor, + * but are not far off typical sensors. + * + * Example timing diagram, with three frames: + * Frame 0-1: Frame duration 50 ms, exposure time 20 ms. + * Frame 2: Frame duration 75 ms, exposure time 65 ms. + * Legend: + * C = update sensor registers for frame + * v = row in reset (vertical blanking interval) + * E = row capturing image data + * R = row being read out + * | = vertical sync signal + *time(ms)| 0 55 105 155 230 270 + * Frame 0| :configure : capture : readout : : : + * Row # | ..|CCCC______|_________|_________| : : + * 0 | :\ \vvvvvEEEER \ : : + * 500 | : \ \vvvvvEEEER \ : : + * 1000 | : \ \vvvvvEEEER \ : : + * 1500 | : \ \vvvvvEEEER \ : : + * 2000 | : \__________\vvvvvEEEER_________\ : : + * Frame 1| : configure capture readout : : + * Row # | : |CCCC_____|_________|______________| : + * 0 | : :\ \vvvvvEEEER \ : + * 500 | : : \ \vvvvvEEEER \ : + * 1000 | : : \ \vvvvvEEEER \ : + * 1500 | : : \ \vvvvvEEEER \ : + * 2000 | : : \_________\vvvvvEEEER______________\ : + * Frame 2| : : configure capture readout: + * Row # | : : |CCCC_____|______________|_______|... + * 0 | : : :\ \vEEEEEEEEEEEEER \ + * 500 | : : : \ \vEEEEEEEEEEEEER \ + * 1000 | : : : \ \vEEEEEEEEEEEEER \ + * 1500 | : : : \ \vEEEEEEEEEEEEER \ + * 2000 | : : : \_________\vEEEEEEEEEEEEER_______\ + */ + +#ifndef HW_EMULATOR_CAMERA2_SENSOR_H +#define HW_EMULATOR_CAMERA2_SENSOR_H + +#include +#include + +#include +#include + +#include "Base.h" +#include "EmulatedScene.h" +#include "JpegCompressor.h" +#include "utils/Mutex.h" +#include "utils/StreamConfigurationMap.h" +#include "utils/Thread.h" +#include "utils/Timers.h" +#include "VmiCamera.h" + +namespace android { + +using google_camera_hal::ColorSpaceProfile; +using google_camera_hal::DynamicRangeProfile; +using google_camera_hal::HwlPipelineCallback; +using google_camera_hal::HwlPipelineResult; +using google_camera_hal::StreamConfiguration; + +using hardware::graphics::common::V1_2::Dataspace; + +/* + * Default to sRGB with D65 white point + */ +struct ColorFilterXYZ { + float rX = 3.2406f; + float rY = -1.5372f; + float rZ = -0.4986f; + float grX = -0.9689f; + float grY = 1.8758f; + float grZ = 0.0415f; + float gbX = -0.9689f; + float gbY = 1.8758f; + float gbZ = 0.0415f; + float bX = 0.0557f; + float bY = -0.2040f; + float bZ = 1.0570f; +}; + +struct ForwardMatrix { + float rX = 0.4355f; + float gX = 0.3848f; + float bX = 0.1425f; + float rY = 0.2216f; + float gY = 0.7168f; + float bY = 0.0605f; + float rZ = 0.0137f; + float gZ = 0.0967f; + float bZ = 0.7139f; +}; + +struct RgbRgbMatrix { + float rR; + float gR; + float bR; + float rG; + float gG; + float bG; + float rB; + float gB; + float bB; +}; + +typedef std::unordered_map> + DynamicRangeProfileMap; + +typedef std::unordered_map< + ColorSpaceProfile, + std::unordered_map>> + ColorSpaceProfileMap; + +struct SensorCharacteristics { + size_t width = 0; + size_t height = 0; + size_t full_res_width = 0; + size_t full_res_height = 0; + nsecs_t exposure_time_range[2] = {0}; + nsecs_t frame_duration_range[2] = {0}; + int32_t sensitivity_range[2] = {0}; + camera_metadata_enum_android_sensor_info_color_filter_arrangement + color_arangement = ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_RGGB; + ColorFilterXYZ color_filter; + ForwardMatrix forward_matrix; + uint32_t max_raw_value = 0; + uint32_t black_level_pattern[4] = {0}; + uint32_t max_raw_streams = 0; + uint32_t max_processed_streams = 0; + uint32_t max_stalling_streams = 0; + uint32_t max_input_streams = 0; + uint32_t physical_size[2] = {0}; + bool is_flash_supported = false; + uint32_t lens_shading_map_size[2] = {0}; + uint32_t max_pipeline_depth = 0; + uint32_t orientation = 0; + bool is_front_facing = false; + bool quad_bayer_sensor = false; + bool is_10bit_dynamic_range_capable = false; + DynamicRangeProfileMap dynamic_range_profiles; + bool support_stream_use_case = false; + int64_t end_valid_stream_use_case = + ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_VIDEO_CALL; + bool support_color_space_profiles = false; + ColorSpaceProfileMap color_space_profiles; + int32_t raw_crop_region_zoomed[4] = {0}; + int32_t raw_crop_region_unzoomed[4] = {0}; + int32_t timestamp_source = ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE_UNKNOWN; +}; + +// Maps logical/physical camera ids to sensor characteristics +typedef std::unordered_map LogicalCharacteristics; + +class EmulatedSensor : private Thread, public virtual RefBase { + public: + EmulatedSensor(); + ~EmulatedSensor(); + + static android_pixel_format_t OverrideFormat( + android_pixel_format_t format, DynamicRangeProfile dynamic_range_profile) { + switch (dynamic_range_profile) { + case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD: + if (format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) { + return HAL_PIXEL_FORMAT_YCBCR_420_888; + } + break; + case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HLG10: + if (format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) { + return static_cast( + HAL_PIXEL_FORMAT_YCBCR_P010); + } + break; + default: + ALOGE("%s: Unsupported dynamic range profile 0x%x", __FUNCTION__, + dynamic_range_profile); + } + + return format; + } + + static bool IsReprocessPathSupported(android_pixel_format_t input_format, + android_pixel_format_t output_format) { + if ((HAL_PIXEL_FORMAT_YCBCR_420_888 == input_format) && + ((HAL_PIXEL_FORMAT_YCBCR_420_888 == output_format) || + (HAL_PIXEL_FORMAT_BLOB == output_format))) { + return true; + } + + if (HAL_PIXEL_FORMAT_RAW16 == input_format && + HAL_PIXEL_FORMAT_RAW16 == output_format) { + return true; + } + + return false; + } + + static bool AreCharacteristicsSupported( + const SensorCharacteristics& characteristics); + + static bool IsStreamCombinationSupported( + uint32_t logical_id, const StreamConfiguration& config, + StreamConfigurationMap& map, StreamConfigurationMap& max_resolution_map, + const PhysicalStreamConfigurationMap& physical_map, + const PhysicalStreamConfigurationMap& physical_map_max_resolution, + const LogicalCharacteristics& sensor_chars); + + static bool IsStreamCombinationSupported( + uint32_t logical_id, const StreamConfiguration& config, + StreamConfigurationMap& map, + const PhysicalStreamConfigurationMap& physical_map, + const LogicalCharacteristics& sensor_chars, bool is_max_res = false); + + /* + * Power control + */ + + status_t StartUp(uint32_t logical_camera_id, + std::unique_ptr logical_chars); + status_t ShutDown(); + + /* + * Physical camera settings control + */ + struct SensorSettings { + nsecs_t exposure_time = 0; + nsecs_t frame_duration = 0; + uint32_t gain = 0; // ISO + uint32_t lens_shading_map_mode; + bool report_neutral_color_point = false; + bool report_green_split = false; + bool report_noise_profile = false; + float zoom_ratio = 1.0f; + bool report_rotate_and_crop = false; + uint8_t rotate_and_crop = ANDROID_SCALER_ROTATE_AND_CROP_NONE; + bool report_video_stab = false; + uint8_t video_stab = ANDROID_CONTROL_VIDEO_STABILIZATION_MODE_OFF; + bool report_edge_mode = false; + uint8_t edge_mode = ANDROID_EDGE_MODE_OFF; + uint8_t sensor_pixel_mode = ANDROID_SENSOR_PIXEL_MODE_DEFAULT; + uint8_t test_pattern_mode = ANDROID_SENSOR_TEST_PATTERN_MODE_OFF; + uint32_t test_pattern_data[4] = {0, 0, 0, 0}; + uint32_t screen_rotation = 0; + uint32_t timestamp_source = ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE_UNKNOWN; + }; + + // Maps physical and logical camera ids to individual device settings + typedef std::unordered_map LogicalCameraSettings; + + void SetCurrentRequest(std::unique_ptr logical_settings, + std::unique_ptr result, + std::unique_ptr partial_result, + std::unique_ptr input_buffers, + std::unique_ptr output_buffers); + + status_t Flush(); + + /* + * Synchronizing with sensor operation (vertical sync) + */ + + // Wait until the sensor outputs its next vertical sync signal, meaning it + // is starting readout of its latest frame of data. Returns true if vertical + // sync is signaled, false if the wait timed out. + bool WaitForVSync(nsecs_t rel_time); + + static const nsecs_t kSupportedExposureTimeRange[2]; + static const nsecs_t kSupportedFrameDurationRange[2]; + static const int32_t kSupportedSensitivityRange[2]; + static const uint8_t kSupportedColorFilterArrangement; + static const uint32_t kDefaultMaxRawValue; + static const nsecs_t kDefaultExposureTime; + static const int32_t kDefaultSensitivity; + static const nsecs_t kDefaultFrameDuration; + static const nsecs_t kReturnResultThreshod; + static const uint32_t kDefaultBlackLevelPattern[4]; + static const camera_metadata_rational kDefaultColorTransform[9]; + static const float kDefaultColorCorrectionGains[4]; + static const float kDefaultToneMapCurveRed[4]; + static const float kDefaultToneMapCurveGreen[4]; + static const float kDefaultToneMapCurveBlue[4]; + static const uint8_t kPipelineDepth; + + private: + // Scene stabilization + static const uint32_t kRegularSceneHandshake; + static const uint32_t kReducedSceneHandshake; + + /** + * Logical characteristics + */ + std::unique_ptr chars_; + + uint32_t logical_camera_id_ = 0; + + static const nsecs_t kMinVerticalBlank; + + // Sensor sensitivity, approximate + + static const float kSaturationVoltage; + static const uint32_t kSaturationElectrons; + static const float kVoltsPerLuxSecond; + static const float kElectronsPerLuxSecond; + + static const float kReadNoiseStddevBeforeGain; // In electrons + static const float kReadNoiseStddevAfterGain; // In raw digital units + static const float kReadNoiseVarBeforeGain; + static const float kReadNoiseVarAfterGain; + static const camera_metadata_rational kNeutralColorPoint[3]; + static const float kGreenSplit; + + static const uint32_t kMaxRAWStreams; + static const uint32_t kMaxProcessedStreams; + static const uint32_t kMaxStallingStreams; + static const uint32_t kMaxInputStreams; + static const uint32_t kMaxLensShadingMapSize[2]; + static const int32_t kFixedBitPrecision; + static const int32_t kSaturationPoint; + + std::vector gamma_table_sRGB_; + std::vector gamma_table_smpte170m_; + std::vector gamma_table_hlg_; + + Mutex control_mutex_; // Lock before accessing control parameters + // Start of control parameters + Condition vsync_; + bool got_vsync_; + std::unique_ptr current_settings_; + std::unique_ptr current_result_; + std::unique_ptr partial_result_; + std::unique_ptr current_output_buffers_; + std::unique_ptr current_input_buffers_; + std::unique_ptr jpeg_compressor_; + + // End of control parameters + + unsigned int rand_seed_ = 1; + + /** + * Inherited Thread virtual overrides, and members only used by the + * processing thread + */ + bool threadLoop() override; + + nsecs_t next_capture_time_; + nsecs_t next_readout_time_; + + struct SensorBinningFactorInfo { + bool has_raw_stream = false; + bool has_non_raw_stream = false; + bool quad_bayer_sensor = false; + bool max_res_request = false; + bool has_cropped_raw_stream = false; + bool raw_in_sensor_zoom_applied = false; + }; + + std::map sensor_binning_factor_info_; + + std::unique_ptr scene_; + + RgbRgbMatrix rgb_rgb_matrix_; + + static EmulatedScene::ColorChannels GetQuadBayerColor(uint32_t x, uint32_t y); + + static void RemosaicQuadBayerBlock(uint16_t* img_in, uint16_t* img_out, + int xstart, int ystart, + int row_stride_in_bytes); + + static status_t RemosaicRAW16Image(uint16_t* img_in, uint16_t* img_out, + size_t row_stride_in_bytes, + const SensorCharacteristics& chars); + + void CaptureRawBinned(uint8_t* img, size_t row_stride_in_bytes, uint32_t gain, + const SensorCharacteristics& chars); + + void CaptureRawFullRes(uint8_t* img, size_t row_stride_in_bytes, + uint32_t gain, const SensorCharacteristics& chars); + void CaptureRawInSensorZoom(uint8_t* img, size_t row_stride_in_bytes, + uint32_t gain, const SensorCharacteristics& chars); + void CaptureRaw(uint8_t* img, size_t row_stride_in_bytes, uint32_t gain, + const SensorCharacteristics& chars, bool in_sensor_zoom, + bool binned); + + enum RGBLayout { RGB, RGBA, ARGB }; + void CaptureRGB(uint8_t* img, uint32_t width, uint32_t height, + uint32_t stride, RGBLayout layout, uint32_t gain, + int32_t color_space, const SensorCharacteristics& chars); + void CaptureYUV420(YCbCrPlanes yuv_layout, uint32_t width, uint32_t height, + uint32_t gain, float zoom_ratio, bool rotate, + int32_t color_space, const SensorCharacteristics& chars); + void CaptureDepth(uint8_t* img, uint32_t gain, uint32_t width, uint32_t height, + uint32_t stride, const SensorCharacteristics& chars); + void RgbToRgb(uint32_t* r_count, uint32_t* g_count, uint32_t* b_count); + void CalculateRgbRgbMatrix(int32_t color_space, + const SensorCharacteristics& chars); + + struct YUV420Frame { + uint32_t width = 0; + uint32_t height = 0; + YCbCrPlanes planes; + }; + + enum ProcessType { REPROCESS, HIGH_QUALITY, REGULAR }; + status_t ProcessYUV420(const YUV420Frame& input, const YUV420Frame& output, + uint32_t gain, ProcessType process_type, + float zoom_ratio, bool rotate_and_crop, + int32_t color_space, + const SensorCharacteristics& chars, int fps = 0); + + inline int32_t ApplysRGBGamma(int32_t value, int32_t saturation); + inline int32_t ApplySMPTE170MGamma(int32_t value, int32_t saturation); + inline int32_t ApplyST2084Gamma(int32_t value, int32_t saturation); + inline int32_t ApplyHLGGamma(int32_t value, int32_t saturation); + inline int32_t GammaTable(int32_t value, int32_t color_space); + + bool WaitForVSyncLocked(nsecs_t reltime); + void CalculateAndAppendNoiseProfile(float gain /*in ISO*/, + float base_gain_factor, + HalCameraMetadata* result /*out*/); + + void ReturnResults(HwlPipelineCallback callback, + std::unique_ptr settings, + std::unique_ptr result, + bool reprocess_request, + std::unique_ptr partial_result); + + static float GetBaseGainFactor(float max_raw_value) { + return max_raw_value / EmulatedSensor::kSaturationElectrons; + } + + nsecs_t getSystemTimeWithSource(uint32_t timestamp_source); + std::unique_ptr vmi_camera_ = nullptr; + std::atomic_bool start_preview_done_ = false; +}; + +} // namespace android + +#endif // HW_EMULATOR_CAMERA2_SENSOR_H diff --git a/aosp/hardware/google/camera/devices/EmulatedCamera/hwl/apex/Android.bp b/aosp/hardware/google/camera/devices/EmulatedCamera/hwl/apex/Android.bp new file mode 100644 index 000000000..8a1035e21 --- /dev/null +++ b/aosp/hardware/google/camera/devices/EmulatedCamera/hwl/apex/Android.bp @@ -0,0 +1,87 @@ +// Copyright (C) 2022 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package { + default_applicable_licenses: ["Android-Apache-2.0"], +} + +apex_key { + name: "com.google.camera.provider.hal.key", + public_key: "com.google.camera.provider.hal.avbpubkey", + private_key: "com.google.camera.provider.hal.pem", +} + +android_app_certificate { + name: "com.google.camera.provider.hal.certificate", + certificate: "com.google.camera.provider.hal", +} + +prebuilt_etc { + name: "com.google.camera.provider.hal.rc", + src: "com.google.camera.provider.hal.rc", + installable: false, +} + +prebuilt_etc { + name: "com.google.camera.provider.hal.xml", + src: ":android.hardware.camera.provider@2.7-service-google.xml", + sub_dir: "vintf", + installable: false, +} + +apex_defaults { + name: "com.google.camera.provider.hal.defaults", + manifest: "apex_manifest.json", + key: "com.google.camera.provider.hal.key", + certificate: ":com.google.camera.provider.hal.certificate", + file_contexts: "file_contexts", + use_vndk_as_stable: true, + updatable: false, + // Install the apex in /vendor/apex + soc_specific: true, + binaries: [ + "android.hardware.camera.provider@2.7-service-google", + ], + overrides: [ + "android.hardware.camera.provider@2.7-impl-google", + "android.hardware.camera.provider@2.7-service-google", + "libgooglecamerahwl_impl", + "libgooglecamerahwl_impl_fast_scene_cycle", + ], + prebuilts: [ + "com.google.camera.provider.hal.rc", + "com.google.camera.provider.hal.xml", // vintf fragment + "android.hardware.camera.concurrent.prebuilt.xml", + "android.hardware.camera.flash-autofocus.prebuilt.xml", + "android.hardware.camera.front.prebuilt.xml", + "android.hardware.camera.full.prebuilt.xml", + "android.hardware.camera.raw.prebuilt.xml", + "google_camera_back.json", + "google_camera_depth.json", + "google_camera_front.json", + "google_camera_external.json", + ], +} + +apex { + name: "com.google.camera.provider.hal", + defaults: ["com.google.camera.provider.hal.defaults"], + native_shared_libs: ["libgooglecamerahwl_impl"], +} + +apex { + name: "com.google.camera.provider.hal.fastscenecycle", + defaults: ["com.google.camera.provider.hal.defaults"], + native_shared_libs: ["libgooglecamerahwl_impl_fast_scene_cycle"], +} diff --git a/aosp/hardware/google/camera/devices/EmulatedCamera/hwl/apex/apex_manifest.json b/aosp/hardware/google/camera/devices/EmulatedCamera/hwl/apex/apex_manifest.json new file mode 100644 index 000000000..55f98ca8b --- /dev/null +++ b/aosp/hardware/google/camera/devices/EmulatedCamera/hwl/apex/apex_manifest.json @@ -0,0 +1,5 @@ +{ + "name": "com.google.camera.provider.hal", + "version": 1, + "supportsRebootlessUpdate": true +} diff --git a/aosp/hardware/google/camera/devices/EmulatedCamera/hwl/apex/com.google.camera.provider.hal.avbpubkey b/aosp/hardware/google/camera/devices/EmulatedCamera/hwl/apex/com.google.camera.provider.hal.avbpubkey new file mode 100644 index 0000000000000000000000000000000000000000..0c28e11c7ed6388a61f2f13ba95c168e1dab0748 GIT binary patch literal 1032 zcmV+j1o!&@01yC%?(&Jc%#bZqvBm^IwVDDj^D zO-}(cd+Z1gJR1hbfH|3_IO3S@08I+?r&KrHsPv6YN#9dtfBS8w< z+sx!s8;B(;BxcRvK;-qjC}%H#sqv#mRnDbeQmi1s?6K9z?a(BnVYq{fm+_6f1X^

_%GPDp+3xzXD&$YYlOc|g<%EeyK! zLDH6CrQAoMkDFHS`-+Ac#sX|U`Ls|j(~ePxNHmmw>=E2RLgD7L{|}a^X^aXy-ER_F zBR6>r#N1`Uw07xKLKWx4E{JppGgP+)o(HExlV>hmn3w^A05P>#ws!R~Tsb@m(JNN% zc!)N8(bEP_vC^ju(Nd)ZTj9Hh74v!OKR>Ss-10`+huoEa-&;0Bz|nS2r?yBN0NMK{)Q7=HqKYQl9^V+4^aEm{N!CdC{PBXr=_(9Jv)pp~!_}P3^?xN-axn^_ CEb1cw literal 0 HcmV?d00001 diff --git a/aosp/hardware/google/camera/devices/EmulatedCamera/hwl/apex/com.google.camera.provider.hal.pem b/aosp/hardware/google/camera/devices/EmulatedCamera/hwl/apex/com.google.camera.provider.hal.pem new file mode 100644 index 000000000..94c79c941 --- /dev/null +++ b/aosp/hardware/google/camera/devices/EmulatedCamera/hwl/apex/com.google.camera.provider.hal.pem @@ -0,0 +1,51 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIJKQIBAAKCAgEAusyQLVSxxgRA49ayfyjpgTs5o/YoLOJmNqE4dXxw1nweTAnD +39CadQVhk92mF8GAMj6rZPgrQgBHjIL/ZYpoIBiL11iVCa+BTMxfZZn/8S41JgOK +SM7aN8TccimH9BonNKRecG1UXs+IzQxipvyH1KSutnxPQdisw1cvUQJ4NGPxJ2eS +lE7zzBAo8Z7+TU8BM3vsCA88GwbHgDmZpjjimO4ATQr0p1Q33aq4cycGsFc+MTbX ++Vr1BlEsw9pz56daqBSGGZYqukySB3scTRBgtDOiBNt2TLbGxSR6dtJHqUjESR2z +Ae6S15MWtxyBYRwgXHi7GBT2M2AEdQ+kgn22T62uXWtXYVQIRtcvarcF99fRtEvU +snqkMvep7QYhMfkqQu+Ng7bBWuA9uyebZ6dfWT155U5vBlYQXytMJLjnEo1AegQd +ZkofWNaRs3EkZBjLA0/fzMXEXVz/I0EK2tvM5FMbiCUqJGbN4EDk9bwoZy+AqfGj +RlXOpV5SrCDB7LHVyO3QJKNhuIOLl/GNvARacwwcujhQsX0d61bimnpBFAb9WyTQ +iblstq+Uf5SdBIidElMwT1Vp/kpNH1/BB7B1tVx/wHSiBSovq1ZCctJvuc6pWSWj +yISn3QQEYKT3odJwQc0FS5xOSH3uudHbMMhjlv95QNQILQy69EHSlmGl3EcCAwEA +AQKCAgEAgsBHNwOuf81gYlpYjLtlXqjG+uaFTo2WQCzvKQVWsjsktdKsAVCxnLGM +kIS4Cq7N/d1x+PXgyY0Kh+b1v+x2X+jukWiWwbXQSqJPL/3wcbAHUblupPHtOtYX +++zoFcvsn2NiG03bnZWkyuodb4cZyJURGfi/PXbdzsmK/Cg/XWSLWyqbJiZxbeft +0NqaZCCl1ZSrLSUEzGIdaLpouzncGnGVUlgV0b4YcJdcDnZFr08R4D7kQ80P70EI +lXqmYIL66OWcy/IZrFeGa6gXsjWBiwENKls3XhEd5sZW1i7wLCUcB5W7Q+HrdOun +HbrdMM0QNcnoI74gauuNkybE3vYBkmfM8vM8vH4eIx+CAS9gnfT7QhiTmUzgfD6k +MC/vpYMzzNAbzXn0FG6ks3PWgXoZitI0E107SuDDrqxv0E+x8uPrQ+z5yKX48EM+ +fgb3y7wRKNdHssJKbbZQluhyQy/yS7xUG2bt7/HEbrtqfeJQ4vhKrp/lT02k3a71 +MxieYFjoJEWvaIsx6FX/UGwqv3GBeQlJ0fmFqFDBwAFjbrPt5F517/uuj9ZjMdrF +wpXo2O70TUuOeBguqlSMkl7RcM0ax28cekz3AADHHQGGdrVKxsSyGZXq8AAM0e3n +a+TOxx8NXlOI/ZF3f6xOrdlhVU/egKg3cwpNeJwrwX8cpXwS/WkCggEBAOJhywQk +OETD3rIOKefQ30vxue04uH2egGZDnieVAE9AmGgHqlYnA+WovUHO1ueF53rvW380 +7CaVYWVXKtqLHKE4QY54Zap8cLQyGmT3NiAoYHhWy3veYn4j/FnmWtr34ZiPU9vy +dPSUTYn+BgHXE7QGksml6rXke+LwCuE/EmyhhyCczuJiqdI9jfJ6yZBQSGTivuHI +mk6kwUXWFK8xs/2y2CsXoWEhFmLGFw026sdg+f99r5962KaPjUTq2wWZnAHkYqKT +mm4UHSzW4ynq6LvFcRoqWebIh84SGg83qEkLcvLsQSq3s7/YPSJdXhjhxJmSved2 +zquhYiYMl+USCZsCggEBANM9BSPFWhjvVwrbCKv48i/6QblvhwwTC7N0rdyt1ksB +xM2wsDXf4LXPq+jhO/tfSl+QU+1E9imHQroP2SE6+0CSdvM10PBBoSz0pjRAfutA +6KF6baAZ6con5T22v3cG6hTIG7EmMNcXs5XOyCU/0tvtxY2XRTrZQDwzvE8+8TMU +w7sK/zekuffUQwtfbRd4Acx+pPKyP1wWxg4x3LFTEQM+21dZ2ZQvvngUogW4LPyc +fN5G8poFbuUwzMb//JTrSVejdMKQFTrNzTr/GyLdoF0L3LRz5vOnNtZA4rIyOMFF +FH47vwICQiZ+aJhNkD9CbEvnwSTUL5wuDx7s+K8w6MUCggEAYqEqu0Ywgb04pCjJ +lycIcmUBlVn1/zz0QhnJqQMg3GaPQBu+2cQrzX5D3o0IUlyjqoroOTbMgE7q3SUq +FYcwVQlWfoTz/mAzFj8SAtU17rLIvQVLqE8OaFizVFOpV+dRkY84gQZUcE7ArZNP ++LNE8VU/1L0F0nOWihv9EX/SPiPt5IaNGFLWHDQXSQK4GLjxoYqskWA94m+jiRKp +dl7YRXsK9VNZSyEISMZ3OpmnlnAo22heAMSb6Y13hgQwonL3ZlejpaNbUARRZbzF +wfiHp29xRG4ZNxQ9HsoCMokUN6bWUQIfrkXU+YtzryowmfSbHDGzrUm050/rnBo2 +f2XpawKCAQEAw5Bgq8dQLHmY+iHim2Q0xBpKsuUAADu5v4CsXfxKwtJ2Y3/LA3Wr +UmdbXpT3tTd5YZP7P1VzGOty6VM20D8M0bFHks8mCuiX0UkGfqWfWymStbzktS6I +dXIOF96S0B2EpYzFpnIXEWuOBYmVXncCPj6ZgQalP2BWyeWT10IMiCAXPZlmwxss +WLcZAvRrySh/cdVl3JMNebJT1lxvV3Px8jFFXE+A0mKJUh64CdeDPrOaHydL/zA8 +hM9zJmFkdHKISiy4MlC2duSFtrLrapIIn1wWDrKnBLiwWhdkSVmZlcTgviWOJsv0 +djLdnvNgMlDKdlOvSutu0IcL1LPLYFZFiQKCAQBv1X9MCwppE/0yAb07CAuynX0d +ZyqH4si0ghGqLACmu7HPBndbN4A0SJKlyyGm8+rpNXc3NaZrWfZ2ENmgqiSo7dmE +tl3y+dUVRvMdyB/SK7MHAue+QHDGzCPXrlze3nuI53jJ8RotVvFI9rCIhsK2frAT +a8LQo7wdVm5dmrrN7sllJ75biN0eD1Lfq8Pzpnu1P7TuIvE1esQfSm3c5tZuTeQO +pvL+27Z183OvSTXe4YInyNSasshPDkdzBxoS1fJSS313/cl2gyrG5SxheOK7ft7+ +zzwjaBm/aJCXg3QOLmYMNkOdyRp5hbtLfFbWE5vafJMEA5bfeaS2H1jsQ5UV +-----END RSA PRIVATE KEY----- diff --git a/aosp/hardware/google/camera/devices/EmulatedCamera/hwl/apex/com.google.camera.provider.hal.pk8 b/aosp/hardware/google/camera/devices/EmulatedCamera/hwl/apex/com.google.camera.provider.hal.pk8 new file mode 100644 index 0000000000000000000000000000000000000000..f83b5da6f64ec95f33e2bb574718d21fa51e1c84 GIT binary patch literal 2376 zcmV-O3Agqzf(b+d0RS)!1_>&LNQUwE--=#Dgprj0)heo0Ix@oojf#i zmG3?(ctwM$Z_R zf01Ye2sx*m9bw&T#K~2>RRxB<9EfZ@ff$T0epP#aw;SQJCeI z*iwA=k`fXHg=7x>8D-r5>Fz2|t?o!x#1ZhvWL0iv!@r`~Es`y{F&D~_S{B3K%QC8l zgVeMfQxq92SKNjDs7a%JVz<_UgbijU0hB?^Mvm7R`0RqRR31Ex(eiT4!tB&xl&|nj zl}$cL0c%7wJm%cXYCdanGTw-(HammO=Wk0#uj=jKR=m{r?ykbE6rWLWLUCMi)gNEq zja4e^NXB;B%=ZS#%Mye{#gCL`9Gf2hVJ~6TsECpSmx`paB%%u-WOkjGKgAw0 z{zL9s*V?weN0HSeU=xMe2v1JiXC+Sm;GttX3Wu3GmqFo|k;f_Su_Iba6`l-F*#ZLr009Dm0s#Pvoojh= z{Vd!VO|ft`THf@R_8g#7wzIeD6+FW95r~f1W~Pyqdu21(IFB(rHaw{B0#Ibf>_Q%( z(<{k$9_=Sc6;tY~i(O7IIMjT+oG5}*z%wa%P9T1E#F}JQ7avA#IEa=&+9WX*@JBpd zsj`_=iz)y0*x3O2L|-Bu+dN4{W%_l-d1P~B{_iv5K)@zvyyS@32?v}lAu~!D90+8n zgy008CZO>n?=d|B@XxJ&igiBr@w73ue<;F7RkpwTcoVE*43=T)gy|RZgIO_LOzugZ2d8iE@ z)o9sHsWeTdZh)68S)_=q@%C*xk5j6~K2Ld7K@5W=&Qn+p#?hLHT8b(VOn@7)@YYi3 zt$_S)D(Rp;T%vOn3cLn|aUSkoKGL_1qeH69?Ia;l`=fRF}

LG-_b3y^)Bk z@3p!a#P9hLsFcM-f*`=Q5j)_5_;AZ@ihsEqSPi^O{>Arzx9Xt+f&l>l)l|DT^|#B` z5IKY&SF9??+%zbiEVw;b+!mOudJAV*6b@b^H?C`Y0(;TpYV5@aIvxRPh2-`}d?Nt) z-eY)p#I9A4XSI`M7MK)F7`ro%DZ7F4YojC=W$HL1j(8UCn>Gg~5-OpsL0+W)HS|nD zi3A=J6N?0!2_({%n8pC`&U9-5)6!uHvpxi#Y{81V!-0NSYq~`GodJq$uGQ7H>rXdU zaJ?kV)K6V+)*zbMx?2ln2^sxk*j)EVt&>wvE#wd){t)T$sv;-(6kHHF)u%AP8&6Fv zKL#!ZaRp0s4H_|qTj+K}fSrxB|HZq!^Krwdv5t##qG0)hbn0Mb@?un?F> zBZ_gm%+VhBxtzSGchhH@mUw%F_rm5$%zghmR1H;?TBa!qRflWIb#T#~jDnJ4b01K* z5{j9x*~1_L75BLdfEB1s!8S~OO=nu22SqcvU}Ig4oQg(ir`SH8@!%UNHj3+;B;etK zjsVjQem~9Vp`1v%b7^=6)+$tr*)QT&7BnJ>D>nQFF$9G#Bkr`wZd1B-Y8J##xk|l# zqJ#T6J`-wDN*PBdRV_&(H!}jUaot%E&KbWu_`QizH{B1W8k6x86#{|*07fWWebv~3 zH^3A+NLYLAf-5l?9zdhQ!6SHP^J*Kf`~Gx~F9Xxx(+`OY2*8wQW3CWNB=0TKbj9^~ z53{_0)h^Mhpco5Q6AQ2|6s(ziCR_3+l|v%l?za4;L&QnwIL2V9PcraCMTb`j>PVwB zB;{MKOaYTwi)SHj1WNDgMMjWt)T9OP71EW}%?LG0Ti?40gDAq3hT8SB!E|aYqrjC% zysXUkdP!ttbucx4*OmJ9FJL3&`d%Q6&P?7zs;P_gW}T^!R)W4l=^k!O(uUm9Ea98jHdyXIHkjDd~n6U(m@aWG(P&n8OPg_aLs0uUH3^(Ir2XvY!FVs@d z5JhvWjv*`$E|*iv0tMs#22*IlZ}2BhkW4{R=wyYK@g`!MK!k|l!96%Uq;-A-l9on^ibv>k@AeWBUF+jYg4(&LS|0(ok?hTAIksw=v|Pz@K& zj<-e7W);QXwQa`P{O0AvvB04HZs1`*4!}}k@O)%t?A<577Zko uMn@a!s=_dy7FP0d&`apH0Hh|dvfWL{2{mx3lKT8wE!HVkKY(pZmi3(P9&b1R literal 0 HcmV?d00001 diff --git a/aosp/hardware/google/camera/devices/EmulatedCamera/hwl/apex/com.google.camera.provider.hal.rc b/aosp/hardware/google/camera/devices/EmulatedCamera/hwl/apex/com.google.camera.provider.hal.rc new file mode 100644 index 000000000..505d580e4 --- /dev/null +++ b/aosp/hardware/google/camera/devices/EmulatedCamera/hwl/apex/com.google.camera.provider.hal.rc @@ -0,0 +1,11 @@ +# Re-start the service on rebootless-update +on property:apex.com.google.camera.provider.hal.ready=true + start vendor.camera-provider-2-7-google + +service vendor.camera-provider-2-7-google /apex/com.google.camera.provider.hal/bin/hw/android.hardware.camera.provider@2.7-service-google + class hal + user system + group system + capabilities SYS_NICE + rlimit rtprio 10 10 + task_profiles CameraServiceCapacity CameraServicePerformance diff --git a/aosp/hardware/google/camera/devices/EmulatedCamera/hwl/apex/com.google.camera.provider.hal.x509.pem b/aosp/hardware/google/camera/devices/EmulatedCamera/hwl/apex/com.google.camera.provider.hal.x509.pem new file mode 100644 index 000000000..528c923d0 --- /dev/null +++ b/aosp/hardware/google/camera/devices/EmulatedCamera/hwl/apex/com.google.camera.provider.hal.x509.pem @@ -0,0 +1,34 @@ +-----BEGIN CERTIFICATE----- +MIIF7TCCA9UCFHsvubLT/OxpJdqifK/l7sBMmpCoMA0GCSqGSIb3DQEBCwUAMIGx +MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91 +bnRhaW4gVmlldzEQMA4GA1UECgwHQW5kcm9pZDEQMA4GA1UECwwHQW5kcm9pZDEi +MCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTEtMCsGA1UEAwwkY29t +LmFuZHJvaWQuaGFyZHdhcmUuY2FtZXJhLnByb3ZpZGVyMCAXDTIyMDEyNDIzMTMy +NloYDzQ3NTkxMjIxMjMxMzI2WjCBsTELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNh +bGlmb3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxEDAOBgNVBAoMB0FuZHJv +aWQxEDAOBgNVBAsMB0FuZHJvaWQxIjAgBgkqhkiG9w0BCQEWE2FuZHJvaWRAYW5k +cm9pZC5jb20xLTArBgNVBAMMJGNvbS5hbmRyb2lkLmhhcmR3YXJlLmNhbWVyYS5w +cm92aWRlcjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK9HkJ08NHPl +75cP95BmQ+ODGQ/9QWKyFn0oCmXAuIgjPDgOyqyCQ5zuUW2xOALeRBsB9+7vf4ZG +zxiXf5FoBAg5p5wdYd1rxMlVvFUFhr0ciGw8gRiML35Ve3+3G+GzJtUft+KfQ932 +VvcDA6SobNhSfPeSEhIFhWQO/Rll3P7p7ipPre5IVsQR8MdkVW5mw7+i2C2SLbkx +F8qRWhbD38syqoaD1LQcUxQZLFfchf2oSaN9YrfWgoQNZiYBlEHMRo7XGfjsgrJU +HjyM0fJyzMLs1GGUr/BNlU0+SQFrRDQ85tzLaj5rcjLeiKk2O4PN529LR6/q7eBW +vNT37q7CrRSfUXBCcVxx1R9f341VKutIxnbazPcGycsShETFj5RmHJse/2EveB6h +5ficqIiSA5eKpLIkogsgZHadlz/FHjL+Q+5a19q2vkeR1SRgE4XZCE9O22clTv/g +oWM7CoeZOpdB4ZeRxynusSNaShWeDRYxrQRsiMRIjn8TdTD+Nd6nD4/QKITFpuGF +5klnaqx1s+XxdHBTQ0QNttKuTE212F0Vc6CcA0UwvoQGFjQfzOAiXBktLmh9vMRY +6tTDhS9OK+Z6Ioy9S/Vv9vi77CRJ5Fl8g+rXlbkdJtp84B8igLvx/oOxu95mB/M7 +2RWwMGHnFFKS3aUZm7ypuJNBHTxk0PLZAgMBAAEwDQYJKoZIhvcNAQELBQADggIB +AFAY+aeKyZ/UjgWX8vqWH7fLVKa4zwQGgLpr7Uo9c7vMtXwWdJkgbSzKQjcsC8WL +c7c26Acv1CpULo3U/b67N+3WnQr3F3K3YraKuiBCMCuTjeq0k3yZyuwr2ktzpo23 +Ei77ldprBu/I7CSOWYOzJCgsymuSbzJhjEt2LKTR+gNLWyKFQJhZZIY2oTq1LT2j +CMVYvVnuDSWW/Dt6u2+tIgFr2u3ZB7TtkfSNgT797gmCdRn4rEJFDH6ExFFDHBa4 +cfWPqZDs+X871jOInqkJVjBT6RMdW/PewY9i2gb/BU7mTziR8/n9+QvHBReH44Ys +nVNjC09/njG/jrAILB3y/df4zDJUJMz1jOZXZyuAE0bo08+YhG58Ms1wJ26oAu9E +PXBNDv9ihISsepOoY7laoFyrPIlXitRtXd/zbY+k7Uw0dwNNJ3dwhcuKO+FDW5pb +Lubh2w6TgQKUGqPwe9C3hLmvYVqc34U/R61Fq33dRwl6wxzoWQ6R+DuC42GWFyiz +nXWTUTPBOy9xTHtNi2nDvGh4M3ILLBWPseNJfQkDloLOlOjBQpMMvOfW0qcBQeRd +cexJXMTwx/mEeron+cxIjQerWdvjNMhAPPQdFGN/yDbsoNrZdYH+xszJ2paa4gTl +9Cl3KC8vmRy2JyD6P7Cv9D1BGekHODIRR+ccyfarcfGm +-----END CERTIFICATE----- diff --git a/aosp/hardware/google/camera/devices/EmulatedCamera/hwl/configs/Android.bp b/aosp/hardware/google/camera/devices/EmulatedCamera/hwl/configs/Android.bp new file mode 100644 index 000000000..9615ffe5f --- /dev/null +++ b/aosp/hardware/google/camera/devices/EmulatedCamera/hwl/configs/Android.bp @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package { + // See: http://go/android-license-faq + default_applicable_licenses: ["Android-Apache-2.0"], +} + +prebuilt_defaults { + name: "emu_camera_config_defaults", + relative_install_path: "config", + soc_specific: true, + installable: false, +} + +prebuilt_etc { + name: "google_camera_back.json", + src: "google_camera_back.json", + defaults: ["emu_camera_config_defaults"], +} + +prebuilt_etc { + name: "google_camera_depth.json", + src: "google_camera_depth.json", + defaults: ["emu_camera_config_defaults"], +} + +prebuilt_etc { + name: "google_camera_front.json", + src: "google_camera_front.json", + defaults: ["emu_camera_config_defaults"], +} + +prebuilt_etc { + name: "google_camera_external.json", + src: "google_camera_external.json", + defaults: ["emu_camera_config_defaults"], +} diff --git a/aosp/hardware/google/camera/devices/EmulatedCamera/hwl/configs/google_camera_back.json b/aosp/hardware/google/camera/devices/EmulatedCamera/hwl/configs/google_camera_back.json new file mode 100644 index 000000000..2e4ed9d4e --- /dev/null +++ b/aosp/hardware/google/camera/devices/EmulatedCamera/hwl/configs/google_camera_back.json @@ -0,0 +1,1038 @@ +{ + "android.colorCorrection.availableAberrationModes": [ + "0", + "1", + "2" + ], + "android.control.aeAvailableAntibandingModes": [ + "0", + "3" + ], + "android.control.aeAvailableModes": [ + "0", + "1", + "2", + "3" + ], + "android.control.aeAvailableTargetFpsRanges": [ + "15", + "15", + "15", + "30", + "30", + "30" + ], + "android.control.aeCompensationRange": [ + "-9", + "9" + ], + "android.control.aeCompensationStep": [ + "1", + "3" + ], + "android.control.aeLockAvailable": [ + "TRUE" + ], + "android.control.afAvailableModes": [ + "0", + "1", + "2", + "3", + "4" + ], + "android.control.availableExtendedSceneModeMaxSizes": [ + "0", + "0", + "0", + "1", + "1920", + "1080", + "64", + "1920", + "1080" + ], + "android.control.availableExtendedSceneModeZoomRatioRanges": [ + "1.0", + "4.0", + "1.0", + "4.0" + ], + "android.control.availableEffects": [ + "0" + ], + "android.control.availableModes": [ + "0", + "1", + "2", + "4" + ], + "android.control.availableSceneModes": [ + "1" + ], + "android.control.availableSettingsOverrides": [ + "0", + "1" + ], + "android.control.availableVideoStabilizationModes": [ + "0", + "1", + "2" + ], + "android.control.awbAvailableModes": [ + "0", + "1", + "2", + "3", + "5", + "8" + ], + "android.control.awbLockAvailable": [ + "TRUE" + ], + "android.control.autoframingAvailable": [ + "FALSE" + ], + "android.control.maxRegions": [ + "1", + "0", + "1" + ], + "android.control.postRawSensitivityBoostRange": [ + "100", + "100" + ], + "android.control.sceneModeOverrides": [ + "1", + "1", + "1" + ], + "android.control.zoomRatioRange": [ + "1.0", + "10.0" + ], + "android.edge.availableEdgeModes": [ + "0", + "1", + "2", + "3" + ], + "android.flash.singleStrengthMaxLevel" : [ + "10" + ], + "android.flash.singleStrengthDefaultLevel": [ + "2" + ], + "android.flash.torchStrengthDefaultLevel": [ + "5" + ], + "android.flash.torchStrengthMaxLevel" :[ + "15" + ], + "android.flash.info.available": [ + "TRUE" + ], + "android.flash.info.strengthMaximumLevel": [ + "10" + ], + "android.flash.info.strengthDefaultLevel": [ + "3" + ], + "android.hotPixel.availableHotPixelModes": [ + "0", + "1", + "2" + ], + "android.info.supportedHardwareLevel": [ + "3" + ], + "android.jpeg.availableThumbnailSizes": [ + "0", + "0", + "160", + "120", + "320", + "240" + ], + "android.jpeg.maxSize": [ + "300000" + ], + "android.lens.facing": [ + "BACK" + ], + "android.lens.info.availableApertures": [ + "2.79999995" + ], + "android.lens.info.availableFilterDensities": [ + "0.00000000" + ], + "android.lens.info.availableFocalLengths": [ + "3.29999995" + ], + "android.lens.info.availableOpticalStabilization": [ + "0" + ], + "android.lens.info.focusDistanceCalibration": [ + "APPROXIMATE" + ], + "android.lens.info.hyperfocalDistance": [ + "0.20000000" + ], + "android.lens.info.minimumFocusDistance": [ + "20.00000000" + ], + "android.lens.info.shadingMapSize": [ + "17", + "13" + ], + "android.noiseReduction.availableNoiseReductionModes": [ + "0", + "1", + "2", + "4" + ], + "android.request.availableCapabilities": [ + "BACKWARD_COMPATIBLE", + "MANUAL_SENSOR", + "MANUAL_POST_PROCESSING", + "READ_SENSOR_SETTINGS", + "BURST_CAPTURE", + "PRIVATE_REPROCESSING", + "YUV_REPROCESSING", + "RAW", + "DYNAMIC_RANGE_TEN_BIT", + "STREAM_USE_CASE", + "COLOR_SPACE_PROFILES" + ], + "android.sensor.referenceIlluminant1": [ + "D50" + ], + "android.statistics.info.availableHotPixelMapModes": [ + "0", + "1" + ], + "android.request.maxNumInputStreams": [ + "1" + ], + "android.request.availableDynamicRangeProfilesMap": [ + "2", + "3", + "0" + ], + "android.request.availableColorSpaceProfilesMap": [ + "0", + "35", + "1", + "16", + "54", + "2", + "7", + "35", + "1", + "0", + "34", + "1", + "16", + "34", + "2", + "7", + "34", + "1", + "0", + "256", + "1", + "7", + "256", + "1" + ], + "android.request.recommendedTenBitDynamicRangeProfile": [ + "2" + ], + "android.scaler.availableInputOutputFormatsMap": [ + "34", + "2", + "33", + "35", + "35", + "2", + "33", + "35" + ], + "android.scaler.availableStreamUseCases": [ + "0", + "1", + "2", + "3", + "4", + "5", + ], + "android.reprocess.maxCaptureStall": [ + "2" + ], + "android.request.availableCharacteristicsKeys": [ + "983043", + "983044", + "983041", + "917517", + "983045", + "983046", + "983040", + "917518", + "983048", + "983042", + "983047", + "917516", + "917529", + "589826", + "589829", + "589828", + "589824", + "589825", + "589827", + "589830", + "589831", + "524293", + "327680", + "1245188", + "1245189", + "851978", + "851979", + "851980", + "851981", + "851972", + "458759", + "458760", + "1179648", + "1179650", + "1179655", + "1507329", + "65589", + "65574", + "65561", + "65560", + "65564", + "65555", + "65558", + "65557", + "65556", + "65554", + "65572", + "65563", + "65573", + "65559", + "65562", + "4", + "196610", + "1376256", + "655362", + "1048578", + "786438", + "786442", + "786443", + "786444", + "786445", + "786446", + "786447", + "65575", + "65579", + "65580", + "65582", + "65592", + "983050", + "393217", + "1572865", + "786440", + "851977", + "917507", + "917509", + "917511", + "917513", + "1179654", + "851984", + "-2080374781" + ], + "android.request.availableRequestKeys": [ + "786435", + "786433", + "786432", + "524290", + "524291", + "524288", + "524289", + "524292", + "917504", + "917505", + "917506", + "262146", + "262144", + "262145", + "393216", + "131072", + "655360", + "1048576", + "0", + "1245187", + "196608", + "1", + "2", + "1245186", + "1245185", + "1245184", + "851968", + "458756", + "458758", + "458757", + "458752", + "458753", + "458754", + "458755", + "1114112", + "1114115", + "65549", + "65551", + "65541", + "65550", + "65552", + "65539", + "65538", + "65540", + "65537", + "65536", + "65542", + "65547", + "65546", + "65543", + "65544", + "65545", + "65553", + "65588", + "1441792", + "1114128", + "3", + "917528", + "65576", + "65581", + "65583", + "851985", + "-2080374783", + "-2080374782", + "-2080374780", + "2097152" + ], + "android.request.availableResultKeys": [ + "786435", + "786433", + "786432", + "524290", + "524291", + "524288", + "524289", + "524292", + "917504", + "917505", + "917506", + "262146", + "262144", + "262145", + "393216", + "131072", + "655360", + "1048576", + "0", + "1245187", + "196608", + "1", + "2", + "1245186", + "1245185", + "1245184", + "851968", + "458756", + "458758", + "458757", + "458752", + "458753", + "458754", + "458755", + "1114112", + "1114115", + "65549", + "65551", + "65541", + "65550", + "65552", + "65539", + "65538", + "65540", + "65537", + "65536", + "65542", + "65547", + "65546", + "65543", + "65544", + "65545", + "65553", + "65588", + "65590", + "1441792", + "1114128", + "3", + "917528", + "65567", + "65568", + "65570", + "262149", + "524297", + "524296", + "917530", + "1114126", + "1114123", + "786441", + "917520", + "917522", + "65576", + "65581", + "65583", + "917523", + "917526", + "851985", + "1114133", + "1114134", + "1703939", + "-2080374783", + "-2080374782" + ], + "android.request.availableSessionKeys": [ + "786435", + "-2080374782" + ], + "android.request.maxNumOutputStreams": [ + "1", + "3", + "1" + ], + "android.request.partialResultCount": [ + "2" + ], + "android.request.pipelineMaxDepth": [ + "8" + ], + "android.scaler.availableMaxDigitalZoom": [ + "10.00000000" + ], + "android.scaler.availableRotateAndCropModes": [ + "0", + "1", + "4" + ], + "android.scaler.availableMinFrameDurations": [ + "32", + "1920", + "1080", + "33331760", + "33", + "1920", + "1080", + "33331760", + "54", + "1920", + "1080", + "33331760", + "33", + "1280", + "720", + "33331760", + "54", + "1280", + "720", + "33331760", + "34", + "160", + "120", + "33331760", + "54", + "160", + "120", + "33331760", + "34", + "320", + "240", + "33331760", + "54", + "320", + "240", + "33331760", + "35", + "160", + "120", + "33331760", + "33", + "160", + "120", + "33331760", + "35", + "320", + "240", + "33331760", + "33", + "320", + "240", + "33331760", + "34", + "640", + "480", + "33331760", + "35", + "640", + "480", + "33331760", + "33", + "640", + "480", + "33331760", + "54", + "640", + "480", + "33331760", + "34", + "1280", + "720", + "33331760", + "34", + "1920", + "1080", + "33331760", + "35", + "1280", + "720", + "33331760", + "35", + "1920", + "1080", + "33331760", + "1", + "1600", + "1200", + "33331760", + "34", + "176", + "144", + "33331760", + "35", + "176", + "144", + "33331760", + "33", + "176", + "144", + "33331760", + "54", + "176", + "144", + "33331760", + "34", + "1024", + "768", + "33331760", + "35", + "1024", + "768", + "33331760", + "33", + "1024", + "768", + "33331760", + "54", + "1024", + "768", + "33331760" + ], + "android.scaler.availableStallDurations": [ + "32", + "1920", + "1080", + "33331760", + "33", + "1920", + "1080", + "33331760", + "33", + "1280", + "720", + "33331760", + "33", + "1024", + "768", + "33331760", + "54", + "1024", + "768", + "0", + "34", + "160", + "120", + "0", + "34", + "320", + "240", + "0", + "35", + "160", + "120", + "0", + "54", + "160", + "120", + "0", + "35", + "320", + "240", + "0", + "1", + "320", + "240", + "0", + "54", + "320", + "240", + "0", + "34", + "640", + "480", + "0", + "35", + "640", + "480", + "0", + "33", + "640", + "480", + "33331760", + "54", + "640", + "480", + "0", + "34", + "1280", + "720", + "0", + "34", + "1920", + "1080", + "0", + "35", + "1280", + "720", + "0", + "54", + "1280", + "720", + "0", + "35", + "1920", + "1080", + "0", + "54", + "1920", + "1080", + "0", + "1", + "1600", + "1200", + "0", + "54", + "1024", + "768", + "0", + "33", + "160", + "120", + "33331760", + "33", + "320", + "240", + "33331760", + "33", + "176", + "144", + "33331760" + ], + "android.scaler.availableStreamConfigurations": [ + "35", + "1920", + "1080", + "INPUT", + "33", + "1920", + "1080", + "OUTPUT", + "33", + "1280", + "720", + "OUTPUT", + "34", + "160", + "120", + "OUTPUT", + "33", + "160", + "120", + "OUTPUT", + "54", + "160", + "120", + "OUTPUT", + "34", + "320", + "240", + "OUTPUT", + "54", + "320", + "240", + "OUTPUT", + "35", + "160", + "120", + "OUTPUT", + "35", + "320", + "240", + "OUTPUT", + "33", + "320", + "240", + "OUTPUT", + "34", + "640", + "480", + "OUTPUT", + "35", + "640", + "480", + "OUTPUT", + "33", + "640", + "480", + "OUTPUT", + "54", + "640", + "480", + "OUTPUT", + "34", + "1280", + "720", + "OUTPUT", + "34", + "1920", + "1080", + "INPUT", + "34", + "1920", + "1080", + "OUTPUT", + "35", + "1280", + "720", + "OUTPUT", + "54", + "1280", + "720", + "OUTPUT", + "35", + "1920", + "1080", + "OUTPUT", + "32", + "1920", + "1080", + "OUTPUT", + "54", + "1920", + "1080", + "OUTPUT", + "INPUT", + "1600", + "1200", + "OUTPUT", + "34", + "176", + "144", + "OUTPUT", + "35", + "176", + "144", + "OUTPUT", + "33", + "176", + "144", + "OUTPUT", + "54", + "176", + "144", + "OUTPUT", + "34", + "1024", + "768", + "OUTPUT", + "35", + "1024", + "768", + "OUTPUT", + "33", + "1024", + "768", + "OUTPUT", + "54", + "1024", + "768", + "OUTPUT" + ], + "android.scaler.croppingType": [ + "CENTER_ONLY" + ], + "android.sensor.calibrationTransform1": [ + "128", + "128", + "0", + "128", + "0", + "128", + "0", + "128", + "128", + "128", + "0", + "128", + "0", + "128", + "0", + "128", + "128", + "128" + ], + "android.sensor.colorTransform1": [ + "3209", + "1024", + "-1655", + "1024", + "-502", + "1024", + "-1002", + "1024", + "1962", + "1024", + "34", + "1024", + "73", + "1024", + "-234", + "1024", + "1438", + "1024" + ], + "android.sensor.forwardMatrix1": [ + "446", + "1024", + "394", + "1024", + "146", + "1024", + "227", + "1024", + "734", + "1024", + "62", + "1024", + "14", + "1024", + "99", + "1024", + "731", + "1024" + ], + "android.sensor.availableTestPatternModes": [ + "0", + "1", + "5" + ], + "android.sensor.blackLevelPattern": [ + "64", + "64", + "64", + "64" + ], + "android.sensor.info.activeArraySize": [ + "0", + "0", + "1920", + "1080" + ], + "android.sensor.info.colorFilterArrangement": [ + "RGGB" + ], + "android.sensor.info.exposureTimeRange": [ + "1000", + "300000000" + ], + "android.sensor.info.maxFrameDuration": [ + "300000000" + ], + "android.sensor.info.physicalSize": [ + "3.20000005", + "2.40000010" + ], + "android.sensor.info.pixelArraySize": [ + "1920", + "1080" + ], + "android.sensor.info.preCorrectionActiveArraySize": [ + "0", + "0", + "1920", + "1080" + ], + "android.sensor.info.sensitivityRange": [ + "100", + "1600" + ], + "android.sensor.info.timestampSource": [ + "REALTIME" + ], + "android.sensor.info.whiteLevel": [ + "4000" + ], + "android.sensor.maxAnalogSensitivity": [ + "1600" + ], + "android.sensor.orientation": [ + "90" + ], + "android.shading.availableModes": [ + "0", + "1", + "2" + ], + "android.statistics.info.availableFaceDetectModes": [ + "0", + "1", + "2" + ], + "android.statistics.info.availableLensShadingMapModes": [ + "0", + "1" + ], + "android.statistics.info.maxFaceCount": [ + "8" + ], + "android.sync.maxLatency": [ + "PER_FRAME_CONTROL" + ], + "android.tonemap.availableToneMapModes": [ + "0", + "1", + "2" + ], + "android.tonemap.maxCurvePoints": [ + "128" + ] +} diff --git a/aosp/hardware/google/camera/devices/EmulatedCamera/hwl/configs/google_camera_depth.json b/aosp/hardware/google/camera/devices/EmulatedCamera/hwl/configs/google_camera_depth.json new file mode 100644 index 000000000..8497e861a --- /dev/null +++ b/aosp/hardware/google/camera/devices/EmulatedCamera/hwl/configs/google_camera_depth.json @@ -0,0 +1,532 @@ +{ + "android.colorCorrection.availableAberrationModes": [ + "0" + ], + "android.control.aeAvailableAntibandingModes": [ + "0" + ], + "android.control.aeAvailableTargetFpsRanges": [ + "5", + "20", + "20", + "20" + ], + "android.control.aeCompensationRange": [ + "0", + "0" + ], + "android.control.aeCompensationStep": [ + "0", + "10" + ], + "android.control.aeLockAvailable": [ + "FALSE" + ], + "android.control.afAvailableModes": [ + "0" + ], + "android.control.availableEffects": [ + "0" + ], + "android.control.availableModes": [ + "0", + "1" + ], + "android.control.availableSceneModes": [ + "0" + ], + "android.control.availableVideoStabilizationModes": [ + "0" + ], + "android.control.awbAvailableModes": [ + "0" + ], + "android.control.awbLockAvailable": [ + "FALSE" + ], + "android.control.autoframingAvailable": [ + "FALSE" + ], + "android.control.maxRegions": [ + "0", + "0", + "0" + ], + "android.control.sceneModeOverrides": [ + "0", + "0", + "0" + ], + "android.depth.availableDepthMinFrameDurations": [ + "540422489", + "240", + "180", + "50000000" + ], + "android.depth.availableDepthStallDurations": [ + "540422489", + "240", + "180", + "50000000" + ], + "android.depth.availableDepthStreamConfigurations": [ + "540422489", + "240", + "180", + "OUTPUT" + ], + "android.depth.depthIsExclusive": [ + "TRUE" + ], + "android.depth.maxDepthSamples": [ + "43200" + ], + "android.flash.info.available": [ + "FALSE" + ], + "android.hotPixel.availableHotPixelModes": [ + "0" + ], + "android.info.supportedHardwareLevel": [ + "LIMITED" + ], + "android.jpeg.maxSize": [ + "29942792" + ], + "android.lens.distortion": [ + "-0.02708390", + "0.25425965", + "-0.53240901", + "0.00000000", + "0.00000000" + ], + "android.lens.facing": [ + "BACK" + ], + "android.lens.info.availableApertures": [ + "1.70000005" + ], + "android.lens.info.availableFilterDensities": [ + "0.00000000" + ], + "android.lens.info.availableFocalLengths": [ + "3.25999999" + ], + "android.lens.info.availableOpticalStabilization": [ + "0" + ], + "android.lens.info.focusDistanceCalibration": [ + "APPROXIMATE" + ], + "android.lens.info.hyperfocalDistance": [ + "0.44789043" + ], + "android.lens.info.minimumFocusDistance": [ + "0.00000000" + ], + "android.lens.intrinsicCalibration": [ + "212.91796875", + "213.16793823", + "118.33354950", + "91.61108398", + "0.00000000" + ], + "android.lens.poseReference": [ + "PRIMARY_CAMERA" + ], + "android.lens.poseRotation": [ + "0.71329737", + "-0.70067680", + "0.00672206", + "0.01461948" + ], + "android.lens.poseTranslation": [ + "-0.01890985", + "-0.00000000", + "-0.00000000" + ], + "android.noiseReduction.availableNoiseReductionModes": [ + "0" + ], + "android.reprocess.maxCaptureStall": [ + "2" + ], + "android.request.availableCapabilities": [ + "DEPTH_OUTPUT" + ], + "android.request.availableCharacteristicsKeys": [ + "4", + "65554", + "65555", + "65556", + "65557", + "65558", + "65559", + "65560", + "65561", + "65562", + "65563", + "65564", + "65565", + "65571", + "65572", + "65573", + "65574", + "65575", + "65592", + "1638402", + "1638401", + "1638403", + "327680", + "393217", + "458759", + "458760", + "589824", + "589825", + "589826", + "589827", + "589828", + "589829", + "589830", + "589831", + "524293", + "1703936", + "786438", + "786440", + "786442", + "786443", + "786444", + "786445", + "786446", + "786447", + "786448", + "851972", + "851977", + "851978", + "851979", + "851980", + "851981", + "983040", + "917526", + "917523", + "917534", + "983041", + "983042", + "983043", + "983044", + "983045", + "983046", + "983047", + "983048", + "983049", + "983050", + "917507", + "917508", + "917509", + "917510", + "917511", + "917512", + "917513", + "917514", + "917516", + "917517", + "917518", + "917519", + "917529", + "1048578", + "1179648", + "1179650", + "1179654", + "1179655", + "1245188", + "1245189", + "1376256", + "1507329", + "1572865", + "1638404", + "524298", + "524294", + "524295", + "524300", + "524301", + "1638400" + ], + "android.request.availableRequestKeys": [ + "3", + "65542", + "65576", + "393216", + "458752", + "458753", + "458754", + "524288", + "524289", + "524290", + "524291", + "524292", + "786433", + "917520", + "1114115", + "1245184", + "1245185", + "1245186", + "65541", + "65549" + ], + "android.request.availableResultKeys": [ + "65567", + "524294", + "524295", + "524298", + "524301", + "65570", + "65576", + "262149", + "458752", + "458753", + "458754", + "524288", + "524289", + "524290", + "524291", + "524296", + "524297", + "524292", + "786433", + "917526", + "917523", + "917520", + "917522", + "917525", + "1114121", + "1114124", + "1114125", + "1114126", + "1114118", + "1114119", + "1245184", + "1245185", + "1245186", + "65541", + "65549" + ], + "android.request.maxNumInputStreams": [ + "0" + ], + "android.request.maxNumOutputStreams": [ + "1", + "3", + "2" + ], + "android.request.partialResultCount": [ + "0" + ], + "android.request.pipelineMaxDepth": [ + "8" + ], + "android.scaler.availableMaxDigitalZoom": [ + "1.00000000" + ], + "android.scaler.croppingType": [ + "CENTER_ONLY" + ], + "android.sensor.availableTestPatternModes": [ + "0" + ], + "android.sensor.blackLevelPattern": [ + "64", + "64", + "64", + "64" + ], + "android.sensor.calibrationTransform1": [ + "1024", + "1024", + "0", + "1024", + "0", + "1024", + "0", + "1024", + "1024", + "1024", + "0", + "1024", + "0", + "1024", + "0", + "1024", + "1024", + "1024" + ], + "android.sensor.calibrationTransform2": [ + "1024", + "1024", + "0", + "1024", + "0", + "1024", + "0", + "1024", + "1024", + "1024", + "0", + "1024", + "0", + "1024", + "0", + "1024", + "1024", + "1024" + ], + "android.sensor.colorTransform1": [ + "698", + "1024", + "-90", + "1024", + "-120", + "1024", + "-603", + "1024", + "1517", + "1024", + "73", + "1024", + "-206", + "1024", + "441", + "1024", + "482", + "1024" + ], + "android.sensor.colorTransform2": [ + "1395", + "1024", + "-636", + "1024", + "-181", + "1024", + "-462", + "1024", + "1542", + "1024", + "-29", + "1024", + "-61", + "1024", + "314", + "1024", + "572", + "1024" + ], + "android.sensor.forwardMatrix1": [ + "730", + "1024", + "27", + "1024", + "231", + "1024", + "290", + "1024", + "718", + "1024", + "16", + "1024", + "32", + "1024", + "-488", + "1024", + "1301", + "1024" + ], + "android.sensor.forwardMatrix2": [ + "586", + "1024", + "92", + "1024", + "309", + "1024", + "147", + "1024", + "766", + "1024", + "111", + "1024", + "-79", + "1024", + "-976", + "1024", + "1900", + "1024" + ], + "android.sensor.info.activeArraySize": [ + "0", + "0", + "1440", + "480" + ], + "android.sensor.info.colorFilterArrangement": [ + "GRBG" + ], + "android.sensor.info.lensShadingApplied": [ + "TRUE" + ], + "android.sensor.info.maxFrameDuration": [ + "200000000" + ], + "android.sensor.info.physicalSize": [ + "0.67199999", + "2.01600003" + ], + "android.sensor.info.pixelArraySize": [ + "1440", + "480" + ], + "android.sensor.info.preCorrectionActiveArraySize": [ + "0", + "0", + "1440", + "480" + ], + "android.sensor.info.timestampSource": [ + "REALTIME" + ], + "android.sensor.info.whiteLevel": [ + "1023" + ], + "android.sensor.orientation": [ + "90" + ], + "android.sensor.profileHueSatMapDimensions": [ + "0", + "0", + "0" + ], + "android.sensor.referenceIlluminant1": [ + "D55" + ], + "android.sensor.referenceIlluminant2": [ + "17" + ], + "android.shading.availableModes": [ + "0" + ], + "android.statistics.info.availableFaceDetectModes": [ + "0" + ], + "android.statistics.info.availableHotPixelMapModes": [ + "0" + ], + "android.statistics.info.availableLensShadingMapModes": [ + "0" + ], + "android.statistics.info.maxFaceCount": [ + "0" + ], + "android.sync.maxLatency": [ + "PER_FRAME_CONTROL" + ], + "android.tonemap.maxCurvePoints": [ + "0" + ] +} diff --git a/aosp/hardware/google/camera/devices/EmulatedCamera/hwl/configs/google_camera_external.json b/aosp/hardware/google/camera/devices/EmulatedCamera/hwl/configs/google_camera_external.json new file mode 100644 index 000000000..f2b429331 --- /dev/null +++ b/aosp/hardware/google/camera/devices/EmulatedCamera/hwl/configs/google_camera_external.json @@ -0,0 +1,498 @@ +{ + "android.colorCorrection.availableAberrationModes": [ + "0" + ], + "android.control.aeAvailableAntibandingModes": [ + "3" + ], + "android.control.aeAvailableModes": [ + "1" + ], + "android.control.aeAvailableTargetFpsRanges": [ + "10", + "20", + "24", + "24", + "30", + "30", + "15", + "30" + ], + "android.control.aeCompensationRange": [ + "0", + "0" + ], + "android.control.aeCompensationStep": [ + "0", + "1" + ], + "android.control.aeLockAvailable": [ + "FALSE" + ], + "android.control.afAvailableModes": [ + "1", + "0" + ], + "android.control.autoframingAvailable": [ + "FALSE" + ], + "android.control.availableEffects": [ + "0" + ], + "android.control.availableModes": [ + "0", + "1" + ], + "android.control.availableSceneModes": [ + "0" + ], + "android.control.availableVideoStabilizationModes": [ + "0" + ], + "android.control.awbAvailableModes": [ + "1" + ], + "android.control.awbLockAvailable": [ + "FALSE" + ], + "android.control.maxRegions": [ + "0", + "0", + "0" + ], + "android.control.zoomRatioRange": [ + "1.00000000", + "4.00000000" + ], + "android.edge.availableEdgeModes": [ + "0", + "1" + ], + "android.flash.info.available": [ + "FALSE" + ], + "android.hotPixel.availableHotPixelModes": [ + "0" + ], + "android.info.supportedHardwareLevel": [ + "EXTERNAL" + ], + "android.jpeg.availableThumbnailSizes": [ + "0", + "0", + "176", + "144", + "240", + "144", + "256", + "144", + "240", + "160", + "256", + "154", + "240", + "180" + ], + "android.jpeg.maxSize": [ + "3145728" + ], + "android.lens.facing": [ + "EXTERNAL" + ], + "android.lens.info.availableOpticalStabilization": [ + "0" + ], + "android.lens.info.focusDistanceCalibration": [ + "UNCALIBRATED" + ], + "android.noiseReduction.availableNoiseReductionModes": [ + "0" + ], + "android.noiseReduction.mode": [ + "OFF" + ], + "android.request.availableCapabilities": [ + "BACKWARD_COMPATIBLE" + ], + "android.request.availableCharacteristicsKeys": [ + "4", + "65554", + "65555", + "65556", + "65557", + "65558", + "65572", + "65559", + "65560", + "65574", + "65561", + "65562", + "65563", + "65573", + "65564", + "327680", + "1376256", + "458759", + "524293", + "589827", + "589831", + "655362", + "786444", + "786440", + "786438", + "786443", + "786442", + "851972", + "851978", + "851981", + "983040", + "983044", + "983046", + "983050", + "983048", + "917518", + "1048578", + "1179648", + "1179654", + "1179655", + "1179650", + "1507329", + "65582", + "589824", + "589826", + "589825", + "1245189" + ], + "android.request.availableRequestKeys": [ + "3", + "65536", + "65537", + "65538", + "65539", + "65542", + "65541", + "65543", + "65545", + "65546", + "65547", + "65549", + "65550", + "65551", + "65552", + "65553", + "262146", + "458755", + "458756", + "458757", + "458758", + "524292", + "655360", + "851968", + "917528", + "1114112", + "1114115", + "65583" + ], + "android.request.availableResultKeys": [ + "3", + "65536", + "65537", + "65538", + "65539", + "65542", + "65567", + "65541", + "65543", + "65568", + "65545", + "65546", + "65547", + "65570", + "65549", + "65550", + "65551", + "65552", + "65553", + "262146", + "262149", + "458755", + "458756", + "458757", + "458758", + "524292", + "655360", + "786441", + "851968", + "917520", + "1114112", + "1114115", + "1114128", + "1114126", + "65583" + ], + "android.request.maxNumInputStreams": [ + "0" + ], + "android.request.maxNumOutputStreams": [ + "0", + "2", + "1" + ], + "android.request.partialResultCount": [ + "1" + ], + "android.request.pipelineMaxDepth": [ + "4" + ], + "android.scaler.availableMaxDigitalZoom": [ + "4.00000000" + ], + "android.scaler.availableMinFrameDurations": [ + "33", + "320", + "240", + "33333333", + "35", + "320", + "240", + "33333333", + "34", + "320", + "240", + "33333333", + "33", + "640", + "480", + "33333333", + "35", + "640", + "480", + "33333333", + "34", + "640", + "480", + "33333333", + "33", + "1280", + "720", + "33333333", + "35", + "1280", + "720", + "33333333", + "34", + "1280", + "720", + "33333333", + "33", + "1920", + "1080", + "33333333", + "35", + "1920", + "1080", + "33333333", + "34", + "1920", + "1080", + "33333333", + "33", + "1920", + "1080", + "33333333", + "35", + "1920", + "1080", + "33333333", + "34", + "1920", + "1080", + "33333333" + ], + "android.scaler.availableStallDurations": [ + "33", + "320", + "240", + "1000000000", + "35", + "320", + "240", + "0", + "34", + "320", + "240", + "0", + "33", + "640", + "480", + "1000000000", + "35", + "640", + "480", + "0", + "34", + "640", + "480", + "0", + "33", + "1280", + "720", + "1000000000", + "35", + "1280", + "720", + "0", + "34", + "1280", + "720", + "0", + "33", + "1920", + "1080", + "1000000000", + "35", + "1920", + "1080", + "0", + "34", + "1920", + "1080", + "0", + "33", + "1920", + "1080", + "1000000000", + "35", + "1920", + "1080", + "0", + "34", + "1920", + "1080", + "0" + ], + "android.scaler.availableStreamConfigurations": [ + "33", + "320", + "240", + "OUTPUT", + "35", + "320", + "240", + "OUTPUT", + "34", + "320", + "240", + "OUTPUT", + "33", + "640", + "480", + "OUTPUT", + "35", + "640", + "480", + "OUTPUT", + "34", + "640", + "480", + "OUTPUT", + "33", + "1280", + "720", + "OUTPUT", + "35", + "1280", + "720", + "OUTPUT", + "34", + "1280", + "720", + "OUTPUT", + "33", + "1920", + "1080", + "OUTPUT", + "35", + "1920", + "1080", + "OUTPUT", + "34", + "1920", + "1080", + "OUTPUT", + "33", + "1920", + "1080", + "OUTPUT", + "35", + "1920", + "1080", + "OUTPUT", + "34", + "1920", + "1080", + "OUTPUT" + ], + "android.scaler.croppingType": [ + "CENTER_ONLY" + ], + "android.sensor.availableTestPatternModes": [ + "0", + "1" + ], + "android.sensor.info.activeArraySize": [ + "0", + "0", + "1920", + "1080" + ], + "android.sensor.info.maxFrameDuration": [ + "200000000" + ], + "android.sensor.info.pixelArraySize": [ + "1920", + "1080" + ], + "android.sensor.info.preCorrectionActiveArraySize": [ + "0", + "0", + "1920", + "1080" + ], + "android.sensor.info.timestampSource": [ + "REALTIME" + ], + "android.sensor.orientation": [ + "0" + ], + "android.shading.availableModes": [ + "0" + ], + "android.statistics.info.availableFaceDetectModes": [ + "0" + ], + "android.statistics.info.availableHotPixelMapModes": [ + "0" + ], + "android.statistics.info.availableLensShadingMapModes": [ + "0" + ], + "android.statistics.info.maxFaceCount": [ + "0" + ], + "android.sync.maxLatency": [ + "UNKNOWN" + ], + "android.lens.info.availableApertures": [ + "1.70000005" + ], + "android.lens.info.availableFocalLengths": [ + "3.25999999" + ], + "android.lens.info.availableFilterDensities": [ + "0.00000000" + ], + "android.tonemap.availableToneMapModes": [ + "1" + ] +} diff --git a/aosp/hardware/google/camera/devices/EmulatedCamera/hwl/configs/google_camera_front.json b/aosp/hardware/google/camera/devices/EmulatedCamera/hwl/configs/google_camera_front.json new file mode 100644 index 000000000..591256408 --- /dev/null +++ b/aosp/hardware/google/camera/devices/EmulatedCamera/hwl/configs/google_camera_front.json @@ -0,0 +1,4525 @@ +[ + { + "android.colorCorrection.availableAberrationModes": [ + "0", + "1", + "2" + ], + "android.control.aeAvailableAntibandingModes": [ + "0", + "1", + "2", + "3" + ], + "android.control.aeAvailableModes": [ + "0", + "1", + "2", + "3", + "4" + ], + "android.control.aeAvailableTargetFpsRanges": [ + "15", + "15", + "15", + "30", + "30", + "30" + ], + "android.control.aeCompensationRange": [ + "-24", + "24" + ], + "android.control.aeCompensationStep": [ + "1", + "6" + ], + "android.control.aeLockAvailable": [ + "TRUE" + ], + "android.control.afAvailableModes": [ + "0", + "1", + "2", + "3", + "4" + ], + "android.control.availableExtendedSceneModeMaxSizes": [ + "0", + "0", + "0", + "1", + "1920", + "1080", + "2", + "1920", + "1440" + ], + "android.control.availableExtendedSceneModeZoomRatioRanges": [ + "2.0", + "2.0", + "1.0", + "1.0" + ], + "android.control.availableEffects": [ + "0" + ], + "android.control.availableModes": [ + "0", + "1", + "2", + "4" + ], + "android.control.availableSceneModes": [ + "0", + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9", + "10", + "12", + "13", + "14", + "15", + "18" + ], + "android.control.availableSettingsOverrides": [ + "0", + "1" + ], + "android.control.availableVideoStabilizationModes": [ + "0" + ], + "android.control.awbAvailableModes": [ + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "0" + ], + "android.control.awbLockAvailable": [ + "TRUE" + ], + "android.control.autoframingAvailable": [ + "TRUE" + ], + "android.control.maxRegions": [ + "1", + "0", + "1" + ], + "android.control.postRawSensitivityBoostRange": [ + "100", + "100" + ], + "android.control.sceneModeOverrides": [ + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0" + ], + "android.control.zoomRatioRange": [ + "1.0", + "8.0" + ], + "android.distortionCorrection.availableModes": [ + "0" + ], + "android.edge.availableEdgeModes": [ + "1", + "2", + "0", + "3" + ], + "android.flash.singleStrengthMaxLevel" : [ + "10" + ], + "android.flash.singleStrengthDefaultLevel": [ + "2" + ], + "android.flash.torchStrengthDefaultLevel": [ + "5" + ], + "android.flash.torchStrengthMaxLevel" :[ + "15" + ], + "android.flash.info.available": [ + "TRUE" + ], + "android.flash.info.strengthMaximumLevel": [ + "10" + ], + "android.flash.info.strengthDefaultLevel": [ + "3" + ], + "android.hotPixel.availableHotPixelModes": [ + "0", + "1", + "2" + ], + "android.info.supportedHardwareLevel": [ + "FULL" + ], + "android.jpeg.availableThumbnailSizes": [ + "0", + "0", + "176", + "144", + "240", + "144", + "256", + "144", + "240", + "160", + "256", + "154", + "246", + "184", + "240", + "240", + "320", + "240" + ], + "android.jpeg.maxSize": [ + "3000000" + ], + "android.lens.distortion": [ + "0.08807813", + "-0.22617353", + "0.16460505", + "0.00000000", + "0.00000000" + ], + "android.lens.facing": [ + "FRONT" + ], + "android.lens.info.availableApertures": [ + "1.73000002" + ], + "android.lens.info.availableFilterDensities": [ + "0.00000000" + ], + "android.lens.info.availableFocalLengths": [ + "4.38000011" + ], + "android.lens.info.availableOpticalStabilization": [ + "0" + ], + "android.lens.info.focusDistanceCalibration": [ + "APPROXIMATE" + ], + "android.lens.info.hyperfocalDistance": [ + "0.25249681" + ], + "android.lens.info.minimumFocusDistance": [ + "10.20408154" + ], + "android.lens.info.shadingMapSize": [ + "17", + "13" + ], + "android.lens.intrinsicCalibration": [ + "3225.77416992", + "3225.77416992", + "960.50427246", + "540.46704102", + "0.00000000" + ], + "android.lens.poseReference": [ + "PRIMARY_CAMERA" + ], + "android.lens.poseRotation": [ + "0.00000000", + "0.00000000", + "0.00000000", + "1.00000000" + ], + "android.lens.poseTranslation": [ + "-0.00000000", + "-0.00000000", + "-0.00000000" + ], + "android.logicalMultiCamera.physicalIds": [ + "51", + "0", + "52", + "0" + ], + "android.logicalMultiCamera.sensorSyncType": [ + "CALIBRATED" + ], + "android.noiseReduction.availableNoiseReductionModes": [ + "0", + "1", + "2", + "3", + "4" + ], + "android.request.availableCapabilities": [ + "BACKWARD_COMPATIBLE", + "READ_SENSOR_SETTINGS", + "MANUAL_SENSOR", + "BURST_CAPTURE", + "MANUAL_POST_PROCESSING", + "LOGICAL_MULTI_CAMERA", + "PRIVATE_REPROCESSING", + "ULTRA_HIGH_RESOLUTION_SENSOR", + "YUV_REPROCESSING", + "RAW", + "REMOSAIC_REPROCESSING", + "DYNAMIC_RANGE_TEN_BIT", + "STREAM_USE_CASE", + "COLOR_SPACE_PROFILES" + ], + "android.request.availableDynamicRangeProfilesMap": [ + "2", + "2", + "0" + ], + "android.request.availableColorSpaceProfilesMap": [ + "0", + "35", + "1", + "16", + "54", + "2", + "7", + "35", + "1", + "0", + "34", + "1", + "16", + "34", + "2", + "7", + "34", + "1", + "0", + "256", + "1", + "7", + "256", + "1" + ], + "android.request.recommendedTenBitDynamicRangeProfile": [ + "2" + ], + "android.request.maxNumInputStreams": [ + "1" + ], + "android.scaler.availableInputOutputFormatsMap": [ + "34", + "2", + "33", + "35", + "35", + "2", + "33", + "35" + ], + "android.scaler.availableStreamUseCases": [ + "0", + "1", + "2", + "3", + "4", + "5", + "6", + ], + "android.scaler.availableInputOutputFormatsMapMaximumResolution" : [ + "32", + "3", + "32", + "33", + "35", + ], + "android.reprocess.maxCaptureStall": [ + "2" + ], + "android.request.availableCharacteristicsKeys": [ + "4", + "65554", + "65555", + "65556", + "65557", + "65558", + "65559", + "65560", + "65561", + "65562", + "65563", + "65564", + "65565", + "65571", + "65572", + "65573", + "65574", + "65575", + "65579", + "65580", + "65582", + "65589", + "65592", + "1638402", + "1638401", + "1638403", + "1638404", + "1769473", + "196610", + "327680", + "393217", + "458759", + "458760", + "589824", + "589825", + "589826", + "589827", + "589828", + "589829", + "589830", + "589831", + "524293", + "1703936", + "1703937", + "1703938", + "655362", + "786438", + "786440", + "786442", + "786443", + "786444", + "786445", + "786446", + "786447", + "786448", + "851972", + "851977", + "851978", + "851979", + "851976", + "851980", + "851981", + "983040", + "917526", + "917523", + "917534", + "983041", + "983042", + "983043", + "983044", + "983045", + "983046", + "983047", + "983048", + "983049", + "983050", + "917507", + "917508", + "917509", + "917510", + "917511", + "917512", + "917513", + "917514", + "917516", + "917517", + "917518", + "917519", + "917529", + "1048578", + "1179648", + "1179650", + "1179654", + "1179655", + "1179656", + "1245188", + "1245189", + "1376256", + "1507329", + "1572865", + "524300", + "524301", + "524295", + "524294", + "524298", + "851984" + ], + "android.request.availableRequestKeys": [ + "0", + "1", + "2", + "3", + "65536", + "65537", + "65538", + "65539", + "65540", + "65541", + "65542", + "65543", + "65544", + "65545", + "65546", + "65547", + "65549", + "65550", + "65551", + "65552", + "65553", + "65576", + "65581", + "65583", + "65588", + "65591", + "1769472", + "196608", + "262146", + "393216", + "458752", + "458753", + "458754", + "458755", + "458756", + "458757", + "458758", + "524288", + "524289", + "524290", + "524291", + "524292", + "655360", + "786433", + "851968", + "917504", + "917505", + "917506", + "917520", + "1048576", + "1114112", + "1114115", + "1114128", + "1114129", + "1245184", + "1245185", + "1245186", + "1245187", + "1441792", + "851985", + "917536", + "2097152" + ], + "android.request.availableResultKeys": [ + "0", + "1", + "2", + "65537", + "65539", + "65540", + "65538", + "65567", + "65543", + "65544", + "65568", + "65547", + "65570", + "65551", + "65576", + "65581", + "65583", + "65588", + "65590", + "65591", + "65593", + "196608", + "262146", + "262149", + "458752", + "458753", + "458754", + "458755", + "458756", + "458757", + "458758", + "524288", + "524289", + "524290", + "524291", + "524296", + "524297", + "524294", + "524295", + "524298", + "524301", + "524292", + "655360", + "786433", + "851968", + "917526", + "917523", + "917504", + "917505", + "917506", + "917520", + "917522", + "917525", + "1048576", + "1114112", + "1114121", + "1114124", + "1114125", + "1114126", + "1114118", + "1114119", + "1114129", + "1114130", + "1114131", + "1114132", + "1245184", + "1245185", + "1245186", + "1245187", + "1441792", + "65541", + "65542", + "65545", + "65552", + "1114123", + "1703938", + "917530", + "851985", + "917536" + ], + "android.request.maxNumOutputStreams": [ + "1", + "3", + "2" + ], + "android.scaler.availableRotateAndCropModes": [ + "0" + ], + "android.request.partialResultCount": [ + "2" + ], + "android.request.pipelineMaxDepth": [ + "8" + ], + "android.scaler.availableMaxDigitalZoom": [ + "8.00000000" + ], + "android.scaler.availableMinFrameDurations": [ + "54", + "1920", + "1440", + "33331760", + "54", + "1920", + "1080", + "33331760", + "54", + "1920", + "960", + "33331760", + "54", + "1600", + "1200", + "33331760", + "54", + "1440", + "1080", + "33331760", + "54", + "1280", + "960", + "33331760", + "54", + "1280", + "720", + "33331760", + "54", + "1024", + "768", + "33331760", + "54", + "800", + "600", + "33331760", + "54", + "720", + "480", + "33331760", + "54", + "640", + "480", + "33331760", + "54", + "640", + "360", + "33331760", + "54", + "352", + "288", + "33331760", + "54", + "320", + "240", + "33331760", + "54", + "176", + "144", + "33331760", + "32", + "1920", + "1440", + "33331760", + "34", + "1920", + "1440", + "33331760", + "35", + "1920", + "1440", + "33331760", + "33", + "1920", + "1440", + "33331760", + "34", + "1920", + "1080", + "33331760", + "35", + "1920", + "1080", + "33331760", + "33", + "1920", + "1080", + "33331760", + "34", + "1920", + "960", + "33331760", + "35", + "1920", + "960", + "33331760", + "33", + "1920", + "960", + "33331760", + "34", + "1600", + "1200", + "33331760", + "35", + "1600", + "1200", + "33331760", + "33", + "1600", + "1200", + "33331760", + "34", + "1440", + "1080", + "33331760", + "35", + "1440", + "1080", + "33331760", + "33", + "1440", + "1080", + "33331760", + "34", + "1280", + "960", + "33331760", + "35", + "1280", + "960", + "33331760", + "33", + "1280", + "960", + "33331760", + "34", + "1280", + "720", + "33331760", + "35", + "1280", + "720", + "33331760", + "33", + "1280", + "720", + "33331760", + "34", + "1024", + "768", + "33331760", + "35", + "1024", + "768", + "33331760", + "33", + "1024", + "768", + "33331760", + "34", + "800", + "600", + "33331760", + "35", + "800", + "600", + "33331760", + "33", + "800", + "600", + "33331760", + "34", + "720", + "480", + "33331760", + "35", + "720", + "480", + "33331760", + "33", + "720", + "480", + "33331760", + "34", + "640", + "480", + "33331760", + "35", + "640", + "480", + "33331760", + "33", + "640", + "480", + "33331760", + "34", + "640", + "360", + "33331760", + "35", + "640", + "360", + "33331760", + "33", + "640", + "360", + "33331760", + "34", + "352", + "288", + "33331760", + "35", + "352", + "288", + "33331760", + "33", + "352", + "288", + "33331760", + "34", + "320", + "240", + "33331760", + "35", + "320", + "240", + "33331760", + "33", + "320", + "240", + "33331760", + "34", + "176", + "144", + "33331760", + "35", + "176", + "144", + "33331760", + "33", + "176", + "144", + "33331760" + ], +"android.scaler.availableMinFrameDurationsMaximumResolution": [ + "32", + "6048", + "4024", + "33331760", + "33", + "6048", + "4024", + "33331760", + "35", + "6048", + "4024", + "33331760" + ], + "android.scaler.availableStallDurations": [ + "32", + "1920", + "1440", + "17971200", + "33", + "1920", + "1440", + "17971200", + "33", + "1920", + "1080", + "13478400", + "33", + "1920", + "960", + "11980800", + "33", + "1600", + "1200", + "12480000", + "33", + "1440", + "1080", + "10108800", + "33", + "1280", + "960", + "7987200", + "33", + "1280", + "720", + "5990400", + "33", + "1024", + "768", + "5111808", + "33", + "800", + "600", + "3120000", + "33", + "720", + "480", + "2246400", + "33", + "640", + "480", + "1996800", + "33", + "640", + "360", + "1497600", + "33", + "352", + "288", + "658944", + "33", + "320", + "240", + "499200", + "33", + "176", + "144", + "164736" + ], + "android.scaler.availableStallDurationsMaximumResolution": [ + "32", + "6048", + "4024", + "287539200", + "33", + "6048", + "4024", + "287539200" + ], + "android.scaler.availableStreamConfigurations": [ + "54", + "1920", + "1440", + "OUTPUT", + "54", + "1920", + "1080", + "OUTPUT", + "54", + "1920", + "960", + "OUTPUT", + "54", + "1600", + "1200", + "OUTPUT", + "54", + "1440", + "1080", + "OUTPUT", + "54", + "1280", + "960", + "OUTPUT", + "54", + "1280", + "720", + "OUTPUT", + "54", + "1024", + "768", + "OUTPUT", + "54", + "800", + "600", + "OUTPUT", + "54", + "720", + "480", + "OUTPUT", + "54", + "640", + "480", + "OUTPUT", + "54", + "640", + "360", + "OUTPUT", + "54", + "352", + "288", + "OUTPUT", + "54", + "320", + "240", + "OUTPUT", + "54", + "176", + "144", + "OUTPUT", + "32", + "1920", + "1440", + "OUTPUT", + "35", + "1920", + "1440", + "INPUT", + "35", + "1920", + "1440", + "OUTPUT", + "35", + "1920", + "1080", + "OUTPUT", + "35", + "1920", + "960", + "OUTPUT", + "35", + "1600", + "1200", + "OUTPUT", + "35", + "1440", + "1080", + "OUTPUT", + "35", + "1280", + "960", + "OUTPUT", + "35", + "1280", + "720", + "OUTPUT", + "35", + "1024", + "768", + "OUTPUT", + "35", + "800", + "600", + "OUTPUT", + "35", + "720", + "480", + "OUTPUT", + "35", + "640", + "480", + "OUTPUT", + "35", + "640", + "360", + "OUTPUT", + "35", + "352", + "288", + "OUTPUT", + "35", + "320", + "240", + "OUTPUT", + "35", + "176", + "144", + "OUTPUT", + "34", + "1920", + "1440", + "INPUT", + "34", + "1920", + "1440", + "OUTPUT", + "34", + "1920", + "1080", + "OUTPUT", + "34", + "1920", + "960", + "OUTPUT", + "34", + "1600", + "1200", + "OUTPUT", + "34", + "1440", + "1080", + "OUTPUT", + "34", + "1280", + "960", + "OUTPUT", + "34", + "1280", + "720", + "OUTPUT", + "34", + "1024", + "768", + "OUTPUT", + "34", + "800", + "600", + "OUTPUT", + "34", + "720", + "480", + "OUTPUT", + "34", + "640", + "480", + "OUTPUT", + "34", + "640", + "360", + "OUTPUT", + "34", + "352", + "288", + "OUTPUT", + "34", + "320", + "240", + "OUTPUT", + "34", + "176", + "144", + "OUTPUT", + "33", + "1920", + "1440", + "OUTPUT", + "33", + "1920", + "1080", + "OUTPUT", + "33", + "1920", + "960", + "OUTPUT", + "33", + "1600", + "1200", + "OUTPUT", + "33", + "1440", + "1080", + "OUTPUT", + "33", + "1280", + "960", + "OUTPUT", + "33", + "1280", + "720", + "OUTPUT", + "33", + "1024", + "768", + "OUTPUT", + "33", + "800", + "600", + "OUTPUT", + "33", + "720", + "480", + "OUTPUT", + "33", + "640", + "480", + "OUTPUT", + "33", + "640", + "360", + "OUTPUT", + "33", + "352", + "288", + "OUTPUT", + "33", + "320", + "240", + "OUTPUT" + ], + "android.scaler.availableStreamConfigurationsMaximumResolution": [ + "32", + "6048", + "4024", + "INPUT", + "32", + "6048", + "4024", + "OUTPUT", + "33", + "6048", + "4024", + "OUTPUT", + "35", + "6048", + "4024", + "OUTPUT" + ], + "android.scaler.croppingType": [ + "CENTER_ONLY" + ], + "android.scaler.multiResolutionStreamSupported": [ + "TRUE" + ], + "android.sensor.availableTestPatternModes": [ + "0", + "5" + ], + "android.sensor.blackLevelPattern": [ + "64", + "64", + "64", + "64" + ], + "android.sensor.calibrationTransform1": [ + "58", + "128", + "0", + "128", + "0", + "128", + "0", + "128", + "128", + "128", + "0", + "128", + "0", + "128", + "0", + "128", + "85", + "128" + ], + "android.sensor.calibrationTransform2": [ + "84", + "128", + "0", + "128", + "0", + "128", + "0", + "128", + "128", + "128", + "0", + "128", + "0", + "128", + "0", + "128", + "45", + "128" + ], + "android.sensor.colorTransform1": [ + "221", + "128", + "-105", + "128", + "-34", + "128", + "-124", + "128", + "240", + "128", + "5", + "128", + "5", + "128", + "-19", + "128", + "99", + "128" + ], + "android.sensor.colorTransform2": [ + "360", + "128", + "-249", + "128", + "-63", + "128", + "-137", + "128", + "279", + "128", + "-1", + "128", + "7", + "128", + "-18", + "128", + "159", + "128" + ], + "android.sensor.forwardMatrix1": [ + "56", + "128", + "49", + "128", + "18", + "128", + "28", + "128", + "92", + "128", + "8", + "128", + "2", + "128", + "12", + "128", + "91", + "128" + ], + "android.sensor.forwardMatrix2": [ + "56", + "128", + "49", + "128", + "18", + "128", + "28", + "128", + "92", + "128", + "8", + "128", + "2", + "128", + "12", + "128", + "91", + "128" + ], + "android.sensor.info.activeArraySize": [ + "0", + "0", + "1920", + "1440" + ], + "android.sensor.info.activeArraySizeMaximumResolution": [ + "0", + "0", + "6048", + "4024" + ], + "android.sensor.info.colorFilterArrangement": [ + "RGGB" + ], + "android.sensor.info.exposureTimeRange": [ + "13611", + "10319000832" + ], + "android.sensor.info.lensShadingApplied": [ + "TRUE" + ], + "android.sensor.info.maxFrameDuration": [ + "1319055264" + ], + "android.sensor.info.physicalSize": [ + "5.64480019", + "4.23360014" + ], + "android.sensor.info.pixelArraySize": [ + "1920", + "1440" + ], + "android.sensor.info.preCorrectionActiveArraySize": [ + "0", + "0", + "1920", + "1440" + ], + "android.sensor.info.pixelArraySizeMaximumResolution": [ + "6048", + "4024" + ], + "android.sensor.info.binningFactor": [ + "2", + "2" + ], + "android.sensor.info.preCorrectionActiveArraySizeMaximumResolution": [ + "0", + "0", + "6048", + "4024" + ], + "android.sensor.info.sensitivityRange": [ + "100", + "1000" + ], + "android.sensor.info.timestampSource": [ + "REALTIME" + ], + "android.sensor.info.whiteLevel": [ + "1023" + ], + "android.sensor.maxAnalogSensitivity": [ + "444" + ], + "android.sensor.orientation": [ + "270" + ], + "android.sensor.profileHueSatMapDimensions": [ + "0", + "0", + "0" + ], + "android.sensor.referenceIlluminant1": [ + "D65" + ], + "android.sensor.referenceIlluminant2": [ + "17" + ], + "android.shading.availableModes": [ + "0", + "1", + "2" + ], + "android.statistics.info.availableFaceDetectModes": [ + "0", + "1", + "2" + ], + "android.statistics.info.availableHotPixelMapModes": [ + "0" + ], + "android.statistics.info.availableLensShadingMapModes": [ + "0", + "1" + ], + "android.statistics.info.maxFaceCount": [ + "10" + ], + "android.info.supportedBufferManagementVersion" : [ + "SESSION_CONFIGURABLE" + ], + "android.sync.maxLatency": [ + "PER_FRAME_CONTROL" + ], + "android.tonemap.availableToneMapModes": [ + "0", + "1", + "2" + ], + "android.tonemap.maxCurvePoints": [ + "64" + ] + }, + { + "android.colorCorrection.availableAberrationModes": [ + "0", + "1", + "2" + ], + "android.control.aeAvailableAntibandingModes": [ + "0", + "1", + "2", + "3" + ], + "android.control.aeAvailableModes": [ + "0", + "1", + "2", + "3", + "4" + ], + "android.control.aeAvailableTargetFpsRanges": [ + "15", + "15", + "15", + "30", + "30", + "30" + ], + "android.control.aeCompensationRange": [ + "-24", + "24" + ], + "android.control.aeCompensationStep": [ + "1", + "6" + ], + "android.control.aeLockAvailable": [ + "TRUE" + ], + "android.control.afAvailableModes": [ + "0", + "1", + "2", + "3", + "4" + ], + "android.control.availableExtendedSceneModeMaxSizes": [ + "0", + "0", + "0", + "1", + "1920", + "1080", + "2", + "1920", + "1440" + ], + "android.control.availableExtendedSceneModeZoomRatioRanges": [ + "2.0", + "2.0", + "1.0", + "1.0" + ], + "android.control.availableEffects": [ + "0" + ], + "android.control.availableModes": [ + "0", + "1", + "2", + "4" + ], + "android.control.availableSceneModes": [ + "0", + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9", + "10", + "12", + "13", + "14", + "15", + "18" + ], + "android.control.availableSettingsOverrides": [ + "0", + "1" + ], + "android.control.availableVideoStabilizationModes": [ + "0" + ], + "android.control.awbAvailableModes": [ + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "0" + ], + "android.control.awbLockAvailable": [ + "TRUE" + ], + "android.control.maxRegions": [ + "1", + "0", + "1" + ], + "android.control.postRawSensitivityBoostRange": [ + "100", + "100" + ], + "android.control.sceneModeOverrides": [ + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0" + ], + "android.control.zoomRatioRange": [ + "1.0", + "8.0" + ], + "android.distortionCorrection.availableModes": [ + "0" + ], + "android.edge.availableEdgeModes": [ + "1", + "2", + "0", + "3" + ], + "android.flash.singleStrengthMaxLevel" : [ + "10" + ], + "android.flash.singleStrengthDefaultLevel": [ + "2" + ], + "android.flash.torchStrengthDefaultLevel": [ + "5" + ], + "android.flash.torchStrengthMaxLevel" :[ + "15" + ], + "android.flash.info.available": [ + "TRUE" + ], + "android.hotPixel.availableHotPixelModes": [ + "0", + "1", + "2" + ], + "android.info.supportedHardwareLevel": [ + "FULL" + ], + "android.jpeg.availableThumbnailSizes": [ + "0", + "0", + "176", + "144", + "240", + "144", + "256", + "144", + "240", + "160", + "256", + "154", + "246", + "184", + "240", + "240", + "320", + "240" + ], + "android.jpeg.maxSize": [ + "3000000" + ], + "android.lens.distortion": [ + "0.08807813", + "-0.22617353", + "0.16460505", + "0.00000000", + "0.00000000" + ], + "android.lens.facing": [ + "FRONT" + ], + "android.lens.info.availableApertures": [ + "1.73000002" + ], + "android.lens.info.availableFilterDensities": [ + "0.00000000" + ], + "android.lens.info.availableFocalLengths": [ + "4.38000011" + ], + "android.lens.info.availableOpticalStabilization": [ + "0", + "1" + ], + "android.lens.info.focusDistanceCalibration": [ + "APPROXIMATE" + ], + "android.lens.info.hyperfocalDistance": [ + "0.25249681" + ], + "android.lens.info.minimumFocusDistance": [ + "10.20408154" + ], + "android.lens.info.shadingMapSize": [ + "17", + "13" + ], + "android.lens.intrinsicCalibration": [ + "3225.77416992", + "3225.77416992", + "960.50427246", + "540.46704102", + "0.00000000" + ], + "android.lens.poseReference": [ + "PRIMARY_CAMERA" + ], + "android.lens.poseRotation": [ + "0.00000000", + "0.00000000", + "0.00000000", + "1.00000000" + ], + "android.lens.poseTranslation": [ + "-0.00000000", + "-0.00000000", + "-0.00000000" + ], + "android.noiseReduction.availableNoiseReductionModes": [ + "0", + "1", + "2", + "3", + "4" + ], + "android.request.availableCapabilities": [ + "BACKWARD_COMPATIBLE", + "READ_SENSOR_SETTINGS", + "MANUAL_SENSOR", + "BURST_CAPTURE", + "MANUAL_POST_PROCESSING", + "PRIVATE_REPROCESSING", + "ULTRA_HIGH_RESOLUTION_SENSOR", + "YUV_REPROCESSING", + "RAW", + "REMOSAIC_REPROCESSING", + "DYNAMIC_RANGE_TEN_BIT" + ], + "android.request.availableDynamicRangeProfilesMap": [ + "2", + "2", + "0" + ], + "android.request.recommendedTenBitDynamicRangeProfile": [ + "2" + ], + "android.request.maxNumInputStreams": [ + "1" + ], + "android.scaler.availableInputOutputFormatsMap": [ + "34", + "2", + "33", + "35", + "35", + "2", + "33", + "35" + ], + "android.scaler.availableInputOutputFormatsMapMaximumResolution" : [ + "32", + "1", + "32" + ], + "android.reprocess.maxCaptureStall": [ + "2" + ], + "android.request.availableCharacteristicsKeys": [ + "4", + "65554", + "65555", + "65556", + "65557", + "65558", + "65559", + "65560", + "65561", + "65562", + "65563", + "65564", + "65565", + "65571", + "65572", + "65573", + "65574", + "65575", + "65579", + "65580", + "65582", + "65589", + "65592", + "1638402", + "1638401", + "1638403", + "1638404", + "1769473", + "196610", + "327680", + "393217", + "458759", + "458760", + "589824", + "589825", + "589826", + "589827", + "589828", + "589829", + "589830", + "589831", + "524293", + "1703936", + "1703937", + "1703938", + "655362", + "786438", + "786440", + "786442", + "786443", + "786444", + "786445", + "786446", + "786447", + "786448", + "851972", + "851977", + "851978", + "851979", + "851976", + "851980", + "851981", + "983040", + "917526", + "917523", + "917534", + "983041", + "983042", + "983043", + "983044", + "983045", + "983046", + "983047", + "983048", + "983049", + "983050", + "917507", + "917508", + "917509", + "917510", + "917511", + "917512", + "917513", + "917514", + "917516", + "917517", + "917518", + "917519", + "917529", + "1048578", + "1179648", + "1179650", + "1179654", + "1179655", + "1179656", + "1245188", + "1245189", + "1376256", + "1507329", + "1572865", + "524300", + "524301", + "524295", + "524294", + "524298", + "851984", + "851986" + ], + "android.request.availableRequestKeys": [ + "0", + "1", + "2", + "3", + "65536", + "65537", + "65538", + "65539", + "65540", + "65541", + "65542", + "65543", + "65544", + "65545", + "65546", + "65547", + "65549", + "65550", + "65551", + "65552", + "65553", + "65576", + "65581", + "65583", + "65588", + "65591", + "1769472", + "196608", + "262146", + "393216", + "458752", + "458753", + "458754", + "458755", + "458756", + "458757", + "458758", + "524288", + "524289", + "524290", + "524291", + "524292", + "655360", + "786433", + "851968", + "917504", + "917505", + "917506", + "917520", + "1048576", + "1114112", + "1114115", + "1114128", + "1114129", + "1245184", + "1245185", + "1245186", + "1245187", + "1441792", + "851985", + "917536" + ], + "android.request.availableResultKeys": [ + "0", + "1", + "2", + "65537", + "65539", + "65540", + "65567", + "65543", + "65544", + "65568", + "65547", + "65538", + "65570", + "65551", + "65576", + "65581", + "65583", + "65588", + "65590", + "65591", + "65593", + "196608", + "262146", + "262149", + "458752", + "458753", + "458754", + "458755", + "458756", + "458757", + "458758", + "524288", + "524289", + "524290", + "524291", + "524296", + "524297", + "524294", + "524295", + "524298", + "524301", + "524292", + "655360", + "786433", + "851968", + "917526", + "917523", + "917504", + "917505", + "917506", + "917520", + "917522", + "917525", + "1048576", + "1114112", + "1114121", + "1114124", + "1114125", + "1114126", + "1114118", + "1114119", + "1114129", + "1114130", + "1114131", + "1114132", + "1245184", + "1245185", + "1245186", + "1245187", + "1441792", + "65541", + "65542", + "65545", + "65552", + "1114123", + "917530", + "851985", + "917536" + ], + "android.request.maxNumOutputStreams": [ + "1", + "3", + "2" + ], + "android.scaler.availableRotateAndCropModes": [ + "0" + ], + "android.request.partialResultCount": [ + "2" + ], + "android.request.pipelineMaxDepth": [ + "8" + ], + "android.scaler.availableMaxDigitalZoom": [ + "8.00000000" + ], + "android.scaler.availableMinFrameDurations": [ + "54", + "1920", + "1440", + "33331760", + "54", + "1920", + "1080", + "33331760", + "54", + "1920", + "960", + "33331760", + "54", + "1600", + "1200", + "33331760", + "54", + "1440", + "1080", + "33331760", + "54", + "1280", + "960", + "33331760", + "54", + "1280", + "720", + "33331760", + "54", + "1024", + "768", + "33331760", + "54", + "800", + "600", + "33331760", + "54", + "720", + "480", + "33331760", + "54", + "640", + "480", + "33331760", + "54", + "640", + "360", + "33331760", + "54", + "352", + "288", + "33331760", + "54", + "320", + "240", + "33331760", + "54", + "176", + "144", + "33331760", + "32", + "1920", + "1440", + "33331760", + "34", + "1920", + "1440", + "33331760", + "35", + "1920", + "1440", + "33331760", + "33", + "1920", + "1440", + "33331760", + "34", + "1920", + "1080", + "33331760", + "35", + "1920", + "1080", + "33331760", + "33", + "1920", + "1080", + "33331760", + "34", + "1920", + "960", + "33331760", + "35", + "1920", + "960", + "33331760", + "33", + "1920", + "960", + "33331760", + "34", + "1600", + "1200", + "33331760", + "35", + "1600", + "1200", + "33331760", + "33", + "1600", + "1200", + "33331760", + "34", + "1440", + "1080", + "33331760", + "35", + "1440", + "1080", + "33331760", + "33", + "1440", + "1080", + "33331760", + "34", + "1280", + "960", + "33331760", + "35", + "1280", + "960", + "33331760", + "33", + "1280", + "960", + "33331760", + "34", + "1280", + "720", + "33331760", + "35", + "1280", + "720", + "33331760", + "33", + "1280", + "720", + "33331760", + "34", + "1024", + "768", + "33331760", + "35", + "1024", + "768", + "33331760", + "33", + "1024", + "768", + "33331760", + "34", + "800", + "600", + "33331760", + "35", + "800", + "600", + "33331760", + "33", + "800", + "600", + "33331760", + "34", + "720", + "480", + "33331760", + "35", + "720", + "480", + "33331760", + "33", + "720", + "480", + "33331760", + "34", + "640", + "480", + "33331760", + "35", + "640", + "480", + "33331760", + "33", + "640", + "480", + "33331760", + "34", + "640", + "360", + "33331760", + "35", + "640", + "360", + "33331760", + "33", + "640", + "360", + "33331760", + "34", + "352", + "288", + "33331760", + "35", + "352", + "288", + "33331760", + "33", + "352", + "288", + "33331760", + "34", + "320", + "240", + "33331760", + "35", + "320", + "240", + "33331760", + "33", + "320", + "240", + "33331760", + "34", + "176", + "144", + "33331760", + "35", + "176", + "144", + "33331760", + "33", + "176", + "144", + "33331760" + ], + "android.scaler.availableMinFrameDurationsMaximumResolution": [ + "32", + "6048", + "4024", + "33331760", + "33", + "6048", + "4024", + "33331760", + "35", + "6048", + "4024", + "33331760" + ], + "android.scaler.availableStallDurations": [ + "32", + "1920", + "1440", + "17971200", + "33", + "1920", + "1440", + "17971200", + "33", + "1920", + "1080", + "13478400", + "33", + "1920", + "960", + "11980800", + "33", + "1600", + "1200", + "12480000", + "33", + "1440", + "1080", + "10108800", + "33", + "1280", + "960", + "7987200", + "33", + "1280", + "720", + "5990400", + "33", + "1024", + "768", + "5111808", + "33", + "800", + "600", + "3120000", + "33", + "720", + "480", + "2246400", + "33", + "640", + "480", + "1996800", + "33", + "640", + "360", + "1497600", + "33", + "352", + "288", + "658944", + "33", + "320", + "240", + "499200", + "33", + "176", + "144", + "164736" + ], + "android.scaler.availableStallDurationsMaximumResolution": [ + "32", + "6048", + "4024", + "287539200", + "33", + "6048", + "4024", + "287539200" + ], + "android.scaler.availableStreamConfigurations": [ + "54", + "1920", + "1440", + "OUTPUT", + "54", + "1920", + "1080", + "OUTPUT", + "54", + "1920", + "960", + "OUTPUT", + "54", + "1600", + "1200", + "OUTPUT", + "54", + "1440", + "1080", + "OUTPUT", + "54", + "1280", + "960", + "OUTPUT", + "54", + "1280", + "720", + "OUTPUT", + "54", + "1024", + "768", + "OUTPUT", + "54", + "800", + "600", + "OUTPUT", + "54", + "720", + "480", + "OUTPUT", + "54", + "640", + "480", + "OUTPUT", + "54", + "640", + "360", + "OUTPUT", + "54", + "352", + "288", + "OUTPUT", + "54", + "320", + "240", + "OUTPUT", + "54", + "176", + "144", + "OUTPUT", + "32", + "1920", + "1440", + "OUTPUT", + "35", + "1920", + "1440", + "INPUT", + "34", + "1920", + "1440", + "INPUT", + "34", + "1920", + "1440", + "OUTPUT", + "35", + "1920", + "1440", + "OUTPUT", + "33", + "1920", + "1440", + "OUTPUT", + "34", + "1920", + "1080", + "OUTPUT", + "35", + "1920", + "1080", + "OUTPUT", + "33", + "1920", + "1080", + "OUTPUT", + "34", + "1920", + "960", + "OUTPUT", + "35", + "1920", + "960", + "OUTPUT", + "33", + "1920", + "960", + "OUTPUT", + "34", + "1600", + "1200", + "OUTPUT", + "35", + "1600", + "1200", + "OUTPUT", + "33", + "1600", + "1200", + "OUTPUT", + "34", + "1440", + "1080", + "OUTPUT", + "35", + "1440", + "1080", + "OUTPUT", + "33", + "1440", + "1080", + "OUTPUT", + "34", + "1280", + "960", + "OUTPUT", + "35", + "1280", + "960", + "OUTPUT", + "33", + "1280", + "960", + "OUTPUT", + "34", + "1280", + "720", + "OUTPUT", + "35", + "1280", + "720", + "OUTPUT", + "33", + "1280", + "720", + "OUTPUT", + "34", + "1024", + "768", + "OUTPUT", + "35", + "1024", + "768", + "OUTPUT", + "33", + "1024", + "768", + "OUTPUT", + "34", + "800", + "600", + "OUTPUT", + "35", + "800", + "600", + "OUTPUT", + "33", + "800", + "600", + "OUTPUT", + "34", + "720", + "480", + "OUTPUT", + "35", + "720", + "480", + "OUTPUT", + "33", + "720", + "480", + "OUTPUT", + "34", + "640", + "480", + "OUTPUT", + "35", + "640", + "480", + "OUTPUT", + "33", + "640", + "480", + "OUTPUT", + "34", + "640", + "360", + "OUTPUT", + "35", + "640", + "360", + "OUTPUT", + "33", + "640", + "360", + "OUTPUT", + "34", + "352", + "288", + "OUTPUT", + "35", + "352", + "288", + "OUTPUT", + "33", + "352", + "288", + "OUTPUT", + "34", + "320", + "240", + "OUTPUT", + "35", + "320", + "240", + "OUTPUT", + "33", + "320", + "240", + "OUTPUT", + "34", + "176", + "144", + "OUTPUT", + "35", + "176", + "144", + "OUTPUT", + "33", + "176", + "144", + "OUTPUT" + ], + "android.scaler.availableStreamConfigurationsMaximumResolution": [ + "32", + "6048", + "4024", + "INPUT", + "32", + "6048", + "4024", + "OUTPUT", + "33", + "6048", + "4024", + "OUTPUT", + "35", + "6048", + "4024", + "OUTPUT" + ], + "android.scaler.croppingType": [ + "CENTER_ONLY" + ], + "android.scaler.physicalCameraMultiResolutionStreamConfigurations": [ + "34", + "1920", + "1440", + "INPUT", + "35", + "1920", + "1440", + "INPUT", + "33", + "1920", + "1440", + "OUTPUT", + "34", + "1920", + "1440", + "OUTPUT", + "35", + "1920", + "1440", + "OUTPUT" + ], + "android.sensor.availableTestPatternModes": [ + "0", + "5" + ], + "android.sensor.blackLevelPattern": [ + "64", + "64", + "64", + "64" + ], + "android.sensor.calibrationTransform1": [ + "58", + "128", + "0", + "128", + "0", + "128", + "0", + "128", + "128", + "128", + "0", + "128", + "0", + "128", + "0", + "128", + "85", + "128" + ], + "android.sensor.calibrationTransform2": [ + "84", + "128", + "0", + "128", + "0", + "128", + "0", + "128", + "128", + "128", + "0", + "128", + "0", + "128", + "0", + "128", + "45", + "128" + ], + "android.sensor.colorTransform1": [ + "221", + "128", + "-105", + "128", + "-34", + "128", + "-124", + "128", + "240", + "128", + "5", + "128", + "5", + "128", + "-19", + "128", + "99", + "128" + ], + "android.sensor.colorTransform2": [ + "360", + "128", + "-249", + "128", + "-63", + "128", + "-137", + "128", + "279", + "128", + "-1", + "128", + "7", + "128", + "-18", + "128", + "159", + "128" + ], + "android.sensor.forwardMatrix1": [ + "56", + "128", + "49", + "128", + "18", + "128", + "28", + "128", + "92", + "128", + "8", + "128", + "2", + "128", + "12", + "128", + "91", + "128" + ], + "android.sensor.forwardMatrix2": [ + "56", + "128", + "49", + "128", + "18", + "128", + "28", + "128", + "92", + "128", + "8", + "128", + "2", + "128", + "12", + "128", + "91", + "128" + ], + "android.sensor.info.activeArraySize": [ + "0", + "0", + "1920", + "1440" + ], + "android.sensor.info.activeArraySizeMaximumResolution": [ + "0", + "0", + "6048", + "4024" + ], + "android.sensor.info.colorFilterArrangement": [ + "RGGB" + ], + "android.sensor.info.exposureTimeRange": [ + "13611", + "10319000832" + ], + "android.sensor.info.lensShadingApplied": [ + "TRUE" + ], + "android.sensor.info.maxFrameDuration": [ + "1319055264" + ], + "android.sensor.info.physicalSize": [ + "5.64480019", + "4.23360014" + ], + "android.sensor.info.pixelArraySize": [ + "1920", + "1440" + ], + "android.sensor.info.preCorrectionActiveArraySize": [ + "0", + "0", + "1920", + "1440" + ], + "android.sensor.info.pixelArraySizeMaximumResolution": [ + "6048", + "4024" + ], + "android.sensor.info.preCorrectionActiveArraySizeMaximumResolution": [ + "0", + "0", + "6048", + "4024" + ], + "android.sensor.info.binningFactor": [ + "2", + "2" + ], + "android.sensor.info.sensitivityRange": [ + "100", + "1000" + ], + "android.sensor.info.timestampSource": [ + "REALTIME" + ], + "android.sensor.info.whiteLevel": [ + "1023" + ], + "android.sensor.maxAnalogSensitivity": [ + "444" + ], + "android.sensor.orientation": [ + "270" + ], + "android.sensor.profileHueSatMapDimensions": [ + "0", + "0", + "0" + ], + "android.sensor.referenceIlluminant1": [ + "D65" + ], + "android.sensor.referenceIlluminant2": [ + "17" + ], + "android.shading.availableModes": [ + "0", + "1", + "2" + ], + "android.statistics.info.availableFaceDetectModes": [ + "0", + "1", + "2" + ], + "android.statistics.info.availableHotPixelMapModes": [ + "0" + ], + "android.statistics.info.availableLensShadingMapModes": [ + "0", + "1" + ], + "android.statistics.info.maxFaceCount": [ + "10" + ], + "android.info.supportedBufferManagementVersion" : [ + "SESSION_CONFIGURABLE" + ], + "android.sync.maxLatency": [ + "PER_FRAME_CONTROL" + ], + "android.tonemap.availableToneMapModes": [ + "0", + "1", + "2" + ], + "android.tonemap.maxCurvePoints": [ + "64" + ] + }, + { + "android.colorCorrection.availableAberrationModes": [ + "0", + "1", + "2" + ], + "android.control.aeAvailableAntibandingModes": [ + "0", + "1", + "2", + "3" + ], + "android.control.aeAvailableModes": [ + "0", + "1", + "2", + "3", + "4" + ], + "android.control.aeAvailableTargetFpsRanges": [ + "15", + "15", + "15", + "30", + "30", + "30" + ], + "android.control.aeCompensationRange": [ + "-24", + "24" + ], + "android.control.aeCompensationStep": [ + "1", + "6" + ], + "android.control.aeLockAvailable": [ + "TRUE" + ], + "android.control.afAvailableModes": [ + "0", + "1", + "2", + "3", + "4" + ], + "android.control.availableExtendedSceneModeMaxSizes": [ + "0", + "0", + "0", + "1", + "1920", + "1080", + "2", + "1920", + "1440" + ], + "android.control.availableExtendedSceneModeZoomRatioRanges": [ + "2.0", + "2.0", + "1.0", + "1.0" + ], + "android.control.availableEffects": [ + "0" + ], + "android.control.availableModes": [ + "0", + "1", + "2", + "4" + ], + "android.control.availableSceneModes": [ + "0", + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9", + "10", + "12", + "13", + "14", + "15", + "18" + ], + "android.control.availableSettingsOverrides": [ + "0", + "1" + ], + "android.control.availableVideoStabilizationModes": [ + "0" + ], + "android.control.awbAvailableModes": [ + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "0" + ], + "android.control.awbLockAvailable": [ + "TRUE" + ], + "android.control.maxRegions": [ + "1", + "0", + "1" + ], + "android.control.postRawSensitivityBoostRange": [ + "100", + "100" + ], + "android.control.sceneModeOverrides": [ + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0" + ], + "android.control.zoomRatioRange": [ + "1.0", + "8.0" + ], + "android.distortionCorrection.availableModes": [ + "0" + ], + "android.edge.availableEdgeModes": [ + "1", + "2", + "0", + "3" + ], + "android.flash.singleStrengthMaxLevel" : [ + "10" + ], + "android.flash.singleStrengthDefaultLevel": [ + "2" + ], + "android.flash.torchStrengthDefaultLevel": [ + "5" + ], + "android.flash.torchStrengthMaxLevel" :[ + "15" + ], + "android.flash.info.available": [ + "TRUE" + ], + "android.hotPixel.availableHotPixelModes": [ + "0", + "1", + "2" + ], + "android.info.supportedHardwareLevel": [ + "FULL" + ], + "android.jpeg.availableThumbnailSizes": [ + "0", + "0", + "176", + "144", + "240", + "144", + "256", + "144", + "240", + "160", + "256", + "154", + "246", + "184", + "240", + "240", + "320", + "240" + ], + "android.jpeg.maxSize": [ + "3000000" + ], + "android.lens.distortion": [ + "0.27679554", + "-1.56508207", + "3.02522445", + "0.00000000", + "0.00000000" + ], + "android.lens.facing": [ + "FRONT" + ], + "android.lens.info.availableApertures": [ + "2.40000010" + ], + "android.lens.info.availableFilterDensities": [ + "0.00000000" + ], + "android.lens.info.availableFocalLengths": [ + "5.84000015" + ], + "android.lens.info.availableOpticalStabilization": [ + "0", + "1" + ], + "android.lens.info.focusDistanceCalibration": [ + "APPROXIMATE" + ], + "android.lens.info.hyperfocalDistance": [ + "0.14073935" + ], + "android.lens.info.minimumFocusDistance": [ + "10.10101032" + ], + "android.lens.info.shadingMapSize": [ + "17", + "13" + ], + "android.lens.intrinsicCalibration": [ + "5941.24902344", + "5941.24902344", + "960.14233398", + "540.47375488", + "0.00000000" + ], + "android.lens.poseReference": [ + "PRIMARY_CAMERA" + ], + "android.lens.poseRotation": [ + "-0.00032215", + "0.00118852", + "-0.00006529", + "0.99999928" + ], + "android.lens.poseTranslation": [ + "0.00034755", + "0.01267981", + "-0.00284645" + ], + "android.noiseReduction.availableNoiseReductionModes": [ + "0", + "1", + "2", + "3", + "4" + ], + "android.request.availableCapabilities": [ + "BACKWARD_COMPATIBLE", + "READ_SENSOR_SETTINGS", + "MANUAL_SENSOR", + "BURST_CAPTURE", + "MANUAL_POST_PROCESSING", + "PRIVATE_REPROCESSING", + "ULTRA_HIGH_RESOLUTION_SENSOR", + "YUV_REPROCESSING", + "RAW", + "REMOSAIC_REPROCESSING", + "DYNAMIC_RANGE_TEN_BIT" + ], + "android.request.availableDynamicRangeProfilesMap": [ + "2", + "2", + "0" + ], + "android.request.recommendedTenBitDynamicRangeProfile": [ + "2" + ], + "android.request.maxNumInputStreams": [ + "1" + ], + "android.scaler.availableInputOutputFormatsMap": [ + "34", + "2", + "33", + "35", + "35", + "2", + "33", + "35" + ], + "android.scaler.availableInputOutputFormatsMapMaximumResolution" : [ + "32", + "1", + "32" + ], + "android.reprocess.maxCaptureStall": [ + "2" + ], + "android.request.availableCharacteristicsKeys": [ + "4", + "65554", + "65555", + "65556", + "65557", + "65558", + "65559", + "65560", + "65561", + "65562", + "65563", + "65564", + "65565", + "65571", + "65572", + "65573", + "65574", + "65575", + "65579", + "65580", + "65582", + "65589", + "65592", + "1638402", + "1638401", + "1638403", + "1638404", + "1769473", + "196610", + "327680", + "393217", + "458759", + "458760", + "589824", + "589825", + "589826", + "589827", + "589828", + "589829", + "589830", + "589831", + "524293", + "1703936", + "1703937", + "1703938", + "655362", + "786438", + "786440", + "786442", + "786443", + "786444", + "786445", + "786446", + "786447", + "786448", + "851972", + "851977", + "851978", + "851979", + "851976", + "851980", + "851981", + "983040", + "917526", + "917523", + "917534", + "983041", + "983042", + "983043", + "983044", + "983045", + "983046", + "983047", + "983048", + "983049", + "983050", + "917507", + "917508", + "917509", + "917510", + "917511", + "917512", + "917513", + "917514", + "917516", + "917517", + "917518", + "917519", + "917529", + "1048578", + "1179648", + "1179650", + "1179654", + "1179655", + "1179656", + "1245188", + "1245189", + "1376256", + "1507329", + "1572865", + "524300", + "524301", + "524295", + "524294", + "524298", + "851984", + "851986" + ], + "android.request.availableRequestKeys": [ + "0", + "1", + "2", + "3", + "65536", + "65537", + "65538", + "65539", + "65540", + "65541", + "65542", + "65543", + "65544", + "65545", + "65546", + "65547", + "65549", + "65550", + "65551", + "65552", + "65553", + "65576", + "65581", + "65583", + "65588", + "65591", + "1769472", + "196608", + "262146", + "393216", + "458752", + "458753", + "458754", + "458755", + "458756", + "458757", + "458758", + "524288", + "524289", + "524290", + "524291", + "524292", + "655360", + "786433", + "851968", + "917504", + "917505", + "917506", + "917520", + "1048576", + "1114112", + "1114115", + "1114128", + "1114129", + "1245184", + "1245185", + "1245186", + "1245187", + "1441792", + "851985", + "917536" + ], + "android.request.availableResultKeys": [ + "0", + "1", + "2", + "65537", + "65539", + "65540", + "65567", + "65543", + "65544", + "65538", + "65568", + "65547", + "65570", + "65551", + "65576", + "65581", + "65583", + "65588", + "65590", + "65591", + "65593", + "196608", + "262146", + "262149", + "458752", + "458753", + "458754", + "458755", + "458756", + "458757", + "458758", + "524288", + "524289", + "524290", + "524291", + "524296", + "524297", + "524294", + "524295", + "524298", + "524301", + "524292", + "655360", + "786433", + "851968", + "917526", + "917523", + "917504", + "917505", + "917506", + "917520", + "917522", + "917525", + "1048576", + "1114112", + "1114121", + "1114124", + "1114125", + "1114126", + "1114118", + "1114119", + "1114129", + "1114130", + "1114131", + "1114132", + "1245184", + "1245185", + "1245186", + "1245187", + "1441792", + "65541", + "65542", + "65545", + "65552", + "1114123", + "917530", + "851985", + "917536", + "851994" + ], + "android.request.maxNumOutputStreams": [ + "1", + "3", + "2" + ], + "android.scaler.availableRotateAndCropModes": [ + "0" + ], + "android.request.partialResultCount": [ + "2" + ], + "android.request.pipelineMaxDepth": [ + "8" + ], + "android.scaler.availableMaxDigitalZoom": [ + "8.00000000" + ], + "android.scaler.availableMinFrameDurations": [ + "54", + "2048", + "1536", + "33331760", + "54", + "1920", + "1440", + "33331760", + "54", + "1920", + "1080", + "33331760", + "54", + "1920", + "960", + "33331760", + "54", + "1600", + "1200", + "33331760", + "54", + "1440", + "1080", + "33331760", + "54", + "1280", + "960", + "33331760", + "54", + "1280", + "720", + "33331760", + "54", + "1024", + "768", + "33331760", + "54", + "800", + "600", + "33331760", + "54", + "720", + "480", + "33331760", + "54", + "640", + "480", + "33331760", + "54", + "640", + "360", + "33331760", + "54", + "352", + "288", + "33331760", + "54", + "320", + "240", + "33331760", + "54", + "176", + "144", + "33331760", + "32", + "2048", + "1536", + "33331760", + "34", + "2048", + "1536", + "33331760", + "35", + "2048", + "1536", + "33331760", + "33", + "2048", + "1536", + "33331760", + "32", + "1920", + "1440", + "33331760", + "34", + "1920", + "1440", + "33331760", + "35", + "1920", + "1440", + "33331760", + "33", + "1920", + "1440", + "33331760", + "34", + "1920", + "1080", + "33331760", + "35", + "1920", + "1080", + "33331760", + "33", + "1920", + "1080", + "33331760", + "34", + "1920", + "960", + "33331760", + "35", + "1920", + "960", + "33331760", + "33", + "1920", + "960", + "33331760", + "34", + "1600", + "1200", + "33331760", + "35", + "1600", + "1200", + "33331760", + "33", + "1600", + "1200", + "33331760", + "34", + "1440", + "1080", + "33331760", + "35", + "1440", + "1080", + "33331760", + "33", + "1440", + "1080", + "33331760", + "34", + "1280", + "960", + "33331760", + "35", + "1280", + "960", + "33331760", + "33", + "1280", + "960", + "33331760", + "34", + "1280", + "720", + "33331760", + "35", + "1280", + "720", + "33331760", + "33", + "1280", + "720", + "33331760", + "34", + "1024", + "768", + "33331760", + "35", + "1024", + "768", + "33331760", + "33", + "1024", + "768", + "33331760", + "34", + "800", + "600", + "33331760", + "35", + "800", + "600", + "33331760", + "33", + "800", + "600", + "33331760", + "34", + "720", + "480", + "33331760", + "35", + "720", + "480", + "33331760", + "33", + "720", + "480", + "33331760", + "34", + "640", + "480", + "33331760", + "35", + "640", + "480", + "33331760", + "33", + "640", + "480", + "33331760", + "34", + "640", + "360", + "33331760", + "35", + "640", + "360", + "33331760", + "33", + "640", + "360", + "33331760", + "34", + "352", + "288", + "33331760", + "35", + "352", + "288", + "33331760", + "33", + "352", + "288", + "33331760", + "34", + "320", + "240", + "33331760", + "35", + "320", + "240", + "33331760", + "33", + "320", + "240", + "33331760", + "34", + "176", + "144", + "33331760", + "35", + "176", + "144", + "33331760", + "33", + "176", + "144", + "33331760" + ], + "android.scaler.availableMinFrameDurationsMaximumResolution": [ + "32", + "6048", + "4024", + "33331760", + "33", + "6048", + "4024", + "33331760", + "35", + "6048", + "4024", + "33331760" + ], + "android.scaler.availableStallDurations": [ + "32", + "2048", + "1536", + "17971200", + "33", + "2048", + "1536", + "17971200", + "32", + "1920", + "1440", + "17971200", + "33", + "1920", + "1440", + "17971200", + "33", + "1920", + "1080", + "13478400", + "33", + "1920", + "960", + "11980800", + "33", + "1600", + "1200", + "12480000", + "33", + "1440", + "1080", + "10108800", + "33", + "1280", + "960", + "7987200", + "33", + "1280", + "720", + "5990400", + "33", + "1024", + "768", + "5111808", + "33", + "800", + "600", + "3120000", + "33", + "720", + "480", + "2246400", + "33", + "640", + "480", + "1996800", + "33", + "640", + "360", + "1497600", + "33", + "352", + "288", + "658944", + "33", + "320", + "240", + "499200", + "33", + "176", + "144", + "164736" + ], + "android.scaler.availableStallDurationsMaximumResolution": [ + "32", + "6048", + "4024", + "287539200", + "33", + "6048", + "4024", + "287539200" + ], + "android.scaler.availableStreamConfigurations": [ + "54", + "2048", + "1536", + "OUTPUT", + "54", + "1920", + "1440", + "OUTPUT", + "54", + "1920", + "1080", + "OUTPUT", + "54", + "1920", + "960", + "OUTPUT", + "54", + "1600", + "1200", + "OUTPUT", + "54", + "1440", + "1080", + "OUTPUT", + "54", + "1280", + "960", + "OUTPUT", + "54", + "1280", + "720", + "OUTPUT", + "54", + "1024", + "768", + "OUTPUT", + "54", + "800", + "600", + "OUTPUT", + "54", + "720", + "480", + "OUTPUT", + "54", + "640", + "480", + "OUTPUT", + "54", + "640", + "360", + "OUTPUT", + "54", + "352", + "288", + "OUTPUT", + "54", + "320", + "240", + "OUTPUT", + "54", + "176", + "144", + "OUTPUT", + "34", + "2048", + "1536", + "INPUT", + "35", + "2048", + "1536", + "INPUT", + "32", + "2048", + "1536", + "OUTPUT", + "34", + "2048", + "1536", + "OUTPUT", + "35", + "2048", + "1536", + "OUTPUT", + "33", + "2048", + "1536", + "OUTPUT", + "32", + "1920", + "1440", + "OUTPUT", + "34", + "1920", + "1440", + "OUTPUT", + "35", + "1920", + "1440", + "OUTPUT", + "33", + "1920", + "1440", + "OUTPUT", + "34", + "1920", + "1080", + "OUTPUT", + "35", + "1920", + "1080", + "OUTPUT", + "33", + "1920", + "1080", + "OUTPUT", + "34", + "1920", + "960", + "OUTPUT", + "35", + "1920", + "960", + "OUTPUT", + "33", + "1920", + "960", + "OUTPUT", + "34", + "1600", + "1200", + "OUTPUT", + "35", + "1600", + "1200", + "OUTPUT", + "33", + "1600", + "1200", + "OUTPUT", + "34", + "1440", + "1080", + "OUTPUT", + "35", + "1440", + "1080", + "OUTPUT", + "33", + "1440", + "1080", + "OUTPUT", + "34", + "1280", + "960", + "OUTPUT", + "35", + "1280", + "960", + "OUTPUT", + "33", + "1280", + "960", + "OUTPUT", + "34", + "1280", + "720", + "OUTPUT", + "35", + "1280", + "720", + "OUTPUT", + "33", + "1280", + "720", + "OUTPUT", + "34", + "1024", + "768", + "OUTPUT", + "35", + "1024", + "768", + "OUTPUT", + "33", + "1024", + "768", + "OUTPUT", + "34", + "800", + "600", + "OUTPUT", + "35", + "800", + "600", + "OUTPUT", + "33", + "800", + "600", + "OUTPUT", + "34", + "720", + "480", + "OUTPUT", + "35", + "720", + "480", + "OUTPUT", + "33", + "720", + "480", + "OUTPUT", + "34", + "640", + "480", + "OUTPUT", + "35", + "640", + "480", + "OUTPUT", + "33", + "640", + "480", + "OUTPUT", + "34", + "640", + "360", + "OUTPUT", + "35", + "640", + "360", + "OUTPUT", + "33", + "640", + "360", + "OUTPUT", + "34", + "352", + "288", + "OUTPUT", + "35", + "352", + "288", + "OUTPUT", + "33", + "352", + "288", + "OUTPUT", + "34", + "320", + "240", + "OUTPUT", + "35", + "320", + "240", + "OUTPUT", + "33", + "320", + "240", + "OUTPUT", + "34", + "176", + "144", + "OUTPUT", + "35", + "176", + "144", + "OUTPUT" + ], + "android.scaler.availableStreamConfigurationsMaximumResolution": [ + "32", + "6048", + "4024", + "INPUT", + "32", + "6048", + "4024", + "OUTPUT", + "33", + "6048", + "4024", + "OUTPUT", + "35", + "6048", + "4024", + "OUTPUT" + ], + "android.scaler.croppingType": [ + "CENTER_ONLY" + ], + "android.scaler.physicalCameraMultiResolutionStreamConfigurations": [ + "34", + "2048", + "1536", + "INPUT", + "35", + "2048", + "1536", + "INPUT", + "33", + "2048", + "1536", + "OUTPUT", + "34", + "2048", + "1536", + "OUTPUT", + "35", + "2048", + "1536", + "OUTPUT" + ], + "android.sensor.availableTestPatternModes": [ + "0", + "5" + ], + "android.sensor.blackLevelPattern": [ + "64", + "64", + "64", + "64" + ], + "android.sensor.calibrationTransform1": [ + "68", + "128", + "0", + "128", + "0", + "128", + "0", + "128", + "128", + "128", + "0", + "128", + "0", + "128", + "0", + "128", + "78", + "128" + ], + "android.sensor.calibrationTransform2": [ + "97", + "128", + "0", + "128", + "0", + "128", + "0", + "128", + "128", + "128", + "0", + "128", + "0", + "128", + "0", + "128", + "41", + "128" + ], + "android.sensor.colorTransform1": [ + "221", + "128", + "-105", + "128", + "-34", + "128", + "-124", + "128", + "240", + "128", + "5", + "128", + "5", + "128", + "-19", + "128", + "99", + "128" + ], + "android.sensor.colorTransform2": [ + "360", + "128", + "-249", + "128", + "-63", + "128", + "-137", + "128", + "279", + "128", + "-1", + "128", + "7", + "128", + "-18", + "128", + "159", + "128" + ], + "android.sensor.forwardMatrix1": [ + "56", + "128", + "49", + "128", + "18", + "128", + "28", + "128", + "92", + "128", + "8", + "128", + "2", + "128", + "12", + "128", + "91", + "128" + ], + "android.sensor.forwardMatrix2": [ + "56", + "128", + "49", + "128", + "18", + "128", + "28", + "128", + "92", + "128", + "8", + "128", + "2", + "128", + "12", + "128", + "91", + "128" + ], + "android.sensor.info.activeArraySize": [ + "0", + "0", + "2048", + "1536" + ], + "android.sensor.info.activeArraySizeMaximumResolution": [ + "0", + "0", + "6048", + "4024" + ], + "android.sensor.info.colorFilterArrangement": [ + "RGGB" + ], + "android.sensor.info.exposureTimeRange": [ + "9377", + "13388615424" + ], + "android.sensor.info.lensShadingApplied": [ + "TRUE" + ], + "android.sensor.info.maxFrameDuration": [ + "1319055264" + ], + "android.sensor.info.physicalSize": [ + "4.65600014", + "3.49600005" + ], + "android.sensor.info.pixelArraySize": [ + "2048", + "1536" + ], + "android.sensor.info.preCorrectionActiveArraySize": [ + "0", + "0", + "2048", + "1536" + ], + "android.sensor.info.pixelArraySizeMaximumResolution": [ + "6048", + "4024" + ], + "android.sensor.info.preCorrectionActiveArraySizeMaximumResolution": [ + "0", + "0", + "6048", + "4024" + ], + "android.sensor.info.binningFactor": [ + "2", + "2" + ], + "android.sensor.info.sensitivityRange": [ + "100", + "1000" + ], + "android.sensor.info.timestampSource": [ + "REALTIME" + ], + "android.sensor.info.whiteLevel": [ + "1023" + ], + "android.sensor.maxAnalogSensitivity": [ + "640" + ], + "android.sensor.orientation": [ + "270" + ], + "android.sensor.profileHueSatMapDimensions": [ + "0", + "0", + "0" + ], + "android.sensor.referenceIlluminant1": [ + "D65" + ], + "android.sensor.referenceIlluminant2": [ + "17" + ], + "android.shading.availableModes": [ + "0", + "1", + "2" + ], + "android.statistics.info.availableFaceDetectModes": [ + "0", + "1", + "2" + ], + "android.statistics.info.availableHotPixelMapModes": [ + "0" + ], + "android.statistics.info.availableLensShadingMapModes": [ + "0", + "1" + ], + "android.statistics.info.maxFaceCount": [ + "10" + ], + "android.info.supportedBufferManagementVersion" : [ + "SESSION_CONFIGURABLE" + ], + "android.sync.maxLatency": [ + "PER_FRAME_CONTROL" + ], + "android.tonemap.availableToneMapModes": [ + "0", + "1", + "2" + ], + "android.tonemap.maxCurvePoints": [ + "64" + ] + } +] diff --git a/aosp/vendor/common/prebuild/Android.bp b/aosp/vendor/common/prebuild/Android.bp index 712391618..95cd45540 100644 --- a/aosp/vendor/common/prebuild/Android.bp +++ b/aosp/vendor/common/prebuild/Android.bp @@ -17,4 +17,37 @@ cc_prebuilt_library_shared { "liblog", "libutils", ], -} \ No newline at end of file +} + +cc_prebuilt_library_shared { + name: "libvmicamera", + vendor: true, + arch: { + arm: { + srcs: ["system/lib64/libvmicamera.so"], + }, + arm64: { + srcs: ["system/lib64/libvmicamera.so"], + }, + }, + compile_multilib: "both", + check_elf_files: false, + export_include_dirs: ["include"], + shared_libs: [ + "libcutils", + "liblog", + "libui", + "libutils", + "libbinder_ndk", + "libmediandk", + "libavcodec", + "libswresample", + "libswscale", + "libavutil", + "va_drv_video", + "libc++_shared", + "libvaccrt", + "libjpeg", + "libpng", + ], +} diff --git a/aosp/vendor/common/prebuild/include/PacketQueue.h b/aosp/vendor/common/prebuild/include/PacketQueue.h new file mode 100644 index 000000000..bc7ee0faf --- /dev/null +++ b/aosp/vendor/common/prebuild/include/PacketQueue.h @@ -0,0 +1,132 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2025-2025. All rights reserved. + * Description: VmiAgent接收队列的包装类,带有退出机制避免锁销毁后访问 + */ + +#ifndef PACKET_QUEUE_H +#define PACKET_QUEUE_H + +#include +#include +#include +#include +#include +#include + +namespace android { + +constexpr static uint32_t PUBLIC_QUEUE_ID = 0xFF; + +class PacketQueue { +private: + // 包装缓冲区及其大小的结构体 + struct BufferWithSize { + std::unique_ptr buffer; + size_t size; + }; + +public: + PacketQueue() : m_running(true) {} + ~PacketQueue() { + // 析构时设置退出标志并唤醒所有等待线程 + stop(); + } + + // 禁止拷贝和移动,避免锁和条件变量的不安全操作 + PacketQueue(const PacketQueue&) = delete; + PacketQueue& operator=(const PacketQueue&) = delete; + PacketQueue(PacketQueue&&) = delete; + PacketQueue& operator=(PacketQueue&&) = delete; + + // 入队操作 - 保存缓冲区大小 + // 当队列已停止时,忽略入队操作 + void enqueue(std::unique_ptr buffer, size_t size) { + std::lock_guard lock(m_mutex); + if (m_running) { // 只有运行中才处理入队 + m_queue.push({std::move(buffer), size}); + m_cond.notify_one(); + } + } + + // 出队操作(阻塞模式) - 返回缓冲区大小 + // 当队列已停止时,返回空指针 + std::unique_ptr dequeue(size_t& outSize) { + std::unique_lock lock(m_mutex); + // 等待队列非空或已停止 + m_cond.wait(lock, [this] { return !m_queue.empty() || !m_running; }); + + // 如果队列已停止,直接返回空 + if (!m_running) { + outSize = 0; + return nullptr; + } + + auto item = std::move(m_queue.front()); + m_queue.pop(); + outSize = item.size; + return std::move(item.buffer); + } + + // 出队操作(带超时) - 返回缓冲区大小 + // 当队列已停止时,返回空指针 + std::unique_ptr dequeue(size_t& outSize, std::chrono::milliseconds timeout) { + std::unique_lock lock(m_mutex); + // 等待队列非空、已停止或超时 + if (!m_cond.wait_for(lock, timeout, [this] { return !m_queue.empty() || !m_running; })) { + outSize = 0; + return nullptr; // 超时 + } + + // 如果队列已停止,直接返回空 + if (!m_running) { + outSize = 0; + return nullptr; + } + + auto item = std::move(m_queue.front()); + m_queue.pop(); + outSize = item.size; + return std::move(item.buffer); + } + + // 停止队列,唤醒所有等待线程,后续操作将被忽略 + void stop() { + std::lock_guard lock(m_mutex); + if (m_running) { + m_running = false; + m_cond.notify_all(); // 唤醒所有等待的线程 + } + } + + // 清空队列内容 + void clear() { + std::lock_guard lock(m_mutex); + while (!m_queue.empty()) { + m_queue.pop(); + } + m_cond.notify_all(); // 唤醒所有等待的线程 + } + + // 检查队列是否为空 + bool empty() const { + std::lock_guard lock(m_mutex); + return m_queue.empty(); + } + + // 获取队列大小 + size_t size() const { + std::lock_guard lock(m_mutex); + return m_queue.size(); + } + +private: + std::queue m_queue; + mutable std::mutex m_mutex; // mutable允许在const函数中加锁 + std::condition_variable m_cond; // 条件变量用于等待/通知机制 + bool m_running; // 运行状态标志,控制队列生命周期 +}; + +} // namespace android + +#endif // PACKET_QUEUE_H + diff --git a/aosp/vendor/common/prebuild/include/VmiAgent.h b/aosp/vendor/common/prebuild/include/VmiAgent.h new file mode 100644 index 000000000..b2223e5e9 --- /dev/null +++ b/aosp/vendor/common/prebuild/include/VmiAgent.h @@ -0,0 +1,62 @@ + +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2025-2025. All rights reserved. + * Description: UNIX Socket Server,提供接收和发送消息的接口 + */ + +#ifndef VMI_AGENT_H +#define VMI_AGENT_H + +#include +#include +#include +#include +#include +#include +#include "VmiMsgHeader.h" +#include "PacketQueue.h" + +namespace android { + +constexpr static uint32_t MAX_PACKET_SIZE = (10 * 1024 * 1024); +constexpr static uint32_t PACKET_HEADER_SIZE = (16); + +class VmiAgent { +public: + VmiAgent(); + ~VmiAgent(); + int Init(const std::string&); + static std::shared_ptr GetInstance(); + std::unique_ptr WaitForMessage(int id, MsgType type, size_t& size, int32_t timeout = 5000); + int Write(const uint8_t* buffer, size_t size); + void InitQueue(int, MsgType); + void EnQueue(int, MsgType, std::unique_ptr, size_t); + int GetClientNum() { return m_clientNum.load(); } + +private: + void StateHandler(const std::string&); + void IOThread(); + int InitServerFd(); + uint64_t GetCurrentTimeMs(); + void ProcessData(); + int Read(uint8_t *buffer, size_t size); + + std::string m_unixSocketName; + std::mutex m_lock; + std::thread* m_ioThread{nullptr}; + std::atomic_bool m_threadRun{false}; + std::atomic_bool m_connected{false}; + std::atomic_int_fast32_t m_clientNum{0}; + int m_serverFd{-1}; + int m_clientFd{-1}; + std::atomic_uint_fast64_t m_lastTime{0}; + std::atomic_uint_fast32_t m_messageCount{0}; + static std::shared_ptr g_instance; + static std::mutex g_instanceLock; + std::map, PacketQueue> m_packetMap; + std::mutex m_packetMapLock; +}; + +} + +#endif diff --git a/aosp/vendor/common/prebuild/include/VmiCamera.h b/aosp/vendor/common/prebuild/include/VmiCamera.h new file mode 100644 index 000000000..faa2dbb85 --- /dev/null +++ b/aosp/vendor/common/prebuild/include/VmiCamera.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2025-2025. All rights reserved. + * Description: 定义VmiCamera接口的抽象类 + */ + +#ifndef VMI_CAMERA_H +#define VMI_CAMERA_H + +#include +#include + +namespace android { + +class VmiCamera { +public: + VmiCamera() = default; + virtual ~VmiCamera() = default; + + VmiCamera(const VmiCamera&) = delete; + VmiCamera& operator=(const VmiCamera&) = delete; + + virtual void Init() = 0; + virtual std::unique_ptr GetFrame(size_t&, size_t&, size_t&) = 0; + virtual int StartPreview(size_t, size_t, size_t) = 0; + virtual int StopPreview() = 0; + virtual bool Simulate() = 0; +}; + +class VmiCameraFactory { +public: + static std::unique_ptr CreateVmiCamera(int, int); +}; + +} + +#endif // VMI_CAMERA_H + diff --git a/aosp/vendor/common/prebuild/include/VmiMsgHeader.h b/aosp/vendor/common/prebuild/include/VmiMsgHeader.h new file mode 100644 index 000000000..9eec8a7f4 --- /dev/null +++ b/aosp/vendor/common/prebuild/include/VmiMsgHeader.h @@ -0,0 +1,274 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2025-2025. All rights reserved. + * Description: VMi消息头定义 + */ + +#ifndef VMI_MSG_HEADER_H +#define VMI_MSG_HEADER_H + +#include +#include +#include +#include +#include + +namespace android { + +using MsgType = uint16_t; + +const uint16_t DEV_OPT_CAMERA_GET_PARAM_REQ = 0x1; +const uint16_t DEV_OPT_CAMERA_GET_PARAM_RSP = 0x1001; +const uint16_t DEV_OPT_CAMERA_SET_PARAM_REQ = 0x2; +const uint16_t DEV_OPT_CAMERA_SET_PARAM_RSP = 0x1002; +const uint16_t DEV_OPT_CAMERA_GET_INFO_REQ = 0x3; +const uint16_t DEV_OPT_CAMERA_GET_INFO_RSP = 0x1003; +const uint16_t DEV_OPT_CAMERA_START_PREVIEW_REQ = 0x4; +const uint16_t DEV_OPT_CAMERA_START_PREVIEW_RSP = 0x1004; +const uint16_t DEV_OPT_CAMERA_STOP_PREVIEW_REQ = 0x5; +const uint16_t DEV_OPT_CAMERA_STOP_PREVIEW_RSP = 0x1005; +const uint16_t DEV_OPT_CAMERA_USE_FORMAT_REQ = 0x6; +const uint16_t DEV_OPT_CAMERA_USE_FORMAT_RSP = 0x1006; +const uint16_t DEV_OPT_CAMERA_GET_SIZE_REQ = 0x7; +const uint16_t DEV_OPT_CAMERA_GET_SIZE_RSP = 0x1007; +const uint16_t DEV_OPT_CAMERA_FRAME = 0x8; + +// 摄像头帧数据的类型 +const uint8_t VMI_CAMERA_FORMAT_H264 = 0x01; +const uint8_t VMI_CAMERA_FORMAT_JPEG = 0x02; +const uint8_t VMI_CAMERA_FORMAT_I420 = 0x03; +const uint8_t VMI_CAMERA_FORMAT_LOCAL = 0x04; +const uint8_t VMI_CAMERA_FORMAT_INVALID = 0xFF; + +struct DEV_CAMERA_HEADER { + uint16_t version; + uint16_t optType; + uint16_t devType; + uint16_t devId; + uint32_t len; + uint16_t nextProto; + uint16_t hopLimits; +} __attribute__((packed)); + +struct DEV_CAMERA_START_REVIEW_REQ { + struct DEV_CAMERA_HEADER devCameraHeader; + uint16_t width; + uint16_t height; + uint16_t fps; + DEV_CAMERA_START_REVIEW_REQ() + { + devCameraHeader.version = htons(0x1); + devCameraHeader.optType = htons(DEV_OPT_CAMERA_START_PREVIEW_REQ); + devCameraHeader.devType = htons(0x1); + devCameraHeader.len = htonl(sizeof(struct DEV_CAMERA_HEADER) + sizeof(uint16_t)*3); + devCameraHeader.nextProto = htons(0x0); + devCameraHeader.hopLimits = htons(0x0); + width = htons(640); //default value; + height = htons(480); //default value; + fps = htons(30); //default value; + } +} __attribute__((packed)); + +struct DEV_CAMERA_START_REVIEW_RSP { + struct DEV_CAMERA_HEADER devCameraHeader; + DEV_CAMERA_START_REVIEW_RSP() + { + devCameraHeader.version = htons(0x1); + devCameraHeader.optType = htons(DEV_OPT_CAMERA_START_PREVIEW_RSP); + devCameraHeader.devType = htons(0x1); + devCameraHeader.len = htonl(sizeof(struct DEV_CAMERA_HEADER) + sizeof(uint16_t)); + devCameraHeader.nextProto = htons(0x0); + devCameraHeader.hopLimits = htons(0x0); + } + uint16_t result; +} __attribute__((packed)); + +struct DEV_CAMERA_STOP_REVIEW_REQ{ + struct DEV_CAMERA_HEADER devCameraHeader; + + DEV_CAMERA_STOP_REVIEW_REQ() + { + devCameraHeader.version = htons(0x1); + devCameraHeader.optType = htons(DEV_OPT_CAMERA_STOP_PREVIEW_REQ); + devCameraHeader.devType = htons(0x1); + devCameraHeader.len = htonl(sizeof(struct DEV_CAMERA_HEADER)); + devCameraHeader.nextProto = htons(0x0); + devCameraHeader.hopLimits = htons(0x0); + } +} __attribute__((packed)); + +struct DEV_CAMERA_STOP_REVIEW_RSP { + struct DEV_CAMERA_HEADER devCameraHeader; + DEV_CAMERA_STOP_REVIEW_RSP() + { + devCameraHeader.version = htons(0x1); + devCameraHeader.optType = htons(DEV_OPT_CAMERA_STOP_PREVIEW_RSP); + devCameraHeader.devType = htons(0x1); + devCameraHeader.len = htonl(sizeof(struct DEV_CAMERA_HEADER) + sizeof(uint16_t)); + devCameraHeader.nextProto = htons(0x0); + devCameraHeader.hopLimits = htons(0x0); + } + uint16_t result; +} __attribute__((packed)); + +struct DEV_CAMERA_GET_PARAM_REQ { + struct DEV_CAMERA_HEADER devCameraHeader; + + DEV_CAMERA_GET_PARAM_REQ() + { + devCameraHeader.version = htons(0x1); + devCameraHeader.optType = htons(DEV_OPT_CAMERA_GET_PARAM_REQ); + devCameraHeader.devType = htons(0x1); + devCameraHeader.len = htonl(sizeof(struct DEV_CAMERA_HEADER)); + devCameraHeader.nextProto = htons(0x0); + devCameraHeader.hopLimits = htons(0x0); + } +} __attribute__((packed)); + +struct DEV_CAMERA_GET_PARAM_RSP_DATA { + uint16_t result; + uint8_t data[0]; +} __attribute__((packed)); + +struct DEV_CAMERA_GET_PARAM_RSP { + struct DEV_CAMERA_HEADER devCameraHeader; + DEV_CAMERA_GET_PARAM_RSP() + { + devCameraHeader.version = htons(0x1); + devCameraHeader.optType = htons(DEV_OPT_CAMERA_GET_PARAM_RSP); + devCameraHeader.devType = htons(0x1); + devCameraHeader.nextProto = htons(0x0); + devCameraHeader.hopLimits = htons(0x0); + } + struct DEV_CAMERA_GET_PARAM_RSP_DATA* rspData; +} __attribute__((packed)); + +struct DEV_CAMERA_GET_INFO_REQ { + struct DEV_CAMERA_HEADER devCameraHeader; + + DEV_CAMERA_GET_INFO_REQ() + { + devCameraHeader.version = htons(0x1); + devCameraHeader.optType = htons(DEV_OPT_CAMERA_GET_INFO_REQ); + devCameraHeader.devType = htons(0x1); + devCameraHeader.len = htonl(sizeof(struct DEV_CAMERA_HEADER)); + devCameraHeader.nextProto = htons(0x0); + devCameraHeader.hopLimits = htons(0x0); + } +} __attribute__((packed)); + +struct DEV_CAMERA_GET_INFO_RSP_DATA { + uint16_t result; + uint8_t facing; + uint16_t orientation; + +} __attribute__((packed)); + +struct DEV_CAMERA_GET_INFO_RSP { + struct DEV_CAMERA_HEADER devCameraHeader; + DEV_CAMERA_GET_INFO_RSP() + { + devCameraHeader.version = htons(0x1); + devCameraHeader.optType = htons(DEV_OPT_CAMERA_GET_INFO_RSP); + devCameraHeader.devType = htons(0x1); + devCameraHeader.nextProto = htons(0x0); + devCameraHeader.hopLimits = htons(0x0); + } + struct DEV_CAMERA_GET_INFO_RSP_DATA* rspData; +} __attribute__((packed)); + +struct DEV_CAMERA_GET_SIZE_REQ { + struct DEV_CAMERA_HEADER devCameraHeader; + + DEV_CAMERA_GET_SIZE_REQ() + { + devCameraHeader.version = htons(0x1); + devCameraHeader.optType = htons(DEV_OPT_CAMERA_GET_SIZE_REQ); + devCameraHeader.devType = htons(0x1); + devCameraHeader.len = htonl(sizeof(struct DEV_CAMERA_HEADER)); + devCameraHeader.nextProto = htons(0x0); + devCameraHeader.hopLimits = htons(0x0); + } +} __attribute__((packed)); + +struct DEV_CAMERA_GET_SIZE_RSP_DATA { + uint16_t result; + uint16_t width; + uint16_t height; + +} __attribute__((packed)); + +struct DEV_CAMERA_GET_SIZE_RSP { + struct DEV_CAMERA_HEADER devCameraHeader; + DEV_CAMERA_GET_SIZE_RSP() + { + devCameraHeader.version = htons(0x1); + devCameraHeader.optType = htons(DEV_OPT_CAMERA_GET_SIZE_RSP); + devCameraHeader.devType = htons(0x1); + devCameraHeader.len = htonl(sizeof(struct DEV_CAMERA_HEADER) + sizeof(uint16_t) * 3); + devCameraHeader.nextProto = htons(0x0); + devCameraHeader.hopLimits = htons(0x0); + } + struct DEV_CAMERA_GET_SIZE_RSP_DATA* rspData; +} __attribute__((packed)); + +struct DEV_CAMERA_SET_PARAM_REQ { + struct DEV_CAMERA_HEADER devCameraHeader; + uint8_t data[0]; + + DEV_CAMERA_SET_PARAM_REQ() + { + devCameraHeader.version = htons(0x1); + devCameraHeader.optType = htons(DEV_OPT_CAMERA_SET_PARAM_REQ); + devCameraHeader.devType = htons(0x1); + devCameraHeader.nextProto = htons(0x0); + devCameraHeader.hopLimits = htons(0x0); + } +} __attribute__((packed)); + +class VmiMsgHeader { +public: + explicit VmiMsgHeader(std::unique_ptr&& buffer) + : buffer(std::move(buffer)) { + ParseHeader(); + } + ~VmiMsgHeader() = default; + + // 获取各字段值的访问器 + uint16_t GetVersion() const { return version; } + uint16_t GetOptType() const { return optType; } + uint16_t GetDevType() const { return devType; } + uint16_t GetDevId() const { return devId; } + uint32_t GetLength() const { return len; } + uint16_t GetNextProto() const { return nextProto; } + uint16_t GetHopLimits() const { return hopLimits; } + +private: + std::unique_ptr buffer; + + // 解析后的字段值(已转换为主机字节序) + uint16_t version; + uint16_t optType; + uint16_t devType; + uint16_t devId; + uint32_t len; + uint16_t nextProto; + uint16_t hopLimits; + + // 解析包头 + void ParseHeader() { + const uint8_t* ptr = buffer.get(); + + // 直接通过指针访问和类型转换读取各字段 + version = ntohs(*reinterpret_cast(ptr + offsetof(DEV_CAMERA_HEADER, version))); + optType = ntohs(*reinterpret_cast(ptr + offsetof(DEV_CAMERA_HEADER, optType))); + devType = ntohs(*reinterpret_cast(ptr + offsetof(DEV_CAMERA_HEADER, devType))); + devId = ntohs(*reinterpret_cast(ptr + offsetof(DEV_CAMERA_HEADER, devId))); + len = ntohl(*reinterpret_cast(ptr + offsetof(DEV_CAMERA_HEADER, len))); + nextProto = ntohs(*reinterpret_cast(ptr + offsetof(DEV_CAMERA_HEADER, nextProto))); + hopLimits = ntohs(*reinterpret_cast(ptr + offsetof(DEV_CAMERA_HEADER, hopLimits))); + } +}; + +} + +#endif diff --git a/aosp/vendor/isula/common.mk b/aosp/vendor/isula/common.mk index 6d4e7c0f6..2e7c909b7 100644 --- a/aosp/vendor/isula/common.mk +++ b/aosp/vendor/isula/common.mk @@ -26,6 +26,8 @@ PRODUCT_FULL_TREBLE_OVERRIDE := true PRODUCT_ENABLE_UFFD_GC := true PRODUCT_DEFAULT_DEV_CERTIFICATE := vendor/common/certificates/releasekey PRODUCT_SOONG_NAMESPACES += device/generic/goldfish +PRODUCT_SOONG_NAMESPACES += hardware/google/camera +PRODUCT_SOONG_NAMESPACES += hardware/google/camera/devices/EmulatedCamera PRODUCT_PACKAGE_OVERLAYS := vendor/common/overlay PRODUCT_DEFAULT_PROPERTY_OVERRIDES += ro.zygote=zygote64_32 diff --git a/aosp/vendor/isula/copyfiles.mk b/aosp/vendor/isula/copyfiles.mk index c7c0a8b86..4c2e65a4c 100644 --- a/aosp/vendor/isula/copyfiles.mk +++ b/aosp/vendor/isula/copyfiles.mk @@ -46,4 +46,4 @@ PRODUCT_COPY_FILES += \ frameworks/native/data/etc/android.software.opengles.deqp.level-latest.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.software.opengles.deqp.level.xml \ frameworks/native/data/etc/android.software.verified_boot.xml:${TARGET_COPY_OUT_PRODUCT}/etc/permissions/android.software.verified_boot.xml \ frameworks/native/data/etc/android.software.vulkan.deqp.level-latest.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.software.vulkan.deqp.level.xml \ - + device/google/coral/media_profiles_V1_0.xml:$(TARGET_COPY_OUT_VENDOR)/etc/media_profiles_V1_0.xml \ diff --git a/aosp/vendor/isula/packages.mk b/aosp/vendor/isula/packages.mk index 096a80893..5ef7cd2fa 100644 --- a/aosp/vendor/isula/packages.mk +++ b/aosp/vendor/isula/packages.mk @@ -34,11 +34,13 @@ PRODUCT_PACKAGES += \ com.google.oemlock \ com.google.confirmationui \ com.google.light \ + com.google.camera.provider.hal \ # apks PRODUCT_PACKAGES += \ Launcher3 \ + Camera2 \ # migrate from goldfish -- Gitee