status_t CameraMetadata::erase(uint32_t tag) {
    camera_metadata_entry_t entry;
    status_t res;
    if (mLocked) {
        ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
        return INVALID_OPERATION;
    }
    res = find_camera_metadata_entry(mBuffer, tag, &entry);
    if (res == NAME_NOT_FOUND) {
        return OK;
    } else if (res != OK) {
        ALOGE("%s: Error looking for entry %s.%s (%x): %s %d",
                __FUNCTION__,
                get_camera_metadata_section_name(tag),
                get_camera_metadata_tag_name(tag), tag, strerror(-res), res);
        return res;
    }
    res = delete_camera_metadata_entry(mBuffer, entry.index);
    if (res != OK) {
        ALOGE("%s: Error deleting entry %s.%s (%x): %s %d",
                __FUNCTION__,
                get_camera_metadata_section_name(tag),
                get_camera_metadata_tag_name(tag), tag, strerror(-res), res);
    }
    return res;
}
status_t CameraMetadata::update(uint32_t tag, const void *data,
        size_t data_count) {
    status_t res;
    int type = get_camera_metadata_tag_type(tag);
    if (type == -1) {
        ALOGE("%s: Tag %d not found", __FUNCTION__, tag);
        return BAD_VALUE;
    }
    size_t data_size = calculate_camera_metadata_entry_data_size(type,
            data_count);

    res = resizeIfNeeded(1, data_size);

    if (res == OK) {
        camera_metadata_entry_t entry;
        res = find_camera_metadata_entry(mBuffer, tag, &entry);
        if (res == NAME_NOT_FOUND) {
            res = add_camera_metadata_entry(mBuffer,
                    tag, data, data_count);
        } else if (res == OK) {
            res = update_camera_metadata_entry(mBuffer,
                    entry.index, data, data_count, NULL);
        }
    }

    if (res != OK) {
        ALOGE("%s: Unable to update metadata entry %s.%s (%x): %s (%d)",
                __FUNCTION__, get_camera_metadata_section_name(tag),
                get_camera_metadata_tag_name(tag), tag, strerror(-res), res);
    }
    return res;
}
bool FrameProcessor::get3aResult(const CameraMetadata& result, int32_t tag,
        T* value, int32_t frameNumber, int cameraId) {
    camera_metadata_ro_entry_t entry;
    if (value == NULL) {
        ALOGE("%s: Camera %d: Value to write to is NULL",
                __FUNCTION__, cameraId);
        return false;
    }

    entry = result.find(tag);
    if (entry.count == 0) {
        ALOGE("%s: Camera %d: No %s provided by HAL for frame %d!",
                __FUNCTION__, cameraId,
                get_camera_metadata_tag_name(tag), frameNumber);
        return false;
    } else {
        switch(sizeof(Src)){
            case sizeof(uint8_t):
                *value = static_cast<T>(entry.data.u8[0]);
                break;
            case sizeof(int32_t):
                *value = static_cast<T>(entry.data.i32[0]);
                break;
            default:
                ALOGE("%s: Camera %d: Unsupported source",
                        __FUNCTION__, cameraId);
                return false;
        }
    }
    return true;
}
status_t CameraMetadata::updateImpl(uint32_t tag, const void *data,
        size_t data_count) {
    status_t res;
    if (mLocked) {
        ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
        return INVALID_OPERATION;
    }
    int type = get_camera_metadata_tag_type(tag);
    if (type == -1) {
        ALOGE("%s: Tag %d not found", __FUNCTION__, tag);
        return BAD_VALUE;
    }
    // Safety check - ensure that data isn't pointing to this metadata, since
    // that would get invalidated if a resize is needed
    size_t bufferSize = get_camera_metadata_size(mBuffer);
    uintptr_t bufAddr = reinterpret_cast<uintptr_t>(mBuffer);
    uintptr_t dataAddr = reinterpret_cast<uintptr_t>(data);
    if (dataAddr > bufAddr && dataAddr < (bufAddr + bufferSize)) {
        ALOGE("%s: Update attempted with data from the same metadata buffer!",
                __FUNCTION__);
        return INVALID_OPERATION;
    }

    size_t data_size = calculate_camera_metadata_entry_data_size(type,
            data_count);

    res = resizeIfNeeded(1, data_size);

    if (res == OK) {
        camera_metadata_entry_t entry;
        res = find_camera_metadata_entry(mBuffer, tag, &entry);
        if (res == NAME_NOT_FOUND) {
            res = add_camera_metadata_entry(mBuffer,
                    tag, data, data_count);
        } else if (res == OK) {
            res = update_camera_metadata_entry(mBuffer,
                    entry.index, data, data_count, NULL);
        }
    }

    if (res != OK) {
        ALOGE("%s: Unable to update metadata entry %s.%s (%x): %s (%d)",
                __FUNCTION__, get_camera_metadata_section_name(tag),
                get_camera_metadata_tag_name(tag), tag, strerror(-res), res);
    }

    IF_ALOGV() {
        ALOGE_IF(validate_camera_metadata_structure(mBuffer, /*size*/NULL) !=
                 OK,

                 "%s: Failed to validate metadata structure after update %p",
                 __FUNCTION__, mBuffer);
    }

    return res;
}
const void * getMetadataValues(const camera_metadata_t * metadata, uint32_t tag, int type, int * count)
{
    status_t res = NO_ERROR;
    camera_metadata_ro_entry entry;
    res = find_camera_metadata_ro_entry(metadata, tag, &entry);
    if (res != OK) {
        LOGE("Failed to find %s.%s",
            get_camera_metadata_section_name(tag),
            get_camera_metadata_tag_name(tag));
        return NULL;
    }
    if (entry.type != type) {
        LOGE("Bad type %d for tag %s.%s! Should be %d",
            type,
            get_camera_metadata_section_name(tag),
            get_camera_metadata_tag_name(tag),
            entry.type);
        return NULL;
    }
    if (count)
        * count = entry.count;

    return entry.data.u8;
}
const void * getMetadataValues(const CameraMetadata &metadata, uint32_t tag, int type, int * count)
{
    camera_metadata_ro_entry entry = metadata.find(tag);
    if (entry.type != type) {
        LOGE("Bad type %d for tag %s.%s! Should be %d",
            type,
            get_camera_metadata_section_name(tag),
            get_camera_metadata_tag_name(tag),
            entry.type);
        return NULL;
    }
    if (count)
        * count = entry.count;
    return entry.data.u8;
}
status_t CameraMetadata::checkType(uint32_t tag, uint8_t expectedType) {
    int tagType = get_camera_metadata_tag_type(tag);
    if ( CC_UNLIKELY(tagType == -1)) {
        ALOGE("Update metadata entry: Unknown tag %d", tag);
        return INVALID_OPERATION;
    }
    if ( CC_UNLIKELY(tagType != expectedType) ) {
        ALOGE("Mismatched tag type when updating entry %s (%d) of type %s; "
                "got type %s data instead ",
                get_camera_metadata_tag_name(tag), tag,
                camera_metadata_type_names[tagType],
                camera_metadata_type_names[expectedType]);
        return INVALID_OPERATION;
    }
    return OK;
}
status_t CameraMetadata::updateImpl(uint32_t tag, const void *data,
        size_t data_count) {
    status_t res;
    if (mLocked) {
        ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
        return INVALID_OPERATION;
    }
    int type = get_camera_metadata_tag_type(tag);
    if (type == -1) {
        ALOGE("%s: Tag %d not found", __FUNCTION__, tag);
        return BAD_VALUE;
    }
    size_t data_size = calculate_camera_metadata_entry_data_size(type,
            data_count);

    res = resizeIfNeeded(1, data_size);

    if (res == OK) {
        camera_metadata_entry_t entry;
        res = find_camera_metadata_entry(mBuffer, tag, &entry);
        if (res == NAME_NOT_FOUND) {
            res = add_camera_metadata_entry(mBuffer,
                    tag, data, data_count);
        } else if (res == OK) {
            res = update_camera_metadata_entry(mBuffer,
                    entry.index, data, data_count, NULL);
        }
    }

    if (res != OK) {
        ALOGE("%s: Unable to update metadata entry %s.%s (%x): %s (%d)",
                __FUNCTION__, get_camera_metadata_section_name(tag),
                get_camera_metadata_tag_name(tag), tag, strerror(-res), res);
    }

    IF_ALOGV() {
        ALOGE_IF(validate_camera_metadata_structure(mBuffer, /*size*/NULL) !=
                 OK,

                 "%s: Failed to validate metadata structure after update %p",
                 __FUNCTION__, mBuffer);
    }

    return res;
}
status_t CameraMetadata::getTagFromName(const char *name,
        const VendorTagDescriptor* vTags, uint32_t *tag) {

    if (name == nullptr || tag == nullptr) return BAD_VALUE;

    size_t nameLength = strlen(name);

    const SortedVector<String8> *vendorSections;
    size_t vendorSectionCount = 0;

    if (vTags != NULL) {
        vendorSections = vTags->getAllSectionNames();
        vendorSectionCount = vendorSections->size();
    }

    // First, find the section by the longest string match
    const char *section = NULL;
    size_t sectionIndex = 0;
    size_t sectionLength = 0;
    size_t totalSectionCount = ANDROID_SECTION_COUNT + vendorSectionCount;
    for (size_t i = 0; i < totalSectionCount; ++i) {

        const char *str = (i < ANDROID_SECTION_COUNT) ? camera_metadata_section_names[i] :
                (*vendorSections)[i - ANDROID_SECTION_COUNT].string();

        ALOGV("%s: Trying to match against section '%s'", __FUNCTION__, str);

        if (strstr(name, str) == name) { // name begins with the section name
            size_t strLength = strlen(str);

            ALOGV("%s: Name begins with section name", __FUNCTION__);

            // section name is the longest we've found so far
            if (section == NULL || sectionLength < strLength) {
                section = str;
                sectionIndex = i;
                sectionLength = strLength;

                ALOGV("%s: Found new best section (%s)", __FUNCTION__, section);
            }
        }
    }

    // TODO: Make above get_camera_metadata_section_from_name ?

    if (section == NULL) {
        return NAME_NOT_FOUND;
    } else {
        ALOGV("%s: Found matched section '%s' (%zu)",
              __FUNCTION__, section, sectionIndex);
    }

    // Get the tag name component of the name
    const char *nameTagName = name + sectionLength + 1; // x.y.z -> z
    if (sectionLength + 1 >= nameLength) {
        return BAD_VALUE;
    }

    // Match rest of name against the tag names in that section only
    uint32_t candidateTag = 0;
    if (sectionIndex < ANDROID_SECTION_COUNT) {
        // Match built-in tags (typically android.*)
        uint32_t tagBegin, tagEnd; // [tagBegin, tagEnd)
        tagBegin = camera_metadata_section_bounds[sectionIndex][0];
        tagEnd = camera_metadata_section_bounds[sectionIndex][1];

        for (candidateTag = tagBegin; candidateTag < tagEnd; ++candidateTag) {
            const char *tagName = get_camera_metadata_tag_name(candidateTag);

            if (strcmp(nameTagName, tagName) == 0) {
                ALOGV("%s: Found matched tag '%s' (%d)",
                      __FUNCTION__, tagName, candidateTag);
                break;
            }
        }

        if (candidateTag == tagEnd) {
            return NAME_NOT_FOUND;
        }
    } else if (vTags != NULL) {
        // Match vendor tags (typically com.*)
        const String8 sectionName(section);
        const String8 tagName(nameTagName);

        status_t res = OK;
        if ((res = vTags->lookupTag(tagName, sectionName, &candidateTag)) != OK) {
            return NAME_NOT_FOUND;
        }
    }

    *tag = candidateTag;
    return OK;
}
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);
    }

}