Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1e14bd55 authored by Victor Shutemov's avatar Victor Shutemov
Browse files

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
parent 35bf32ff
Loading
Loading
Loading
Loading
+3063 −1920

File changed.

Preview size limit exceeded, changes collapsed.

+70 −31
Original line number Original line Diff line number Diff line
@@ -19,23 +19,56 @@ import sys


from pathlib import Path
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_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_TITLE = re.compile("^(?:\s|\*)*((?:\w|\s|\.)*)\n(?:\s|\*)*(?:\n|$)")
RE_BLOCK_COMMENT_ANNOTATION = re.compile("^(?:\s|\*)*@(\w*)\s+((?:\w|:)*)", re.MULTILINE)
RE_BLOCK_COMMENT_ANNOTATION = re.compile("^(?:\s|\*)*@(\w*)\s+((?:[\w:\.])*)", re.MULTILINE)
RE_HEX_NUMBER = re.compile("([0-9A-Fa-fxX]+)")
RE_HEX_NUMBER = re.compile("([\.\-0-9A-Za-z]+)")




class JEnum:
class JEnum:
    def __init__(self, name):
    def __init__(self, package, name):
        self.package = package
        self.name = name
        self.name = name
        self.values = []
        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:
    def parse(self, enums):
    # Only addition is supported for now, but that covers all existing properties except
        if self.parsed:
    # OBD diagnostics, which use bitwise shifts
            return
    def calculateValue(self, expression, default_value):
        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)
        numbers = RE_HEX_NUMBER.findall(expression)
        if len(numbers) == 0:
        if len(numbers) == 0:
            return default_value
            return default_value
@@ -44,6 +77,12 @@ class Converter:
        if numbers[0].lower().startswith("0x"):
        if numbers[0].lower().startswith("0x"):
            base = 16
            base = 16
        for number in numbers:
        for number in numbers:
            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)
                result += int(number, base)
        return result
        return result


@@ -54,30 +93,22 @@ class Converter:
            break
            break
        annots_res = RE_BLOCK_COMMENT_ANNOTATION.findall(blockComment)
        annots_res = RE_BLOCK_COMMENT_ANNOTATION.findall(blockComment)
        for annot in annots_res:
        for annot in annots_res:
            value[annot[0]] = annot[1]
            value[annot[0]] = annot[1].replace(".", ":")

    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)


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):
    def convert(self, input):
        text = Path(input).read_text()
        text = Path(input).read_text()
        matches = RE_ENUM.findall(text)
        matches = RE_ENUM.findall(text)
        jenums = []
        package = RE_PACKAGE.findall(text)[0]
        imports = RE_IMPORT.findall(text)
        enums = []
        for match in matches:
        for match in matches:
            enum = JEnum(match[0])
            enum = Enum(package, match[0], match[1], imports)
            self.parseEnumContents(enum, match[1])
            enums.append(enum)
            jenums.append(enum)
        return enums
        return jenums



def main():
def main():
    if (len(sys.argv) != 3):
    if (len(sys.argv) != 3):
@@ -85,10 +116,18 @@ def main():
        sys.exit(1)
        sys.exit(1)
    aidl_path = sys.argv[1]
    aidl_path = sys.argv[1]
    out_path = sys.argv[2]
    out_path = sys.argv[2]
    result = []
    enums_dict = dict()
    for file in os.listdir(aidl_path):
    for file in os.listdir(aidl_path):
        result.extend(Converter().convert(os.path.join(aidl_path, file)))
        enums = Converter().convert(os.path.join(aidl_path, file))
    json_result = json.dumps(result, default=vars, indent=2)
        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:
    with open(out_path, 'w') as f:
        f.write(json_result)
        f.write(json_result)