blob: 47519c601aab3374d53cdcb7f1f4a312c63f4def [file] [log] [blame]
#!/usr/bin/env python
#
# Copyright (C) 2018 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
"""
Dump new HIDL types that are introduced in each FCM version.
"""
from __future__ import print_function
import argparse
import collections
import json
import os
import subprocess
import sys
class Globals:
pass
def call(args):
if Globals.verbose:
print(' '.join(args), file=sys.stderr)
sp = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = sp.communicate()
return sp.returncode, out.decode(), err.decode()
def check_call(args):
r, o, e = call(args)
assert not r, '`{}` returns {}'.format(' '.join(args), r)
return o, e
def lines(o):
return filter(lambda line: line, (line.strip() for line in o.split()))
def to_level(s):
if s == 'legacy': return 0
if s == '': return float('inf')
return int(s)
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('--verbose', help='Verbose mode', action='store_true')
parser.add_argument('--pretty', help='Print pretty JSON', action='store_true')
parser.add_argument('--hidl-gen', help='Location of hidl-gen', required=True)
parser.add_argument('--analyze-matrix', help='Location of analyze_matrix', required=True)
parser.add_argument('--compatibility-matrix', metavar='FILE',
help='Location of framework compatibility matrices', nargs='+', required=True)
parser.add_argument('--package-root', metavar='PACKAGE:PATH',
help='package roots provided to hidl-gen, e.g. android.hardware:hardware/interfaces',
nargs='+')
parser.parse_args(namespace=Globals)
interfaces_for_level = dict()
for matrix_path in Globals.compatibility_matrix:
r, o, _ = call([Globals.analyze_matrix, '--input', matrix_path, '--level'])
if r:
# Not a compatibility matrix, ignore
continue
# stderr may contain warning message if level is empty
level = o.strip()
o, _ = check_call([Globals.analyze_matrix, '--input', matrix_path, '--interfaces'])
# stderr may contain warning message if no interfaces
interfaces = list(lines(o))
if not interfaces: continue
if level not in interfaces_for_level:
interfaces_for_level[level] = set()
# Put top level interfaces
interfaces_for_level[level].update(interfaces)
# Put interfaces referenced by top level interfaces
args = [Globals.hidl_gen, '-Ldependencies']
if Globals.package_root:
args.append('-R')
for package_root in Globals.package_root:
args.extend(['-r', package_root])
args.extend(interfaces)
o, e = check_call(args)
assert not e, '`{}` has written to stderr:\n{}'.format(' '.join(args), e)
interfaces_for_level[level].update(lines(o))
seen_interfaces = set()
new_interfaces_for_level = collections.OrderedDict()
for level, interfaces in sorted(interfaces_for_level.items(), key=lambda tup: to_level(tup[0])):
new_interfaces_for_level[level] = sorted(interfaces - seen_interfaces)
seen_interfaces.update(interfaces)
print(json.dumps(new_interfaces_for_level,
separators=None if Globals.pretty else (',',':'),
indent=4 if Globals.pretty else None))
if __name__ == '__main__':
main()