Camera: Update SDK metadata key/enum generation

- Flatten Key hierarchy
- Insert Keys into their respective containers instead of separate files
- Use ints instead of Enum types
- Insert enum ints into CameraMetadata
- Add @see cross-references between enum Keys and values.
- Add Javadoc to Keys and enum values.
- Map SCALER_AVAILABLE_FORMATS to int

Bug: 10345522
Change-Id: Ia9762b326b404c572de97c2c7814c4e2e0f3070d
diff --git a/camera/docs/.gitignore b/camera/docs/.gitignore
new file mode 100644
index 0000000..0d20b64
--- /dev/null
+++ b/camera/docs/.gitignore
@@ -0,0 +1 @@
+*.pyc
diff --git a/camera/docs/CameraMetadataEnums.mako b/camera/docs/CameraMetadataEnums.mako
new file mode 100644
index 0000000..831d61d
--- /dev/null
+++ b/camera/docs/CameraMetadataEnums.mako
@@ -0,0 +1,89 @@
+## -*- coding: utf-8 -*-
+##
+## Copyright (C) 2013 The Android Open Source Project
+##
+## Licensed under the Apache License, Version 2.0 (the "License");
+## you may not use this file except in compliance with the License.
+## You may obtain a copy of the License at
+##
+##      http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS,
+## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+## See the License for the specific language governing permissions and
+## limitations under the License.
+##
+\
+## This section of enum integer definitions is inserted into
+## android.hardware.camera2.CameraMetadata.
+    /*@O~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~
+     * The enum values below this point are generated from metadata
+     * definitions in /system/media/camera/docs. Do not modify by hand or
+     * modify the comment blocks at the start or end.
+     *~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~*/
+##
+## Generate an enum's integers
+<%def name="generate_enum(entry, target_class)">\
+    //
+    // Enumeration values for ${target_class}#${entry.name | jkey_identifier}
+    //
+
+  % for value in entry.enum.values:
+    /**
+    % if value.notes:
+${value.notes | javadoc}\
+    % endif
+     * @see ${target_class}#${entry.name | jkey_identifier}
+    % if entry.applied_visibility == 'hidden':
+     * @hide
+    %endif
+     */
+    public static final int ${jenum_value(entry, value)} = ${enum_calculate_value_string(value)};
+
+  % endfor
+</%def>\
+##
+## Generate a list of only Static, Controls, or Dynamic properties.
+<%def name="single_kind_keys(xml_name, target_class)">\
+% for outer_namespace in metadata.outer_namespaces: ## assumes single 'android' namespace
+  % for section in outer_namespace.sections:
+    % if section.find_first(lambda x: isinstance(x, metadata_model.Entry) and x.kind == xml_name) and \
+         any_visible(section, xml_name, ('public','hidden') ):
+      % for inner_namespace in get_children_by_filtering_kind(section, xml_name, 'namespaces'):
+## We only support 1 level of inner namespace, i.e. android.a.b and android.a.b.c works, but not android.a.b.c.d
+## If we need to support more, we should use a recursive function here instead.. but the indentation gets trickier.
+        % for entry in filter_visibility(inner_namespace.entries, ('hidden','public')):
+          % if entry.enum \
+              and not (entry.typedef and entry.typedef.languages.get('java')) \
+              and not entry.is_clone():
+${generate_enum(entry, target_class)}\
+          % endif
+        % endfor
+      % endfor
+      % for entry in filter_visibility( \
+          get_children_by_filtering_kind(section, xml_name, 'entries'), \
+                                         ('hidden', 'public')):
+        % if entry.enum \
+             and not (entry.typedef and entry.typedef.languages.get('java')) \
+             and not entry.is_clone():
+${generate_enum(entry, target_class)}\
+        % endif
+      % endfor
+    % endif
+  % endfor
+% endfor
+</%def>\
+
+##
+## Static properties only
+${single_kind_keys('static','CameraProperties')}\
+##
+## Controls properties only
+${single_kind_keys('controls','CaptureRequest')}\
+##
+## Dynamic properties only
+${single_kind_keys('dynamic','CaptureResult')}\
+    /*~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~
+     * End generated code
+     *~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~O@*/
diff --git a/camera/docs/CameraMetadataKeys.mako b/camera/docs/CameraMetadataKeys.mako
index 0ba54b3..a390431 100644
--- a/camera/docs/CameraMetadataKeys.mako
+++ b/camera/docs/CameraMetadataKeys.mako
@@ -1,148 +1,74 @@
 ## -*- coding: utf-8 -*-
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.hardware.camera2;
-
-import static android.hardware.camera2.CameraMetadata.Key;
-
-/**
- * ! Do not edit this file directly !
- *
- * Generated automatically from ${java_class}Keys.mako
- *
- * TODO: Include a hash of the input files here that the build can check.
- */
-
-<%page args="java_class, xml_kind" />\
-/**
- * The base class for camera controls and information.
- *
- * This class defines the basic key/value map used for querying for camera
- * characteristics or capture results, and for setting camera request
- * parameters.
- *
- * @see ${java_class}
- * @see CameraMetadata
- * @hide
- **/
 ##
