blob: 91f58d4387a5a306cdbf0dc0f0d10585a2c0ddaf [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.
Yifan Hongace13de2023-04-28 15:54:04 -070019"""
20
21import argparse
22import os
23import pathlib
Justin Yuncb8fb432024-07-19 09:29:45 +090024import re
Yifan Hongace13de2023-04-28 15:54:04 -070025import subprocess
26import textwrap
27
28
29def check_call(*args, **kwargs):
30 print(args)
31 subprocess.check_call(*args, **kwargs)
32
33
34def check_output(*args, **kwargs):
35 print(args)
36 return subprocess.check_output(*args, **kwargs)
37
38
39class Bump(object):
40
41 def __init__(self, cmdline_args):
42 self.top = pathlib.Path(os.environ["ANDROID_BUILD_TOP"])
43 self.interfaces_dir = self.top / "hardware/interfaces"
44
Devin Moore04259162024-02-06 22:52:32 +000045 self.current_level = cmdline_args.current_level
46 self.current_letter = cmdline_args.current_letter
Justin Yuncb8fb432024-07-19 09:29:45 +090047 self.current_version = cmdline_args.platform_version
Devin Moored07ca2b2025-01-13 18:18:12 +000048 self.next_version = cmdline_args.next_platform_version
Yifan Hongace13de2023-04-28 15:54:04 -070049 self.current_module_name = f"framework_compatibility_matrix.{self.current_level}.xml"
50 self.current_xml = self.interfaces_dir / f"compatibility_matrices/compatibility_matrix.{self.current_level}.xml"
Devin Moore4be20f72024-02-01 21:39:36 +000051 self.device_module_name = "framework_compatibility_matrix.device.xml"
Yifan Hongace13de2023-04-28 15:54:04 -070052
Devin Moore04259162024-02-06 22:52:32 +000053 self.next_level = cmdline_args.next_level
54 self.next_letter = cmdline_args.next_letter
Yifan Hongace13de2023-04-28 15:54:04 -070055 self.next_module_name = f"framework_compatibility_matrix.{self.next_level}.xml"
56 self.next_xml = self.interfaces_dir / f"compatibility_matrices/compatibility_matrix.{self.next_level}.xml"
57
Yifan Hongace13de2023-04-28 15:54:04 -070058 def run(self):
59 self.bump_kernel_configs()
60 self.copy_matrix()
61 self.edit_android_bp()
Justin Yuncb8fb432024-07-19 09:29:45 +090062 self.bump_libvintf()
Yifan Hongace13de2023-04-28 15:54:04 -070063
Yifan Hongace13de2023-04-28 15:54:04 -070064 def bump_kernel_configs(self):
65 check_call([
66 self.top / "kernel/configs/tools/bump.py",
Justin Yuncb8fb432024-07-19 09:29:45 +090067 self.current_letter.lower(),
68 self.next_letter.lower(),
Yifan Hongace13de2023-04-28 15:54:04 -070069 ])
70
71 def copy_matrix(self):
Devin Moore4be20f72024-02-01 21:39:36 +000072 with open(self.current_xml) as f_current, open(self.next_xml, "w") as f_next:
73 f_next.write(f_current.read().replace(f"level=\"{self.current_level}\"", f"level=\"{self.next_level}\""))
Yifan Hongace13de2023-04-28 15:54:04 -070074
75 def edit_android_bp(self):
76 android_bp = self.interfaces_dir / "compatibility_matrices/Android.bp"
77
78 with open(android_bp, "r+") as f:
79 if self.next_module_name not in f.read():
80 f.seek(0, 2) # end of file
81 f.write("\n")
82 f.write(
83 textwrap.dedent(f"""\
84 vintf_compatibility_matrix {{
85 name: "{self.next_module_name}",
86 }}
87 """))
88
89 next_kernel_configs = check_output(
90 """grep -rh name: | sed -E 's/^.*"(.*)".*/\\1/g'""",
91 cwd=self.top / "kernel/configs" /
Justin Yuncb8fb432024-07-19 09:29:45 +090092 self.next_letter.lower(),
Yifan Hongace13de2023-04-28 15:54:04 -070093 text=True,
94 shell=True,
95 ).splitlines()
96 print(next_kernel_configs)
97
98 check_call([
99 "bpmodify", "-w", "-m", self.next_module_name, "-property", "stem",
100 "-str", self.next_xml.name, android_bp
101 ])
102
103 check_call([
104 "bpmodify", "-w", "-m", self.next_module_name, "-property", "srcs",
105 "-a",
106 self.next_xml.relative_to(android_bp.parent), android_bp
107 ])
108
109 check_call([
110 "bpmodify", "-w", "-m", self.next_module_name, "-property",
111 "kernel_configs", "-a", " ".join(next_kernel_configs), android_bp
112 ])
113
Devin Mooref28b6952024-09-12 18:09:21 +0000114 # update the SYSTEM_MATRIX_DEPS variable and the phony module's
115 # product_variables entry.
116 lines = []
117 with open(android_bp) as f:
118 for line in f:
119 if f" \"{self.device_module_name}\",\n" in line:
120 lines.append(f" \"{self.current_module_name}\",\n")
121
122 if f" \"{self.current_module_name}\",\n" in line:
123 lines.append(f" \"{self.next_module_name}\",\n")
124 else:
125 lines.append(line)
126
127 with open(android_bp, "w") as f:
128 f.write("".join(lines))
129
Justin Yuncb8fb432024-07-19 09:29:45 +0900130 def bump_libvintf(self):
131 if not self.current_version:
132 print("Skip libvintf update...")
133 return
134 try:
135 check_call(["grep", "-h",
Devin Moored07ca2b2025-01-13 18:18:12 +0000136 f"{self.next_letter.upper()} = {self.next_level}",
Devin Moore6d9b76b2025-01-13 18:09:14 +0000137 f"{self.top}/system/libvintf/include/vintf/Level.h"])
Justin Yuncb8fb432024-07-19 09:29:45 +0900138 except subprocess.CalledProcessError:
139 print("Adding new API level to libvintf")
Devin Moore6d9b76b2025-01-13 18:09:14 +0000140 add_lines_above(f"{self.top}/system/libvintf/analyze_matrix/analyze_matrix.cpp",
Justin Yuncb8fb432024-07-19 09:29:45 +0900141 " case Level::UNSPECIFIED:",
142 textwrap.indent(textwrap.dedent(f"""\
Devin Moored07ca2b2025-01-13 18:18:12 +0000143 case Level::{self.next_letter.upper()}:
144 return "Android {self.next_version} ({self.next_letter.upper()})";"""),
Justin Yuncb8fb432024-07-19 09:29:45 +0900145 " "*2))
Devin Moore6d9b76b2025-01-13 18:09:14 +0000146 add_lines_above(f"{self.top}/system/libvintf/include/vintf/Level.h",
Justin Yuncb8fb432024-07-19 09:29:45 +0900147 " // To add new values:",
Devin Moored07ca2b2025-01-13 18:18:12 +0000148 f" {self.next_letter.upper()} = {self.next_level},")
Devin Moore6d9b76b2025-01-13 18:09:14 +0000149 add_lines_above(f"{self.top}/system/libvintf/include/vintf/Level.h",
Justin Yuncb8fb432024-07-19 09:29:45 +0900150 " Level::UNSPECIFIED,",
Devin Moored07ca2b2025-01-13 18:18:12 +0000151 f" Level::{self.next_letter.upper()},")
Devin Moore6d9b76b2025-01-13 18:09:14 +0000152 add_lines_above(f"{self.top}/system/libvintf/RuntimeInfo.cpp",
Justin Yuncb8fb432024-07-19 09:29:45 +0900153 " // Add more levels above this line.",
154 textwrap.indent(textwrap.dedent(f"""\
Devin Moored07ca2b2025-01-13 18:18:12 +0000155 case {self.next_version}: {{
156 ret = Level::{self.next_letter.upper()};
Justin Yuncb8fb432024-07-19 09:29:45 +0900157 }} break;"""),
158 " "*3))
159
160
161def add_lines_above(file, pattern, lines):
162 with open(file, 'r+') as f:
163 text = f.read()
164 split_text = re.split(rf"\n{pattern}\n", text)
165 if len(split_text) != 2:
166 # Only one pattern must be found, otherwise the source must be
167 # changed unexpectedly.
168 raise Exception(
169 f'Pattern "{pattern}" not found or multiple patterns found in {file}')
170 f.seek(0)
171 f.write(f"\n{lines}\n{pattern}\n".join(split_text))
172 f.truncate()
173
Yifan Hongace13de2023-04-28 15:54:04 -0700174
175def main():
176 parser = argparse.ArgumentParser(description=__doc__)
Devin Moore04259162024-02-06 22:52:32 +0000177 parser.add_argument("current_level",
Yifan Hongace13de2023-04-28 15:54:04 -0700178 type=str,
Justin Yuncb8fb432024-07-19 09:29:45 +0900179 help="VINTF level of the current version (e.g. 202404)")
Devin Moore04259162024-02-06 22:52:32 +0000180 parser.add_argument("next_level",
Yifan Hongace13de2023-04-28 15:54:04 -0700181 type=str,
Justin Yuncb8fb432024-07-19 09:29:45 +0900182 help="VINTF level of the next version (e.g. 202504)")
Devin Moore04259162024-02-06 22:52:32 +0000183 parser.add_argument("current_letter",
184 type=str,
Devin Moore9434f192024-12-17 17:52:31 +0000185 help="Letter of the API level of the current version (e.g. b)")
Devin Moore04259162024-02-06 22:52:32 +0000186 parser.add_argument("next_letter",
187 type=str,
Devin Moore9434f192024-12-17 17:52:31 +0000188 help="Letter of the API level of the next version (e.g. c)")
Justin Yuncb8fb432024-07-19 09:29:45 +0900189 parser.add_argument("platform_version",
190 type=str,
191 nargs="?",
Devin Moored07ca2b2025-01-13 18:18:12 +0000192 help="Current Android release version number (e.g. 16)")
193 parser.add_argument("next_platform_version",
194 type=str,
195 nargs="?",
196 help="Next Android release version number number (e.g. 17)")
Yifan Hongace13de2023-04-28 15:54:04 -0700197 cmdline_args = parser.parse_args()
198
199 Bump(cmdline_args).run()
200
201
202if __name__ == "__main__":
203 main()