blob: 05d078be95e2dfcc6e1525ee7c1d3620f84a20e6 [file] [log] [blame]
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -07001/*
2 * Copyright (C) 2012 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
Igor Murashkine2d1e3d2013-04-30 18:18:06 -070017// #define LOG_NDEBUG 0
18
Eino-Ville Talvala4bb81182012-09-24 09:46:53 -070019#define LOG_TAG "Camera2-Metadata"
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -070020#include <utils/Log.h>
21#include <utils/Errors.h>
22
Igor Murashkine7ee7632013-06-11 18:10:18 -070023#include <binder/Parcel.h>
Eino-Ville Talvala4d453832016-07-15 11:56:53 -070024#include <camera/CameraMetadata.h>
Emilian Peev0ec234e2020-08-24 11:48:50 -070025#include <camera_metadata_hidden.h>
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -070026
27namespace android {
28
Zhijun He146aed12013-12-05 07:46:51 -080029#define ALIGN_TO(val, alignment) \
30 (((uintptr_t)(val) + ((alignment) - 1)) & ~((alignment) - 1))
31
Igor Murashkine7ee7632013-06-11 18:10:18 -070032typedef Parcel::WritableBlob WritableBlob;
33typedef Parcel::ReadableBlob ReadableBlob;
34
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -070035CameraMetadata::CameraMetadata() :
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -080036 mBuffer(NULL), mLocked(false) {
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -070037}
38
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -080039CameraMetadata::CameraMetadata(size_t entryCapacity, size_t dataCapacity) :
40 mLocked(false)
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -070041{
42 mBuffer = allocate_camera_metadata(entryCapacity, dataCapacity);
43}
44
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -080045CameraMetadata::CameraMetadata(const CameraMetadata &other) :
46 mLocked(false) {
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -070047 mBuffer = clone_camera_metadata(other.mBuffer);
48}
49
Jayant Chowdhary8a0be292020-01-08 13:10:38 -080050CameraMetadata::CameraMetadata(CameraMetadata &&other) :mBuffer(NULL), mLocked(false) {
51 acquire(other);
52}
53
54CameraMetadata &CameraMetadata::operator=(CameraMetadata &&other) {
55 acquire(other);
56 return *this;
57}
58
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -080059CameraMetadata::CameraMetadata(camera_metadata_t *buffer) :
60 mBuffer(NULL), mLocked(false) {
Igor Murashkin7efa5202013-02-13 15:53:56 -080061 acquire(buffer);
62}
63
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -070064CameraMetadata &CameraMetadata::operator=(const CameraMetadata &other) {
65 return operator=(other.mBuffer);
66}
67
68CameraMetadata &CameraMetadata::operator=(const camera_metadata_t *buffer) {
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -080069 if (mLocked) {
70 ALOGE("%s: Assignment to a locked CameraMetadata!", __FUNCTION__);
71 return *this;
72 }
73
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -070074 if (CC_LIKELY(buffer != mBuffer)) {
75 camera_metadata_t *newBuffer = clone_camera_metadata(buffer);
76 clear();
77 mBuffer = newBuffer;
78 }
79 return *this;
80}
81
82CameraMetadata::~CameraMetadata() {
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -080083 mLocked = false;
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -070084 clear();
85}
86
Yin-Chia Yeh54298b32015-03-24 16:51:41 -070087const camera_metadata_t* CameraMetadata::getAndLock() const {
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -080088 mLocked = true;
89 return mBuffer;
90}
91
Yin-Chia Yeh8aac03f2016-03-03 15:45:23 -080092status_t CameraMetadata::unlock(const camera_metadata_t *buffer) const {
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -080093 if (!mLocked) {
94 ALOGE("%s: Can't unlock a non-locked CameraMetadata!", __FUNCTION__);
95 return INVALID_OPERATION;
96 }
97 if (buffer != mBuffer) {
98 ALOGE("%s: Can't unlock CameraMetadata with wrong pointer!",
99 __FUNCTION__);
100 return BAD_VALUE;
101 }
102 mLocked = false;
103 return OK;
104}
105
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700106camera_metadata_t* CameraMetadata::release() {
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800107 if (mLocked) {
108 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
109 return NULL;
110 }
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700111 camera_metadata_t *released = mBuffer;
112 mBuffer = NULL;
113 return released;
114}
115
116void CameraMetadata::clear() {
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800117 if (mLocked) {
118 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
119 return;
120 }
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700121 if (mBuffer) {
122 free_camera_metadata(mBuffer);
123 mBuffer = NULL;
124 }
125}
126
127void CameraMetadata::acquire(camera_metadata_t *buffer) {
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800128 if (mLocked) {
129 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
130 return;
131 }
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700132 clear();
133 mBuffer = buffer;
Igor Murashkine2d1e3d2013-04-30 18:18:06 -0700134
wangxiaobin274a28c2025-02-07 14:52:18 +0800135 IF_ALOGV() {
136 ALOGE_IF(validate_camera_metadata_structure(mBuffer, /*size*/NULL) != OK,
137 "%s: Failed to validate metadata structure %p",
138 __FUNCTION__, buffer);
139 }
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700140}
141
142void CameraMetadata::acquire(CameraMetadata &other) {
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800143 if (mLocked) {
144 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
145 return;
146 }
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700147 acquire(other.release());
148}
149
150status_t CameraMetadata::append(const CameraMetadata &other) {
Eino-Ville Talvalafd6ecdd2013-10-11 09:51:09 -0700151 return append(other.mBuffer);
152}
153
154status_t CameraMetadata::append(const camera_metadata_t* other) {
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800155 if (mLocked) {
156 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
157 return INVALID_OPERATION;
158 }
Eino-Ville Talvalafd6ecdd2013-10-11 09:51:09 -0700159 size_t extraEntries = get_camera_metadata_entry_count(other);
160 size_t extraData = get_camera_metadata_data_count(other);
161 resizeIfNeeded(extraEntries, extraData);
162
163 return append_camera_metadata(mBuffer, other);
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700164}
165
166size_t CameraMetadata::entryCount() const {
167 return (mBuffer == NULL) ? 0 :
168 get_camera_metadata_entry_count(mBuffer);
169}
170
Eino-Ville Talvalada6665c2012-08-29 17:37:16 -0700171bool CameraMetadata::isEmpty() const {
172 return entryCount() == 0;
173}
174
Emilian Peev5f268f32020-09-09 17:29:48 -0700175size_t CameraMetadata::bufferSize() const {
176 return (mBuffer == NULL) ? 0 :
177 get_camera_metadata_size(mBuffer);
178}
179
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700180status_t CameraMetadata::sort() {
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800181 if (mLocked) {
182 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
183 return INVALID_OPERATION;
184 }
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700185 return sort_camera_metadata(mBuffer);
186}
187
188status_t CameraMetadata::checkType(uint32_t tag, uint8_t expectedType) {
Emilian Peev71c73a22017-03-21 16:35:51 +0000189 int tagType = get_local_camera_metadata_tag_type(tag, mBuffer);
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700190 if ( CC_UNLIKELY(tagType == -1)) {
191 ALOGE("Update metadata entry: Unknown tag %d", tag);
192 return INVALID_OPERATION;
193 }
194 if ( CC_UNLIKELY(tagType != expectedType) ) {
195 ALOGE("Mismatched tag type when updating entry %s (%d) of type %s; "
196 "got type %s data instead ",
Emilian Peev71c73a22017-03-21 16:35:51 +0000197 get_local_camera_metadata_tag_name(tag, mBuffer), tag,
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700198 camera_metadata_type_names[tagType],
199 camera_metadata_type_names[expectedType]);
200 return INVALID_OPERATION;
201 }
202 return OK;
203}
204
205status_t CameraMetadata::update(uint32_t tag,
206 const int32_t *data, size_t data_count) {
207 status_t res;
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800208 if (mLocked) {
209 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
210 return INVALID_OPERATION;
211 }
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700212 if ( (res = checkType(tag, TYPE_INT32)) != OK) {
213 return res;
214 }
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800215 return updateImpl(tag, (const void*)data, data_count);
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700216}
217
218status_t CameraMetadata::update(uint32_t tag,
219 const uint8_t *data, size_t data_count) {
220 status_t res;
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800221 if (mLocked) {
222 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
223 return INVALID_OPERATION;
224 }
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700225 if ( (res = checkType(tag, TYPE_BYTE)) != OK) {
226 return res;
227 }
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800228 return updateImpl(tag, (const void*)data, data_count);
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700229}
230
231status_t CameraMetadata::update(uint32_t tag,
232 const float *data, size_t data_count) {
233 status_t res;
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800234 if (mLocked) {
235 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
236 return INVALID_OPERATION;
237 }
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700238 if ( (res = checkType(tag, TYPE_FLOAT)) != OK) {
239 return res;
240 }
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800241 return updateImpl(tag, (const void*)data, data_count);
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700242}
243
244status_t CameraMetadata::update(uint32_t tag,
245 const int64_t *data, size_t data_count) {
246 status_t res;
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800247 if (mLocked) {
248 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
249 return INVALID_OPERATION;
250 }
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700251 if ( (res = checkType(tag, TYPE_INT64)) != OK) {
252 return res;
253 }
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800254 return updateImpl(tag, (const void*)data, data_count);
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700255}
256
257status_t CameraMetadata::update(uint32_t tag,
258 const double *data, size_t data_count) {
259 status_t res;
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800260 if (mLocked) {
261 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
262 return INVALID_OPERATION;
263 }
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700264 if ( (res = checkType(tag, TYPE_DOUBLE)) != OK) {
265 return res;
266 }
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800267 return updateImpl(tag, (const void*)data, data_count);
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700268}
269
270status_t CameraMetadata::update(uint32_t tag,
271 const camera_metadata_rational_t *data, size_t data_count) {
272 status_t res;
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800273 if (mLocked) {
274 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
275 return INVALID_OPERATION;
276 }
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700277 if ( (res = checkType(tag, TYPE_RATIONAL)) != OK) {
278 return res;
279 }
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800280 return updateImpl(tag, (const void*)data, data_count);
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700281}
282
283status_t CameraMetadata::update(uint32_t tag,
284 const String8 &string) {
285 status_t res;
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800286 if (mLocked) {
287 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
288 return INVALID_OPERATION;
289 }
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700290 if ( (res = checkType(tag, TYPE_BYTE)) != OK) {
291 return res;
292 }
Zhijun He7595c472014-03-27 16:46:15 -0700293 // string.size() doesn't count the null termination character.
Tomasz Wasilczyk12b04a52023-08-11 15:52:22 +0000294 return updateImpl(tag, (const void*)string.c_str(), string.size() + 1);
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700295}
296
Eino-Ville Talvala4d453832016-07-15 11:56:53 -0700297status_t CameraMetadata::update(const camera_metadata_ro_entry &entry) {
298 status_t res;
299 if (mLocked) {
300 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
301 return INVALID_OPERATION;
302 }
303 if ( (res = checkType(entry.tag, entry.type)) != OK) {
304 return res;
305 }
306 return updateImpl(entry.tag, (const void*)entry.data.u8, entry.count);
307}
308
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800309status_t CameraMetadata::updateImpl(uint32_t tag, const void *data,
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700310 size_t data_count) {
311 status_t res;
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800312 if (mLocked) {
313 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
314 return INVALID_OPERATION;
315 }
Emilian Peev71c73a22017-03-21 16:35:51 +0000316 int type = get_local_camera_metadata_tag_type(tag, mBuffer);
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700317 if (type == -1) {
318 ALOGE("%s: Tag %d not found", __FUNCTION__, tag);
319 return BAD_VALUE;
320 }
Eino-Ville Talvalae2b60c82015-07-17 16:21:44 -0700321 // Safety check - ensure that data isn't pointing to this metadata, since
322 // that would get invalidated if a resize is needed
323 size_t bufferSize = get_camera_metadata_size(mBuffer);
324 uintptr_t bufAddr = reinterpret_cast<uintptr_t>(mBuffer);
325 uintptr_t dataAddr = reinterpret_cast<uintptr_t>(data);
326 if (dataAddr > bufAddr && dataAddr < (bufAddr + bufferSize)) {
327 ALOGE("%s: Update attempted with data from the same metadata buffer!",
328 __FUNCTION__);
329 return INVALID_OPERATION;
330 }
331
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700332 size_t data_size = calculate_camera_metadata_entry_data_size(type,
333 data_count);
334
335 res = resizeIfNeeded(1, data_size);
336
337 if (res == OK) {
338 camera_metadata_entry_t entry;
339 res = find_camera_metadata_entry(mBuffer, tag, &entry);
340 if (res == NAME_NOT_FOUND) {
341 res = add_camera_metadata_entry(mBuffer,
342 tag, data, data_count);
343 } else if (res == OK) {
344 res = update_camera_metadata_entry(mBuffer,
345 entry.index, data, data_count, NULL);
346 }
347 }
348
349 if (res != OK) {
350 ALOGE("%s: Unable to update metadata entry %s.%s (%x): %s (%d)",
Emilian Peev71c73a22017-03-21 16:35:51 +0000351 __FUNCTION__, get_local_camera_metadata_section_name(tag, mBuffer),
352 get_local_camera_metadata_tag_name(tag, mBuffer), tag,
353 strerror(-res), res);
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700354 }
Igor Murashkine2d1e3d2013-04-30 18:18:06 -0700355
356 IF_ALOGV() {
357 ALOGE_IF(validate_camera_metadata_structure(mBuffer, /*size*/NULL) !=
358 OK,
359
360 "%s: Failed to validate metadata structure after update %p",
361 __FUNCTION__, mBuffer);
362 }
363
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700364 return res;
365}
366
Igor Murashkinfc42642a2013-02-13 18:23:39 -0800367bool CameraMetadata::exists(uint32_t tag) const {
368 camera_metadata_ro_entry entry;
369 return find_camera_metadata_ro_entry(mBuffer, tag, &entry) == 0;
370}
371
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700372camera_metadata_entry_t CameraMetadata::find(uint32_t tag) {
373 status_t res;
374 camera_metadata_entry entry;
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800375 if (mLocked) {
376 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
377 entry.count = 0;
378 return entry;
379 }
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700380 res = find_camera_metadata_entry(mBuffer, tag, &entry);
381 if (CC_UNLIKELY( res != OK )) {
382 entry.count = 0;
383 entry.data.u8 = NULL;
384 }
385 return entry;
386}
387
388camera_metadata_ro_entry_t CameraMetadata::find(uint32_t tag) const {
389 status_t res;
390 camera_metadata_ro_entry entry;
391 res = find_camera_metadata_ro_entry(mBuffer, tag, &entry);
392 if (CC_UNLIKELY( res != OK )) {
393 entry.count = 0;
394 entry.data.u8 = NULL;
395 }
396 return entry;
397}
398
399status_t CameraMetadata::erase(uint32_t tag) {
400 camera_metadata_entry_t entry;
401 status_t res;
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800402 if (mLocked) {
403 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
404 return INVALID_OPERATION;
405 }
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700406 res = find_camera_metadata_entry(mBuffer, tag, &entry);
407 if (res == NAME_NOT_FOUND) {
408 return OK;
409 } else if (res != OK) {
410 ALOGE("%s: Error looking for entry %s.%s (%x): %s %d",
411 __FUNCTION__,
Emilian Peev71c73a22017-03-21 16:35:51 +0000412 get_local_camera_metadata_section_name(tag, mBuffer),
413 get_local_camera_metadata_tag_name(tag, mBuffer),
414 tag, strerror(-res), res);
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700415 return res;
416 }
417 res = delete_camera_metadata_entry(mBuffer, entry.index);
418 if (res != OK) {
419 ALOGE("%s: Error deleting entry %s.%s (%x): %s %d",
420 __FUNCTION__,
Emilian Peev71c73a22017-03-21 16:35:51 +0000421 get_local_camera_metadata_section_name(tag, mBuffer),
422 get_local_camera_metadata_tag_name(tag, mBuffer),
423 tag, strerror(-res), res);
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700424 }
425 return res;
426}
427
Emilian Peeve20c6372018-08-14 18:45:53 +0100428status_t CameraMetadata::removePermissionEntries(metadata_vendor_id_t vendorId,
429 std::vector<int32_t> *tagsRemoved) {
430 uint32_t tagCount = 0;
431 std::vector<uint32_t> tagsToRemove;
432
433 if (tagsRemoved == nullptr) {
434 return BAD_VALUE;
435 }
436
437 sp<VendorTagDescriptor> vTags = VendorTagDescriptor::getGlobalVendorTagDescriptor();
438 if ((nullptr == vTags.get()) || (0 >= vTags->getTagCount())) {
439 sp<VendorTagDescriptorCache> cache =
440 VendorTagDescriptorCache::getGlobalVendorTagCache();
441 if (cache.get()) {
442 cache->getVendorTagDescriptor(vendorId, &vTags);
443 }
444 }
445
446 if ((nullptr != vTags.get()) && (vTags->getTagCount() > 0)) {
447 tagCount = vTags->getTagCount();
448 uint32_t *vendorTags = new uint32_t[tagCount];
449 if (nullptr == vendorTags) {
450 return NO_MEMORY;
451 }
452 vTags->getTagArray(vendorTags);
453
454 tagsToRemove.reserve(tagCount);
455 tagsToRemove.insert(tagsToRemove.begin(), vendorTags, vendorTags + tagCount);
456
457 delete [] vendorTags;
458 tagCount = 0;
459 }
460
461 auto tagsNeedingPermission = get_camera_metadata_permission_needed(&tagCount);
462 if (tagCount > 0) {
463 tagsToRemove.reserve(tagsToRemove.capacity() + tagCount);
464 tagsToRemove.insert(tagsToRemove.end(), tagsNeedingPermission,
465 tagsNeedingPermission + tagCount);
466 }
467
468 tagsRemoved->reserve(tagsToRemove.size());
469 for (const auto &it : tagsToRemove) {
470 if (exists(it)) {
471 auto rc = erase(it);
472 if (NO_ERROR != rc) {
473 ALOGE("%s: Failed to erase tag: %x", __func__, it);
474 return rc;
475 }
476 tagsRemoved->push_back(it);
477 }
478 }
479
480 // Update the available characterstics accordingly
481 if (exists(ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS)) {
482 std::vector<uint32_t> currentKeys;
483
484 std::sort(tagsRemoved->begin(), tagsRemoved->end());
485 auto keys = find(ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS);
486 currentKeys.reserve(keys.count);
487 currentKeys.insert(currentKeys.end(), keys.data.i32, keys.data.i32 + keys.count);
488 std::sort(currentKeys.begin(), currentKeys.end());
489
490 std::vector<int32_t> newKeys(keys.count);
491 auto end = std::set_difference(currentKeys.begin(), currentKeys.end(), tagsRemoved->begin(),
492 tagsRemoved->end(), newKeys.begin());
493 newKeys.resize(end - newKeys.begin());
494
495 update(ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS, newKeys.data(), newKeys.size());
496 }
497
498 return NO_ERROR;
499}
500
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700501void CameraMetadata::dump(int fd, int verbosity, int indentation) const {
502 dump_indented_camera_metadata(mBuffer, fd, verbosity, indentation);
503}
504
505status_t CameraMetadata::resizeIfNeeded(size_t extraEntries, size_t extraData) {
506 if (mBuffer == NULL) {
507 mBuffer = allocate_camera_metadata(extraEntries * 2, extraData * 2);
508 if (mBuffer == NULL) {
509 ALOGE("%s: Can't allocate larger metadata buffer", __FUNCTION__);
510 return NO_MEMORY;
511 }
512 } else {
513 size_t currentEntryCount = get_camera_metadata_entry_count(mBuffer);
514 size_t currentEntryCap = get_camera_metadata_entry_capacity(mBuffer);
515 size_t newEntryCount = currentEntryCount +
516 extraEntries;
517 newEntryCount = (newEntryCount > currentEntryCap) ?
518 newEntryCount * 2 : currentEntryCap;
519
520 size_t currentDataCount = get_camera_metadata_data_count(mBuffer);
521 size_t currentDataCap = get_camera_metadata_data_capacity(mBuffer);
522 size_t newDataCount = currentDataCount +
523 extraData;
524 newDataCount = (newDataCount > currentDataCap) ?
525 newDataCount * 2 : currentDataCap;
526
527 if (newEntryCount > currentEntryCap ||
528 newDataCount > currentDataCap) {
529 camera_metadata_t *oldBuffer = mBuffer;
530 mBuffer = allocate_camera_metadata(newEntryCount,
531 newDataCount);
532 if (mBuffer == NULL) {
Jayant Chowdharya94cbe62021-04-29 13:22:58 -0700533 // Maintain old buffer to avoid potential memory leak.
534 mBuffer = oldBuffer;
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700535 ALOGE("%s: Can't allocate larger metadata buffer", __FUNCTION__);
536 return NO_MEMORY;
537 }
538 append_camera_metadata(mBuffer, oldBuffer);
539 free_camera_metadata(oldBuffer);
540 }
541 }
542 return OK;
543}
544
Igor Murashkine7ee7632013-06-11 18:10:18 -0700545status_t CameraMetadata::readFromParcel(const Parcel& data,
546 camera_metadata_t** out) {
Jayant Chowdhary2e310da2020-05-12 12:40:36 -0700547
Igor Murashkine7ee7632013-06-11 18:10:18 -0700548 status_t err = OK;
549
550 camera_metadata_t* metadata = NULL;
551
552 if (out) {
553 *out = NULL;
554 }
555
Zhijun He146aed12013-12-05 07:46:51 -0800556 // See CameraMetadata::writeToParcel for parcel data layout diagram and explanation.
557 // arg0 = blobSize (int32)
558 int32_t blobSizeTmp = -1;
559 if ((err = data.readInt32(&blobSizeTmp)) != OK) {
Igor Murashkine7ee7632013-06-11 18:10:18 -0700560 ALOGE("%s: Failed to read metadata size (error %d %s)",
561 __FUNCTION__, err, strerror(-err));
562 return err;
563 }
Zhijun He146aed12013-12-05 07:46:51 -0800564 const size_t blobSize = static_cast<size_t>(blobSizeTmp);
565 const size_t alignment = get_camera_metadata_alignment();
Igor Murashkine7ee7632013-06-11 18:10:18 -0700566
Zhijun He146aed12013-12-05 07:46:51 -0800567 // Special case: zero blob size means zero sized (NULL) metadata.
568 if (blobSize == 0) {
Igor Murashkine7ee7632013-06-11 18:10:18 -0700569 ALOGV("%s: Read 0-sized metadata", __FUNCTION__);
570 return OK;
571 }
572
Zhijun He146aed12013-12-05 07:46:51 -0800573 if (blobSize <= alignment) {
574 ALOGE("%s: metadata blob is malformed, blobSize(%zu) should be larger than alignment(%zu)",
575 __FUNCTION__, blobSize, alignment);
576 return BAD_VALUE;
577 }
578
579 const size_t metadataSize = blobSize - alignment;
580
581 // NOTE: this doesn't make sense to me. shouldn't the blob
Igor Murashkine7ee7632013-06-11 18:10:18 -0700582 // know how big it is? why do we have to specify the size
583 // to Parcel::readBlob ?
Igor Murashkine7ee7632013-06-11 18:10:18 -0700584 ReadableBlob blob;
585 // arg1 = metadata (blob)
586 do {
Zhijun He146aed12013-12-05 07:46:51 -0800587 if ((err = data.readBlob(blobSize, &blob)) != OK) {
588 ALOGE("%s: Failed to read metadata blob (sized %zu). Possible "
Igor Murashkine7ee7632013-06-11 18:10:18 -0700589 " serialization bug. Error %d %s",
Zhijun He146aed12013-12-05 07:46:51 -0800590 __FUNCTION__, blobSize, err, strerror(-err));
Igor Murashkine7ee7632013-06-11 18:10:18 -0700591 break;
592 }
Igor Murashkine7ee7632013-06-11 18:10:18 -0700593
Zhijun He146aed12013-12-05 07:46:51 -0800594 // arg2 = offset (blob)
595 // Must be after blob since we don't know offset until after writeBlob.
596 int32_t offsetTmp;
597 if ((err = data.readInt32(&offsetTmp)) != OK) {
598 ALOGE("%s: Failed to read metadata offsetTmp (error %d %s)",
599 __FUNCTION__, err, strerror(-err));
600 break;
601 }
602 const size_t offset = static_cast<size_t>(offsetTmp);
603 if (offset >= alignment) {
604 ALOGE("%s: metadata offset(%zu) should be less than alignment(%zu)",
605 __FUNCTION__, blobSize, alignment);
606 err = BAD_VALUE;
607 break;
608 }
609
610 const uintptr_t metadataStart = reinterpret_cast<uintptr_t>(blob.data()) + offset;
611 const camera_metadata_t* tmp =
612 reinterpret_cast<const camera_metadata_t*>(metadataStart);
613 ALOGV("%s: alignment is: %zu, metadata start: %p, offset: %zu",
614 __FUNCTION__, alignment, tmp, offset);
Igor Murashkine7ee7632013-06-11 18:10:18 -0700615 metadata = allocate_copy_camera_metadata_checked(tmp, metadataSize);
616 if (metadata == NULL) {
617 // We consider that allocation only fails if the validation
618 // also failed, therefore the readFromParcel was a failure.
Zhijun He146aed12013-12-05 07:46:51 -0800619 ALOGE("%s: metadata allocation and copy failed", __FUNCTION__);
Igor Murashkine7ee7632013-06-11 18:10:18 -0700620 err = BAD_VALUE;
621 }
622 } while(0);
623 blob.release();
624
625 if (out) {
626 ALOGV("%s: Set out metadata to %p", __FUNCTION__, metadata);
627 *out = metadata;
628 } else if (metadata != NULL) {
629 ALOGV("%s: Freed camera metadata at %p", __FUNCTION__, metadata);
630 free_camera_metadata(metadata);
631 }
632
633 return err;
634}
635
636status_t CameraMetadata::writeToParcel(Parcel& data,
637 const camera_metadata_t* metadata) {
638 status_t res = OK;
639
Zhijun He146aed12013-12-05 07:46:51 -0800640 /**
641 * Below is the camera metadata parcel layout:
642 *
643 * |--------------------------------------------|
644 * | arg0: blobSize |
645 * | (length = 4) |
646 * |--------------------------------------------|<--Skip the rest if blobSize == 0.
647 * | |
648 * | |
649 * | arg1: blob |
650 * | (length = variable, see arg1 layout below) |
651 * | |
652 * | |
653 * |--------------------------------------------|
654 * | arg2: offset |
655 * | (length = 4) |
656 * |--------------------------------------------|
657 */
Igor Murashkine7ee7632013-06-11 18:10:18 -0700658
Zhijun He146aed12013-12-05 07:46:51 -0800659 // arg0 = blobSize (int32)
Igor Murashkine7ee7632013-06-11 18:10:18 -0700660 if (metadata == NULL) {
Zhijun He146aed12013-12-05 07:46:51 -0800661 // Write zero blobSize for null metadata.
Igor Murashkine7ee7632013-06-11 18:10:18 -0700662 return data.writeInt32(0);
663 }
664
Zhijun He146aed12013-12-05 07:46:51 -0800665 /**
666 * Always make the blob size sufficiently larger, as we need put alignment
667 * padding and metadata into the blob. Since we don't know the alignment
668 * offset before writeBlob. Then write the metadata to aligned offset.
669 */
Igor Murashkine7ee7632013-06-11 18:10:18 -0700670 const size_t metadataSize = get_camera_metadata_compact_size(metadata);
Zhijun He146aed12013-12-05 07:46:51 -0800671 const size_t alignment = get_camera_metadata_alignment();
672 const size_t blobSize = metadataSize + alignment;
673 res = data.writeInt32(static_cast<int32_t>(blobSize));
Igor Murashkine7ee7632013-06-11 18:10:18 -0700674 if (res != OK) {
675 return res;
676 }
677
Zhijun He146aed12013-12-05 07:46:51 -0800678 size_t offset = 0;
679 /**
680 * arg1 = metadata (blob).
681 *
682 * The blob size is the sum of front padding size, metadata size and back padding
683 * size, which is equal to metadataSize + alignment.
684 *
685 * The blob layout is:
686 * |------------------------------------|<----Start address of the blob (unaligned).
687 * | front padding |
688 * | (size = offset) |
689 * |------------------------------------|<----Aligned start address of metadata.
690 * | |
691 * | |
692 * | metadata |
693 * | (size = metadataSize) |
694 * | |
695 * | |
696 * |------------------------------------|
697 * | back padding |
698 * | (size = alignment - offset) |
699 * |------------------------------------|<----End address of blob.
700 * (Blob start address + blob size).
701 */
Igor Murashkine7ee7632013-06-11 18:10:18 -0700702 WritableBlob blob;
703 do {
Jeff Browne8df5392015-06-05 15:10:44 -0700704 res = data.writeBlob(blobSize, false, &blob);
Igor Murashkine7ee7632013-06-11 18:10:18 -0700705 if (res != OK) {
706 break;
707 }
Zhijun He146aed12013-12-05 07:46:51 -0800708 const uintptr_t metadataStart = ALIGN_TO(blob.data(), alignment);
709 offset = metadataStart - reinterpret_cast<uintptr_t>(blob.data());
710 ALOGV("%s: alignment is: %zu, metadata start: %p, offset: %zu",
Mark Salyzyn1a93f0c2014-06-09 16:34:58 -0700711 __FUNCTION__, alignment,
712 reinterpret_cast<const void *>(metadataStart), offset);
Zhijun He146aed12013-12-05 07:46:51 -0800713 copy_camera_metadata(reinterpret_cast<void*>(metadataStart), metadataSize, metadata);
Igor Murashkine7ee7632013-06-11 18:10:18 -0700714
715 // Not too big of a problem since receiving side does hard validation
716 // Don't check the size since the compact size could be larger
wangxiaobin274a28c2025-02-07 14:52:18 +0800717 IF_ALOGV() {
718 if (validate_camera_metadata_structure(metadata, /*size*/NULL) != OK) {
719 ALOGW("%s: Failed to validate metadata %p before writing blob",
720 __FUNCTION__, metadata);
721 }
Igor Murashkine7ee7632013-06-11 18:10:18 -0700722 }
723
724 } while(false);
725 blob.release();
726
Zhijun He146aed12013-12-05 07:46:51 -0800727 // arg2 = offset (int32)
728 res = data.writeInt32(static_cast<int32_t>(offset));
729
Igor Murashkine7ee7632013-06-11 18:10:18 -0700730 return res;
731}
732
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800733status_t CameraMetadata::readFromParcel(const Parcel *parcel) {
Jayant Chowdhary2e310da2020-05-12 12:40:36 -0700734
Igor Murashkine7ee7632013-06-11 18:10:18 -0700735 ALOGV("%s: parcel = %p", __FUNCTION__, parcel);
736
737 status_t res = OK;
738
739 if (parcel == NULL) {
740 ALOGE("%s: parcel is null", __FUNCTION__);
741 return BAD_VALUE;
742 }
743
744 if (mLocked) {
745 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
746 return INVALID_OPERATION;
747 }
748
749 camera_metadata *buffer = NULL;
750 // TODO: reading should return a status code, in case validation fails
751 res = CameraMetadata::readFromParcel(*parcel, &buffer);
752
753 if (res != NO_ERROR) {
754 ALOGE("%s: Failed to read from parcel. Metadata is unchanged.",
755 __FUNCTION__);
756 return res;
757 }
758
759 clear();
760 mBuffer = buffer;
761
762 return OK;
763}
764
765status_t CameraMetadata::writeToParcel(Parcel *parcel) const {
Jayant Chowdhary2e310da2020-05-12 12:40:36 -0700766
Igor Murashkine7ee7632013-06-11 18:10:18 -0700767 ALOGV("%s: parcel = %p", __FUNCTION__, parcel);
768
769 if (parcel == NULL) {
770 ALOGE("%s: parcel is null", __FUNCTION__);
771 return BAD_VALUE;
772 }
773
774 return CameraMetadata::writeToParcel(*parcel, mBuffer);
775}
776
777void CameraMetadata::swap(CameraMetadata& other) {
778 if (mLocked) {
779 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
780 return;
781 } else if (other.mLocked) {
782 ALOGE("%s: Other CameraMetadata is locked", __FUNCTION__);
783 return;
784 }
785
786 camera_metadata* thisBuf = mBuffer;
787 camera_metadata* otherBuf = other.mBuffer;
788
789 other.mBuffer = thisBuf;
790 mBuffer = otherBuf;
791}
792
Eino-Ville Talvala4d453832016-07-15 11:56:53 -0700793status_t CameraMetadata::getTagFromName(const char *name,
794 const VendorTagDescriptor* vTags, uint32_t *tag) {
Jayant Chowdhary2e310da2020-05-12 12:40:36 -0700795
Eino-Ville Talvala4d453832016-07-15 11:56:53 -0700796 if (name == nullptr || tag == nullptr) return BAD_VALUE;
797
798 size_t nameLength = strlen(name);
799
800 const SortedVector<String8> *vendorSections;
801 size_t vendorSectionCount = 0;
802
803 if (vTags != NULL) {
804 vendorSections = vTags->getAllSectionNames();
805 vendorSectionCount = vendorSections->size();
806 }
807
808 // First, find the section by the longest string match
809 const char *section = NULL;
810 size_t sectionIndex = 0;
811 size_t sectionLength = 0;
812 size_t totalSectionCount = ANDROID_SECTION_COUNT + vendorSectionCount;
813 for (size_t i = 0; i < totalSectionCount; ++i) {
814
815 const char *str = (i < ANDROID_SECTION_COUNT) ? camera_metadata_section_names[i] :
Tomasz Wasilczyk12b04a52023-08-11 15:52:22 +0000816 (*vendorSections)[i - ANDROID_SECTION_COUNT].c_str();
Eino-Ville Talvala4d453832016-07-15 11:56:53 -0700817
818 ALOGV("%s: Trying to match against section '%s'", __FUNCTION__, str);
819
820 if (strstr(name, str) == name) { // name begins with the section name
821 size_t strLength = strlen(str);
822
823 ALOGV("%s: Name begins with section name", __FUNCTION__);
824
825 // section name is the longest we've found so far
826 if (section == NULL || sectionLength < strLength) {
827 section = str;
828 sectionIndex = i;
829 sectionLength = strLength;
830
831 ALOGV("%s: Found new best section (%s)", __FUNCTION__, section);
832 }
833 }
834 }
835
836 // TODO: Make above get_camera_metadata_section_from_name ?
837
838 if (section == NULL) {
839 return NAME_NOT_FOUND;
840 } else {
841 ALOGV("%s: Found matched section '%s' (%zu)",
842 __FUNCTION__, section, sectionIndex);
843 }
844
845 // Get the tag name component of the name
846 const char *nameTagName = name + sectionLength + 1; // x.y.z -> z
847 if (sectionLength + 1 >= nameLength) {
848 return BAD_VALUE;
849 }
850
851 // Match rest of name against the tag names in that section only
852 uint32_t candidateTag = 0;
853 if (sectionIndex < ANDROID_SECTION_COUNT) {
854 // Match built-in tags (typically android.*)
855 uint32_t tagBegin, tagEnd; // [tagBegin, tagEnd)
856 tagBegin = camera_metadata_section_bounds[sectionIndex][0];
857 tagEnd = camera_metadata_section_bounds[sectionIndex][1];
858
859 for (candidateTag = tagBegin; candidateTag < tagEnd; ++candidateTag) {
860 const char *tagName = get_camera_metadata_tag_name(candidateTag);
861
862 if (strcmp(nameTagName, tagName) == 0) {
863 ALOGV("%s: Found matched tag '%s' (%d)",
864 __FUNCTION__, tagName, candidateTag);
865 break;
866 }
867 }
868
869 if (candidateTag == tagEnd) {
870 return NAME_NOT_FOUND;
871 }
872 } else if (vTags != NULL) {
873 // Match vendor tags (typically com.*)
874 const String8 sectionName(section);
875 const String8 tagName(nameTagName);
876
877 status_t res = OK;
878 if ((res = vTags->lookupTag(tagName, sectionName, &candidateTag)) != OK) {
879 return NAME_NOT_FOUND;
880 }
881 }
882
883 *tag = candidateTag;
884 return OK;
885}
886
malikakash9a238f62023-12-14 22:47:55 +0000887metadata_vendor_id_t CameraMetadata::getVendorId() const {
Emilian Peev0ec234e2020-08-24 11:48:50 -0700888 return get_camera_metadata_vendor_id(mBuffer);
889}
Eino-Ville Talvala4d453832016-07-15 11:56:53 -0700890
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700891}; // namespace android