-## Function to generate an enum
-<%def name="generate_enum(entry)">
-            % if entry.applied_visibility == 'hidden':
-            /**
-             * @hide
-             */
-            %endif
-            public static final class ${entry.get_name_minimal() | pascal_case}Key extends Key<${jtype_boxed(entry)}> {
-                public enum Enum {
-                  % for value,last in enumerate_with_last(entry.enum.values):
-                    ${value.name | jidentifier}${"," if not last else ";"}
-                  % endfor
-                }
+## Copyright (C) 2013 The Android Open Source Project
+##
+## Licensed under the Apache License, Version 2.0 (the "License");
+## you may not use this file except in compliance with the License.
+## You may obtain a copy of the License at
+##
+##      http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS,
+## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+## See the License for the specific language governing permissions and
+## limitations under the License.
+##
+\
+## These sections of metadata Key definitions are inserted into the middle of
+## android.hardware.camera2.CameraProperties, CaptureRequest, and CaptureResult.
+<%page args="java_class, xml_kind" />\
+    /*@O~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~
+     * The key entries below this point are generated from metadata
+     * definitions in /system/media/camera/docs. Do not modify by hand or
+     * modify the comment blocks at the start or end.
+     *~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~*/
 
-              % for value in entry.enum.values:
-                public static final Enum ${value.name | jidentifier} = Enum.${value.name | jidentifier};
-              % endfor
-
-                // TODO: remove requirement for constructor by making Key an interface
-                private ${entry.get_name_minimal() | pascal_case}Key(String name) {
-                    super(name, ${jtype_boxed(entry)}.class);
-                }
-
-              % if entry.enum.has_values_with_id:
-                static {
-                    CameraMetadata.registerEnumValues(${jenum(entry.enum)}.class, new int[] {
-                      % for (value, last) in enumerate_with_last(entry.enum.values):
-                        ${enum_calculate_value_string(value)}${"," if not last else ""}  // ${value.name | jidentifier}
-                      % endfor
-                    });
-                }
-              % endif
-            }
+##
+## Generate a single key and docs
+<%def name="generate_key(entry)">\
+    /**
+  % if entry.description:
+${entry.description | javadoc}\
+  % endif
+  % if entry.notes:
+${entry.notes | javadoc}\
+  % endif
+  % if entry.enum and not (entry.typedef and entry.typedef.languages.get('java')):
+    % for value in entry.enum.values:
+     * @see #${jenum_value(entry, value)}
+    % endfor
+  % endif
+  % if entry.applied_visibility == 'hidden':
+     *
+     * @hide
+  % endif
+     */
+    public static final Key<${jtype_boxed(entry)}> ${entry.name | jkey_identifier} =
+            new Key<${jtype_boxed(entry)}>("${entry.name}", ${jclass(entry)});
 </%def>\
 ##
 ## Generate a list of only Static, Controls, or Dynamic properties.
 <%def name="single_kind_keys(java_name, xml_name)">\
