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