summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYifan Hong2018-10-02 18:55:47 -0500
committerYifan Hong2018-10-09 19:30:55 -0500
commit0710a86dc59bed180e134ab92bf62cb44cb078ed (patch)
treeeb052456617e4483e055889522cb80f70d206b1c
parentd34570694d7c9fe5c7bba7756c883c27b3a1590e (diff)
downloadplatform-system-libvintf-0710a86dc59bed180e134ab92bf62cb44cb078ed.tar.gz
platform-system-libvintf-0710a86dc59bed180e134ab92bf62cb44cb078ed.tar.xz
platform-system-libvintf-0710a86dc59bed180e134ab92bf62cb44cb078ed.zip
Add dump_hals_for_release.py and analyze_matrix.
Test: ./system/libvintf/analyze_matrix/dump_hals_for_release.py \ --hidl-gen=$(which hidl-gen) \ --analyze-matrix=$(which analyze_matrix) \ --compatibility-matrix \ hardware/interfaces/compatibility_matrices/compatibility_matrix.*.xml Bug: 116165266 Change-Id: Ic3fa41f8e2dfa6c083ec867534fc39dad469410e
-rw-r--r--analyze_matrix/Android.bp43
-rw-r--r--analyze_matrix/analyze_matrix.cpp128
-rwxr-xr-xanalyze_matrix/dump_hals_for_release.py110
3 files changed, 281 insertions, 0 deletions
diff --git a/analyze_matrix/Android.bp b/analyze_matrix/Android.bp
new file mode 100644
index 0000000..1d8beb1
--- /dev/null
+++ b/analyze_matrix/Android.bp
@@ -0,0 +1,43 @@
1// Copyright (C) 2018 The Android Open Source Project
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15cc_binary_host {
16 name: "analyze_matrix",
17 defaults: ["libvintf-defaults"],
18 shared_libs: [
19 "libbase",
20 "libhidl-gen-utils",
21 "libgflags",
22 "libvintf",
23 ],
24 cpp_std: "experimental",
25 srcs: [
26 "analyze_matrix.cpp",
27 ],
28}
29
30python_binary_host {
31 name: "dump_hals_for_release",
32 srcs: [
33 "dump_hals_for_release.py",
34 ],
35 version: {
36 py2: {
37 enabled: true,
38 },
39 py3: {
40 enabled: false,
41 },
42 },
43}
diff --git a/analyze_matrix/analyze_matrix.cpp b/analyze_matrix/analyze_matrix.cpp
new file mode 100644
index 0000000..49134ef
--- /dev/null
+++ b/analyze_matrix/analyze_matrix.cpp
@@ -0,0 +1,128 @@
1/*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <optional>
18#include <set>
19
20#include <android-base/logging.h>
21#include <gflags/gflags.h>
22#include <hidl-util/FqInstance.h>
23#include <vintf/FileSystem.h>
24#include <vintf/parse_string.h>
25#include <vintf/parse_xml.h>
26
27namespace android {
28namespace vintf {
29
30namespace {
31
32template <typename T>
33std::optional<T> readObject(const std::string& path, const XmlConverter<T>& converter) {
34 std::string xml;
35 std::string error;
36 status_t err = details::FileSystemImpl().fetch(path, &xml, &error);
37 if (err != OK) {
38 LOG(ERROR) << "Cannot read '" << path << "': " << error;
39 return std::nullopt;
40 }
41 auto ret = std::make_optional<T>();
42 if (!converter(&ret.value(), xml, &error)) {
43 LOG(ERROR) << "Cannot parse '" << path << "': " << error;
44 return std::nullopt;
45 }
46 return ret;
47}
48
49std::optional<std::set<std::string>> getInterfaces(const CompatibilityMatrix& mat) {
50 auto set = std::make_optional<std::set<std::string>>();
51 mat.forEachInstance([&set](const auto& matrixInstance) {
52 for (auto minorVer = matrixInstance.versionRange().minMinor;
53 minorVer <= matrixInstance.versionRange().maxMinor; ++minorVer) {
54 FqInstance fqInstance;
55 if (!fqInstance.setTo(matrixInstance.package(), matrixInstance.versionRange().majorVer,
56 minorVer, matrixInstance.interface())) {
57 LOG(ERROR) << "Matrix not valid; '" << matrixInstance.package() << "@"
58 << matrixInstance.versionRange().majorVer << "." << minorVer
59 << "::" << matrixInstance.interface() << "' is not a valid FQName.";
60 set = std::nullopt;
61 return false; // break
62 }
63
64 set->insert(fqInstance.string());
65 }
66 return true; // continue
67 });
68 return set;
69}
70
71} // namespace
72
73} // namespace vintf
74} // namespace android
75
76DEFINE_string(input, "", "Input compatibility matrix file");
77static bool ValidateInput(const char* /* flagname */, const std::string& value) {
78 return !value.empty();
79}
80DEFINE_validator(input, &ValidateInput);
81
82DEFINE_bool(level, false, "Write level (FCM version) of the compatibility matrix.");
83DEFINE_bool(interfaces, false, "Write strings like \"android.hardware.foo@1.0::IFoo\".");
84
85int main(int argc, char** argv) {
86 using namespace android::vintf;
87
88 gflags::ParseCommandLineFlags(&argc, &argv, true /* remove flags */);
89
90 auto mat = readObject(FLAGS_input, gCompatibilityMatrixConverter);
91 if (!mat) {
92 return 1;
93 }
94
95 bool written = false;
96
97 if (FLAGS_level) {
98 if (mat->level() == Level::UNSPECIFIED) {
99 LOG(WARNING) << "FCM version is unspecified.";
100 }
101 std::cout << mat->level() << std::endl;
102
103 written = true;
104 }
105
106 if (FLAGS_interfaces) {
107 auto pvs = getInterfaces(*mat);
108 if (!pvs) {
109 return 1;
110 }
111 if (pvs->empty()) {
112 LOG(WARNING) << "No package and versions are found.";
113 }
114
115 for (const auto& pv : *pvs) {
116 std::cout << pv << std::endl;
117 }
118
119 written = true;
120 }
121
122 if (!written) {
123 LOG(ERROR) << "No output format is set.";
124 return 1;
125 }
126
127 return 0;
128}
diff --git a/analyze_matrix/dump_hals_for_release.py b/analyze_matrix/dump_hals_for_release.py
new file mode 100755
index 0000000..47519c6
--- /dev/null
+++ b/analyze_matrix/dump_hals_for_release.py
@@ -0,0 +1,110 @@
1#!/usr/bin/env python
2#
3# Copyright (C) 2018 The Android Open Source Project
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16#
17
18"""
19Dump new HIDL types that are introduced in each FCM version.
20"""
21
22from __future__ import print_function
23
24import argparse
25import collections
26import json
27import os
28import subprocess
29import sys
30
31class Globals:
32 pass
33
34def call(args):
35 if Globals.verbose:
36 print(' '.join(args), file=sys.stderr)
37 sp = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
38 out, err = sp.communicate()
39 return sp.returncode, out.decode(), err.decode()
40
41def check_call(args):
42 r, o, e = call(args)
43 assert not r, '`{}` returns {}'.format(' '.join(args), r)
44 return o, e
45
46def lines(o):
47 return filter(lambda line: line, (line.strip() for line in o.split()))
48
49def to_level(s):
50 if s == 'legacy': return 0
51 if s == '': return float('inf')
52 return int(s)
53
54def main():
55 parser = argparse.ArgumentParser(description=__doc__)
56 parser.add_argument('--verbose', help='Verbose mode', action='store_true')
57 parser.add_argument('--pretty', help='Print pretty JSON', action='store_true')
58 parser.add_argument('--hidl-gen', help='Location of hidl-gen', required=True)
59 parser.add_argument('--analyze-matrix', help='Location of analyze_matrix', required=True)
60 parser.add_argument('--compatibility-matrix', metavar='FILE',
61 help='Location of framework compatibility matrices', nargs='+', required=True)
62 parser.add_argument('--package-root', metavar='PACKAGE:PATH',
63 help='package roots provided to hidl-gen, e.g. android.hardware:hardware/interfaces',
64 nargs='+')
65 parser.parse_args(namespace=Globals)
66
67 interfaces_for_level = dict()
68 for matrix_path in Globals.compatibility_matrix:
69 r, o, _ = call([Globals.analyze_matrix, '--input', matrix_path, '--level'])
70 if r:
71 # Not a compatibility matrix, ignore
72 continue
73 # stderr may contain warning message if level is empty
74 level = o.strip()
75
76 o, _ = check_call([Globals.analyze_matrix, '--input', matrix_path, '--interfaces'])
77 # stderr may contain warning message if no interfaces
78
79 interfaces = list(lines(o))
80 if not interfaces: continue
81
82 if level not in interfaces_for_level:
83 interfaces_for_level[level] = set()
84
85 # Put top level interfaces
86 interfaces_for_level[level].update(interfaces)
87
88 # Put interfaces referenced by top level interfaces
89 args = [Globals.hidl_gen, '-Ldependencies']
90 if Globals.package_root:
91 args.append('-R')
92 for package_root in Globals.package_root:
93 args.extend(['-r', package_root])
94 args.extend(interfaces)
95 o, e = check_call(args)
96 assert not e, '`{}` has written to stderr:\n{}'.format(' '.join(args), e)
97 interfaces_for_level[level].update(lines(o))
98
99 seen_interfaces = set()
100 new_interfaces_for_level = collections.OrderedDict()
101 for level, interfaces in sorted(interfaces_for_level.items(), key=lambda tup: to_level(tup[0])):
102 new_interfaces_for_level[level] = sorted(interfaces - seen_interfaces)
103 seen_interfaces.update(interfaces)
104
105 print(json.dumps(new_interfaces_for_level,
106 separators=None if Globals.pretty else (',',':'),
107 indent=4 if Globals.pretty else None))
108
109if __name__ == '__main__':
110 main()