-public final class ${java_name}Keys {
 % for outer_namespace in metadata.outer_namespaces: ## assumes single 'android' namespace
   % for section in outer_namespace.sections:
     % if section.find_first(lambda x: isinstance(x, metadata_model.Entry) and x.kind == xml_name) and \
          any_visible(section, xml_name, ('public','hidden') ):
-    % if not any_visible(section, xml_name, ('public')):
-    /**
-     * @hide
-     */
-    %endif
-    public static final class ${section.name | pascal_case} {
       % for inner_namespace in get_children_by_filtering_kind(section, xml_name, 'namespaces'):
 ## We only support 1 level of inner namespace, i.e. android.a.b and android.a.b.c works, but not android.a.b.c.d
 ## If we need to support more, we should use a recursive function here instead.. but the indentation gets trickier.
-        public static final class ${inner_namespace.name| pascal_case} {
-          % for entry in filter_visibility(inner_namespace.merged_entries, ('hidden','public')):
-            % if entry.enum and not (entry.typedef and not entry.typedef.languages.get('java')):
-${generate_enum(entry)}
-            % if entry.applied_visibility == 'hidden':
-            /**
-             * @hide
-             */
-            %endif
-            public static final Key<${jtype_boxed(entry)}> ${entry.get_name_minimal() | csym} =
-                    new ${entry.get_name_minimal() | pascal_case}Key("${entry.name}");
-            % else:
-            % if entry.applied_visibility == 'hidden':
-            /**
-             * @hide
-             */
-            %endif
-            public static final Key<${jtype_boxed(entry)}> ${entry.get_name_minimal() | csym} =
-                    new Key<${jtype_boxed(entry)}>("${entry.name}", ${jclass(entry)});
-            % endif
-          % endfor
-        }
-      % endfor
-      % for entry in filter_visibility( \
-          get_children_by_filtering_kind(section, xml_name, 'merged_entries'), \
+        % for entry in filter_visibility(inner_namespace.merged_entries, ('hidden','public')):
+${generate_key(entry)}
+       % endfor
+    % endfor
+    % for entry in filter_visibility( \
+        get_children_by_filtering_kind(section, xml_name, 'merged_entries'), \
                                          ('hidden', 'public')):
-        % if entry.enum and not (entry.typedef and entry.typedef.languages.get('java')):
-${generate_enum(entry)}
-          % if entry.applied_visibility == 'hidden':
-        /**
-         * @hide
-         */
-          %endif
-        public static final Key<${jtype_boxed(entry)}> ${entry.get_name_minimal() | csym} =
-                new ${entry.get_name_minimal() | pascal_case}Key("${entry.name}");
-        % else:
-          % if entry.applied_visibility == 'hidden':
-        /**
-         * @hide
-         */
-          %endif
-        public static final Key<${jtype_boxed(entry)}> ${entry.get_name_minimal() | csym} =
-                new Key<${jtype_boxed(entry)}>("${entry.name}", ${jclass(entry)});
-        % endif
-      % endfor
-
-    }
-
+${generate_key(entry)}
+    % endfor
     % endif
   % endfor
 % endfor
-}
 </%def>\
 ##
 ## Static properties only
@@ -153,4 +79,7 @@
 ##
 ## Dynamic properties only
 ##${single_kind_keys('CaptureResultKeys', 'dynamic')}
-${single_kind_keys(java_class, xml_kind)}
+${single_kind_keys(java_class, xml_kind)}\
+    /*~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~
+     * End generated code
+     *~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~O@*/
\ No newline at end of file
diff --git a/camera/docs/CameraPropertiesTest.mako b/camera/docs/CameraPropertiesTest.mako
index 88a4ce4..1e46cf6 100644
--- a/camera/docs/CameraPropertiesTest.mako
+++ b/camera/docs/CameraPropertiesTest.mako
@@ -29,7 +29,6 @@
 import android.hardware.camera2.CameraDevice;
 import android.hardware.camera2.CameraManager;
 import android.hardware.camera2.CameraProperties;
-import android.hardware.camera2.CameraPropertiesKeys;
 import android.test.AndroidTestCase;
 
 /**
@@ -73,7 +72,7 @@
             assertNotNull(String.format("Can't get camera properties from: ID %s", ids[i]),
                                         props);
             assertNotNull("Invalid property: ${entry.name}",
-                    props.get(CameraPropertiesKeys.${jkey_identifier(entry.name)}));
+                    props.get(CameraProperties.${jkey_identifier(entry.name)}));
         }
     }
         % endif
diff --git a/camera/docs/docs.html b/camera/docs/docs.html
index 49d2e3c..7760aa8 100644
--- a/camera/docs/docs.html
+++ b/camera/docs/docs.html
@@ -7210,7 +7210,7 @@
                 <span class="entry_type_array">
                   n
                 </span>
-              <span class="entry_type_visibility"> [public]</span>
+              <span class="entry_type_visibility"> [public as imageFormat]</span>
                 <div class="entry_type_notes">values from HAL_<wbr>PIXEL_<wbr>FORMAT_<wbr>* in /<wbr>system/<wbr>core/<wbr>include/<wbr>system/<wbr>graphics.<wbr>h</div>
 
                 <ul class="entry_type_enum">
diff --git a/camera/docs/metadata-generate b/camera/docs/metadata-generate
index 36df140..9b17b2c 100755
--- a/camera/docs/metadata-generate
+++ b/camera/docs/metadata-generate
@@ -31,7 +31,7 @@
 thisdir=$(cd "$(dirname "$0")"; pwd)
 fwkdir="$ANDROID_BUILD_TOP/frameworks/base/core/java/android/hardware/camera2/"
 ctsdir="$ANDROID_BUILD_TOP/cts/tests/tests/hardware/src/android/hardware/camera2/cts"
-
+outdir="$ANDROID_PRODUCT_OUT/obj/ETC/system-media-camera-docs_intermediates"
 out_files=()
 
 function relpath() {
@@ -50,6 +50,7 @@
 function gen_file_abs() {
     local in="$1"
     local out="$2"
+    local intermediates="$3"
 
     python $thisdir/metadata_parser_xml.py $thisdir/metadata_properties.xml $in $out
 
@@ -58,7 +59,9 @@
     if [[ $succ -eq 0 ]]
     then
         echo "OK: Generated $(relpath "$out")"
-        out_files+=$'\n'" $out"
+        if [[ "$intermediates" != "no" ]]; then
+          out_files+=$'\n'" $out"
+        fi
     else
         echo "FAIL: Errors while generating $(relpath "$out")" >& 2
     fi
@@ -96,15 +99,80 @@
     printf %s\\n "${git_directories[@]}" | sort | uniq
 }
 
+# Insert a file into the middle of another, starting at the line containing the
+# start delim and ending on the end delim, both of which are replaced
+function insert_file() {
+    local src_part="$1"
+    local dst_file="$2"
+    local start_delim="/*@O~"
+    local end_delim="~O@*/"
+
+    local start_line="$(grep -n -F "${start_delim}" "${dst_file}" | cut -d: -f1)"
+    local end_line="$(grep -n -F "${end_delim}" "${dst_file}" | cut -d: -f1)"
+
+    # Adjust cutoff points to use start/end line from inserted file
+    (( start_line-- ))
+    (( end_line++ ))
+
+    # Do some basic sanity checks
+
+    if [[ -z "$start_line" ]]; then
+       echo "No starting delimiter found in ${dst_file}" >& 2
+       echo "FAIL: Errors in inserting into $(relpath ${dst_file})" >& 2
+       return 1
+    fi
+
+    if [[ -z "$end_line" ]]; then
+       echo "No ending delimiter found in ${dst_file}" >& 2
+       echo "FAIL: Errors in inserting into $(relpath ${dst_file})" >& 2
+       return 1
+    fi
+
+    if [[ "$start_line" -ge "$end_line" ]]; then
+       echo "Starting delim later than ending delim: $start_line vs $end_line" >& 2
+       echo "FAIL: Errors in inserting into $(relpath ${dst_file})" >& 2
+       return 1
+    fi
+
+    local tmp_name=$(mktemp -t XXXXXXXX)
+
+    # Compose the three parts of the final file together
+
+    head -n "$start_line" "${dst_file}" > "${tmp_name}"
+    cat "${src_part}" >> "${tmp_name}"
+    tail -n "+${end_line}" "${dst_file}" >> "${tmp_name}"
+
+    # And replace the destination file with the new version
+
+    mv "${tmp_name}" "${dst_file}"
+    echo "OK: Inserted $(relpath "$src_part") into $(relpath "$dst_file")"
+    out_files+=$'\n'" $dst_file"
+}
+
 $thisdir/metadata-check-dependencies || exit 1
 $thisdir/metadata-validate $thisdir/metadata_properties.xml || exit 1
 $thisdir/metadata-parser-sanity-check || exit 1
