blob: b2eb172ef8e24446def94d2c0767920a3f26f3cd [file] [log] [blame]
#!/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()