OSDN Git Service

Merge commit 'f9e3022c474619c69a46ae7dbe11b5b531dbad57' into am-0d58d39a-0539-474e...
[android-x86/system-media.git] / camera / src / camera_metadata.c
index 70074c8..f33da8d 100644 (file)
  * limitations under the License.
  */
 
-#include <inttypes.h>
+#define LOG_TAG "camera_metadata"
+
 #include <system/camera_metadata.h>
 #include <camera_metadata_hidden.h>
 
-#define LOG_TAG "camera_metadata"
-#include <cutils/log.h>
 #include <assert.h>
+#include <errno.h>
+#include <inttypes.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <errno.h>
+
+#include <log/log.h>
 
 #define OK              0
 #define ERROR           1
-#define NOT_FOUND       -ENOENT
+#define NOT_FOUND       (-ENOENT)
 #define SN_EVENT_LOG_ID 0x534e4554
 
 #define ALIGN_TO(val, alignment) \
@@ -99,7 +101,8 @@ struct camera_metadata {
     metadata_size_t          data_count;
     metadata_size_t          data_capacity;
     metadata_uptrdiff_t      data_start; // Offset from camera_metadata
-    uint8_t                  reserved[];
+    uint32_t                 padding;    // padding to 8 bytes boundary
+    metadata_vendor_id_t     vendor_id;
 };
 
 /**
@@ -118,6 +121,49 @@ typedef union camera_metadata_data {
     camera_metadata_rational_t r;
 } camera_metadata_data_t;
 
+_Static_assert(sizeof(metadata_size_t) == 4,
+         "Size of metadata_size_t must be 4");
+_Static_assert(sizeof(metadata_uptrdiff_t) == 4,
+         "Size of metadata_uptrdiff_t must be 4");
+_Static_assert(sizeof(metadata_vendor_id_t) == 8,
+         "Size of metadata_vendor_id_t must be 8");
+_Static_assert(sizeof(camera_metadata_data_t) == 8,
+         "Size of camera_metadata_data_t must be 8");
+
+_Static_assert(offsetof(camera_metadata_buffer_entry_t, tag) == 0,
+         "Offset of tag must be 0");
+_Static_assert(offsetof(camera_metadata_buffer_entry_t, count) == 4,
+         "Offset of count must be 4");
+_Static_assert(offsetof(camera_metadata_buffer_entry_t, data) == 8,
+         "Offset of data must be 8");
+_Static_assert(offsetof(camera_metadata_buffer_entry_t, type) == 12,
+         "Offset of type must be 12");
+_Static_assert(sizeof(camera_metadata_buffer_entry_t) == 16,
+         "Size of camera_metadata_buffer_entry_t must be 16");
+
+_Static_assert(offsetof(camera_metadata_t, size) == 0,
+         "Offset of size must be 0");
+_Static_assert(offsetof(camera_metadata_t, version) == 4,
+         "Offset of version must be 4");
+_Static_assert(offsetof(camera_metadata_t, flags) == 8,
+         "Offset of flags must be 8");
+_Static_assert(offsetof(camera_metadata_t, entry_count) == 12,
+         "Offset of entry_count must be 12");
+_Static_assert(offsetof(camera_metadata_t, entry_capacity) == 16,
+         "Offset of entry_capacity must be 16");
+_Static_assert(offsetof(camera_metadata_t, entries_start) == 20,
+         "Offset of entries_start must be 20");
+_Static_assert(offsetof(camera_metadata_t, data_count) == 24,
+         "Offset of data_count must be 24");
+_Static_assert(offsetof(camera_metadata_t, data_capacity) == 28,
+         "Offset of data_capacity must be 28");
+_Static_assert(offsetof(camera_metadata_t, data_start) == 32,
+         "Offset of data_start must be 32");
+_Static_assert(offsetof(camera_metadata_t, vendor_id) == 40,
+         "Offset of vendor_id must be 40");
+_Static_assert(sizeof(camera_metadata_t) == 48,
+         "Size of camera_metadata_t must be 48");
+
 /**
  * The preferred alignment of a packet of camera metadata. In general,
  * this is the lowest common multiple of the constituents of a metadata
@@ -125,7 +171,7 @@ typedef union camera_metadata_data {
  */
 #define MAX_ALIGNMENT(A, B) (((A) > (B)) ? (A) : (B))
 #define METADATA_PACKET_ALIGNMENT \