+
+# Generate HTML properties documentation
 gen_file html.mako docs.html || exit 1
+
+# Generate C API headers and implementation
 gen_file camera_metadata_tag_info.mako ../src/camera_metadata_tag_info.c || exit 1
 gen_file camera_metadata_tags.mako ../include/system/camera_metadata_tags.h || exit 1
-gen_file_abs CaptureResultKeys.mako "$fwkdir/CaptureResultKeys.java" || exit 1
-gen_file_abs CaptureRequestKeys.mako "$fwkdir/CaptureRequestKeys.java" || exit 1
-gen_file_abs CameraPropertiesKeys.mako "$fwkdir/CameraPropertiesKeys.java" || exit 1
+
+# Generate Java API definitions
+mkdir -p "${outdir}"
+gen_file_abs CameraMetadataEnums.mako "$outdir/CameraMetadataEnums.java.part" no || exit 1
+gen_file_abs CameraPropertiesKeys.mako "$outdir/CameraPropertiesKeys.java.part" no || exit 1
+gen_file_abs CaptureRequestKeys.mako "$outdir/CaptureRequestKeys.java.part" no || exit 1
+gen_file_abs CaptureResultKeys.mako "$outdir/CaptureResultKeys.java.part" no || exit 1
+
+insert_file "$outdir/CameraMetadataEnums.java.part" "$fwkdir/CameraMetadata.java" || exit 1
+insert_file "$outdir/CameraPropertiesKeys.java.part" "$fwkdir/CameraProperties.java" || exit 1
+insert_file "$outdir/CaptureRequestKeys.java.part" "$fwkdir/CaptureRequest.java" || exit 1
+insert_file "$outdir/CaptureResultKeys.java.part" "$fwkdir/CaptureResult.java" || exit 1
+
+# Generate CTS tests
 gen_file_abs CameraPropertiesTest.mako "$ctsdir/CameraPropertiesTest.java" || exit 1
 
 echo ""
