blob: 80814a6a9c7a00f92db50dabcb12b670c6b25ea7 [file] [log] [blame] [edit]
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
//#define LOG_NDEBUG 0
#define LOG_TAG "EmulatedCameraProviderHwlImpl"
#include "EmulatedCameraProviderHWLImpl.h"
#include <android-base/file.h>
#include <android-base/strings.h>
#include <cutils/properties.h>
#include <hardware/camera_common.h>
#include <log/log.h>
#include "ConfigUtils.h"
#include "EmulatedCameraDeviceHWLImpl.h"
#include "EmulatedCameraDeviceSessionHWLImpl.h"
#include "EmulatedLogicalRequestState.h"
#include "EmulatedSensor.h"
#include "EmulatedTorchState.h"
#include "utils/HWLUtils.h"
#include "vendor_tag_defs.h"
namespace android {
constexpr StreamSize s240pStreamSize = std::pair(240, 180);
constexpr StreamSize s720pStreamSize = std::pair(1280, 720);
constexpr StreamSize s1440pStreamSize = std::pair(1920, 1440);
std::unique_ptr<EmulatedCameraProviderHwlImpl>
EmulatedCameraProviderHwlImpl::Create() {
auto provider = std::unique_ptr<EmulatedCameraProviderHwlImpl>(
new EmulatedCameraProviderHwlImpl());
if (provider == nullptr) {
ALOGE("%s: Creating EmulatedCameraProviderHwlImpl failed.", __FUNCTION__);
return nullptr;
}
status_t res = provider->Initialize();
if (res != OK) {
ALOGE("%s: Initializing EmulatedCameraProviderHwlImpl failed: %s (%d).",
__FUNCTION__, strerror(-res), res);
return nullptr;
}
ALOGI("%s: Created EmulatedCameraProviderHwlImpl", __FUNCTION__);
return provider;
}
static bool IsMaxSupportedSizeGreaterThanOrEqual(
const std::set<StreamSize>& stream_sizes, StreamSize compare_size) {
for (const auto& stream_size : stream_sizes) {
if (stream_size.first * stream_size.second >=
compare_size.first * compare_size.second) {
return true;
}
}
return false;
}
static bool SupportsCapability(const uint32_t camera_id,
const HalCameraMetadata& static_metadata,
uint8_t cap) {
camera_metadata_ro_entry_t entry;
auto ret = static_metadata.Get(ANDROID_REQUEST_AVAILABLE_CAPABILITIES, &entry);
if (ret != OK || (entry.count == 0)) {
ALOGE("Error getting capabilities for camera id %u", camera_id);
return false;
}
for (size_t i = 0; i < entry.count; i++) {
if (entry.data.u8[i] == cap) {
return true;
}
}
return false;
}
bool EmulatedCameraProviderHwlImpl::SupportsMandatoryConcurrentStreams(
uint32_t camera_id) {
HalCameraMetadata& static_metadata = *(static_metadata_.at(camera_id));
auto map = std::make_unique<StreamConfigurationMap>(static_metadata);
auto yuv_output_sizes = map->GetOutputSizes(HAL_PIXEL_FORMAT_YCBCR_420_888);
auto blob_output_sizes = map->GetOutputSizes(HAL_PIXEL_FORMAT_BLOB);
auto depth16_output_sizes = map->GetOutputSizes(HAL_PIXEL_FORMAT_Y16);
auto priv_output_sizes =
map->GetOutputSizes(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED);
if (!SupportsCapability(
camera_id, static_metadata,
ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE) &&
IsMaxSupportedSizeGreaterThanOrEqual(depth16_output_sizes,
s240pStreamSize)) {
ALOGI("%s: Depth only output supported by camera id %u", __FUNCTION__,
camera_id);
return true;
}
if (yuv_output_sizes.empty()) {
ALOGW("%s: No YUV output supported by camera id %u", __FUNCTION__,
camera_id);
return false;
}
if (priv_output_sizes.empty()) {
ALOGW("No PRIV output supported by camera id %u", camera_id);
return false;
}
if (blob_output_sizes.empty()) {
ALOGW("No BLOB output supported by camera id %u", camera_id);
return false;
}
// According to the HAL spec, if a device supports format sizes > 1440p and
// 720p, it must support both 1440p and 720p streams for PRIV, JPEG and YUV
// formats. Otherwise it must support 2 streams (YUV / PRIV + JPEG) of the max
// supported size.
// Check for YUV output sizes
if (IsMaxSupportedSizeGreaterThanOrEqual(yuv_output_sizes, s1440pStreamSize) &&
(yuv_output_sizes.find(s1440pStreamSize) == yuv_output_sizes.end() ||
yuv_output_sizes.find(s720pStreamSize) == yuv_output_sizes.end())) {
ALOGW("%s: 1440p+720p YUV outputs not found for camera id %u", __FUNCTION__,
camera_id);
return false;
} else if (IsMaxSupportedSizeGreaterThanOrEqual(yuv_output_sizes,
s720pStreamSize) &&
yuv_output_sizes.find(s720pStreamSize) == yuv_output_sizes.end()) {
ALOGW("%s: 720p YUV output not found for camera id %u", __FUNCTION__,
camera_id);
return false;
}
// Check for PRIV output sizes
if (IsMaxSupportedSizeGreaterThanOrEqual(priv_output_sizes, s1440pStreamSize) &&
(priv_output_sizes.find(s1440pStreamSize) == priv_output_sizes.end() ||
priv_output_sizes.find(s720pStreamSize) == priv_output_sizes.end())) {
ALOGW("%s: 1440p + 720p PRIV outputs not found for camera id %u",
__FUNCTION__, camera_id);
return false;
} else if (IsMaxSupportedSizeGreaterThanOrEqual(priv_output_sizes,
s720pStreamSize) &&
priv_output_sizes.find(s720pStreamSize) == priv_output_sizes.end()) {
ALOGW("%s: 720p PRIV output not found for camera id %u", __FUNCTION__,
camera_id);
return false;
}
// Check for BLOB output sizes
if (IsMaxSupportedSizeGreaterThanOrEqual(blob_output_sizes, s1440pStreamSize) &&
(blob_output_sizes.find(s1440pStreamSize) == blob_output_sizes.end() ||
blob_output_sizes.find(s720pStreamSize) == blob_output_sizes.end())) {
ALOGW("%s: 1440p + 720p BLOB outputs not found for camera id %u",
__FUNCTION__, camera_id);
return false;
} else if (IsMaxSupportedSizeGreaterThanOrEqual(blob_output_sizes,
s720pStreamSize) &&
blob_output_sizes.find(s720pStreamSize) == blob_output_sizes.end()) {
ALOGW("%s: 720p BLOB output not found for camera id %u", __FUNCTION__,
camera_id);
return false;
}
return true;
}
status_t EmulatedCameraProviderHwlImpl::GetConcurrentStreamingCameraIds(
std::vector<std::unordered_set<uint32_t>>* combinations) {
if (combinations == nullptr) {
return BAD_VALUE;
}
// Collect all camera ids that support the guaranteed stream combinations
// (720p YUV and IMPLEMENTATION_DEFINED) and put them in one set. We don't
// make all possible combinations since it should be possible to stream all
// of them at once in the emulated camera.
std::unordered_set<uint32_t> candidate_ids;
for (auto const& [camera_id, _] : camera_id_map_) {
if (SupportsMandatoryConcurrentStreams(camera_id)) {
candidate_ids.insert(camera_id);
}
}
combinations->emplace_back(std::move(candidate_ids));
return OK;
}
status_t EmulatedCameraProviderHwlImpl::DumpState(int /*fd*/) {
return OK;
}
status_t EmulatedCameraProviderHwlImpl::IsConcurrentStreamCombinationSupported(
const std::vector<CameraIdAndStreamConfiguration>& configs,
bool* is_supported) {
*is_supported = false;
// Go through the given camera ids, get their sensor characteristics, stream
// config maps and call EmulatedSensor::IsStreamCombinationSupported()
for (auto& config : configs) {
uint32_t camera_id = config.camera_id;
// TODO: Consider caching sensor characteristics and StreamConfigurationMap
if (camera_id_map_.find(camera_id) == camera_id_map_.end()) {
ALOGE("%s: Camera id %u does not exist", __FUNCTION__, camera_id);
return BAD_VALUE;
}
auto stream_configuration_map = std::make_unique<StreamConfigurationMap>(
*(static_metadata_.at(camera_id)));
auto stream_configuration_map_max_resolution =
std::make_unique<StreamConfigurationMap>(
*(static_metadata_.at(camera_id)), /*maxResolution*/ true);
LogicalCharacteristics sensor_chars;
status_t ret = GetSensorCharacteristics(
(static_metadata_.at(camera_id)).get(), &sensor_chars[camera_id]);
if (ret != OK) {
ALOGE("%s: Unable to extract sensor chars for camera id %u", __FUNCTION__,
camera_id);
return UNKNOWN_ERROR;
}
PhysicalStreamConfigurationMap physical_stream_configuration_map;
PhysicalStreamConfigurationMap physical_stream_configuration_map_max_resolution;
auto const& physicalCameraInfo = camera_id_map_.at(camera_id);
for (size_t i = 0; i < physicalCameraInfo.size(); i++) {
uint32_t physical_camera_id = physicalCameraInfo[i].second;
physical_stream_configuration_map.emplace(
physical_camera_id, std::make_unique<StreamConfigurationMap>(
*(static_metadata_.at(physical_camera_id))));
physical_stream_configuration_map_max_resolution.emplace(
physical_camera_id, std::make_unique<StreamConfigurationMap>(
*(static_metadata_.at(physical_camera_id)),
/*maxResolution*/ true));
ret = GetSensorCharacteristics(
static_metadata_.at(physical_camera_id).get(),
&sensor_chars[physical_camera_id]);
if (ret != OK) {
ALOGE("%s: Unable to extract camera %d sensor characteristics %s (%d)",
__FUNCTION__, physical_camera_id, strerror(-ret), ret);
return ret;
}
}
if (!EmulatedSensor::IsStreamCombinationSupported(
camera_id, config.stream_configuration, *stream_configuration_map,
*stream_configuration_map_max_resolution,
physical_stream_configuration_map,
physical_stream_configuration_map_max_resolution, sensor_chars)) {
return OK;
}
}
*is_supported = true;
return OK;
}
status_t EmulatedCameraProviderHwlImpl::Initialize() {
std::vector<CameraConfiguration> camera_configs;
status_t res = GetCameraConfigurations(&camera_configs);
if (res != OK) {
return res;
}
for (auto& config : camera_configs) {
static_metadata_[config.id] = std::move(config.characteristics);
if (!config.physical_camera_characteristics.empty()) {
// This is a logical camera
std::vector<std::pair<CameraDeviceStatus, uint32_t>> physical_ids;
size_t physical_device_count = 0;
for (auto const& [physical_id, physical_chars] :
config.physical_camera_characteristics) {
static_metadata_[physical_id] =
HalCameraMetadata::Clone(physical_chars.get());
auto device_status = (physical_device_count < 2)
? CameraDeviceStatus::kPresent
: CameraDeviceStatus::kNotPresent;
physical_ids.push_back({device_status, physical_id});
physical_device_count++;
}
camera_id_map_[config.id] = std::move(physical_ids);
auto physical_devices = std::make_unique<PhysicalDeviceMap>();
for (const auto& physical_device : camera_id_map_.at(config.id)) {
physical_devices->emplace(
physical_device.second,
std::make_pair(
physical_device.first,
HalCameraMetadata::Clone(
static_metadata_.at(physical_device.second).get())));
}
auto updated_logical_chars =
EmulatedLogicalRequestState::AdaptLogicalCharacteristics(
HalCameraMetadata::Clone(static_metadata_.at(config.id).get()),
std::move(physical_devices));
if (updated_logical_chars.get() != nullptr) {
static_metadata_.at(config.id).swap(updated_logical_chars);
} else {
ALOGE(
"%s: Failed to updating logical camera characteristics for id %u!",
__FUNCTION__, config.id);
return BAD_VALUE;
}
} else {
camera_id_map_[config.id] = {};
}
}
return OK;
}
status_t EmulatedCameraProviderHwlImpl::SetCallback(
const HwlCameraProviderCallback& callback) {
torch_cb_ = callback.torch_mode_status_change;
physical_camera_status_cb_ = callback.physical_camera_device_status_change;
return OK;
}
status_t EmulatedCameraProviderHwlImpl::TriggerDeferredCallbacks() {
std::lock_guard<std::mutex> lock(status_callback_future_lock_);
if (status_callback_future_.valid()) {
return OK;
}
status_callback_future_ = std::async(
std::launch::async,
&EmulatedCameraProviderHwlImpl::NotifyPhysicalCameraUnavailable, this);
return OK;
}
void EmulatedCameraProviderHwlImpl::WaitForStatusCallbackFuture() {
{
std::lock_guard<std::mutex> lock(status_callback_future_lock_);
if (!status_callback_future_.valid()) {
// If there is no future pending, construct an empty one.
status_callback_future_ = std::async([]() { return; });
}
}
status_callback_future_.wait();
}
void EmulatedCameraProviderHwlImpl::NotifyPhysicalCameraUnavailable() {
for (const auto& one_map : camera_id_map_) {
for (const auto& physical_device : one_map.second) {
if (physical_device.first != CameraDeviceStatus::kNotPresent) {
continue;
}
uint32_t logical_camera_id = one_map.first;
uint32_t physical_camera_id = physical_device.second;
physical_camera_status_cb_(
logical_camera_id, physical_camera_id,
CameraDeviceStatus::kNotPresent);
}
}
}
status_t EmulatedCameraProviderHwlImpl::GetVendorTags(
std::vector<VendorTagSection>* vendor_tag_sections) {
if (vendor_tag_sections == nullptr) {
ALOGE("%s: vendor_tag_sections is nullptr.", __FUNCTION__);
return BAD_VALUE;
}
// No vendor specific tags as of now
return OK;
}
status_t EmulatedCameraProviderHwlImpl::GetVisibleCameraIds(
std::vector<uint32_t>* camera_ids) {
if (camera_ids == nullptr) {
ALOGE("%s: camera_ids is nullptr.", __FUNCTION__);
return BAD_VALUE;
}
for (const auto& device : camera_id_map_) {
camera_ids->push_back(device.first);
}
return OK;
}
status_t EmulatedCameraProviderHwlImpl::CreateCameraDeviceHwl(
uint32_t camera_id, std::unique_ptr<CameraDeviceHwl>* camera_device_hwl) {
if (camera_device_hwl == nullptr) {
ALOGE("%s: camera_device_hwl is nullptr.", __FUNCTION__);
return BAD_VALUE;
}
if (camera_id_map_.find(camera_id) == camera_id_map_.end()) {
ALOGE("%s: Invalid camera id: %u", __func__, camera_id);
return BAD_VALUE;
}
std::unique_ptr<HalCameraMetadata> meta =
HalCameraMetadata::Clone(static_metadata_.at(camera_id).get());
std::shared_ptr<EmulatedTorchState> torch_state;
camera_metadata_ro_entry entry;
bool flash_supported = false;
auto ret = meta->Get(ANDROID_FLASH_INFO_AVAILABLE, &entry);
if ((ret == OK) && (entry.count == 1)) {
if (entry.data.u8[0] == ANDROID_FLASH_INFO_AVAILABLE_TRUE) {
flash_supported = true;
}
}
if (flash_supported) {
torch_state = std::make_shared<EmulatedTorchState>(camera_id, torch_cb_);
}
auto physical_devices = std::make_unique<PhysicalDeviceMap>();
for (const auto& physical_device : camera_id_map_.at(camera_id)) {
physical_devices->emplace(
physical_device.second,
std::make_pair(physical_device.first,
HalCameraMetadata::Clone(
static_metadata_.at(physical_device.second).get())));
}
*camera_device_hwl = EmulatedCameraDeviceHwlImpl::Create(
camera_id, std::move(meta), std::move(physical_devices), torch_state);
if (*camera_device_hwl == nullptr) {
ALOGE("%s: Cannot create EmulatedCameraDeviceHWlImpl.", __FUNCTION__);
return BAD_VALUE;
}
return OK;
}
status_t EmulatedCameraProviderHwlImpl::CreateBufferAllocatorHwl(
std::unique_ptr<CameraBufferAllocatorHwl>* camera_buffer_allocator_hwl) {
if (camera_buffer_allocator_hwl == nullptr) {
ALOGE("%s: camera_buffer_allocator_hwl is nullptr.", __FUNCTION__);
return BAD_VALUE;
}
// Currently not supported
return INVALID_OPERATION;
}
status_t EmulatedCameraProviderHwlImpl::NotifyDeviceStateChange(
DeviceState /*device_state*/) {
return OK;
}
} // namespace android