blob: 5cad1e5e31e6697299ce9718a35553d6408f515a [file] [log] [blame]
Yifan Hongace13de2023-04-28 15:54:04 -07001#!/usr/bin/env python3
2#
3# Copyright (C) 2023 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"""
18Creates the next compatibility matrix.
19
20Requires libvintf Level.h to be updated before executing this script.
21"""
22
23import argparse
24import os
25import pathlib
26import shutil
27import subprocess
28import textwrap
29
30
31def check_call(*args, **kwargs):
32 print(args)
33 subprocess.check_call(*args, **kwargs)
34
35
36def check_output(*args, **kwargs):
37 print(args)
38 return subprocess.check_output(*args, **kwargs)
39
40
41class Bump(object):
42
43 def __init__(self, cmdline_args):
44 self.top = pathlib.Path(os.environ["ANDROID_BUILD_TOP"])
45 self.interfaces_dir = self.top / "hardware/interfaces"
46
47 self.current_level = cmdline_args.current
48 self.current_module_name = f"framework_compatibility_matrix.{self.current_level}.xml"
49 self.current_xml = self.interfaces_dir / f"compatibility_matrices/compatibility_matrix.{self.current_level}.xml"
Devin Moore4be20f72024-02-01 21:39:36 +000050 self.device_module_name = "framework_compatibility_matrix.device.xml"
Yifan Hongace13de2023-04-28 15:54:04 -070051
52 self.next_level = cmdline_args.next
53 self.next_module_name = f"framework_compatibility_matrix.{self.next_level}.xml"
54 self.next_xml = self.interfaces_dir / f"compatibility_matrices/compatibility_matrix.{self.next_level}.xml"
55
56 self.level_to_letter = self.get_level_to_letter_mapping()
57 print("Found level mapping in libvintf Level.h:", self.level_to_letter)
58
59 def run(self):
60 self.bump_kernel_configs()
61 self.copy_matrix()
62 self.edit_android_bp()
63 self.edit_android_mk()
64
65 def get_level_to_letter_mapping(self):
66 levels_file = self.top / "system/libvintf/include/vintf/Level.h"
67 with open(levels_file) as f:
68 lines = f.readlines()
69 pairs = [
70 line.split("=", maxsplit=2) for line in lines if "=" in line
71 ]
72 return {
73 level.strip().removesuffix(","): letter.strip()
74 for letter, level in pairs
75 }
76
77 def bump_kernel_configs(self):
78 check_call([
79 self.top / "kernel/configs/tools/bump.py",
80 self.level_to_letter[self.current_level].lower(),
81 self.level_to_letter[self.next_level].lower(),
82 ])
83
84 def copy_matrix(self):
Devin Moore4be20f72024-02-01 21:39:36 +000085 with open(self.current_xml) as f_current, open(self.next_xml, "w") as f_next:
86 f_next.write(f_current.read().replace(f"level=\"{self.current_level}\"", f"level=\"{self.next_level}\""))
Yifan Hongace13de2023-04-28 15:54:04 -070087
88 def edit_android_bp(self):
89 android_bp = self.interfaces_dir / "compatibility_matrices/Android.bp"
90
91 with open(android_bp, "r+") as f:
92 if self.next_module_name not in f.read():
93 f.seek(0, 2) # end of file
94 f.write("\n")
95 f.write(
96 textwrap.dedent(f"""\
97 vintf_compatibility_matrix {{
98 name: "{self.next_module_name}",
99 }}
100 """))
101
102 next_kernel_configs = check_output(
103 """grep -rh name: | sed -E 's/^.*"(.*)".*/\\1/g'""",
104 cwd=self.top / "kernel/configs" /
105 self.level_to_letter[self.next_level].lower(),
106 text=True,
107 shell=True,
108 ).splitlines()
109 print(next_kernel_configs)
110
111 check_call([
112 "bpmodify", "-w", "-m", self.next_module_name, "-property", "stem",
113 "-str", self.next_xml.name, android_bp
114 ])
115
116 check_call([
117 "bpmodify", "-w", "-m", self.next_module_name, "-property", "srcs",
118 "-a",
119 self.next_xml.relative_to(android_bp.parent), android_bp
120 ])
121
122 check_call([
123 "bpmodify", "-w", "-m", self.next_module_name, "-property",
124 "kernel_configs", "-a", " ".join(next_kernel_configs), android_bp
125 ])
126
127 def edit_android_mk(self):
128 android_mk = self.interfaces_dir / "compatibility_matrices/Android.mk"
Devin Moore4be20f72024-02-01 21:39:36 +0000129 lines = []
Yifan Hongace13de2023-04-28 15:54:04 -0700130 with open(android_mk) as f:
131 if self.next_module_name in f.read():
132 return
133 f.seek(0)
Devin Moore4be20f72024-02-01 21:39:36 +0000134 for line in f:
135 if f" {self.device_module_name} \\\n" in line:
136 lines.append(f" {self.current_module_name} \\\n")
137
138 if self.current_module_name in line:
139 lines.append(f" {self.next_module_name} \\\n")
140 else:
141 lines.append(line)
142
Yifan Hongace13de2023-04-28 15:54:04 -0700143 with open(android_mk, "w") as f:
144 f.write("".join(lines))
145
146
147def main():
148 parser = argparse.ArgumentParser(description=__doc__)
149 parser.add_argument("current",
150 type=str,
151 help="VINTF level of the current version (e.g. 9)")
152 parser.add_argument("next",
153 type=str,
154 help="VINTF level of the next version (e.g. 10)")
155 cmdline_args = parser.parse_args()
156
157 Bump(cmdline_args).run()
158
159
160if __name__ == "__main__":
161 main()