diff --git a/camera/docs/metadata_helpers.py b/camera/docs/metadata_helpers.py
index 14bf85c..51444bf 100644
--- a/camera/docs/metadata_helpers.py
+++ b/camera/docs/metadata_helpers.py
@@ -371,11 +371,8 @@
 
   if not java_type:
     if not java_type and entry.enum:
-      name = entry.name
-
-      name_without_ons = entry.get_name_as_list()[1:]
-      base_type = ".".join([pascal_case(i) for i in name_without_ons]) + \
-                   "Key.Enum"
+      # Always map enums to Java ints, unless there's a typedef override
+      base_type = 'int'
 
     else:
       mapping = {
@@ -593,29 +590,78 @@
     name.
 
   Example:
-    jkey_identifier("android.lens.facing") == "Lens.FACING"
+    jkey_identifier("android.lens.facing") == "LENS_FACING"
   """
-  tokens = what.split('.')
-  return ".".join(map(pascal_case, tokens[1:-1])) + "." + csym(tokens[-1])
+  return csym(what[what.find('.') + 1:])
 
-def jenum(enum):
+def jenum_value(enum_entry, enum_value):
   """
-  Calculate the Java symbol referencing an enum value (in Java).
+  Calculate the Java name for an integer enum value
 
   Args:
-    enum: An Enum node
+    enum: An enum-typed Entry node
+    value: An EnumValue node for the enum
 
   Returns:
     String representing the Java symbol
   """
 
-  entry = enum.parent
-  name = entry.name
+  cname = csym(enum_entry.name)
+  return cname[cname.find('_') + 1:] + '_' + enum_value.name
 
-  name_without_ons = entry.get_name_as_list()[1:]
-  jenum_name = ".".join([pascal_case(i) for i in name_without_ons]) + "Key.Enum"
+def javadoc(text, indent = 4):
+  """
+  Format text block as a javadoc comment section
 
-  return jenum_name
+  Args:
+    text: A multi-line string to format
+    indent: baseline level of indentation for javadoc block
+  Returns:
+    String with:
+    - Indent and * for insertion into a Javadoc comment block
+    - Leading/trailing whitespace removed
+    - Paragraph tags added on newlines between paragraphs
+
+  Example:
+    "This is a comment for Javadoc\n" +
+    "     with multiple lines, that should be   \n" +
+    "     formatted better\n" +
+    "\n" +
+    "    That covers multiple lines as well\n"
+
+    transforms to
+    "    * <p>\n" +
+    "    * This is a comment for Javadoc\n" +
+    "    * with multiple lines, that should be\n" +
+    "    * formatted better\n" +
+    "    * </p><p>\n" +
+    "    * That covers multiple lines as well\n" +
+    "    * </p>\n"
+  """
+  comment_prefix = " " * indent + " * ";
+  comment_para = comment_prefix + "</p><p>\n";
+  javatext = comment_prefix + "<p>\n";
+
+  in_body = False # Eat empty lines at start
+  first_paragraph = True
+  for line in ( line.strip() for line in text.splitlines() ):
+    if not line:
+      in_body = False # collapse multi-blank lines into one
+    else:
+      # Insert para end/start after a span of blank lines except for
+      # the first paragraph, which got a para start already
+      if not in_body and not first_paragraph:
+        javatext = javatext + comment_para
+
+      in_body = True
+      first_paragraph = False
+
+      javatext = javatext + comment_prefix + line + "\n";
+
+  # Close last para tag
+  javatext = javatext + comment_prefix + "</p>\n";
+
+  return javatext
 
 def any_visible(section, kind_name, visibilities):
   """
diff --git a/camera/docs/metadata_properties.xml b/camera/docs/metadata_properties.xml
index 31b07cc..c8575ec 100644
--- a/camera/docs/metadata_properties.xml
+++ b/camera/docs/metadata_properties.xml
@@ -54,6 +54,9 @@
     <typedef name="boolean">
       <language name="java">boolean</language>
     </typedef>
+    <typedef name="imageFormat">
+      <language name="java">int</language>
+    </typedef>
   </types>
 
   <namespace name="android">
@@ -1635,7 +1638,7 @@
         <entry name="availableFormats" type="int32"
         visibility="public" enum="true"
         type_notes="values from HAL_PIXEL_FORMAT_* in /system/core/include/system/graphics.h"
-        container="array">
+        container="array" typedef="imageFormat">
           <array>
             <size>n</size>
           </array>