1 /*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <system/camera_metadata.h>
18 #include <camera_metadata_hidden.h>
19
20 #define LOG_TAG "GCH_VendorTagUtils"
21 #include <log/log.h>
22
23 #include <map>
24 #include <string>
25 #include <unordered_set>
26
27 #include "vendor_tag_utils.h"
28
29 namespace android {
30 namespace google_camera_hal {
31 namespace vendor_tag_utils {
32
CombineVendorTags(const std::vector<VendorTagSection> & source1,const std::vector<VendorTagSection> & source2,std::vector<VendorTagSection> * destination)33 status_t CombineVendorTags(const std::vector<VendorTagSection>& source1,
34 const std::vector<VendorTagSection>& source2,
35 std::vector<VendorTagSection>* destination) {
36 if (destination == nullptr) {
37 ALOGE("%s destination is nullptr", __FUNCTION__);
38 return BAD_VALUE;
39 }
40
41 // Temporary sets to guarantee the uniqueness of IDs and tag names
42 std::unordered_set<std::string> tag_names;
43 std::unordered_set<uint32_t> tag_ids;
44 // Maps unique vendor tag section names to a list of tags
45 std::map<std::string, std::vector<VendorTag>> section_tags;
46
47 // Loop through the source1 and source2 section lists
48 for (auto& section_list : {source1, source2}) {
49 // Loop through every section
50 for (const VendorTagSection& section : section_list) {
51 // Loop through every tag in this section's tag list
52 for (const VendorTag& tag : section.tags) {
53 section_tags[section.section_name].push_back(tag);
54
55 // Ensure that the vendor tag name is unique
56 std::string full_tag_name = section.section_name + "." + tag.tag_name;
57 auto [name_it, name_inserted] = tag_names.insert(full_tag_name);
58 if (!name_inserted) {
59 ALOGE(
60 "%s Error! Vendor tag name collision: Tag %s is used more than "
61 "once",
62 __FUNCTION__, full_tag_name.c_str());
63 return BAD_VALUE;
64 }
65
66 // Ensure that the vendor tag ID is unique
67 auto [id_it, id_inserted] = tag_ids.insert(tag.tag_id);
68 if (!id_inserted) {
69 ALOGE(
70 "%s Error! Vendor tag ID collision: Tag 0x%x (%u) is used more "
71 "than once",
72 __FUNCTION__, tag.tag_id, tag.tag_id);
73 return BAD_VALUE;
74 }
75 }
76 }
77 }
78
79 // Convert the section_tags map to the resulting type
80 destination->resize(section_tags.size());
81 size_t index = 0;
82 for (auto& [section_name, section_tags] : section_tags) {
83 destination->at(index).section_name = section_name;
84 destination->at(index).tags = section_tags;
85 index++;
86 }
87
88 return OK;
89 }
90 } // namespace vendor_tag_utils
91
92 // Vendor tag operations called by the camera metadata framework
GetCount(const vendor_tag_ops_t *)93 static int GetCount(const vendor_tag_ops_t* /*tag_ops*/) {
94 return VendorTagManager::GetInstance().GetCount();
95 }
96
GetAllTags(const vendor_tag_ops_t *,uint32_t * tag_array)97 static void GetAllTags(const vendor_tag_ops_t* /*tag_ops*/,
98 uint32_t* tag_array) {
99 return VendorTagManager::GetInstance().GetAllTags(tag_array);
100 }
101
GetSectionName(const vendor_tag_ops_t *,uint32_t tag_id)102 static const char* GetSectionName(const vendor_tag_ops_t* /*tag_ops*/,
103 uint32_t tag_id) {
104 return VendorTagManager::GetInstance().GetSectionName(tag_id);
105 }
106
GetTagName(const vendor_tag_ops_t *,uint32_t tag_id)107 static const char* GetTagName(const vendor_tag_ops_t* /*tag_ops*/,
108 uint32_t tag_id) {
109 return VendorTagManager::GetInstance().GetTagName(tag_id);
110 }
111
GetTagType(const vendor_tag_ops_t *,uint32_t tag_id)112 static int GetTagType(const vendor_tag_ops_t* /*tag_ops*/, uint32_t tag_id) {
113 return VendorTagManager::GetInstance().GetTagType(tag_id);
114 }
115
GetInstance()116 VendorTagManager& VendorTagManager::GetInstance() {
117 static VendorTagManager instance;
118 return instance;
119 }
120
AddTags(const std::vector<VendorTagSection> & tag_sections)121 status_t VendorTagManager::AddTags(
122 const std::vector<VendorTagSection>& tag_sections) {
123 std::lock_guard<std::mutex> lock(api_mutex_);
124
125 std::vector<VendorTagSection> combined_tags;
126 status_t res = vendor_tag_utils::CombineVendorTags(
127 tag_sections_, tag_sections, &combined_tags);
128 if (res != OK) {
129 ALOGE("%s: CombineVendorTags() failed: %s(%d)", __FUNCTION__,
130 strerror(-res), res);
131 return res;
132 }
133 tag_sections_ = combined_tags;
134
135 // Add new tags to internal maps to help speed up the metadata framework
136 // lookup calls
137 for (auto& section : tag_sections) {
138 for (auto& tag : section.tags) {
139 vendor_tag_map_[tag.tag_id] =
140 VendorTagInfo{.tag_id = tag.tag_id,
141 .tag_type = static_cast<int>(tag.tag_type),
142 .section_name = section.section_name,
143 .tag_name = tag.tag_name};
144
145 vendor_tag_inverse_map_[TagString(section.section_name, tag.tag_name)] =
146 tag.tag_id;
147 }
148 }
149
150 // Vendor tag callbacks used by the camera metadata framework
151 static vendor_tag_ops_t vendor_tag_ops = {
152 .get_tag_count = google_camera_hal::GetCount,
153 .get_all_tags = google_camera_hal::GetAllTags,
154 .get_section_name = google_camera_hal::GetSectionName,
155 .get_tag_name = google_camera_hal::GetTagName,
156 .get_tag_type = google_camera_hal::GetTagType,
157 };
158 res = set_camera_metadata_vendor_ops(&vendor_tag_ops);
159 if (res != OK) {
160 ALOGE("%s: set_camera_metadata_vendor_ops() failed: %s(%d)", __FUNCTION__,
161 strerror(-res), res);
162 return res;
163 }
164
165 return OK;
166 }
167
GetTags() const168 const std::vector<VendorTagSection>& VendorTagManager::GetTags() const {
169 return tag_sections_;
170 }
171
Reset()172 void VendorTagManager::Reset() {
173 std::lock_guard<std::mutex> lock(api_mutex_);
174 vendor_tag_map_.clear();
175 tag_sections_.clear();
176 set_camera_metadata_vendor_ops(nullptr);
177 }
178
GetCount() const179 int VendorTagManager::GetCount() const {
180 std::lock_guard<std::mutex> lock(api_mutex_);
181 return static_cast<int>(vendor_tag_map_.size());
182 }
183
GetAllTags(uint32_t * tag_array) const184 void VendorTagManager::GetAllTags(uint32_t* tag_array) const {
185 std::lock_guard<std::mutex> lock(api_mutex_);
186 if (tag_array == nullptr) {
187 ALOGE("%s tag_array is nullptr", __FUNCTION__);
188 return;
189 }
190
191 uint32_t index = 0;
192 for (auto& [tag_id, tag_descriptor] : vendor_tag_map_) {
193 tag_array[index++] = tag_id;
194 }
195 }
196
GetSectionName(uint32_t tag_id) const197 const char* VendorTagManager::GetSectionName(uint32_t tag_id) const {
198 std::lock_guard<std::mutex> lock(api_mutex_);
199 auto it = vendor_tag_map_.find(tag_id);
200 if (it == vendor_tag_map_.end()) {
201 ALOGE("%s Unknown vendor tag ID: %u", __FUNCTION__, tag_id);
202 return "unknown";
203 }
204
205 return it->second.section_name.c_str();
206 }
207
GetTagName(uint32_t tag_id) const208 const char* VendorTagManager::GetTagName(uint32_t tag_id) const {
209 std::lock_guard<std::mutex> lock(api_mutex_);
210 auto it = vendor_tag_map_.find(tag_id);
211 if (it == vendor_tag_map_.end()) {
212 ALOGE("%s Unknown vendor tag ID: %u", __FUNCTION__, tag_id);
213 return "unknown";
214 }
215
216 return it->second.tag_name.c_str();
217 }
218
GetTagType(uint32_t tag_id) const219 int VendorTagManager::GetTagType(uint32_t tag_id) const {
220 std::lock_guard<std::mutex> lock(api_mutex_);
221 auto it = vendor_tag_map_.find(tag_id);
222 if (it == vendor_tag_map_.end()) {
223 ALOGE("%s Unknown vendor tag ID: 0x%x (%u)", __FUNCTION__, tag_id, tag_id);
224 return -1;
225 }
226
227 return it->second.tag_type;
228 }
229
GetTagInfo(uint32_t tag_id,VendorTagInfo * tag_info)230 status_t VendorTagManager::GetTagInfo(uint32_t tag_id, VendorTagInfo* tag_info) {
231 if (tag_info == nullptr) {
232 ALOGE("%s tag_info is nullptr", __FUNCTION__);
233 return BAD_VALUE;
234 }
235 std::lock_guard<std::mutex> lock(api_mutex_);
236 auto itr = vendor_tag_map_.find(tag_id);
237 if (itr == vendor_tag_map_.end()) {
238 ALOGE("%s Given tag_id not found", __FUNCTION__);
239 return BAD_VALUE;
240 }
241
242 *tag_info = itr->second;
243 return OK;
244 }
245
GetTag(const std::string section_name,const std::string tag_name,uint32_t * tag_id)246 status_t VendorTagManager::GetTag(const std::string section_name,
247 const std::string tag_name, uint32_t* tag_id) {
248 if (tag_id == nullptr) {
249 ALOGE("%s tag_id is nullptr", __FUNCTION__);
250 return BAD_VALUE;
251 }
252 std::lock_guard<std::mutex> lock(api_mutex_);
253
254 const TagString section_tag{section_name, tag_name};
255
256 auto itr = vendor_tag_inverse_map_.find(section_tag);
257 if (itr == vendor_tag_inverse_map_.end()) {
258 ALOGE("%s Given section/tag names not found", __FUNCTION__);
259 return BAD_VALUE;
260 }
261
262 *tag_id = itr->second;
263 return OK;
264 }
265
266 } // namespace google_camera_hal
267 } // namespace android
268