status_t CameraMetadata::append(const camera_metadata_t* other) {
    if (mLocked) {
        ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
        return INVALID_OPERATION;
    }
    size_t extraEntries = get_camera_metadata_entry_count(other);
    size_t extraData = get_camera_metadata_data_count(other);
    resizeIfNeeded(extraEntries, extraData);

    return append_camera_metadata(mBuffer, other);
}
status_t CameraMetadata::resizeIfNeeded(size_t extraEntries, size_t extraData) {
    if (mBuffer == NULL) {
        mBuffer = allocate_camera_metadata(extraEntries * 2, extraData * 2);
        if (mBuffer == NULL) {
            ALOGE("%s: Can't allocate larger metadata buffer", __FUNCTION__);
            return NO_MEMORY;
        }
    } else {
        size_t currentEntryCount = get_camera_metadata_entry_count(mBuffer);
        size_t currentEntryCap = get_camera_metadata_entry_capacity(mBuffer);
        size_t newEntryCount = currentEntryCount +
                extraEntries;
        newEntryCount = (newEntryCount > currentEntryCap) ?
                newEntryCount * 2 : currentEntryCap;

        size_t currentDataCount = get_camera_metadata_data_count(mBuffer);
        size_t currentDataCap = get_camera_metadata_data_capacity(mBuffer);
        size_t newDataCount = currentDataCount +
                extraData;
        newDataCount = (newDataCount > currentDataCap) ?
                newDataCount * 2 : currentDataCap;

        if (newEntryCount > currentEntryCap ||
                newDataCount > currentDataCap) {
            camera_metadata_t *oldBuffer = mBuffer;
            mBuffer = allocate_camera_metadata(newEntryCount,
                    newDataCount);
            if (mBuffer == NULL) {
                ALOGE("%s: Can't allocate larger metadata buffer", __FUNCTION__);
                return NO_MEMORY;
            }
            append_camera_metadata(mBuffer, oldBuffer);
            free_camera_metadata(oldBuffer);
        }
    }
    return OK;
}
size_t CameraMetadata::entryCount() const {
    return (mBuffer == NULL) ? 0 :
            get_camera_metadata_entry_count(mBuffer);
}
void dumpMetadata(const camera_metadata_t * meta)
{
    if (!meta)
        return;
    if ((gLogLevel & CAMERA_DEBUG_LOG_LEVEL2) != CAMERA_DEBUG_LOG_LEVEL2)
        return;

    int entryCount = get_camera_metadata_entry_count(meta);

    for (int i = 0; i < entryCount; i++) {
        camera_metadata_entry_t entry;
        if (get_camera_metadata_entry((camera_metadata_t *)meta, i, &entry)) {
            continue;
        }

        // Print tag & type
        const char *tagName, *tagSection;
        tagSection = get_camera_metadata_section_name(entry.tag);
        if (tagSection == NULL) {
            tagSection = "unknownSection";
        }
        tagName = get_camera_metadata_tag_name(entry.tag);
        if (tagName == NULL) {
            tagName = "unknownTag";
        }
        const char *typeName;
        if (entry.type >= NUM_TYPES) {
            typeName = "unknown";
        } else {
            typeName = camera_metadata_type_names[entry.type];
        }
        LOG2("(%d)%s.%s (%05x): %s[%d], type: %d\n",
             i,
             tagSection,
             tagName,
             entry.tag,
             typeName,
             entry.count,
             entry.type);

        // Print data
#define MAX_DATA_COUNT 512
        size_t j;
        int length = 0;
        char str[64 + 8 * (MAX_DATA_COUNT)] = {0};
        const uint8_t *u8;
        const int32_t *i32;
        const float   *f;
        const int64_t *i64;
        const double  *d;
        const camera_metadata_rational_t *r;
        length = sprintf(str+length,"[");
        if (length < 0) {
            LOGW("%s sprintf failed at %d", __FUNCTION__, __LINE__);
            return;
        }
        switch (entry.type) {
        case TYPE_BYTE:
            u8 = entry.data.u8;
            for (j = 0; j < entry.count; j++) {
                length += sprintf(str+length, "%d ", u8[j]);
            }
            break;
        case TYPE_INT32:
            i32 = entry.data.i32;
            for (j = 0; j < entry.count; j++)
                length += sprintf(str+length, " %d ", i32[j]);
            break;
        case TYPE_FLOAT:
            f = entry.data.f;
            for (j = 0; j < entry.count; j++)
                length += sprintf(str+length, " %0.2f ", f[j]);
            break;
        case TYPE_INT64:
            i64 = entry.data.i64;
            for (j = 0; j < entry.count; j++)
                length += sprintf(str+length, " %lld ", i64[j]);
            break;
        case TYPE_DOUBLE:
            d = entry.data.d;
            for (j = 0; j < entry.count; j++)
                length += sprintf(str+length, " %0.2f ", d[j]);
            break;
        case TYPE_RATIONAL:
            r = entry.data.r;
            for (j = 0; j < entry.count; j++)
                length += sprintf(str+length, " (%d, %d) ", r[j].numerator, r[j].denominator);
            break;
        }
        if (length < 0) {
            LOGW("%s sprintf failed at %d", __FUNCTION__, __LINE__);
            return;
        }
        length += sprintf(str+length, "]");
        LOG2("%s", str);
    }

}