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 0000000000000000000000000000000000000000..dc4e08f945f210796b2c44639e5c049fcde5604d
--- /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 0000000000000000000000000000000000000000..4b861ae2e5ac0ab160bf50737802a24532aa283e
--- /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 0000000000000000000000000000000000000000..5726a0076f281386df86862d79b4f07a5282a390
--- /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 0000000000000000000000000000000000000000..b7330693f3617fe63723d565e4efcceb5c0587df
--- /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 0000000000000000000000000000000000000000..25eeb98dc4658085c6eee24fb8c4885d3573317e
--- /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 0000000000000000000000000000000000000000..95091e4bd68fe7b82b9b0fbbf922697b2fe91cb2
--- /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 0000000000000000000000000000000000000000..df0282b9dd3c33927d4513004579103176f85fed
--- /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 0000000000000000000000000000000000000000..8a1035e216dfb923804870d2d08ff51e0f0e7f5d
--- /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 0000000000000000000000000000000000000000..55f98ca8b48858a37b144941723dc29a5e5af069
--- /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
Binary files /dev/null and b/aosp/hardware/google/camera/devices/EmulatedCamera/hwl/apex/com.google.camera.provider.hal.avbpubkey differ
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 0000000000000000000000000000000000000000..94c79c941609934ec35ab0d91c86a3fc73d0468a
--- /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
Binary files /dev/null and b/aosp/hardware/google/camera/devices/EmulatedCamera/hwl/apex/com.google.camera.provider.hal.pk8 differ
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 0000000000000000000000000000000000000000..505d580e4f6bafbd16d8233a37bec25864e61d6b
--- /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 0000000000000000000000000000000000000000..528c923d0c4237b1f358887aed55f045dbf37efc
--- /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 0000000000000000000000000000000000000000..9615ffe5fc24a74eed18ca20199c084d00184279
--- /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 0000000000000000000000000000000000000000..2e4ed9d4e03cccd5f6f41d3f0714417cbb08f7b3
--- /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 0000000000000000000000000000000000000000..8497e861a4dfe813ad1c68e31ad93a91c2b59029
--- /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 0000000000000000000000000000000000000000..f2b4293311654d33a81df2da80971c6698f83401
--- /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 0000000000000000000000000000000000000000..591256408c7a52f5f56b3ded51d625e8e96a78a2
--- /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 712391618c553b3b794b7c263d1a5b54d57e8b7b..95cd455405fb47865e77b5c94dd2415dc01a2c26 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 0000000000000000000000000000000000000000..bc7ee0faf0260bb0436a1151fbd54036ad3c5595
--- /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 0000000000000000000000000000000000000000..b2223e5e977fa778118252ca183dfff299b67564
--- /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