1*b9df5ad1SAndroid Build Coastguard Worker#!/usr/bin/python 2*b9df5ad1SAndroid Build Coastguard Worker 3*b9df5ad1SAndroid Build Coastguard Worker# 4*b9df5ad1SAndroid Build Coastguard Worker# Copyright (C) 2012 The Android Open Source Project 5*b9df5ad1SAndroid Build Coastguard Worker# 6*b9df5ad1SAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); 7*b9df5ad1SAndroid Build Coastguard Worker# you may not use this file except in compliance with the License. 8*b9df5ad1SAndroid Build Coastguard Worker# You may obtain a copy of the License at 9*b9df5ad1SAndroid Build Coastguard Worker# 10*b9df5ad1SAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0 11*b9df5ad1SAndroid Build Coastguard Worker# 12*b9df5ad1SAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 13*b9df5ad1SAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS, 14*b9df5ad1SAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15*b9df5ad1SAndroid Build Coastguard Worker# See the License for the specific language governing permissions and 16*b9df5ad1SAndroid Build Coastguard Worker# limitations under the License. 17*b9df5ad1SAndroid Build Coastguard Worker# 18*b9df5ad1SAndroid Build Coastguard Worker 19*b9df5ad1SAndroid Build Coastguard Worker""" 20*b9df5ad1SAndroid Build Coastguard WorkerA set of classes (models) each closely representing an XML node in the 21*b9df5ad1SAndroid Build Coastguard Workermetadata_definitions.xml file. 22*b9df5ad1SAndroid Build Coastguard Worker 23*b9df5ad1SAndroid Build Coastguard Worker Node: Base class for most nodes. 24*b9df5ad1SAndroid Build Coastguard Worker Entry: A node corresponding to <entry> elements. 25*b9df5ad1SAndroid Build Coastguard Worker Clone: A node corresponding to <clone> elements. 26*b9df5ad1SAndroid Build Coastguard Worker MergedEntry: A node corresponding to either <entry> or <clone> elements. 27*b9df5ad1SAndroid Build Coastguard Worker Kind: A node corresponding to <dynamic>, <static>, <controls> elements. 28*b9df5ad1SAndroid Build Coastguard Worker InnerNamespace: A node corresponding to a <namespace> nested under a <kind>. 29*b9df5ad1SAndroid Build Coastguard Worker OuterNamespace: A node corresponding to a <namespace> with <kind> children. 30*b9df5ad1SAndroid Build Coastguard Worker Section: A node corresponding to a <section> element. 31*b9df5ad1SAndroid Build Coastguard Worker Enum: A class corresponding an <enum> element within an <entry> 32*b9df5ad1SAndroid Build Coastguard Worker EnumValue: A class corresponding to a <value> element within an Enum 33*b9df5ad1SAndroid Build Coastguard Worker Metadata: Root node that also provides tree construction functionality. 34*b9df5ad1SAndroid Build Coastguard Worker Tag: A node corresponding to a top level <tag> element. 35*b9df5ad1SAndroid Build Coastguard Worker Typedef: A node corresponding to a <typedef> element under <types>. 36*b9df5ad1SAndroid Build Coastguard Worker""" 37*b9df5ad1SAndroid Build Coastguard Worker 38*b9df5ad1SAndroid Build Coastguard Workerimport sys 39*b9df5ad1SAndroid Build Coastguard Workerimport functools 40*b9df5ad1SAndroid Build Coastguard Workerimport itertools 41*b9df5ad1SAndroid Build Coastguard Workerfrom collections import OrderedDict 42*b9df5ad1SAndroid Build Coastguard Worker 43*b9df5ad1SAndroid Build Coastguard Workerclass Node(object): 44*b9df5ad1SAndroid Build Coastguard Worker """ 45*b9df5ad1SAndroid Build Coastguard Worker Base class for most nodes that are part of the Metadata graph. 46*b9df5ad1SAndroid Build Coastguard Worker 47*b9df5ad1SAndroid Build Coastguard Worker Attributes (Read-Only): 48*b9df5ad1SAndroid Build Coastguard Worker parent: An edge to a parent Node. 49*b9df5ad1SAndroid Build Coastguard Worker name: A string describing the name, usually but not always the 'name' 50*b9df5ad1SAndroid Build Coastguard Worker attribute of the corresponding XML node. 51*b9df5ad1SAndroid Build Coastguard Worker """ 52*b9df5ad1SAndroid Build Coastguard Worker 53*b9df5ad1SAndroid Build Coastguard Worker def __init__(self): 54*b9df5ad1SAndroid Build Coastguard Worker self._parent = None 55*b9df5ad1SAndroid Build Coastguard Worker self._name = None 56*b9df5ad1SAndroid Build Coastguard Worker 57*b9df5ad1SAndroid Build Coastguard Worker @property 58*b9df5ad1SAndroid Build Coastguard Worker def parent(self): 59*b9df5ad1SAndroid Build Coastguard Worker return self._parent 60*b9df5ad1SAndroid Build Coastguard Worker 61*b9df5ad1SAndroid Build Coastguard Worker @property 62*b9df5ad1SAndroid Build Coastguard Worker def name(self): 63*b9df5ad1SAndroid Build Coastguard Worker return self._name 64*b9df5ad1SAndroid Build Coastguard Worker 65*b9df5ad1SAndroid Build Coastguard Worker def find_all(self, pred): 66*b9df5ad1SAndroid Build Coastguard Worker """ 67*b9df5ad1SAndroid Build Coastguard Worker Find all descendants that match the predicate. 68*b9df5ad1SAndroid Build Coastguard Worker 69*b9df5ad1SAndroid Build Coastguard Worker Args: 70*b9df5ad1SAndroid Build Coastguard Worker pred: a predicate function that acts as a filter for a Node 71*b9df5ad1SAndroid Build Coastguard Worker 72*b9df5ad1SAndroid Build Coastguard Worker Yields: 73*b9df5ad1SAndroid Build Coastguard Worker A sequence of all descendants for which pred(node) is true, 74*b9df5ad1SAndroid Build Coastguard Worker in a pre-order visit order. 75*b9df5ad1SAndroid Build Coastguard Worker """ 76*b9df5ad1SAndroid Build Coastguard Worker if pred(self): 77*b9df5ad1SAndroid Build Coastguard Worker yield self 78*b9df5ad1SAndroid Build Coastguard Worker 79*b9df5ad1SAndroid Build Coastguard Worker if self._get_children() is None: 80*b9df5ad1SAndroid Build Coastguard Worker return 81*b9df5ad1SAndroid Build Coastguard Worker 82*b9df5ad1SAndroid Build Coastguard Worker for i in self._get_children(): 83*b9df5ad1SAndroid Build Coastguard Worker for j in i.find_all(pred): 84*b9df5ad1SAndroid Build Coastguard Worker yield j 85*b9df5ad1SAndroid Build Coastguard Worker 86*b9df5ad1SAndroid Build Coastguard Worker def find_first(self, pred): 87*b9df5ad1SAndroid Build Coastguard Worker """ 88*b9df5ad1SAndroid Build Coastguard Worker Find the first descendant that matches the predicate. 89*b9df5ad1SAndroid Build Coastguard Worker 90*b9df5ad1SAndroid Build Coastguard Worker Args: 91*b9df5ad1SAndroid Build Coastguard Worker pred: a predicate function that acts as a filter for a Node 92*b9df5ad1SAndroid Build Coastguard Worker 93*b9df5ad1SAndroid Build Coastguard Worker Returns: 94*b9df5ad1SAndroid Build Coastguard Worker The first Node from find_all(pred), or None if there were no results. 95*b9df5ad1SAndroid Build Coastguard Worker """ 96*b9df5ad1SAndroid Build Coastguard Worker for i in self.find_all(pred): 97*b9df5ad1SAndroid Build Coastguard Worker return i 98*b9df5ad1SAndroid Build Coastguard Worker 99*b9df5ad1SAndroid Build Coastguard Worker return None 100*b9df5ad1SAndroid Build Coastguard Worker 101*b9df5ad1SAndroid Build Coastguard Worker def find_parent_first(self, pred): 102*b9df5ad1SAndroid Build Coastguard Worker """ 103*b9df5ad1SAndroid Build Coastguard Worker Find the first ancestor that matches the predicate. 104*b9df5ad1SAndroid Build Coastguard Worker 105*b9df5ad1SAndroid Build Coastguard Worker Args: 106*b9df5ad1SAndroid Build Coastguard Worker pred: A predicate function that acts as a filter for a Node 107*b9df5ad1SAndroid Build Coastguard Worker 108*b9df5ad1SAndroid Build Coastguard Worker Returns: 109*b9df5ad1SAndroid Build Coastguard Worker The first ancestor closest to the node for which pred(node) is true. 110*b9df5ad1SAndroid Build Coastguard Worker """ 111*b9df5ad1SAndroid Build Coastguard Worker for i in self.find_parents(pred): 112*b9df5ad1SAndroid Build Coastguard Worker return i 113*b9df5ad1SAndroid Build Coastguard Worker 114*b9df5ad1SAndroid Build Coastguard Worker return None 115*b9df5ad1SAndroid Build Coastguard Worker 116*b9df5ad1SAndroid Build Coastguard Worker def find_parents(self, pred): 117*b9df5ad1SAndroid Build Coastguard Worker """ 118*b9df5ad1SAndroid Build Coastguard Worker Find all ancestors that match the predicate. 119*b9df5ad1SAndroid Build Coastguard Worker 120*b9df5ad1SAndroid Build Coastguard Worker Args: 121*b9df5ad1SAndroid Build Coastguard Worker pred: A predicate function that acts as a filter for a Node 122*b9df5ad1SAndroid Build Coastguard Worker 123*b9df5ad1SAndroid Build Coastguard Worker Yields: 124*b9df5ad1SAndroid Build Coastguard Worker A sequence of all ancestors (closest to furthest) from the node, 125*b9df5ad1SAndroid Build Coastguard Worker where pred(node) is true. 126*b9df5ad1SAndroid Build Coastguard Worker """ 127*b9df5ad1SAndroid Build Coastguard Worker parent = self.parent 128*b9df5ad1SAndroid Build Coastguard Worker 129*b9df5ad1SAndroid Build Coastguard Worker while parent is not None: 130*b9df5ad1SAndroid Build Coastguard Worker if pred(parent): 131*b9df5ad1SAndroid Build Coastguard Worker yield parent 132*b9df5ad1SAndroid Build Coastguard Worker parent = parent.parent 133*b9df5ad1SAndroid Build Coastguard Worker 134*b9df5ad1SAndroid Build Coastguard Worker def sort_children(self): 135*b9df5ad1SAndroid Build Coastguard Worker """ 136*b9df5ad1SAndroid Build Coastguard Worker Sorts the immediate children in-place. 137*b9df5ad1SAndroid Build Coastguard Worker """ 138*b9df5ad1SAndroid Build Coastguard Worker self._sort_by_name(self._children) 139*b9df5ad1SAndroid Build Coastguard Worker 140*b9df5ad1SAndroid Build Coastguard Worker def _sort_by_name(self, what): 141*b9df5ad1SAndroid Build Coastguard Worker what.sort(key=lambda x: x.name) 142*b9df5ad1SAndroid Build Coastguard Worker 143*b9df5ad1SAndroid Build Coastguard Worker def _get_name(self): 144*b9df5ad1SAndroid Build Coastguard Worker return lambda x: x.name 145*b9df5ad1SAndroid Build Coastguard Worker 146*b9df5ad1SAndroid Build Coastguard Worker # Iterate over all children nodes. None when node doesn't support children. 147*b9df5ad1SAndroid Build Coastguard Worker def _get_children(self): 148*b9df5ad1SAndroid Build Coastguard Worker return (i for i in self._children) 149*b9df5ad1SAndroid Build Coastguard Worker 150*b9df5ad1SAndroid Build Coastguard Worker def _children_name_map_matching(self, match=lambda x: True): 151*b9df5ad1SAndroid Build Coastguard Worker d = {} 152*b9df5ad1SAndroid Build Coastguard Worker for i in self._get_children(): 153*b9df5ad1SAndroid Build Coastguard Worker if match(i): 154*b9df5ad1SAndroid Build Coastguard Worker d[i.name] = i 155*b9df5ad1SAndroid Build Coastguard Worker return d 156*b9df5ad1SAndroid Build Coastguard Worker 157*b9df5ad1SAndroid Build Coastguard Worker @staticmethod 158*b9df5ad1SAndroid Build Coastguard Worker def _dictionary_by_name(values): 159*b9df5ad1SAndroid Build Coastguard Worker d = OrderedDict() 160*b9df5ad1SAndroid Build Coastguard Worker for i in values: 161*b9df5ad1SAndroid Build Coastguard Worker d[i.name] = i 162*b9df5ad1SAndroid Build Coastguard Worker 163*b9df5ad1SAndroid Build Coastguard Worker return d 164*b9df5ad1SAndroid Build Coastguard Worker 165*b9df5ad1SAndroid Build Coastguard Worker def validate_tree(self): 166*b9df5ad1SAndroid Build Coastguard Worker """ 167*b9df5ad1SAndroid Build Coastguard Worker Sanity check the tree recursively, ensuring for a node n, all children's 168*b9df5ad1SAndroid Build Coastguard Worker parents are also n. 169*b9df5ad1SAndroid Build Coastguard Worker 170*b9df5ad1SAndroid Build Coastguard Worker Returns: 171*b9df5ad1SAndroid Build Coastguard Worker True if validation succeeds, False otherwise. 172*b9df5ad1SAndroid Build Coastguard Worker """ 173*b9df5ad1SAndroid Build Coastguard Worker succ = True 174*b9df5ad1SAndroid Build Coastguard Worker children = self._get_children() 175*b9df5ad1SAndroid Build Coastguard Worker if children is None: 176*b9df5ad1SAndroid Build Coastguard Worker return True 177*b9df5ad1SAndroid Build Coastguard Worker 178*b9df5ad1SAndroid Build Coastguard Worker for child in self._get_children(): 179*b9df5ad1SAndroid Build Coastguard Worker if child.parent != self: 180*b9df5ad1SAndroid Build Coastguard Worker print("ERROR: Node '%s' doesn't match the parent (expected: %s, actual %s)" \ 181*b9df5ad1SAndroid Build Coastguard Worker % (child, self, child.parent), file=sys.stderr) 182*b9df5ad1SAndroid Build Coastguard Worker succ = False 183*b9df5ad1SAndroid Build Coastguard Worker 184*b9df5ad1SAndroid Build Coastguard Worker succ = child.validate_tree() and succ 185*b9df5ad1SAndroid Build Coastguard Worker 186*b9df5ad1SAndroid Build Coastguard Worker return succ 187*b9df5ad1SAndroid Build Coastguard Worker 188*b9df5ad1SAndroid Build Coastguard Worker def __str__(self): 189*b9df5ad1SAndroid Build Coastguard Worker return "<%s name='%s'>" %(self.__class__, self.name) 190*b9df5ad1SAndroid Build Coastguard Worker 191*b9df5ad1SAndroid Build Coastguard Workerclass Metadata(Node): 192*b9df5ad1SAndroid Build Coastguard Worker """ 193*b9df5ad1SAndroid Build Coastguard Worker A node corresponding to a <metadata> entry. 194*b9df5ad1SAndroid Build Coastguard Worker 195*b9df5ad1SAndroid Build Coastguard Worker Attributes (Read-Only): 196*b9df5ad1SAndroid Build Coastguard Worker parent: An edge to the parent Node. This is always None for Metadata. 197*b9df5ad1SAndroid Build Coastguard Worker outer_namespaces: A sequence of immediate OuterNamespace children. 198*b9df5ad1SAndroid Build Coastguard Worker tags: A sequence of all Tag instances available in the graph. 199*b9df5ad1SAndroid Build Coastguard Worker types: An iterable of all Typedef instances available in the graph. 200*b9df5ad1SAndroid Build Coastguard Worker """ 201*b9df5ad1SAndroid Build Coastguard Worker 202*b9df5ad1SAndroid Build Coastguard Worker def __init__(self): 203*b9df5ad1SAndroid Build Coastguard Worker """ 204*b9df5ad1SAndroid Build Coastguard Worker Initialize with no children. Use insert_* functions and then 205*b9df5ad1SAndroid Build Coastguard Worker construct_graph() to build up the Metadata from some source. 206*b9df5ad1SAndroid Build Coastguard Worker """ 207*b9df5ad1SAndroid Build Coastguard Worker# Private 208*b9df5ad1SAndroid Build Coastguard Worker self._entries = [] 209*b9df5ad1SAndroid Build Coastguard Worker # kind => { name => entry } 210*b9df5ad1SAndroid Build Coastguard Worker self._entry_map = { 'static': {}, 'dynamic': {}, 'controls': {} } 211*b9df5ad1SAndroid Build Coastguard Worker self._entries_ordered = [] # list of ordered Entry/Clone instances 212*b9df5ad1SAndroid Build Coastguard Worker self._clones = [] 213*b9df5ad1SAndroid Build Coastguard Worker 214*b9df5ad1SAndroid Build Coastguard Worker# Public (Read Only) 215*b9df5ad1SAndroid Build Coastguard Worker self._name = None 216*b9df5ad1SAndroid Build Coastguard Worker self._parent = None 217*b9df5ad1SAndroid Build Coastguard Worker self._outer_namespaces = None 218*b9df5ad1SAndroid Build Coastguard Worker self._tags = [] 219*b9df5ad1SAndroid Build Coastguard Worker self._types = [] 220*b9df5ad1SAndroid Build Coastguard Worker 221*b9df5ad1SAndroid Build Coastguard Worker @property 222*b9df5ad1SAndroid Build Coastguard Worker def outer_namespaces(self): 223*b9df5ad1SAndroid Build Coastguard Worker if self._outer_namespaces is None: 224*b9df5ad1SAndroid Build Coastguard Worker return None 225*b9df5ad1SAndroid Build Coastguard Worker else: 226*b9df5ad1SAndroid Build Coastguard Worker return (i for i in self._outer_namespaces) 227*b9df5ad1SAndroid Build Coastguard Worker 228*b9df5ad1SAndroid Build Coastguard Worker @property 229*b9df5ad1SAndroid Build Coastguard Worker def tags(self): 230*b9df5ad1SAndroid Build Coastguard Worker return (i for i in self._tags) 231*b9df5ad1SAndroid Build Coastguard Worker 232*b9df5ad1SAndroid Build Coastguard Worker @property 233*b9df5ad1SAndroid Build Coastguard Worker def types(self): 234*b9df5ad1SAndroid Build Coastguard Worker return (i for i in self._types) 235*b9df5ad1SAndroid Build Coastguard Worker 236*b9df5ad1SAndroid Build Coastguard Worker def _get_properties(self): 237*b9df5ad1SAndroid Build Coastguard Worker 238*b9df5ad1SAndroid Build Coastguard Worker for i in self._entries: 239*b9df5ad1SAndroid Build Coastguard Worker yield i 240*b9df5ad1SAndroid Build Coastguard Worker 241*b9df5ad1SAndroid Build Coastguard Worker for i in self._clones: 242*b9df5ad1SAndroid Build Coastguard Worker yield i 243*b9df5ad1SAndroid Build Coastguard Worker 244*b9df5ad1SAndroid Build Coastguard Worker def insert_tag(self, tag, description=""): 245*b9df5ad1SAndroid Build Coastguard Worker """ 246*b9df5ad1SAndroid Build Coastguard Worker Insert a tag into the metadata. 247*b9df5ad1SAndroid Build Coastguard Worker 248*b9df5ad1SAndroid Build Coastguard Worker Args: 249*b9df5ad1SAndroid Build Coastguard Worker tag: A string identifier for a tag. 250*b9df5ad1SAndroid Build Coastguard Worker description: A string description for a tag. 251*b9df5ad1SAndroid Build Coastguard Worker 252*b9df5ad1SAndroid Build Coastguard Worker Example: 253*b9df5ad1SAndroid Build Coastguard Worker metadata.insert_tag("BC", "Backwards Compatibility for old API") 254*b9df5ad1SAndroid Build Coastguard Worker 255*b9df5ad1SAndroid Build Coastguard Worker Remarks: 256*b9df5ad1SAndroid Build Coastguard Worker Subsequent calls to insert_tag with the same tag are safe (they will 257*b9df5ad1SAndroid Build Coastguard Worker be ignored). 258*b9df5ad1SAndroid Build Coastguard Worker """ 259*b9df5ad1SAndroid Build Coastguard Worker tag_ids = [tg.name for tg in self.tags if tg.name == tag] 260*b9df5ad1SAndroid Build Coastguard Worker if not tag_ids: 261*b9df5ad1SAndroid Build Coastguard Worker self._tags.append(Tag(tag, self, description)) 262*b9df5ad1SAndroid Build Coastguard Worker 263*b9df5ad1SAndroid Build Coastguard Worker def insert_type(self, type_name, type_selector="typedef", **kwargs): 264*b9df5ad1SAndroid Build Coastguard Worker """ 265*b9df5ad1SAndroid Build Coastguard Worker Insert a type into the metadata. 266*b9df5ad1SAndroid Build Coastguard Worker 267*b9df5ad1SAndroid Build Coastguard Worker Args: 268*b9df5ad1SAndroid Build Coastguard Worker type_name: A type's name 269*b9df5ad1SAndroid Build Coastguard Worker type_selector: The selector for the type, e.g. 'typedef' 270*b9df5ad1SAndroid Build Coastguard Worker 271*b9df5ad1SAndroid Build Coastguard Worker Args (if type_selector == 'typedef'): 272*b9df5ad1SAndroid Build Coastguard Worker languages: A map of 'language name' -> 'fully qualified class path' 273*b9df5ad1SAndroid Build Coastguard Worker 274*b9df5ad1SAndroid Build Coastguard Worker Example: 275*b9df5ad1SAndroid Build Coastguard Worker metadata.insert_type('rectangle', 'typedef', 276*b9df5ad1SAndroid Build Coastguard Worker { 'java': 'android.graphics.Rect' }) 277*b9df5ad1SAndroid Build Coastguard Worker 278*b9df5ad1SAndroid Build Coastguard Worker Remarks: 279*b9df5ad1SAndroid Build Coastguard Worker Subsequent calls to insert_type with the same type name are safe (they 280*b9df5ad1SAndroid Build Coastguard Worker will be ignored) 281*b9df5ad1SAndroid Build Coastguard Worker """ 282*b9df5ad1SAndroid Build Coastguard Worker 283*b9df5ad1SAndroid Build Coastguard Worker if type_selector != 'typedef': 284*b9df5ad1SAndroid Build Coastguard Worker raise ValueError("Unsupported type_selector given " + type_selector) 285*b9df5ad1SAndroid Build Coastguard Worker 286*b9df5ad1SAndroid Build Coastguard Worker type_names = [tp.name for tp in self.types if tp.name == tp] 287*b9df5ad1SAndroid Build Coastguard Worker if not type_names: 288*b9df5ad1SAndroid Build Coastguard Worker self._types.append(Typedef(type_name, self, kwargs.get('languages'))) 289*b9df5ad1SAndroid Build Coastguard Worker 290*b9df5ad1SAndroid Build Coastguard Worker def insert_entry(self, entry): 291*b9df5ad1SAndroid Build Coastguard Worker """ 292*b9df5ad1SAndroid Build Coastguard Worker Insert an entry into the metadata. 293*b9df5ad1SAndroid Build Coastguard Worker 294*b9df5ad1SAndroid Build Coastguard Worker Args: 295*b9df5ad1SAndroid Build Coastguard Worker entry: A key-value dictionary describing an entry. Refer to 296*b9df5ad1SAndroid Build Coastguard Worker Entry#__init__ for the keys required/optional. 297*b9df5ad1SAndroid Build Coastguard Worker 298*b9df5ad1SAndroid Build Coastguard Worker Remarks: 299*b9df5ad1SAndroid Build Coastguard Worker Subsequent calls to insert_entry with the same entry+kind name are safe 300*b9df5ad1SAndroid Build Coastguard Worker (they will be ignored). 301*b9df5ad1SAndroid Build Coastguard Worker """ 302*b9df5ad1SAndroid Build Coastguard Worker e = Entry(**entry) 303*b9df5ad1SAndroid Build Coastguard Worker self._entries.append(e) 304*b9df5ad1SAndroid Build Coastguard Worker self._entry_map[e.kind][e.name] = e 305*b9df5ad1SAndroid Build Coastguard Worker self._entries_ordered.append(e) 306*b9df5ad1SAndroid Build Coastguard Worker 307*b9df5ad1SAndroid Build Coastguard Worker def insert_clone(self, clone): 308*b9df5ad1SAndroid Build Coastguard Worker """ 309*b9df5ad1SAndroid Build Coastguard Worker Insert a clone into the metadata. 310*b9df5ad1SAndroid Build Coastguard Worker 311*b9df5ad1SAndroid Build Coastguard Worker Args: 312*b9df5ad1SAndroid Build Coastguard Worker clone: A key-value dictionary describing a clone. Refer to 313*b9df5ad1SAndroid Build Coastguard Worker Clone#__init__ for the keys required/optional. 314*b9df5ad1SAndroid Build Coastguard Worker 315*b9df5ad1SAndroid Build Coastguard Worker Remarks: 316*b9df5ad1SAndroid Build Coastguard Worker Subsequent calls to insert_clone with the same clone+kind name are safe 317*b9df5ad1SAndroid Build Coastguard Worker (they will be ignored). Also the target entry need not be inserted 318*b9df5ad1SAndroid Build Coastguard Worker ahead of the clone entry. 319*b9df5ad1SAndroid Build Coastguard Worker """ 320*b9df5ad1SAndroid Build Coastguard Worker # figure out corresponding entry later. allow clone insert, entry insert 321*b9df5ad1SAndroid Build Coastguard Worker entry = None 322*b9df5ad1SAndroid Build Coastguard Worker c = Clone(entry, **clone) 323*b9df5ad1SAndroid Build Coastguard Worker self._entry_map[c.kind][c.name] = c 324*b9df5ad1SAndroid Build Coastguard Worker self._clones.append(c) 325*b9df5ad1SAndroid Build Coastguard Worker self._entries_ordered.append(c) 326*b9df5ad1SAndroid Build Coastguard Worker 327*b9df5ad1SAndroid Build Coastguard Worker def prune_clones(self): 328*b9df5ad1SAndroid Build Coastguard Worker """ 329*b9df5ad1SAndroid Build Coastguard Worker Remove all clones that don't point to an existing entry. 330*b9df5ad1SAndroid Build Coastguard Worker 331*b9df5ad1SAndroid Build Coastguard Worker Remarks: 332*b9df5ad1SAndroid Build Coastguard Worker This should be called after all insert_entry/insert_clone calls have 333*b9df5ad1SAndroid Build Coastguard Worker finished. 334*b9df5ad1SAndroid Build Coastguard Worker """ 335*b9df5ad1SAndroid Build Coastguard Worker remove_list = [] 336*b9df5ad1SAndroid Build Coastguard Worker for p in self._clones: 337*b9df5ad1SAndroid Build Coastguard Worker if p.entry is None: 338*b9df5ad1SAndroid Build Coastguard Worker remove_list.append(p) 339*b9df5ad1SAndroid Build Coastguard Worker 340*b9df5ad1SAndroid Build Coastguard Worker for p in remove_list: 341*b9df5ad1SAndroid Build Coastguard Worker 342*b9df5ad1SAndroid Build Coastguard Worker # remove from parent's entries list 343*b9df5ad1SAndroid Build Coastguard Worker if p.parent is not None: 344*b9df5ad1SAndroid Build Coastguard Worker p.parent._entries.remove(p) 345*b9df5ad1SAndroid Build Coastguard Worker # remove from parents' _leafs list 346*b9df5ad1SAndroid Build Coastguard Worker for ancestor in p.find_parents(lambda x: not isinstance(x, Metadata)): 347*b9df5ad1SAndroid Build Coastguard Worker ancestor._leafs.remove(p) 348*b9df5ad1SAndroid Build Coastguard Worker 349*b9df5ad1SAndroid Build Coastguard Worker # remove from global list 350*b9df5ad1SAndroid Build Coastguard Worker self._clones.remove(p) 351*b9df5ad1SAndroid Build Coastguard Worker self._entry_map[p.kind].pop(p.name) 352*b9df5ad1SAndroid Build Coastguard Worker self._entries_ordered.remove(p) 353*b9df5ad1SAndroid Build Coastguard Worker 354*b9df5ad1SAndroid Build Coastguard Worker def is_entry_this_kind(self, entry, kind): 355*b9df5ad1SAndroid Build Coastguard Worker """ 356*b9df5ad1SAndroid Build Coastguard Worker Check if input entry if of input kind 357*b9df5ad1SAndroid Build Coastguard Worker 358*b9df5ad1SAndroid Build Coastguard Worker Args: 359*b9df5ad1SAndroid Build Coastguard Worker entry: an Entry object 360*b9df5ad1SAndroid Build Coastguard Worker kind: a string. Possible values are "static", "dynamic", "controls" 361*b9df5ad1SAndroid Build Coastguard Worker 362*b9df5ad1SAndroid Build Coastguard Worker Returns: 363*b9df5ad1SAndroid Build Coastguard Worker A boolean indicating whether input entry is of input kind. 364*b9df5ad1SAndroid Build Coastguard Worker """ 365*b9df5ad1SAndroid Build Coastguard Worker if kind not in ("static", "dynamic", "controls"): 366*b9df5ad1SAndroid Build Coastguard Worker assert(False), "Unknown kind value " + kind 367*b9df5ad1SAndroid Build Coastguard Worker 368*b9df5ad1SAndroid Build Coastguard Worker return entry.name in self._entry_map[kind] 369*b9df5ad1SAndroid Build Coastguard Worker 370*b9df5ad1SAndroid Build Coastguard Worker # After all entries/clones are inserted, 371*b9df5ad1SAndroid Build Coastguard Worker # invoke this to generate the parent/child node graph all these objects 372*b9df5ad1SAndroid Build Coastguard Worker def construct_graph(self): 373*b9df5ad1SAndroid Build Coastguard Worker """ 374*b9df5ad1SAndroid Build Coastguard Worker Generate the graph recursively, after which all Entry nodes will be 375*b9df5ad1SAndroid Build Coastguard Worker accessible recursively by crawling through the outer_namespaces sequence. 376*b9df5ad1SAndroid Build Coastguard Worker 377*b9df5ad1SAndroid Build Coastguard Worker Remarks: 378*b9df5ad1SAndroid Build Coastguard Worker This is safe to be called multiple times at any time. It should be done at 379*b9df5ad1SAndroid Build Coastguard Worker least once or there will be no graph. 380*b9df5ad1SAndroid Build Coastguard Worker """ 381*b9df5ad1SAndroid Build Coastguard Worker self.validate_tree() 382*b9df5ad1SAndroid Build Coastguard Worker self._construct_tags() 383*b9df5ad1SAndroid Build Coastguard Worker self.validate_tree() 384*b9df5ad1SAndroid Build Coastguard Worker self._construct_types() 385*b9df5ad1SAndroid Build Coastguard Worker self.validate_tree() 386*b9df5ad1SAndroid Build Coastguard Worker self._construct_clones() 387*b9df5ad1SAndroid Build Coastguard Worker self.validate_tree() 388*b9df5ad1SAndroid Build Coastguard Worker self._construct_outer_namespaces() 389*b9df5ad1SAndroid Build Coastguard Worker self.validate_tree() 390*b9df5ad1SAndroid Build Coastguard Worker 391*b9df5ad1SAndroid Build Coastguard Worker def _construct_tags(self): 392*b9df5ad1SAndroid Build Coastguard Worker tag_dict = self._dictionary_by_name(self.tags) 393*b9df5ad1SAndroid Build Coastguard Worker for p in self._get_properties(): 394*b9df5ad1SAndroid Build Coastguard Worker p._tags = [] 395*b9df5ad1SAndroid Build Coastguard Worker for tag_id in p._tag_ids: 396*b9df5ad1SAndroid Build Coastguard Worker tag = tag_dict.get(tag_id) 397*b9df5ad1SAndroid Build Coastguard Worker 398*b9df5ad1SAndroid Build Coastguard Worker if tag not in p._tags: 399*b9df5ad1SAndroid Build Coastguard Worker p._tags.append(tag) 400*b9df5ad1SAndroid Build Coastguard Worker 401*b9df5ad1SAndroid Build Coastguard Worker if p not in tag.entries: 402*b9df5ad1SAndroid Build Coastguard Worker tag._entries.append(p) 403*b9df5ad1SAndroid Build Coastguard Worker 404*b9df5ad1SAndroid Build Coastguard Worker def _construct_types(self): 405*b9df5ad1SAndroid Build Coastguard Worker type_dict = self._dictionary_by_name(self.types) 406*b9df5ad1SAndroid Build Coastguard Worker for p in self._get_properties(): 407*b9df5ad1SAndroid Build Coastguard Worker if p._type_name: 408*b9df5ad1SAndroid Build Coastguard Worker type_node = type_dict.get(p._type_name) 409*b9df5ad1SAndroid Build Coastguard Worker p._typedef = type_node 410*b9df5ad1SAndroid Build Coastguard Worker 411*b9df5ad1SAndroid Build Coastguard Worker if p not in type_node.entries: 412*b9df5ad1SAndroid Build Coastguard Worker type_node._entries.append(p) 413*b9df5ad1SAndroid Build Coastguard Worker 414*b9df5ad1SAndroid Build Coastguard Worker def _construct_clones(self): 415*b9df5ad1SAndroid Build Coastguard Worker for p in self._clones: 416*b9df5ad1SAndroid Build Coastguard Worker target_kind = p.target_kind 417*b9df5ad1SAndroid Build Coastguard Worker target_entry = self._entry_map[target_kind].get(p.name) 418*b9df5ad1SAndroid Build Coastguard Worker p._entry = target_entry 419*b9df5ad1SAndroid Build Coastguard Worker if (p.hal_major_version == 0): 420*b9df5ad1SAndroid Build Coastguard Worker p._hal_major_version = target_entry._hal_major_version 421*b9df5ad1SAndroid Build Coastguard Worker p._hal_minor_version = target_entry._hal_minor_version 422*b9df5ad1SAndroid Build Coastguard Worker # should not throw if we pass validation 423*b9df5ad1SAndroid Build Coastguard Worker # but can happen when importing obsolete CSV entries 424*b9df5ad1SAndroid Build Coastguard Worker if target_entry is None: 425*b9df5ad1SAndroid Build Coastguard Worker print("WARNING: Clone entry '%s' target kind '%s' has no corresponding entry" \ 426*b9df5ad1SAndroid Build Coastguard Worker % (p.name, p.target_kind), file=sys.stderr) 427*b9df5ad1SAndroid Build Coastguard Worker 428*b9df5ad1SAndroid Build Coastguard Worker def _construct_outer_namespaces(self): 429*b9df5ad1SAndroid Build Coastguard Worker 430*b9df5ad1SAndroid Build Coastguard Worker if self._outer_namespaces is None: #the first time this runs 431*b9df5ad1SAndroid Build Coastguard Worker self._outer_namespaces = [] 432*b9df5ad1SAndroid Build Coastguard Worker 433*b9df5ad1SAndroid Build Coastguard Worker root = self._dictionary_by_name(self._outer_namespaces) 434*b9df5ad1SAndroid Build Coastguard Worker for ons_name, ons in root.items(): 435*b9df5ad1SAndroid Build Coastguard Worker ons._leafs = [] 436*b9df5ad1SAndroid Build Coastguard Worker 437*b9df5ad1SAndroid Build Coastguard Worker for p in self._entries_ordered: 438*b9df5ad1SAndroid Build Coastguard Worker ons_name = p.get_outer_namespace() 439*b9df5ad1SAndroid Build Coastguard Worker ons = root.get(ons_name, OuterNamespace(ons_name, self)) 440*b9df5ad1SAndroid Build Coastguard Worker root[ons_name] = ons 441*b9df5ad1SAndroid Build Coastguard Worker 442*b9df5ad1SAndroid Build Coastguard Worker if p not in ons._leafs: 443*b9df5ad1SAndroid Build Coastguard Worker ons._leafs.append(p) 444*b9df5ad1SAndroid Build Coastguard Worker 445*b9df5ad1SAndroid Build Coastguard Worker for ons_name, ons in root.items(): 446*b9df5ad1SAndroid Build Coastguard Worker 447*b9df5ad1SAndroid Build Coastguard Worker ons.validate_tree() 448*b9df5ad1SAndroid Build Coastguard Worker 449*b9df5ad1SAndroid Build Coastguard Worker self._construct_sections(ons) 450*b9df5ad1SAndroid Build Coastguard Worker 451*b9df5ad1SAndroid Build Coastguard Worker if ons not in self._outer_namespaces: 452*b9df5ad1SAndroid Build Coastguard Worker self._outer_namespaces.append(ons) 453*b9df5ad1SAndroid Build Coastguard Worker 454*b9df5ad1SAndroid Build Coastguard Worker ons.validate_tree() 455*b9df5ad1SAndroid Build Coastguard Worker 456*b9df5ad1SAndroid Build Coastguard Worker def _construct_sections(self, outer_namespace): 457*b9df5ad1SAndroid Build Coastguard Worker 458*b9df5ad1SAndroid Build Coastguard Worker sections_dict = self._dictionary_by_name(outer_namespace.sections) 459*b9df5ad1SAndroid Build Coastguard Worker for sec_name, sec in sections_dict.items(): 460*b9df5ad1SAndroid Build Coastguard Worker sec._leafs = [] 461*b9df5ad1SAndroid Build Coastguard Worker sec.validate_tree() 462*b9df5ad1SAndroid Build Coastguard Worker 463*b9df5ad1SAndroid Build Coastguard Worker for p in outer_namespace._leafs: 464*b9df5ad1SAndroid Build Coastguard Worker does_exist = sections_dict.get(p.get_section()) 465*b9df5ad1SAndroid Build Coastguard Worker 466*b9df5ad1SAndroid Build Coastguard Worker sec = sections_dict.get(p.get_section(), \ 467*b9df5ad1SAndroid Build Coastguard Worker Section(p.get_section(), outer_namespace)) 468*b9df5ad1SAndroid Build Coastguard Worker sections_dict[p.get_section()] = sec 469*b9df5ad1SAndroid Build Coastguard Worker 470*b9df5ad1SAndroid Build Coastguard Worker sec.validate_tree() 471*b9df5ad1SAndroid Build Coastguard Worker 472*b9df5ad1SAndroid Build Coastguard Worker if p not in sec._leafs: 473*b9df5ad1SAndroid Build Coastguard Worker sec._leafs.append(p) 474*b9df5ad1SAndroid Build Coastguard Worker 475*b9df5ad1SAndroid Build Coastguard Worker for sec_name, sec in sections_dict.items(): 476*b9df5ad1SAndroid Build Coastguard Worker 477*b9df5ad1SAndroid Build Coastguard Worker if not sec.validate_tree(): 478*b9df5ad1SAndroid Build Coastguard Worker print("ERROR: Failed to validate tree in construct_sections (start), with section = '%s'" 479*b9df5ad1SAndroid Build Coastguard Worker % (sec), file=sys.stderr) 480*b9df5ad1SAndroid Build Coastguard Worker 481*b9df5ad1SAndroid Build Coastguard Worker self._construct_kinds(sec) 482*b9df5ad1SAndroid Build Coastguard Worker 483*b9df5ad1SAndroid Build Coastguard Worker if sec not in outer_namespace.sections: 484*b9df5ad1SAndroid Build Coastguard Worker outer_namespace._sections.append(sec) 485*b9df5ad1SAndroid Build Coastguard Worker 486*b9df5ad1SAndroid Build Coastguard Worker if not sec.validate_tree(): 487*b9df5ad1SAndroid Build Coastguard Worker print("ERROR: Failed to validate tree in construct_sections (end), with section = '%s'" 488*b9df5ad1SAndroid Build Coastguard Worker % (sec), file=sys.stderr) 489*b9df5ad1SAndroid Build Coastguard Worker 490*b9df5ad1SAndroid Build Coastguard Worker # 'controls', 'static' 'dynamic'. etc 491*b9df5ad1SAndroid Build Coastguard Worker def _construct_kinds(self, section): 492*b9df5ad1SAndroid Build Coastguard Worker for kind in section.kinds: 493*b9df5ad1SAndroid Build Coastguard Worker kind._leafs = [] 494*b9df5ad1SAndroid Build Coastguard Worker section.validate_tree() 495*b9df5ad1SAndroid Build Coastguard Worker 496*b9df5ad1SAndroid Build Coastguard Worker group_entry_by_kind = itertools.groupby(section._leafs, lambda x: x.kind) 497*b9df5ad1SAndroid Build Coastguard Worker leaf_it = ((k, g) for k, g in group_entry_by_kind) 498*b9df5ad1SAndroid Build Coastguard Worker 499*b9df5ad1SAndroid Build Coastguard Worker # allow multiple kinds with the same name. merge if adjacent 500*b9df5ad1SAndroid Build Coastguard Worker # e.g. dynamic,dynamic,static,static,dynamic -> dynamic,static,dynamic 501*b9df5ad1SAndroid Build Coastguard Worker # this helps maintain ABI compatibility when adding an entry in a new kind 502*b9df5ad1SAndroid Build Coastguard Worker for idx, (kind_name, entry_it) in enumerate(leaf_it): 503*b9df5ad1SAndroid Build Coastguard Worker if idx >= len(section._kinds): 504*b9df5ad1SAndroid Build Coastguard Worker kind = Kind(kind_name, section) 505*b9df5ad1SAndroid Build Coastguard Worker section._kinds.append(kind) 506*b9df5ad1SAndroid Build Coastguard Worker section.validate_tree() 507*b9df5ad1SAndroid Build Coastguard Worker 508*b9df5ad1SAndroid Build Coastguard Worker kind = section._kinds[idx] 509*b9df5ad1SAndroid Build Coastguard Worker 510*b9df5ad1SAndroid Build Coastguard Worker for p in entry_it: 511*b9df5ad1SAndroid Build Coastguard Worker if p not in kind._leafs: 512*b9df5ad1SAndroid Build Coastguard Worker kind._leafs.append(p) 513*b9df5ad1SAndroid Build Coastguard Worker 514*b9df5ad1SAndroid Build Coastguard Worker for kind in section._kinds: 515*b9df5ad1SAndroid Build Coastguard Worker kind.validate_tree() 516*b9df5ad1SAndroid Build Coastguard Worker self._construct_inner_namespaces(kind) 517*b9df5ad1SAndroid Build Coastguard Worker kind.validate_tree() 518*b9df5ad1SAndroid Build Coastguard Worker self._construct_entries(kind) 519*b9df5ad1SAndroid Build Coastguard Worker kind.validate_tree() 520*b9df5ad1SAndroid Build Coastguard Worker 521*b9df5ad1SAndroid Build Coastguard Worker if not section.validate_tree(): 522*b9df5ad1SAndroid Build Coastguard Worker print("ERROR: Failed to validate tree in construct_kinds, with kind = '%s'" % (kind), 523*b9df5ad1SAndroid Build Coastguard Worker file=sys.stderr) 524*b9df5ad1SAndroid Build Coastguard Worker 525*b9df5ad1SAndroid Build Coastguard Worker if not kind.validate_tree(): 526*b9df5ad1SAndroid Build Coastguard Worker print("ERROR: Failed to validate tree in construct_kinds, with kind = '%s'" % (kind), 527*b9df5ad1SAndroid Build Coastguard Worker file=sys.stderr) 528*b9df5ad1SAndroid Build Coastguard Worker 529*b9df5ad1SAndroid Build Coastguard Worker def _construct_inner_namespaces(self, parent, depth=0): 530*b9df5ad1SAndroid Build Coastguard Worker #parent is InnerNamespace or Kind 531*b9df5ad1SAndroid Build Coastguard Worker ins_dict = self._dictionary_by_name(parent.namespaces) 532*b9df5ad1SAndroid Build Coastguard Worker for name, ins in ins_dict.items(): 533*b9df5ad1SAndroid Build Coastguard Worker ins._leafs = [] 534*b9df5ad1SAndroid Build Coastguard Worker 535*b9df5ad1SAndroid Build Coastguard Worker for p in parent._leafs: 536*b9df5ad1SAndroid Build Coastguard Worker ins_list = p.get_inner_namespace_list() 537*b9df5ad1SAndroid Build Coastguard Worker 538*b9df5ad1SAndroid Build Coastguard Worker if len(ins_list) > depth: 539*b9df5ad1SAndroid Build Coastguard Worker ins_str = ins_list[depth] 540*b9df5ad1SAndroid Build Coastguard Worker ins = ins_dict.get(ins_str, InnerNamespace(ins_str, parent)) 541*b9df5ad1SAndroid Build Coastguard Worker ins_dict[ins_str] = ins 542*b9df5ad1SAndroid Build Coastguard Worker 543*b9df5ad1SAndroid Build Coastguard Worker if p not in ins._leafs: 544*b9df5ad1SAndroid Build Coastguard Worker ins._leafs.append(p) 545*b9df5ad1SAndroid Build Coastguard Worker 546*b9df5ad1SAndroid Build Coastguard Worker for name, ins in ins_dict.items(): 547*b9df5ad1SAndroid Build Coastguard Worker ins.validate_tree() 548*b9df5ad1SAndroid Build Coastguard Worker # construct children INS 549*b9df5ad1SAndroid Build Coastguard Worker self._construct_inner_namespaces(ins, depth + 1) 550*b9df5ad1SAndroid Build Coastguard Worker ins.validate_tree() 551*b9df5ad1SAndroid Build Coastguard Worker # construct children entries 552*b9df5ad1SAndroid Build Coastguard Worker self._construct_entries(ins, depth + 1) 553*b9df5ad1SAndroid Build Coastguard Worker 554*b9df5ad1SAndroid Build Coastguard Worker if ins not in parent.namespaces: 555*b9df5ad1SAndroid Build Coastguard Worker parent._namespaces.append(ins) 556*b9df5ad1SAndroid Build Coastguard Worker 557*b9df5ad1SAndroid Build Coastguard Worker if not ins.validate_tree(): 558*b9df5ad1SAndroid Build Coastguard Worker print("ERROR: Failed to validate tree in construct_inner_namespaces, with ins = '%s'" 559*b9df5ad1SAndroid Build Coastguard Worker % (ins), file=sys.stderr) 560*b9df5ad1SAndroid Build Coastguard Worker 561*b9df5ad1SAndroid Build Coastguard Worker # doesnt construct the entries, so much as links them 562*b9df5ad1SAndroid Build Coastguard Worker def _construct_entries(self, parent, depth=0): 563*b9df5ad1SAndroid Build Coastguard Worker #parent is InnerNamespace or Kind 564*b9df5ad1SAndroid Build Coastguard Worker entry_dict = self._dictionary_by_name(parent.entries) 565*b9df5ad1SAndroid Build Coastguard Worker for p in parent._leafs: 566*b9df5ad1SAndroid Build Coastguard Worker ins_list = p.get_inner_namespace_list() 567*b9df5ad1SAndroid Build Coastguard Worker 568*b9df5ad1SAndroid Build Coastguard Worker if len(ins_list) == depth: 569*b9df5ad1SAndroid Build Coastguard Worker entry = entry_dict.get(p.name, p) 570*b9df5ad1SAndroid Build Coastguard Worker entry_dict[p.name] = entry 571*b9df5ad1SAndroid Build Coastguard Worker 572*b9df5ad1SAndroid Build Coastguard Worker for name, entry in entry_dict.items(): 573*b9df5ad1SAndroid Build Coastguard Worker 574*b9df5ad1SAndroid Build Coastguard Worker old_parent = entry.parent 575*b9df5ad1SAndroid Build Coastguard Worker entry._parent = parent 576*b9df5ad1SAndroid Build Coastguard Worker 577*b9df5ad1SAndroid Build Coastguard Worker if entry not in parent.entries: 578*b9df5ad1SAndroid Build Coastguard Worker parent._entries.append(entry) 579*b9df5ad1SAndroid Build Coastguard Worker 580*b9df5ad1SAndroid Build Coastguard Worker if old_parent is not None and old_parent != parent: 581*b9df5ad1SAndroid Build Coastguard Worker print("ERROR: Parent changed from '%s' to '%s' for entry '%s'" 582*b9df5ad1SAndroid Build Coastguard Worker % (old_parent.name, parent.name, entry.name), file = sys.stderr) 583*b9df5ad1SAndroid Build Coastguard Worker 584*b9df5ad1SAndroid Build Coastguard Worker def _get_children(self): 585*b9df5ad1SAndroid Build Coastguard Worker if self.outer_namespaces is not None: 586*b9df5ad1SAndroid Build Coastguard Worker for i in self.outer_namespaces: 587*b9df5ad1SAndroid Build Coastguard Worker yield i 588*b9df5ad1SAndroid Build Coastguard Worker 589*b9df5ad1SAndroid Build Coastguard Worker if self.tags is not None: 590*b9df5ad1SAndroid Build Coastguard Worker for i in self.tags: 591*b9df5ad1SAndroid Build Coastguard Worker yield i 592*b9df5ad1SAndroid Build Coastguard Worker 593*b9df5ad1SAndroid Build Coastguard Workerclass Tag(Node): 594*b9df5ad1SAndroid Build Coastguard Worker """ 595*b9df5ad1SAndroid Build Coastguard Worker A tag Node corresponding to a top-level <tag> element. 596*b9df5ad1SAndroid Build Coastguard Worker 597*b9df5ad1SAndroid Build Coastguard Worker Attributes (Read-Only): 598*b9df5ad1SAndroid Build Coastguard Worker name: alias for id 599*b9df5ad1SAndroid Build Coastguard Worker id: The name of the tag, e.g. for <tag id="BC"/> id = 'BC' 600*b9df5ad1SAndroid Build Coastguard Worker description: The description of the tag, the contents of the <tag> element. 601*b9df5ad1SAndroid Build Coastguard Worker parent: An edge to the parent, which is always the Metadata root node. 602*b9df5ad1SAndroid Build Coastguard Worker entries: A sequence of edges to entries/clones that are using this Tag. 603*b9df5ad1SAndroid Build Coastguard Worker """ 604*b9df5ad1SAndroid Build Coastguard Worker def __init__(self, name, parent, description=""): 605*b9df5ad1SAndroid Build Coastguard Worker self._name = name # 'id' attribute in XML 606*b9df5ad1SAndroid Build Coastguard Worker self._id = name 607*b9df5ad1SAndroid Build Coastguard Worker self._description = description 608*b9df5ad1SAndroid Build Coastguard Worker self._parent = parent 609*b9df5ad1SAndroid Build Coastguard Worker 610*b9df5ad1SAndroid Build Coastguard Worker # all entries that have this tag, including clones 611*b9df5ad1SAndroid Build Coastguard Worker self._entries = [] # filled in by Metadata#construct_tags 612*b9df5ad1SAndroid Build Coastguard Worker 613*b9df5ad1SAndroid Build Coastguard Worker @property 614*b9df5ad1SAndroid Build Coastguard Worker def id(self): 615*b9df5ad1SAndroid Build Coastguard Worker return self._id 616*b9df5ad1SAndroid Build Coastguard Worker 617*b9df5ad1SAndroid Build Coastguard Worker @property 618*b9df5ad1SAndroid Build Coastguard Worker def description(self): 619*b9df5ad1SAndroid Build Coastguard Worker return self._description 620*b9df5ad1SAndroid Build Coastguard Worker 621*b9df5ad1SAndroid Build Coastguard Worker @property 622*b9df5ad1SAndroid Build Coastguard Worker def entries(self): 623*b9df5ad1SAndroid Build Coastguard Worker return (i for i in self._entries) 624*b9df5ad1SAndroid Build Coastguard Worker 625*b9df5ad1SAndroid Build Coastguard Worker def _get_children(self): 626*b9df5ad1SAndroid Build Coastguard Worker return None 627*b9df5ad1SAndroid Build Coastguard Worker 628*b9df5ad1SAndroid Build Coastguard Workerclass Typedef(Node): 629*b9df5ad1SAndroid Build Coastguard Worker """ 630*b9df5ad1SAndroid Build Coastguard Worker A typedef Node corresponding to a <typedef> element under a top-level <types>. 631*b9df5ad1SAndroid Build Coastguard Worker 632*b9df5ad1SAndroid Build Coastguard Worker Attributes (Read-Only): 633*b9df5ad1SAndroid Build Coastguard Worker name: The name of this typedef as a string. 634*b9df5ad1SAndroid Build Coastguard Worker languages: A dictionary of 'language name' -> 'fully qualified class'. 635*b9df5ad1SAndroid Build Coastguard Worker parent: An edge to the parent, which is always the Metadata root node. 636*b9df5ad1SAndroid Build Coastguard Worker entries: An iterable over all entries which reference this typedef. 637*b9df5ad1SAndroid Build Coastguard Worker """ 638*b9df5ad1SAndroid Build Coastguard Worker def __init__(self, name, parent, languages=None): 639*b9df5ad1SAndroid Build Coastguard Worker self._name = name 640*b9df5ad1SAndroid Build Coastguard Worker self._parent = parent 641*b9df5ad1SAndroid Build Coastguard Worker 642*b9df5ad1SAndroid Build Coastguard Worker # all entries that have this typedef 643*b9df5ad1SAndroid Build Coastguard Worker self._entries = [] # filled in by Metadata#construct_types 644*b9df5ad1SAndroid Build Coastguard Worker 645*b9df5ad1SAndroid Build Coastguard Worker self._languages = languages or {} 646*b9df5ad1SAndroid Build Coastguard Worker 647*b9df5ad1SAndroid Build Coastguard Worker @property 648*b9df5ad1SAndroid Build Coastguard Worker def languages(self): 649*b9df5ad1SAndroid Build Coastguard Worker return self._languages 650*b9df5ad1SAndroid Build Coastguard Worker 651*b9df5ad1SAndroid Build Coastguard Worker @property 652*b9df5ad1SAndroid Build Coastguard Worker def entries(self): 653*b9df5ad1SAndroid Build Coastguard Worker return (i for i in self._entries) 654*b9df5ad1SAndroid Build Coastguard Worker 655*b9df5ad1SAndroid Build Coastguard Worker def _get_children(self): 656*b9df5ad1SAndroid Build Coastguard Worker return None 657*b9df5ad1SAndroid Build Coastguard Worker 658*b9df5ad1SAndroid Build Coastguard Workerclass OuterNamespace(Node): 659*b9df5ad1SAndroid Build Coastguard Worker """ 660*b9df5ad1SAndroid Build Coastguard Worker A node corresponding to a <namespace> element under <metadata> 661*b9df5ad1SAndroid Build Coastguard Worker 662*b9df5ad1SAndroid Build Coastguard Worker Attributes (Read-Only): 663*b9df5ad1SAndroid Build Coastguard Worker name: The name attribute of the <namespace name="foo"> element. 664*b9df5ad1SAndroid Build Coastguard Worker parent: An edge to the parent, which is always the Metadata root node. 665*b9df5ad1SAndroid Build Coastguard Worker sections: A sequence of Section children. 666*b9df5ad1SAndroid Build Coastguard Worker """ 667*b9df5ad1SAndroid Build Coastguard Worker def __init__(self, name, parent, sections=[]): 668*b9df5ad1SAndroid Build Coastguard Worker self._name = name 669*b9df5ad1SAndroid Build Coastguard Worker self._parent = parent # MetadataSet 670*b9df5ad1SAndroid Build Coastguard Worker self._sections = sections[:] 671*b9df5ad1SAndroid Build Coastguard Worker self._leafs = [] 672*b9df5ad1SAndroid Build Coastguard Worker 673*b9df5ad1SAndroid Build Coastguard Worker self._children = self._sections 674*b9df5ad1SAndroid Build Coastguard Worker 675*b9df5ad1SAndroid Build Coastguard Worker @property 676*b9df5ad1SAndroid Build Coastguard Worker def sections(self): 677*b9df5ad1SAndroid Build Coastguard Worker return (i for i in self._sections) 678*b9df5ad1SAndroid Build Coastguard Worker 679*b9df5ad1SAndroid Build Coastguard Workerclass Section(Node): 680*b9df5ad1SAndroid Build Coastguard Worker """ 681*b9df5ad1SAndroid Build Coastguard Worker A node corresponding to a <section> element under <namespace> 682*b9df5ad1SAndroid Build Coastguard Worker 683*b9df5ad1SAndroid Build Coastguard Worker Attributes (Read-Only): 684*b9df5ad1SAndroid Build Coastguard Worker name: The name attribute of the <section name="foo"> element. 685*b9df5ad1SAndroid Build Coastguard Worker parent: An edge to the parent, which is always an OuterNamespace instance. 686*b9df5ad1SAndroid Build Coastguard Worker description: A string description of the section, or None. 687*b9df5ad1SAndroid Build Coastguard Worker kinds: A sequence of Kind children. 688*b9df5ad1SAndroid Build Coastguard Worker merged_kinds: A sequence of virtual Kind children, 689*b9df5ad1SAndroid Build Coastguard Worker with each Kind's children merged by the kind.name 690*b9df5ad1SAndroid Build Coastguard Worker hal_versions: A set of tuples (major, minor) describing all the HAL versions entries in this section have 691*b9df5ad1SAndroid Build Coastguard Worker """ 692*b9df5ad1SAndroid Build Coastguard Worker def __init__(self, name, parent, description=None, kinds=[]): 693*b9df5ad1SAndroid Build Coastguard Worker self._name = name 694*b9df5ad1SAndroid Build Coastguard Worker self._parent = parent 695*b9df5ad1SAndroid Build Coastguard Worker self._description = description 696*b9df5ad1SAndroid Build Coastguard Worker self._kinds = kinds[:] 697*b9df5ad1SAndroid Build Coastguard Worker 698*b9df5ad1SAndroid Build Coastguard Worker self._leafs = [] 699*b9df5ad1SAndroid Build Coastguard Worker 700*b9df5ad1SAndroid Build Coastguard Worker @property 701*b9df5ad1SAndroid Build Coastguard Worker def description(self): 702*b9df5ad1SAndroid Build Coastguard Worker return self._description 703*b9df5ad1SAndroid Build Coastguard Worker 704*b9df5ad1SAndroid Build Coastguard Worker @property 705*b9df5ad1SAndroid Build Coastguard Worker def kinds(self): 706*b9df5ad1SAndroid Build Coastguard Worker return (i for i in self._kinds) 707*b9df5ad1SAndroid Build Coastguard Worker 708*b9df5ad1SAndroid Build Coastguard Worker @property 709*b9df5ad1SAndroid Build Coastguard Worker def hal_versions(self): 710*b9df5ad1SAndroid Build Coastguard Worker hal_versions = set() 711*b9df5ad1SAndroid Build Coastguard Worker for i in self._kinds: 712*b9df5ad1SAndroid Build Coastguard Worker for entry in i.entries: 713*b9df5ad1SAndroid Build Coastguard Worker hal_versions.add( (entry.hal_major_version, entry.hal_minor_version) ) 714*b9df5ad1SAndroid Build Coastguard Worker for namespace in i.namespaces: 715*b9df5ad1SAndroid Build Coastguard Worker hal_versions.update(namespace.hal_versions) 716*b9df5ad1SAndroid Build Coastguard Worker return hal_versions 717*b9df5ad1SAndroid Build Coastguard Worker 718*b9df5ad1SAndroid Build Coastguard Worker def sort_children(self): 719*b9df5ad1SAndroid Build Coastguard Worker self.validate_tree() 720*b9df5ad1SAndroid Build Coastguard Worker # order is always controls,static,dynamic 721*b9df5ad1SAndroid Build Coastguard Worker find_child = lambda x: [i for i in self._get_children() if i.name == x] 722*b9df5ad1SAndroid Build Coastguard Worker new_lst = find_child('controls') \ 723*b9df5ad1SAndroid Build Coastguard Worker + find_child('static') \ 724*b9df5ad1SAndroid Build Coastguard Worker + find_child('dynamic') 725*b9df5ad1SAndroid Build Coastguard Worker self._kinds = new_lst 726*b9df5ad1SAndroid Build Coastguard Worker self.validate_tree() 727*b9df5ad1SAndroid Build Coastguard Worker 728*b9df5ad1SAndroid Build Coastguard Worker def _get_children(self): 729*b9df5ad1SAndroid Build Coastguard Worker return (i for i in self.kinds) 730*b9df5ad1SAndroid Build Coastguard Worker 731*b9df5ad1SAndroid Build Coastguard Worker @property 732*b9df5ad1SAndroid Build Coastguard Worker def merged_kinds(self): 733*b9df5ad1SAndroid Build Coastguard Worker 734*b9df5ad1SAndroid Build Coastguard Worker def aggregate_by_name(acc, el): 735*b9df5ad1SAndroid Build Coastguard Worker existing = [i for i in acc if i.name == el.name] 736*b9df5ad1SAndroid Build Coastguard Worker if existing: 737*b9df5ad1SAndroid Build Coastguard Worker k = existing[0] 738*b9df5ad1SAndroid Build Coastguard Worker else: 739*b9df5ad1SAndroid Build Coastguard Worker k = Kind(el.name, el.parent) 740*b9df5ad1SAndroid Build Coastguard Worker acc.append(k) 741*b9df5ad1SAndroid Build Coastguard Worker 742*b9df5ad1SAndroid Build Coastguard Worker k._namespaces.extend(el._namespaces) 743*b9df5ad1SAndroid Build Coastguard Worker k._entries.extend(el._entries) 744*b9df5ad1SAndroid Build Coastguard Worker 745*b9df5ad1SAndroid Build Coastguard Worker return acc 746*b9df5ad1SAndroid Build Coastguard Worker 747*b9df5ad1SAndroid Build Coastguard Worker new_kinds_lst = functools.reduce(aggregate_by_name, self.kinds, []) 748*b9df5ad1SAndroid Build Coastguard Worker 749*b9df5ad1SAndroid Build Coastguard Worker for k in new_kinds_lst: 750*b9df5ad1SAndroid Build Coastguard Worker yield k 751*b9df5ad1SAndroid Build Coastguard Worker 752*b9df5ad1SAndroid Build Coastguard Worker def combine_kinds_into_single_node(self): 753*b9df5ad1SAndroid Build Coastguard Worker r""" 754*b9df5ad1SAndroid Build Coastguard Worker Combines the section's Kinds into a single node. 755*b9df5ad1SAndroid Build Coastguard Worker 756*b9df5ad1SAndroid Build Coastguard Worker Combines all the children (kinds) of this section into a single 757*b9df5ad1SAndroid Build Coastguard Worker virtual Kind node. 758*b9df5ad1SAndroid Build Coastguard Worker 759*b9df5ad1SAndroid Build Coastguard Worker Returns: 760*b9df5ad1SAndroid Build Coastguard Worker A new Kind node that collapses all Kind siblings into one, combining 761*b9df5ad1SAndroid Build Coastguard Worker all their children together. 762*b9df5ad1SAndroid Build Coastguard Worker 763*b9df5ad1SAndroid Build Coastguard Worker For example, given self.kinds == [ x, y ] 764*b9df5ad1SAndroid Build Coastguard Worker 765*b9df5ad1SAndroid Build Coastguard Worker x y z 766*b9df5ad1SAndroid Build Coastguard Worker / | | \ --> / | | \ 767*b9df5ad1SAndroid Build Coastguard Worker a b c d a b c d 768*b9df5ad1SAndroid Build Coastguard Worker 769*b9df5ad1SAndroid Build Coastguard Worker a new instance z is returned in this example. 770*b9df5ad1SAndroid Build Coastguard Worker 771*b9df5ad1SAndroid Build Coastguard Worker Remarks: 772*b9df5ad1SAndroid Build Coastguard Worker The children of the kinds are the same references as before, that is 773*b9df5ad1SAndroid Build Coastguard Worker their parents will point to the old parents and not to the new parent. 774*b9df5ad1SAndroid Build Coastguard Worker """ 775*b9df5ad1SAndroid Build Coastguard Worker combined = Kind(name="combined", parent=self) 776*b9df5ad1SAndroid Build Coastguard Worker 777*b9df5ad1SAndroid Build Coastguard Worker for k in self._get_children(): 778*b9df5ad1SAndroid Build Coastguard Worker combined._namespaces.extend(k.namespaces) 779*b9df5ad1SAndroid Build Coastguard Worker combined._entries.extend(k.entries) 780*b9df5ad1SAndroid Build Coastguard Worker 781*b9df5ad1SAndroid Build Coastguard Worker return combined 782*b9df5ad1SAndroid Build Coastguard Worker 783*b9df5ad1SAndroid Build Coastguard Workerclass Kind(Node): 784*b9df5ad1SAndroid Build Coastguard Worker """ 785*b9df5ad1SAndroid Build Coastguard Worker A node corresponding to one of: <static>,<dynamic>,<controls> under a 786*b9df5ad1SAndroid Build Coastguard Worker <section> element. 787*b9df5ad1SAndroid Build Coastguard Worker 788*b9df5ad1SAndroid Build Coastguard Worker Attributes (Read-Only): 789*b9df5ad1SAndroid Build Coastguard Worker name: A string which is one of 'static', 'dynamic, or 'controls'. 790*b9df5ad1SAndroid Build Coastguard Worker parent: An edge to the parent, which is always a Section instance. 791*b9df5ad1SAndroid Build Coastguard Worker namespaces: A sequence of InnerNamespace children. 792*b9df5ad1SAndroid Build Coastguard Worker entries: A sequence of Entry/Clone children. 793*b9df5ad1SAndroid Build Coastguard Worker merged_entries: A sequence of MergedEntry virtual nodes from entries 794*b9df5ad1SAndroid Build Coastguard Worker """ 795*b9df5ad1SAndroid Build Coastguard Worker def __init__(self, name, parent): 796*b9df5ad1SAndroid Build Coastguard Worker self._name = name 797*b9df5ad1SAndroid Build Coastguard Worker self._parent = parent 798*b9df5ad1SAndroid Build Coastguard Worker self._namespaces = [] 799*b9df5ad1SAndroid Build Coastguard Worker self._entries = [] 800*b9df5ad1SAndroid Build Coastguard Worker 801*b9df5ad1SAndroid Build Coastguard Worker self._leafs = [] 802*b9df5ad1SAndroid Build Coastguard Worker 803*b9df5ad1SAndroid Build Coastguard Worker @property 804*b9df5ad1SAndroid Build Coastguard Worker def namespaces(self): 805*b9df5ad1SAndroid Build Coastguard Worker return self._namespaces 806*b9df5ad1SAndroid Build Coastguard Worker 807*b9df5ad1SAndroid Build Coastguard Worker @property 808*b9df5ad1SAndroid Build Coastguard Worker def entries(self): 809*b9df5ad1SAndroid Build Coastguard Worker return self._entries 810*b9df5ad1SAndroid Build Coastguard Worker 811*b9df5ad1SAndroid Build Coastguard Worker @property 812*b9df5ad1SAndroid Build Coastguard Worker def merged_entries(self): 813*b9df5ad1SAndroid Build Coastguard Worker for i in self.entries: 814*b9df5ad1SAndroid Build Coastguard Worker yield i.merge() 815*b9df5ad1SAndroid Build Coastguard Worker 816*b9df5ad1SAndroid Build Coastguard Worker def sort_children(self): 817*b9df5ad1SAndroid Build Coastguard Worker self._namespaces.sort(key=self._get_name()) 818*b9df5ad1SAndroid Build Coastguard Worker self._entries.sort(key=self._get_name()) 819*b9df5ad1SAndroid Build Coastguard Worker 820*b9df5ad1SAndroid Build Coastguard Worker def _get_children(self): 821*b9df5ad1SAndroid Build Coastguard Worker for i in self.namespaces: 822*b9df5ad1SAndroid Build Coastguard Worker yield i 823*b9df5ad1SAndroid Build Coastguard Worker for i in self.entries: 824*b9df5ad1SAndroid Build Coastguard Worker yield i 825*b9df5ad1SAndroid Build Coastguard Worker 826*b9df5ad1SAndroid Build Coastguard Worker def combine_children_by_name(self): 827*b9df5ad1SAndroid Build Coastguard Worker r""" 828*b9df5ad1SAndroid Build Coastguard Worker Combine multiple children with the same name into a single node. 829*b9df5ad1SAndroid Build Coastguard Worker 830*b9df5ad1SAndroid Build Coastguard Worker Returns: 831*b9df5ad1SAndroid Build Coastguard Worker A new Kind where all of the children with the same name were combined. 832*b9df5ad1SAndroid Build Coastguard Worker 833*b9df5ad1SAndroid Build Coastguard Worker For example: 834*b9df5ad1SAndroid Build Coastguard Worker 835*b9df5ad1SAndroid Build Coastguard Worker Given a Kind k: 836*b9df5ad1SAndroid Build Coastguard Worker 837*b9df5ad1SAndroid Build Coastguard Worker k 838*b9df5ad1SAndroid Build Coastguard Worker / | \ 839*b9df5ad1SAndroid Build Coastguard Worker a b c 840*b9df5ad1SAndroid Build Coastguard Worker | | | 841*b9df5ad1SAndroid Build Coastguard Worker d e f 842*b9df5ad1SAndroid Build Coastguard Worker 843*b9df5ad1SAndroid Build Coastguard Worker a.name == "foo" 844*b9df5ad1SAndroid Build Coastguard Worker b.name == "foo" 845*b9df5ad1SAndroid Build Coastguard Worker c.name == "bar" 846*b9df5ad1SAndroid Build Coastguard Worker 847*b9df5ad1SAndroid Build Coastguard Worker The returned Kind will look like this: 848*b9df5ad1SAndroid Build Coastguard Worker 849*b9df5ad1SAndroid Build Coastguard Worker k' 850*b9df5ad1SAndroid Build Coastguard Worker / \ 851*b9df5ad1SAndroid Build Coastguard Worker a' c' 852*b9df5ad1SAndroid Build Coastguard Worker / | | 853*b9df5ad1SAndroid Build Coastguard Worker d e f 854*b9df5ad1SAndroid Build Coastguard Worker 855*b9df5ad1SAndroid Build Coastguard Worker Remarks: 856*b9df5ad1SAndroid Build Coastguard Worker This operation is not recursive. To combine the grandchildren and other 857*b9df5ad1SAndroid Build Coastguard Worker ancestors, call this method on the ancestor nodes. 858*b9df5ad1SAndroid Build Coastguard Worker """ 859*b9df5ad1SAndroid Build Coastguard Worker return Kind._combine_children_by_name(self, new_type=type(self)) 860*b9df5ad1SAndroid Build Coastguard Worker 861*b9df5ad1SAndroid Build Coastguard Worker # new_type is either Kind or InnerNamespace 862*b9df5ad1SAndroid Build Coastguard Worker @staticmethod 863*b9df5ad1SAndroid Build Coastguard Worker def _combine_children_by_name(self, new_type): 864*b9df5ad1SAndroid Build Coastguard Worker new_ins_dict = OrderedDict() 865*b9df5ad1SAndroid Build Coastguard Worker new_ent_dict = OrderedDict() 866*b9df5ad1SAndroid Build Coastguard Worker 867*b9df5ad1SAndroid Build Coastguard Worker for ins in self.namespaces: 868*b9df5ad1SAndroid Build Coastguard Worker new_ins = new_ins_dict.setdefault(ins.name, 869*b9df5ad1SAndroid Build Coastguard Worker InnerNamespace(ins.name, parent=self)) 870*b9df5ad1SAndroid Build Coastguard Worker new_ins._namespaces.extend(ins.namespaces) 871*b9df5ad1SAndroid Build Coastguard Worker new_ins._entries.extend(ins.entries) 872*b9df5ad1SAndroid Build Coastguard Worker 873*b9df5ad1SAndroid Build Coastguard Worker for ent in self.entries: 874*b9df5ad1SAndroid Build Coastguard Worker new_ent = new_ent_dict.setdefault(ent.name, 875*b9df5ad1SAndroid Build Coastguard Worker ent.merge()) 876*b9df5ad1SAndroid Build Coastguard Worker 877*b9df5ad1SAndroid Build Coastguard Worker kind = new_type(self.name, self.parent) 878*b9df5ad1SAndroid Build Coastguard Worker kind._namespaces = new_ins_dict.values() 879*b9df5ad1SAndroid Build Coastguard Worker kind._entries = new_ent_dict.values() 880*b9df5ad1SAndroid Build Coastguard Worker 881*b9df5ad1SAndroid Build Coastguard Worker return kind 882*b9df5ad1SAndroid Build Coastguard Worker 883*b9df5ad1SAndroid Build Coastguard Workerclass InnerNamespace(Node): 884*b9df5ad1SAndroid Build Coastguard Worker """ 885*b9df5ad1SAndroid Build Coastguard Worker A node corresponding to a <namespace> which is an ancestor of a Kind. 886*b9df5ad1SAndroid Build Coastguard Worker These namespaces may have other namespaces recursively, or entries as leafs. 887*b9df5ad1SAndroid Build Coastguard Worker 888*b9df5ad1SAndroid Build Coastguard Worker Attributes (Read-Only): 889*b9df5ad1SAndroid Build Coastguard Worker name: Name attribute from the element, e.g. <namespace name="foo"> -> 'foo' 890*b9df5ad1SAndroid Build Coastguard Worker parent: An edge to the parent, which is an InnerNamespace or a Kind. 891*b9df5ad1SAndroid Build Coastguard Worker namespaces: A sequence of InnerNamespace children. 892*b9df5ad1SAndroid Build Coastguard Worker entries: A sequence of Entry/Clone children. 893*b9df5ad1SAndroid Build Coastguard Worker merged_entries: A sequence of MergedEntry virtual nodes from entries 894*b9df5ad1SAndroid Build Coastguard Worker hal_versions: A set of tuples (major, minor) describing all the HAL versions entries in this section have 895*b9df5ad1SAndroid Build Coastguard Worker """ 896*b9df5ad1SAndroid Build Coastguard Worker def __init__(self, name, parent): 897*b9df5ad1SAndroid Build Coastguard Worker self._name = name 898*b9df5ad1SAndroid Build Coastguard Worker self._parent = parent 899*b9df5ad1SAndroid Build Coastguard Worker self._namespaces = [] 900*b9df5ad1SAndroid Build Coastguard Worker self._entries = [] 901*b9df5ad1SAndroid Build Coastguard Worker self._leafs = [] 902*b9df5ad1SAndroid Build Coastguard Worker 903*b9df5ad1SAndroid Build Coastguard Worker @property 904*b9df5ad1SAndroid Build Coastguard Worker def namespaces(self): 905*b9df5ad1SAndroid Build Coastguard Worker return self._namespaces 906*b9df5ad1SAndroid Build Coastguard Worker 907*b9df5ad1SAndroid Build Coastguard Worker @property 908*b9df5ad1SAndroid Build Coastguard Worker def entries(self): 909*b9df5ad1SAndroid Build Coastguard Worker return self._entries 910*b9df5ad1SAndroid Build Coastguard Worker 911*b9df5ad1SAndroid Build Coastguard Worker @property 912*b9df5ad1SAndroid Build Coastguard Worker def hal_versions(self): 913*b9df5ad1SAndroid Build Coastguard Worker hal_versions = set() 914*b9df5ad1SAndroid Build Coastguard Worker for entry in self.entries: 915*b9df5ad1SAndroid Build Coastguard Worker hal_versions.add( (entry.hal_major_version, entry.hal_minor_version) ) 916*b9df5ad1SAndroid Build Coastguard Worker for namespace in self.namespaces: 917*b9df5ad1SAndroid Build Coastguard Worker hal_versions.update(namespace.hal_versions) 918*b9df5ad1SAndroid Build Coastguard Worker return hal_versions 919*b9df5ad1SAndroid Build Coastguard Worker 920*b9df5ad1SAndroid Build Coastguard Worker @property 921*b9df5ad1SAndroid Build Coastguard Worker def merged_entries(self): 922*b9df5ad1SAndroid Build Coastguard Worker for i in self.entries: 923*b9df5ad1SAndroid Build Coastguard Worker yield i.merge() 924*b9df5ad1SAndroid Build Coastguard Worker 925*b9df5ad1SAndroid Build Coastguard Worker def sort_children(self): 926*b9df5ad1SAndroid Build Coastguard Worker self._namespaces.sort(key=self._get_name()) 927*b9df5ad1SAndroid Build Coastguard Worker self._entries.sort(key=self._get_name()) 928*b9df5ad1SAndroid Build Coastguard Worker 929*b9df5ad1SAndroid Build Coastguard Worker def _get_children(self): 930*b9df5ad1SAndroid Build Coastguard Worker for i in self.namespaces: 931*b9df5ad1SAndroid Build Coastguard Worker yield i 932*b9df5ad1SAndroid Build Coastguard Worker for i in self.entries: 933*b9df5ad1SAndroid Build Coastguard Worker yield i 934*b9df5ad1SAndroid Build Coastguard Worker 935*b9df5ad1SAndroid Build Coastguard Worker def combine_children_by_name(self): 936*b9df5ad1SAndroid Build Coastguard Worker r""" 937*b9df5ad1SAndroid Build Coastguard Worker Combine multiple children with the same name into a single node. 938*b9df5ad1SAndroid Build Coastguard Worker 939*b9df5ad1SAndroid Build Coastguard Worker Returns: 940*b9df5ad1SAndroid Build Coastguard Worker A new InnerNamespace where all of the children with the same name were 941*b9df5ad1SAndroid Build Coastguard Worker combined. 942*b9df5ad1SAndroid Build Coastguard Worker 943*b9df5ad1SAndroid Build Coastguard Worker For example: 944*b9df5ad1SAndroid Build Coastguard Worker 945*b9df5ad1SAndroid Build Coastguard Worker Given an InnerNamespace i: 946*b9df5ad1SAndroid Build Coastguard Worker 947*b9df5ad1SAndroid Build Coastguard Worker i 948*b9df5ad1SAndroid Build Coastguard Worker / | \ 949*b9df5ad1SAndroid Build Coastguard Worker a b c 950*b9df5ad1SAndroid Build Coastguard Worker | | | 951*b9df5ad1SAndroid Build Coastguard Worker d e f 952*b9df5ad1SAndroid Build Coastguard Worker 953*b9df5ad1SAndroid Build Coastguard Worker a.name == "foo" 954*b9df5ad1SAndroid Build Coastguard Worker b.name == "foo" 955*b9df5ad1SAndroid Build Coastguard Worker c.name == "bar" 956*b9df5ad1SAndroid Build Coastguard Worker 957*b9df5ad1SAndroid Build Coastguard Worker The returned InnerNamespace will look like this: 958*b9df5ad1SAndroid Build Coastguard Worker 959*b9df5ad1SAndroid Build Coastguard Worker i' 960*b9df5ad1SAndroid Build Coastguard Worker / \ 961*b9df5ad1SAndroid Build Coastguard Worker a' c' 962*b9df5ad1SAndroid Build Coastguard Worker / | | 963*b9df5ad1SAndroid Build Coastguard Worker d e f 964*b9df5ad1SAndroid Build Coastguard Worker 965*b9df5ad1SAndroid Build Coastguard Worker Remarks: 966*b9df5ad1SAndroid Build Coastguard Worker This operation is not recursive. To combine the grandchildren and other 967*b9df5ad1SAndroid Build Coastguard Worker ancestors, call this method on the ancestor nodes. 968*b9df5ad1SAndroid Build Coastguard Worker """ 969*b9df5ad1SAndroid Build Coastguard Worker return Kind._combine_children_by_name(self, new_type=type(self)) 970*b9df5ad1SAndroid Build Coastguard Worker 971*b9df5ad1SAndroid Build Coastguard Workerclass EnumValue(Node): 972*b9df5ad1SAndroid Build Coastguard Worker """ 973*b9df5ad1SAndroid Build Coastguard Worker A class corresponding to a <value> element within an <enum> within an <entry>. 974*b9df5ad1SAndroid Build Coastguard Worker 975*b9df5ad1SAndroid Build Coastguard Worker Attributes (Read-Only): 976*b9df5ad1SAndroid Build Coastguard Worker name: A string, e.g. 'ON' or 'OFF' 977*b9df5ad1SAndroid Build Coastguard Worker id: An optional numeric string, e.g. '0' or '0xFF' 978*b9df5ad1SAndroid Build Coastguard Worker deprecated: A boolean, True if the enum should be deprecated. 979*b9df5ad1SAndroid Build Coastguard Worker optional: A boolean 980*b9df5ad1SAndroid Build Coastguard Worker visibility: A string, one of "system", "java_public", "ndk_public", "hidden", "public", 981*b9df5ad1SAndroid Build Coastguard Worker "fwk_java_public", "fwk_public", "fwk_ndk_public", "extension", "fwk_system_public" 982*b9df5ad1SAndroid Build Coastguard Worker notes: A string describing the notes, or None. 983*b9df5ad1SAndroid Build Coastguard Worker sdk_notes: A string describing extra notes for public SDK only 984*b9df5ad1SAndroid Build Coastguard Worker ndk_notes: A string describing extra notes for public NDK only 985*b9df5ad1SAndroid Build Coastguard Worker parent: An edge to the parent, always an Enum instance. 986*b9df5ad1SAndroid Build Coastguard Worker hal_major_version: The major HIDL HAL version this value was first added in 987*b9df5ad1SAndroid Build Coastguard Worker hal_minor_version: The minor HIDL HAL version this value was first added in 988*b9df5ad1SAndroid Build Coastguard Worker aconfig_flag: The aconfig flag name that determines if this enum value is actually enabled 989*b9df5ad1SAndroid Build Coastguard Worker """ 990*b9df5ad1SAndroid Build Coastguard Worker def __init__(self, name, parent, 991*b9df5ad1SAndroid Build Coastguard Worker id=None, deprecated=False, optional=False, visibility=None, notes=None, 992*b9df5ad1SAndroid Build Coastguard Worker sdk_notes=None, ndk_notes=None, hal_version='3.2', aconfig_flag=None): 993*b9df5ad1SAndroid Build Coastguard Worker self._name = name # str, e.g. 'ON' or 'OFF' 994*b9df5ad1SAndroid Build Coastguard Worker self._id = id # int, e.g. '0' 995*b9df5ad1SAndroid Build Coastguard Worker self._deprecated = deprecated # bool 996*b9df5ad1SAndroid Build Coastguard Worker self._optional = optional # bool 997*b9df5ad1SAndroid Build Coastguard Worker self._visibility = visibility # None or str; None is same as public 998*b9df5ad1SAndroid Build Coastguard Worker self._notes = notes # None or str 999*b9df5ad1SAndroid Build Coastguard Worker self._sdk_notes = sdk_notes # None or str 1000*b9df5ad1SAndroid Build Coastguard Worker self._ndk_notes = ndk_notes # None or str 1001*b9df5ad1SAndroid Build Coastguard Worker self._parent = parent 1002*b9df5ad1SAndroid Build Coastguard Worker if hal_version is None: 1003*b9df5ad1SAndroid Build Coastguard Worker if parent is not None and parent.parent is not None: 1004*b9df5ad1SAndroid Build Coastguard Worker self._hal_major_version = parent.parent.hal_major_version 1005*b9df5ad1SAndroid Build Coastguard Worker self._hal_minor_version = parent.parent.hal_minor_version 1006*b9df5ad1SAndroid Build Coastguard Worker else: 1007*b9df5ad1SAndroid Build Coastguard Worker self._hal_major_version = 3 1008*b9df5ad1SAndroid Build Coastguard Worker self._hal_minor_version = 2 1009*b9df5ad1SAndroid Build Coastguard Worker else: 1010*b9df5ad1SAndroid Build Coastguard Worker self._hal_major_version = int(hal_version.partition('.')[0]) 1011*b9df5ad1SAndroid Build Coastguard Worker self._hal_minor_version = int(hal_version.partition('.')[2]) 1012*b9df5ad1SAndroid Build Coastguard Worker 1013*b9df5ad1SAndroid Build Coastguard Worker self._aconfig_flag = aconfig_flag 1014*b9df5ad1SAndroid Build Coastguard Worker if self._aconfig_flag is None: 1015*b9df5ad1SAndroid Build Coastguard Worker if parent is not None and parent.parent is not None: 1016*b9df5ad1SAndroid Build Coastguard Worker self._aconfig_flag = parent.parent.aconfig_flag 1017*b9df5ad1SAndroid Build Coastguard Worker 1018*b9df5ad1SAndroid Build Coastguard Worker @property 1019*b9df5ad1SAndroid Build Coastguard Worker def id(self): 1020*b9df5ad1SAndroid Build Coastguard Worker return self._id 1021*b9df5ad1SAndroid Build Coastguard Worker 1022*b9df5ad1SAndroid Build Coastguard Worker @property 1023*b9df5ad1SAndroid Build Coastguard Worker def deprecated(self): 1024*b9df5ad1SAndroid Build Coastguard Worker return self._deprecated 1025*b9df5ad1SAndroid Build Coastguard Worker 1026*b9df5ad1SAndroid Build Coastguard Worker @property 1027*b9df5ad1SAndroid Build Coastguard Worker def optional(self): 1028*b9df5ad1SAndroid Build Coastguard Worker return self._optional 1029*b9df5ad1SAndroid Build Coastguard Worker 1030*b9df5ad1SAndroid Build Coastguard Worker @property 1031*b9df5ad1SAndroid Build Coastguard Worker def visibility(self): 1032*b9df5ad1SAndroid Build Coastguard Worker return self._visibility 1033*b9df5ad1SAndroid Build Coastguard Worker 1034*b9df5ad1SAndroid Build Coastguard Worker @property 1035*b9df5ad1SAndroid Build Coastguard Worker def applied_visibility(self): 1036*b9df5ad1SAndroid Build Coastguard Worker return self._visibility or 'public' 1037*b9df5ad1SAndroid Build Coastguard Worker 1038*b9df5ad1SAndroid Build Coastguard Worker @property 1039*b9df5ad1SAndroid Build Coastguard Worker def hidl_comment_string(self): 1040*b9df5ad1SAndroid Build Coastguard Worker parent_enum = None 1041*b9df5ad1SAndroid Build Coastguard Worker if (self.parent is not None and self.parent.parent is not None): 1042*b9df5ad1SAndroid Build Coastguard Worker parent_enum = self.parent.parent 1043*b9df5ad1SAndroid Build Coastguard Worker if parent_enum is not None and parent_enum.visibility in ('fwk_only', 'fwk_java_public',\ 1044*b9df5ad1SAndroid Build Coastguard Worker 'fwk_public', 'fwk_ndk_public') or self._visibility in ('fwk_only', 'fwk_java_public',\ 1045*b9df5ad1SAndroid Build Coastguard Worker 'fwk_public', 'fwk_ndk_public'): 1046*b9df5ad1SAndroid Build Coastguard Worker return ',' 1047*b9df5ad1SAndroid Build Coastguard Worker return ', // HIDL v' + str(self._hal_major_version) + '.' + str(self.hal_minor_version) 1048*b9df5ad1SAndroid Build Coastguard Worker 1049*b9df5ad1SAndroid Build Coastguard Worker @property 1050*b9df5ad1SAndroid Build Coastguard Worker def hidden(self): 1051*b9df5ad1SAndroid Build Coastguard Worker return self.visibility in {'hidden', 'ndk_public', 'test', 'extension', 'fwk_system_public'} 1052*b9df5ad1SAndroid Build Coastguard Worker 1053*b9df5ad1SAndroid Build Coastguard Worker @property 1054*b9df5ad1SAndroid Build Coastguard Worker def ndk_hidden(self): 1055*b9df5ad1SAndroid Build Coastguard Worker return self._visibility in {'hidden', 'java_public', 'test'} 1056*b9df5ad1SAndroid Build Coastguard Worker 1057*b9df5ad1SAndroid Build Coastguard Worker @property 1058*b9df5ad1SAndroid Build Coastguard Worker def notes(self): 1059*b9df5ad1SAndroid Build Coastguard Worker return self._notes 1060*b9df5ad1SAndroid Build Coastguard Worker 1061*b9df5ad1SAndroid Build Coastguard Worker @property 1062*b9df5ad1SAndroid Build Coastguard Worker def sdk_notes(self): 1063*b9df5ad1SAndroid Build Coastguard Worker return self._sdk_notes 1064*b9df5ad1SAndroid Build Coastguard Worker 1065*b9df5ad1SAndroid Build Coastguard Worker @property 1066*b9df5ad1SAndroid Build Coastguard Worker def ndk_notes(self): 1067*b9df5ad1SAndroid Build Coastguard Worker return self._ndk_notes 1068*b9df5ad1SAndroid Build Coastguard Worker 1069*b9df5ad1SAndroid Build Coastguard Worker @property 1070*b9df5ad1SAndroid Build Coastguard Worker def hal_major_version(self): 1071*b9df5ad1SAndroid Build Coastguard Worker return self._hal_major_version 1072*b9df5ad1SAndroid Build Coastguard Worker 1073*b9df5ad1SAndroid Build Coastguard Worker @property 1074*b9df5ad1SAndroid Build Coastguard Worker def hal_minor_version(self): 1075*b9df5ad1SAndroid Build Coastguard Worker return self._hal_minor_version 1076*b9df5ad1SAndroid Build Coastguard Worker 1077*b9df5ad1SAndroid Build Coastguard Worker @property 1078*b9df5ad1SAndroid Build Coastguard Worker def aconfig_flag(self): 1079*b9df5ad1SAndroid Build Coastguard Worker return self._aconfig_flag 1080*b9df5ad1SAndroid Build Coastguard Worker 1081*b9df5ad1SAndroid Build Coastguard Worker def _get_children(self): 1082*b9df5ad1SAndroid Build Coastguard Worker return None 1083*b9df5ad1SAndroid Build Coastguard Worker 1084*b9df5ad1SAndroid Build Coastguard Workerclass Enum(Node): 1085*b9df5ad1SAndroid Build Coastguard Worker """ 1086*b9df5ad1SAndroid Build Coastguard Worker A class corresponding to an <enum> element within an <entry>. 1087*b9df5ad1SAndroid Build Coastguard Worker 1088*b9df5ad1SAndroid Build Coastguard Worker Attributes (Read-Only): 1089*b9df5ad1SAndroid Build Coastguard Worker parent: An edge to the parent, always an Entry instance. 1090*b9df5ad1SAndroid Build Coastguard Worker values: A sequence of EnumValue children. 1091*b9df5ad1SAndroid Build Coastguard Worker has_values_with_id: A boolean representing if any of the children have a 1092*b9df5ad1SAndroid Build Coastguard Worker non-empty id property. 1093*b9df5ad1SAndroid Build Coastguard Worker """ 1094*b9df5ad1SAndroid Build Coastguard Worker def __init__(self, parent, values, ids={}, deprecateds=[], 1095*b9df5ad1SAndroid Build Coastguard Worker optionals=[], visibilities={}, notes={}, sdk_notes={}, ndk_notes={}, 1096*b9df5ad1SAndroid Build Coastguard Worker hal_versions={}, aconfig_flags={}): 1097*b9df5ad1SAndroid Build Coastguard Worker self._parent = parent 1098*b9df5ad1SAndroid Build Coastguard Worker self._name = None 1099*b9df5ad1SAndroid Build Coastguard Worker self._values = \ 1100*b9df5ad1SAndroid Build Coastguard Worker [ EnumValue(val, self, ids.get(val), val in deprecateds, val in optionals, visibilities.get(val), \ 1101*b9df5ad1SAndroid Build Coastguard Worker notes.get(val), sdk_notes.get(val), ndk_notes.get(val), hal_versions.get(val), \ 1102*b9df5ad1SAndroid Build Coastguard Worker aconfig_flags.get(val)) \ 1103*b9df5ad1SAndroid Build Coastguard Worker for val in values ] 1104*b9df5ad1SAndroid Build Coastguard Worker 1105*b9df5ad1SAndroid Build Coastguard Worker @property 1106*b9df5ad1SAndroid Build Coastguard Worker def values(self): 1107*b9df5ad1SAndroid Build Coastguard Worker return (i for i in self._values) 1108*b9df5ad1SAndroid Build Coastguard Worker 1109*b9df5ad1SAndroid Build Coastguard Worker @property 1110*b9df5ad1SAndroid Build Coastguard Worker def has_values_with_id(self): 1111*b9df5ad1SAndroid Build Coastguard Worker return bool(any(i for i in self.values if i.id)) 1112*b9df5ad1SAndroid Build Coastguard Worker 1113*b9df5ad1SAndroid Build Coastguard Worker def has_new_values_added_in_hal_version(self, hal_major_version, hal_minor_version): 1114*b9df5ad1SAndroid Build Coastguard Worker return bool(any(i for i in self.values if i.hal_major_version == hal_major_version and i.hal_minor_version == hal_minor_version)) 1115*b9df5ad1SAndroid Build Coastguard Worker 1116*b9df5ad1SAndroid Build Coastguard Worker def _get_children(self): 1117*b9df5ad1SAndroid Build Coastguard Worker return (i for i in self._values) 1118*b9df5ad1SAndroid Build Coastguard Worker 1119*b9df5ad1SAndroid Build Coastguard Workerclass Entry(Node): 1120*b9df5ad1SAndroid Build Coastguard Worker """ 1121*b9df5ad1SAndroid Build Coastguard Worker A node corresponding to an <entry> element. 1122*b9df5ad1SAndroid Build Coastguard Worker 1123*b9df5ad1SAndroid Build Coastguard Worker Attributes (Read-Only): 1124*b9df5ad1SAndroid Build Coastguard Worker parent: An edge to the parent node, which is an InnerNamespace or Kind. 1125*b9df5ad1SAndroid Build Coastguard Worker name: The fully qualified name string, e.g. 'android.shading.mode' 1126*b9df5ad1SAndroid Build Coastguard Worker name_short: The name attribute from <entry name="mode">, e.g. mode 1127*b9df5ad1SAndroid Build Coastguard Worker type: The type attribute from <entry type="bar"> 1128*b9df5ad1SAndroid Build Coastguard Worker kind: A string ('static', 'dynamic', 'controls') corresponding to the 1129*b9df5ad1SAndroid Build Coastguard Worker ancestor Kind#name 1130*b9df5ad1SAndroid Build Coastguard Worker container: The container attribute from <entry container="array">, or None. 1131*b9df5ad1SAndroid Build Coastguard Worker container_sizes: A sequence of size strings or None if container is None. 1132*b9df5ad1SAndroid Build Coastguard Worker enum: An Enum instance if the enum attribute is true, None otherwise. 1133*b9df5ad1SAndroid Build Coastguard Worker visibility: The visibility of this entry ('system', 'hidden', 'public' etc) 1134*b9df5ad1SAndroid Build Coastguard Worker across the system. System entries are only visible in native code 1135*b9df5ad1SAndroid Build Coastguard Worker headers. Hidden entries are marked @hide in managed code, while 1136*b9df5ad1SAndroid Build Coastguard Worker public entries are visible in the Android SDK. 1137*b9df5ad1SAndroid Build Coastguard Worker applied_visibility: As visibility, but always valid, defaulting to 'system' 1138*b9df5ad1SAndroid Build Coastguard Worker if no visibility is given for an entry. 1139*b9df5ad1SAndroid Build Coastguard Worker applied_ndk_visible: Always valid. Default is 'false'. 1140*b9df5ad1SAndroid Build Coastguard Worker Set to 'true' when the visibility implied entry is visible 1141*b9df5ad1SAndroid Build Coastguard Worker in NDK. 1142*b9df5ad1SAndroid Build Coastguard Worker synthetic: The C-level visibility of this entry ('false', 'true'). 1143*b9df5ad1SAndroid Build Coastguard Worker Synthetic entries will not be generated into the native metadata 1144*b9df5ad1SAndroid Build Coastguard Worker list of entries (in C code). In general a synthetic entry is 1145*b9df5ad1SAndroid Build Coastguard Worker glued together at the Java layer from multiple visibiltity=hidden 1146*b9df5ad1SAndroid Build Coastguard Worker entries. 1147*b9df5ad1SAndroid Build Coastguard Worker hwlevel: The lowest hardware level at which the entry is guaranteed 1148*b9df5ad1SAndroid Build Coastguard Worker to be supported by the camera device. All devices with higher 1149*b9df5ad1SAndroid Build Coastguard Worker hwlevels will also include this entry. None means that the 1150*b9df5ad1SAndroid Build Coastguard Worker entry is optional on any hardware level. 1151*b9df5ad1SAndroid Build Coastguard Worker permission_needed: Flags whether the tag needs extra camera permission. 1152*b9df5ad1SAndroid Build Coastguard Worker aconfig_flag: The aconfig flag name that determines if the entry is actually enabled 1153*b9df5ad1SAndroid Build Coastguard Worker deprecated: Marks an entry as @Deprecated in the Java layer; if within an 1154*b9df5ad1SAndroid Build Coastguard Worker unreleased version this needs to be removed altogether. If applied 1155*b9df5ad1SAndroid Build Coastguard Worker to an entry from an older release, then this means the entry 1156*b9df5ad1SAndroid Build Coastguard Worker should be ignored by newer code. 1157*b9df5ad1SAndroid Build Coastguard Worker optional: a bool representing the optional attribute, which denotes the entry 1158*b9df5ad1SAndroid Build Coastguard Worker is required for hardware level full devices, but optional for other 1159*b9df5ad1SAndroid Build Coastguard Worker hardware levels. None if not present. 1160*b9df5ad1SAndroid Build Coastguard Worker applied_optional: As optional but always valid, defaulting to False if no 1161*b9df5ad1SAndroid Build Coastguard Worker optional attribute is present. 1162*b9df5ad1SAndroid Build Coastguard Worker tuple_values: A sequence of strings describing the tuple values, 1163*b9df5ad1SAndroid Build Coastguard Worker None if container is not 'tuple'. 1164*b9df5ad1SAndroid Build Coastguard Worker description: A string description, or None. 1165*b9df5ad1SAndroid Build Coastguard Worker deprecation_description: A string describing the reason for deprecation. Must be present 1166*b9df5ad1SAndroid Build Coastguard Worker if deprecated is true, otherwise may be None. 1167*b9df5ad1SAndroid Build Coastguard Worker range: A string range, or None. 1168*b9df5ad1SAndroid Build Coastguard Worker units: A string units, or None. 1169*b9df5ad1SAndroid Build Coastguard Worker tags: A sequence of Tag nodes associated with this Entry. 1170*b9df5ad1SAndroid Build Coastguard Worker type_notes: A string describing notes for the type, or None. 1171*b9df5ad1SAndroid Build Coastguard Worker typedef: A Typedef associated with this Entry, or None. 1172*b9df5ad1SAndroid Build Coastguard Worker 1173*b9df5ad1SAndroid Build Coastguard Worker Remarks: 1174*b9df5ad1SAndroid Build Coastguard Worker Subclass Clone can be used interchangeable with an Entry, 1175*b9df5ad1SAndroid Build Coastguard Worker for when we don't care about the underlying type. 1176*b9df5ad1SAndroid Build Coastguard Worker 1177*b9df5ad1SAndroid Build Coastguard Worker parent and tags edges are invalid until after Metadata#construct_graph 1178*b9df5ad1SAndroid Build Coastguard Worker has been invoked. 1179*b9df5ad1SAndroid Build Coastguard Worker """ 1180*b9df5ad1SAndroid Build Coastguard Worker def __init__(self, **kwargs): 1181*b9df5ad1SAndroid Build Coastguard Worker """ 1182*b9df5ad1SAndroid Build Coastguard Worker Instantiate a new Entry node. 1183*b9df5ad1SAndroid Build Coastguard Worker 1184*b9df5ad1SAndroid Build Coastguard Worker Args: 1185*b9df5ad1SAndroid Build Coastguard Worker name: A string with the fully qualified name, e.g. 'android.shading.mode' 1186*b9df5ad1SAndroid Build Coastguard Worker type: A string describing the type, e.g. 'int32' 1187*b9df5ad1SAndroid Build Coastguard Worker kind: A string describing the kind, e.g. 'static' 1188*b9df5ad1SAndroid Build Coastguard Worker hal_version: A string for the initial HIDL HAL metadata version this entry 1189*b9df5ad1SAndroid Build Coastguard Worker was added in 1190*b9df5ad1SAndroid Build Coastguard Worker 1191*b9df5ad1SAndroid Build Coastguard Worker Args (if container): 1192*b9df5ad1SAndroid Build Coastguard Worker container: A string describing the container, e.g. 'array' or 'tuple' 1193*b9df5ad1SAndroid Build Coastguard Worker container_sizes: A list of string sizes if a container, or None otherwise 1194*b9df5ad1SAndroid Build Coastguard Worker 1195*b9df5ad1SAndroid Build Coastguard Worker Args (if container is 'tuple'): 1196*b9df5ad1SAndroid Build Coastguard Worker tuple_values: A list of tuple values, e.g. ['width', 'height'] 1197*b9df5ad1SAndroid Build Coastguard Worker 1198*b9df5ad1SAndroid Build Coastguard Worker Args (if the 'enum' attribute is true): 1199*b9df5ad1SAndroid Build Coastguard Worker enum: A boolean, True if this is an enum, False otherwise 1200*b9df5ad1SAndroid Build Coastguard Worker enum_values: A list of value strings, e.g. ['ON', 'OFF'] 1201*b9df5ad1SAndroid Build Coastguard Worker enum_optionals: A list of optional enum values, e.g. ['OFF'] 1202*b9df5ad1SAndroid Build Coastguard Worker enum_notes: A dictionary of value->notes strings. 1203*b9df5ad1SAndroid Build Coastguard Worker enum_ids: A dictionary of value->id strings. 1204*b9df5ad1SAndroid Build Coastguard Worker enum_hal_versions: A dictionary of value->hal version strings 1205*b9df5ad1SAndroid Build Coastguard Worker enum_aconfig_flags: A dictionary of value->aconfig flag name strings 1206*b9df5ad1SAndroid Build Coastguard Worker 1207*b9df5ad1SAndroid Build Coastguard Worker Args (if the 'deprecated' attribute is true): 1208*b9df5ad1SAndroid Build Coastguard Worker deprecation_description: A string explaining the deprecation, to be added 1209*b9df5ad1SAndroid Build Coastguard Worker to the Java-layer @deprecated tag 1210*b9df5ad1SAndroid Build Coastguard Worker 1211*b9df5ad1SAndroid Build Coastguard Worker Args (optional): 1212*b9df5ad1SAndroid Build Coastguard Worker description: A string with a description of the entry. 1213*b9df5ad1SAndroid Build Coastguard Worker range: A string with the range of the values of the entry, e.g. '>= 0' 1214*b9df5ad1SAndroid Build Coastguard Worker units: A string with the units of the values, e.g. 'inches' 1215*b9df5ad1SAndroid Build Coastguard Worker details: A string with the detailed documentation for the entry 1216*b9df5ad1SAndroid Build Coastguard Worker hal_details: A string with the HAL implementation details for the entry 1217*b9df5ad1SAndroid Build Coastguard Worker ndk_details: A string with the extra NDK API documentation for the entry= 1218*b9df5ad1SAndroid Build Coastguard Worker tag_ids: A list of tag ID strings, e.g. ['BC', 'V1'] 1219*b9df5ad1SAndroid Build Coastguard Worker type_notes: A string with the notes for the type 1220*b9df5ad1SAndroid Build Coastguard Worker visibility: A string describing the visibility, eg 'system', 'hidden', 1221*b9df5ad1SAndroid Build Coastguard Worker 'public' 1222*b9df5ad1SAndroid Build Coastguard Worker synthetic: A bool to mark whether this entry is visible only at the Java 1223*b9df5ad1SAndroid Build Coastguard Worker layer (True), or at both layers (False = default). 1224*b9df5ad1SAndroid Build Coastguard Worker hwlevel: A string of the HW level (one of 'legacy', 'limited', 'full') 1225*b9df5ad1SAndroid Build Coastguard Worker deprecated: A bool to mark whether this is @Deprecated at the Java layer 1226*b9df5ad1SAndroid Build Coastguard Worker (default = False). 1227*b9df5ad1SAndroid Build Coastguard Worker optional: A bool to mark whether optional for non-full hardware devices 1228*b9df5ad1SAndroid Build Coastguard Worker typedef: A string corresponding to a typedef's name attribute. 1229*b9df5ad1SAndroid Build Coastguard Worker """ 1230*b9df5ad1SAndroid Build Coastguard Worker 1231*b9df5ad1SAndroid Build Coastguard Worker if kwargs.get('type') is None: 1232*b9df5ad1SAndroid Build Coastguard Worker print("ERROR: Missing type for entry '%s' kind '%s'" 1233*b9df5ad1SAndroid Build Coastguard Worker % (kwargs.get('name'), kwargs.get('kind')), file=sys.stderr) 1234*b9df5ad1SAndroid Build Coastguard Worker 1235*b9df5ad1SAndroid Build Coastguard Worker # Attributes are Read-Only, but edges may be mutated by 1236*b9df5ad1SAndroid Build Coastguard Worker # Metadata, particularly during construct_graph 1237*b9df5ad1SAndroid Build Coastguard Worker 1238*b9df5ad1SAndroid Build Coastguard Worker self._name = kwargs['name'] 1239*b9df5ad1SAndroid Build Coastguard Worker self._type = kwargs['type'] 1240*b9df5ad1SAndroid Build Coastguard Worker self._kind = kwargs['kind'] # static, dynamic, or controls 1241*b9df5ad1SAndroid Build Coastguard Worker 1242*b9df5ad1SAndroid Build Coastguard Worker self._init_common(**kwargs) 1243*b9df5ad1SAndroid Build Coastguard Worker 1244*b9df5ad1SAndroid Build Coastguard Worker @property 1245*b9df5ad1SAndroid Build Coastguard Worker def type(self): 1246*b9df5ad1SAndroid Build Coastguard Worker return self._type 1247*b9df5ad1SAndroid Build Coastguard Worker 1248*b9df5ad1SAndroid Build Coastguard Worker @property 1249*b9df5ad1SAndroid Build Coastguard Worker def kind(self): 1250*b9df5ad1SAndroid Build Coastguard Worker return self._kind 1251*b9df5ad1SAndroid Build Coastguard Worker 1252*b9df5ad1SAndroid Build Coastguard Worker @property 1253*b9df5ad1SAndroid Build Coastguard Worker def hal_major_version(self): 1254*b9df5ad1SAndroid Build Coastguard Worker return self._hal_major_version 1255*b9df5ad1SAndroid Build Coastguard Worker 1256*b9df5ad1SAndroid Build Coastguard Worker @property 1257*b9df5ad1SAndroid Build Coastguard Worker def hal_minor_version(self): 1258*b9df5ad1SAndroid Build Coastguard Worker return self._hal_minor_version 1259*b9df5ad1SAndroid Build Coastguard Worker 1260*b9df5ad1SAndroid Build Coastguard Worker @property 1261*b9df5ad1SAndroid Build Coastguard Worker def visibility(self): 1262*b9df5ad1SAndroid Build Coastguard Worker return self._visibility 1263*b9df5ad1SAndroid Build Coastguard Worker 1264*b9df5ad1SAndroid Build Coastguard Worker @property 1265*b9df5ad1SAndroid Build Coastguard Worker def applied_visibility(self): 1266*b9df5ad1SAndroid Build Coastguard Worker return self._visibility or 'system' 1267*b9df5ad1SAndroid Build Coastguard Worker 1268*b9df5ad1SAndroid Build Coastguard Worker @property 1269*b9df5ad1SAndroid Build Coastguard Worker def hidl_comment_string(self): 1270*b9df5ad1SAndroid Build Coastguard Worker if self._visibility in ('fwk_only', 'fwk_java_public', 'fwk_public', 'fwk_ndk_public'): 1271*b9df5ad1SAndroid Build Coastguard Worker return self._visibility 1272*b9df5ad1SAndroid Build Coastguard Worker visibility_lj = str(self.applied_visibility).ljust(12) 1273*b9df5ad1SAndroid Build Coastguard Worker return visibility_lj + ' | HIDL v' + str(self._hal_major_version) + '.' + str(self._hal_minor_version) 1274*b9df5ad1SAndroid Build Coastguard Worker 1275*b9df5ad1SAndroid Build Coastguard Worker @property 1276*b9df5ad1SAndroid Build Coastguard Worker def applied_ndk_visible(self): 1277*b9df5ad1SAndroid Build Coastguard Worker if self._visibility in ("public", "ndk_public", "fwk_public", "fwk_ndk_public"): 1278*b9df5ad1SAndroid Build Coastguard Worker return "true" 1279*b9df5ad1SAndroid Build Coastguard Worker return "false" 1280*b9df5ad1SAndroid Build Coastguard Worker 1281*b9df5ad1SAndroid Build Coastguard Worker @property 1282*b9df5ad1SAndroid Build Coastguard Worker def synthetic(self): 1283*b9df5ad1SAndroid Build Coastguard Worker return self._synthetic 1284*b9df5ad1SAndroid Build Coastguard Worker 1285*b9df5ad1SAndroid Build Coastguard Worker @property 1286*b9df5ad1SAndroid Build Coastguard Worker def hwlevel(self): 1287*b9df5ad1SAndroid Build Coastguard Worker return self._hwlevel 1288*b9df5ad1SAndroid Build Coastguard Worker 1289*b9df5ad1SAndroid Build Coastguard Worker @property 1290*b9df5ad1SAndroid Build Coastguard Worker def deprecated(self): 1291*b9df5ad1SAndroid Build Coastguard Worker return self._deprecated 1292*b9df5ad1SAndroid Build Coastguard Worker 1293*b9df5ad1SAndroid Build Coastguard Worker @property 1294*b9df5ad1SAndroid Build Coastguard Worker def deprecation_description(self): 1295*b9df5ad1SAndroid Build Coastguard Worker return self._deprecation_description 1296*b9df5ad1SAndroid Build Coastguard Worker 1297*b9df5ad1SAndroid Build Coastguard Worker @property 1298*b9df5ad1SAndroid Build Coastguard Worker def permission_needed(self): 1299*b9df5ad1SAndroid Build Coastguard Worker return self._permission_needed or "false" 1300*b9df5ad1SAndroid Build Coastguard Worker 1301*b9df5ad1SAndroid Build Coastguard Worker @property 1302*b9df5ad1SAndroid Build Coastguard Worker def aconfig_flag(self): 1303*b9df5ad1SAndroid Build Coastguard Worker return self._aconfig_flag 1304*b9df5ad1SAndroid Build Coastguard Worker 1305*b9df5ad1SAndroid Build Coastguard Worker # TODO: optional should just return hwlevel is None 1306*b9df5ad1SAndroid Build Coastguard Worker @property 1307*b9df5ad1SAndroid Build Coastguard Worker def optional(self): 1308*b9df5ad1SAndroid Build Coastguard Worker return self._optional 1309*b9df5ad1SAndroid Build Coastguard Worker 1310*b9df5ad1SAndroid Build Coastguard Worker @property 1311*b9df5ad1SAndroid Build Coastguard Worker def applied_optional(self): 1312*b9df5ad1SAndroid Build Coastguard Worker return self._optional or False 1313*b9df5ad1SAndroid Build Coastguard Worker 1314*b9df5ad1SAndroid Build Coastguard Worker @property 1315*b9df5ad1SAndroid Build Coastguard Worker def name_short(self): 1316*b9df5ad1SAndroid Build Coastguard Worker return self.get_name_minimal() 1317*b9df5ad1SAndroid Build Coastguard Worker 1318*b9df5ad1SAndroid Build Coastguard Worker @property 1319*b9df5ad1SAndroid Build Coastguard Worker def container(self): 1320*b9df5ad1SAndroid Build Coastguard Worker return self._container 1321*b9df5ad1SAndroid Build Coastguard Worker 1322*b9df5ad1SAndroid Build Coastguard Worker @property 1323*b9df5ad1SAndroid Build Coastguard Worker def container_sizes(self): 1324*b9df5ad1SAndroid Build Coastguard Worker if self._container_sizes is None: 1325*b9df5ad1SAndroid Build Coastguard Worker return None 1326*b9df5ad1SAndroid Build Coastguard Worker else: 1327*b9df5ad1SAndroid Build Coastguard Worker return (i for i in self._container_sizes) 1328*b9df5ad1SAndroid Build Coastguard Worker 1329*b9df5ad1SAndroid Build Coastguard Worker @property 1330*b9df5ad1SAndroid Build Coastguard Worker def tuple_values(self): 1331*b9df5ad1SAndroid Build Coastguard Worker if self._tuple_values is None: 1332*b9df5ad1SAndroid Build Coastguard Worker return None 1333*b9df5ad1SAndroid Build Coastguard Worker else: 1334*b9df5ad1SAndroid Build Coastguard Worker return (i for i in self._tuple_values) 1335*b9df5ad1SAndroid Build Coastguard Worker 1336*b9df5ad1SAndroid Build Coastguard Worker @property 1337*b9df5ad1SAndroid Build Coastguard Worker def description(self): 1338*b9df5ad1SAndroid Build Coastguard Worker return self._description 1339*b9df5ad1SAndroid Build Coastguard Worker 1340*b9df5ad1SAndroid Build Coastguard Worker @property 1341*b9df5ad1SAndroid Build Coastguard Worker def range(self): 1342*b9df5ad1SAndroid Build Coastguard Worker return self._range 1343*b9df5ad1SAndroid Build Coastguard Worker 1344*b9df5ad1SAndroid Build Coastguard Worker @property 1345*b9df5ad1SAndroid Build Coastguard Worker def units(self): 1346*b9df5ad1SAndroid Build Coastguard Worker return self._units 1347*b9df5ad1SAndroid Build Coastguard Worker 1348*b9df5ad1SAndroid Build Coastguard Worker @property 1349*b9df5ad1SAndroid Build Coastguard Worker def details(self): 1350*b9df5ad1SAndroid Build Coastguard Worker return self._details 1351*b9df5ad1SAndroid Build Coastguard Worker 1352*b9df5ad1SAndroid Build Coastguard Worker @property 1353*b9df5ad1SAndroid Build Coastguard Worker def hal_details(self): 1354*b9df5ad1SAndroid Build Coastguard Worker return self._hal_details 1355*b9df5ad1SAndroid Build Coastguard Worker 1356*b9df5ad1SAndroid Build Coastguard Worker @property 1357*b9df5ad1SAndroid Build Coastguard Worker def ndk_details(self): 1358*b9df5ad1SAndroid Build Coastguard Worker return self._ndk_details 1359*b9df5ad1SAndroid Build Coastguard Worker 1360*b9df5ad1SAndroid Build Coastguard Worker @property 1361*b9df5ad1SAndroid Build Coastguard Worker def applied_ndk_details(self): 1362*b9df5ad1SAndroid Build Coastguard Worker return (self._details or "") + (self._ndk_details or "") 1363*b9df5ad1SAndroid Build Coastguard Worker 1364*b9df5ad1SAndroid Build Coastguard Worker @property 1365*b9df5ad1SAndroid Build Coastguard Worker def tags(self): 1366*b9df5ad1SAndroid Build Coastguard Worker if self._tags is None: 1367*b9df5ad1SAndroid Build Coastguard Worker return None 1368*b9df5ad1SAndroid Build Coastguard Worker else: 1369*b9df5ad1SAndroid Build Coastguard Worker return (i for i in self._tags) 1370*b9df5ad1SAndroid Build Coastguard Worker 1371*b9df5ad1SAndroid Build Coastguard Worker @property 1372*b9df5ad1SAndroid Build Coastguard Worker def type_notes(self): 1373*b9df5ad1SAndroid Build Coastguard Worker return self._type_notes 1374*b9df5ad1SAndroid Build Coastguard Worker 1375*b9df5ad1SAndroid Build Coastguard Worker @property 1376*b9df5ad1SAndroid Build Coastguard Worker def typedef(self): 1377*b9df5ad1SAndroid Build Coastguard Worker return self._typedef 1378*b9df5ad1SAndroid Build Coastguard Worker 1379*b9df5ad1SAndroid Build Coastguard Worker @property 1380*b9df5ad1SAndroid Build Coastguard Worker def enum(self): 1381*b9df5ad1SAndroid Build Coastguard Worker return self._enum 1382*b9df5ad1SAndroid Build Coastguard Worker 1383*b9df5ad1SAndroid Build Coastguard Worker @property 1384*b9df5ad1SAndroid Build Coastguard Worker def session_characteristics_key_since(self): 1385*b9df5ad1SAndroid Build Coastguard Worker return self._session_characteristics_key_since 1386*b9df5ad1SAndroid Build Coastguard Worker 1387*b9df5ad1SAndroid Build Coastguard Worker def has_new_values_added_in_hal_version(self, hal_major_version, hal_minor_version): 1388*b9df5ad1SAndroid Build Coastguard Worker if self._enum is not None: 1389*b9df5ad1SAndroid Build Coastguard Worker return self._enum.has_new_values_added_in_hal_version(hal_major_version,hal_minor_version) 1390*b9df5ad1SAndroid Build Coastguard Worker else: 1391*b9df5ad1SAndroid Build Coastguard Worker return False 1392*b9df5ad1SAndroid Build Coastguard Worker 1393*b9df5ad1SAndroid Build Coastguard Worker def _get_children(self): 1394*b9df5ad1SAndroid Build Coastguard Worker if self.enum: 1395*b9df5ad1SAndroid Build Coastguard Worker yield self.enum 1396*b9df5ad1SAndroid Build Coastguard Worker 1397*b9df5ad1SAndroid Build Coastguard Worker def sort_children(self): 1398*b9df5ad1SAndroid Build Coastguard Worker return None 1399*b9df5ad1SAndroid Build Coastguard Worker 1400*b9df5ad1SAndroid Build Coastguard Worker def is_clone(self): 1401*b9df5ad1SAndroid Build Coastguard Worker """ 1402*b9df5ad1SAndroid Build Coastguard Worker Whether or not this is a Clone instance. 1403*b9df5ad1SAndroid Build Coastguard Worker 1404*b9df5ad1SAndroid Build Coastguard Worker Returns: 1405*b9df5ad1SAndroid Build Coastguard Worker False 1406*b9df5ad1SAndroid Build Coastguard Worker """ 1407*b9df5ad1SAndroid Build Coastguard Worker return False 1408*b9df5ad1SAndroid Build Coastguard Worker 1409*b9df5ad1SAndroid Build Coastguard Worker def _init_common(self, **kwargs): 1410*b9df5ad1SAndroid Build Coastguard Worker 1411*b9df5ad1SAndroid Build Coastguard Worker self._parent = None # filled in by Metadata::_construct_entries 1412*b9df5ad1SAndroid Build Coastguard Worker 1413*b9df5ad1SAndroid Build Coastguard Worker self._container = kwargs.get('container') 1414*b9df5ad1SAndroid Build Coastguard Worker self._container_sizes = kwargs.get('container_sizes') 1415*b9df5ad1SAndroid Build Coastguard Worker 1416*b9df5ad1SAndroid Build Coastguard Worker hal_version = kwargs.get('hal_version') 1417*b9df5ad1SAndroid Build Coastguard Worker if hal_version is None: 1418*b9df5ad1SAndroid Build Coastguard Worker if self.is_clone(): 1419*b9df5ad1SAndroid Build Coastguard Worker self._hal_major_version = 0 1420*b9df5ad1SAndroid Build Coastguard Worker self._hal_minor_version = 0 1421*b9df5ad1SAndroid Build Coastguard Worker else: 1422*b9df5ad1SAndroid Build Coastguard Worker self._hal_major_version = 3 1423*b9df5ad1SAndroid Build Coastguard Worker self._hal_minor_version = 2 1424*b9df5ad1SAndroid Build Coastguard Worker else: 1425*b9df5ad1SAndroid Build Coastguard Worker self._hal_major_version = int(hal_version.partition('.')[0]) 1426*b9df5ad1SAndroid Build Coastguard Worker self._hal_minor_version = int(hal_version.partition('.')[2]) 1427*b9df5ad1SAndroid Build Coastguard Worker 1428*b9df5ad1SAndroid Build Coastguard Worker self._aconfig_flag = kwargs.get('aconfig_flag') 1429*b9df5ad1SAndroid Build Coastguard Worker 1430*b9df5ad1SAndroid Build Coastguard Worker # access these via the 'enum' prop 1431*b9df5ad1SAndroid Build Coastguard Worker enum_values = kwargs.get('enum_values') 1432*b9df5ad1SAndroid Build Coastguard Worker enum_deprecateds = kwargs.get('enum_deprecateds') 1433*b9df5ad1SAndroid Build Coastguard Worker enum_optionals = kwargs.get('enum_optionals') 1434*b9df5ad1SAndroid Build Coastguard Worker enum_visibilities = kwargs.get('enum_visibilities') 1435*b9df5ad1SAndroid Build Coastguard Worker enum_notes = kwargs.get('enum_notes') # { value => notes } 1436*b9df5ad1SAndroid Build Coastguard Worker enum_sdk_notes = kwargs.get('enum_sdk_notes') # { value => sdk_notes } 1437*b9df5ad1SAndroid Build Coastguard Worker enum_ndk_notes = kwargs.get('enum_ndk_notes') # { value => ndk_notes } 1438*b9df5ad1SAndroid Build Coastguard Worker enum_ids = kwargs.get('enum_ids') # { value => notes } 1439*b9df5ad1SAndroid Build Coastguard Worker enum_hal_versions = kwargs.get('enum_hal_versions') # { value => hal_versions } 1440*b9df5ad1SAndroid Build Coastguard Worker enum_aconfig_flags = kwargs.get('enum_aconfig_flags') # { value => aconfig flags } 1441*b9df5ad1SAndroid Build Coastguard Worker 1442*b9df5ad1SAndroid Build Coastguard Worker self._tuple_values = kwargs.get('tuple_values') 1443*b9df5ad1SAndroid Build Coastguard Worker 1444*b9df5ad1SAndroid Build Coastguard Worker self._description = kwargs.get('description') 1445*b9df5ad1SAndroid Build Coastguard Worker self._range = kwargs.get('range') 1446*b9df5ad1SAndroid Build Coastguard Worker self._units = kwargs.get('units') 1447*b9df5ad1SAndroid Build Coastguard Worker self._details = kwargs.get('details') 1448*b9df5ad1SAndroid Build Coastguard Worker self._hal_details = kwargs.get('hal_details') 1449*b9df5ad1SAndroid Build Coastguard Worker self._ndk_details = kwargs.get('ndk_details') 1450*b9df5ad1SAndroid Build Coastguard Worker 1451*b9df5ad1SAndroid Build Coastguard Worker self._tag_ids = kwargs.get('tag_ids', []) 1452*b9df5ad1SAndroid Build Coastguard Worker self._tags = None # Filled in by Metadata::_construct_tags 1453*b9df5ad1SAndroid Build Coastguard Worker 1454*b9df5ad1SAndroid Build Coastguard Worker self._type_notes = kwargs.get('type_notes') 1455*b9df5ad1SAndroid Build Coastguard Worker self._type_name = kwargs.get('type_name') 1456*b9df5ad1SAndroid Build Coastguard Worker self._typedef = None # Filled in by Metadata::_construct_types 1457*b9df5ad1SAndroid Build Coastguard Worker 1458*b9df5ad1SAndroid Build Coastguard Worker if kwargs.get('enum', False): 1459*b9df5ad1SAndroid Build Coastguard Worker self._enum = Enum(self, enum_values, enum_ids, enum_deprecateds, enum_optionals, 1460*b9df5ad1SAndroid Build Coastguard Worker enum_visibilities, enum_notes, enum_sdk_notes, enum_ndk_notes, 1461*b9df5ad1SAndroid Build Coastguard Worker enum_hal_versions, enum_aconfig_flags) 1462*b9df5ad1SAndroid Build Coastguard Worker else: 1463*b9df5ad1SAndroid Build Coastguard Worker self._enum = None 1464*b9df5ad1SAndroid Build Coastguard Worker 1465*b9df5ad1SAndroid Build Coastguard Worker self._visibility = kwargs.get('visibility') 1466*b9df5ad1SAndroid Build Coastguard Worker self._synthetic = kwargs.get('synthetic', False) 1467*b9df5ad1SAndroid Build Coastguard Worker self._hwlevel = kwargs.get('hwlevel') 1468*b9df5ad1SAndroid Build Coastguard Worker self._deprecated = kwargs.get('deprecated', False) 1469*b9df5ad1SAndroid Build Coastguard Worker self._deprecation_description = kwargs.get('deprecation_description') 1470*b9df5ad1SAndroid Build Coastguard Worker 1471*b9df5ad1SAndroid Build Coastguard Worker self._permission_needed = kwargs.get('permission_needed') 1472*b9df5ad1SAndroid Build Coastguard Worker self._optional = kwargs.get('optional') 1473*b9df5ad1SAndroid Build Coastguard Worker self._ndk_visible = kwargs.get('ndk_visible') 1474*b9df5ad1SAndroid Build Coastguard Worker 1475*b9df5ad1SAndroid Build Coastguard Worker self._session_characteristics_key_since = None \ 1476*b9df5ad1SAndroid Build Coastguard Worker if not kwargs.get('session_characteristics_key_since') \ 1477*b9df5ad1SAndroid Build Coastguard Worker else int(kwargs.get('session_characteristics_key_since')) 1478*b9df5ad1SAndroid Build Coastguard Worker 1479*b9df5ad1SAndroid Build Coastguard Worker self._property_keys = kwargs 1480*b9df5ad1SAndroid Build Coastguard Worker 1481*b9df5ad1SAndroid Build Coastguard Worker def merge(self): 1482*b9df5ad1SAndroid Build Coastguard Worker """ 1483*b9df5ad1SAndroid Build Coastguard Worker Copy the attributes into a new entry, merging it with the target entry 1484*b9df5ad1SAndroid Build Coastguard Worker if it's a clone. 1485*b9df5ad1SAndroid Build Coastguard Worker """ 1486*b9df5ad1SAndroid Build Coastguard Worker return MergedEntry(self) 1487*b9df5ad1SAndroid Build Coastguard Worker 1488*b9df5ad1SAndroid Build Coastguard Worker # Helpers for accessing less than the fully qualified name 1489*b9df5ad1SAndroid Build Coastguard Worker 1490*b9df5ad1SAndroid Build Coastguard Worker def get_name_as_list(self): 1491*b9df5ad1SAndroid Build Coastguard Worker """ 1492*b9df5ad1SAndroid Build Coastguard Worker Returns the name as a list split by a period. 1493*b9df5ad1SAndroid Build Coastguard Worker 1494*b9df5ad1SAndroid Build Coastguard Worker For example: 1495*b9df5ad1SAndroid Build Coastguard Worker entry.name is 'android.lens.info.shading' 1496*b9df5ad1SAndroid Build Coastguard Worker entry.get_name_as_list() == ['android', 'lens', 'info', 'shading'] 1497*b9df5ad1SAndroid Build Coastguard Worker """ 1498*b9df5ad1SAndroid Build Coastguard Worker return self.name.split(".") 1499*b9df5ad1SAndroid Build Coastguard Worker 1500*b9df5ad1SAndroid Build Coastguard Worker def get_inner_namespace_list(self): 1501*b9df5ad1SAndroid Build Coastguard Worker """ 1502*b9df5ad1SAndroid Build Coastguard Worker Returns the inner namespace part of the name as a list 1503*b9df5ad1SAndroid Build Coastguard Worker 1504*b9df5ad1SAndroid Build Coastguard Worker For example: 1505*b9df5ad1SAndroid Build Coastguard Worker entry.name is 'android.lens.info.shading' 1506*b9df5ad1SAndroid Build Coastguard Worker entry.get_inner_namespace_list() == ['info'] 1507*b9df5ad1SAndroid Build Coastguard Worker """ 1508*b9df5ad1SAndroid Build Coastguard Worker return self.get_name_as_list()[2:-1] 1509*b9df5ad1SAndroid Build Coastguard Worker 1510*b9df5ad1SAndroid Build Coastguard Worker def get_outer_namespace(self): 1511*b9df5ad1SAndroid Build Coastguard Worker """ 1512*b9df5ad1SAndroid Build Coastguard Worker Returns the outer namespace as a string. 1513*b9df5ad1SAndroid Build Coastguard Worker 1514*b9df5ad1SAndroid Build Coastguard Worker For example: 1515*b9df5ad1SAndroid Build Coastguard Worker entry.name is 'android.lens.info.shading' 1516*b9df5ad1SAndroid Build Coastguard Worker entry.get_outer_namespace() == 'android' 1517*b9df5ad1SAndroid Build Coastguard Worker 1518*b9df5ad1SAndroid Build Coastguard Worker Remarks: 1519*b9df5ad1SAndroid Build Coastguard Worker Since outer namespaces are non-recursive, 1520*b9df5ad1SAndroid Build Coastguard Worker and each entry has one, this does not need to be a list. 1521*b9df5ad1SAndroid Build Coastguard Worker """ 1522*b9df5ad1SAndroid Build Coastguard Worker return self.get_name_as_list()[0] 1523*b9df5ad1SAndroid Build Coastguard Worker 1524*b9df5ad1SAndroid Build Coastguard Worker def get_section(self): 1525*b9df5ad1SAndroid Build Coastguard Worker """ 1526*b9df5ad1SAndroid Build Coastguard Worker Returns the section as a string. 1527*b9df5ad1SAndroid Build Coastguard Worker 1528*b9df5ad1SAndroid Build Coastguard Worker For example: 1529*b9df5ad1SAndroid Build Coastguard Worker entry.name is 'android.lens.info.shading' 1530*b9df5ad1SAndroid Build Coastguard Worker entry.get_section() == '' 1531*b9df5ad1SAndroid Build Coastguard Worker 1532*b9df5ad1SAndroid Build Coastguard Worker Remarks: 1533*b9df5ad1SAndroid Build Coastguard Worker Since outer namespaces are non-recursive, 1534*b9df5ad1SAndroid Build Coastguard Worker and each entry has one, this does not need to be a list. 1535*b9df5ad1SAndroid Build Coastguard Worker """ 1536*b9df5ad1SAndroid Build Coastguard Worker return self.get_name_as_list()[1] 1537*b9df5ad1SAndroid Build Coastguard Worker 1538*b9df5ad1SAndroid Build Coastguard Worker def get_name_minimal(self): 1539*b9df5ad1SAndroid Build Coastguard Worker """ 1540*b9df5ad1SAndroid Build Coastguard Worker Returns only the last component of the fully qualified name as a string. 1541*b9df5ad1SAndroid Build Coastguard Worker 1542*b9df5ad1SAndroid Build Coastguard Worker For example: 1543*b9df5ad1SAndroid Build Coastguard Worker entry.name is 'android.lens.info.shading' 1544*b9df5ad1SAndroid Build Coastguard Worker entry.get_name_minimal() == 'shading' 1545*b9df5ad1SAndroid Build Coastguard Worker 1546*b9df5ad1SAndroid Build Coastguard Worker Remarks: 1547*b9df5ad1SAndroid Build Coastguard Worker entry.name_short it an alias for this 1548*b9df5ad1SAndroid Build Coastguard Worker """ 1549*b9df5ad1SAndroid Build Coastguard Worker return self.get_name_as_list()[-1] 1550*b9df5ad1SAndroid Build Coastguard Worker 1551*b9df5ad1SAndroid Build Coastguard Worker def get_path_without_name(self): 1552*b9df5ad1SAndroid Build Coastguard Worker """ 1553*b9df5ad1SAndroid Build Coastguard Worker Returns a string path to the entry, with the name component excluded. 1554*b9df5ad1SAndroid Build Coastguard Worker 1555*b9df5ad1SAndroid Build Coastguard Worker For example: 1556*b9df5ad1SAndroid Build Coastguard Worker entry.name is 'android.lens.info.shading' 1557*b9df5ad1SAndroid Build Coastguard Worker entry.get_path_without_name() == 'android.lens.info' 1558*b9df5ad1SAndroid Build Coastguard Worker """ 1559*b9df5ad1SAndroid Build Coastguard Worker return ".".join(self.get_name_as_list()[0:-1]) 1560*b9df5ad1SAndroid Build Coastguard Worker 1561*b9df5ad1SAndroid Build Coastguard Worker 1562*b9df5ad1SAndroid Build Coastguard Workerclass Clone(Entry): 1563*b9df5ad1SAndroid Build Coastguard Worker """ 1564*b9df5ad1SAndroid Build Coastguard Worker A Node corresponding to a <clone> element. It has all the attributes of an 1565*b9df5ad1SAndroid Build Coastguard Worker <entry> element (Entry) plus the additions specified below. 1566*b9df5ad1SAndroid Build Coastguard Worker 1567*b9df5ad1SAndroid Build Coastguard Worker Attributes (Read-Only): 1568*b9df5ad1SAndroid Build Coastguard Worker entry: an edge to an Entry object that this targets 1569*b9df5ad1SAndroid Build Coastguard Worker target_kind: A string describing the kind of the target entry. 1570*b9df5ad1SAndroid Build Coastguard Worker name: a string of the name, same as entry.name 1571*b9df5ad1SAndroid Build Coastguard Worker kind: a string of the Kind ancestor, one of 'static', 'controls', 'dynamic' 1572*b9df5ad1SAndroid Build Coastguard Worker for the <clone> element. 1573*b9df5ad1SAndroid Build Coastguard Worker type: always None, since a clone cannot override the type. 1574*b9df5ad1SAndroid Build Coastguard Worker """ 1575*b9df5ad1SAndroid Build Coastguard Worker def __init__(self, entry=None, **kwargs): 1576*b9df5ad1SAndroid Build Coastguard Worker """ 1577*b9df5ad1SAndroid Build Coastguard Worker Instantiate a new Clone node. 1578*b9df5ad1SAndroid Build Coastguard Worker 1579*b9df5ad1SAndroid Build Coastguard Worker Args: 1580*b9df5ad1SAndroid Build Coastguard Worker name: A string with the fully qualified name, e.g. 'android.shading.mode' 1581*b9df5ad1SAndroid Build Coastguard Worker type: A string describing the type, e.g. 'int32' 1582*b9df5ad1SAndroid Build Coastguard Worker kind: A string describing the kind, e.g. 'static' 1583*b9df5ad1SAndroid Build Coastguard Worker target_kind: A string for the kind of the target entry, e.g. 'dynamic' 1584*b9df5ad1SAndroid Build Coastguard Worker hal_version: A string for the initial HIDL HAL metadata version this entry 1585*b9df5ad1SAndroid Build Coastguard Worker was added in 1586*b9df5ad1SAndroid Build Coastguard Worker 1587*b9df5ad1SAndroid Build Coastguard Worker Args (if container): 1588*b9df5ad1SAndroid Build Coastguard Worker container: A string describing the container, e.g. 'array' or 'tuple' 1589*b9df5ad1SAndroid Build Coastguard Worker container_sizes: A list of string sizes if a container, or None otherwise 1590*b9df5ad1SAndroid Build Coastguard Worker 1591*b9df5ad1SAndroid Build Coastguard Worker Args (if container is 'tuple'): 1592*b9df5ad1SAndroid Build Coastguard Worker tuple_values: A list of tuple values, e.g. ['width', 'height'] 1593*b9df5ad1SAndroid Build Coastguard Worker 1594*b9df5ad1SAndroid Build Coastguard Worker Args (if the 'enum' attribute is true): 1595*b9df5ad1SAndroid Build Coastguard Worker enum: A boolean, True if this is an enum, False otherwise 1596*b9df5ad1SAndroid Build Coastguard Worker enum_values: A list of value strings, e.g. ['ON', 'OFF'] 1597*b9df5ad1SAndroid Build Coastguard Worker enum_optionals: A list of optional enum values, e.g. ['OFF'] 1598*b9df5ad1SAndroid Build Coastguard Worker enum_notes: A dictionary of value->notes strings. 1599*b9df5ad1SAndroid Build Coastguard Worker enum_ids: A dictionary of value->id strings. 1600*b9df5ad1SAndroid Build Coastguard Worker 1601*b9df5ad1SAndroid Build Coastguard Worker Args (optional): 1602*b9df5ad1SAndroid Build Coastguard Worker entry: An edge to the corresponding target Entry. 1603*b9df5ad1SAndroid Build Coastguard Worker description: A string with a description of the entry. 1604*b9df5ad1SAndroid Build Coastguard Worker range: A string with the range of the values of the entry, e.g. '>= 0' 1605*b9df5ad1SAndroid Build Coastguard Worker units: A string with the units of the values, e.g. 'inches' 1606*b9df5ad1SAndroid Build Coastguard Worker details: A string with the detailed documentation for the entry 1607*b9df5ad1SAndroid Build Coastguard Worker hal_details: A string with the HAL implementation details for the entry 1608*b9df5ad1SAndroid Build Coastguard Worker ndk_details: A string with the extra NDK documentation for the entry 1609*b9df5ad1SAndroid Build Coastguard Worker tag_ids: A list of tag ID strings, e.g. ['BC', 'V1'] 1610*b9df5ad1SAndroid Build Coastguard Worker type_notes: A string with the notes for the type 1611*b9df5ad1SAndroid Build Coastguard Worker 1612*b9df5ad1SAndroid Build Coastguard Worker Remarks: 1613*b9df5ad1SAndroid Build Coastguard Worker Note that type is not specified since it has to be the same as the 1614*b9df5ad1SAndroid Build Coastguard Worker entry.type. 1615*b9df5ad1SAndroid Build Coastguard Worker """ 1616*b9df5ad1SAndroid Build Coastguard Worker self._entry = entry # Entry object 1617*b9df5ad1SAndroid Build Coastguard Worker self._target_kind = kwargs['target_kind'] 1618*b9df5ad1SAndroid Build Coastguard Worker self._name = kwargs['name'] # same as entry.name 1619*b9df5ad1SAndroid Build Coastguard Worker self._kind = kwargs['kind'] 1620*b9df5ad1SAndroid Build Coastguard Worker 1621*b9df5ad1SAndroid Build Coastguard Worker # illegal to override the type, it should be the same as the entry 1622*b9df5ad1SAndroid Build Coastguard Worker self._type = None 1623*b9df5ad1SAndroid Build Coastguard Worker # the rest of the kwargs are optional 1624*b9df5ad1SAndroid Build Coastguard Worker # can be used to override the regular entry data 1625*b9df5ad1SAndroid Build Coastguard Worker self._init_common(**kwargs) 1626*b9df5ad1SAndroid Build Coastguard Worker 1627*b9df5ad1SAndroid Build Coastguard Worker @property 1628*b9df5ad1SAndroid Build Coastguard Worker def entry(self): 1629*b9df5ad1SAndroid Build Coastguard Worker return self._entry 1630*b9df5ad1SAndroid Build Coastguard Worker 1631*b9df5ad1SAndroid Build Coastguard Worker @property 1632*b9df5ad1SAndroid Build Coastguard Worker def target_kind(self): 1633*b9df5ad1SAndroid Build Coastguard Worker return self._target_kind 1634*b9df5ad1SAndroid Build Coastguard Worker 1635*b9df5ad1SAndroid Build Coastguard Worker def is_clone(self): 1636*b9df5ad1SAndroid Build Coastguard Worker """ 1637*b9df5ad1SAndroid Build Coastguard Worker Whether or not this is a Clone instance. 1638*b9df5ad1SAndroid Build Coastguard Worker 1639*b9df5ad1SAndroid Build Coastguard Worker Returns: 1640*b9df5ad1SAndroid Build Coastguard Worker True 1641*b9df5ad1SAndroid Build Coastguard Worker """ 1642*b9df5ad1SAndroid Build Coastguard Worker return True 1643*b9df5ad1SAndroid Build Coastguard Worker 1644*b9df5ad1SAndroid Build Coastguard Workerclass MergedEntry(Entry): 1645*b9df5ad1SAndroid Build Coastguard Worker """ 1646*b9df5ad1SAndroid Build Coastguard Worker A MergedEntry has all the attributes of a Clone and its target Entry merged 1647*b9df5ad1SAndroid Build Coastguard Worker together. 1648*b9df5ad1SAndroid Build Coastguard Worker 1649*b9df5ad1SAndroid Build Coastguard Worker Remarks: 1650*b9df5ad1SAndroid Build Coastguard Worker Useful when we want to 'unfold' a clone into a real entry by copying out 1651*b9df5ad1SAndroid Build Coastguard Worker the target entry data. In this case we don't care about distinguishing 1652*b9df5ad1SAndroid Build Coastguard Worker a clone vs an entry. 1653*b9df5ad1SAndroid Build Coastguard Worker """ 1654*b9df5ad1SAndroid Build Coastguard Worker def __init__(self, entry): 1655*b9df5ad1SAndroid Build Coastguard Worker """ 1656*b9df5ad1SAndroid Build Coastguard Worker Create a new instance of MergedEntry. 1657*b9df5ad1SAndroid Build Coastguard Worker 1658*b9df5ad1SAndroid Build Coastguard Worker Args: 1659*b9df5ad1SAndroid Build Coastguard Worker entry: An Entry or Clone instance 1660*b9df5ad1SAndroid Build Coastguard Worker """ 1661*b9df5ad1SAndroid Build Coastguard Worker props_distinct = ['description', 'units', 'range', 'details', 1662*b9df5ad1SAndroid Build Coastguard Worker 'hal_details', 'ndk_details', 'tags', 'kind', 1663*b9df5ad1SAndroid Build Coastguard Worker 'deprecation_description'] 1664*b9df5ad1SAndroid Build Coastguard Worker 1665*b9df5ad1SAndroid Build Coastguard Worker for p in props_distinct: 1666*b9df5ad1SAndroid Build Coastguard Worker p = '_' + p 1667*b9df5ad1SAndroid Build Coastguard Worker if entry.is_clone(): 1668*b9df5ad1SAndroid Build Coastguard Worker setattr(self, p, getattr(entry, p) or getattr(entry.entry, p)) 1669*b9df5ad1SAndroid Build Coastguard Worker else: 1670*b9df5ad1SAndroid Build Coastguard Worker setattr(self, p, getattr(entry, p)) 1671*b9df5ad1SAndroid Build Coastguard Worker 1672*b9df5ad1SAndroid Build Coastguard Worker props_common = ['parent', 'name', 'container', 1673*b9df5ad1SAndroid Build Coastguard Worker 'container_sizes', 'enum', 1674*b9df5ad1SAndroid Build Coastguard Worker 'tuple_values', 1675*b9df5ad1SAndroid Build Coastguard Worker 'type', 1676*b9df5ad1SAndroid Build Coastguard Worker 'type_notes', 1677*b9df5ad1SAndroid Build Coastguard Worker 'visibility', 1678*b9df5ad1SAndroid Build Coastguard Worker 'ndk_visible', 1679*b9df5ad1SAndroid Build Coastguard Worker 'synthetic', 1680*b9df5ad1SAndroid Build Coastguard Worker 'hwlevel', 1681*b9df5ad1SAndroid Build Coastguard Worker 'deprecated', 1682*b9df5ad1SAndroid Build Coastguard Worker 'optional', 1683*b9df5ad1SAndroid Build Coastguard Worker 'typedef', 1684*b9df5ad1SAndroid Build Coastguard Worker 'hal_major_version', 1685*b9df5ad1SAndroid Build Coastguard Worker 'hal_minor_version', 1686*b9df5ad1SAndroid Build Coastguard Worker 'permission_needed', 1687*b9df5ad1SAndroid Build Coastguard Worker 'aconfig_flag', 1688*b9df5ad1SAndroid Build Coastguard Worker 'session_characteristics_key_since' 1689*b9df5ad1SAndroid Build Coastguard Worker ] 1690*b9df5ad1SAndroid Build Coastguard Worker 1691*b9df5ad1SAndroid Build Coastguard Worker for p in props_common: 1692*b9df5ad1SAndroid Build Coastguard Worker p = '_' + p 1693*b9df5ad1SAndroid Build Coastguard Worker if entry.is_clone(): 1694*b9df5ad1SAndroid Build Coastguard Worker setattr(self, p, getattr(entry.entry, p)) 1695*b9df5ad1SAndroid Build Coastguard Worker else: 1696*b9df5ad1SAndroid Build Coastguard Worker setattr(self, p, getattr(entry, p)) 1697