Camera: Generate HIDL metadata modules
- Add HidlMetadata.mako template for creating HIDL types.hal files
- Add necessary helpers and model properties to easily find sections and entries added in a given
HIDL version
- Ensure the HIDL version also shows up in the first entry of each section in the camera_metadata
C headers
- Add HIDL output to metadata-generate (though each new HIDL version needs to have a few lines added)
Bug: 33262893
Test: Verify generated HIDL output manually, build, and HIDL built-in sanity checks.
Add a few test entries and sections with different HIDL versions to see that generated code is right.
Change-Id: I9ee3b0839bab4b3efed415dab4208bacdbad56b1
diff --git a/camera/docs/HidlMetadata.mako b/camera/docs/HidlMetadata.mako
new file mode 100644
index 0000000..196dab5
--- /dev/null
+++ b/camera/docs/HidlMetadata.mako
@@ -0,0 +1,124 @@
+## -*- coding: utf-8 -*-
+/*
+ * Copyright (C) 2017 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.
+ */
+
+/**
+ * Autogenerated from camera metadata definitions in
+ * /system/media/camera/docs/metadata_definitions.xml
+ * *** DO NOT EDIT BY HAND ***
+ */
+
+<%!
+ def annotated_type(entry):
+ if entry.enum:
+ type = 'enum'
+ else:
+ type = entry.type
+ if entry.container == 'array':
+ type += '[]'
+
+ return type
+%>\
+
+package android.hardware.camera.metadata@${hal_major_version()}.${hal_minor_version()};
+
+% if first_hal_minor_version(hal_major_version()) != hal_minor_version():
+/* Include definitions from all prior minor HAL metadata revisions */
+ % for i in range(first_hal_minor_version(hal_major_version()),hal_minor_version()):
+import android.hardware.camera.metadata@${hal_major_version()}.${i};
+ % endfor
+
+% endif
+/**
+ * Top level hierarchy definitions for camera metadata. *_INFO sections are for
+ * the static metadata that can be retrived without opening the camera device.
+ */
+enum CameraMetadataSection : ${'uint32_t' if first_hal_minor_version(hal_major_version()) == hal_minor_version() else 'android.hardware.camera.metadata@%d.%d::CameraMetadataSection' % (hal_major_version(), hal_minor_version()-1)} {
+% for idx, section in enumerate(find_all_sections_added_in_hal(metadata, hal_major_version(), hal_minor_version())):
+ % if idx == 0 and first_hal_minor_version(hal_major_version()) != hal_minor_version():
+ ${path_name(section) | csym} =
+ android.hardware.camera.metadata@${hal_major_version()}.${hal_minor_version()-1}::CameraMetadataSection::ANDROID_SECTION_COUNT,
+ % else:
+ ${path_name(section) | csym},
+ % endif
+
+% endfor
+ ANDROID_SECTION_COUNT,
+
+ VENDOR_SECTION = 0x8000,
+
+};
+
+/**
+ * Hierarchy positions in enum space. All vendor extension sections must be
+ * defined with tag >= VENDOR_SECTION_START
+ */
+enum CameraMetadataSectionStart : ${'uint32_t' if first_hal_minor_version(hal_major_version()) == hal_minor_version() else 'android.hardware.camera.metadata@%d.%d::CameraMetadataSectionStart' % (hal_major_version(), hal_minor_version()-1)} {
+ % for i in find_all_sections_added_in_hal(metadata, hal_major_version(), hal_minor_version()):
+ ${path_name(i) + '.start' | csym} = CameraMetadataSection:${path_name(i) | csym} << 16,
+
+ % endfor
+ VENDOR_SECTION_START = CameraMetadataSection:VENDOR_SECTION << 16,
+
+};
+
+/**
+ * Main enum for defining camera metadata tags. New entries must always go
+ * before the section _END tag to preserve existing enumeration values.
+ */
+enum CameraMetadataTag : ${'uint32_t' if first_hal_minor_version(hal_major_version()) == hal_minor_version() else 'android.hardware.camera.metadata@%d.%d::CameraMetadataTag' % (hal_major_version(), hal_minor_version()-1)} {
+ % for sec in find_all_sections(metadata):
+<% gotEntries = False %>\
+ % for idx,entry in enumerate(filter_added_in_hal_version(remove_synthetic(find_unique_entries(sec)), hal_major_version(), hal_minor_version())):
+<% gotEntries = True %>\
+ % if idx == 0:
+ ${entry.name + " = " | csym,ljust(50)}// ${annotated_type(entry) | ljust(12) } | ${entry.applied_visibility}
+ % if find_first_older_used_hal_version(sec, hal_major_version(), hal_minor_version()) == (0, 0):
+ CameraMetadataSectionStart:${path_name(find_parent_section(entry)) | csym}_START,
+ % else:
+ ${'android.hardware.camera.metadata@%d.%d' % find_first_older_used_hal_version(sec, hal_major_version(), hal_minor_version())}::CameraMetadataTag:${path_name(find_parent_section(entry)) | csym}_END,
+ % endif
+ % else:
+ ${entry.name + "," | csym,ljust(50)}// ${annotated_type(entry) | ljust(12)} | ${entry.applied_visibility}
+ % endif
+ % endfor
+ % if gotEntries:
+ ${path_name(sec) | csym}_END,
+
+ % endif
+ %endfor
+};
+
+/**
+ * Enumeration definitions for the various entries that need them
+ */
+% for sec in find_all_sections(metadata):
+ % for entry in filter_added_in_hal_version(remove_synthetic(find_unique_entries(sec)), hal_major_version(), hal_minor_version()):
+ % if entry.enum:
+// ${entry.name}
+enum CameraMetadataEnum${entry.name | pascal_case} : uint32_t {
+ % for val in entry.enum.values:
+ % if val.id is None:
+ ${entry.name | csym}_${val.name},
+ % else:
+ ${'%s_%s'%(csym(entry.name), val.name) | pad(65)} = ${val.id},
+ % endif
+ % endfor
+};
+
+ % endif
+ % endfor
+% endfor
diff --git a/camera/docs/camera_metadata_tags.mako b/camera/docs/camera_metadata_tags.mako
index 6860385..9351d26 100644
--- a/camera/docs/camera_metadata_tags.mako
+++ b/camera/docs/camera_metadata_tags.mako
@@ -77,10 +77,10 @@
% for sec in find_all_sections(metadata):
% for idx,entry in enumerate(remove_synthetic(find_unique_entries(sec))):
% if idx == 0:
- ${entry.name + " = " | csym,ljust(50)}// ${annotated_type(entry) | ljust(12)} | ${entry.applied_visibility}
+ ${entry.name + " = " | csym,ljust(50)}// ${annotated_type(entry) | ljust(12)} | ${entry.applied_visibility | ljust(12)} | HIDL v${entry.hal_major_version}.${entry.hal_minor_version}
${path_name(find_parent_section(entry)) | csym}_START,
% else:
- ${entry.name + "," | csym,ljust(50)}// ${annotated_type(entry) | ljust(12)} | ${entry.applied_visibility | ljust(12)} | HIDL v${entry.hal_version}
+ ${entry.name + "," | csym,ljust(50)}// ${annotated_type(entry) | ljust(12)} | ${entry.applied_visibility | ljust(12)} | HIDL v${entry.hal_major_version}.${entry.hal_minor_version}
% endif
% endfor
${path_name(sec) | csym}_END,
diff --git a/camera/docs/html.mako b/camera/docs/html.mako
index e63d70a..2074daa 100644
--- a/camera/docs/html.mako
+++ b/camera/docs/html.mako
@@ -346,7 +346,7 @@
</td>
<td class="entry_hal_version">
- ${prop.hal_version | md_html, linkify_tags(metadata), wbr}
+ ${"%d.%d" % (prop.hal_major_version, prop.hal_minor_version) | md_html, linkify_tags(metadata), wbr}
</td>
<td class="entry_tags">
diff --git a/camera/docs/metadata-generate b/camera/docs/metadata-generate
index 27c7811..58b5565 100755
--- a/camera/docs/metadata-generate
+++ b/camera/docs/metadata-generate
@@ -36,6 +36,7 @@
thisdir=$(cd "$(dirname "$0")"; pwd)
fwkdir="$ANDROID_BUILD_TOP/frameworks/base/core/java/android/hardware/camera2/"
fwkdir_html="$ANDROID_BUILD_TOP/frameworks/base/docs/html/reference"
+hidldir="$ANDROID_BUILD_TOP/hardware/interfaces/camera/metadata"
ctsdir="$ANDROID_BUILD_TOP/cts/tests/camera/src/android/hardware/camera2/cts"
outdir="$ANDROID_PRODUCT_OUT/obj/ETC/system-media-camera-docs_intermediates"
ndk_header_dir="$ANDROID_BUILD_TOP/frameworks/av/camera/ndk/include/camera"
@@ -61,9 +62,10 @@
local in="$1"
local out="$2"
local intermediates="$3"
+ local hal_version="${4:-3.2}"
local spec_file=$thisdir/metadata_definitions.xml
- python $thisdir/metadata_parser_xml.py $spec_file $in $out
+ python $thisdir/metadata_parser_xml.py $spec_file $in $out $hal_version
local succ=$?
@@ -197,6 +199,13 @@
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
+# Generate HIDL metadata modules - new versions need to be added here manually
+mkdir -p "${hidldir}/3.2"
+gen_file_abs HidlMetadata.mako "$hidldir/3.2/types.hal" yes 3.2 || exit 1
+# Uncomment below to generate 3.3 HIDL module
+#mkdir -p "${hidldir}/3.3"
+#gen_file_abs HidlMetadata.mako "$hidldir/3.3/types.hal" yes 3.3 || exit 1
+
#Generate NDK header
gen_file_abs ndk_camera_metadata_tags.mako "$ndk_header_dir/NdkCameraMetadataTags.h" yes || exit 1
diff --git a/camera/docs/metadata_helpers.py b/camera/docs/metadata_helpers.py
index c258a4e..7cde49b 100644
--- a/camera/docs/metadata_helpers.py
+++ b/camera/docs/metadata_helpers.py
@@ -37,6 +37,8 @@
NDKDOC_IMAGE_SRC_METADATA="../" + IMAGE_SRC_METADATA
_context_buf = None
+_hal_major_version = None
+_hal_minor_version = None
def _is_sec_or_ins(x):
return isinstance(x, metadata_model.Section) or \
@@ -1256,6 +1258,20 @@
"""
return (e for e in entries if not e.synthetic)
+def filter_added_in_hal_version(entries, hal_major_version, hal_minor_version):
+ """
+ Filter the given entries to those added in the given HIDL HAL version
+
+ Args:
+ entries: An iterable of Entry nodes
+ hal_major_version: Major HIDL version to filter for
+ hal_minor_version: Minor HIDL version to filter for
+
+ Yields:
+ An iterable of Entry nodes
+ """
+ return (e for e in entries if e.hal_major_version == hal_major_version and e.hal_minor_version == hal_minor_version)
+
def filter_ndk_visible(entries):
"""
Filter the given entries by removing those that are not NDK visible.
@@ -1327,3 +1343,53 @@
navigable_string.extract()
return soup.decode()
+
+def hal_major_version():
+ return _hal_major_version
+
+def hal_minor_version():
+ return _hal_minor_version
+
+def first_hal_minor_version(hal_major_version):
+ return 2 if hal_major_version == 3 else 0
+
+def find_all_sections_added_in_hal(root, hal_major_version, hal_minor_version):
+ """
+ Find all descendants that are Section or InnerNamespace instances, which
+ were added in HIDL HAL version major.minor. The section is defined to be
+ added in a HAL version iff the lowest HAL version number of its entries is
+ that HAL version.
+
+ Args:
+ root: a Metadata instance
+ hal_major/minor_version: HAL version numbers
+
+ Returns:
+ A list of Section/InnerNamespace instances
+
+ Remarks:
+ These are known as "sections" in the generated C code.
+ """
+ all_sections = find_all_sections(root)
+ new_sections = []
+ for section in all_sections:
+ min_major_version = None
+ min_minor_version = None
+ for entry in remove_synthetic(find_unique_entries(section)):
+ min_major_version = (min_major_version or entry.hal_major_version)
+ min_minor_version = (min_minor_version or entry.hal_minor_version)
+ if entry.hal_major_version < min_major_version or \
+ (entry.hal_major_version == min_major_version and entry.hal_minor_version < min_minor_version):
+ min_minor_version = entry.hal_minor_version
+ min_major_version = entry.hal_major_version
+ if min_major_version == hal_major_version and min_minor_version == hal_minor_version:
+ new_sections.append(section)
+ return new_sections
+
+def find_first_older_used_hal_version(section, hal_major_version, hal_minor_version):
+ hal_version = (0, 0)
+ for v in section.hal_versions:
+ if (v[0] > hal_version[0] or (v[0] == hal_version[0] and v[1] > hal_version[1])) and \
+ (v[0] < hal_major_version or (v[0] == hal_major_version and v[1] < hal_minor_version)):
+ hal_version = v
+ return hal_version
diff --git a/camera/docs/metadata_model.py b/camera/docs/metadata_model.py
index 66a734d..648e44b 100644
--- a/camera/docs/metadata_model.py
+++ b/camera/docs/metadata_model.py
@@ -690,6 +690,7 @@
kinds: A sequence of Kind children.
merged_kinds: A sequence of virtual Kind children,
with each Kind's children merged by the kind.name
+ hal_versions: A set of tuples (major, minor) describing all the HAL versions entries in this section have
"""
def __init__(self, name, parent, description=None, kinds=[]):
self._name = name
@@ -699,7 +700,6 @@
self._leafs = []
-
@property
def description(self):
return self._description
@@ -708,6 +708,16 @@
def kinds(self):
return (i for i in self._kinds)
+ @property
+ def hal_versions(self):
+ hal_versions = set()
+ for i in self._kinds:
+ for entry in i.entries:
+ hal_versions.add( (entry.hal_major_version, entry.hal_minor_version) )
+ for namespace in i.namespaces:
+ hal_versions.update(namespace.hal_versions)
+ return hal_versions
+
def sort_children(self):
self.validate_tree()
# order is always controls,static,dynamic
@@ -884,6 +894,7 @@
namespaces: A sequence of InnerNamespace children.
entries: A sequence of Entry/Clone children.
merged_entries: A sequence of MergedEntry virtual nodes from entries
+ hal_versions: A set of tuples (major, minor) describing all the HAL versions entries in this section have
"""
def __init__(self, name, parent):
self._name = name
@@ -901,6 +912,15 @@
return self._entries
@property
+ def hal_versions(self):
+ hal_versions = set()
+ for entry in self.entries:
+ hal_versions.add( (entry.hal_major_version, entry.hal_minor_version) )
+ for namespace in self.namespaces:
+ hal_versions.update(namespace.hal_versions)
+ return hal_versions
+
+ @property
def merged_entries(self):
for i in self.entries:
yield i.merge()
@@ -1170,8 +1190,12 @@
return self._kind
@property
- def hal_version(self):
- return self._hal_version
+ def hal_major_version(self):
+ return self._hal_major_version
+
+ @property
+ def hal_minor_version(self):
+ return self._hal_minor_version
@property
def visibility(self):
@@ -1300,9 +1324,13 @@
self._container = kwargs.get('container')
self._container_sizes = kwargs.get('container_sizes')
- self._hal_version = kwargs.get('hal_version')
- if self._hal_version is None:
- self._hal_version = '3.2'
+ hal_version = kwargs.get('hal_version')
+ if hal_version is None:
+ self._hal_major_version = 3
+ self._hal_minor_version = 2
+ else:
+ self._hal_major_version = int(hal_version.partition('.')[0])
+ self._hal_minor_version = int(hal_version.partition('.')[2])
# access these via the 'enum' prop
enum_values = kwargs.get('enum_values')
@@ -1547,7 +1575,8 @@
'deprecated',
'optional',
'typedef',
- 'hal_version'
+ 'hal_major_version',
+ 'hal_minor_version'
]
for p in props_common:
diff --git a/camera/docs/metadata_parser_xml.py b/camera/docs/metadata_parser_xml.py
index 0f18e6e..81a7ec9 100755
--- a/camera/docs/metadata_parser_xml.py
+++ b/camera/docs/metadata_parser_xml.py
@@ -303,7 +303,7 @@
return d
- def render(self, template, output_name=None):
+ def render(self, template, output_name=None, hal_version="3.2"):
"""
Render the metadata model using a Mako template as the view.
@@ -315,9 +315,13 @@
Args:
template: path to a Mako template file
output_name: path to the output file, or None to use stdout
+ hal_version: target HAL version, used when generating HIDL HAL outputs.
+ Must be a string of form "X.Y" where X and Y are integers.
"""
buf = StringIO.StringIO()
metadata_helpers._context_buf = buf
+ metadata_helpers._hal_major_version = int(hal_version.partition('.')[0])
+ metadata_helpers._hal_minor_version = int(hal_version.partition('.')[2])
helpers = [(i, getattr(metadata_helpers, i))
for i in dir(metadata_helpers) if not i.startswith('_')]
@@ -344,14 +348,16 @@
if __name__ == "__main__":
if len(sys.argv) <= 2:
print >> sys.stderr, \
- "Usage: %s <filename.xml> <template.mako> [<output_file>]" \
+ "Usage: %s <filename.xml> <template.mako> [<output_file>] [<hal_version>]" \
% (sys.argv[0])
sys.exit(0)
file_name = sys.argv[1]
template_name = sys.argv[2]
output_name = sys.argv[3] if len(sys.argv) > 3 else None
+ hal_version = sys.argv[4] if len(sys.argv) > 4 else "3.2"
+
parser = MetadataParserXml.create_from_file(file_name)
- parser.render(template_name, output_name)
+ parser.render(template_name, output_name, hal_version)
sys.exit(0)
diff --git a/camera/docs/metadata_template.mako b/camera/docs/metadata_template.mako
index 03cd479..f45bfba 100644
--- a/camera/docs/metadata_template.mako
+++ b/camera/docs/metadata_template.mako
@@ -120,8 +120,8 @@
hwlevel="${prop.hwlevel}"
% endif
- % if prop.hal_version != '3.2':
- hal_version="${prop.hal_version}"
+ % if (prop.hal_major_version, prop.hal_minor_version) != (3,2):
+ hal_version="${prop.hal_major_version}.${prop.hal_minor_version}"
% endif
>