Camera: Metadata docs HTML generated from XML: DO NOT MERGE
Change-Id: Ic39249d7019dab0a6c5f5daf5d54074f6cc9c0d4
diff --git a/camera/docs/html.mako b/camera/docs/html.mako
new file mode 100644
index 0000000..a3a9042
--- /dev/null
+++ b/camera/docs/html.mako
@@ -0,0 +1,275 @@
+## -*- coding: utf-8 -*-
+<!DOCTYPE html>
+<html>
+<!-- Copyright (C) 2012 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.
+-->
+<head>
+ <meta charset="utf-8" />
+ <title>Android Camera HAL2.0 Properties</title>
+ <style type="text/css">
+ .section { font-size: 1.5em; font-weight: bold; background-color: beige; padding: 0.5em 0em 0.5em 0.1em }
+ .kind { font-size: 1.2em; font-weight: bold; padding-left: 0.5em; background-color: gray }
+ .entry { background-color: burlywood }
+
+ /* table column sizes */
+ table { table-layout: fixed; width: 100%; word-wrap: break-word }
+ td,th { border: 1px solid; }
+ .th_name { width: 20% }
+ .th_units { width: 10% }
+ .th_tags { width: 5% }
+ .th_notes { width: 30% }
+ .th_type { width: 20% }
+ td { font-size: 0.9em; }
+
+ /* hide the first thead, we need it there only to enforce column sizes */
+ .thead_dummy { visibility: hidden; }
+
+ /* Entry flair */
+ .entry_name { font-family: monospace; font-style: italic; }
+
+ /* Entry type flair */
+ .entry_type_name { color: darkgreen; font-weight: bold; }
+ .entry_type_enum_name { font-family: monospace; font-weight: bolder; }
+ .entry_type_enum_notes:before { content:" - " }
+ .entry_type_enum_value:before { content:" = " }
+ .entry_type_enum_value { font-family: monospace; }
+ .entry ul { margin: 0 0 0 0; list-style-position: inside; padding-left: 0.5em; }
+ .entry ul li { padding: 0 0 0 0; margin: 0 0 0 0;}
+
+ /* Entry tags flair */
+ .entry_tags ul { list-style-type: none; }
+
+
+ /* TODO: generate abbr element for each tag link? */
+ /* TODO for each x.y.z try to link it to the entry */
+
+ </style>
+</head>
+
+<%!
+ # insert word break hints for the browser
+ # e.g. X/Y/Z -> X/<wbr>Y/<wbr>/Z. also for X.Y.Z, X_Y_Z.
+ def wbr(text):
+ replace_chars=['.', '/', '_', ',']
+ new_txt = text
+ for i in replace_chars:
+ new_txt = new_txt.replace(i, i + "<wbr>")
+
+ return new_txt
+%>
+
+
+<body>
+ <h1>Android Camera HAL2.0 Properties</h1>
+
+ <h2>Table of Contents</h2>
+ <ul class="toc">
+ <li><a href="#tag_index">Tags</a></li>
+
+
+ % for section in metadata.find_all(lambda x: isinstance(x, metadata_model.Section)):
+ <li><p class="toc_section"><a href="#section_${section.name}">${section.name}</a></p>
+ <ul class="toc_section">
+ % for prop in section.find_all(lambda x: isinstance(x, metadata_model.Entry)):
+ <li><a href="#${prop.kind}_${prop.name}">${prop.name}</a> (${prop.kind})</li>
+ % endfor
+ </ul>
+ </li> <!-- toc_section -->
+ % endfor
+ </ul>
+
+ <h1>Properties</h1>
+ <table class="properties">
+
+ <thead class="thead_dummy">
+ <tr>
+ <th class="th_name">Property Name</th>
+ <th class="th_type">Type</th>
+ <th class="th_description">Description</th>
+ <th class="th_units">Units</th>
+ <th class="th_range">Range</th>
+ <th class="th_notes">Notes</th>
+ <th class="th_tags">Tags</th>
+ </tr>
+ </thead> <!-- so that the first occurrence of thead is not
+ above the first occurrence of tr -->
+% for root in metadata.outer_namespaces:
+<!-- <namespace name="${root.name}"> -->
+ % for section in root.sections:
+ <tr><td colspan="7" id="section_${section.name}" class="section">${section.name}</td></tr>
+
+ % if section.description is not None:
+ <tr class="description"><td>${section.description}</td></tr>
+ % endif
+
+ % for kind in section.kinds: # dynamic,static,controls
+ <tr><td colspan="7" class="kind">${kind.name}</td></tr>
+
+ <thead>
+ <tr>
+ <th class="th_name">Property Name</th>
+ <th class="th_type">Type</th>
+ <th class="th_description">Description</th>
+ <th class="th_units">Units</th>
+ <th class="th_range">Range</th>
+ <th class="th_notes">Notes</th>
+ <th class="th_tags">Tags</th>
+ </tr>
+ </thead>
+
+ <tbody>
+
+ <%def name="insert_body(node)">
+ % for nested in node.namespaces:
+ ${insert_namespace(nested)}
+ % endfor
+
+ % for entry in node.merged_entries:
+ ${insert_entry(entry)}
+ % endfor
+ </%def>
+
+ <%def name="insert_namespace(namespace)">
+ ${insert_body(namespace)}
+ </%def>
+
+ <%def name="insert_entry(prop)">
+ % if False: #prop.is_clone():
+ <clone entry="${prop.name}" kind="${prop.target_kind}">
+
+ % if prop.notes is not None:
+ <notes>${prop.notes | h,wbr}</notes>
+ % endif
+
+ % for tag in prop.tags:
+ <tag id="${tag.id}" />
+ % endfor
+
+ </clone>
+ % else:
+ <tr class="entry" id="${prop.kind}_${prop.name}">
+ <td class="entry_name">${prop.name | wbr}</td>
+ <td class="entry_type">
+ <span class="entry_type_name">${prop.type}</span>
+ % if prop.container is not None:
+ <span class="entry_type_container">x</span>
+ % endif
+
+ % if prop.container == 'array':
+ <span class="entry_type_array">
+ ${" x ".join(prop.container_sizes)}
+ </span>
+ % elif prop.container == 'tuple':
+ <ul class="entry_type_tuple">
+ % for val in prop.tuple_values:
+ <li>${val}</li>
+ % endfor
+ </ul>
+ % endif
+
+ % if prop.type_notes is not None:
+ <div class="entry_type_notes">${prop.type_notes | wbr}</div>
+ % endif
+
+ % if prop.type == 'enum':
+ <ul class="entry_type_enum">
+ % for value in prop.enum.values:
+ <li>
+ <span class="entry_type_enum_name">${value.name}</span>
+ % if value.optional:
+ <span class="entry_type_enum_optional">optional</span>
+ % endif:
+ % if value.id is not None:
+ <span class="entry_type_enum_value">${value.id}</span>
+ % endif
+ % if value.notes is not None:
+ <span class="entry_type_enum_notes">${value.notes | wbr}</span>
+ % endif
+ </li>
+ % endfor
+ </ul>
+ % endif
+
+ </td> <!-- entry_type -->
+
+ <td class="entry_description">
+ % if prop.description is not None:
+ ${prop.description | wbr}
+ % endif
+ </td>
+
+ <td class="entry_units">
+ % if prop.units is not None:
+ ${prop.units | wbr}
+ % endif
+ </td>
+
+ <td class="entry_range">
+ % if prop.range is not None:
+ ${prop.range | wbr}
+ % endif
+ </td>
+
+ <td class="entry_notes">
+ % if prop.notes is not None:
+ ${prop.notes | wbr}
+ % endif
+ </td>
+
+ <td class="entry_tags">
+ % if list(prop.tags):
+ <ul class="entry_tags">
+ % for tag in prop.tags:
+ <li><a href="#tag_${tag.id}">${tag.id}</a></li>
+ % endfor
+ </ul>
+ % endif
+ </td>
+
+ </tr> <!-- end of entry -->
+ % endif
+ </%def>
+
+ ${insert_body(kind)}
+
+ <!-- end of kind -->
+ </tbody>
+ % endfor # for each kind
+
+ <!-- end of section -->
+ % endfor
+<!-- </namespace> -->
+% endfor
+ </table>
+
+ <div class="tags" id="tag_index">
+ <h2>Tags</h2>
+ <ul>
+ % for tag in metadata.tags:
+ <li id="tag_${tag.id}">${tag.id} - ${tag.description}
+ <ul class="tags_entries">
+ % for prop in tag.entries:
+ <li><a href="#${prop.kind}_${prop.name}">${prop.name}</a> (${prop.kind})</li>
+ % endfor
+ </ul>
+ </li> <!-- tag_${tag.id} -->
+ % endfor
+ </ul>
+ </div>
+
+ [ <a href="#">top</a> ]
+
+</body>
+</html>
diff --git a/camera/docs/metadata-parser-sanity-check b/camera/docs/metadata-parser-sanity-check
index dfb83d0..e47ec0b 100755
--- a/camera/docs/metadata-parser-sanity-check
+++ b/camera/docs/metadata-parser-sanity-check
@@ -34,7 +34,7 @@
tmp_tidy1=$(mktemp)
tmp_tidy2=$(mktemp)
-$thisdir/metadata_parser_xml.py $thisdir/metadata_properties.xml > $tmp_out
+$thisdir/metadata_parser_xml.py $thisdir/metadata_properties.xml $thisdir/metadata_template.mako > $tmp_out
tidy -indent -xml -quiet $thisdir/metadata_properties.xml > $tmp_tidy1
tidy -indent -xml -quiet $tmp_out > $tmp_tidy2
diff --git a/camera/docs/metadata_model.py b/camera/docs/metadata_model.py
index 03dacad..b6215ae 100644
--- a/camera/docs/metadata_model.py
+++ b/camera/docs/metadata_model.py
@@ -342,6 +342,9 @@
if tag not in p._tags:
p._tags.append(tag)
+ if p not in tag.entries:
+ tag._entries.append(p)
+
def _construct_clones(self):
for p in self._clones:
target_kind = p.target_kind
@@ -553,7 +556,7 @@
self._parent = parent
# all entries that have this tag, including clones
- self._entries = []
+ self._entries = [] # filled in by Metadata#construct_tags
@property
def id(self):
@@ -641,6 +644,7 @@
parent: An edge to the parent, which is always a Section instance.
namespaces: A sequence of InnerNamespace children.
entries: A sequence of Entry/Clone children.
+ merged_entries: A sequence of MergedEntry virtual nodes from entries
"""
def __init__(self, name, parent):
self._name = name
@@ -658,6 +662,11 @@
def entries(self):
return self._entries
+ @property
+ def merged_entries(self):
+ for i in self.entries:
+ yield i.merge()
+
def sort_children(self):
self._namespaces.sort(key=self._get_name())
self._entries.sort(key=self._get_name())
@@ -678,6 +687,7 @@
parent: An edge to the parent, which is an InnerNamespace or a Kind.
namespaces: A sequence of InnerNamespace children.
entries: A sequence of Entry/Clone children.
+ merged_entries: A sequence of MergedEntry virtual nodes from entries
"""
def __init__(self, name, parent):
self._name = name
@@ -694,6 +704,11 @@
def entries(self):
return self._entries
+ @property
+ def merged_entries(self):
+ for i in self.entries:
+ yield i.merge()
+
def sort_children(self):
self._namespaces.sort(key=self._get_name())
self._entries.sort(key=self._get_name())
@@ -934,9 +949,18 @@
if self._type == 'enum':
self._enum = Enum(self, enum_values, enum_ids, enum_optionals, enum_notes)
+ else:
+ self._enum = None
self._property_keys = kwargs
+ def merge(self):
+ """
+ Copy the attributes into a new entry, merging it with the target entry
+ if it's a clone.
+ """
+ return MergedEntry(self)
+
# Helpers for accessing less than the fully qualified name
def get_name_as_list(self):
@@ -1077,6 +1101,42 @@
"""
return True
+class MergedEntry(Entry):
+ """
+ A MergedEntry has all the attributes of a Clone and its target Entry merged
+ together.
+ Remarks:
+ Useful when we want to 'unfold' a clone into a real entry by copying out
+ the target entry data. In this case we don't care about distinguishing
+ a clone vs an entry.
+ """
+ def __init__(self, entry):
+ """
+ Create a new instance of MergedEntry.
+ Args:
+ entry: An Entry or Clone instance
+ """
+ props_distinct = ['description', 'units', 'range', 'notes', 'tags', 'kind']
+
+ for p in props_distinct:
+ if entry.is_clone():
+ setattr(self, '_' + p, getattr(entry, p) or getattr(entry.entry, p))
+ else:
+ setattr(self, '_' + p, getattr(entry, p))
+
+ props_common = ['parent', 'name', 'name_short', 'container',
+ 'container_sizes', 'enum',
+ 'tuple_values',
+ 'type',
+ 'type_notes',
+ 'enum'
+ ]
+
+ for p in props_common:
+ if entry.is_clone():
+ setattr(self, '_' + p, getattr(entry.entry, p))
+ else:
+ setattr(self, '_' + p, getattr(entry, p))
diff --git a/camera/docs/metadata_parser_xml.py b/camera/docs/metadata_parser_xml.py
index 5390cc4..05953d4 100755
--- a/camera/docs/metadata_parser_xml.py
+++ b/camera/docs/metadata_parser_xml.py
@@ -21,7 +21,7 @@
over a Mako template.
Usage:
- metadata_parser_xml.py <filename.xml>
+ metadata_parser_xml.py <filename.xml> <template.mako>
- outputs the resulting template to stdout
Module:
@@ -43,6 +43,7 @@
from mako.template import Template
from metadata_model import *
+import metadata_model
from metadata_validate import *
class MetadataParserXml:
@@ -216,7 +217,7 @@
output_name: path to the output file, or None to use stdout
"""
tpl = Template(filename=template)
- tpl_data = tpl.render(metadata=self.metadata)
+ tpl_data = tpl.render(metadata=self.metadata, metadata_model=metadata_model)
if output_name is None:
print tpl_data
@@ -228,11 +229,13 @@
if __name__ == "__main__":
if len(sys.argv) <= 1:
- print >> sys.stderr, "Usage: %s <filename.xml>" % (sys.argv[0])
+ print >> sys.stderr, "Usage: %s <filename.xml> <template.mako>" \
+ % (sys.argv[0])
sys.exit(0)
file_name = sys.argv[1]
+ template_name = sys.argv[2]
parser = MetadataParserXml(file_name)
- parser.render("metadata_template.mako")
+ parser.render(template_name)
sys.exit(0)
diff --git a/camera/docs/metadata_properties.xml b/camera/docs/metadata_properties.xml
index 360cbfc..0c80cec 100644
--- a/camera/docs/metadata_properties.xml
+++ b/camera/docs/metadata_properties.xml
@@ -89,7 +89,6 @@
</enum>
<description>Enum for controlling
antibanding</description>
- <units>Enum</units>
<range>
android.control.aeAvailableAntibandingModes</range>
</entry>
@@ -114,7 +113,6 @@
</enum>
<description>Whether AE is currently locked to its latest
calculated values</description>
- <units>Enum</units>
<notes>Note that even when AE is locked, the flash may be
fired if the AE mode is ON_AUTO_FLASH / ON_ALWAYS_FLASH /
ON_AUTO_FLASH_REDEYE.</notes>
@@ -146,7 +144,6 @@
</enum>
<description>Whether AE is currently updating the sensor
exposure and sensitivity fields</description>
- <units>Enum</units>
<range>android.control.aeAvailableModes</range>
<notes>Only effective if android.control.mode =
AUTO</notes>
@@ -154,7 +151,8 @@
</entry>
<entry name="aeRegions" type="int32" container="array">
<array>
- <size>5 per area</size>
+ <size>5</size>
+ <size>area_count</size>
</array>
<description>List of areas to use for
metering</description>
@@ -251,12 +249,12 @@
</enum>
<description>Whether AF is currently enabled, and what
mode it is set to</description>
- <units>Enum</units>
<tag id="BC" />
</entry>
<entry name="afRegions" type="int32" container="array">
<array>
- <size>5 per area</size>
+ <size>5</size>
+ <size>area_count</size>
</array>
<description>List of areas to use for focus
estimation</description>
@@ -288,7 +286,6 @@
</enum>
<description>Whether AWB is currently locked to its
latest calculated values</description>
- <units>Enum</units>
<notes>Note that AWB lock is only meaningful for AUTO
mode; in other modes, AWB is already fixed to a specific
setting</notes>
@@ -309,14 +306,14 @@
<description>Whether AWB is currently setting the color
transform fields, and what its illumination target
is</description>
- <units>Enum</units>
<notes>[BC - AWB lock,AWB modes]</notes>
<tag id="BC" />
<tag id="AWB" />
</entry>
<entry name="awbRegions" type="int32" container="array">
<array>
- <size>5 per area</size>
+ <size>5</size>
+ <size>area_count</size>
</array>
<description>List of areas to use for illuminant
estimation</description>
@@ -363,7 +360,6 @@
<description>Information to 3A routines about the purpose
of this capture, to help decide optimal 3A
strategy</description>
- <units>Enum</units>
<range>all must be supported</range>
<notes>Only used if android.control.mode != OFF.</notes>
<tag id="BC" />
@@ -382,7 +378,6 @@
</enum>
<description>Whether any special color effect is in use.
Only used if android.control.mode != OFF</description>
- <units>Enum</units>
<range>android.control.availableEffects</range>
<tag id="BC" />
</entry>
@@ -408,7 +403,6 @@
</enum>
<description>Overall mode of 3A control
routines</description>
- <units>Enum</units>
<range>all must be supported</range>
<tag id="BC" />
</entry>
@@ -442,7 +436,6 @@
</enum>
<description>Which scene mode is active when
android.control.mode = SCENE_MODE</description>
- <units>Enum</units>
<range>android.control.availableSceneModes</range>
<tag id="BC" />
</entry>
@@ -453,7 +446,6 @@
</enum>
<description>Whether video stabilization is
active</description>
- <units>Enum</units>
<notes>If enabled, video stabilization can modify the
android.scaler.cropRegion to keep the video stream
stabilized</notes>
@@ -552,7 +544,7 @@
<tag id="BC" />
</entry>
<entry name="awbAvailableModes" type="byte">
- <units>List of enums</units>
+ <units>List of enums (android.control.awbMode)</units>
<range>OFF, AUTO must be included</range>
<tag id="BC" />
</entry>
@@ -631,7 +623,6 @@
FLASH_REQUIRED as appropriate</notes></value>
</enum>
<description>Current state of AE algorithm</description>
- <units>Enum</units>
<notes>Whenever the AE algorithm state changes, a
MSG_AUTOEXPOSURE notification must be send if a
notification callback is registered.</notes>
@@ -667,7 +658,6 @@
locked</notes></value>
</enum>
<description>Current state of AF algorithm</description>
- <units>Enum</units>
<notes>Whenever the AF algorithm state changes, a
MSG_AUTOFOCUS notification must be send if a notification
callback is registered.</notes>
@@ -698,7 +688,6 @@
LOCKED)</notes></value>
</enum>
<description>Current state of AWB algorithm</description>
- <units>Enum</units>
<notes>Whenever the AWB algorithm state changes, a
MSG_AUTOWHITEBALANCE notification must be send if a
notification callback is registered.</notes>
@@ -1684,7 +1673,6 @@
<description>Arrangement of color filters on sensor;
represents the colors in the top-left 2x2 section of
the sensor, in reading order</description>
- <units>Enum</units>
<tag id="DNG" />
</entry>
<entry name="exposureTimeRange" type="int64"
@@ -1892,7 +1880,6 @@
</enum>
<description>Light source used to define transform
1</description>
- <units>Enum</units>
<notes>[EXIF LightSource tag] Must all these be
supported? Need CCT for each!</notes>
<tag id="DNG" />