1 /*
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
17 // #define LOG_NDEBUG 0
18
19 #define LOG_TAG "Camera2-Metadata"
20 #include <utils/Log.h>
21 #include <utils/Errors.h>
22
23 #include <binder/Parcel.h>
24 #include <camera/CameraMetadata.h>
25
26 namespace android {
27
28 #define ALIGN_TO(val, alignment) \
29 (((uintptr_t)(val) + ((alignment) - 1)) & ~((alignment) - 1))
30
31 typedef Parcel::WritableBlob WritableBlob;
32 typedef Parcel::ReadableBlob ReadableBlob;
33
CameraMetadata()34 CameraMetadata::CameraMetadata() :
35 mBuffer(NULL), mLocked(false) {
36 }
37
CameraMetadata(size_t entryCapacity,size_t dataCapacity)38 CameraMetadata::CameraMetadata(size_t entryCapacity, size_t dataCapacity) :
39 mLocked(false)
40 {
41 mBuffer = allocate_camera_metadata(entryCapacity, dataCapacity);
42 }
43
CameraMetadata(const CameraMetadata & other)44 CameraMetadata::CameraMetadata(const CameraMetadata &other) :
45 mLocked(false) {
46 mBuffer = clone_camera_metadata(other.mBuffer);
47 }
48
CameraMetadata(CameraMetadata && other)49 CameraMetadata::CameraMetadata(CameraMetadata &&other) :mBuffer(NULL), mLocked(false) {
50 acquire(other);
51 }
52
operator =(CameraMetadata && other)53 CameraMetadata &CameraMetadata::operator=(CameraMetadata &&other) {
54 acquire(other);
55 return *this;
56 }
57
CameraMetadata(camera_metadata_t * buffer)58 CameraMetadata::CameraMetadata(camera_metadata_t *buffer) :
59 mBuffer(NULL), mLocked(false) {
60 acquire(buffer);
61 }
62
operator =(const CameraMetadata & other)63 CameraMetadata &CameraMetadata::operator=(const CameraMetadata &other) {
64 return operator=(other.mBuffer);
65 }
66
operator =(const camera_metadata_t * buffer)67 CameraMetadata &CameraMetadata::operator=(const camera_metadata_t *buffer) {
68 if (mLocked) {
69 ALOGE("%s: Assignment to a locked CameraMetadata!", __FUNCTION__);
70 return *this;
71 }
72
73 if (CC_LIKELY(buffer != mBuffer)) {
74 camera_metadata_t *newBuffer = clone_camera_metadata(buffer);
75 clear();
76 mBuffer = newBuffer;
77 }
78 return *this;
79 }
80
~CameraMetadata()81 CameraMetadata::~CameraMetadata() {
82 mLocked = false;
83 clear();
84 }
85
getAndLock() const86 const camera_metadata_t* CameraMetadata::getAndLock() const {
87 mLocked = true;
88 return mBuffer;
89 }
90
unlock(const camera_metadata_t * buffer) const91 status_t CameraMetadata::unlock(const camera_metadata_t *buffer) const {
92 if (!mLocked) {
93 ALOGE("%s: Can't unlock a non-locked CameraMetadata!", __FUNCTION__);
94 return INVALID_OPERATION;
95 }
96 if (buffer != mBuffer) {
97 ALOGE("%s: Can't unlock CameraMetadata with wrong pointer!",
98 __FUNCTION__);
99 return BAD_VALUE;
100 }
101 mLocked = false;
102 return OK;
103 }
104
release()105 camera_metadata_t* CameraMetadata::release() {
106 if (mLocked) {
107 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
108 return NULL;
109 }
110 camera_metadata_t *released = mBuffer;
111 mBuffer = NULL;
112 return released;
113 }
114
clear()115 void CameraMetadata::clear() {
116 if (mLocked) {
117 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
118 return;
119 }
120 if (mBuffer) {
121 free_camera_metadata(mBuffer);
122 mBuffer = NULL;
123 }
124 }
125
acquire(camera_metadata_t * buffer)126 void CameraMetadata::acquire(camera_metadata_t *buffer) {
127 if (mLocked) {
128 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
129 return;
130 }
131 clear();
132 mBuffer = buffer;
133
134 ALOGE_IF(validate_camera_metadata_structure(mBuffer, /*size*/NULL) != OK,
135 "%s: Failed to validate metadata structure %p",
136 __FUNCTION__, buffer);
137 }
138
acquire(CameraMetadata & other)139 void CameraMetadata::acquire(CameraMetadata &other) {
140 if (mLocked) {
141 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
142 return;
143 }
144 acquire(other.release());
145 }
146
append(const CameraMetadata & other)147 status_t CameraMetadata::append(const CameraMetadata &other) {
148 return append(other.mBuffer);
149 }
150
append(const camera_metadata_t * other)151 status_t CameraMetadata::append(const camera_metadata_t* other) {
152 if (mLocked) {
153 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
154 return INVALID_OPERATION;
155 }
156 size_t extraEntries = get_camera_metadata_entry_count(other);
157 size_t extraData = get_camera_metadata_data_count(other);
158 resizeIfNeeded(extraEntries, extraData);
159
160 return append_camera_metadata(mBuffer, other);
161 }
162
entryCount() const163 size_t CameraMetadata::entryCount() const {
164 return (mBuffer == NULL) ? 0 :
165 get_camera_metadata_entry_count(mBuffer);
166 }
167
isEmpty() const168 bool CameraMetadata::isEmpty() const {
169 return entryCount() == 0;
170 }
171
sort()172 status_t CameraMetadata::sort() {
173 if (mLocked) {
174 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
175 return INVALID_OPERATION;
176 }
177 return sort_camera_metadata(mBuffer);
178 }
179
checkType(uint32_t tag,uint8_t expectedType)180 status_t CameraMetadata::checkType(uint32_t tag, uint8_t expectedType) {
181 int tagType = get_local_camera_metadata_tag_type(tag, mBuffer);
182 if ( CC_UNLIKELY(tagType == -1)) {
183 ALOGE("Update metadata entry: Unknown tag %d", tag);
184 return INVALID_OPERATION;
185 }
186 if ( CC_UNLIKELY(tagType != expectedType) ) {
187 ALOGE("Mismatched tag type when updating entry %s (%d) of type %s; "
188 "got type %s data instead ",
189 get_local_camera_metadata_tag_name(tag, mBuffer), tag,
190 camera_metadata_type_names[tagType],
191 camera_metadata_type_names[expectedType]);
192 return INVALID_OPERATION;
193 }
194 return OK;
195 }
196
update(uint32_t tag,const int32_t * data,size_t data_count)197 status_t CameraMetadata::update(uint32_t tag,
198 const int32_t *data, size_t data_count) {
199 status_t res;
200 if (mLocked) {
201 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
202 return INVALID_OPERATION;
203 }
204 if ( (res = checkType(tag, TYPE_INT32)) != OK) {
205 return res;
206 }
207 return updateImpl(tag, (const void*)data, data_count);
208 }
209
update(uint32_t tag,const uint8_t * data,size_t data_count)210 status_t CameraMetadata::update(uint32_t tag,
211 const uint8_t *data, size_t data_count) {
212 status_t res;
213 if (mLocked) {
214 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
215 return INVALID_OPERATION;
216 }
217 if ( (res = checkType(tag, TYPE_BYTE)) != OK) {
218 return res;
219 }
220 return updateImpl(tag, (const void*)data, data_count);
221 }
222
update(uint32_t tag,const float * data,size_t data_count)223 status_t CameraMetadata::update(uint32_t tag,
224 const float *data, size_t data_count) {
225 status_t res;
226 if (mLocked) {
227 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
228 return INVALID_OPERATION;
229 }
230 if ( (res = checkType(tag, TYPE_FLOAT)) != OK) {
231 return res;
232 }
233 return updateImpl(tag, (const void*)data, data_count);
234 }
235
update(uint32_t tag,const int64_t * data,size_t data_count)236 status_t CameraMetadata::update(uint32_t tag,
237 const int64_t *data, size_t data_count) {
238 status_t res;
239 if (mLocked) {
240 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
241 return INVALID_OPERATION;
242 }
243 if ( (res = checkType(tag, TYPE_INT64)) != OK) {
244 return res;
245 }
246 return updateImpl(tag, (const void*)data, data_count);
247 }
248
update(uint32_t tag,const double * data,size_t data_count)249 status_t CameraMetadata::update(uint32_t tag,
250 const double *data, size_t data_count) {
251 status_t res;
252 if (mLocked) {
253 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
254 return INVALID_OPERATION;
255 }
256 if ( (res = checkType(tag, TYPE_DOUBLE)) != OK) {
257 return res;
258 }
259 return updateImpl(tag, (const void*)data, data_count);
260 }
261
update(uint32_t tag,const camera_metadata_rational_t * data,size_t data_count)262 status_t CameraMetadata::update(uint32_t tag,
263 const camera_metadata_rational_t *data, size_t data_count) {
264 status_t res;
265 if (mLocked) {
266 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
267 return INVALID_OPERATION;
268 }
269 if ( (res = checkType(tag, TYPE_RATIONAL)) != OK) {
270 return res;
271 }
272 return updateImpl(tag, (const void*)data, data_count);
273 }
274
update(uint32_t tag,const String8 & string)275 status_t CameraMetadata::update(uint32_t tag,
276 const String8 &string) {
277 status_t res;
278 if (mLocked) {
279 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
280 return INVALID_OPERATION;
281 }
282 if ( (res = checkType(tag, TYPE_BYTE)) != OK) {
283 return res;
284 }
285 // string.size() doesn't count the null termination character.
286 return updateImpl(tag, (const void*)string.string(), string.size() + 1);
287 }
288
update(const camera_metadata_ro_entry & entry)289 status_t CameraMetadata::update(const camera_metadata_ro_entry &entry) {
290 status_t res;
291 if (mLocked) {
292 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
293 return INVALID_OPERATION;
294 }
295 if ( (res = checkType(entry.tag, entry.type)) != OK) {
296 return res;
297 }
298 return updateImpl(entry.tag, (const void*)entry.data.u8, entry.count);
299 }
300
updateImpl(uint32_t tag,const void * data,size_t data_count)301 status_t CameraMetadata::updateImpl(uint32_t tag, const void *data,
302 size_t data_count) {
303 status_t res;
304 if (mLocked) {
305 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
306 return INVALID_OPERATION;
307 }
308 int type = get_local_camera_metadata_tag_type(tag, mBuffer);
309 if (type == -1) {
310 ALOGE("%s: Tag %d not found", __FUNCTION__, tag);
311 return BAD_VALUE;
312 }
313 // Safety check - ensure that data isn't pointing to this metadata, since
314 // that would get invalidated if a resize is needed
315 size_t bufferSize = get_camera_metadata_size(mBuffer);
316 uintptr_t bufAddr = reinterpret_cast<uintptr_t>(mBuffer);
317 uintptr_t dataAddr = reinterpret_cast<uintptr_t>(data);
318 if (dataAddr > bufAddr && dataAddr < (bufAddr + bufferSize)) {
319 ALOGE("%s: Update attempted with data from the same metadata buffer!",
320 __FUNCTION__);
321 return INVALID_OPERATION;
322 }
323
324 size_t data_size = calculate_camera_metadata_entry_data_size(type,
325 data_count);
326
327 res = resizeIfNeeded(1, data_size);
328
329 if (res == OK) {
330 camera_metadata_entry_t entry;
331 res = find_camera_metadata_entry(mBuffer, tag, &entry);
332 if (res == NAME_NOT_FOUND) {
333 res = add_camera_metadata_entry(mBuffer,
334 tag, data, data_count);
335 } else if (res == OK) {
336 res = update_camera_metadata_entry(mBuffer,
337 entry.index, data, data_count, NULL);
338 }
339 }
340
341 if (res != OK) {
342 ALOGE("%s: Unable to update metadata entry %s.%s (%x): %s (%d)",
343 __FUNCTION__, get_local_camera_metadata_section_name(tag, mBuffer),
344 get_local_camera_metadata_tag_name(tag, mBuffer), tag,
345 strerror(-res), res);
346 }
347
348 IF_ALOGV() {
349 ALOGE_IF(validate_camera_metadata_structure(mBuffer, /*size*/NULL) !=
350 OK,
351
352 "%s: Failed to validate metadata structure after update %p",
353 __FUNCTION__, mBuffer);
354 }
355
356 return res;
357 }
358
exists(uint32_t tag) const359 bool CameraMetadata::exists(uint32_t tag) const {
360 camera_metadata_ro_entry entry;
361 return find_camera_metadata_ro_entry(mBuffer, tag, &entry) == 0;
362 }
363
find(uint32_t tag)364 camera_metadata_entry_t CameraMetadata::find(uint32_t tag) {
365 status_t res;
366 camera_metadata_entry entry;
367 if (mLocked) {
368 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
369 entry.count = 0;
370 return entry;
371 }
372 res = find_camera_metadata_entry(mBuffer, tag, &entry);
373 if (CC_UNLIKELY( res != OK )) {
374 entry.count = 0;
375 entry.data.u8 = NULL;
376 }
377 return entry;
378 }
379
find(uint32_t tag) const380 camera_metadata_ro_entry_t CameraMetadata::find(uint32_t tag) const {
381 status_t res;
382 camera_metadata_ro_entry entry;
383 res = find_camera_metadata_ro_entry(mBuffer, tag, &entry);
384 if (CC_UNLIKELY( res != OK )) {
385 entry.count = 0;
386 entry.data.u8 = NULL;
387 }
388 return entry;
389 }
390
erase(uint32_t tag)391 status_t CameraMetadata::erase(uint32_t tag) {
392 camera_metadata_entry_t entry;
393 status_t res;
394 if (mLocked) {
395 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
396 return INVALID_OPERATION;
397 }
398 res = find_camera_metadata_entry(mBuffer, tag, &entry);
399 if (res == NAME_NOT_FOUND) {
400 return OK;
401 } else if (res != OK) {
402 ALOGE("%s: Error looking for entry %s.%s (%x): %s %d",
403 __FUNCTION__,
404 get_local_camera_metadata_section_name(tag, mBuffer),
405 get_local_camera_metadata_tag_name(tag, mBuffer),
406 tag, strerror(-res), res);
407 return res;
408 }
409 res = delete_camera_metadata_entry(mBuffer, entry.index);
410 if (res != OK) {
411 ALOGE("%s: Error deleting entry %s.%s (%x): %s %d",
412 __FUNCTION__,
413 get_local_camera_metadata_section_name(tag, mBuffer),
414 get_local_camera_metadata_tag_name(tag, mBuffer),
415 tag, strerror(-res), res);
416 }
417 return res;
418 }
419
removePermissionEntries(metadata_vendor_id_t vendorId,std::vector<int32_t> * tagsRemoved)420 status_t CameraMetadata::removePermissionEntries(metadata_vendor_id_t vendorId,
421 std::vector<int32_t> *tagsRemoved) {
422 uint32_t tagCount = 0;
423 std::vector<uint32_t> tagsToRemove;
424
425 if (tagsRemoved == nullptr) {
426 return BAD_VALUE;
427 }
428
429 sp<VendorTagDescriptor> vTags = VendorTagDescriptor::getGlobalVendorTagDescriptor();
430 if ((nullptr == vTags.get()) || (0 >= vTags->getTagCount())) {
431 sp<VendorTagDescriptorCache> cache =
432 VendorTagDescriptorCache::getGlobalVendorTagCache();
433 if (cache.get()) {
434 cache->getVendorTagDescriptor(vendorId, &vTags);
435 }
436 }
437
438 if ((nullptr != vTags.get()) && (vTags->getTagCount() > 0)) {
439 tagCount = vTags->getTagCount();
440 uint32_t *vendorTags = new uint32_t[tagCount];
441 if (nullptr == vendorTags) {
442 return NO_MEMORY;
443 }
444 vTags->getTagArray(vendorTags);
445
446 tagsToRemove.reserve(tagCount);
447 tagsToRemove.insert(tagsToRemove.begin(), vendorTags, vendorTags + tagCount);
448
449 delete [] vendorTags;
450 tagCount = 0;
451 }
452
453 auto tagsNeedingPermission = get_camera_metadata_permission_needed(&tagCount);
454 if (tagCount > 0) {
455 tagsToRemove.reserve(tagsToRemove.capacity() + tagCount);
456 tagsToRemove.insert(tagsToRemove.end(), tagsNeedingPermission,
457 tagsNeedingPermission + tagCount);
458 }
459
460 tagsRemoved->reserve(tagsToRemove.size());
461 for (const auto &it : tagsToRemove) {
462 if (exists(it)) {
463 auto rc = erase(it);
464 if (NO_ERROR != rc) {
465 ALOGE("%s: Failed to erase tag: %x", __func__, it);
466 return rc;
467 }
468 tagsRemoved->push_back(it);
469 }
470 }
471
472 // Update the available characterstics accordingly
473 if (exists(ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS)) {
474 std::vector<uint32_t> currentKeys;
475
476 std::sort(tagsRemoved->begin(), tagsRemoved->end());
477 auto keys = find(ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS);
478 currentKeys.reserve(keys.count);
479 currentKeys.insert(currentKeys.end(), keys.data.i32, keys.data.i32 + keys.count);
480 std::sort(currentKeys.begin(), currentKeys.end());
481
482 std::vector<int32_t> newKeys(keys.count);
483 auto end = std::set_difference(currentKeys.begin(), currentKeys.end(), tagsRemoved->begin(),
484 tagsRemoved->end(), newKeys.begin());
485 newKeys.resize(end - newKeys.begin());
486
487 update(ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS, newKeys.data(), newKeys.size());
488 }
489
490 return NO_ERROR;
491 }
492
dump(int fd,int verbosity,int indentation) const493 void CameraMetadata::dump(int fd, int verbosity, int indentation) const {
494 dump_indented_camera_metadata(mBuffer, fd, verbosity, indentation);
495 }
496
resizeIfNeeded(size_t extraEntries,size_t extraData)497 status_t CameraMetadata::resizeIfNeeded(size_t extraEntries, size_t extraData) {
498 if (mBuffer == NULL) {
499 mBuffer = allocate_camera_metadata(extraEntries * 2, extraData * 2);
500 if (mBuffer == NULL) {
501 ALOGE("%s: Can't allocate larger metadata buffer", __FUNCTION__);
502 return NO_MEMORY;
503 }
504 } else {
505 size_t currentEntryCount = get_camera_metadata_entry_count(mBuffer);
506 size_t currentEntryCap = get_camera_metadata_entry_capacity(mBuffer);
507 size_t newEntryCount = currentEntryCount +
508 extraEntries;
509 newEntryCount = (newEntryCount > currentEntryCap) ?
510 newEntryCount * 2 : currentEntryCap;
511
512 size_t currentDataCount = get_camera_metadata_data_count(mBuffer);
513 size_t currentDataCap = get_camera_metadata_data_capacity(mBuffer);
514 size_t newDataCount = currentDataCount +
515 extraData;
516 newDataCount = (newDataCount > currentDataCap) ?
517 newDataCount * 2 : currentDataCap;
518
519 if (newEntryCount > currentEntryCap ||
520 newDataCount > currentDataCap) {
521 camera_metadata_t *oldBuffer = mBuffer;
522 mBuffer = allocate_camera_metadata(newEntryCount,
523 newDataCount);
524 if (mBuffer == NULL) {
525 ALOGE("%s: Can't allocate larger metadata buffer", __FUNCTION__);
526 return NO_MEMORY;
527 }
528 append_camera_metadata(mBuffer, oldBuffer);
529 free_camera_metadata(oldBuffer);
530 }
531 }
532 return OK;
533 }
534
readFromParcel(const Parcel & data,camera_metadata_t ** out)535 status_t CameraMetadata::readFromParcel(const Parcel& data,
536 camera_metadata_t** out) {
537
538 status_t err = OK;
539
540 camera_metadata_t* metadata = NULL;
541
542 if (out) {
543 *out = NULL;
544 }
545
546 // See CameraMetadata::writeToParcel for parcel data layout diagram and explanation.
547 // arg0 = blobSize (int32)
548 int32_t blobSizeTmp = -1;
549 if ((err = data.readInt32(&blobSizeTmp)) != OK) {
550 ALOGE("%s: Failed to read metadata size (error %d %s)",
551 __FUNCTION__, err, strerror(-err));
552 return err;
553 }
554 const size_t blobSize = static_cast<size_t>(blobSizeTmp);
555 const size_t alignment = get_camera_metadata_alignment();
556
557 // Special case: zero blob size means zero sized (NULL) metadata.
558 if (blobSize == 0) {
559 ALOGV("%s: Read 0-sized metadata", __FUNCTION__);
560 return OK;
561 }
562
563 if (blobSize <= alignment) {
564 ALOGE("%s: metadata blob is malformed, blobSize(%zu) should be larger than alignment(%zu)",
565 __FUNCTION__, blobSize, alignment);
566 return BAD_VALUE;
567 }
568
569 const size_t metadataSize = blobSize - alignment;
570
571 // NOTE: this doesn't make sense to me. shouldn't the blob
572 // know how big it is? why do we have to specify the size
573 // to Parcel::readBlob ?
574 ReadableBlob blob;
575 // arg1 = metadata (blob)
576 do {
577 if ((err = data.readBlob(blobSize, &blob)) != OK) {
578 ALOGE("%s: Failed to read metadata blob (sized %zu). Possible "
579 " serialization bug. Error %d %s",
580 __FUNCTION__, blobSize, err, strerror(-err));
581 break;
582 }
583
584 // arg2 = offset (blob)
585 // Must be after blob since we don't know offset until after writeBlob.
586 int32_t offsetTmp;
587 if ((err = data.readInt32(&offsetTmp)) != OK) {
588 ALOGE("%s: Failed to read metadata offsetTmp (error %d %s)",
589 __FUNCTION__, err, strerror(-err));
590 break;
591 }
592 const size_t offset = static_cast<size_t>(offsetTmp);
593 if (offset >= alignment) {
594 ALOGE("%s: metadata offset(%zu) should be less than alignment(%zu)",
595 __FUNCTION__, blobSize, alignment);
596 err = BAD_VALUE;
597 break;
598 }
599
600 const uintptr_t metadataStart = reinterpret_cast<uintptr_t>(blob.data()) + offset;
601 const camera_metadata_t* tmp =
602 reinterpret_cast<const camera_metadata_t*>(metadataStart);
603 ALOGV("%s: alignment is: %zu, metadata start: %p, offset: %zu",
604 __FUNCTION__, alignment, tmp, offset);
605 metadata = allocate_copy_camera_metadata_checked(tmp, metadataSize);
606 if (metadata == NULL) {
607 // We consider that allocation only fails if the validation
608 // also failed, therefore the readFromParcel was a failure.
609 ALOGE("%s: metadata allocation and copy failed", __FUNCTION__);
610 err = BAD_VALUE;
611 }
612 } while(0);
613 blob.release();
614
615 if (out) {
616 ALOGV("%s: Set out metadata to %p", __FUNCTION__, metadata);
617 *out = metadata;
618 } else if (metadata != NULL) {
619 ALOGV("%s: Freed camera metadata at %p", __FUNCTION__, metadata);
620 free_camera_metadata(metadata);
621 }
622
623 return err;
624 }
625
writeToParcel(Parcel & data,const camera_metadata_t * metadata)626 status_t CameraMetadata::writeToParcel(Parcel& data,
627 const camera_metadata_t* metadata) {
628 status_t res = OK;
629
630 /**
631 * Below is the camera metadata parcel layout:
632 *
633 * |--------------------------------------------|
634 * | arg0: blobSize |
635 * | (length = 4) |
636 * |--------------------------------------------|<--Skip the rest if blobSize == 0.
637 * | |
638 * | |
639 * | arg1: blob |
640 * | (length = variable, see arg1 layout below) |
641 * | |
642 * | |
643 * |--------------------------------------------|
644 * | arg2: offset |
645 * | (length = 4) |
646 * |--------------------------------------------|
647 */
648
649 // arg0 = blobSize (int32)
650 if (metadata == NULL) {
651 // Write zero blobSize for null metadata.
652 return data.writeInt32(0);
653 }
654
655 /**
656 * Always make the blob size sufficiently larger, as we need put alignment
657 * padding and metadata into the blob. Since we don't know the alignment
658 * offset before writeBlob. Then write the metadata to aligned offset.
659 */
660 const size_t metadataSize = get_camera_metadata_compact_size(metadata);
661 const size_t alignment = get_camera_metadata_alignment();
662 const size_t blobSize = metadataSize + alignment;
663 res = data.writeInt32(static_cast<int32_t>(blobSize));
664 if (res != OK) {
665 return res;
666 }
667
668 size_t offset = 0;
669 /**
670 * arg1 = metadata (blob).
671 *
672 * The blob size is the sum of front padding size, metadata size and back padding
673 * size, which is equal to metadataSize + alignment.
674 *
675 * The blob layout is:
676 * |------------------------------------|<----Start address of the blob (unaligned).
677 * | front padding |
678 * | (size = offset) |
679 * |------------------------------------|<----Aligned start address of metadata.
680 * | |
681 * | |
682 * | metadata |
683 * | (size = metadataSize) |
684 * | |
685 * | |
686 * |------------------------------------|
687 * | back padding |
688 * | (size = alignment - offset) |
689 * |------------------------------------|<----End address of blob.
690 * (Blob start address + blob size).
691 */
692 WritableBlob blob;
693 do {
694 res = data.writeBlob(blobSize, false, &blob);
695 if (res != OK) {
696 break;
697 }
698 const uintptr_t metadataStart = ALIGN_TO(blob.data(), alignment);
699 offset = metadataStart - reinterpret_cast<uintptr_t>(blob.data());
700 ALOGV("%s: alignment is: %zu, metadata start: %p, offset: %zu",
701 __FUNCTION__, alignment,
702 reinterpret_cast<const void *>(metadataStart), offset);
703 copy_camera_metadata(reinterpret_cast<void*>(metadataStart), metadataSize, metadata);
704
705 // Not too big of a problem since receiving side does hard validation
706 // Don't check the size since the compact size could be larger
707 if (validate_camera_metadata_structure(metadata, /*size*/NULL) != OK) {
708 ALOGW("%s: Failed to validate metadata %p before writing blob",
709 __FUNCTION__, metadata);
710 }
711
712 } while(false);
713 blob.release();
714
715 // arg2 = offset (int32)
716 res = data.writeInt32(static_cast<int32_t>(offset));
717
718 return res;
719 }
720
readFromParcel(const Parcel * parcel)721 status_t CameraMetadata::readFromParcel(const Parcel *parcel) {
722
723 ALOGV("%s: parcel = %p", __FUNCTION__, parcel);
724
725 status_t res = OK;
726
727 if (parcel == NULL) {
728 ALOGE("%s: parcel is null", __FUNCTION__);
729 return BAD_VALUE;
730 }
731
732 if (mLocked) {
733 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
734 return INVALID_OPERATION;
735 }
736
737 camera_metadata *buffer = NULL;
738 // TODO: reading should return a status code, in case validation fails
739 res = CameraMetadata::readFromParcel(*parcel, &buffer);
740
741 if (res != NO_ERROR) {
742 ALOGE("%s: Failed to read from parcel. Metadata is unchanged.",
743 __FUNCTION__);
744 return res;
745 }
746
747 clear();
748 mBuffer = buffer;
749
750 return OK;
751 }
752
writeToParcel(Parcel * parcel) const753 status_t CameraMetadata::writeToParcel(Parcel *parcel) const {
754
755 ALOGV("%s: parcel = %p", __FUNCTION__, parcel);
756
757 if (parcel == NULL) {
758 ALOGE("%s: parcel is null", __FUNCTION__);
759 return BAD_VALUE;
760 }
761
762 return CameraMetadata::writeToParcel(*parcel, mBuffer);
763 }
764
swap(CameraMetadata & other)765 void CameraMetadata::swap(CameraMetadata& other) {
766 if (mLocked) {
767 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
768 return;
769 } else if (other.mLocked) {
770 ALOGE("%s: Other CameraMetadata is locked", __FUNCTION__);
771 return;
772 }
773
774 camera_metadata* thisBuf = mBuffer;
775 camera_metadata* otherBuf = other.mBuffer;
776
777 other.mBuffer = thisBuf;
778 mBuffer = otherBuf;
779 }
780
getTagFromName(const char * name,const VendorTagDescriptor * vTags,uint32_t * tag)781 status_t CameraMetadata::getTagFromName(const char *name,
782 const VendorTagDescriptor* vTags, uint32_t *tag) {
783
784 if (name == nullptr || tag == nullptr) return BAD_VALUE;
785
786 size_t nameLength = strlen(name);
787
788 const SortedVector<String8> *vendorSections;
789 size_t vendorSectionCount = 0;
790
791 if (vTags != NULL) {
792 vendorSections = vTags->getAllSectionNames();
793 vendorSectionCount = vendorSections->size();
794 }
795
796 // First, find the section by the longest string match
797 const char *section = NULL;
798 size_t sectionIndex = 0;
799 size_t sectionLength = 0;
800 size_t totalSectionCount = ANDROID_SECTION_COUNT + vendorSectionCount;
801 for (size_t i = 0; i < totalSectionCount; ++i) {
802
803 const char *str = (i < ANDROID_SECTION_COUNT) ? camera_metadata_section_names[i] :
804 (*vendorSections)[i - ANDROID_SECTION_COUNT].string();
805
806 ALOGV("%s: Trying to match against section '%s'", __FUNCTION__, str);
807
808 if (strstr(name, str) == name) { // name begins with the section name
809 size_t strLength = strlen(str);
810
811 ALOGV("%s: Name begins with section name", __FUNCTION__);
812
813 // section name is the longest we've found so far
814 if (section == NULL || sectionLength < strLength) {
815 section = str;
816 sectionIndex = i;
817 sectionLength = strLength;
818
819 ALOGV("%s: Found new best section (%s)", __FUNCTION__, section);
820 }
821 }
822 }
823
824 // TODO: Make above get_camera_metadata_section_from_name ?
825
826 if (section == NULL) {
827 return NAME_NOT_FOUND;
828 } else {
829 ALOGV("%s: Found matched section '%s' (%zu)",
830 __FUNCTION__, section, sectionIndex);
831 }
832
833 // Get the tag name component of the name
834 const char *nameTagName = name + sectionLength + 1; // x.y.z -> z
835 if (sectionLength + 1 >= nameLength) {
836 return BAD_VALUE;
837 }
838
839 // Match rest of name against the tag names in that section only
840 uint32_t candidateTag = 0;
841 if (sectionIndex < ANDROID_SECTION_COUNT) {
842 // Match built-in tags (typically android.*)
843 uint32_t tagBegin, tagEnd; // [tagBegin, tagEnd)
844 tagBegin = camera_metadata_section_bounds[sectionIndex][0];
845 tagEnd = camera_metadata_section_bounds[sectionIndex][1];
846
847 for (candidateTag = tagBegin; candidateTag < tagEnd; ++candidateTag) {
848 const char *tagName = get_camera_metadata_tag_name(candidateTag);
849
850 if (strcmp(nameTagName, tagName) == 0) {
851 ALOGV("%s: Found matched tag '%s' (%d)",
852 __FUNCTION__, tagName, candidateTag);
853 break;
854 }
855 }
856
857 if (candidateTag == tagEnd) {
858 return NAME_NOT_FOUND;
859 }
860 } else if (vTags != NULL) {
861 // Match vendor tags (typically com.*)
862 const String8 sectionName(section);
863 const String8 tagName(nameTagName);
864
865 status_t res = OK;
866 if ((res = vTags->lookupTag(tagName, sectionName, &candidateTag)) != OK) {
867 return NAME_NOT_FOUND;
868 }
869 }
870
871 *tag = candidateTag;
872 return OK;
873 }
874
875
876 }; // namespace android
877