blob: 7e4c91e61ab36abb14afa558e71e8133ee542dad [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
135 ALOGE_IF(validate_camera_metadata_structure(mBuffer, /*size*/NULL) != OK,
136 "%s: Failed to validate metadata structure %p",
137 __FUNCTION__, buffer);
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700138}
139
140void CameraMetadata::acquire(CameraMetadata &other) {
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800141 if (mLocked) {
142 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
143 return;
144 }
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700145 acquire(other.release());
146}
147
148status_t CameraMetadata::append(const CameraMetadata &other) {
Eino-Ville Talvalafd6ecdd2013-10-11 09:51:09 -0700149 return append(other.mBuffer);
150}
151
152status_t CameraMetadata::append(const camera_metadata_t* other) {
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800153 if (mLocked) {
154 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
155 return INVALID_OPERATION;
156 }
Eino-Ville Talvalafd6ecdd2013-10-11 09:51:09 -0700157 size_t extraEntries = get_camera_metadata_entry_count(other);
158 size_t extraData = get_camera_metadata_data_count(other);
159 resizeIfNeeded(extraEntries, extraData);
160
161 return append_camera_metadata(mBuffer, other);
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700162}
163
164size_t CameraMetadata::entryCount() const {
165 return (mBuffer == NULL) ? 0 :
166 get_camera_metadata_entry_count(mBuffer);
167}
168
Eino-Ville Talvalada6665c2012-08-29 17:37:16 -0700169bool CameraMetadata::isEmpty() const {
170 return entryCount() == 0;
171}
172
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700173status_t CameraMetadata::sort() {
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800174 if (mLocked) {
175 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
176 return INVALID_OPERATION;
177 }
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700178 return sort_camera_metadata(mBuffer);
179}
180
181status_t CameraMetadata::checkType(uint32_t tag, uint8_t expectedType) {
Emilian Peev71c73a22017-03-21 16:35:51 +0000182 int tagType = get_local_camera_metadata_tag_type(tag, mBuffer);
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700183 if ( CC_UNLIKELY(tagType == -1)) {
184 ALOGE("Update metadata entry: Unknown tag %d", tag);
185 return INVALID_OPERATION;
186 }
187 if ( CC_UNLIKELY(tagType != expectedType) ) {
188 ALOGE("Mismatched tag type when updating entry %s (%d) of type %s; "
189 "got type %s data instead ",
Emilian Peev71c73a22017-03-21 16:35:51 +0000190 get_local_camera_metadata_tag_name(tag, mBuffer), tag,
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700191 camera_metadata_type_names[tagType],
192 camera_metadata_type_names[expectedType]);
193 return INVALID_OPERATION;
194 }
195 return OK;
196}
197
198status_t CameraMetadata::update(uint32_t tag,
199 const int32_t *data, size_t data_count) {
200 status_t res;
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800201 if (mLocked) {
202 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
203 return INVALID_OPERATION;
204 }
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700205 if ( (res = checkType(tag, TYPE_INT32)) != OK) {
206 return res;
207 }
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800208 return updateImpl(tag, (const void*)data, data_count);
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700209}
210
211status_t CameraMetadata::update(uint32_t tag,
212 const uint8_t *data, size_t data_count) {
213 status_t res;
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800214 if (mLocked) {
215 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
216 return INVALID_OPERATION;
217 }
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700218 if ( (res = checkType(tag, TYPE_BYTE)) != OK) {
219 return res;
220 }
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800221 return updateImpl(tag, (const void*)data, data_count);
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700222}
223
224status_t CameraMetadata::update(uint32_t tag,
225 const float *data, size_t data_count) {
226 status_t res;
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800227 if (mLocked) {
228 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
229 return INVALID_OPERATION;
230 }
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700231 if ( (res = checkType(tag, TYPE_FLOAT)) != OK) {
232 return res;
233 }
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800234 return updateImpl(tag, (const void*)data, data_count);
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700235}
236
237status_t CameraMetadata::update(uint32_t tag,
238 const int64_t *data, size_t data_count) {
239 status_t res;
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800240 if (mLocked) {
241 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
242 return INVALID_OPERATION;
243 }
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700244 if ( (res = checkType(tag, TYPE_INT64)) != OK) {
245 return res;
246 }
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800247 return updateImpl(tag, (const void*)data, data_count);
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700248}
249
250status_t CameraMetadata::update(uint32_t tag,
251 const double *data, size_t data_count) {
252 status_t res;
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800253 if (mLocked) {
254 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
255 return INVALID_OPERATION;
256 }
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700257 if ( (res = checkType(tag, TYPE_DOUBLE)) != OK) {
258 return res;
259 }
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800260 return updateImpl(tag, (const void*)data, data_count);
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700261}
262
263status_t CameraMetadata::update(uint32_t tag,
264 const camera_metadata_rational_t *data, size_t data_count) {
265 status_t res;
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800266 if (mLocked) {
267 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
268 return INVALID_OPERATION;
269 }
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700270 if ( (res = checkType(tag, TYPE_RATIONAL)) != OK) {
271 return res;
272 }
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800273 return updateImpl(tag, (const void*)data, data_count);
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700274}
275
276status_t CameraMetadata::update(uint32_t tag,
277 const String8 &string) {
278 status_t res;
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800279 if (mLocked) {
280 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
281 return INVALID_OPERATION;
282 }
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700283 if ( (res = checkType(tag, TYPE_BYTE)) != OK) {
284 return res;
285 }
Zhijun He7595c472014-03-27 16:46:15 -0700286 // string.size() doesn't count the null termination character.
287 return updateImpl(tag, (const void*)string.string(), string.size() + 1);
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700288}
289
Eino-Ville Talvala4d453832016-07-15 11:56:53 -0700290status_t CameraMetadata::update(const camera_metadata_ro_entry &entry) {
291 status_t res;
292 if (mLocked) {
293 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
294 return INVALID_OPERATION;
295 }
296 if ( (res = checkType(entry.tag, entry.type)) != OK) {
297 return res;
298 }
299 return updateImpl(entry.tag, (const void*)entry.data.u8, entry.count);
300}
301
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800302status_t CameraMetadata::updateImpl(uint32_t tag, const void *data,
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700303 size_t data_count) {
304 status_t res;
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800305 if (mLocked) {
306 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
307 return INVALID_OPERATION;
308 }
Emilian Peev71c73a22017-03-21 16:35:51 +0000309 int type = get_local_camera_metadata_tag_type(tag, mBuffer);
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700310 if (type == -1) {
311 ALOGE("%s: Tag %d not found", __FUNCTION__, tag);
312 return BAD_VALUE;
313 }
Eino-Ville Talvalae2b60c82015-07-17 16:21:44 -0700314 // Safety check - ensure that data isn't pointing to this metadata, since
315 // that would get invalidated if a resize is needed
316 size_t bufferSize = get_camera_metadata_size(mBuffer);
317 uintptr_t bufAddr = reinterpret_cast<uintptr_t>(mBuffer);
318 uintptr_t dataAddr = reinterpret_cast<uintptr_t>(data);
319 if (dataAddr > bufAddr && dataAddr < (bufAddr + bufferSize)) {
320 ALOGE("%s: Update attempted with data from the same metadata buffer!",
321 __FUNCTION__);
322 return INVALID_OPERATION;
323 }
324
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700325 size_t data_size = calculate_camera_metadata_entry_data_size(type,
326 data_count);
327
328 res = resizeIfNeeded(1, data_size);
329
330 if (res == OK) {
331 camera_metadata_entry_t entry;
332 res = find_camera_metadata_entry(mBuffer, tag, &entry);
333 if (res == NAME_NOT_FOUND) {
334 res = add_camera_metadata_entry(mBuffer,
335 tag, data, data_count);
336 } else if (res == OK) {
337 res = update_camera_metadata_entry(mBuffer,
338 entry.index, data, data_count, NULL);
339 }
340 }
341
342 if (res != OK) {
343 ALOGE("%s: Unable to update metadata entry %s.%s (%x): %s (%d)",
Emilian Peev71c73a22017-03-21 16:35:51 +0000344 __FUNCTION__, get_local_camera_metadata_section_name(tag, mBuffer),
345 get_local_camera_metadata_tag_name(tag, mBuffer), tag,
346 strerror(-res), res);
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700347 }
Igor Murashkine2d1e3d2013-04-30 18:18:06 -0700348
349 IF_ALOGV() {
350 ALOGE_IF(validate_camera_metadata_structure(mBuffer, /*size*/NULL) !=
351 OK,
352
353 "%s: Failed to validate metadata structure after update %p",
354 __FUNCTION__, mBuffer);
355 }
356
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700357 return res;
358}
359
Igor Murashkinfc42642a2013-02-13 18:23:39 -0800360bool CameraMetadata::exists(uint32_t tag) const {
361 camera_metadata_ro_entry entry;
362 return find_camera_metadata_ro_entry(mBuffer, tag, &entry) == 0;
363}
364
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700365camera_metadata_entry_t CameraMetadata::find(uint32_t tag) {
366 status_t res;
367 camera_metadata_entry entry;
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800368 if (mLocked) {
369 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
370 entry.count = 0;
371 return entry;
372 }
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700373 res = find_camera_metadata_entry(mBuffer, tag, &entry);
374 if (CC_UNLIKELY( res != OK )) {
375 entry.count = 0;
376 entry.data.u8 = NULL;
377 }
378 return entry;
379}
380
381camera_metadata_ro_entry_t CameraMetadata::find(uint32_t tag) const {
382 status_t res;
383 camera_metadata_ro_entry entry;
384 res = find_camera_metadata_ro_entry(mBuffer, tag, &entry);
385 if (CC_UNLIKELY( res != OK )) {
386 entry.count = 0;
387 entry.data.u8 = NULL;
388 }
389 return entry;
390}
391
392status_t CameraMetadata::erase(uint32_t tag) {
393 camera_metadata_entry_t entry;
394 status_t res;
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800395 if (mLocked) {
396 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
397 return INVALID_OPERATION;
398 }
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700399 res = find_camera_metadata_entry(mBuffer, tag, &entry);
400 if (res == NAME_NOT_FOUND) {
401 return OK;
402 } else if (res != OK) {
403 ALOGE("%s: Error looking for entry %s.%s (%x): %s %d",
404 __FUNCTION__,
Emilian Peev71c73a22017-03-21 16:35:51 +0000405 get_local_camera_metadata_section_name(tag, mBuffer),
406 get_local_camera_metadata_tag_name(tag, mBuffer),
407 tag, strerror(-res), res);
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700408 return res;
409 }
410 res = delete_camera_metadata_entry(mBuffer, entry.index);
411 if (res != OK) {
412 ALOGE("%s: Error deleting entry %s.%s (%x): %s %d",
413 __FUNCTION__,
Emilian Peev71c73a22017-03-21 16:35:51 +0000414 get_local_camera_metadata_section_name(tag, mBuffer),
415 get_local_camera_metadata_tag_name(tag, mBuffer),
416 tag, strerror(-res), res);
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700417 }
418 return res;
419}
420
Emilian Peeve20c6372018-08-14 18:45:53 +0100421status_t CameraMetadata::removePermissionEntries(metadata_vendor_id_t vendorId,
422 std::vector<int32_t> *tagsRemoved) {
423 uint32_t tagCount = 0;
424 std::vector<uint32_t> tagsToRemove;
425
426 if (tagsRemoved == nullptr) {
427 return BAD_VALUE;
428 }
429
430 sp<VendorTagDescriptor> vTags = VendorTagDescriptor::getGlobalVendorTagDescriptor();
431 if ((nullptr == vTags.get()) || (0 >= vTags->getTagCount())) {
432 sp<VendorTagDescriptorCache> cache =
433 VendorTagDescriptorCache::getGlobalVendorTagCache();
434 if (cache.get()) {
435 cache->getVendorTagDescriptor(vendorId, &vTags);
436 }
437 }
438
439 if ((nullptr != vTags.get()) && (vTags->getTagCount() > 0)) {
440 tagCount = vTags->getTagCount();
441 uint32_t *vendorTags = new uint32_t[tagCount];
442 if (nullptr == vendorTags) {
443 return NO_MEMORY;
444 }
445 vTags->getTagArray(vendorTags);
446
447 tagsToRemove.reserve(tagCount);
448 tagsToRemove.insert(tagsToRemove.begin(), vendorTags, vendorTags + tagCount);
449
450 delete [] vendorTags;
451 tagCount = 0;
452 }
453
454 auto tagsNeedingPermission = get_camera_metadata_permission_needed(&tagCount);
455 if (tagCount > 0) {
456 tagsToRemove.reserve(tagsToRemove.capacity() + tagCount);
457 tagsToRemove.insert(tagsToRemove.end(), tagsNeedingPermission,
458 tagsNeedingPermission + tagCount);
459 }
460
461 tagsRemoved->reserve(tagsToRemove.size());
462 for (const auto &it : tagsToRemove) {
463 if (exists(it)) {
464 auto rc = erase(it);
465 if (NO_ERROR != rc) {
466 ALOGE("%s: Failed to erase tag: %x", __func__, it);
467 return rc;
468 }
469 tagsRemoved->push_back(it);
470 }
471 }
472
473 // Update the available characterstics accordingly
474 if (exists(ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS)) {
475 std::vector<uint32_t> currentKeys;
476
477 std::sort(tagsRemoved->begin(), tagsRemoved->end());
478 auto keys = find(ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS);
479 currentKeys.reserve(keys.count);
480 currentKeys.insert(currentKeys.end(), keys.data.i32, keys.data.i32 + keys.count);
481 std::sort(currentKeys.begin(), currentKeys.end());
482
483 std::vector<int32_t> newKeys(keys.count);
484 auto end = std::set_difference(currentKeys.begin(), currentKeys.end(), tagsRemoved->begin(),
485 tagsRemoved->end(), newKeys.begin());
486 newKeys.resize(end - newKeys.begin());
487
488 update(ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS, newKeys.data(), newKeys.size());
489 }
490
491 return NO_ERROR;
492}
493
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700494void CameraMetadata::dump(int fd, int verbosity, int indentation) const {
495 dump_indented_camera_metadata(mBuffer, fd, verbosity, indentation);
496}
497
498status_t CameraMetadata::resizeIfNeeded(size_t extraEntries, size_t extraData) {
499 if (mBuffer == NULL) {
500 mBuffer = allocate_camera_metadata(extraEntries * 2, extraData * 2);
501 if (mBuffer == NULL) {
502 ALOGE("%s: Can't allocate larger metadata buffer", __FUNCTION__);
503 return NO_MEMORY;
504 }
505 } else {
506 size_t currentEntryCount = get_camera_metadata_entry_count(mBuffer);
507 size_t currentEntryCap = get_camera_metadata_entry_capacity(mBuffer);
508 size_t newEntryCount = currentEntryCount +
509 extraEntries;
510 newEntryCount = (newEntryCount > currentEntryCap) ?
511 newEntryCount * 2 : currentEntryCap;
512
513 size_t currentDataCount = get_camera_metadata_data_count(mBuffer);
514 size_t currentDataCap = get_camera_metadata_data_capacity(mBuffer);
515 size_t newDataCount = currentDataCount +
516 extraData;
517 newDataCount = (newDataCount > currentDataCap) ?
518 newDataCount * 2 : currentDataCap;
519
520 if (newEntryCount > currentEntryCap ||
521 newDataCount > currentDataCap) {
522 camera_metadata_t *oldBuffer = mBuffer;
523 mBuffer = allocate_camera_metadata(newEntryCount,
524 newDataCount);
525 if (mBuffer == NULL) {
526 ALOGE("%s: Can't allocate larger metadata buffer", __FUNCTION__);
527 return NO_MEMORY;
528 }
529 append_camera_metadata(mBuffer, oldBuffer);
530 free_camera_metadata(oldBuffer);
531 }
532 }
533 return OK;
534}
535
Igor Murashkine7ee7632013-06-11 18:10:18 -0700536status_t CameraMetadata::readFromParcel(const Parcel& data,
537 camera_metadata_t** out) {
Jayant Chowdhary2e310da2020-05-12 12:40:36 -0700538
Igor Murashkine7ee7632013-06-11 18:10:18 -0700539 status_t err = OK;
540
541 camera_metadata_t* metadata = NULL;
542
543 if (out) {
544 *out = NULL;
545 }
546
Zhijun He146aed12013-12-05 07:46:51 -0800547 // See CameraMetadata::writeToParcel for parcel data layout diagram and explanation.
548 // arg0 = blobSize (int32)
549 int32_t blobSizeTmp = -1;
550 if ((err = data.readInt32(&blobSizeTmp)) != OK) {
Igor Murashkine7ee7632013-06-11 18:10:18 -0700551 ALOGE("%s: Failed to read metadata size (error %d %s)",
552 __FUNCTION__, err, strerror(-err));
553 return err;
554 }
Zhijun He146aed12013-12-05 07:46:51 -0800555 const size_t blobSize = static_cast<size_t>(blobSizeTmp);
556 const size_t alignment = get_camera_metadata_alignment();
Igor Murashkine7ee7632013-06-11 18:10:18 -0700557
Zhijun He146aed12013-12-05 07:46:51 -0800558 // Special case: zero blob size means zero sized (NULL) metadata.
559 if (blobSize == 0) {
Igor Murashkine7ee7632013-06-11 18:10:18 -0700560 ALOGV("%s: Read 0-sized metadata", __FUNCTION__);
561 return OK;
562 }
563
Zhijun He146aed12013-12-05 07:46:51 -0800564 if (blobSize <= alignment) {
565 ALOGE("%s: metadata blob is malformed, blobSize(%zu) should be larger than alignment(%zu)",
566 __FUNCTION__, blobSize, alignment);
567 return BAD_VALUE;
568 }
569
570 const size_t metadataSize = blobSize - alignment;
571
572 // NOTE: this doesn't make sense to me. shouldn't the blob
Igor Murashkine7ee7632013-06-11 18:10:18 -0700573 // know how big it is? why do we have to specify the size
574 // to Parcel::readBlob ?
Igor Murashkine7ee7632013-06-11 18:10:18 -0700575 ReadableBlob blob;
576 // arg1 = metadata (blob)
577 do {
Zhijun He146aed12013-12-05 07:46:51 -0800578 if ((err = data.readBlob(blobSize, &blob)) != OK) {
579 ALOGE("%s: Failed to read metadata blob (sized %zu). Possible "
Igor Murashkine7ee7632013-06-11 18:10:18 -0700580 " serialization bug. Error %d %s",
Zhijun He146aed12013-12-05 07:46:51 -0800581 __FUNCTION__, blobSize, err, strerror(-err));
Igor Murashkine7ee7632013-06-11 18:10:18 -0700582 break;
583 }
Igor Murashkine7ee7632013-06-11 18:10:18 -0700584
Zhijun He146aed12013-12-05 07:46:51 -0800585 // arg2 = offset (blob)
586 // Must be after blob since we don't know offset until after writeBlob.
587 int32_t offsetTmp;
588 if ((err = data.readInt32(&offsetTmp)) != OK) {
589 ALOGE("%s: Failed to read metadata offsetTmp (error %d %s)",
590 __FUNCTION__, err, strerror(-err));
591 break;
592 }
593 const size_t offset = static_cast<size_t>(offsetTmp);
594 if (offset >= alignment) {
595 ALOGE("%s: metadata offset(%zu) should be less than alignment(%zu)",
596 __FUNCTION__, blobSize, alignment);
597 err = BAD_VALUE;
598 break;
599 }
600
601 const uintptr_t metadataStart = reinterpret_cast<uintptr_t>(blob.data()) + offset;
602 const camera_metadata_t* tmp =
603 reinterpret_cast<const camera_metadata_t*>(metadataStart);
604 ALOGV("%s: alignment is: %zu, metadata start: %p, offset: %zu",
605 __FUNCTION__, alignment, tmp, offset);
Igor Murashkine7ee7632013-06-11 18:10:18 -0700606 metadata = allocate_copy_camera_metadata_checked(tmp, metadataSize);
607 if (metadata == NULL) {
608 // We consider that allocation only fails if the validation
609 // also failed, therefore the readFromParcel was a failure.
Zhijun He146aed12013-12-05 07:46:51 -0800610 ALOGE("%s: metadata allocation and copy failed", __FUNCTION__);
Igor Murashkine7ee7632013-06-11 18:10:18 -0700611 err = BAD_VALUE;
612 }
613 } while(0);
614 blob.release();
615
616 if (out) {
617 ALOGV("%s: Set out metadata to %p", __FUNCTION__, metadata);
618 *out = metadata;
619 } else if (metadata != NULL) {
620 ALOGV("%s: Freed camera metadata at %p", __FUNCTION__, metadata);
621 free_camera_metadata(metadata);
622 }
623
624 return err;
625}
626
627status_t CameraMetadata::writeToParcel(Parcel& data,
628 const camera_metadata_t* metadata) {
629 status_t res = OK;
630
Zhijun He146aed12013-12-05 07:46:51 -0800631 /**
632 * Below is the camera metadata parcel layout:
633 *
634 * |--------------------------------------------|
635 * | arg0: blobSize |
636 * | (length = 4) |
637 * |--------------------------------------------|<--Skip the rest if blobSize == 0.
638 * | |
639 * | |
640 * | arg1: blob |
641 * | (length = variable, see arg1 layout below) |
642 * | |
643 * | |
644 * |--------------------------------------------|
645 * | arg2: offset |
646 * | (length = 4) |
647 * |--------------------------------------------|
648 */
Igor Murashkine7ee7632013-06-11 18:10:18 -0700649
Zhijun He146aed12013-12-05 07:46:51 -0800650 // arg0 = blobSize (int32)
Igor Murashkine7ee7632013-06-11 18:10:18 -0700651 if (metadata == NULL) {
Zhijun He146aed12013-12-05 07:46:51 -0800652 // Write zero blobSize for null metadata.
Igor Murashkine7ee7632013-06-11 18:10:18 -0700653 return data.writeInt32(0);
654 }
655
Zhijun He146aed12013-12-05 07:46:51 -0800656 /**
657 * Always make the blob size sufficiently larger, as we need put alignment
658 * padding and metadata into the blob. Since we don't know the alignment
659 * offset before writeBlob. Then write the metadata to aligned offset.
660 */
Igor Murashkine7ee7632013-06-11 18:10:18 -0700661 const size_t metadataSize = get_camera_metadata_compact_size(metadata);
Zhijun He146aed12013-12-05 07:46:51 -0800662 const size_t alignment = get_camera_metadata_alignment();
663 const size_t blobSize = metadataSize + alignment;
664 res = data.writeInt32(static_cast<int32_t>(blobSize));
Igor Murashkine7ee7632013-06-11 18:10:18 -0700665 if (res != OK) {
666 return res;
667 }
668
Zhijun He146aed12013-12-05 07:46:51 -0800669 size_t offset = 0;
670 /**
671 * arg1 = metadata (blob).
672 *
673 * The blob size is the sum of front padding size, metadata size and back padding
674 * size, which is equal to metadataSize + alignment.
675 *
676 * The blob layout is:
677 * |------------------------------------|<----Start address of the blob (unaligned).
678 * | front padding |
679 * | (size = offset) |
680 * |------------------------------------|<----Aligned start address of metadata.
681 * | |
682 * | |
683 * | metadata |
684 * | (size = metadataSize) |
685 * | |
686 * | |
687 * |------------------------------------|
688 * | back padding |
689 * | (size = alignment - offset) |
690 * |------------------------------------|<----End address of blob.
691 * (Blob start address + blob size).
692 */
Igor Murashkine7ee7632013-06-11 18:10:18 -0700693 WritableBlob blob;
694 do {
Jeff Browne8df5392015-06-05 15:10:44 -0700695 res = data.writeBlob(blobSize, false, &blob);
Igor Murashkine7ee7632013-06-11 18:10:18 -0700696 if (res != OK) {
697 break;
698 }
Zhijun He146aed12013-12-05 07:46:51 -0800699 const uintptr_t metadataStart = ALIGN_TO(blob.data(), alignment);
700 offset = metadataStart - reinterpret_cast<uintptr_t>(blob.data());
701 ALOGV("%s: alignment is: %zu, metadata start: %p, offset: %zu",
Mark Salyzyn1a93f0c2014-06-09 16:34:58 -0700702 __FUNCTION__, alignment,
703 reinterpret_cast<const void *>(metadataStart), offset);
Zhijun He146aed12013-12-05 07:46:51 -0800704 copy_camera_metadata(reinterpret_cast<void*>(metadataStart), metadataSize, metadata);
Igor Murashkine7ee7632013-06-11 18:10:18 -0700705
706 // Not too big of a problem since receiving side does hard validation
707 // Don't check the size since the compact size could be larger
708 if (validate_camera_metadata_structure(metadata, /*size*/NULL) != OK) {
709 ALOGW("%s: Failed to validate metadata %p before writing blob",
710 __FUNCTION__, metadata);
711 }
712
713 } while(false);
714 blob.release();
715
Zhijun He146aed12013-12-05 07:46:51 -0800716 // arg2 = offset (int32)
717 res = data.writeInt32(static_cast<int32_t>(offset));
718
Igor Murashkine7ee7632013-06-11 18:10:18 -0700719 return res;
720}
721
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800722status_t CameraMetadata::readFromParcel(const Parcel *parcel) {
Jayant Chowdhary2e310da2020-05-12 12:40:36 -0700723
Igor Murashkine7ee7632013-06-11 18:10:18 -0700724 ALOGV("%s: parcel = %p", __FUNCTION__, parcel);
725
726 status_t res = OK;
727
728 if (parcel == NULL) {
729 ALOGE("%s: parcel is null", __FUNCTION__);
730 return BAD_VALUE;
731 }
732
733 if (mLocked) {
734 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
735 return INVALID_OPERATION;
736 }
737
738 camera_metadata *buffer = NULL;
739 // TODO: reading should return a status code, in case validation fails
740 res = CameraMetadata::readFromParcel(*parcel, &buffer);
741
742 if (res != NO_ERROR) {
743 ALOGE("%s: Failed to read from parcel. Metadata is unchanged.",
744 __FUNCTION__);
745 return res;
746 }
747
748 clear();
749 mBuffer = buffer;
750
751 return OK;
752}
753
754status_t CameraMetadata::writeToParcel(Parcel *parcel) const {
Jayant Chowdhary2e310da2020-05-12 12:40:36 -0700755
Igor Murashkine7ee7632013-06-11 18:10:18 -0700756 ALOGV("%s: parcel = %p", __FUNCTION__, parcel);
757
758 if (parcel == NULL) {
759 ALOGE("%s: parcel is null", __FUNCTION__);
760 return BAD_VALUE;
761 }
762
763 return CameraMetadata::writeToParcel(*parcel, mBuffer);
764}
765
766void CameraMetadata::swap(CameraMetadata& other) {
767 if (mLocked) {
768 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
769 return;
770 } else if (other.mLocked) {
771 ALOGE("%s: Other CameraMetadata is locked", __FUNCTION__);
772 return;
773 }
774
775 camera_metadata* thisBuf = mBuffer;
776 camera_metadata* otherBuf = other.mBuffer;
777
778 other.mBuffer = thisBuf;
779 mBuffer = otherBuf;
780}
781
Eino-Ville Talvala4d453832016-07-15 11:56:53 -0700782status_t CameraMetadata::getTagFromName(const char *name,
783 const VendorTagDescriptor* vTags, uint32_t *tag) {
Jayant Chowdhary2e310da2020-05-12 12:40:36 -0700784
Eino-Ville Talvala4d453832016-07-15 11:56:53 -0700785 if (name == nullptr || tag == nullptr) return BAD_VALUE;
786
787 size_t nameLength = strlen(name);
788
789 const SortedVector<String8> *vendorSections;
790 size_t vendorSectionCount = 0;
791
792 if (vTags != NULL) {
793 vendorSections = vTags->getAllSectionNames();
794 vendorSectionCount = vendorSections->size();
795 }
796
797 // First, find the section by the longest string match
798 const char *section = NULL;
799 size_t sectionIndex = 0;
800 size_t sectionLength = 0;
801 size_t totalSectionCount = ANDROID_SECTION_COUNT + vendorSectionCount;
802 for (size_t i = 0; i < totalSectionCount; ++i) {
803
804 const char *str = (i < ANDROID_SECTION_COUNT) ? camera_metadata_section_names[i] :
805 (*vendorSections)[i - ANDROID_SECTION_COUNT].string();
806
807 ALOGV("%s: Trying to match against section '%s'", __FUNCTION__, str);
808
809 if (strstr(name, str) == name) { // name begins with the section name
810 size_t strLength = strlen(str);
811
812 ALOGV("%s: Name begins with section name", __FUNCTION__);
813
814 // section name is the longest we've found so far
815 if (section == NULL || sectionLength < strLength) {
816 section = str;
817 sectionIndex = i;
818 sectionLength = strLength;
819
820 ALOGV("%s: Found new best section (%s)", __FUNCTION__, section);
821 }
822 }
823 }
824
825 // TODO: Make above get_camera_metadata_section_from_name ?
826
827 if (section == NULL) {
828 return NAME_NOT_FOUND;
829 } else {
830 ALOGV("%s: Found matched section '%s' (%zu)",
831 __FUNCTION__, section, sectionIndex);
832 }
833
834 // Get the tag name component of the name
835 const char *nameTagName = name + sectionLength + 1; // x.y.z -> z
836 if (sectionLength + 1 >= nameLength) {
837 return BAD_VALUE;
838 }
839
840 // Match rest of name against the tag names in that section only
841 uint32_t candidateTag = 0;
842 if (sectionIndex < ANDROID_SECTION_COUNT) {
843 // Match built-in tags (typically android.*)
844 uint32_t tagBegin, tagEnd; // [tagBegin, tagEnd)
845 tagBegin = camera_metadata_section_bounds[sectionIndex][0];
846 tagEnd = camera_metadata_section_bounds[sectionIndex][1];
847
848 for (candidateTag = tagBegin; candidateTag < tagEnd; ++candidateTag) {
849 const char *tagName = get_camera_metadata_tag_name(candidateTag);
850
851 if (strcmp(nameTagName, tagName) == 0) {
852 ALOGV("%s: Found matched tag '%s' (%d)",
853 __FUNCTION__, tagName, candidateTag);
854 break;
855 }
856 }
857
858 if (candidateTag == tagEnd) {
859 return NAME_NOT_FOUND;
860 }
861 } else if (vTags != NULL) {
862 // Match vendor tags (typically com.*)
863 const String8 sectionName(section);
864 const String8 tagName(nameTagName);
865
866 status_t res = OK;
867 if ((res = vTags->lookupTag(tagName, sectionName, &candidateTag)) != OK) {
868 return NAME_NOT_FOUND;
869 }
870 }
871
872 *tag = candidateTag;
873 return OK;
874}
875
Emilian Peev0ec234e2020-08-24 11:48:50 -0700876metadata_vendor_id_t CameraMetadata::getVendorId() {
877 return get_camera_metadata_vendor_id(mBuffer);
878}
Eino-Ville Talvala4d453832016-07-15 11:56:53 -0700879
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700880}; // namespace android