Camera2: Dump enum data types as strings, not integers

Change-Id: Ia225662d4ee0aad81b22b96355d7f39c4aa70d42
diff --git a/camera/docs/camera_metadata_tag_info.mako b/camera/docs/camera_metadata_tag_info.mako
index bceadc1..26ba619 100644
--- a/camera/docs/camera_metadata_tag_info.mako
+++ b/camera/docs/camera_metadata_tag_info.mako
@@ -101,3 +101,9 @@
     return ret;
 }
 
+<%
+  find_values = lambda x: isinstance(x, metadata_model.EnumValue)
+  enum_values = metadata.find_all(find_values)
+  enum_value_max_len = max([len(value.name) for value in enum_values]) + 1
+%>
+#define CAMERA_METADATA_ENUM_STRING_MAX_SIZE ${enum_value_max_len}
diff --git a/camera/docs/metadata_model.py b/camera/docs/metadata_model.py
index e91fcd1..b403a47 100644
--- a/camera/docs/metadata_model.py
+++ b/camera/docs/metadata_model.py
@@ -720,7 +720,7 @@
     for i in self.entries:
       yield i
 
-class EnumValue(object):
+class EnumValue(Node):
   """
   A class corresponding to a <value> element within an <enum> within an <entry>.
 
@@ -729,16 +729,14 @@
     id: An optional numeric string, e.g. '0' or '0xFF'
     optional: A boolean
     notes: A string describing the notes, or None.
+    parent: An edge to the parent, always an Enum instance.
   """
-  def __init__(self, name, id=None, optional=False, notes=None):
+  def __init__(self, name, parent, id=None, optional=False, notes=None):
     self._name = name                    # str, e.g. 'ON' or 'OFF'
     self._id = id                        # int, e.g. '0'
     self._optional = optional            # bool
     self._notes = notes                  # None or str
-
-  @property
-  def name(self):
-    return self._name
+    self._parent = parent
 
   @property
   def id(self):
@@ -752,7 +750,10 @@
   def notes(self):
     return self._notes
 
-class Enum(object):
+  def _get_children(self):
+    return None
+
+class Enum(Node):
   """
   A class corresponding to an <enum> element within an <entry>.
 
@@ -762,19 +763,19 @@
   """
   def __init__(self, parent, values, ids={}, optionals=[], notes={}):
     self._values =                                                             \
-      [ EnumValue(val, ids.get(val), val in optionals, notes.get(val))         \
+      [ EnumValue(val, self, ids.get(val), val in optionals, notes.get(val))   \
         for val in values ]
 
     self._parent = parent
-
-  @property
-  def parent(self):
-    return self._parent
+    self._name = None
 
   @property
   def values(self):
     return (i for i in self._values)
 
+  def _get_children(self):
+    return (i for i in self._values)
+
 class Entry(Node):
   """
   A node corresponding to an <entry> element.
@@ -910,7 +911,8 @@
     return self._enum
 
   def _get_children(self):
-    return None
+    if self.enum:
+      yield self.enum
 
   def sort_children(self):
     return None
diff --git a/camera/src/camera_metadata.c b/camera/src/camera_metadata.c
index e5c2f25..1963b89 100644
--- a/camera/src/camera_metadata.c
+++ b/camera/src/camera_metadata.c
@@ -640,7 +640,8 @@
     return OK;
 }
 
-static void print_data(int fd, const uint8_t *data_ptr, int type, int count,
+static void print_data(int fd, const uint8_t *data_ptr, uint32_t tag, int type,
+        int count,
         int indentation);
 
 void dump_camera_metadata(const camera_metadata_t *metadata,
@@ -714,11 +715,11 @@
         int count = entry->count;
         if (verbosity < 2 && count > 16) count = 16;
 
-        print_data(fd, data_ptr, entry->type, count, indentation);
+        print_data(fd, data_ptr, entry->tag, entry->type, count, indentation);
     }
 }
 
-static void print_data(int fd, const uint8_t *data_ptr,
+static void print_data(int fd, const uint8_t *data_ptr, uint32_t tag,
         int type, int count, int indentation) {
     static int values_per_line[NUM_TYPES] = {
         [TYPE_BYTE]     = 16,
@@ -729,6 +730,8 @@
         [TYPE_RATIONAL] = 2,
     };
     size_t type_size = camera_metadata_type_size[type];
+    char value_string_tmp[CAMERA_METADATA_ENUM_STRING_MAX_SIZE];
+    uint32_t value;
 
     int lines = count / values_per_line[type];
     if (count % values_per_line[type] != 0) lines++;
@@ -743,12 +746,31 @@
 
             switch (type) {
                 case TYPE_BYTE:
-                    fdprintf(fd, "%hhu ",
-                            *(data_ptr + index));
+                    value = *(data_ptr + index);
+                    if (camera_metadata_enum_snprint(tag,
+                                                     value,
+                                                     value_string_tmp,
+                                                     sizeof(value_string_tmp))
+                        == OK) {
+                        fdprintf(fd, "%s ", value_string_tmp);
+                    } else {
+                        fdprintf(fd, "%hhu ",
+                                *(data_ptr + index));
+                    }
                     break;
                 case TYPE_INT32:
-                    fdprintf(fd, "%d ",
-                            *(int32_t*)(data_ptr + index));
+                    value =
+                            *(int32_t*)(data_ptr + index);
+                    if (camera_metadata_enum_snprint(tag,
+                                                     value,
+                                                     value_string_tmp,
+                                                     sizeof(value_string_tmp))
+                        == OK) {
+                        fdprintf(fd, "%s ", value_string_tmp);
+                    } else {
+                        fdprintf(fd, "%d ",
+                                *(int32_t*)(data_ptr + index));
+                    }
                     break;
                 case TYPE_FLOAT:
                     fdprintf(fd, "%0.2f ",
diff --git a/camera/src/camera_metadata_tag_info.c b/camera/src/camera_metadata_tag_info.c
index b32fd10..5eee140 100644
--- a/camera/src/camera_metadata_tag_info.c
+++ b/camera/src/camera_metadata_tag_info.c
@@ -1775,3 +1775,5 @@
 }
 
 
+#define CAMERA_METADATA_ENUM_STRING_MAX_SIZE 23
+