Yifan Hong | ace13de | 2023-04-28 15:54:04 -0700 | [diff] [blame] | 1 | #!/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 | """ |
| 18 | Creates the next compatibility matrix. |
Yifan Hong | ace13de | 2023-04-28 15:54:04 -0700 | [diff] [blame] | 19 | """ |
| 20 | |
| 21 | import argparse |
| 22 | import os |
| 23 | import pathlib |
Justin Yun | cb8fb43 | 2024-07-19 09:29:45 +0900 | [diff] [blame] | 24 | import re |
Yifan Hong | ace13de | 2023-04-28 15:54:04 -0700 | [diff] [blame] | 25 | import subprocess |
| 26 | import textwrap |
| 27 | |
| 28 | |
| 29 | def check_call(*args, **kwargs): |
| 30 | print(args) |
| 31 | subprocess.check_call(*args, **kwargs) |
| 32 | |
| 33 | |
| 34 | def check_output(*args, **kwargs): |
| 35 | print(args) |
| 36 | return subprocess.check_output(*args, **kwargs) |
| 37 | |
| 38 | |
| 39 | class 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 Moore | 0425916 | 2024-02-06 22:52:32 +0000 | [diff] [blame] | 45 | self.current_level = cmdline_args.current_level |
| 46 | self.current_letter = cmdline_args.current_letter |
Justin Yun | cb8fb43 | 2024-07-19 09:29:45 +0900 | [diff] [blame] | 47 | self.current_version = cmdline_args.platform_version |
Devin Moore | d07ca2b | 2025-01-13 18:18:12 +0000 | [diff] [blame] | 48 | self.next_version = cmdline_args.next_platform_version |
Yifan Hong | ace13de | 2023-04-28 15:54:04 -0700 | [diff] [blame] | 49 | 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 Moore | 4be20f7 | 2024-02-01 21:39:36 +0000 | [diff] [blame] | 51 | self.device_module_name = "framework_compatibility_matrix.device.xml" |
Yifan Hong | ace13de | 2023-04-28 15:54:04 -0700 | [diff] [blame] | 52 | |
Devin Moore | 0425916 | 2024-02-06 22:52:32 +0000 | [diff] [blame] | 53 | self.next_level = cmdline_args.next_level |
| 54 | self.next_letter = cmdline_args.next_letter |
Devin Moore | 7ddc2a5 | 2025-01-21 20:18:57 +0000 | [diff] [blame^] | 55 | self.current_sdk = cmdline_args.current_sdk |
| 56 | self.next_sdk = cmdline_args.next_sdk |
Yifan Hong | ace13de | 2023-04-28 15:54:04 -0700 | [diff] [blame] | 57 | self.next_module_name = f"framework_compatibility_matrix.{self.next_level}.xml" |
| 58 | self.next_xml = self.interfaces_dir / f"compatibility_matrices/compatibility_matrix.{self.next_level}.xml" |
| 59 | |
Yifan Hong | ace13de | 2023-04-28 15:54:04 -0700 | [diff] [blame] | 60 | def run(self): |
| 61 | self.bump_kernel_configs() |
| 62 | self.copy_matrix() |
| 63 | self.edit_android_bp() |
Justin Yun | cb8fb43 | 2024-07-19 09:29:45 +0900 | [diff] [blame] | 64 | self.bump_libvintf() |
Devin Moore | a4155ed | 2025-01-17 23:31:46 +0000 | [diff] [blame] | 65 | self.bump_libvts_vintf() |
Devin Moore | 7ddc2a5 | 2025-01-21 20:18:57 +0000 | [diff] [blame^] | 66 | self.bump_cuttlefish() |
Yifan Hong | ace13de | 2023-04-28 15:54:04 -0700 | [diff] [blame] | 67 | |
Yifan Hong | ace13de | 2023-04-28 15:54:04 -0700 | [diff] [blame] | 68 | def bump_kernel_configs(self): |
| 69 | check_call([ |
| 70 | self.top / "kernel/configs/tools/bump.py", |
Justin Yun | cb8fb43 | 2024-07-19 09:29:45 +0900 | [diff] [blame] | 71 | self.current_letter.lower(), |
| 72 | self.next_letter.lower(), |
Yifan Hong | ace13de | 2023-04-28 15:54:04 -0700 | [diff] [blame] | 73 | ]) |
| 74 | |
| 75 | def copy_matrix(self): |
Devin Moore | 4be20f7 | 2024-02-01 21:39:36 +0000 | [diff] [blame] | 76 | with open(self.current_xml) as f_current, open(self.next_xml, "w") as f_next: |
| 77 | f_next.write(f_current.read().replace(f"level=\"{self.current_level}\"", f"level=\"{self.next_level}\"")) |
Yifan Hong | ace13de | 2023-04-28 15:54:04 -0700 | [diff] [blame] | 78 | |
| 79 | def edit_android_bp(self): |
| 80 | android_bp = self.interfaces_dir / "compatibility_matrices/Android.bp" |
| 81 | |
| 82 | with open(android_bp, "r+") as f: |
| 83 | if self.next_module_name not in f.read(): |
| 84 | f.seek(0, 2) # end of file |
| 85 | f.write("\n") |
| 86 | f.write( |
| 87 | textwrap.dedent(f"""\ |
| 88 | vintf_compatibility_matrix {{ |
| 89 | name: "{self.next_module_name}", |
| 90 | }} |
| 91 | """)) |
| 92 | |
| 93 | next_kernel_configs = check_output( |
| 94 | """grep -rh name: | sed -E 's/^.*"(.*)".*/\\1/g'""", |
| 95 | cwd=self.top / "kernel/configs" / |
Justin Yun | cb8fb43 | 2024-07-19 09:29:45 +0900 | [diff] [blame] | 96 | self.next_letter.lower(), |
Yifan Hong | ace13de | 2023-04-28 15:54:04 -0700 | [diff] [blame] | 97 | text=True, |
| 98 | shell=True, |
| 99 | ).splitlines() |
| 100 | print(next_kernel_configs) |
| 101 | |
| 102 | check_call([ |
| 103 | "bpmodify", "-w", "-m", self.next_module_name, "-property", "stem", |
| 104 | "-str", self.next_xml.name, android_bp |
| 105 | ]) |
| 106 | |
| 107 | check_call([ |
| 108 | "bpmodify", "-w", "-m", self.next_module_name, "-property", "srcs", |
| 109 | "-a", |
| 110 | self.next_xml.relative_to(android_bp.parent), android_bp |
| 111 | ]) |
| 112 | |
| 113 | check_call([ |
| 114 | "bpmodify", "-w", "-m", self.next_module_name, "-property", |
| 115 | "kernel_configs", "-a", " ".join(next_kernel_configs), android_bp |
| 116 | ]) |
| 117 | |
Devin Moore | faa5b0e | 2025-01-08 18:36:14 +0000 | [diff] [blame] | 118 | # Replace the phony module's product_variables entry to add the new FCM |
| 119 | # to the development targets (trunk* configs). |
Devin Moore | f28b695 | 2024-09-12 18:09:21 +0000 | [diff] [blame] | 120 | lines = [] |
| 121 | with open(android_bp) as f: |
| 122 | for line in f: |
Devin Moore | f28b695 | 2024-09-12 18:09:21 +0000 | [diff] [blame] | 123 | if f" \"{self.current_module_name}\",\n" in line: |
| 124 | lines.append(f" \"{self.next_module_name}\",\n") |
| 125 | else: |
| 126 | lines.append(line) |
| 127 | |
| 128 | with open(android_bp, "w") as f: |
| 129 | f.write("".join(lines)) |
| 130 | |
Justin Yun | cb8fb43 | 2024-07-19 09:29:45 +0900 | [diff] [blame] | 131 | def bump_libvintf(self): |
| 132 | if not self.current_version: |
| 133 | print("Skip libvintf update...") |
| 134 | return |
| 135 | try: |
| 136 | check_call(["grep", "-h", |
Devin Moore | d07ca2b | 2025-01-13 18:18:12 +0000 | [diff] [blame] | 137 | f"{self.next_letter.upper()} = {self.next_level}", |
Devin Moore | 6d9b76b | 2025-01-13 18:09:14 +0000 | [diff] [blame] | 138 | f"{self.top}/system/libvintf/include/vintf/Level.h"]) |
Justin Yun | cb8fb43 | 2024-07-19 09:29:45 +0900 | [diff] [blame] | 139 | except subprocess.CalledProcessError: |
| 140 | print("Adding new API level to libvintf") |
Devin Moore | 6d9b76b | 2025-01-13 18:09:14 +0000 | [diff] [blame] | 141 | add_lines_above(f"{self.top}/system/libvintf/analyze_matrix/analyze_matrix.cpp", |
Justin Yun | cb8fb43 | 2024-07-19 09:29:45 +0900 | [diff] [blame] | 142 | " case Level::UNSPECIFIED:", |
| 143 | textwrap.indent(textwrap.dedent(f"""\ |
Devin Moore | d07ca2b | 2025-01-13 18:18:12 +0000 | [diff] [blame] | 144 | case Level::{self.next_letter.upper()}: |
| 145 | return "Android {self.next_version} ({self.next_letter.upper()})";"""), |
Justin Yun | cb8fb43 | 2024-07-19 09:29:45 +0900 | [diff] [blame] | 146 | " "*2)) |
Devin Moore | 6d9b76b | 2025-01-13 18:09:14 +0000 | [diff] [blame] | 147 | add_lines_above(f"{self.top}/system/libvintf/include/vintf/Level.h", |
Justin Yun | cb8fb43 | 2024-07-19 09:29:45 +0900 | [diff] [blame] | 148 | " // To add new values:", |
Devin Moore | d07ca2b | 2025-01-13 18:18:12 +0000 | [diff] [blame] | 149 | f" {self.next_letter.upper()} = {self.next_level},") |
Devin Moore | 6d9b76b | 2025-01-13 18:09:14 +0000 | [diff] [blame] | 150 | add_lines_above(f"{self.top}/system/libvintf/include/vintf/Level.h", |
Justin Yun | cb8fb43 | 2024-07-19 09:29:45 +0900 | [diff] [blame] | 151 | " Level::UNSPECIFIED,", |
Devin Moore | d07ca2b | 2025-01-13 18:18:12 +0000 | [diff] [blame] | 152 | f" Level::{self.next_letter.upper()},") |
Devin Moore | 6d9b76b | 2025-01-13 18:09:14 +0000 | [diff] [blame] | 153 | add_lines_above(f"{self.top}/system/libvintf/RuntimeInfo.cpp", |
Justin Yun | cb8fb43 | 2024-07-19 09:29:45 +0900 | [diff] [blame] | 154 | " // Add more levels above this line.", |
| 155 | textwrap.indent(textwrap.dedent(f"""\ |
Devin Moore | d07ca2b | 2025-01-13 18:18:12 +0000 | [diff] [blame] | 156 | case {self.next_version}: {{ |
| 157 | ret = Level::{self.next_letter.upper()}; |
Justin Yun | cb8fb43 | 2024-07-19 09:29:45 +0900 | [diff] [blame] | 158 | }} break;"""), |
| 159 | " "*3)) |
| 160 | |
Devin Moore | a4155ed | 2025-01-17 23:31:46 +0000 | [diff] [blame] | 161 | def bump_libvts_vintf(self): |
| 162 | if not self.current_version: |
| 163 | print("Skip libvts_vintf update...") |
| 164 | return |
| 165 | try: |
| 166 | check_call(["grep", "-h", |
| 167 | f"{self.next_level}, Level::{self.next_letter.upper()}", |
| 168 | f"{self.top}/test/vts-testcase/hal/treble/vintf/libvts_vintf_test_common/common.cpp"]) |
| 169 | print("libvts_vintf is already up-to-date") |
| 170 | except subprocess.CalledProcessError: |
| 171 | print("Adding new API level to libvts_vintf") |
| 172 | add_lines_below(f"{self.top}/test/vts-testcase/hal/treble/vintf/libvts_vintf_test_common/common.cpp", |
| 173 | f" {{{self.current_level}, Level::{self.current_letter.upper()}}},", |
| 174 | f" {{{self.next_level}, Level::{self.next_letter.upper()}}},\n") |
Justin Yun | cb8fb43 | 2024-07-19 09:29:45 +0900 | [diff] [blame] | 175 | |
Devin Moore | 7ddc2a5 | 2025-01-21 20:18:57 +0000 | [diff] [blame^] | 176 | def bump_cuttlefish(self): |
| 177 | if not self.next_sdk: |
| 178 | print("Skip Cuttlefish update...") |
| 179 | return |
| 180 | cf_mk_file = f"{self.top}/device/google/cuttlefish/shared/device.mk" |
| 181 | try: |
| 182 | check_call(["grep", "-h", |
| 183 | f"PRODUCT_SHIPPING_API_LEVEL := {self.next_sdk}", |
| 184 | cf_mk_file]) |
| 185 | print("Cuttlefish is already up-to-date") |
| 186 | except subprocess.CalledProcessError: |
| 187 | print("Bumping Cuttlefish to the next SHIPPING_API_LEVEL") |
| 188 | final_lines = [] |
| 189 | with open(cf_mk_file, 'r+') as f: |
| 190 | for line in f: |
| 191 | if f"PRODUCT_SHIPPING_API_LEVEL := {self.current_sdk}" in line: |
| 192 | final_lines.append(f"PRODUCT_SHIPPING_API_LEVEL := {self.next_sdk}\n") |
| 193 | elif line.startswith("PRODUCT_SHIPPING_API_LEVEL :="): |
| 194 | # this is the previous SDK level. |
| 195 | final_lines.append(f"PRODUCT_SHIPPING_API_LEVEL := {self.current_sdk}\n") |
| 196 | else: |
| 197 | final_lines.append(line) |
| 198 | f.seek(0) |
| 199 | f.write("".join(final_lines)) |
| 200 | f.truncate() |
| 201 | final_lines = [] |
| 202 | with open(f"{self.top}/device/google/cuttlefish/shared/config/previous_manifest.xml", 'r+') as f: |
| 203 | for line in f: |
| 204 | if "target-level=" in line: |
| 205 | final_lines.append(f"<manifest version=\"1.0\" type=\"device\" target-level=\"{self.current_level}\">\n") |
| 206 | else: |
| 207 | final_lines.append(line) |
| 208 | f.seek(0) |
| 209 | f.write("".join(final_lines)) |
| 210 | f.truncate() |
| 211 | |
| 212 | final_lines = [] |
| 213 | with open(f"{self.top}/device/google/cuttlefish/shared/config/manifest.xml", 'r+') as f: |
| 214 | for line in f: |
| 215 | if "target-level=" in line: |
| 216 | final_lines.append(f"<manifest version=\"1.0\" type=\"device\" target-level=\"{self.next_level}\">\n") |
| 217 | else: |
| 218 | final_lines.append(line) |
| 219 | f.seek(0) |
| 220 | f.write("".join(final_lines)) |
| 221 | f.truncate() |
| 222 | |
Justin Yun | cb8fb43 | 2024-07-19 09:29:45 +0900 | [diff] [blame] | 223 | def add_lines_above(file, pattern, lines): |
| 224 | with open(file, 'r+') as f: |
| 225 | text = f.read() |
| 226 | split_text = re.split(rf"\n{pattern}\n", text) |
| 227 | if len(split_text) != 2: |
| 228 | # Only one pattern must be found, otherwise the source must be |
| 229 | # changed unexpectedly. |
| 230 | raise Exception( |
| 231 | f'Pattern "{pattern}" not found or multiple patterns found in {file}') |
| 232 | f.seek(0) |
| 233 | f.write(f"\n{lines}\n{pattern}\n".join(split_text)) |
| 234 | f.truncate() |
| 235 | |
Devin Moore | a4155ed | 2025-01-17 23:31:46 +0000 | [diff] [blame] | 236 | def add_lines_below(file, pattern, lines): |
| 237 | final_lines = [] |
| 238 | with open(file, 'r+') as f: |
| 239 | for line in f: |
| 240 | final_lines.append(line) |
| 241 | if pattern in line: |
| 242 | final_lines.append(lines) |
| 243 | f.seek(0) |
| 244 | f.write("".join(final_lines)) |
| 245 | f.truncate() |
Yifan Hong | ace13de | 2023-04-28 15:54:04 -0700 | [diff] [blame] | 246 | |
| 247 | def main(): |
| 248 | parser = argparse.ArgumentParser(description=__doc__) |
Devin Moore | 0425916 | 2024-02-06 22:52:32 +0000 | [diff] [blame] | 249 | parser.add_argument("current_level", |
Yifan Hong | ace13de | 2023-04-28 15:54:04 -0700 | [diff] [blame] | 250 | type=str, |
Justin Yun | cb8fb43 | 2024-07-19 09:29:45 +0900 | [diff] [blame] | 251 | help="VINTF level of the current version (e.g. 202404)") |
Devin Moore | 0425916 | 2024-02-06 22:52:32 +0000 | [diff] [blame] | 252 | parser.add_argument("next_level", |
Yifan Hong | ace13de | 2023-04-28 15:54:04 -0700 | [diff] [blame] | 253 | type=str, |
Justin Yun | cb8fb43 | 2024-07-19 09:29:45 +0900 | [diff] [blame] | 254 | help="VINTF level of the next version (e.g. 202504)") |
Devin Moore | 0425916 | 2024-02-06 22:52:32 +0000 | [diff] [blame] | 255 | parser.add_argument("current_letter", |
| 256 | type=str, |
Devin Moore | 9434f19 | 2024-12-17 17:52:31 +0000 | [diff] [blame] | 257 | help="Letter of the API level of the current version (e.g. b)") |
Devin Moore | 0425916 | 2024-02-06 22:52:32 +0000 | [diff] [blame] | 258 | parser.add_argument("next_letter", |
| 259 | type=str, |
Devin Moore | 9434f19 | 2024-12-17 17:52:31 +0000 | [diff] [blame] | 260 | help="Letter of the API level of the next version (e.g. c)") |
Justin Yun | cb8fb43 | 2024-07-19 09:29:45 +0900 | [diff] [blame] | 261 | parser.add_argument("platform_version", |
| 262 | type=str, |
| 263 | nargs="?", |
Devin Moore | d07ca2b | 2025-01-13 18:18:12 +0000 | [diff] [blame] | 264 | help="Current Android release version number (e.g. 16)") |
| 265 | parser.add_argument("next_platform_version", |
| 266 | type=str, |
| 267 | nargs="?", |
| 268 | help="Next Android release version number number (e.g. 17)") |
Devin Moore | 7ddc2a5 | 2025-01-21 20:18:57 +0000 | [diff] [blame^] | 269 | parser.add_argument("current_sdk", |
| 270 | type=str, |
| 271 | nargs="?", |
| 272 | help="Version of the current SDK API level (e.g. 36)") |
| 273 | parser.add_argument("next_sdk", |
| 274 | type=str, |
| 275 | nargs="?", |
| 276 | help="Version of the next SDK API level(e.g. 37)") |
| 277 | |
Yifan Hong | ace13de | 2023-04-28 15:54:04 -0700 | [diff] [blame] | 278 | cmdline_args = parser.parse_args() |
| 279 | |
| 280 | Bump(cmdline_args).run() |
| 281 | |
| 282 | |
| 283 | if __name__ == "__main__": |
| 284 | main() |