Fix AIDL VHAL metadata extraction script

Add capability to process values from imports.
Update json metadata file with new data.

Testing:
1. cd hardware/interfaces/automotive/vehicle/aidl/emu_metadata
2. ./generate_emulator_metadata.py ../../aidl_property/android/hardware/automotive/vehicle out.json

Bug: 317529575
Test: manual
Change-Id: I315f1f75c2372796bde3bdacd39246344579c002
This commit is contained in:
Victor Shutemov 2023-12-20 17:28:59 +01:00
parent 35bf32ff0f
commit 1e14bd55bd
2 changed files with 3791 additions and 2609 deletions

View file

@ -19,23 +19,56 @@ import sys
from pathlib import Path
RE_PACKAGE = re.compile(r"\npackage\s([\.a-z0-9]*);")
RE_IMPORT = re.compile(r"\nimport\s([\.a-zA-Z0-9]*);")
RE_ENUM = re.compile(r"\s*enum\s+(\w*) {\n(.*)}", re.MULTILINE | re.DOTALL)
RE_COMMENT = re.compile(r"(?:(?:\/\*\*)((?:.|\n)*?)(?:\*\/))?(?:\n|^)\s*(\w*)(?:\s+=\s*)?((?:[a-zA-Z0-9]|\s|\+|)*),", re.DOTALL)
RE_COMMENT = re.compile(r"(?:(?:\/\*\*)((?:.|\n)*?)(?:\*\/))?(?:\n|^)\s*(\w*)(?:\s+=\s*)?((?:[\.\-a-zA-Z0-9]|\s|\+|)*),",
re.DOTALL)
RE_BLOCK_COMMENT_TITLE = re.compile("^(?:\s|\*)*((?:\w|\s|\.)*)\n(?:\s|\*)*(?:\n|$)")
RE_BLOCK_COMMENT_ANNOTATION = re.compile("^(?:\s|\*)*@(\w*)\s+((?:\w|:)*)", re.MULTILINE)
RE_HEX_NUMBER = re.compile("([0-9A-Fa-fxX]+)")
RE_BLOCK_COMMENT_ANNOTATION = re.compile("^(?:\s|\*)*@(\w*)\s+((?:[\w:\.])*)", re.MULTILINE)
RE_HEX_NUMBER = re.compile("([\.\-0-9A-Za-z]+)")
class JEnum:
def __init__(self, name):
def __init__(self, package, name):
self.package = package
self.name = name
self.values = []
class Enum:
def __init__(self, package, name, text, imports):
self.text = text
self.parsed = False
self.imports = imports
self.jenum = JEnum(package, name)
class Converter:
# Only addition is supported for now, but that covers all existing properties except
# OBD diagnostics, which use bitwise shifts
def calculateValue(self, expression, default_value):
def parse(self, enums):
if self.parsed:
return
for dep in self.imports:
enums[dep].parse(enums)
print("Parsing " + self.jenum.name)
matches = RE_COMMENT.findall(self.text)
defaultValue = 0
for match in matches:
value = dict()
value['name'] = match[1]
value['value'] = self.calculateValue(match[2], defaultValue, enums)
defaultValue = value['value'] + 1
if self.jenum.name == "VehicleProperty":
block_comment = match[0]
self.parseBlockComment(value, block_comment)
self.jenum.values.append(value)
self.parsed = True
self.text = None
def get_value(self, value_name):
for value in self.jenum.values:
if value['name'] == value_name:
return value['value']
raise Exception("Cannot decode value: " + self.jenum.package + " : " + value_name)
def calculateValue(self, expression, default_value, enums):
numbers = RE_HEX_NUMBER.findall(expression)
if len(numbers) == 0:
return default_value
@ -44,7 +77,13 @@ class Converter:
if numbers[0].lower().startswith("0x"):
base = 16
for number in numbers:
result += int(number, base)
if '.' in number:
package, val_name = number.split('.')
for dep in self.imports:
if package in dep:
result += enums[dep].get_value(val_name)
else:
result += int(number, base)
return result
def parseBlockComment(self, value, blockComment):
@ -54,30 +93,22 @@ class Converter:
break
annots_res = RE_BLOCK_COMMENT_ANNOTATION.findall(blockComment)
for annot in annots_res:
value[annot[0]] = annot[1]
def parseEnumContents(self, enum: JEnum, enumValue):
matches = RE_COMMENT.findall(enumValue)
defaultValue = 0
for match in matches:
value = dict()
value['name'] = match[1]
value['value'] = self.calculateValue(match[2], defaultValue)
defaultValue = value['value'] + 1
if enum.name == "VehicleProperty":
block_comment = match[0]
self.parseBlockComment(value, block_comment)
enum.values.append(value)
value[annot[0]] = annot[1].replace(".", ":")
class Converter:
# Only addition is supported for now, but that covers all existing properties except
# OBD diagnostics, which use bitwise shifts
def convert(self, input):
text = Path(input).read_text()
matches = RE_ENUM.findall(text)
jenums = []
package = RE_PACKAGE.findall(text)[0]
imports = RE_IMPORT.findall(text)
enums = []
for match in matches:
enum = JEnum(match[0])
self.parseEnumContents(enum, match[1])
jenums.append(enum)
return jenums
enum = Enum(package, match[0], match[1], imports)
enums.append(enum)
return enums
def main():
if (len(sys.argv) != 3):
@ -85,10 +116,18 @@ def main():
sys.exit(1)
aidl_path = sys.argv[1]
out_path = sys.argv[2]
result = []
enums_dict = dict()
for file in os.listdir(aidl_path):
result.extend(Converter().convert(os.path.join(aidl_path, file)))
json_result = json.dumps(result, default=vars, indent=2)
enums = Converter().convert(os.path.join(aidl_path, file))
for enum in enums:
enums_dict[enum.jenum.package + "." + enum.jenum.name] = enum
result = []
for enum_name, enum in enums_dict.items():
enum.parse(enums_dict)
result.append(enum.jenum.__dict__)
json_result = json.dumps(result, default=None, indent=2)
with open(out_path, 'w') as f:
f.write(json_result)