summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--devices/EmulatedCamera/hwl/EmulatedCameraDeviceHWLImpl.cpp36
-rw-r--r--devices/EmulatedCamera/hwl/EmulatedCameraDeviceHWLImpl.h8
-rw-r--r--devices/EmulatedCamera/hwl/EmulatedCameraDeviceSessionHWLImpl.cpp65
-rw-r--r--devices/EmulatedCamera/hwl/EmulatedCameraDeviceSessionHWLImpl.h25
-rw-r--r--devices/EmulatedCamera/hwl/EmulatedCameraProviderHWLImpl.cpp130
-rw-r--r--devices/EmulatedCamera/hwl/EmulatedCameraProviderHWLImpl.h7
-rw-r--r--devices/EmulatedCamera/hwl/EmulatedLogicalRequestState.cpp283
-rw-r--r--devices/EmulatedCamera/hwl/EmulatedLogicalRequestState.h72
-rw-r--r--devices/EmulatedCamera/hwl/EmulatedRequestProcessor.cpp78
-rw-r--r--devices/EmulatedCamera/hwl/EmulatedRequestProcessor.h9
-rw-r--r--devices/EmulatedCamera/hwl/EmulatedRequestState.cpp2
-rw-r--r--devices/EmulatedCamera/hwl/EmulatedScene.cpp34
-rw-r--r--devices/EmulatedCamera/hwl/EmulatedScene.h9
-rw-r--r--devices/EmulatedCamera/hwl/EmulatedSensor.cpp374
-rw-r--r--devices/EmulatedCamera/hwl/EmulatedSensor.h55
-rw-r--r--devices/EmulatedCamera/hwl/JpegCompressor.cpp27
-rw-r--r--devices/EmulatedCamera/hwl/JpegCompressor.h4
-rw-r--r--devices/EmulatedCamera/hwl/configs/camera_front.json951
-rw-r--r--devices/EmulatedCamera/hwl/configs/emu_camera_back.json (renamed from devices/EmulatedCamera/hwl/configs/camera.json)0
-rw-r--r--devices/EmulatedCamera/hwl/configs/emu_camera_depth.json (renamed from devices/EmulatedCamera/hwl/configs/camera_depth.json)0
-rw-r--r--devices/EmulatedCamera/hwl/configs/emu_camera_front.json3528
-rwxr-xr-xdevices/EmulatedCamera/hwl/tools/parse_bugreport.py77
-rw-r--r--devices/EmulatedCamera/hwl/utils/HWLUtils.cpp8
-rw-r--r--devices/EmulatedCamera/hwl/utils/HWLUtils.h5
24 files changed, 4552 insertions, 1235 deletions
diff --git a/devices/EmulatedCamera/hwl/EmulatedCameraDeviceHWLImpl.cpp b/devices/EmulatedCamera/hwl/EmulatedCameraDeviceHWLImpl.cpp
index a8d7f2c..0295e95 100644
--- a/devices/EmulatedCamera/hwl/EmulatedCameraDeviceHWLImpl.cpp
+++ b/devices/EmulatedCamera/hwl/EmulatedCameraDeviceHWLImpl.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013-2019 The Android Open Source Project
+ * 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.
@@ -28,9 +28,11 @@ namespace android {
std::unique_ptr<CameraDeviceHwl> EmulatedCameraDeviceHwlImpl::Create(
uint32_t camera_id, std::unique_ptr<HalCameraMetadata> static_meta,
+ PhysicalDeviceMapPtr physical_devices,
std::shared_ptr<EmulatedTorchState> torch_state) {
auto device = std::unique_ptr<EmulatedCameraDeviceHwlImpl>(
new EmulatedCameraDeviceHwlImpl(camera_id, std::move(static_meta),
+ std::move(physical_devices),
torch_state));
if (device == nullptr) {
@@ -53,11 +55,12 @@ std::unique_ptr<CameraDeviceHwl> EmulatedCameraDeviceHwlImpl::Create(
EmulatedCameraDeviceHwlImpl::EmulatedCameraDeviceHwlImpl(
uint32_t camera_id, std::unique_ptr<HalCameraMetadata> static_meta,
+ PhysicalDeviceMapPtr physical_devices,
std::shared_ptr<EmulatedTorchState> torch_state)
: camera_id_(camera_id),
static_metadata_(std::move(static_meta)),
- torch_state_(torch_state) {
-}
+ physical_device_map_(std::move(physical_devices)),
+ torch_state_(torch_state) {}
uint32_t EmulatedCameraDeviceHwlImpl::GetCameraId() const {
return camera_id_;
@@ -97,9 +100,27 @@ status_t EmulatedCameraDeviceHwlImpl::GetCameraCharacteristics(
}
status_t EmulatedCameraDeviceHwlImpl::GetPhysicalCameraCharacteristics(
- uint32_t /*physical_camera_id*/,
- std::unique_ptr<HalCameraMetadata>* /*characteristics*/) const {
- // TODO: Logical camera support
+ uint32_t physical_camera_id,
+ std::unique_ptr<HalCameraMetadata>* characteristics) const {
+ if (characteristics == nullptr) {
+ return BAD_VALUE;
+ }
+
+ if (physical_device_map_.get() == nullptr) {
+ ALOGE("%s: Camera %d is not a logical device!", __func__, camera_id_);
+ return NO_INIT;
+ }
+
+ if (physical_device_map_->find(physical_camera_id) ==
+ physical_device_map_->end()) {
+ ALOGE("%s: Physical camera id %d is not part of logical camera %d!",
+ __func__, physical_camera_id, camera_id_);
+ return NO_INIT;
+ }
+
+ *characteristics = HalCameraMetadata::Clone(
+ physical_device_map_->at(physical_camera_id).get());
+
return OK;
}
@@ -126,7 +147,8 @@ status_t EmulatedCameraDeviceHwlImpl::CreateCameraDeviceSessionHwl(
std::unique_ptr<HalCameraMetadata> meta =
HalCameraMetadata::Clone(static_metadata_.get());
*session = EmulatedCameraDeviceSessionHwlImpl::Create(
- camera_id_, std::move(meta), torch_state_);
+ camera_id_, std::move(meta), ClonePhysicalDeviceMap(physical_device_map_),
+ torch_state_);
if (*session == nullptr) {
ALOGE("%s: Cannot create EmulatedCameraDeviceSessionHWlImpl.", __FUNCTION__);
return BAD_VALUE;
diff --git a/devices/EmulatedCamera/hwl/EmulatedCameraDeviceHWLImpl.h b/devices/EmulatedCamera/hwl/EmulatedCameraDeviceHWLImpl.h
index 2bfe677..90352f5 100644
--- a/devices/EmulatedCamera/hwl/EmulatedCameraDeviceHWLImpl.h
+++ b/devices/EmulatedCamera/hwl/EmulatedCameraDeviceHWLImpl.h
@@ -22,6 +22,7 @@
#include "EmulatedSensor.h"
#include "EmulatedTorchState.h"
+#include "utils/HWLUtils.h"
#include "utils/StreamConfigurationMap.h"
namespace android {
@@ -38,6 +39,7 @@ class EmulatedCameraDeviceHwlImpl : public CameraDeviceHwl {
public:
static std::unique_ptr<CameraDeviceHwl> Create(
uint32_t camera_id, std::unique_ptr<HalCameraMetadata> static_meta,
+ PhysicalDeviceMapPtr physical_devices,
std::shared_ptr<EmulatedTorchState> torch_state);
virtual ~EmulatedCameraDeviceHwlImpl() = default;
@@ -68,16 +70,18 @@ class EmulatedCameraDeviceHwlImpl : public CameraDeviceHwl {
// End of override functions in CameraDeviceHwl.
private:
- const uint32_t camera_id_ = 0;
-
EmulatedCameraDeviceHwlImpl(uint32_t camera_id,
std::unique_ptr<HalCameraMetadata> static_meta,
+ PhysicalDeviceMapPtr physical_devices,
std::shared_ptr<EmulatedTorchState> torch_state);
status_t Initialize();
+ const uint32_t camera_id_ = 0;
+
std::unique_ptr<HalCameraMetadata> static_metadata_;
std::unique_ptr<StreamConfigurationMap> stream_coniguration_map_;
+ PhysicalDeviceMapPtr physical_device_map_;
std::shared_ptr<EmulatedTorchState> torch_state_;
SensorCharacteristics sensor_chars_;
};
diff --git a/devices/EmulatedCamera/hwl/EmulatedCameraDeviceSessionHWLImpl.cpp b/devices/EmulatedCamera/hwl/EmulatedCameraDeviceSessionHWLImpl.cpp
index 29d5b33..eead2c5 100644
--- a/devices/EmulatedCamera/hwl/EmulatedCameraDeviceSessionHWLImpl.cpp
+++ b/devices/EmulatedCamera/hwl/EmulatedCameraDeviceSessionHWLImpl.cpp
@@ -31,6 +31,7 @@ namespace android {
std::unique_ptr<EmulatedCameraDeviceSessionHwlImpl>
EmulatedCameraDeviceSessionHwlImpl::Create(
uint32_t camera_id, std::unique_ptr<HalCameraMetadata> static_meta,
+ PhysicalDeviceMapPtr physical_devices,
std::shared_ptr<EmulatedTorchState> torch_state) {
ATRACE_CALL();
if (static_meta.get() == nullptr) {
@@ -38,7 +39,8 @@ EmulatedCameraDeviceSessionHwlImpl::Create(
}
auto session = std::unique_ptr<EmulatedCameraDeviceSessionHwlImpl>(
- new EmulatedCameraDeviceSessionHwlImpl(torch_state));
+ new EmulatedCameraDeviceSessionHwlImpl(std::move(physical_devices),
+ torch_state));
if (session == nullptr) {
ALOGE("%s: Creating EmulatedCameraDeviceSessionHwlImpl failed",
__FUNCTION__);
@@ -78,8 +80,21 @@ status_t EmulatedCameraDeviceSessionHwlImpl::Initialize(
return ret;
}
+ auto logical_chars = std::make_unique<LogicalCharacteristics>();
+ logical_chars->emplace(camera_id_, sensor_chars_);
+ for (const auto& it : *physical_device_map_) {
+ SensorCharacteristics physical_chars;
+ auto stat = GetSensorCharacteristics(it.second.get(), &physical_chars);
+ if (stat == OK) {
+ logical_chars->emplace(it.first, physical_chars);
+ } else {
+ ALOGE("%s: Unable to extract physical device: %u characteristics %s (%d)",
+ __FUNCTION__, it.first, strerror(-ret), ret);
+ return ret;
+ }
+ }
sp<EmulatedSensor> emulated_sensor = new EmulatedSensor();
- ret = emulated_sensor->StartUp(sensor_chars_);
+ ret = emulated_sensor->StartUp(camera_id_, std::move(logical_chars));
if (ret != OK) {
ALOGE("%s: Failed on sensor start up %s (%d)", __FUNCTION__, strerror(-ret),
ret);
@@ -90,7 +105,8 @@ status_t EmulatedCameraDeviceSessionHwlImpl::Initialize(
std::make_unique<EmulatedRequestProcessor>(camera_id_, emulated_sensor);
return request_processor_->Initialize(
- HalCameraMetadata::Clone(static_metadata_.get()));
+ HalCameraMetadata::Clone(static_metadata_.get()),
+ ClonePhysicalDeviceMap(physical_device_map_));
}
EmulatedCameraDeviceSessionHwlImpl::~EmulatedCameraDeviceSessionHwlImpl() {
@@ -130,6 +146,16 @@ status_t EmulatedCameraDeviceSessionHwlImpl::ConfigurePipeline(
return BAD_VALUE;
}
+ if ((physical_camera_id != camera_id_) &&
+ (physical_device_map_.get() != nullptr)) {
+ if (physical_device_map_->find(physical_camera_id) ==
+ physical_device_map_->end()) {
+ ALOGE("%s: Camera: %d doesn't include physical device with id: %u",
+ __FUNCTION__, camera_id_, physical_camera_id);
+ return BAD_VALUE;
+ }
+ }
+
*pipeline_id = pipelines_.size();
EmulatedPipeline emulated_pipeline{.cb = hwl_pipeline_callback,
.pipeline_id = *pipeline_id,
@@ -274,8 +300,18 @@ uint32_t EmulatedCameraDeviceSessionHwlImpl::GetCameraId() const {
std::vector<uint32_t> EmulatedCameraDeviceSessionHwlImpl::GetPhysicalCameraIds()
const {
- // TODO: Logical camera support
- return std::vector<uint32_t>{};
+ if ((physical_device_map_.get() == nullptr) ||
+ (physical_device_map_->empty())) {
+ return std::vector<uint32_t>{};
+ }
+
+ std::vector<uint32_t> ret;
+ ret.reserve(physical_device_map_->size());
+ for (const auto& it : *physical_device_map_) {
+ ret.push_back(it.first);
+ }
+
+ return ret;
}
status_t EmulatedCameraDeviceSessionHwlImpl::GetCameraCharacteristics(
@@ -296,14 +332,29 @@ status_t EmulatedCameraDeviceSessionHwlImpl::GetCameraCharacteristics(
}
status_t EmulatedCameraDeviceSessionHwlImpl::GetPhysicalCameraCharacteristics(
- uint32_t /*physical_camera_id*/,
+ uint32_t physical_camera_id,
std::unique_ptr<HalCameraMetadata>* characteristics) const {
ATRACE_CALL();
if (characteristics == nullptr) {
return BAD_VALUE;
}
- // TODO: Add logical stream support
+ if (physical_device_map_.get() == nullptr) {
+ ALOGE("%s: Camera: %d doesn't have physical device support!", __FUNCTION__,
+ camera_id_);
+ return BAD_VALUE;
+ }
+
+ if (physical_device_map_->find(physical_camera_id) ==
+ physical_device_map_->end()) {
+ ALOGE("%s: Camera: %d doesn't include physical device with id: %u",
+ __FUNCTION__, camera_id_, physical_camera_id);
+ return BAD_VALUE;
+ }
+
+ (*characteristics) = HalCameraMetadata::Clone(
+ physical_device_map_->at(physical_camera_id).get());
+
return OK;
}
diff --git a/devices/EmulatedCamera/hwl/EmulatedCameraDeviceSessionHWLImpl.h b/devices/EmulatedCamera/hwl/EmulatedCameraDeviceSessionHWLImpl.h
index 980540f..f576021 100644
--- a/devices/EmulatedCamera/hwl/EmulatedCameraDeviceSessionHWLImpl.h
+++ b/devices/EmulatedCamera/hwl/EmulatedCameraDeviceSessionHWLImpl.h
@@ -24,6 +24,7 @@
#include "EmulatedCameraDeviceHWLImpl.h"
#include "EmulatedRequestProcessor.h"
#include "EmulatedTorchState.h"
+#include "multicam_coordinator_hwl.h"
#include "utils/StreamConfigurationMap.h"
namespace android {
@@ -31,12 +32,15 @@ namespace android {
using google_camera_hal::CameraDeviceHwl;
using google_camera_hal::CameraDeviceSessionHwl;
using google_camera_hal::HalStream;
+using google_camera_hal::HwlOfflinePipelineRole;
using google_camera_hal::HwlPipelineCallback;
using google_camera_hal::HwlPipelineRequest;
using google_camera_hal::HwlSessionCallback;
+using google_camera_hal::IMulticamCoordinatorHwl;
using google_camera_hal::StreamConfiguration;
using google_camera_hal::RequestTemplate;
using google_camera_hal::SessionDataKey;
+using google_camera_hal::Stream;
using google_camera_hal::StreamConfiguration;
// Implementation of CameraDeviceSessionHwl interface
@@ -44,6 +48,7 @@ class EmulatedCameraDeviceSessionHwlImpl : public CameraDeviceSessionHwl {
public:
static std::unique_ptr<EmulatedCameraDeviceSessionHwlImpl> Create(
uint32_t camera_id, std::unique_ptr<HalCameraMetadata> static_meta,
+ PhysicalDeviceMapPtr physical_devices,
std::shared_ptr<EmulatedTorchState> torch_state);
virtual ~EmulatedCameraDeviceSessionHwlImpl();
@@ -71,6 +76,13 @@ class EmulatedCameraDeviceSessionHwlImpl : public CameraDeviceSessionHwl {
return OK;
} // Noop for now
+ status_t GetRequiredIntputStreams(const StreamConfiguration& /*overall_config*/,
+ HwlOfflinePipelineRole /*pipeline_role*/,
+ std::vector<Stream>* /*streams*/) override {
+ // N/A
+ return INVALID_OPERATION;
+ }
+
status_t GetConfiguredHalStream(
uint32_t pipeline_id, std::vector<HalStream>* hal_streams) const override;
@@ -93,7 +105,9 @@ class EmulatedCameraDeviceSessionHwlImpl : public CameraDeviceSessionHwl {
uint32_t physical_camera_id,
std::unique_ptr<HalCameraMetadata>* characteristics) const override;
- status_t SetSessionData(SessionDataKey /*key*/, void* /*value*/) override {
+ status_t SetSessionData(SessionDataKey /*key*/
+ ,
+ void* /*value*/) override {
return OK;
} // Noop for now
@@ -110,6 +124,10 @@ class EmulatedCameraDeviceSessionHwlImpl : public CameraDeviceSessionHwl {
return OK;
} // Noop for now
+ std::unique_ptr<IMulticamCoordinatorHwl> CreateMulticamCoordinatorHwl()
+ override {
+ return nullptr;
+ }
// End override functions in CameraDeviceSessionHwl
private:
@@ -117,8 +135,10 @@ class EmulatedCameraDeviceSessionHwlImpl : public CameraDeviceSessionHwl {
std::unique_ptr<HalCameraMetadata> static_meta);
EmulatedCameraDeviceSessionHwlImpl(
+ PhysicalDeviceMapPtr physical_devices,
std::shared_ptr<EmulatedTorchState> torch_state)
- : torch_state_(torch_state) {
+ : torch_state_(torch_state),
+ physical_device_map_(std::move(physical_devices)) {
}
uint8_t max_pipeline_depth_ = 0;
@@ -134,6 +154,7 @@ class EmulatedCameraDeviceSessionHwlImpl : public CameraDeviceSessionHwl {
std::unique_ptr<StreamConfigurationMap> stream_coniguration_map_;
SensorCharacteristics sensor_chars_;
std::shared_ptr<EmulatedTorchState> torch_state_;
+ PhysicalDeviceMapPtr physical_device_map_;
};
} // namespace android
diff --git a/devices/EmulatedCamera/hwl/EmulatedCameraProviderHWLImpl.cpp b/devices/EmulatedCamera/hwl/EmulatedCameraProviderHWLImpl.cpp
index ab21c96..2782783 100644
--- a/devices/EmulatedCamera/hwl/EmulatedCameraProviderHWLImpl.cpp
+++ b/devices/EmulatedCamera/hwl/EmulatedCameraProviderHWLImpl.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013-2019 The Android Open Source Project
+ * 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.
@@ -24,6 +24,7 @@
#include "EmulatedCameraDeviceHWLImpl.h"
#include "EmulatedCameraDeviceSessionHWLImpl.h"
+#include "EmulatedLogicalRequestState.h"
#include "EmulatedSensor.h"
#include "EmulatedTorchState.h"
#include "camera_common.h"
@@ -34,9 +35,9 @@ namespace android {
// Location of the camera configuration files.
const char* EmulatedCameraProviderHwlImpl::kConfigurationFileLocation[] = {
- "/vendor/etc/config/camera.json",
- "/vendor/etc/config/camera_front.json",
- "/vendor/etc/config/camera_depth.json",
+ "/vendor/etc/config/emu_camera_back.json",
+ "/vendor/etc/config/emu_camera_front.json",
+ "/vendor/etc/config/emu_camera_depth.json",
};
std::unique_ptr<EmulatedCameraProviderHwlImpl>
@@ -177,6 +178,7 @@ status_t GetUInt8Value(const Json::Value& value, uint32_t tag_id,
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 {
@@ -206,6 +208,7 @@ status_t GetInt32Value(const Json::Value& value, uint32_t tag_id,
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 {
@@ -222,7 +225,7 @@ status_t GetInt32Value(const Json::Value& value, uint32_t tag_id,
return OK;
}
-status_t GetInt64Value(const Json::Value& value, uint32_t /*tag_id*/,
+status_t GetInt64Value(const Json::Value& value, uint32_t tag_id,
int64_t* result /*out*/) {
if (result == nullptr) {
return BAD_VALUE;
@@ -230,9 +233,12 @@ status_t GetInt64Value(const Json::Value& value, uint32_t /*tag_id*/,
if (value.isString()) {
errno = 0;
- auto int_value = strtol(value.asCString(), nullptr, 10);
+ 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(
@@ -245,7 +251,7 @@ status_t GetInt64Value(const Json::Value& value, uint32_t /*tag_id*/,
return OK;
}
-status_t GetFloatValue(const Json::Value& value, uint32_t /*tag_id*/,
+status_t GetFloatValue(const Json::Value& value, uint32_t tag_id,
float* result /*out*/) {
if (result == nullptr) {
return BAD_VALUE;
@@ -256,6 +262,9 @@ status_t GetFloatValue(const Json::Value& value, uint32_t /*tag_id*/,
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(
@@ -268,7 +277,7 @@ status_t GetFloatValue(const Json::Value& value, uint32_t /*tag_id*/,
return OK;
}
-status_t GetDoubleValue(const Json::Value& value, uint32_t /*tag_id*/,
+status_t GetDoubleValue(const Json::Value& value, uint32_t tag_id,
double* result /*out*/) {
if (result == nullptr) {
return BAD_VALUE;
@@ -279,6 +288,9 @@ status_t GetDoubleValue(const Json::Value& value, uint32_t /*tag_id*/,
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(
@@ -382,11 +394,11 @@ status_t InsertRationalTag(const Json::Value& json_value, uint32_t tag_id,
return ret;
}
-status_t EmulatedCameraProviderHwlImpl::ParseCharacteristics(
- const Json::Value& value) {
+uint32_t EmulatedCameraProviderHwlImpl::ParseCharacteristics(
+ const Json::Value& value, ssize_t id) {
if (!value.isObject()) {
ALOGE("%s: Configuration root is not an object", __FUNCTION__);
- return false;
+ return BAD_VALUE;
}
auto static_meta = HalCameraMetadata::Create(1, 10);
@@ -438,18 +450,27 @@ status_t EmulatedCameraProviderHwlImpl::ParseCharacteristics(
return BAD_VALUE;
}
- // TODO: This probably should not be expected by GCH from every HWL impl.
- // Adding anyhow to pass CTS
+ // 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);
- static_metadata_.push_back(std::move(static_meta));
+ 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 OK;
+ return id;
}
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;
+ static_metadata_.resize(ARRAY_SIZE(kConfigurationFileLocation));
+ size_t logical_id = 0;
for (const auto& config_path : kConfigurationFileLocation) {
if (!android::base::ReadFileToString(config_path, &config)) {
ALOGW("%s: Could not open configuration file: %s", __FUNCTION__,
@@ -465,10 +486,57 @@ status_t EmulatedCameraProviderHwlImpl::Initialize() {
return BAD_VALUE;
}
- auto ret = ParseCharacteristics(root);
- if (ret != OK) {
- return ret;
+ 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<uint32_t>());
+ if (root.size() >= 3) {
+ camera_id_map_[logical_id].reserve(root.size() - 1);
+ while (device_iter != root.end()) {
+ auto physical_id = ParseCharacteristics(*device_iter, /*id*/ -1);
+ if (physical_id < 0) {
+ return physical_id;
+ }
+ camera_id_map_[logical_id].push_back(physical_id);
+
+ device_iter++;
+ }
+
+ auto physical_devices = std::make_unique<PhysicalDeviceMap>();
+ for (const auto& physical_device_id : camera_id_map_[logical_id]) {
+ physical_devices->emplace(
+ physical_device_id,
+ HalCameraMetadata::Clone(
+ static_metadata_[physical_device_id].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<uint32_t>());
}
+
+ logical_id++;
}
return OK;
@@ -499,26 +567,27 @@ status_t EmulatedCameraProviderHwlImpl::GetVisibleCameraIds(
return BAD_VALUE;
}
- for (size_t cameraId = 0; cameraId < static_metadata_.size(); cameraId++) {
- camera_ids->push_back(cameraId);
+ for (const auto& device : camera_id_map_) {
+ camera_ids->push_back(device.first);
}
return OK;
}
status_t EmulatedCameraProviderHwlImpl::CreateCameraDeviceHwl(
- uint32_t cameraId, std::unique_ptr<CameraDeviceHwl>* camera_device_hwl) {
+ uint32_t camera_id, std::unique_ptr<CameraDeviceHwl>* camera_device_hwl) {
if (camera_device_hwl == nullptr) {
ALOGE("%s: camera_device_hwl is nullptr.", __FUNCTION__);
return BAD_VALUE;
}
- if (cameraId >= static_metadata_.size()) {
+ 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<HalCameraMetadata> meta =
- HalCameraMetadata::Clone(static_metadata_[cameraId].get());
+ HalCameraMetadata::Clone(static_metadata_[camera_id].get());
std::shared_ptr<EmulatedTorchState> torch_state;
camera_metadata_ro_entry entry;
@@ -531,11 +600,17 @@ status_t EmulatedCameraProviderHwlImpl::CreateCameraDeviceHwl(
}
if (flash_supported) {
- torch_state = std::make_shared<EmulatedTorchState>(cameraId, torch_cb_);
+ torch_state = std::make_shared<EmulatedTorchState>(camera_id, torch_cb_);
}
+ auto physical_devices = std::make_unique<PhysicalDeviceMap>();
+ for (const auto& physical_device_id : camera_id_map_[camera_id]) {
+ physical_devices->emplace(
+ physical_device_id,
+ HalCameraMetadata::Clone(static_metadata_[physical_device_id].get()));
+ }
*camera_device_hwl = EmulatedCameraDeviceHwlImpl::Create(
- cameraId, std::move(meta), torch_state);
+ 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;
@@ -551,9 +626,8 @@ status_t EmulatedCameraProviderHwlImpl::CreateBufferAllocatorHwl(
return BAD_VALUE;
}
- // TODO: Initialize an emulated buffer allocator
-
- return OK;
+ // Currently not supported
+ return INVALID_OPERATION;
}
} // namespace android
diff --git a/devices/EmulatedCamera/hwl/EmulatedCameraProviderHWLImpl.h b/devices/EmulatedCamera/hwl/EmulatedCameraProviderHWLImpl.h
index 5acb3a4..8904795 100644
--- a/devices/EmulatedCamera/hwl/EmulatedCameraProviderHWLImpl.h
+++ b/devices/EmulatedCamera/hwl/EmulatedCameraProviderHWLImpl.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013-2019 The Android Open Source Project
+ * 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.
@@ -62,12 +62,15 @@ class EmulatedCameraProviderHwlImpl : public CameraProviderHwl {
private:
status_t Initialize();
- status_t ParseCharacteristics(const Json::Value& root);
+ uint32_t ParseCharacteristics(const Json::Value& root, ssize_t id);
status_t GetTagFromName(const char* name, uint32_t* tag);
static const char* kConfigurationFileLocation[];
std::vector<std::unique_ptr<HalCameraMetadata>> static_metadata_;
+ // Logical to physical camera Id mapping. Empty value vector in case
+ // of regular non-logical device.
+ std::unordered_map<uint32_t, std::vector<uint32_t>> camera_id_map_;
HwlTorchModeStatusChangeFunc torch_cb_;
};
diff --git a/devices/EmulatedCamera/hwl/EmulatedLogicalRequestState.cpp b/devices/EmulatedCamera/hwl/EmulatedLogicalRequestState.cpp
new file mode 100644
index 0000000..ec7d0fb
--- /dev/null
+++ b/devices/EmulatedCamera/hwl/EmulatedLogicalRequestState.cpp
@@ -0,0 +1,283 @@
+/*
+ * 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_TAG "EmulatedLogicalState"
+#define ATRACE_TAG ATRACE_TAG_CAMERA
+
+#include "EmulatedLogicalRequestState.h"
+
+#include <log/log.h>
+
+#include "vendor_tag_defs.h"
+
+namespace android {
+
+EmulatedLogicalRequestState::EmulatedLogicalRequestState(uint32_t camera_id)
+ : logical_camera_id_(camera_id),
+ logical_request_state_(std::make_unique<EmulatedRequestState>(camera_id)) {
+}
+
+EmulatedLogicalRequestState::~EmulatedLogicalRequestState() {
+}
+
+status_t EmulatedLogicalRequestState::Initialize(
+ std::unique_ptr<HalCameraMetadata> static_meta,
+ PhysicalDeviceMapPtr physical_devices) {
+ if ((physical_devices.get() != nullptr) && (!physical_devices->empty())) {
+ physical_device_map_ = std::move(physical_devices);
+ // If possible map the available focal lengths to individual physical devices
+ camera_metadata_ro_entry_t logical_entry, physical_entry;
+ auto ret = static_meta->Get(ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS,
+ &logical_entry);
+ if ((ret == OK) && (logical_entry.count > 1)) {
+ for (size_t i = 0; i < logical_entry.count; i++) {
+ for (const auto& it : *physical_device_map_) {
+ ret = it.second->Get(ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS,
+ &physical_entry);
+ if ((ret == OK) && (physical_entry.count > 0)) {
+ if (logical_entry.data.f[i] == physical_entry.data.f[0]) {
+ physical_focal_length_map_[physical_entry.data.f[0]] = it.first;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if (physical_focal_length_map_.size() > 1) {
+ is_logical_device_ = true;
+ current_focal_length_ = logical_entry.data.f[0];
+ for (const auto& it : *physical_device_map_) {
+ std::unique_ptr<EmulatedRequestState> physical_request_state =
+ std::make_unique<EmulatedRequestState>(it.first);
+ auto ret = physical_request_state->Initialize(
+ HalCameraMetadata::Clone(it.second.get()));
+ if (ret != OK) {
+ ALOGE("%s: Physical device: %u request state initialization failed!",
+ __FUNCTION__, it.first);
+ return ret;
+ }
+ physical_request_states_.emplace(it.first,
+ std::move(physical_request_state));
+ }
+ }
+ }
+
+ return logical_request_state_->Initialize(std::move(static_meta));
+}
+
+status_t EmulatedLogicalRequestState::GetDefaultRequest(
+ RequestTemplate type,
+ std::unique_ptr<HalCameraMetadata>* default_settings /*out*/) {
+ return logical_request_state_->GetDefaultRequest(type, default_settings);
+};
+
+std::unique_ptr<HwlPipelineResult>
+EmulatedLogicalRequestState::InitializeLogicalResult(uint32_t pipeline_id,
+ uint32_t frame_number) {
+ auto ret = logical_request_state_->InitializeResult(pipeline_id, frame_number);
+ if (is_logical_device_) {
+ if ((physical_camera_output_ids_.get() != nullptr) &&
+ (!physical_camera_output_ids_->empty())) {
+ ret->physical_camera_results.reserve(physical_camera_output_ids_->size());
+ for (const auto& it : *physical_camera_output_ids_) {
+ ret->physical_camera_results[it] =
+ std::move(physical_request_states_[it]
+ ->InitializeResult(pipeline_id, frame_number)
+ ->result_metadata);
+ }
+ }
+ auto physical_device_id =
+ std::to_string(physical_focal_length_map_[current_focal_length_]);
+ std::vector<uint8_t> result;
+ result.reserve(physical_device_id.size() + 1);
+ result.insert(result.end(), physical_device_id.begin(),
+ physical_device_id.end());
+ result.push_back('\0');
+
+ ret->result_metadata->Set(ANDROID_LOGICAL_MULTI_CAMERA_ACTIVE_PHYSICAL_ID,
+ result.data(), result.size());
+ }
+
+ return ret;
+}
+
+status_t EmulatedLogicalRequestState::InitializeLogicalSettings(
+ std::unique_ptr<HalCameraMetadata> request_settings,
+ std::unique_ptr<std::set<uint32_t>> physical_camera_output_ids,
+ EmulatedSensor::LogicalCameraSettings* logical_settings /*out*/) {
+ if (logical_settings == nullptr) {
+ return BAD_VALUE;
+ }
+
+ // All logical and physical devices can potentially receive individual client
+ // requests (Currently this is not the case due to HWL API limitations).
+ // The emulated sensor can adapt its characteristics and apply most of them
+ // independently however the frame duration needs to be the same across all
+ // settings.
+ // Track the maximum frame duration and override this value at the end for all
+ // logical settings.
+ nsecs_t max_frame_duration = 0;
+ if (is_logical_device_) {
+ std::swap(physical_camera_output_ids_, physical_camera_output_ids);
+
+ for (const auto& physical_request_state : physical_request_states_) {
+ // All physical devices will receive requests and will keep
+ // updating their respective request state.
+ // However only physical devices referenced by client need to propagate
+ // and apply their settings.
+ EmulatedSensor::SensorSettings physical_sensor_settings;
+ auto ret = physical_request_state.second->InitializeSensorSettings(
+ HalCameraMetadata::Clone(request_settings.get()),
+ &physical_sensor_settings);
+ if (ret != OK) {
+ ALOGE(
+ "%s: Initialization of physical sensor settings for device id: %u "
+ "failed!",
+ __FUNCTION__, physical_request_state.first);
+ return ret;
+ }
+
+ if (physical_camera_output_ids_->find(physical_request_state.first) !=
+ physical_camera_output_ids_->end()) {
+ logical_settings->emplace(physical_request_state.first,
+ physical_sensor_settings);
+ if (max_frame_duration < physical_sensor_settings.exposure_time) {
+ max_frame_duration = physical_sensor_settings.exposure_time;
+ }
+ }
+ }
+
+ camera_metadata_ro_entry entry;
+ auto stat = request_settings->Get(ANDROID_LENS_FOCAL_LENGTH, &entry);
+ if ((stat == OK) && (entry.count == 1)) {
+ if (physical_focal_length_map_.find(entry.data.f[0]) !=
+ physical_focal_length_map_.end()) {
+ current_focal_length_ = entry.data.f[0];
+ } else {
+ ALOGE("%s: Unsupported focal length set: %5.2f, re-using older value!",
+ __FUNCTION__, entry.data.f[0]);
+ }
+ } else {
+ ALOGW("%s: Focal length absent from request, re-using older value!",
+ __FUNCTION__);
+ }
+ }
+
+ EmulatedSensor::SensorSettings sensor_settings;
+ auto ret = logical_request_state_->InitializeSensorSettings(
+ std::move(request_settings), &sensor_settings);
+ logical_settings->emplace(logical_camera_id_, sensor_settings);
+ if (max_frame_duration < sensor_settings.exposure_time) {
+ max_frame_duration = sensor_settings.exposure_time;
+ }
+
+ for (auto it : *logical_settings) {
+ it.second.frame_duration = max_frame_duration;
+ }
+
+ return ret;
+}
+
+std::unique_ptr<HalCameraMetadata>
+EmulatedLogicalRequestState::AdaptLogicalCharacteristics(
+ std::unique_ptr<HalCameraMetadata> logical_chars,
+ PhysicalDeviceMapPtr physical_devices) {
+ if ((logical_chars.get() == nullptr) || (physical_devices.get() == nullptr)) {
+ return nullptr;
+ }
+
+ // Update 'android.logicalMultiCamera.physicalIds' according to the newly
+ // assigned physical ids.
+ // Additionally if possible try to emulate a logical camera device backed by
+ // physical devices with different focal lengths. Usually real logical
+ // cameras like that will have device specific logic to switch between
+ // physical sensors. Unfortunately we cannot infer this behavior using only
+ // static camera characteristics. Instead of this, detect the different
+ // focal lengths and update the logical
+ // "android.lens.info.availableFocalLengths" accordingly.
+ std::vector<uint8_t> physical_ids;
+ std::set<float> focal_lengths;
+ camera_metadata_ro_entry_t entry;
+ for (const auto& physical_device : *physical_devices) {
+ auto physical_id = std::to_string(physical_device.first);
+ physical_ids.insert(physical_ids.end(), physical_id.begin(),
+ physical_id.end());
+ physical_ids.push_back('\0');
+ auto ret = physical_device.second->Get(
+ ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS, &entry);
+ if ((ret == OK) && (entry.count > 0)) {
+ focal_lengths.insert(entry.data.f, entry.data.f + entry.count);
+ }
+ }
+ logical_chars->Set(ANDROID_LOGICAL_MULTI_CAMERA_PHYSICAL_IDS,
+ physical_ids.data(), physical_ids.size());
+
+ if (focal_lengths.size() > 1) {
+ std::vector<float> focal_buffer;
+ focal_buffer.reserve(focal_lengths.size());
+ focal_buffer.insert(focal_buffer.end(), focal_lengths.begin(),
+ focal_lengths.end());
+ logical_chars->Set(ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS,
+ focal_buffer.data(), focal_buffer.size());
+
+ // Possibly needs to be removed at some later point:
+ int32_t default_physical_id = physical_devices->begin()->first;
+ logical_chars->Set(google_camera_hal::kLogicalCamDefaultPhysicalId,
+ &default_physical_id, 1);
+
+ logical_chars->Get(ANDROID_REQUEST_AVAILABLE_RESULT_KEYS, &entry);
+ std::set<int32_t> keys(entry.data.i32, entry.data.i32 + entry.count);
+ keys.emplace(ANDROID_LENS_FOCAL_LENGTH);
+ keys.emplace(ANDROID_LOGICAL_MULTI_CAMERA_ACTIVE_PHYSICAL_ID);
+ std::vector<int32_t> keys_buffer(keys.begin(), keys.end());
+ logical_chars->Set(ANDROID_REQUEST_AVAILABLE_RESULT_KEYS,
+ keys_buffer.data(), keys_buffer.size());
+
+ keys.clear();
+ keys_buffer.clear();
+ logical_chars->Get(ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS, &entry);
+ keys.insert(entry.data.i32, entry.data.i32 + entry.count);
+ // Due to API limitations we currently don't support individual physical requests
+ logical_chars->Erase(ANDROID_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS);
+ keys.erase(ANDROID_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS);
+ keys.emplace(ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS);
+ keys.emplace(ANDROID_LOGICAL_MULTI_CAMERA_PHYSICAL_IDS);
+ keys_buffer.insert(keys_buffer.end(), keys.begin(), keys.end());
+ logical_chars->Set(ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS,
+ keys_buffer.data(), keys_buffer.size());
+
+ keys.clear();
+ keys_buffer.clear();
+ logical_chars->Get(ANDROID_REQUEST_AVAILABLE_REQUEST_KEYS, &entry);
+ keys.insert(entry.data.i32, entry.data.i32 + entry.count);
+ keys.emplace(ANDROID_LENS_FOCAL_LENGTH);
+ keys_buffer.insert(keys_buffer.end(), keys.begin(), keys.end());
+ logical_chars->Set(ANDROID_REQUEST_AVAILABLE_REQUEST_KEYS,
+ keys_buffer.data(), keys_buffer.size());
+ } else {
+ ALOGW(
+ "%s: The logical camera doesn't support different focal lengths. "
+ "Emulation "
+ "could be"
+ " very limited in this case!",
+ __FUNCTION__);
+ }
+
+ return logical_chars;
+}
+
+} // namespace android
diff --git a/devices/EmulatedCamera/hwl/EmulatedLogicalRequestState.h b/devices/EmulatedCamera/hwl/EmulatedLogicalRequestState.h
new file mode 100644
index 0000000..93b4c04
--- /dev/null
+++ b/devices/EmulatedCamera/hwl/EmulatedLogicalRequestState.h
@@ -0,0 +1,72 @@
+/*
+ * 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.
+ */
+
+#ifndef EMULATOR_CAMERA_HAL_LOGICAL_REQUEST_STATE_H
+#define EMULATOR_CAMERA_HAL_LOGICAL_REQUEST_STATE_H
+
+#include "EmulatedRequestState.h"
+#include "hwl_types.h"
+#include "utils/HWLUtils.h"
+
+namespace android {
+
+using google_camera_hal::HalCameraMetadata;
+
+class EmulatedLogicalRequestState {
+ public:
+ EmulatedLogicalRequestState(uint32_t camera_id);
+ virtual ~EmulatedLogicalRequestState();
+
+ status_t Initialize(std::unique_ptr<HalCameraMetadata> static_meta,
+ PhysicalDeviceMapPtr physical_device_map);
+
+ status_t GetDefaultRequest(
+ RequestTemplate type,
+ std::unique_ptr<HalCameraMetadata>* default_settings /*out*/);
+
+ std::unique_ptr<HwlPipelineResult> InitializeLogicalResult(
+ uint32_t pipeline_id, uint32_t frame_number);
+
+ status_t InitializeLogicalSettings(
+ std::unique_ptr<HalCameraMetadata> request_settings,
+ std::unique_ptr<std::set<uint32_t>> physical_camera_output_ids,
+ EmulatedSensor::LogicalCameraSettings* logical_settings /*out*/);
+
+ static std::unique_ptr<HalCameraMetadata> AdaptLogicalCharacteristics(
+ std::unique_ptr<HalCameraMetadata> logical_chars,
+ PhysicalDeviceMapPtr physical_devices);
+
+ private:
+ uint32_t logical_camera_id_ = 0;
+ std::unique_ptr<EmulatedRequestState> logical_request_state_;
+ bool is_logical_device_ = false;
+ std::unique_ptr<std::set<uint32_t>> physical_camera_output_ids_;
+ PhysicalDeviceMapPtr physical_device_map_;
+ // Maps a physical device id to its respective request state
+ std::unordered_map<uint32_t, std::unique_ptr<EmulatedRequestState>>
+ physical_request_states_;
+ // Maps particular focal length to physical device id
+ std::unordered_map<float, uint32_t> physical_focal_length_map_;
+ float current_focal_length_ = 0.f;
+
+ EmulatedLogicalRequestState(const EmulatedLogicalRequestState&) = delete;
+ EmulatedLogicalRequestState& operator=(const EmulatedLogicalRequestState&) =
+ delete;
+};
+
+} // namespace android
+
+#endif // EMULATOR_CAMERA_HAL_LOGICAL_REQUEST_STATE_H
diff --git a/devices/EmulatedCamera/hwl/EmulatedRequestProcessor.cpp b/devices/EmulatedCamera/hwl/EmulatedRequestProcessor.cpp
index 4d6b61c..5077f85 100644
--- a/devices/EmulatedCamera/hwl/EmulatedRequestProcessor.cpp
+++ b/devices/EmulatedCamera/hwl/EmulatedRequestProcessor.cpp
@@ -38,7 +38,7 @@ EmulatedRequestProcessor::EmulatedRequestProcessor(uint32_t camera_id,
sp<EmulatedSensor> sensor)
: camera_id_(camera_id),
sensor_(sensor),
- request_state_(std::make_unique<EmulatedRequestState>(camera_id)) {
+ request_state_(std::make_unique<EmulatedLogicalRequestState>(camera_id)) {
ATRACE_CALL();
request_thread_ = std::thread([this] { this->RequestProcessorLoop(); });
}
@@ -271,7 +271,9 @@ std::unique_ptr<SensorBuffer> EmulatedRequestProcessor::CreateSensorBuffer(
buffer->pipeline_id = pipeline_id;
buffer->callback = callback;
buffer->frame_number = frame_number;
- buffer->camera_id = camera_id_;
+ buffer->camera_id = emulated_stream.is_physical_camera_stream
+ ? emulated_stream.physical_camera_id
+ : camera_id_;
buffer->is_input = stream.is_input;
// In case buffer processing is successful, flip this flag accordingly
buffer->stream_buffer.status = BufferStatus::kError;
@@ -339,29 +341,53 @@ void EmulatedRequestProcessor::RequestProcessorLoop() {
auto frame_number = request.output_buffers->at(0)->frame_number;
auto notify_callback = request.output_buffers->at(0)->callback;
auto pipeline_id = request.output_buffers->at(0)->pipeline_id;
- EmulatedSensor::SensorSettings settings;
-
- // Repeating requests usually include valid settings only during the
- // initial call. Afterwards an invalid settings pointer means that there
- // are no changes in the parameters and Hal should re-use the last valid
- // values.
- if (request.settings.get() != nullptr) {
- ret = request_state_->InitializeSensorSettings(
- HalCameraMetadata::Clone(request.settings.get()), &settings);
- last_settings_ = HalCameraMetadata::Clone(request.settings.get());
- } else {
- ret = request_state_->InitializeSensorSettings(
- HalCameraMetadata::Clone(last_settings_.get()), &settings);
- }
auto output_buffers = AcquireBuffers(request.output_buffers.get());
- if (!output_buffers->empty() && (ret == OK)) {
- auto result =
- request_state_->InitializeResult(pipeline_id, frame_number);
- auto input_buffers = AcquireBuffers(request.input_buffers.get());
- sensor_->SetCurrentRequest(settings, std::move(result),
- std::move(input_buffers),
- std::move(output_buffers));
+ auto input_buffers = AcquireBuffers(request.input_buffers.get());
+ if (!output_buffers->empty()) {
+ std::unique_ptr<EmulatedSensor::LogicalCameraSettings> logical_settings =
+ std::make_unique<EmulatedSensor::LogicalCameraSettings>();
+
+ std::unique_ptr<std::set<uint32_t>> physical_camera_output_ids =
+ std::make_unique<std::set<uint32_t>>();
+ for (const auto& it : *output_buffers) {
+ if (it->camera_id != camera_id_) {
+ physical_camera_output_ids->emplace(it->camera_id);
+ }
+ }
+
+ // Repeating requests usually include valid settings only during the
+ // initial call. Afterwards an invalid settings pointer means that
+ // there are no changes in the parameters and Hal should re-use the
+ // last valid values.
+ // TODO: Add support for individual physical camera requests.
+ if (request.settings.get() != nullptr) {
+ ret = request_state_->InitializeLogicalSettings(
+ HalCameraMetadata::Clone(request.settings.get()),
+ std::move(physical_camera_output_ids), logical_settings.get());
+ last_settings_ = HalCameraMetadata::Clone(request.settings.get());
+ } else {
+ ret = request_state_->InitializeLogicalSettings(
+ HalCameraMetadata::Clone(last_settings_.get()),
+ std::move(physical_camera_output_ids), logical_settings.get());
+ }
+
+ if (ret == OK) {
+ auto result = request_state_->InitializeLogicalResult(pipeline_id,
+ frame_number);
+ sensor_->SetCurrentRequest(
+ std::move(logical_settings), std::move(result),
+ std::move(input_buffers), std::move(output_buffers));
+ } else {
+ NotifyMessage msg{.type = MessageType::kError,
+ .message.error = {
+ .frame_number = frame_number,
+ .error_stream_id = -1,
+ .error_code = ErrorCode::kErrorResult,
+ }};
+
+ notify_callback.notify(pipeline_id, msg);
+ }
} else {
// No further processing is needed, just fail the result which will
// complete this request.
@@ -386,9 +412,11 @@ void EmulatedRequestProcessor::RequestProcessorLoop() {
}
status_t EmulatedRequestProcessor::Initialize(
- std::unique_ptr<HalCameraMetadata> static_meta) {
+ std::unique_ptr<HalCameraMetadata> static_meta,
+ PhysicalDeviceMapPtr physical_devices) {
std::lock_guard<std::mutex> lock(process_mutex_);
- return request_state_->Initialize(std::move(static_meta));
+ return request_state_->Initialize(std::move(static_meta),
+ std::move(physical_devices));
}
status_t EmulatedRequestProcessor::GetDefaultRequest(
diff --git a/devices/EmulatedCamera/hwl/EmulatedRequestProcessor.h b/devices/EmulatedCamera/hwl/EmulatedRequestProcessor.h
index 5595111..1eb609f 100644
--- a/devices/EmulatedCamera/hwl/EmulatedRequestProcessor.h
+++ b/devices/EmulatedCamera/hwl/EmulatedRequestProcessor.h
@@ -22,7 +22,7 @@
#include <queue>
#include <thread>
-#include "EmulatedRequestState.h"
+#include "EmulatedLogicalRequestState.h"
#include "EmulatedSensor.h"
#include "hwl_types.h"
@@ -56,7 +56,7 @@ struct PendingRequest {
class EmulatedRequestProcessor {
public:
- EmulatedRequestProcessor(uint32_t cameraId, sp<EmulatedSensor> sensor);
+ EmulatedRequestProcessor(uint32_t camera_id, sp<EmulatedSensor> sensor);
virtual ~EmulatedRequestProcessor();
// Process given pipeline requests and invoke the respective callback in a
@@ -71,7 +71,8 @@ class EmulatedRequestProcessor {
status_t Flush();
- status_t Initialize(std::unique_ptr<HalCameraMetadata> static_meta);
+ status_t Initialize(std::unique_ptr<HalCameraMetadata> static_meta,
+ PhysicalDeviceMapPtr physical_devices);
private:
void RequestProcessorLoop();
@@ -109,7 +110,7 @@ class EmulatedRequestProcessor {
std::queue<PendingRequest> pending_requests_;
uint32_t camera_id_;
sp<EmulatedSensor> sensor_;
- std::unique_ptr<EmulatedRequestState>
+ std::unique_ptr<EmulatedLogicalRequestState>
request_state_; // Stores and handles 3A and related camera states.
std::unique_ptr<HalCameraMetadata> last_settings_;
diff --git a/devices/EmulatedCamera/hwl/EmulatedRequestState.cpp b/devices/EmulatedCamera/hwl/EmulatedRequestState.cpp
index 5ed2efd..febdfb5 100644
--- a/devices/EmulatedCamera/hwl/EmulatedRequestState.cpp
+++ b/devices/EmulatedCamera/hwl/EmulatedRequestState.cpp
@@ -39,6 +39,7 @@ const std::set<uint8_t> EmulatedRequestState::kSupportedCapabilites = {
ANDROID_REQUEST_AVAILABLE_CAPABILITIES_DEPTH_OUTPUT,
ANDROID_REQUEST_AVAILABLE_CAPABILITIES_PRIVATE_REPROCESSING,
ANDROID_REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING,
+ ANDROID_REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA,
};
const std::set<uint8_t> EmulatedRequestState::kSupportedHWLevels = {
@@ -2238,7 +2239,6 @@ status_t EmulatedRequestState::InitializeLensDefaults() {
ret = static_metadata_->Get(ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS, &entry);
if ((ret == OK) && (entry.count > 0)) {
- // TODO: add support for multiple focal lengths
focal_length_ = entry.data.f[0];
} else {
ALOGE("%s: No available focal length!", __FUNCTION__);
diff --git a/devices/EmulatedCamera/hwl/EmulatedScene.cpp b/devices/EmulatedCamera/hwl/EmulatedScene.cpp
index 7810398..26784d1 100644
--- a/devices/EmulatedCamera/hwl/EmulatedScene.cpp
+++ b/devices/EmulatedCamera/hwl/EmulatedScene.cpp
@@ -85,20 +85,7 @@ const uint8_t EmulatedScene::kScene[EmulatedScene::kSceneWidth *
EmulatedScene::EmulatedScene(int sensor_width_px, int sensor_height_px,
float sensor_sensitivity)
- : sensor_width_(sensor_width_px),
- sensor_height_(sensor_height_px),
- hour_(12),
- exposure_duration_(0.033f),
- sensor_sensitivity_(sensor_sensitivity) {
- // Map scene to sensor pixels
- if (sensor_width_ > sensor_height_) {
- map_div_ = (sensor_width_ / (kSceneWidth + 1)) + 1;
- } else {
- map_div_ = (sensor_height_ / (kSceneHeight + 1)) + 1;
- }
- offset_x_ = (kSceneWidth * map_div_ - sensor_width_) / 2;
- offset_y_ = (kSceneHeight * map_div_ - sensor_height_) / 2;
-
+ : hour_(12), exposure_duration_(0.033f) {
// Assume that sensor filters are sRGB primaries to start
filter_r_[0] = 3.2406f;
filter_r_[1] = -1.5372f;
@@ -112,11 +99,30 @@ EmulatedScene::EmulatedScene(int sensor_width_px, int sensor_height_px,
filter_b_[0] = 0.0557f;
filter_b_[1] = -0.2040f;
filter_b_[2] = 1.0570f;
+
+ Initialize(sensor_width_px, sensor_height_px, sensor_sensitivity);
}
EmulatedScene::~EmulatedScene() {
}
+void EmulatedScene::Initialize(int sensor_width_px, int sensor_height_px,
+ float sensor_sensitivity) {
+ sensor_width_ = sensor_width_px;
+ sensor_height_ = sensor_height_px;
+ sensor_sensitivity_ = sensor_sensitivity;
+
+ // Map scene to sensor pixels
+ if (sensor_width_ > sensor_height_) {
+ map_div_ = (sensor_width_ / (kSceneWidth + 1)) + 1;
+ }
+ else {
+ map_div_ = (sensor_height_ / (kSceneHeight + 1)) + 1;
+ }
+ offset_x_ = (kSceneWidth * map_div_ - sensor_width_) / 2;
+ offset_y_ = (kSceneHeight * map_div_ - sensor_height_) / 2;
+}
+
void EmulatedScene::SetColorFilterXYZ(float rX, float rY, float rZ, float grX,
float grY, float grZ, float gbX, float gbY,
float gbZ, float bX, float bY, float bZ) {
diff --git a/devices/EmulatedCamera/hwl/EmulatedScene.h b/devices/EmulatedCamera/hwl/EmulatedScene.h
index 58473e4..a61d735 100644
--- a/devices/EmulatedCamera/hwl/EmulatedScene.h
+++ b/devices/EmulatedCamera/hwl/EmulatedScene.h
@@ -36,6 +36,9 @@ class EmulatedScene {
float sensor_sensitivity);
~EmulatedScene();
+ void Initialize(int sensor_width_px, int sensor_height_px,
+ float sensor_sensitivity);
+
// Set the filter coefficients for the red, green, and blue filters on the
// sensor. Used as an optimization to pre-calculate various illuminance
// values. Two different green filters can be provided, to account for
@@ -56,8 +59,8 @@ class EmulatedScene {
void SetExposureDuration(float seconds);
// Calculate scene information for current hour and the time offset since
- // the hour. Must be called at least once before calling getLuminousExposure.
- // Resets pixel readout location to 0,0
+ // the hour. Must be called at least once before calling
+ // getLuminousExposure. Resets pixel readout location to 0,0
void CalculateScene(nsecs_t time);
// Set sensor pixel readout location.
@@ -170,7 +173,7 @@ class EmulatedScene {
static const uint8_t kMaterialsFlags[NUM_MATERIALS];
static const uint8_t kScene[];
-};
+ };
} // namespace android
diff --git a/devices/EmulatedCamera/hwl/EmulatedSensor.cpp b/devices/EmulatedCamera/hwl/EmulatedSensor.cpp
index babcb10..116263e 100644
--- a/devices/EmulatedCamera/hwl/EmulatedSensor.cpp
+++ b/devices/EmulatedCamera/hwl/EmulatedSensor.cpp
@@ -57,6 +57,9 @@ 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 =
@@ -328,45 +331,45 @@ bool EmulatedSensor::IsStreamCombinationSupported(
return true;
}
-status_t EmulatedSensor::StartUp(SensorCharacteristics characteristics) {
- ALOGV("%s: E", __FUNCTION__);
+status_t EmulatedSensor::StartUp(
+ uint32_t logical_camera_id,
+ std::unique_ptr<LogicalCharacteristics> logical_chars) {
+ if (isRunning()) {
+ return OK;
+ }
- if (!AreCharacteristicsSupported(characteristics)) {
- ALOGE("%s: Sensor characteristics not supported!", __FUNCTION__);
+ if (logical_chars.get() == nullptr) {
return BAD_VALUE;
}
- std::unique_ptr<ExifUtils> exif_utils(ExifUtils::Create(characteristics));
+ auto device_chars = logical_chars->find(logical_camera_id);
+ if (device_chars == logical_chars->end()) {
+ ALOGE(
+ "%s: Logical camera id: %u absent from logical camera characteristics!",
+ __FUNCTION__, logical_camera_id);
+ return BAD_VALUE;
+ }
- if (isRunning()) {
- return OK;
+ for (const auto& it : *logical_chars) {
+ if (!AreCharacteristicsSupported(it.second)) {
+ ALOGE("%s: Sensor characteristics for camera id: %u not supported!",
+ __FUNCTION__, it.first);
+ return BAD_VALUE;
+ }
}
- chars_ = characteristics;
- scene_ = std::make_unique<EmulatedScene>(chars_.width, chars_.height,
+ logical_camera_id_ = logical_camera_id;
+ chars_ = std::move(logical_chars);
+ scene_ = std::make_unique<EmulatedScene>(device_chars->second.width,
+ device_chars->second.height,
kElectronsPerLuxSecond);
- scene_->SetColorFilterXYZ(
- chars_.color_filter.rX, chars_.color_filter.rY, chars_.color_filter.rZ,
- chars_.color_filter.grX, chars_.color_filter.grY, chars_.color_filter.grZ,
- chars_.color_filter.gbX, chars_.color_filter.gbY, chars_.color_filter.gbZ,
- chars_.color_filter.bX, chars_.color_filter.bY, chars_.color_filter.bZ);
- row_readout_time_ = chars_.frame_duration_range[0] / chars_.height;
- base_gain_factor_ =
- (float)chars_.max_raw_value / EmulatedSensor::kSaturationElectrons;
- jpeg_compressor_ = std::make_unique<JpegCompressor>(std::move(exif_utils));
-
- if ((chars_.lens_shading_map_size[0] > 0) &&
- (chars_.lens_shading_map_size[1] > 0)) {
- // Perfect lens, no actual shading needed.
- lens_shading_map_.resize(
- chars_.lens_shading_map_size[0] * chars_.lens_shading_map_size[1] * 4,
- 1.f);
- }
+ jpeg_compressor_ = std::make_unique<JpegCompressor>();
auto res = run(LOG_TAG, ANDROID_PRIORITY_URGENT_DISPLAY);
if (res != OK) {
ALOGE("Unable to start up sensor capture thread: %d", res);
}
+
return res;
}
@@ -379,12 +382,13 @@ status_t EmulatedSensor::ShutDown() {
return res;
}
-void EmulatedSensor::SetCurrentRequest(SensorSettings settings,
- std::unique_ptr<HwlPipelineResult> result,
- std::unique_ptr<Buffers> input_buffers,
- std::unique_ptr<Buffers> output_buffers) {
+void EmulatedSensor::SetCurrentRequest(
+ std::unique_ptr<LogicalCameraSettings> logical_settings,
+ std::unique_ptr<HwlPipelineResult> result,
+ std::unique_ptr<Buffers> input_buffers,
+ std::unique_ptr<Buffers> output_buffers) {
Mutex::Autolock lock(control_mutex_);
- current_settings_ = settings;
+ 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);
@@ -415,8 +419,7 @@ status_t EmulatedSensor::Flush() {
// First recreate the jpeg compressor. This will abort any ongoing processing
// and flush any pending jobs.
- std::unique_ptr<ExifUtils> exif_utils(ExifUtils::Create(chars_));
- jpeg_compressor_ = std::make_unique<JpegCompressor>(std::move(exif_utils));
+ jpeg_compressor_ = std::make_unique<JpegCompressor>();
// Then return any pending frames here
if ((current_input_buffers_.get() != nullptr) &&
@@ -464,11 +467,11 @@ bool EmulatedSensor::threadLoop() {
std::unique_ptr<Buffers> next_buffers;
std::unique_ptr<Buffers> next_input_buffer;
std::unique_ptr<HwlPipelineResult> next_result;
- SensorSettings settings;
+ std::unique_ptr<LogicalCameraSettings> settings;
HwlPipelineCallback callback = {nullptr, nullptr};
{
Mutex::Autolock lock(control_mutex_);
- settings = current_settings_;
+ 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_);
@@ -479,13 +482,16 @@ bool EmulatedSensor::threadLoop() {
vsync_.signal();
}
- if (settings.frame_duration == 0) {
- settings.frame_duration = EmulatedSensor::kSupportedFrameDurationRange[0];
+ auto frame_duration = EmulatedSensor::kSupportedFrameDurationRange[0];
+ // Frame duration must always be the same among all physical devices
+ if ((settings.get() != nullptr) && (!settings->empty())) {
+ frame_duration = settings->begin()->second.frame_duration;
}
+
nsecs_t start_real_time = systemTime();
// Stagefright cares about system time for timestamps, so base simulated
// time on that.
- nsecs_t frame_end_real_time = start_real_time + settings.frame_duration;
+ nsecs_t frame_end_real_time = start_real_time + frame_duration;
/**
* Stage 2: Capture new image
@@ -515,7 +521,7 @@ bool EmulatedSensor::threadLoop() {
}
}
- if (next_buffers != nullptr) {
+ if ((next_buffers != nullptr) && (settings != nullptr)) {
callback = next_buffers->at(0)->callback;
if (callback.notify != nullptr) {
NotifyMessage msg{
@@ -525,49 +531,52 @@ bool EmulatedSensor::threadLoop() {
.timestamp_ns = static_cast<uint64_t>(next_capture_time_)}};
callback.notify(next_result->pipeline_id, msg);
}
- ALOGVV("Starting next capture: Exposure: %f ms, gain: %d",
- ns2ms(settings.exposureTime), gain);
- scene_->SetExposureDuration((float)settings.exposure_time / 1e9);
- scene_->CalculateScene(next_capture_time_);
- next_result->result_metadata->Set(ANDROID_SENSOR_TIMESTAMP,
- &next_capture_time_, 1);
- if (settings.lens_shading_map_mode ==
- ANDROID_STATISTICS_LENS_SHADING_MAP_MODE_ON) {
- next_result->result_metadata->Set(ANDROID_STATISTICS_LENS_SHADING_MAP,
- lens_shading_map_.data(),
- lens_shading_map_.size());
- }
- if (settings.report_neutral_color_point) {
- next_result->result_metadata->Set(ANDROID_SENSOR_NEUTRAL_COLOR_POINT,
- kNeutralColorPoint,
- ARRAY_SIZE(kNeutralColorPoint));
- }
- if (settings.report_green_split) {
- next_result->result_metadata->Set(ANDROID_SENSOR_GREEN_SPLIT,
- &kGreenSplit, 1);
- }
- if (settings.report_noise_profile) {
- // TODO: pass the results as parameter to capture instead of re-calculating
- float total_gain = settings.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};
- next_result->result_metadata->Set(ANDROID_SENSOR_NOISE_PROFILE,
- noise_profile,
- ARRAY_SIZE(noise_profile));
- }
-
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;
+ }
+
+ ALOGVV("Starting next capture: Exposure: %" PRIu64 " ms, gain: %d",
+ ns2ms(device_settings->second.exposure_time),
+ device_settings->second.gain);
+
+ scene_->Initialize(device_chars->second.width,
+ device_chars->second.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_->CalculateScene(next_capture_time_);
+
(*b)->stream_buffer.status = BufferStatus::kOk;
switch ((*b)->format) {
case HAL_PIXEL_FORMAT_RAW16:
if (!reprocess_request) {
- CaptureRaw((*b)->plane.img.img, settings.gain, (*b)->width);
+ CaptureRaw((*b)->plane.img.img, device_settings->second.gain,
+ (*b)->width, device_chars->second);
} else {
ALOGE("%s: Reprocess requests with output format %x no supported!",
__FUNCTION__, (*b)->format);
@@ -577,7 +586,8 @@ bool EmulatedSensor::threadLoop() {
case HAL_PIXEL_FORMAT_RGB_888:
if (!reprocess_request) {
CaptureRGB((*b)->plane.img.img, (*b)->width, (*b)->height,
- (*b)->plane.img.stride, RGBLayout::RGB, settings.gain);
+ (*b)->plane.img.stride, RGBLayout::RGB,
+ device_settings->second.gain, device_chars->second);
} else {
ALOGE("%s: Reprocess requests with output format %x no supported!",
__FUNCTION__, (*b)->format);
@@ -587,7 +597,8 @@ bool EmulatedSensor::threadLoop() {
case HAL_PIXEL_FORMAT_RGBA_8888:
if (!reprocess_request) {
CaptureRGB((*b)->plane.img.img, (*b)->width, (*b)->height,
- (*b)->plane.img.stride, RGBLayout::RGBA, settings.gain);
+ (*b)->plane.img.stride, RGBLayout::RGBA,
+ device_settings->second.gain, device_chars->second);
} else {
ALOGE("%s: Reprocess requests with output format %x no supported!",
__FUNCTION__, (*b)->format);
@@ -622,14 +633,17 @@ bool EmulatedSensor::threadLoop() {
.height = jpeg_input->height,
.planes = jpeg_input->yuv_planes};
- auto ret = ProcessYUV420(yuv_input, yuv_output, settings.gain,
- reprocess_request);
+ auto ret = ProcessYUV420(yuv_input, yuv_output,
+ device_settings->second.gain,
+ reprocess_request, device_chars->second);
if (ret != 0) {
(*b)->stream_buffer.status = BufferStatus::kError;
break;
}
auto jpeg_job = std::make_unique<JpegYUV420Job>();
+ jpeg_job->exif_utils = std::unique_ptr<ExifUtils>(
+ 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.
@@ -659,8 +673,9 @@ bool EmulatedSensor::threadLoop() {
YUV420Frame yuv_output{.width = (*b)->width,
.height = (*b)->height,
.planes = (*b)->plane.img_y_crcb};
- auto ret = ProcessYUV420(yuv_input, yuv_output, settings.gain,
- reprocess_request);
+ auto ret =
+ ProcessYUV420(yuv_input, yuv_output, device_settings->second.gain,
+ reprocess_request, device_chars->second);
if (ret != 0) {
(*b)->stream_buffer.status = BufferStatus::kError;
}
@@ -668,8 +683,9 @@ bool EmulatedSensor::threadLoop() {
case HAL_PIXEL_FORMAT_Y16:
if (!reprocess_request) {
if ((*b)->dataSpace == HAL_DATASPACE_DEPTH) {
- CaptureDepth((*b)->plane.img.img, settings.gain, (*b)->width,
- (*b)->height, (*b)->plane.img.stride);
+ CaptureDepth((*b)->plane.img.img, device_settings->second.gain,
+ (*b)->width, (*b)->height, (*b)->plane.img.stride,
+ device_chars->second);
} else {
ALOGE("%s: Format %x with dataspace %x is TODO", __FUNCTION__,
(*b)->format, (*b)->dataSpace);
@@ -699,14 +715,25 @@ bool EmulatedSensor::threadLoop() {
next_input_buffer->clear();
}
- if ((callback.process_pipeline_result != nullptr) &&
- (next_result.get() != nullptr) &&
- (next_result->result_metadata.get() != nullptr)) {
- callback.process_pipeline_result(std::move(next_result));
+ nsecs_t work_done_real_time = systemTime();
+ // 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));
}
+ work_done_real_time = systemTime();
ALOGVV("Sensor vertical blanking interval");
- nsecs_t work_done_real_time = systemTime();
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;
@@ -722,12 +749,120 @@ bool EmulatedSensor::threadLoop() {
ALOGVV("Frame cycle took %" PRIu64 " ms, target %" PRIu64 " ms",
ns2ms(end_real_time - start_real_time), ns2ms(frame_duration));
+ ReturnResults(callback, std::move(settings), std::move(next_result));
+
return true;
};
-void EmulatedSensor::CaptureRaw(uint8_t* img, uint32_t gain, uint32_t width) {
+void EmulatedSensor::ReturnResults(
+ HwlPipelineCallback callback,
+ std::unique_ptr<LogicalCameraSettings> settings,
+ std::unique_ptr<HwlPipelineResult> 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);
+ 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<float> 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_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 (!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;
+ }
+
+ // 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());
+ }
+ }
+ }
+
+ 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));
+ }
+}
+
+void EmulatedSensor::CaptureRaw(uint8_t* img, uint32_t gain, uint32_t width,
+ const SensorCharacteristics& chars) {
ATRACE_CALL();
- float total_gain = gain / 100.0 * base_gain_factor_;
+ 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;
@@ -736,10 +871,10 @@ void EmulatedSensor::CaptureRaw(uint8_t* img, uint32_t gain, uint32_t width) {
int bayer_select[4] = {EmulatedScene::R, EmulatedScene::Gr, EmulatedScene::Gb,
EmulatedScene::B};
scene_->SetReadoutPixel(0, 0);
- for (unsigned int y = 0; y < chars_.height; y++) {
+ for (unsigned int y = 0; y < chars.height; y++) {
int* bayer_row = bayer_select + (y & 0x1) * 2;
uint16_t* px = (uint16_t*)img + y * width;
- for (unsigned int x = 0; x < chars_.width; x++) {
+ for (unsigned int x = 0; x < chars.width; x++) {
uint32_t electron_count;
electron_count = scene_->GetPixelElectrons()[bayer_row[x & 0x1]];
@@ -751,7 +886,7 @@ void EmulatedSensor::CaptureRaw(uint8_t* img, uint32_t gain, uint32_t width) {
// 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;
+ (raw_count < chars.max_raw_value) ? raw_count : chars.max_raw_value;
// Calculate noise value
// TODO: Use more-correct Gaussian instead of uniform noise
@@ -760,7 +895,7 @@ void EmulatedSensor::CaptureRaw(uint8_t* img, uint32_t gain, uint32_t width) {
// 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[bayer_row[x & 0x1]];
+ raw_count += chars.black_level_pattern[bayer_row[x & 0x1]];
raw_count += noise_stddev * noise_sample;
*px++ = raw_count;
@@ -772,19 +907,19 @@ void EmulatedSensor::CaptureRaw(uint8_t* img, uint32_t gain, uint32_t width) {
}
void EmulatedSensor::CaptureRGB(uint8_t* img, uint32_t width, uint32_t height,
- uint32_t stride, RGBLayout layout,
- uint32_t gain) {
+ uint32_t stride, RGBLayout layout, uint32_t gain,
+ const SensorCharacteristics& chars) {
ATRACE_CALL();
- float total_gain = gain / 100.0 * base_gain_factor_;
+ 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_.width / width);
- uint32_t inc_v = ceil((float)chars_.height / height);
+ int scale64x = 64 * total_gain * 255 / chars.max_raw_value;
+ uint32_t inc_h = ceil((float)chars.width / width);
+ uint32_t inc_v = ceil((float)chars.height / height);
- for (unsigned int y = 0, outy = 0; y < chars_.height; y += inc_v, outy++) {
+ for (unsigned int y = 0, outy = 0; y < chars.height; y += inc_v, outy++) {
scene_->SetReadoutPixel(0, y);
uint8_t* px = img + outy * stride;
- for (unsigned int x = 0; x < chars_.width; x += inc_h) {
+ for (unsigned int x = 0; x < chars.width; x += inc_h) {
uint32_t r_count, g_count, b_count;
// TODO: Perfect demosaicing is a cheat
const uint32_t* pixel = scene_->GetPixelElectrons();
@@ -824,13 +959,14 @@ void EmulatedSensor::CaptureRGB(uint8_t* img, uint32_t width, uint32_t height,
}
void EmulatedSensor::CaptureYUV420(YCbCrPlanes yuv_layout, uint32_t width,
- uint32_t height, uint32_t gain) {
+ uint32_t height, uint32_t gain,
+ const SensorCharacteristics& chars) {
ATRACE_CALL();
- float total_gain = gain / 100.0 * base_gain_factor_;
+ 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;
+ 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
@@ -842,9 +978,9 @@ void EmulatedSensor::CaptureYUV420(YCbCrPlanes yuv_layout, uint32_t width,
const int scale_out_sq = scale_out * scale_out; // after multiplies
// inc = how many pixels to skip while reading every next pixel
- uint32_t inc_h = ceil((float)chars_.width / width);
- uint32_t inc_v = ceil((float)chars_.height / height);
- for (unsigned int y = 0, out_y = 0; y < chars_.height; y += inc_v, out_y++) {
+ uint32_t inc_h = ceil((float)chars.width / width);
+ uint32_t inc_v = ceil((float)chars.height / height);
+ for (unsigned int y = 0, out_y = 0; y < chars.height; y += inc_v, 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;
@@ -887,18 +1023,19 @@ void EmulatedSensor::CaptureYUV420(YCbCrPlanes yuv_layout, uint32_t width,
}
void EmulatedSensor::CaptureDepth(uint8_t* img, uint32_t gain, uint32_t width,
- uint32_t height, uint32_t stride) {
+ uint32_t height, uint32_t stride,
+ const SensorCharacteristics& chars) {
ATRACE_CALL();
- float total_gain = gain / 100.0 * base_gain_factor_;
+ 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_.width / width);
- uint32_t inc_v = ceil((float)chars_.height / height);
+ int scale64x = 64 * total_gain * 8191 / chars.max_raw_value;
+ uint32_t inc_h = ceil((float)chars.width / width);
+ uint32_t inc_v = ceil((float)chars.height / height);
- for (unsigned int y = 0, out_y = 0; y < chars_.height; y += inc_v, out_y++) {
+ for (unsigned int y = 0, out_y = 0; y < chars.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_.width; x += inc_h) {
+ for (unsigned int x = 0; x < chars.width; x += inc_h) {
uint32_t depth_count;
// TODO: Make up real depth scene instead of using green channel
// as depth
@@ -916,7 +1053,8 @@ void EmulatedSensor::CaptureDepth(uint8_t* img, uint32_t gain, uint32_t width,
status_t EmulatedSensor::ProcessYUV420(const YUV420Frame& input,
const YUV420Frame& output, uint32_t gain,
- bool reprocess_request) {
+ bool reprocess_request,
+ const SensorCharacteristics& chars) {
ATRACE_CALL();
size_t input_width, input_height;
YCbCrPlanes input_planes, output_planes;
@@ -961,7 +1099,7 @@ status_t EmulatedSensor::ProcessYUV420(const YUV420Frame& input,
.y_stride = static_cast<uint32_t>(input_width),
.cbcr_stride = static_cast<uint32_t>(input_width) / 2,
.cbcr_step = 1};
- CaptureYUV420(input_planes, input_width, input_height, gain);
+ CaptureYUV420(input_planes, input_width, input_height, gain, chars);
}
output_planes = output.planes;
diff --git a/devices/EmulatedCamera/hwl/EmulatedSensor.h b/devices/EmulatedCamera/hwl/EmulatedSensor.h
index 09a4470..3f19754 100644
--- a/devices/EmulatedCamera/hwl/EmulatedSensor.h
+++ b/devices/EmulatedCamera/hwl/EmulatedSensor.h
@@ -134,6 +134,9 @@ struct SensorCharacteristics {
uint32_t max_pipeline_depth = 0;
};
+// Maps logical/physical camera ids to sensor characteristics
+typedef std::unordered_map<uint32_t, SensorCharacteristics> LogicalCharacteristics;
+
class EmulatedSensor : private Thread, public virtual RefBase {
public:
EmulatedSensor();
@@ -168,11 +171,12 @@ class EmulatedSensor : private Thread, public virtual RefBase {
* Power control
*/
- status_t StartUp(SensorCharacteristics characteristics);
+ status_t StartUp(uint32_t logical_camera_id,
+ std::unique_ptr<LogicalCharacteristics> logical_chars);
status_t ShutDown();
/*
- * Settings control
+ * Physical camera settings control
*/
struct SensorSettings {
nsecs_t exposure_time = 0;
@@ -184,7 +188,10 @@ class EmulatedSensor : private Thread, public virtual RefBase {
bool report_noise_profile = false;
};
- void SetCurrentRequest(SensorSettings settings,
+ // Maps physical and logical camera ids to individual device settings
+ typedef std::unordered_map<uint32_t, SensorSettings> LogicalCameraSettings;
+
+ void SetCurrentRequest(std::unique_ptr<LogicalCameraSettings> logical_settings,
std::unique_ptr<HwlPipelineResult> result,
std::unique_ptr<Buffers> input_buffers,
std::unique_ptr<Buffers> output_buffers);
@@ -208,6 +215,7 @@ class EmulatedSensor : private Thread, public virtual RefBase {
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];
@@ -218,17 +226,11 @@ class EmulatedSensor : private Thread, public virtual RefBase {
private:
/**
- * Sensor characteristics
+ * Logical characteristics
*/
- SensorCharacteristics chars_;
-
- float base_gain_factor_;
+ std::unique_ptr<LogicalCharacteristics> chars_;
- // While each row has to read out, reset, and then expose, the (reset +
- // expose) sequence can be overlapped by other row readouts, so the final
- // minimum frame duration is purely a function of row readout time, at least
- // if there's a reasonable number of rows.
- nsecs_t row_readout_time_;
+ uint32_t logical_camera_id_ = 0;
static const nsecs_t kMinVerticalBlank;
@@ -254,14 +256,13 @@ class EmulatedSensor : private Thread, public virtual RefBase {
static const int32_t kFixedBitPrecision;
static const int32_t kSaturationPoint;
- std::vector<float> lens_shading_map_;
std::vector<int32_t> gamma_table_;
Mutex control_mutex_; // Lock before accessing control parameters
// Start of control parameters
Condition vsync_;
bool got_vsync_;
- SensorSettings current_settings_;
+ std::unique_ptr<LogicalCameraSettings> current_settings_;
std::unique_ptr<HwlPipelineResult> current_result_;
std::unique_ptr<Buffers> current_output_buffers_;
std::unique_ptr<Buffers> current_input_buffers_;
@@ -281,14 +282,16 @@ class EmulatedSensor : private Thread, public virtual RefBase {
std::unique_ptr<EmulatedScene> scene_;
- void CaptureRaw(uint8_t* img, uint32_t gain, uint32_t width);
+ void CaptureRaw(uint8_t* img, uint32_t gain, uint32_t width,
+ const SensorCharacteristics& chars);
enum RGBLayout { RGB, RGBA, ARGB };
void CaptureRGB(uint8_t* img, uint32_t width, uint32_t height,
- uint32_t stride, RGBLayout layout, uint32_t gain);
+ uint32_t stride, RGBLayout layout, uint32_t gain,
+ const SensorCharacteristics& chars);
void CaptureYUV420(YCbCrPlanes yuv_layout, uint32_t width, uint32_t height,
- uint32_t gain);
- void CaptureDepth(uint8_t* img, uint32_t gain, uint32_t width,
- uint32_t height, uint32_t stride);
+ uint32_t gain, const SensorCharacteristics& chars);
+ void CaptureDepth(uint8_t* img, uint32_t gain, uint32_t width, uint32_t height,
+ uint32_t stride, const SensorCharacteristics& chars);
struct YUV420Frame {
uint32_t width = 0;
@@ -297,11 +300,23 @@ class EmulatedSensor : private Thread, public virtual RefBase {
};
status_t ProcessYUV420(const YUV420Frame& input, const YUV420Frame& output,
- uint32_t gain, bool reprocess_request);
+ uint32_t gain, bool reprocess_request,
+ const SensorCharacteristics& chars);
inline int32_t ApplysRGBGamma(int32_t value, int32_t saturation);
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<LogicalCameraSettings> settings,
+ std::unique_ptr<HwlPipelineResult> result);
+
+ static float GetBaseGainFactor(float max_raw_value) {
+ return max_raw_value / EmulatedSensor::kSaturationElectrons;
+ }
};
} // namespace android
diff --git a/devices/EmulatedCamera/hwl/JpegCompressor.cpp b/devices/EmulatedCamera/hwl/JpegCompressor.cpp
index 86c955c..43b1830 100644
--- a/devices/EmulatedCamera/hwl/JpegCompressor.cpp
+++ b/devices/EmulatedCamera/hwl/JpegCompressor.cpp
@@ -31,8 +31,7 @@ using google_camera_hal::ErrorCode;
using google_camera_hal::MessageType;
using google_camera_hal::NotifyMessage;
-JpegCompressor::JpegCompressor(std::unique_ptr<ExifUtils> exif_utils)
- : exif_utils_(std::move(exif_utils)) {
+JpegCompressor::JpegCompressor() {
ATRACE_CALL();
char value[PROPERTY_VALUE_MAX];
if (property_get("ro.product.vendor.manufacturer", value, "unknown") <= 0) {
@@ -110,9 +109,9 @@ void JpegCompressor::CompressYUV420(std::unique_ptr<JpegYUV420Job> job) {
size_t app1_buffer_size = 0;
std::vector<uint8_t> thumbnail_jpeg_buffer;
size_t encoded_thumbnail_size = 0;
- if ((exif_utils_.get() != nullptr) &&
+ if ((job->exif_utils.get() != nullptr) &&
(job->result_metadata.get() != nullptr)) {
- if (exif_utils_->Initialize()) {
+ if (job->exif_utils->Initialize()) {
camera_metadata_ro_entry_t entry;
size_t thumbnail_width = 0;
size_t thumbnail_height = 0;
@@ -150,8 +149,8 @@ void JpegCompressor::CompressYUV420(std::unique_ptr<JpegYUV420Job> job) {
}
}
- if (exif_utils_->SetFromMetadata(*job->result_metadata, job->input->width,
- job->input->height)) {
+ if (job->exif_utils->SetFromMetadata(
+ *job->result_metadata, job->input->width, job->input->height)) {
if (!thumb_yuv420_frame.empty()) {
thumbnail_jpeg_buffer.resize(64 * 1024); // APP1 is limited by 64k
encoded_thumbnail_size = CompressYUV420Frame(
@@ -170,14 +169,14 @@ void JpegCompressor::CompressYUV420(std::unique_ptr<JpegYUV420Job> job) {
}
}
- exif_utils_->SetMake(exif_make_);
- exif_utils_->SetModel(exif_model_);
- if (exif_utils_->GenerateApp1(thumbnail_jpeg_buffer.empty()
- ? nullptr
- : thumbnail_jpeg_buffer.data(),
- encoded_thumbnail_size)) {
- app1_buffer = exif_utils_->GetApp1Buffer();
- app1_buffer_size = exif_utils_->GetApp1Length();
+ job->exif_utils->SetMake(exif_make_);
+ job->exif_utils->SetModel(exif_model_);
+ if (job->exif_utils->GenerateApp1(thumbnail_jpeg_buffer.empty()
+ ? nullptr
+ : thumbnail_jpeg_buffer.data(),
+ encoded_thumbnail_size)) {
+ app1_buffer = job->exif_utils->GetApp1Buffer();
+ app1_buffer_size = job->exif_utils->GetApp1Length();
} else {
ALOGE("%s: Unable to generate App1 buffer", __FUNCTION__);
}
diff --git a/devices/EmulatedCamera/hwl/JpegCompressor.h b/devices/EmulatedCamera/hwl/JpegCompressor.h
index faaa3e1..1ebda72 100644
--- a/devices/EmulatedCamera/hwl/JpegCompressor.h
+++ b/devices/EmulatedCamera/hwl/JpegCompressor.h
@@ -62,11 +62,12 @@ struct JpegYUV420Job {
std::unique_ptr<JpegYUV420Input> input;
std::unique_ptr<SensorBuffer> output;
std::unique_ptr<HalCameraMetadata> result_metadata;
+ std::unique_ptr<ExifUtils> exif_utils;
};
class JpegCompressor {
public:
- JpegCompressor(std::unique_ptr<ExifUtils> exif_utils);
+ JpegCompressor();
virtual ~JpegCompressor();
status_t QueueYUV420(std::unique_ptr<JpegYUV420Job> job);
@@ -77,7 +78,6 @@ class JpegCompressor {
std::atomic_bool jpeg_done_ = false;
std::thread jpeg_processing_thread_;
std::queue<std::unique_ptr<JpegYUV420Job>> pending_yuv_jobs_;
- std::unique_ptr<ExifUtils> exif_utils_;
std::string exif_make_, exif_model_;
j_common_ptr jpeg_error_info_;
diff --git a/devices/EmulatedCamera/hwl/configs/camera_front.json b/devices/EmulatedCamera/hwl/configs/camera_front.json
deleted file mode 100644
index 7da89da..0000000
--- a/devices/EmulatedCamera/hwl/configs/camera_front.json
+++ /dev/null
@@ -1,951 +0,0 @@
-{
- "android.colorCorrection.availableAberrationModes": [
- "0"
- ],
- "android.control.aeAvailableAntibandingModes": [
- "0",
- "3"
- ],
- "android.control.aeAvailableModes": [
- "0",
- "1"
- ],
- "android.control.aeAvailableTargetFpsRanges": [
- "7",
- "7",
- "10",
- "10",
- "15",
- "15",
- "8",
- "30",
- "10",
- "30",
- "15",
- "30",
- "30",
- "30"
- ],
- "android.control.aeCompensationRange": [
- "-20",
- "20"
- ],
- "android.control.aeCompensationStep": [
- "10",
- "100"
- ],
- "android.control.aeLockAvailable": [
- "TRUE"
- ],
- "android.control.afAvailableModes": [
- "0"
- ],
- "android.control.availableEffects": [
- "0",
- "1",
- "2",
- "4",
- "5",
- "8"
- ],
- "android.control.availableModes": [
- "0",
- "1",
- "2"
- ],
- "android.control.availableSceneModes": [
- "0",
- "1"
- ],
- "android.control.availableVideoStabilizationModes": [
- "0"
- ],
- "android.control.awbAvailableModes": [
- "0",
- "1",
- "2",
- "3",
- "5",
- "6"
- ],
- "android.control.awbLockAvailable": [
- "TRUE"
- ],
- "android.control.maxRegions": [
- "0",
- "0",
- "0"
- ],
- "android.control.postRawSensitivityBoostRange": [
- "100",
- "100"
- ],
- "android.control.sceneModeOverrides": [
- "1",
- "1",
- "0",
- "1",
- "1",
- "0"
- ],
- "android.edge.availableEdgeModes": [
- "0",
- "1",
- "2"
- ],
- "android.flash.colorTemperature": [
- "0"
- ],
- "android.flash.info.available": [
- "FALSE"
- ],
- "android.flash.info.chargeDuration": [
- "0"
- ],
- "android.flash.maxEnergy": [
- "0"
- ],
- "android.hotPixel.availableHotPixelModes": [
- "0",
- "1",
- "2"
- ],
- "android.info.supportedHardwareLevel": [
- "LIMITED"
- ],
- "android.jpeg.availableThumbnailSizes": [
- "0",
- "0",
- "320",
- "240",
- "384",
- "384",
- "512",
- "288",
- "512",
- "384"
- ],
- "android.jpeg.maxSize": [
- "9953664"
- ],
- "android.lens.facing": [
- "FRONT"
- ],
- "android.lens.info.availableApertures": [
- "2.40000010"
- ],
- "android.lens.info.availableFilterDensities": [
- "0.00000000"
- ],
- "android.lens.info.availableFocalLengths": [
- "1.86000001"
- ],
- "android.lens.info.availableOpticalStabilization": [
- "0"
- ],
- "android.lens.info.focusDistanceCalibration": [
- "UNCALIBRATED"
- ],
- "android.lens.info.hyperfocalDistance": [
- "0.00000000"
- ],
- "android.lens.info.minimumFocusDistance": [
- "0.00000000"
- ],
- "android.noiseReduction.availableNoiseReductionModes": [
- "0",
- "1",
- "2"
- ],
- "android.request.availableCapabilities": [
- "BACKWARD_COMPATIBLE",
- "BURST_CAPTURE"
- ],
- "android.request.availableCharacteristicsKeys": [
- "4",
- "65554",
- "65555",
- "65556",
- "65557",
- "65558",
- "65559",
- "65560",
- "65561",
- "65562",
- "65563",
- "65564",
- "65572",
- "65573",
- "65574",
- "65575",
- "327680",
- "393217",
- "1376256",
- "458759",
- "524293",
- "589826",
- "589827",
- "589831",
- "589828",
- "589829",
- "655362",
- "786444",
- "786438",
- "786443",
- "786442",
- "851972",
- "851978",
- "851981",
- "917529",
- "917516",
- "917509",
- "917510",
- "917511",
- "917512",
- "917513",
- "917514",
- "983040",
- "983042",
- "983043",
- "983044",
- "983045",
- "983046",
- "983041",
- "983047",
- "983048",
- "917517",
- "917518",
- "917507",
- "917508",
- "1048578",
- "1179648",
- "1179654",
- "1179655",
- "1179650",
- "1507329",
- "1245188",
- "983050"
- ],
- "android.request.availableRequestKeys": [
- "65536",
- "393216",
- "65542",
- "65537",
- "65538",
- "65539",
- "65541",
- "65543",
- "65545",
- "65546",
- "65547",
- "65549",
- "65550",
- "65551",
- "65552",
- "65553",
- "262146",
- "458752",
- "458753",
- "458754",
- "458755",
- "458756",
- "458757",
- "458758",
- "851968",
- "1114112",
- "524292",
- "655360",
- "3",
- "65576",
- "786433"
- ],
- "android.request.availableResultKeys": [
- "65536",
- "917530",
- "1114126",
- "917505",
- "917506",
- "65568",
- "65570",
- "65542",
- "65567",
- "65537",
- "65538",
- "65539",
- "65541",
- "65543",
- "65545",
- "65546",
- "65547",
- "65549",
- "65550",
- "65551",
- "65552",
- "65553",
- "262146",
- "262149",
- "458752",
- "458753",
- "458754",
- "458755",
- "458756",
- "458757",
- "458758",
- "851968",
- "1114112",
- "524292",
- "655360",
- "3",
- "65576",
- "917520"
- ],
- "android.request.maxNumInputStreams": [
- "0"
- ],
- "android.request.maxNumOutputStreams": [
- "1",
- "3",
- "1"
- ],
- "android.request.partialResultCount": [
- "1"
- ],
- "android.request.pipelineMaxDepth": [
- "7"
- ],
- "android.scaler.availableMaxDigitalZoom": [
- "4.00000000"
- ],
- "android.scaler.availableMinFrameDurations": [
- "34",
- "1920",
- "1080",
- "33331760",
- "34",
- "1440",
- "1080",
- "33331760",
- "34",
- "1280",
- "720",
- "33331760",
- "34",
- "1072",
- "1072",
- "33331760",
- "34",
- "960",
- "720",
- "33331760",
- "34",
- "720",
- "480",
- "33331760",
- "34",
- "640",
- "480",
- "33331760",
- "34",
- "352",
- "288",
- "33331760",
- "34",
- "320",
- "240",
- "33331760",
- "34",
- "256",
- "144",
- "33331760",
- "34",
- "176",
- "144",
- "33331760",
- "35",
- "1920",
- "1080",
- "33331760",
- "35",
- "1440",
- "1080",
- "33331760",
- "35",
- "1280",
- "720",
- "33331760",
- "35",
- "1072",
- "1072",
- "33331760",
- "35",
- "960",
- "720",
- "33331760",
- "35",
- "720",
- "480",
- "33331760",
- "35",
- "640",
- "480",
- "33331760",
- "35",
- "352",
- "288",
- "33331760",
- "35",
- "320",
- "240",
- "33331760",
- "35",
- "256",
- "144",
- "33331760",
- "35",
- "176",
- "144",
- "33331760",
- "33",
- "1920",
- "1080",
- "33331760",
- "33",
- "1440",
- "1080",
- "33331760",
- "33",
- "1280",
- "720",
- "33331760",
- "33",
- "1072",
- "1072",
- "33331760",
- "33",
- "960",
- "720",
- "33331760",
- "33",
- "720",
- "480",
- "33331760",
- "33",
- "640",
- "480",
- "33331760",
- "33",
- "352",
- "288",
- "33331760",
- "33",
- "320",
- "240",
- "33331760",
- "33",
- "256",
- "144",
- "33331760",
- "33",
- "176",
- "144",
- "33331760"
- ],
- "android.scaler.availableStallDurations": [
- "34",
- "1920",
- "1080",
- "0",
- "34",
- "1440",
- "1080",
- "0",
- "34",
- "1280",
- "720",
- "0",
- "34",
- "1072",
- "1072",
- "0",
- "34",
- "960",
- "720",
- "0",
- "34",
- "720",
- "480",
- "0",
- "34",
- "640",
- "480",
- "0",
- "34",
- "352",
- "288",
- "0",
- "34",
- "320",
- "240",
- "0",
- "34",
- "256",
- "144",
- "0",
- "34",
- "176",
- "144",
- "0",
- "35",
- "1920",
- "1080",
- "0",
- "35",
- "1440",
- "1080",
- "0",
- "35",
- "1280",
- "720",
- "0",
- "35",
- "1072",
- "1072",
- "0",
- "35",
- "960",
- "720",
- "0",
- "35",
- "720",
- "480",
- "0",
- "35",
- "640",
- "480",
- "0",
- "35",
- "352",
- "288",
- "0",
- "35",
- "320",
- "240",
- "0",
- "35",
- "256",
- "144",
- "0",
- "35",
- "176",
- "144",
- "0",
- "33",
- "1920",
- "1080",
- "33331760",
- "33",
- "1440",
- "1080",
- "33331760",
- "33",
- "1280",
- "720",
- "33331760",
- "33",
- "1072",
- "1072",
- "33331760",
- "33",
- "960",
- "720",
- "33331760",
- "33",
- "720",
- "480",
- "33331760",
- "33",
- "640",
- "480",
- "33331760",
- "33",
- "352",
- "288",
- "33331760",
- "33",
- "320",
- "240",
- "33331760",
- "33",
- "256",
- "144",
- "33331760",
- "33",
- "176",
- "144",
- "33331760"
- ],
- "android.scaler.availableStreamConfigurations": [
- "34",
- "1920",
- "1080",
- "OUTPUT",
- "34",
- "1440",
- "1080",
- "OUTPUT",
- "34",
- "1280",
- "720",
- "OUTPUT",
- "34",
- "1072",
- "1072",
- "OUTPUT",
- "34",
- "960",
- "720",
- "OUTPUT",
- "34",
- "720",
- "480",
- "OUTPUT",
- "34",
- "640",
- "480",
- "OUTPUT",
- "34",
- "352",
- "288",
- "OUTPUT",
- "34",
- "320",
- "240",
- "OUTPUT",
- "34",
- "256",
- "144",
- "OUTPUT",
- "34",
- "176",
- "144",
- "OUTPUT",
- "35",
- "1920",
- "1080",
- "OUTPUT",
- "35",
- "1440",
- "1080",
- "OUTPUT",
- "35",
- "1280",
- "720",
- "OUTPUT",
- "35",
- "1072",
- "1072",
- "OUTPUT",
- "35",
- "960",
- "720",
- "OUTPUT",
- "35",
- "720",
- "480",
- "OUTPUT",
- "35",
- "640",
- "480",
- "OUTPUT",
- "35",
- "352",
- "288",
- "OUTPUT",
- "35",
- "320",
- "240",
- "OUTPUT",
- "35",
- "256",
- "144",
- "OUTPUT",
- "35",
- "176",
- "144",
- "OUTPUT",
- "33",
- "1920",
- "1080",
- "OUTPUT",
- "33",
- "1440",
- "1080",
- "OUTPUT",
- "33",
- "1280",
- "720",
- "OUTPUT",
- "33",
- "1072",
- "1072",
- "OUTPUT",
- "33",
- "960",
- "720",
- "OUTPUT",
- "33",
- "720",
- "480",
- "OUTPUT",
- "33",
- "640",
- "480",
- "OUTPUT",
- "33",
- "352",
- "288",
- "OUTPUT",
- "33",
- "320",
- "240",
- "OUTPUT",
- "33",
- "256",
- "144",
- "OUTPUT",
- "33",
- "176",
- "144",
- "OUTPUT"
- ],
- "android.scaler.croppingType": [
- "FREEFORM"
- ],
- "android.sensor.availableTestPatternModes": [
- "0"
- ],
- "android.sensor.blackLevelPattern": [
- "1000",
- "1000",
- "1000",
- "1000"
- ],
- "android.sensor.calibrationTransform1": [
- "128",
- "128",
- "0",
- "128",
- "0",
- "128",
- "0",
- "128",
- "128",
- "128",
- "0",
- "128",
- "0",
- "128",
- "0",
- "128",
- "128",
- "128"
- ],
- "android.sensor.calibrationTransform2": [
- "128",
- "128",
- "0",
- "128",
- "0",
- "128",
- "0",
- "128",
- "128",
- "128",
- "0",
- "128",
- "0",
- "128",
- "0",
- "128",
- "128",
- "128"
- ],
- "android.sensor.colorTransform1": [
- "128",
- "128",
- "0",
- "128",
- "0",
- "128",
- "0",
- "128",
- "128",
- "128",
- "0",
- "128",
- "0",
- "128",
- "0",
- "128",
- "128",
- "128"
- ],
- "android.sensor.colorTransform2": [
- "128",
- "128",
- "0",
- "128",
- "0",
- "128",
- "0",
- "128",
- "128",
- "128",
- "0",
- "128",
- "0",
- "128",
- "0",
- "128",
- "128",
- "128"
- ],
- "android.sensor.forwardMatrix1": [
- "128",
- "128",
- "0",
- "128",
- "0",
- "128",
- "0",
- "128",
- "128",
- "128",
- "0",
- "128",
- "0",
- "128",
- "0",
- "128",
- "128",
- "128"
- ],
- "android.sensor.forwardMatrix2": [
- "128",
- "128",
- "0",
- "128",
- "0",
- "128",
- "0",
- "128",
- "128",
- "128",
- "0",
- "128",
- "0",
- "128",
- "0",
- "128",
- "128",
- "128"
- ],
- "android.sensor.info.activeArraySize": [
- "0",
- "0",
- "1920",
- "1080"
- ],
- "android.sensor.info.colorFilterArrangement": [
- "RGGB"
- ],
- "android.sensor.info.exposureTimeRange": [
- "14000",
- "125000000"
- ],
- "android.sensor.info.maxFrameDuration": [
- "500000000"
- ],
- "android.sensor.info.physicalSize": [
- "3.84711116",
- "2.16400003"
- ],
- "android.sensor.info.pixelArraySize": [
- "1920",
- "1080"
- ],
- "android.sensor.info.preCorrectionActiveArraySize": [
- "0",
- "0",
- "1920",
- "1080"
- ],
- "android.sensor.info.sensitivityRange": [
- "100",
- "1600"
- ],
- "android.sensor.info.timestampSource": [
- "UNKNOWN"
- ],
- "android.sensor.info.whiteLevel": [
- "4000"
- ],
- "android.sensor.maxAnalogSensitivity": [
- "800"
- ],
- "android.sensor.orientation": [
- "270"
- ],
- "android.sensor.profileHueSatMapDimensions": [
- "1",
- "2",
- "1"
- ],
- "android.sensor.referenceIlluminant1": [
- "DAYLIGHT"
- ],
- "android.sensor.referenceIlluminant2": [
- "1"
- ],
- "android.shading.availableModes": [
- "0",
- "1",
- "2"
- ],
- "android.statistics.info.availableFaceDetectModes": [
- "0",
- "1"
- ],
- "android.statistics.info.availableHotPixelMapModes": [
- "0"
- ],
- "android.statistics.info.availableLensShadingMapModes": [
- "0"
- ],
- "android.statistics.info.histogramBucketCount": [
- "64"
- ],
- "android.statistics.info.maxFaceCount": [
- "16"
- ],
- "android.statistics.info.maxHistogramCount": [
- "1000"
- ],
- "android.statistics.info.maxSharpnessMapValue": [
- "1000"
- ],
- "android.statistics.info.sharpnessMapSize": [
- "64",
- "64"
- ],
- "android.sync.maxLatency": [
- "PER_FRAME_CONTROL"
- ],
- "android.tonemap.availableToneMapModes": [
- "1",
- "2"
- ],
- "android.tonemap.maxCurvePoints": [
- "128"
- ]
-}
diff --git a/devices/EmulatedCamera/hwl/configs/camera.json b/devices/EmulatedCamera/hwl/configs/emu_camera_back.json
index 0bdb7ad..0bdb7ad 100644
--- a/devices/EmulatedCamera/hwl/configs/camera.json
+++ b/devices/EmulatedCamera/hwl/configs/emu_camera_back.json
diff --git a/devices/EmulatedCamera/hwl/configs/camera_depth.json b/devices/EmulatedCamera/hwl/configs/emu_camera_depth.json
index 8a53d72..8a53d72 100644
--- a/devices/EmulatedCamera/hwl/configs/camera_depth.json
+++ b/devices/EmulatedCamera/hwl/configs/emu_camera_depth.json
diff --git a/devices/EmulatedCamera/hwl/configs/emu_camera_front.json b/devices/EmulatedCamera/hwl/configs/emu_camera_front.json
new file mode 100644
index 0000000..49a661a
--- /dev/null
+++ b/devices/EmulatedCamera/hwl/configs/emu_camera_front.json
@@ -0,0 +1,3528 @@
+[
+ {
+ "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",
+ "7",
+ "30",
+ "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.availableEffects": [
+ "0"
+ ],
+ "android.control.availableModes": [
+ "0",
+ "1",
+ "2"
+ ],
+ "android.control.availableSceneModes": [
+ "0",
+ "1",
+ "2",
+ "3",
+ "4",
+ "5",
+ "6",
+ "7",
+ "8",
+ "9",
+ "10",
+ "12",
+ "13",
+ "14",
+ "15",
+ "18"
+ ],
+ "android.control.availableVideoStabilizationModes": [
+ "0",
+ "1"
+ ],
+ "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.distortionCorrection.availableModes": [
+ "0"
+ ],
+ "android.edge.availableEdgeModes": [
+ "1",
+ "2",
+ "0"
+ ],
+ "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": [
+ "300000"
+ ],
+ "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"
+ ],
+ "android.reprocess.maxCaptureStall": [
+ "2"
+ ],
+ "android.request.availableCapabilities": [
+ "BACKWARD_COMPATIBLE",
+ "RAW",
+ "READ_SENSOR_SETTINGS",
+ "MANUAL_SENSOR",
+ "BURST_CAPTURE",
+ "MANUAL_POST_PROCESSING",
+ "LOGICAL_MULTI_CAMERA"
+ ],
+ "android.request.availableCharacteristicsKeys": [
+ "4",
+ "65554",
+ "65555",
+ "65556",
+ "65557",
+ "65558",
+ "65559",
+ "65560",
+ "65561",
+ "65562",
+ "65563",
+ "65564",
+ "65565",
+ "65571",
+ "65572",
+ "65573",
+ "65574",
+ "65575",
+ "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"
+ ],
+ "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",
+ "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"
+ ],
+ "android.request.availableResultKeys": [
+ "0",
+ "1",
+ "2",
+ "65537",
+ "65539",
+ "65540",
+ "65567",
+ "65543",
+ "65544",
+ "65568",
+ "65547",
+ "65570",
+ "65551",
+ "65576",
+ "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"
+ ],
+ "android.request.maxNumInputStreams": [
+ "0"
+ ],
+ "android.request.maxNumOutputStreams": [
+ "1",
+ "3",
+ "2"
+ ],
+ "android.request.partialResultCount": [
+ "1"
+ ],
+ "android.request.pipelineMaxDepth": [
+ "8"
+ ],
+ "android.scaler.availableMaxDigitalZoom": [
+ "8.00000000"
+ ],
+ "android.scaler.availableMinFrameDurations": [
+ "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",
+ "32",
+ "1920",
+ "1440",
+ "33320000"
+ ],
+ "android.scaler.availableStallDurations": [
+ "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.availableStreamConfigurations": [
+ "32",
+ "1920",
+ "1440",
+ "OUTPUT",
+ "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",
+ "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.croppingType": [
+ "CENTER_ONLY"
+ ],
+ "android.sensor.availableTestPatternModes": [
+ "0",
+ "1",
+ "2",
+ "3",
+ "4"
+ ],
+ "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.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.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.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",
+ "7",
+ "30",
+ "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.availableEffects": [
+ "0"
+ ],
+ "android.control.availableModes": [
+ "0",
+ "1",
+ "2"
+ ],
+ "android.control.availableSceneModes": [
+ "0",
+ "1",
+ "2",
+ "3",
+ "4",
+ "5",
+ "6",
+ "7",
+ "8",
+ "9",
+ "10",
+ "12",
+ "13",
+ "14",
+ "15",
+ "18"
+ ],
+ "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.distortionCorrection.availableModes": [
+ "0"
+ ],
+ "android.edge.availableEdgeModes": [
+ "1",
+ "2",
+ "0"
+ ],
+ "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": [
+ "300000"
+ ],
+ "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"
+ ],
+ "android.reprocess.maxCaptureStall": [
+ "2"
+ ],
+ "android.request.availableCapabilities": [
+ "BACKWARD_COMPATIBLE",
+ "RAW",
+ "READ_SENSOR_SETTINGS",
+ "MANUAL_SENSOR",
+ "BURST_CAPTURE",
+ "MANUAL_POST_PROCESSING"
+ ],
+ "android.request.availableCharacteristicsKeys": [
+ "4",
+ "65554",
+ "65555",
+ "65556",
+ "65557",
+ "65558",
+ "65559",
+ "65560",
+ "65561",
+ "65562",
+ "65563",
+ "65564",
+ "65565",
+ "65571",
+ "65572",
+ "65573",
+ "65574",
+ "65575",
+ "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"
+ ],
+ "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",
+ "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"
+ ],
+ "android.request.availableResultKeys": [
+ "0",
+ "1",
+ "2",
+ "65537",
+ "65539",
+ "65540",
+ "65567",
+ "65543",
+ "65544",
+ "65568",
+ "65547",
+ "65570",
+ "65551",
+ "65576",
+ "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"
+ ],
+ "android.request.maxNumInputStreams": [
+ "0"
+ ],
+ "android.request.maxNumOutputStreams": [
+ "1",
+ "3",
+ "2"
+ ],
+ "android.request.partialResultCount": [
+ "1"
+ ],
+ "android.request.pipelineMaxDepth": [
+ "8"
+ ],
+ "android.scaler.availableMaxDigitalZoom": [
+ "8.00000000"
+ ],
+ "android.scaler.availableMinFrameDurations": [
+ "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",
+ "32",
+ "1920",
+ "1440",
+ "33320000"
+ ],
+ "android.scaler.availableStallDurations": [
+ "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.availableStreamConfigurations": [
+ "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",
+ "32",
+ "1920",
+ "1440",
+ "OUTPUT"
+ ],
+ "android.scaler.croppingType": [
+ "CENTER_ONLY"
+ ],
+ "android.sensor.availableTestPatternModes": [
+ "0",
+ "1",
+ "2",
+ "3",
+ "4"
+ ],
+ "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.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.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.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",
+ "7",
+ "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.availableEffects": [
+ "0"
+ ],
+ "android.control.availableModes": [
+ "0",
+ "1",
+ "2"
+ ],
+ "android.control.availableSceneModes": [
+ "0",
+ "1",
+ "2",
+ "3",
+ "4",
+ "5",
+ "6",
+ "7",
+ "8",
+ "9",
+ "10",
+ "12",
+ "13",
+ "14",
+ "15",
+ "18"
+ ],
+ "android.control.availableVideoStabilizationModes": [
+ "0",
+ "1"
+ ],
+ "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.distortionCorrection.availableModes": [
+ "0"
+ ],
+ "android.edge.availableEdgeModes": [
+ "1",
+ "2",
+ "0"
+ ],
+ "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": [
+ "300000"
+ ],
+ "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"
+ ],
+ "android.reprocess.maxCaptureStall": [
+ "2"
+ ],
+ "android.request.availableCapabilities": [
+ "BACKWARD_COMPATIBLE",
+ "RAW",
+ "READ_SENSOR_SETTINGS",
+ "MANUAL_SENSOR",
+ "BURST_CAPTURE",
+ "MANUAL_POST_PROCESSING"
+ ],
+ "android.request.availableCharacteristicsKeys": [
+ "4",
+ "65554",
+ "65555",
+ "65556",
+ "65557",
+ "65558",
+ "65559",
+ "65560",
+ "65561",
+ "65562",
+ "65563",
+ "65564",
+ "65565",
+ "65571",
+ "65572",
+ "65573",
+ "65574",
+ "65575",
+ "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"
+ ],
+ "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",
+ "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"
+ ],
+ "android.request.availableResultKeys": [
+ "0",
+ "1",
+ "2",
+ "65537",
+ "65539",
+ "65540",
+ "65567",
+ "65543",
+ "65544",
+ "65568",
+ "65547",
+ "65570",
+ "65551",
+ "65576",
+ "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"
+ ],
+ "android.request.maxNumInputStreams": [
+ "0"
+ ],
+ "android.request.maxNumOutputStreams": [
+ "1",
+ "3",
+ "2"
+ ],
+ "android.request.partialResultCount": [
+ "1"
+ ],
+ "android.request.pipelineMaxDepth": [
+ "8"
+ ],
+ "android.scaler.availableMaxDigitalZoom": [
+ "8.00000000"
+ ],
+ "android.scaler.availableMinFrameDurations": [
+ "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",
+ "32",
+ "1920",
+ "1440",
+ "33326886"
+ ],
+ "android.scaler.availableStallDurations": [
+ "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.availableStreamConfigurations": [
+ "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",
+ "32",
+ "1920",
+ "1440",
+ "OUTPUT"
+ ],
+ "android.scaler.croppingType": [
+ "CENTER_ONLY"
+ ],
+ "android.sensor.availableTestPatternModes": [
+ "0",
+ "1",
+ "2",
+ "3",
+ "4"
+ ],
+ "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",
+ "1920",
+ "1440"
+ ],
+ "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": [
+ "1920",
+ "1440"
+ ],
+ "android.sensor.info.preCorrectionActiveArraySize": [
+ "0",
+ "0",
+ "1920",
+ "1440"
+ ],
+ "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.sync.maxLatency": [
+ "PER_FRAME_CONTROL"
+ ],
+ "android.tonemap.availableToneMapModes": [
+ "0",
+ "1",
+ "2"
+ ],
+ "android.tonemap.maxCurvePoints": [
+ "64"
+ ]
+ }
+]
diff --git a/devices/EmulatedCamera/hwl/tools/parse_bugreport.py b/devices/EmulatedCamera/hwl/tools/parse_bugreport.py
index d1699e9..c806ddd 100755
--- a/devices/EmulatedCamera/hwl/tools/parse_bugreport.py
+++ b/devices/EmulatedCamera/hwl/tools/parse_bugreport.py
@@ -38,10 +38,11 @@ def storeJsonConfigration(filePath, chars):
"""
Parse media.camera dump section and populate the camera
-characteristics dictionary.
+characteristics list of dictionaries.
"""
-def parseCameraDump(deviceId, cameraDumpPath, chars):
+def parseCameraDump(deviceId, cameraDumpPath, tagList):
deviceRegExp = "== Camera HAL device device@[0-9]+\.[0-9]+/{0} \(v3.".format(deviceId)
+ physicalDeviceRegExp = "Physical camera [0-9] characteristics:"
tagRegExp = " {4}android[a-zA-Z0-9\.]+ \([a-z0-9]+\): "
tagValueRegExp = "[^a-zA-Z0-9-\._]"
with open(cameraDumpPath, "r") as file:
@@ -50,45 +51,51 @@ def parseCameraDump(deviceId, cameraDumpPath, chars):
print "Camera device id: {0} not found".format(deviceId)
sys.exit()
- tags = re.split(tagRegExp, devices[1])
- tagsContent = re.findall(tagRegExp, devices[1])
- i = 0;
- parseEnd = False
- for tag in tags[1:]:
- if parseEnd:
- break
+ physicalDevices = re.split(physicalDeviceRegExp, devices[1])
+ physicalIdx = 0
+ for physicalDevice in physicalDevices:
+ physicalIdx += 1
+ tags = re.split(tagRegExp, physicalDevice)
+ tagsContent = re.findall(tagRegExp, physicalDevice)
+ i = 0;
+ parseEnd = False
+ deviceChars = dict()
+ for tag in tags[1:]:
+ if parseEnd:
+ break
- lines = tag.splitlines()
- if len(lines) < 2:
- print "Empty tag entry, skipping!"
- continue
- tagName = tagsContent[i].split()[0]
+ lines = tag.splitlines()
+ if len(lines) < 2:
+ print "Empty tag entry, skipping!"
+ continue
+ tagName = tagsContent[i].split()[0]
- if tagName is None or len(tagName) < 1:
- print "Invalid tag found, skipping!"
- continue
+ if tagName is None or len(tagName) < 1:
+ print "Invalid tag found, skipping!"
+ continue
- i += 1
- for line in lines[1:]:
- if line.startswith('== Camera HAL device device'):
- parseEnd = True
- break
+ i += 1
+ for line in lines[1:]:
+ if line.startswith('== Camera HAL device device'):
+ parseEnd = True
+ break
- values = re.split(r' {8}', line)
- if len(values) == 2:
- key = tagName
- tagValues = filter(None, re.split(tagValueRegExp, values[1]))
- if chars.has_key(key):
- chars[key] = chars[key] + tagValues
+ values = re.split(r' {8}', line)
+ if len(values) == 2:
+ key = tagName
+ tagValues = filter(None, re.split(tagValueRegExp, values[1]))
+ if deviceChars.has_key(key):
+ deviceChars[key] = deviceChars[key] + tagValues
+ else:
+ deviceChars[key] = tagValues
else:
- chars[key] = tagValues
- else:
- break
+ break
+ tagList.append(deviceChars)
os.remove(cameraDumpPath)
if __name__ == '__main__':
argc = len(sys.argv)
- deviceId = "legacy/0"
+ deviceId = ""
bugreportPath = ""
configPath = ""
if argc >= 4:
@@ -110,7 +117,7 @@ if __name__ == '__main__':
print("Camera dump not found in bugreport!")
sys.exit()
- chars = dict()
- parseCameraDump(deviceId, bugzip.extract(cameraDumpFile), chars)
- storeJsonConfigration(configPath, chars)
+ tagList = list()
+ parseCameraDump(deviceId, bugzip.extract(cameraDumpFile), tagList)
+ storeJsonConfigration(configPath, tagList)
diff --git a/devices/EmulatedCamera/hwl/utils/HWLUtils.cpp b/devices/EmulatedCamera/hwl/utils/HWLUtils.cpp
index 6a5b711..e68ea56 100644
--- a/devices/EmulatedCamera/hwl/utils/HWLUtils.cpp
+++ b/devices/EmulatedCamera/hwl/utils/HWLUtils.cpp
@@ -205,4 +205,12 @@ status_t GetSensorCharacteristics(const HalCameraMetadata* metadata,
return ret;
}
+PhysicalDeviceMapPtr ClonePhysicalDeviceMap(const PhysicalDeviceMapPtr& src) {
+ auto ret = std::make_unique<PhysicalDeviceMap>();
+ for (const auto& it : *src) {
+ ret->emplace(it.first, HalCameraMetadata::Clone(it.second.get()));
+ }
+ return ret;
+}
+
} // namespace android
diff --git a/devices/EmulatedCamera/hwl/utils/HWLUtils.h b/devices/EmulatedCamera/hwl/utils/HWLUtils.h
index 860b51d..d9ec11d 100644
--- a/devices/EmulatedCamera/hwl/utils/HWLUtils.h
+++ b/devices/EmulatedCamera/hwl/utils/HWLUtils.h
@@ -31,12 +31,17 @@
namespace android {
+typedef std::unordered_map<uint32_t, std::unique_ptr<HalCameraMetadata>>
+ PhysicalDeviceMap;
+typedef std::unique_ptr<PhysicalDeviceMap> PhysicalDeviceMapPtr;
+
using google_camera_hal::HalCameraMetadata;
// Metadata utility functions start
bool HasCapability(const HalCameraMetadata* metadata, uint8_t capability);
status_t GetSensorCharacteristics(const HalCameraMetadata* metadata,
SensorCharacteristics* sensor_chars /*out*/);
+PhysicalDeviceMapPtr ClonePhysicalDeviceMap(const PhysicalDeviceMapPtr& src);
// Metadata utility functions end
} // namespace android