• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_camera_metadata_tag_type(tag);
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_camera_metadata_tag_name(tag), 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_camera_metadata_tag_type(tag);
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_camera_metadata_section_name(tag),
336                 get_camera_metadata_tag_name(tag), tag, strerror(-res), res);
337     }
338 
339     IF_ALOGV() {
340         ALOGE_IF(validate_camera_metadata_structure(mBuffer, /*size*/NULL) !=
341                  OK,
342 
343                  "%s: Failed to validate metadata structure after update %p",
344                  __FUNCTION__, mBuffer);
345     }
346 
347     return res;
348 }
349 
exists(uint32_t tag) const350 bool CameraMetadata::exists(uint32_t tag) const {
351     camera_metadata_ro_entry entry;
352     return find_camera_metadata_ro_entry(mBuffer, tag, &entry) == 0;
353 }
354 
find(uint32_t tag)355 camera_metadata_entry_t CameraMetadata::find(uint32_t tag) {
356     status_t res;
357     camera_metadata_entry entry;
358     if (mLocked) {
359         ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
360         entry.count = 0;
361         return entry;
362     }
363     res = find_camera_metadata_entry(mBuffer, tag, &entry);
364     if (CC_UNLIKELY( res != OK )) {
365         entry.count = 0;
366         entry.data.u8 = NULL;
367     }
368     return entry;
369 }
370 
find(uint32_t tag) const371 camera_metadata_ro_entry_t CameraMetadata::find(uint32_t tag) const {
372     status_t res;
373     camera_metadata_ro_entry entry;
374     res = find_camera_metadata_ro_entry(mBuffer, tag, &entry);
375     if (CC_UNLIKELY( res != OK )) {
376         entry.count = 0;
377         entry.data.u8 = NULL;
378     }
379     return entry;
380 }
381 
erase(uint32_t tag)382 status_t CameraMetadata::erase(uint32_t tag) {
383     camera_metadata_entry_t entry;
384     status_t res;
385     if (mLocked) {
386         ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
387         return INVALID_OPERATION;
388     }
389     res = find_camera_metadata_entry(mBuffer, tag, &entry);
390     if (res == NAME_NOT_FOUND) {
391         return OK;
392     } else if (res != OK) {
393         ALOGE("%s: Error looking for entry %s.%s (%x): %s %d",
394                 __FUNCTION__,
395                 get_camera_metadata_section_name(tag),
396                 get_camera_metadata_tag_name(tag), tag, strerror(-res), res);
397         return res;
398     }
399     res = delete_camera_metadata_entry(mBuffer, entry.index);
400     if (res != OK) {
401         ALOGE("%s: Error deleting entry %s.%s (%x): %s %d",
402                 __FUNCTION__,
403                 get_camera_metadata_section_name(tag),
404                 get_camera_metadata_tag_name(tag), tag, strerror(-res), res);
405     }
406     return res;
407 }
408 
dump(int fd,int verbosity,int indentation) const409 void CameraMetadata::dump(int fd, int verbosity, int indentation) const {
410     dump_indented_camera_metadata(mBuffer, fd, verbosity, indentation);
411 }
412 
resizeIfNeeded(size_t extraEntries,size_t extraData)413 status_t CameraMetadata::resizeIfNeeded(size_t extraEntries, size_t extraData) {
414     if (mBuffer == NULL) {
415         mBuffer = allocate_camera_metadata(extraEntries * 2, extraData * 2);
416         if (mBuffer == NULL) {
417             ALOGE("%s: Can't allocate larger metadata buffer", __FUNCTION__);
418             return NO_MEMORY;
419         }
420     } else {
421         size_t currentEntryCount = get_camera_metadata_entry_count(mBuffer);
422         size_t currentEntryCap = get_camera_metadata_entry_capacity(mBuffer);
423         size_t newEntryCount = currentEntryCount +
424                 extraEntries;
425         newEntryCount = (newEntryCount > currentEntryCap) ?
426                 newEntryCount * 2 : currentEntryCap;
427 
428         size_t currentDataCount = get_camera_metadata_data_count(mBuffer);
429         size_t currentDataCap = get_camera_metadata_data_capacity(mBuffer);
430         size_t newDataCount = currentDataCount +
431                 extraData;
432         newDataCount = (newDataCount > currentDataCap) ?
433                 newDataCount * 2 : currentDataCap;
434 
435         if (newEntryCount > currentEntryCap ||
436                 newDataCount > currentDataCap) {
437             camera_metadata_t *oldBuffer = mBuffer;
438             mBuffer = allocate_camera_metadata(newEntryCount,
439                     newDataCount);
440             if (mBuffer == NULL) {
441                 ALOGE("%s: Can't allocate larger metadata buffer", __FUNCTION__);
442                 return NO_MEMORY;
443             }
444             append_camera_metadata(mBuffer, oldBuffer);
445             free_camera_metadata(oldBuffer);
446         }
447     }
448     return OK;
449 }
450 
readFromParcel(const Parcel & data,camera_metadata_t ** out)451 status_t CameraMetadata::readFromParcel(const Parcel& data,
452                                         camera_metadata_t** out) {
453 
454     status_t err = OK;
455 
456     camera_metadata_t* metadata = NULL;
457 
458     if (out) {
459         *out = NULL;
460     }
461 
462     // See CameraMetadata::writeToParcel for parcel data layout diagram and explanation.
463     // arg0 = blobSize (int32)
464     int32_t blobSizeTmp = -1;
465     if ((err = data.readInt32(&blobSizeTmp)) != OK) {
466         ALOGE("%s: Failed to read metadata size (error %d %s)",
467               __FUNCTION__, err, strerror(-err));
468         return err;
469     }
470     const size_t blobSize = static_cast<size_t>(blobSizeTmp);
471     const size_t alignment = get_camera_metadata_alignment();
472 
473     // Special case: zero blob size means zero sized (NULL) metadata.
474     if (blobSize == 0) {
475         ALOGV("%s: Read 0-sized metadata", __FUNCTION__);
476         return OK;
477     }
478 
479     if (blobSize <= alignment) {
480         ALOGE("%s: metadata blob is malformed, blobSize(%zu) should be larger than alignment(%zu)",
481                 __FUNCTION__, blobSize, alignment);
482         return BAD_VALUE;
483     }
484 
485     const size_t metadataSize = blobSize - alignment;
486 
487     // NOTE: this doesn't make sense to me. shouldn't the blob
488     // know how big it is? why do we have to specify the size
489     // to Parcel::readBlob ?
490     ReadableBlob blob;
491     // arg1 = metadata (blob)
492     do {
493         if ((err = data.readBlob(blobSize, &blob)) != OK) {
494             ALOGE("%s: Failed to read metadata blob (sized %zu). Possible "
495                   " serialization bug. Error %d %s",
496                   __FUNCTION__, blobSize, err, strerror(-err));
497             break;
498         }
499 
500         // arg2 = offset (blob)
501         // Must be after blob since we don't know offset until after writeBlob.
502         int32_t offsetTmp;
503         if ((err = data.readInt32(&offsetTmp)) != OK) {
504             ALOGE("%s: Failed to read metadata offsetTmp (error %d %s)",
505                   __FUNCTION__, err, strerror(-err));
506             break;
507         }
508         const size_t offset = static_cast<size_t>(offsetTmp);
509         if (offset >= alignment) {
510             ALOGE("%s: metadata offset(%zu) should be less than alignment(%zu)",
511                     __FUNCTION__, blobSize, alignment);
512             err = BAD_VALUE;
513             break;
514         }
515 
516         const uintptr_t metadataStart = reinterpret_cast<uintptr_t>(blob.data()) + offset;
517         const camera_metadata_t* tmp =
518                        reinterpret_cast<const camera_metadata_t*>(metadataStart);
519         ALOGV("%s: alignment is: %zu, metadata start: %p, offset: %zu",
520                 __FUNCTION__, alignment, tmp, offset);
521         metadata = allocate_copy_camera_metadata_checked(tmp, metadataSize);
522         if (metadata == NULL) {
523             // We consider that allocation only fails if the validation
524             // also failed, therefore the readFromParcel was a failure.
525             ALOGE("%s: metadata allocation and copy failed", __FUNCTION__);
526             err = BAD_VALUE;
527         }
528     } while(0);
529     blob.release();
530 
531     if (out) {
532         ALOGV("%s: Set out metadata to %p", __FUNCTION__, metadata);
533         *out = metadata;
534     } else if (metadata != NULL) {
535         ALOGV("%s: Freed camera metadata at %p", __FUNCTION__, metadata);
536         free_camera_metadata(metadata);
537     }
538 
539     return err;
540 }
541 
writeToParcel(Parcel & data,const camera_metadata_t * metadata)542 status_t CameraMetadata::writeToParcel(Parcel& data,
543                                        const camera_metadata_t* metadata) {
544     status_t res = OK;
545 
546     /**
547      * Below is the camera metadata parcel layout:
548      *
549      * |--------------------------------------------|
550      * |             arg0: blobSize                 |
551      * |              (length = 4)                  |
552      * |--------------------------------------------|<--Skip the rest if blobSize == 0.
553      * |                                            |
554      * |                                            |
555      * |              arg1: blob                    |
556      * | (length = variable, see arg1 layout below) |
557      * |                                            |
558      * |                                            |
559      * |--------------------------------------------|
560      * |              arg2: offset                  |
561      * |              (length = 4)                  |
562      * |--------------------------------------------|
563      */
564 
565     // arg0 = blobSize (int32)
566     if (metadata == NULL) {
567         // Write zero blobSize for null metadata.
568         return data.writeInt32(0);
569     }
570 
571     /**
572      * Always make the blob size sufficiently larger, as we need put alignment
573      * padding and metadata into the blob. Since we don't know the alignment
574      * offset before writeBlob. Then write the metadata to aligned offset.
575      */
576     const size_t metadataSize = get_camera_metadata_compact_size(metadata);
577     const size_t alignment = get_camera_metadata_alignment();
578     const size_t blobSize = metadataSize + alignment;
579     res = data.writeInt32(static_cast<int32_t>(blobSize));
580     if (res != OK) {
581         return res;
582     }
583 
584     size_t offset = 0;
585     /**
586      * arg1 = metadata (blob).
587      *
588      * The blob size is the sum of front padding size, metadata size and back padding
589      * size, which is equal to metadataSize + alignment.
590      *
591      * The blob layout is:
592      * |------------------------------------|<----Start address of the blob (unaligned).
593      * |           front padding            |
594      * |          (size = offset)           |
595      * |------------------------------------|<----Aligned start address of metadata.
596      * |                                    |
597      * |                                    |
598      * |            metadata                |
599      * |       (size = metadataSize)        |
600      * |                                    |
601      * |                                    |
602      * |------------------------------------|
603      * |           back padding             |
604      * |     (size = alignment - offset)    |
605      * |------------------------------------|<----End address of blob.
606      *                                            (Blob start address + blob size).
607      */
608     WritableBlob blob;
609     do {
610         res = data.writeBlob(blobSize, false, &blob);
611         if (res != OK) {
612             break;
613         }
614         const uintptr_t metadataStart = ALIGN_TO(blob.data(), alignment);
615         offset = metadataStart - reinterpret_cast<uintptr_t>(blob.data());
616         ALOGV("%s: alignment is: %zu, metadata start: %p, offset: %zu",
617                 __FUNCTION__, alignment,
618                 reinterpret_cast<const void *>(metadataStart), offset);
619         copy_camera_metadata(reinterpret_cast<void*>(metadataStart), metadataSize, metadata);
620 
621         // Not too big of a problem since receiving side does hard validation
622         // Don't check the size since the compact size could be larger
623         if (validate_camera_metadata_structure(metadata, /*size*/NULL) != OK) {
624             ALOGW("%s: Failed to validate metadata %p before writing blob",
625                    __FUNCTION__, metadata);
626         }
627 
628     } while(false);
629     blob.release();
630 
631     // arg2 = offset (int32)
632     res = data.writeInt32(static_cast<int32_t>(offset));
633 
634     return res;
635 }
636 
readFromParcel(const Parcel * parcel)637 status_t CameraMetadata::readFromParcel(const Parcel *parcel) {
638 
639     ALOGV("%s: parcel = %p", __FUNCTION__, parcel);
640 
641     status_t res = OK;
642 
643     if (parcel == NULL) {
644         ALOGE("%s: parcel is null", __FUNCTION__);
645         return BAD_VALUE;
646     }
647 
648     if (mLocked) {
649         ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
650         return INVALID_OPERATION;
651     }
652 
653     camera_metadata *buffer = NULL;
654     // TODO: reading should return a status code, in case validation fails
655     res = CameraMetadata::readFromParcel(*parcel, &buffer);
656 
657     if (res != NO_ERROR) {
658         ALOGE("%s: Failed to read from parcel. Metadata is unchanged.",
659               __FUNCTION__);
660         return res;
661     }
662 
663     clear();
664     mBuffer = buffer;
665 
666     return OK;
667 }
668 
writeToParcel(Parcel * parcel) const669 status_t CameraMetadata::writeToParcel(Parcel *parcel) const {
670 
671     ALOGV("%s: parcel = %p", __FUNCTION__, parcel);
672 
673     if (parcel == NULL) {
674         ALOGE("%s: parcel is null", __FUNCTION__);
675         return BAD_VALUE;
676     }
677 
678     return CameraMetadata::writeToParcel(*parcel, mBuffer);
679 }
680 
swap(CameraMetadata & other)681 void CameraMetadata::swap(CameraMetadata& other) {
682     if (mLocked) {
683         ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
684         return;
685     } else if (other.mLocked) {
686         ALOGE("%s: Other CameraMetadata is locked", __FUNCTION__);
687         return;
688     }
689 
690     camera_metadata* thisBuf = mBuffer;
691     camera_metadata* otherBuf = other.mBuffer;
692 
693     other.mBuffer = thisBuf;
694     mBuffer = otherBuf;
695 }
696 
getTagFromName(const char * name,const VendorTagDescriptor * vTags,uint32_t * tag)697 status_t CameraMetadata::getTagFromName(const char *name,
698         const VendorTagDescriptor* vTags, uint32_t *tag) {
699 
700     if (name == nullptr || tag == nullptr) return BAD_VALUE;
701 
702     size_t nameLength = strlen(name);
703 
704     const SortedVector<String8> *vendorSections;
705     size_t vendorSectionCount = 0;
706 
707     if (vTags != NULL) {
708         vendorSections = vTags->getAllSectionNames();
709         vendorSectionCount = vendorSections->size();
710     }
711 
712     // First, find the section by the longest string match
713     const char *section = NULL;
714     size_t sectionIndex = 0;
715     size_t sectionLength = 0;
716     size_t totalSectionCount = ANDROID_SECTION_COUNT + vendorSectionCount;
717     for (size_t i = 0; i < totalSectionCount; ++i) {
718 
719         const char *str = (i < ANDROID_SECTION_COUNT) ? camera_metadata_section_names[i] :
720                 (*vendorSections)[i - ANDROID_SECTION_COUNT].string();
721 
722         ALOGV("%s: Trying to match against section '%s'", __FUNCTION__, str);
723 
724         if (strstr(name, str) == name) { // name begins with the section name
725             size_t strLength = strlen(str);
726 
727             ALOGV("%s: Name begins with section name", __FUNCTION__);
728 
729             // section name is the longest we've found so far
730             if (section == NULL || sectionLength < strLength) {
731                 section = str;
732                 sectionIndex = i;
733                 sectionLength = strLength;
734 
735                 ALOGV("%s: Found new best section (%s)", __FUNCTION__, section);
736             }
737         }
738     }
739 
740     // TODO: Make above get_camera_metadata_section_from_name ?
741 
742     if (section == NULL) {
743         return NAME_NOT_FOUND;
744     } else {
745         ALOGV("%s: Found matched section '%s' (%zu)",
746               __FUNCTION__, section, sectionIndex);
747     }
748 
749     // Get the tag name component of the name
750     const char *nameTagName = name + sectionLength + 1; // x.y.z -> z
751     if (sectionLength + 1 >= nameLength) {
752         return BAD_VALUE;
753     }
754 
755     // Match rest of name against the tag names in that section only
756     uint32_t candidateTag = 0;
757     if (sectionIndex < ANDROID_SECTION_COUNT) {
758         // Match built-in tags (typically android.*)
759         uint32_t tagBegin, tagEnd; // [tagBegin, tagEnd)
760         tagBegin = camera_metadata_section_bounds[sectionIndex][0];
761         tagEnd = camera_metadata_section_bounds[sectionIndex][1];
762 
763         for (candidateTag = tagBegin; candidateTag < tagEnd; ++candidateTag) {
764             const char *tagName = get_camera_metadata_tag_name(candidateTag);
765 
766             if (strcmp(nameTagName, tagName) == 0) {
767                 ALOGV("%s: Found matched tag '%s' (%d)",
768                       __FUNCTION__, tagName, candidateTag);
769                 break;
770             }
771         }
772 
773         if (candidateTag == tagEnd) {
774             return NAME_NOT_FOUND;
775         }
776     } else if (vTags != NULL) {
777         // Match vendor tags (typically com.*)
778         const String8 sectionName(section);
779         const String8 tagName(nameTagName);
780 
781         status_t res = OK;
782         if ((res = vTags->lookupTag(tagName, sectionName, &candidateTag)) != OK) {
783             return NAME_NOT_FOUND;
784         }
785     }
786 
787     *tag = candidateTag;
788     return OK;
789 }
790 
791 
792 }; // namespace android
793