-    MAX_ALIGNMENT(MAX_ALIGNMENT(DATA_ALIGNMENT, METADATA_ALIGNMENT), ENTRY_ALIGNMENT);
+    MAX_ALIGNMENT(MAX_ALIGNMENT(DATA_ALIGNMENT, METADATA_ALIGNMENT), ENTRY_ALIGNMENT)
 
 /** Versioning information */
 #define CURRENT_METADATA_VERSION 1
@@ -206,9 +252,15 @@ camera_metadata_t *allocate_camera_metadata(size_t entry_capacity,
     size_t memory_needed = calculate_camera_metadata_size(entry_capacity,
                                                           data_capacity);
     void *buffer = calloc(1, memory_needed);
-    return place_camera_metadata(buffer, memory_needed,
-                                 entry_capacity,
-                                 data_capacity);
+    camera_metadata_t *metadata = place_camera_metadata(
+        buffer, memory_needed, entry_capacity, data_capacity);
+    if (!metadata) {
+        /* This should not happen when memory_needed is the same
+         * calculated in this function and in place_camera_metadata.
+         */
+        free(buffer);
+    }
+    return metadata;
 }
 
 camera_metadata_t *place_camera_metadata(void *dst,
@@ -234,6 +286,7 @@ camera_metadata_t *place_camera_metadata(void *dst,
     size_t data_unaligned = (uint8_t*)(get_entries(metadata) +
             metadata->entry_capacity) - (uint8_t*)metadata;
     metadata->data_start = ALIGN_TO(data_unaligned, DATA_ALIGNMENT);
+    metadata->vendor_id = CAMERA_METADATA_INVALID_VENDOR_ID;
 
     assert(validate_camera_metadata_structure(metadata, NULL) == OK);
     return metadata;
@@ -251,6 +304,8 @@ size_t calculate_camera_metadata_size(size_t entry_count,
     // Start buffer list at aligned boundary
     memory_needed = ALIGN_TO(memory_needed, DATA_ALIGNMENT);
     memory_needed += sizeof(uint8_t[data_count]);
+    // Make sure camera metadata can be stacked in continuous memory
+    memory_needed = ALIGN_TO(memory_needed, METADATA_PACKET_ALIGNMENT);
     return memory_needed;
 }
 
@@ -296,6 +351,7 @@ camera_metadata_t* copy_camera_metadata(void *dst, size_t dst_size,
     metadata->flags = src->flags;
     metadata->entry_count = src->entry_count;
     metadata->data_count = src->data_count;
+    metadata->vendor_id = src->vendor_id;
 
     memcpy(get_entries(metadata), get_entries(src),
             sizeof(camera_metadata_buffer_entry_t[metadata->entry_count]));
@@ -343,9 +399,12 @@ int validate_camera_metadata_structure(const camera_metadata_t *metadata,
 
     if (metadata == NULL) {
         ALOGE("%s: metadata is null!", __FUNCTION__);
-        return ERROR;
+        return CAMERA_METADATA_VALIDATION_ERROR;
     }
 
+    uintptr_t aligned_ptr = ALIGN_TO(metadata, METADATA_PACKET_ALIGNMENT);
+    const uintptr_t alignmentOffset = aligned_ptr - (uintptr_t) metadata;
+
     // Check that the metadata pointer is well-aligned first.
     {
         static const struct {
@@ -367,14 +426,15 @@ int validate_camera_metadata_structure(const camera_metadata_t *metadata,
         };
 
         for (size_t i = 0; i < sizeof(alignments)/sizeof(alignments[0]); ++i) {
-            uintptr_t aligned_ptr = ALIGN_TO(metadata, alignments[i].alignment);
+            uintptr_t aligned_ptr = ALIGN_TO((uintptr_t) metadata + alignmentOffset,
+                    alignments[i].alignment);
 
-            if ((uintptr_t)metadata != aligned_ptr) {
+            if ((uintptr_t)metadata + alignmentOffset != aligned_ptr) {
                 ALOGE("%s: Metadata pointer is not aligned (actual %p, "
-                      "expected %p) to type %s",
+                      "expected %p, offset %" PRIuPTR ") to type %s",
                       __FUNCTION__, metadata,
-                      (void*)aligned_ptr, alignments[i].name);
-                return ERROR;
+                      (void*)aligned_ptr, alignmentOffset, alignments[i].name);
+                return CAMERA_METADATA_VALIDATION_ERROR;
             }
         }
     }
@@ -386,14 +446,14 @@ int validate_camera_metadata_structure(const camera_metadata_t *metadata,
     if (expected_size != NULL && metadata->size > *expected_size) {
         ALOGE("%s: Metadata size (%" PRIu32 ") should be <= expected size (%zu)",
               __FUNCTION__, metadata->size, *expected_size);
-        return ERROR;
+        return CAMERA_METADATA_VALIDATION_ERROR;
     }
 
     if (metadata->entry_count > metadata->entry_capacity) {
         ALOGE("%s: Entry count (%" PRIu32 ") should be <= entry capacity "
               "(%" PRIu32 ")",
               __FUNCTION__, metadata->entry_count, metadata->entry_capacity);
-        return ERROR;
+        return CAMERA_METADATA_VALIDATION_ERROR;
     }
 
     if (metadata->data_count > metadata->data_capacity) {
@@ -401,7 +461,7 @@ int validate_camera_metadata_structure(const camera_metadata_t *metadata,
               "(%" PRIu32 ")",
               __FUNCTION__, metadata->data_count, metadata->data_capacity);
         android_errorWriteLog(SN_EVENT_LOG_ID, "30591838");
-        return ERROR;
+        return CAMERA_METADATA_VALIDATION_ERROR;
     }
 
     const metadata_uptrdiff_t entries_end =
@@ -414,7 +474,7 @@ int validate_camera_metadata_structure(const camera_metadata_t *metadata,
                __FUNCTION__,
               (metadata->entries_start + metadata->entry_capacity),
               metadata->data_start);
-        return ERROR;
+        return CAMERA_METADATA_VALIDATION_ERROR;
     }
 
     const metadata_uptrdiff_t data_end =
@@ -427,7 +487,7 @@ int validate_camera_metadata_structure(const camera_metadata_t *metadata,
                __FUNCTION__,
               (metadata->data_start + metadata->data_capacity),
               metadata->size);
-        return ERROR;
+        return CAMERA_METADATA_VALIDATION_ERROR;
     }
 
     // Validate each entry
@@ -436,11 +496,12 @@ int validate_camera_metadata_structure(const camera_metadata_t *metadata,
 
     for (size_t i = 0; i < entry_count; ++i) {
 
-        if ((uintptr_t)&entries[i] != ALIGN_TO(&entries[i], ENTRY_ALIGNMENT)) {
+        if ((uintptr_t)&entries[i] + alignmentOffset !=
+                ALIGN_TO((uintptr_t)&entries[i] + alignmentOffset, ENTRY_ALIGNMENT)) {
             ALOGE("%s: Entry index %zu had bad alignment (address %p),"
                   " expected alignment %zu",
                   __FUNCTION__, i, &entries[i], ENTRY_ALIGNMENT);
-            return ERROR;
+            return CAMERA_METADATA_VALIDATION_ERROR;
         }
 
         camera_metadata_buffer_entry_t entry = entries[i];
@@ -448,17 +509,17 @@ int validate_camera_metadata_structure(const camera_metadata_t *metadata,
         if (entry.type >= NUM_TYPES) {
             ALOGE("%s: Entry index %zu had a bad type %d",
                   __FUNCTION__, i, entry.type);
-            return ERROR;
+            return CAMERA_METADATA_VALIDATION_ERROR;
         }
 
         // TODO: fix vendor_tag_ops across processes so we don't need to special
         //       case vendor-specific tags
         uint32_t tag_section = entry.tag >> 16;
-        int tag_type = get_camera_metadata_tag_type(entry.tag);
+        int tag_type = get_local_camera_metadata_tag_type(entry.tag, metadata);
         if (tag_type != (int)entry.type && tag_section < VENDOR_SECTION) {
             ALOGE("%s: Entry index %zu had tag type %d, but the type was %d",
                   __FUNCTION__, i, tag_type, entry.type);
-            return ERROR;
+            return CAMERA_METADATA_VALIDATION_ERROR;
         }
 
         size_t data_size;
@@ -466,7 +527,7 @@ int validate_camera_metadata_structure(const camera_metadata_t *metadata,
                 entry.count) != OK) {
             ALOGE("%s: Entry data size is invalid. type: %u count: %u", __FUNCTION__, entry.type,
                     entry.count);
-            return ERROR;
+            return CAMERA_METADATA_VALIDATION_ERROR;
         }
 
         if (data_size != 0) {
@@ -474,13 +535,14 @@ int validate_camera_metadata_structure(const camera_metadata_t *metadata,
                     (camera_metadata_data_t*) (get_data(metadata) +
                                                entry.data.offset);
 
-            if ((uintptr_t)data != ALIGN_TO(data, DATA_ALIGNMENT)) {
+            if ((uintptr_t)data + alignmentOffset !=
+                        ALIGN_TO((uintptr_t)data + alignmentOffset, DATA_ALIGNMENT)) {
                 ALOGE("%s: Entry index %zu had bad data alignment (address %p),"
                       " expected align %zu, (tag name %s, data size %zu)",
                       __FUNCTION__, i, data, DATA_ALIGNMENT,
-                      get_camera_metadata_tag_name(entry.tag) ?: "unknown",
-                      data_size);
-                return ERROR;
+                      get_local_camera_metadata_tag_name(entry.tag, metadata) ?
+                              : "unknown", data_size);
+                return CAMERA_METADATA_VALIDATION_ERROR;
             }
 
             size_t data_entry_end = entry.data.offset + data_size;
@@ -490,20 +552,23 @@ int validate_camera_metadata_structure(const camera_metadata_t *metadata,
                 ALOGE("%s: Entry index %zu data ends (%zu) beyond the capacity "
                       "%" PRIu32, __FUNCTION__, i, data_entry_end,
                       metadata->data_capacity);
-                return ERROR;
+                return CAMERA_METADATA_VALIDATION_ERROR;
             }
 
         } else if (entry.count == 0) {
             if (entry.data.offset != 0) {
                 ALOGE("%s: Entry index %zu had 0 items, but offset was non-0 "
                      "(%" PRIu32 "), tag name: %s", __FUNCTION__, i, entry.data.offset,
-                        get_camera_metadata_tag_name(entry.tag) ?: "unknown");
-                return ERROR;
+                        get_local_camera_metadata_tag_name(entry.tag, metadata) ? : "unknown");
+                return CAMERA_METADATA_VALIDATION_ERROR;
             }
         } // else data stored inline, so we look at value which can be anything.
     }
 
-    return OK;
+    if (alignmentOffset == 0) {
+        return OK;
+    }
+    return CAMERA_METADATA_VALIDATION_SHIFTED;
 }
 
 int append_camera_metadata(camera_metadata_t *dst,
@@ -517,6 +582,15 @@ int append_camera_metadata(camera_metadata_t *dst,
     if (dst->entry_capacity < src->entry_count + dst->entry_count) return ERROR;
     if (dst->data_capacity < src->data_count + dst->data_count) return ERROR;
 
+    if ((dst->vendor_id != CAMERA_METADATA_INVALID_VENDOR_ID) &&
+            (src->vendor_id != CAMERA_METADATA_INVALID_VENDOR_ID)) {
+        if (dst->vendor_id != src->vendor_id) {
+            ALOGE("%s: Append for metadata from different vendors is"
+                    "not supported!", __func__);
+            return ERROR;
+        }
+    }
+
     memcpy(get_entries(dst) + dst->entry_count, get_entries(src),
             sizeof(camera_metadata_buffer_entry_t[src->entry_count]));
     memcpy(get_data(dst) + dst->data_count, get_data(src),
@@ -542,6 +616,10 @@ int append_camera_metadata(camera_metadata_t *dst,
     dst->entry_count += src->entry_count;
     dst->data_count += src->data_count;
 
+    if (dst->vendor_id == CAMERA_METADATA_INVALID_VENDOR_ID) {
+        dst->vendor_id = src->vendor_id;
+    }
+
     assert(validate_camera_metadata_structure(dst, NULL) == OK);
     return OK;
 }
@@ -605,7 +683,7 @@ int add_camera_metadata_entry(camera_metadata_t *dst,
         const void *data,
         size_t data_count) {
 
-    int type = get_camera_metadata_tag_type(tag);
+    int type = get_local_camera_metadata_tag_type(tag, dst);
     if (type == -1) {
         ALOGE("%s: Unknown tag %04x.", __FUNCTION__, tag);
         return ERROR;
@@ -824,10 +902,16 @@ int update_camera_metadata_entry(camera_metadata_t *dst,
 }
 
 static const vendor_tag_ops_t *vendor_tag_ops = NULL;
+static const struct vendor_tag_cache_ops *vendor_cache_ops = NULL;
 
-const char *get_camera_metadata_section_name(uint32_t tag) {
+// Declared in system/media/private/camera/include/camera_metadata_hidden.h
+const char *get_local_camera_metadata_section_name_vendor_id(uint32_t tag,
+        metadata_vendor_id_t id) {
     uint32_t tag_section = tag >> 16;
-    if (tag_section >= VENDOR_SECTION && vendor_tag_ops != NULL) {
+    if (tag_section >= VENDOR_SECTION && vendor_cache_ops != NULL &&
+               id != CAMERA_METADATA_INVALID_VENDOR_ID) {
+           return vendor_cache_ops->get_section_name(tag, id);
+    } else if (tag_section >= VENDOR_SECTION && vendor_tag_ops != NULL) {
         return vendor_tag_ops->get_section_name(
             vendor_tag_ops,
             tag);
@@ -838,9 +922,14 @@ const char *get_camera_metadata_section_name(uint32_t tag) {
     return camera_metadata_section_names[tag_section];
 }
 
-const char *get_camera_metadata_tag_name(uint32_t tag) {
+// Declared in system/media/private/camera/include/camera_metadata_hidden.h
+const char *get_local_camera_metadata_tag_name_vendor_id(uint32_t tag,
+        metadata_vendor_id_t id) {
     uint32_t tag_section = tag >> 16;
-    if (tag_section >= VENDOR_SECTION && vendor_tag_ops != NULL) {
+    if (tag_section >= VENDOR_SECTION && vendor_cache_ops != NULL &&
+                id != CAMERA_METADATA_INVALID_VENDOR_ID) {
+            return vendor_cache_ops->get_tag_name(tag, id);
+    } else  if (tag_section >= VENDOR_SECTION && vendor_tag_ops != NULL) {
         return vendor_tag_ops->get_tag_name(
             vendor_tag_ops,
             tag);
@@ -853,9 +942,14 @@ const char *get_camera_metadata_tag_name(uint32_t tag) {
     return tag_info[tag_section][tag_index].tag_name;
 }
 
-int get_camera_metadata_tag_type(uint32_t tag) {
+// Declared in system/media/private/camera/include/camera_metadata_hidden.h
+int get_local_camera_metadata_tag_type_vendor_id(uint32_t tag,
+        metadata_vendor_id_t id) {
     uint32_t tag_section = tag >> 16;
-    if (tag_section >= VENDOR_SECTION && vendor_tag_ops != NULL) {
+    if (tag_section >= VENDOR_SECTION && vendor_cache_ops != NULL &&
+                id != CAMERA_METADATA_INVALID_VENDOR_ID) {
+            return vendor_cache_ops->get_tag_type(tag, id);
+    } else if (tag_section >= VENDOR_SECTION && vendor_tag_ops != NULL) {
         return vendor_tag_ops->get_tag_type(
             vendor_tag_ops,
             tag);
@@ -868,6 +962,42 @@ int get_camera_metadata_tag_type(uint32_t tag) {
     return tag_info[tag_section][tag_index].tag_type;
 }
 
+const char *get_camera_metadata_section_name(uint32_t tag) {
+    return get_local_camera_metadata_section_name(tag, NULL);
+}
+
+const char *get_camera_metadata_tag_name(uint32_t tag) {
+    return get_local_camera_metadata_tag_name(tag, NULL);
+}
+
+int get_camera_metadata_tag_type(uint32_t tag) {
+    return get_local_camera_metadata_tag_type(tag, NULL);
+}
+
+const char *get_local_camera_metadata_section_name(uint32_t tag,
+        const camera_metadata_t *meta) {
+    metadata_vendor_id_t id = (NULL == meta) ? CAMERA_METADATA_INVALID_VENDOR_ID :
+            meta->vendor_id;
+
+    return get_local_camera_metadata_section_name_vendor_id(tag, id);
+}
+
+const char *get_local_camera_metadata_tag_name(uint32_t tag,
+        const camera_metadata_t *meta) {
+    metadata_vendor_id_t id = (NULL == meta) ? CAMERA_METADATA_INVALID_VENDOR_ID :
+            meta->vendor_id;
+
+    return get_local_camera_metadata_tag_name_vendor_id(tag, id);
+}
+
+int get_local_camera_metadata_tag_type(uint32_t tag,
+        const camera_metadata_t *meta) {
+    metadata_vendor_id_t id = (NULL == meta) ? CAMERA_METADATA_INVALID_VENDOR_ID :
+            meta->vendor_id;
+
+    return get_local_camera_metadata_tag_type_vendor_id(tag, id);
+}
+
 int set_camera_metadata_vendor_tag_ops(const vendor_tag_query_ops_t* ops) {
     // **DEPRECATED**
     (void) ops;
@@ -881,6 +1011,33 @@ int set_camera_metadata_vendor_ops(const vendor_tag_ops_t* ops) {
     return OK;
 }
 
+// Declared in system/media/private/camera/include/camera_metadata_hidden.h
+int set_camera_metadata_vendor_cache_ops(
+        const struct vendor_tag_cache_ops *query_cache_ops) {
+    vendor_cache_ops = query_cache_ops;
+    return OK;
+}
+
+// Declared in system/media/private/camera/include/camera_metadata_hidden.h
+void set_camera_metadata_vendor_id(camera_metadata_t *meta,
+        metadata_vendor_id_t id) {
+    if (NULL != meta) {
+        meta->vendor_id = id;
+    }
+}
+
+// Declared in system/media/private/camera/include/camera_metadata_hidden.h
+metadata_vendor_id_t get_camera_metadata_vendor_id(
+        const camera_metadata_t *meta) {
+    metadata_vendor_id_t ret = CAMERA_METADATA_INVALID_VENDOR_ID;
+
+    if (NULL != meta) {
+        ret = meta->vendor_id;
+    }
+
+    return ret;
+}
+
 static void print_data(int fd, const uint8_t *data_ptr, uint32_t tag, int type,
         int count,
         int indentation);
@@ -913,11 +1070,11 @@ void dump_indented_camera_metadata(const camera_metadata_t *metadata,
     for (i=0; i < metadata->entry_count; i++, entry++) {
 
         const char *tag_name, *tag_section;
-        tag_section = get_camera_metadata_section_name(entry->tag);
+        tag_section = get_local_camera_metadata_section_name(entry->tag, metadata);
         if (tag_section == NULL) {
             tag_section = "unknownSection";
         }
-        tag_name = get_camera_metadata_tag_name(entry->tag);
+        tag_name = get_local_camera_metadata_tag_name(entry->tag, metadata);
         if (tag_name == NULL) {
             tag_name = "unknownTag";
         }