CameraMetadata.cpp revision 71c73a2985a7ac65ee597be3441ab300fa56e22e
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
27namespace android {
28
29#define ALIGN_TO(val, alignment) \
30    (((uintptr_t)(val) + ((alignment) - 1)) & ~((alignment) - 1))
31
32typedef Parcel::WritableBlob WritableBlob;
33typedef Parcel::ReadableBlob ReadableBlob;
34
35CameraMetadata::CameraMetadata() :
36        mBuffer(NULL), mLocked(false) {
37}
38
39CameraMetadata::CameraMetadata(size_t entryCapacity, size_t dataCapacity) :
40        mLocked(false)
41{
42    mBuffer = allocate_camera_metadata(entryCapacity, dataCapacity);
43}
44
45CameraMetadata::CameraMetadata(const CameraMetadata &other) :
46        mLocked(false) {
47    mBuffer = clone_camera_metadata(other.mBuffer);
48}
49
50CameraMetadata::CameraMetadata(camera_metadata_t *buffer) :
51        mBuffer(NULL), mLocked(false) {
52    acquire(buffer);
53}
54
55CameraMetadata &CameraMetadata::operator=(const CameraMetadata &other) {
56    return operator=(other.mBuffer);
57}
58
59CameraMetadata &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
73CameraMetadata::~CameraMetadata() {
74    mLocked = false;
75    clear();
76}
77
78const camera_metadata_t* CameraMetadata::getAndLock() const {
79    mLocked = true;
80    return mBuffer;
81}
82
83status_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
97camera_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
107void 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
118void 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
131void CameraMetadata::acquire(CameraMetadata &other) {
132    if (mLocked) {
133        ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
134        return;
135    }
136    acquire(other.release());
137}
138
139status_t CameraMetadata::append(const CameraMetadata &other) {
140    return append(other.mBuffer);
141}
142
143status_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
155size_t CameraMetadata::entryCount() const {
156    return (mBuffer == NULL) ? 0 :
157            get_camera_metadata_entry_count(mBuffer);
158}
159
160bool CameraMetadata::isEmpty() const {
161    return entryCount() == 0;
162}
163
164status_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
172status_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
189status_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
202status_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
215status_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
228status_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
241status_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
254status_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
267status_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
281status_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
293status_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
351bool 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
356camera_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
372camera_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
383status_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
412void CameraMetadata::dump(int fd, int verbosity, int indentation) const {
413    dump_indented_camera_metadata(mBuffer, fd, verbosity, indentation);
414}
415
416status_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
454status_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
545status_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
640status_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
672status_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
684void 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
700status_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