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

Commit 1d4fe975 authored by Victor Shutemov's avatar Victor Shutemov Committed by Victor Shutemov
Browse files

Add emulator metadata generator script

Add script to generate vehicle properties metadata file
for use with emulator's vehicle tab.
Metadata includes:
    - names of the properties,
    - names for the data enum values
    - change and access modes

Change-Id: Ica1df3466b7965916d11adc513f6472d439e1119
parent ad2871f7
Loading
Loading
Loading
Loading
+3460 −0

File added.

Preview size limit exceeded, changes collapsed.

+97 −0
Original line number Diff line number Diff line
#!/usr/bin/python3

#
# Script for generation of VHAL properties metadata .json from AIDL interface
#
# This metadata is used to display human property names, names of enum
# data types for their values, change and access modes and other information,
# available from AIDL block comments, but not at runtime.
#
# Usage example:
#  ./emu_metadata/generate_emulator_metadata.py android/hardware/automotive/vehicle $OUT/android.hardware.automotive.vehicle-types-meta.json
#  (Note, that the resulting file has to match a '*types-meta.json' pattern to be parsed by the emulator).
#

import json
import os
import re
import sys

from pathlib import Path

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_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]+)")


class JEnum:
    def __init__(self, name):
        self.name = name
        self.values = []


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):
        numbers = RE_HEX_NUMBER.findall(expression)
        if len(numbers) == 0:
            return default_value
        result = 0
        base = 10
        if numbers[0].lower().startswith("0x"):
            base = 16
        for number in numbers:
            result += int(number, base)
        return result

    def parseBlockComment(self, value, blockComment):
        titles = RE_BLOCK_COMMENT_TITLE.findall(blockComment)
        for title in titles:
            value['name'] = title
            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)

    def convert(self, input):
        text = Path(input).read_text()
        matches = RE_ENUM.findall(text)
        jenums = []
        for match in matches:
            enum = JEnum(match[0])
            self.parseEnumContents(enum, match[1])
            jenums.append(enum)
        return jenums

def main():
    if (len(sys.argv) != 3):
        print("Usage: ", sys.argv[0], " INPUT_PATH OUTPUT")
        sys.exit(1)
    aidl_path = sys.argv[1]
    out_path = sys.argv[2]
    result = []
    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)
    with open(out_path, 'w') as f:
        f.write(json_result)


if __name__ == "__main__":
    main()