OSDN Git Service

Merge changes from topic "b23270724" into lmp-dev am: 5802bad0f4 am: 49acc79a1d ...
[android-x86/frameworks-av.git] / camera / CameraMetadata.cpp
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
35 CameraMetadata::CameraMetadata() :
36         mBuffer(NULL), mLocked(false) {
37 }
38
39 CameraMetadata::CameraMetadata(size_t entryCapacity, size_t dataCapacity) :
40         mLocked(false)
41 {
42     mBuffer = allocate_camera_metadata(entryCapacity, dataCapacity);
43 }
44
45 CameraMetadata::CameraMetadata(const CameraMetadata &other) :
46         mLocked(false) {
47     mBuffer = clone_camera_metadata(other.mBuffer);
48 }
49
50 CameraMetadata::CameraMetadata(camera_metadata_t *buffer) :
51         mBuffer(NULL), mLocked(false) {
52     acquire(buffer);
53 }
54
55 CameraMetadata &CameraMetadata::operator=(const CameraMetadata &other) {
56     return operator=(other.mBuffer);
57 }
58
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
73 CameraMetadata::~CameraMetadata() {
74     mLocked = false;
75     clear();
76 }
77
78 const camera_metadata_t* CameraMetadata::getAndLock() const {
79     mLocked = true;
80     return mBuffer;
81 }
82
83 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
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
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
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
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
139 status_t CameraMetadata::append(const CameraMetadata &other) {
140     return append(other.mBuffer);
141 }
142
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
155 size_t CameraMetadata::entryCount() const {
156     return (mBuffer == NULL) ? 0 :
157             get_camera_metadata_entry_count(mBuffer);
158 }
159
160 bool CameraMetadata::isEmpty() const {
161     return entryCount() == 0;
162 }
163
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
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
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
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
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
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
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
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
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
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
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
351 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
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
372 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
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
412 void CameraMetadata::dump(int fd, int verbosity, int indentation) const {
413     dump_indented_camera_metadata(mBuffer, fd, verbosity, indentation);
414 }
415
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
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
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
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
672 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
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
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