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