blob: 84cf4eafcfb9fff86e2ec7f276860e2bb2d36d76 [file] [log] [blame]
/*
* 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.
*/
#include <system/camera_metadata.h>
#include <camera_metadata_hidden.h>
#define LOG_TAG "GCH_VendorTagUtils"
#include <log/log.h>
#include <map>
#include <string>
#include <unordered_set>
#include "vendor_tag_utils.h"
namespace android {
namespace google_camera_hal {
namespace vendor_tag_utils {
status_t CombineVendorTags(const std::vector<VendorTagSection>& source1,
const std::vector<VendorTagSection>& source2,
std::vector<VendorTagSection>* destination) {
if (destination == nullptr) {
ALOGE("%s destination is nullptr", __FUNCTION__);
return BAD_VALUE;
}
// Temporary sets to guarantee the uniqueness of IDs and tag names
std::unordered_set<std::string> tag_names;
std::unordered_set<uint32_t> tag_ids;
// Maps unique vendor tag section names to a list of tags
std::map<std::string, std::vector<VendorTag>> section_tags;
// Loop through the source1 and source2 section lists
for (auto& section_list : {source1, source2}) {
// Loop through every section
for (const VendorTagSection& section : section_list) {
// Loop through every tag in this section's tag list
for (const VendorTag& tag : section.tags) {
section_tags[section.section_name].push_back(tag);
// Ensure that the vendor tag name is unique
std::string full_tag_name = section.section_name + "." + tag.tag_name;
auto [name_it, name_inserted] = tag_names.insert(full_tag_name);
if (!name_inserted) {
ALOGE(
"%s Error! Vendor tag name collision: Tag %s is used more than "
"once",
__FUNCTION__, full_tag_name.c_str());
return BAD_VALUE;
}
// Ensure that the vendor tag ID is unique
auto [id_it, id_inserted] = tag_ids.insert(tag.tag_id);
if (!id_inserted) {
ALOGE(
"%s Error! Vendor tag ID collision: Tag 0x%x (%u) is used more "
"than once",
__FUNCTION__, tag.tag_id, tag.tag_id);
return BAD_VALUE;
}
}
}
}
// Convert the section_tags map to the resulting type
destination->resize(section_tags.size());
size_t index = 0;
for (auto& [section_name, section_tags] : section_tags) {
destination->at(index).section_name = section_name;
destination->at(index).tags = section_tags;
index++;
}
return OK;
}
} // namespace vendor_tag_utils
// Vendor tag operations called by the camera metadata framework
static int GetCount(const vendor_tag_ops_t* /*tag_ops*/) {
return VendorTagManager::GetInstance().GetCount();
}
static void GetAllTags(const vendor_tag_ops_t* /*tag_ops*/,
uint32_t* tag_array) {
return VendorTagManager::GetInstance().GetAllTags(tag_array);
}
static const char* GetSectionName(const vendor_tag_ops_t* /*tag_ops*/,
uint32_t tag_id) {
return VendorTagManager::GetInstance().GetSectionName(tag_id);
}
static const char* GetTagName(const vendor_tag_ops_t* /*tag_ops*/,
uint32_t tag_id) {
return VendorTagManager::GetInstance().GetTagName(tag_id);
}
static int GetTagType(const vendor_tag_ops_t* /*tag_ops*/, uint32_t tag_id) {
return VendorTagManager::GetInstance().GetTagType(tag_id);
}
VendorTagManager& VendorTagManager::GetInstance() {
static VendorTagManager instance;
return instance;
}
status_t VendorTagManager::AddTags(
const std::vector<VendorTagSection>& tag_sections) {
std::lock_guard<std::mutex> lock(api_mutex_);
std::vector<VendorTagSection> combined_tags;
status_t res = vendor_tag_utils::CombineVendorTags(
tag_sections_, tag_sections, &combined_tags);
if (res != OK) {
ALOGE("%s: CombineVendorTags() failed: %s(%d)", __FUNCTION__,
strerror(-res), res);
return res;
}
tag_sections_ = combined_tags;
// Add new tags to internal maps to help speed up the metadata framework
// lookup calls
for (auto& section : tag_sections) {
for (auto& tag : section.tags) {
vendor_tag_map_[tag.tag_id] =
VendorTagInfo{.tag_id = tag.tag_id,
.tag_type = static_cast<int>(tag.tag_type),
.section_name = section.section_name,
.tag_name = tag.tag_name};
vendor_tag_inverse_map_[TagString(section.section_name, tag.tag_name)] =
tag.tag_id;
}
}
// Vendor tag callbacks used by the camera metadata framework
static vendor_tag_ops_t vendor_tag_ops = {
.get_tag_count = google_camera_hal::GetCount,
.get_all_tags = google_camera_hal::GetAllTags,
.get_section_name = google_camera_hal::GetSectionName,
.get_tag_name = google_camera_hal::GetTagName,
.get_tag_type = google_camera_hal::GetTagType,
};
res = set_camera_metadata_vendor_ops(&vendor_tag_ops);
if (res != OK) {
ALOGE("%s: set_camera_metadata_vendor_ops() failed: %s(%d)", __FUNCTION__,
strerror(-res), res);
return res;
}
return OK;
}
const std::vector<VendorTagSection>& VendorTagManager::GetTags() const {
return tag_sections_;
}
void VendorTagManager::Reset() {
std::lock_guard<std::mutex> lock(api_mutex_);
vendor_tag_map_.clear();
tag_sections_.clear();
set_camera_metadata_vendor_ops(nullptr);
}
int VendorTagManager::GetCount() const {
std::lock_guard<std::mutex> lock(api_mutex_);
return static_cast<int>(vendor_tag_map_.size());
}
void VendorTagManager::GetAllTags(uint32_t* tag_array) const {
std::lock_guard<std::mutex> lock(api_mutex_);
if (tag_array == nullptr) {
ALOGE("%s tag_array is nullptr", __FUNCTION__);
return;
}
uint32_t index = 0;
for (auto& [tag_id, tag_descriptor] : vendor_tag_map_) {
tag_array[index++] = tag_id;
}
}
const char* VendorTagManager::GetSectionName(uint32_t tag_id) const {
std::lock_guard<std::mutex> lock(api_mutex_);
auto it = vendor_tag_map_.find(tag_id);
if (it == vendor_tag_map_.end()) {
ALOGE("%s Unknown vendor tag ID: %u", __FUNCTION__, tag_id);
return "unknown";
}
return it->second.section_name.c_str();
}
const char* VendorTagManager::GetTagName(uint32_t tag_id) const {
std::lock_guard<std::mutex> lock(api_mutex_);
auto it = vendor_tag_map_.find(tag_id);
if (it == vendor_tag_map_.end()) {
ALOGE("%s Unknown vendor tag ID: %u", __FUNCTION__, tag_id);
return "unknown";
}
return it->second.tag_name.c_str();
}
int VendorTagManager::GetTagType(uint32_t tag_id) const {
std::lock_guard<std::mutex> lock(api_mutex_);
auto it = vendor_tag_map_.find(tag_id);
if (it == vendor_tag_map_.end()) {
ALOGE("%s Unknown vendor tag ID: 0x%x (%u)", __FUNCTION__, tag_id, tag_id);
return -1;
}
return it->second.tag_type;
}
status_t VendorTagManager::GetTagInfo(uint32_t tag_id, VendorTagInfo* tag_info) {
if (tag_info == nullptr) {
ALOGE("%s tag_info is nullptr", __FUNCTION__);
return BAD_VALUE;
}
std::lock_guard<std::mutex> lock(api_mutex_);
auto itr = vendor_tag_map_.find(tag_id);
if (itr == vendor_tag_map_.end()) {
ALOGE("%s Given tag_id not found", __FUNCTION__);
return BAD_VALUE;
}
*tag_info = itr->second;
return OK;
}
status_t VendorTagManager::GetTag(const std::string section_name,
const std::string tag_name, uint32_t* tag_id) {
if (tag_id == nullptr) {
ALOGE("%s tag_id is nullptr", __FUNCTION__);
return BAD_VALUE;
}
std::lock_guard<std::mutex> lock(api_mutex_);
const TagString section_tag{section_name, tag_name};
auto itr = vendor_tag_inverse_map_.find(section_tag);
if (itr == vendor_tag_inverse_map_.end()) {
ALOGE("%s Given section/tag names not found", __FUNCTION__);
return BAD_VALUE;
}
*tag_id = itr->second;
return OK;
}
} // namespace google_camera_hal
} // namespace android