Home | History | Annotate | Download | only in camera
      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
    796