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 |
Yifan Hong | ace13de | 2023-04-28 15:54:04 -0700 | [diff] [blame] | 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 Moore | 4be20f7 | 2024-02-01 21:39:36 +0000 | [diff] [blame] | 50 | self.device_module_name = "framework_compatibility_matrix.device.xml" |
Yifan Hong | ace13de | 2023-04-28 15:54:04 -0700 | [diff] [blame] | 51 | |
Devin Moore | 0425916 | 2024-02-06 22:52:32 +0000 | [diff] [blame] | 52 | self.next_level = cmdline_args.next_level |
| 53 | self.next_letter = cmdline_args.next_letter |
Yifan Hong | ace13de | 2023-04-28 15:54:04 -0700 | [diff] [blame] | 54 | self.next_module_name = f"framework_compatibility_matrix.{self.next_level}.xml" |
| 55 | self.next_xml = self.interfaces_dir / f"compatibility_matrices/compatibility_matrix.{self.next_level}.xml" |
| 56 | |
Yifan Hong | ace13de | 2023-04-28 15:54:04 -0700 | [diff] [blame] | 57 | def run(self): |
| 58 | self.bump_kernel_configs() |
| 59 | self.copy_matrix() |
| 60 | self.edit_android_bp() |
| 61 | self.edit_android_mk() |
Justin Yun | cb8fb43 | 2024-07-19 09:29:45 +0900 | [diff] [blame] | 62 | self.bump_libvintf() |
Yifan Hong | ace13de | 2023-04-28 15:54:04 -0700 | [diff] [blame] | 63 | |
Yifan Hong | ace13de | 2023-04-28 15:54:04 -0700 | [diff] [blame] | 64 | def bump_kernel_configs(self): |
| 65 | check_call([ |
| 66 | self.top / "kernel/configs/tools/bump.py", |
Justin Yun | cb8fb43 | 2024-07-19 09:29:45 +0900 | [diff] [blame] | 67 | self.current_letter.lower(), |
| 68 | self.next_letter.lower(), |
Yifan Hong | ace13de | 2023-04-28 15:54:04 -0700 | [diff] [blame] | 69 | ]) |
| 70 | |
| 71 | def copy_matrix(self): |
Devin Moore | 4be20f7 | 2024-02-01 21:39:36 +0000 | [diff] [blame] | 72 | 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 Hong | ace13de | 2023-04-28 15:54:04 -0700 | [diff] [blame] | 74 | |
| 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 Yun | cb8fb43 | 2024-07-19 09:29:45 +0900 | [diff] [blame] | 92 | self.next_letter.lower(), |
Yifan Hong | ace13de | 2023-04-28 15:54:04 -0700 | [diff] [blame] | 93 | 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 Moore | f28b695 | 2024-09-12 18:09:21 +0000 | [diff] [blame] | 114 | # 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 | |
| 130 | |
| 131 | # This Android.mk file may be deprecated soon and the functionality is |
| 132 | # replaced by the soong phony module system_compatibility_matrix.xml. |
Yifan Hong | ace13de | 2023-04-28 15:54:04 -0700 | [diff] [blame] | 133 | def edit_android_mk(self): |
| 134 | android_mk = self.interfaces_dir / "compatibility_matrices/Android.mk" |
Devin Moore | 4be20f7 | 2024-02-01 21:39:36 +0000 | [diff] [blame] | 135 | lines = [] |
Yifan Hong | ace13de | 2023-04-28 15:54:04 -0700 | [diff] [blame] | 136 | with open(android_mk) as f: |
| 137 | if self.next_module_name in f.read(): |
| 138 | return |
| 139 | f.seek(0) |
Devin Moore | 4be20f7 | 2024-02-01 21:39:36 +0000 | [diff] [blame] | 140 | for line in f: |
| 141 | if f" {self.device_module_name} \\\n" in line: |
| 142 | lines.append(f" {self.current_module_name} \\\n") |
| 143 | |
| 144 | if self.current_module_name in line: |
| 145 | lines.append(f" {self.next_module_name} \\\n") |
| 146 | else: |
| 147 | lines.append(line) |
| 148 | |
Yifan Hong | ace13de | 2023-04-28 15:54:04 -0700 | [diff] [blame] | 149 | with open(android_mk, "w") as f: |
| 150 | f.write("".join(lines)) |
| 151 | |
Justin Yun | cb8fb43 | 2024-07-19 09:29:45 +0900 | [diff] [blame] | 152 | def bump_libvintf(self): |
| 153 | if not self.current_version: |
| 154 | print("Skip libvintf update...") |
| 155 | return |
| 156 | try: |
| 157 | check_call(["grep", "-h", |
| 158 | f"{self.current_letter.upper()} = {self.current_level}", |
| 159 | "system/libvintf/include/vintf/Level.h"]) |
| 160 | except subprocess.CalledProcessError: |
| 161 | print("Adding new API level to libvintf") |
| 162 | add_lines_above("system/libvintf/analyze_matrix/analyze_matrix.cpp", |
| 163 | " case Level::UNSPECIFIED:", |
| 164 | textwrap.indent(textwrap.dedent(f"""\ |
| 165 | case Level::{self.current_letter.upper()}: |
| 166 | return "Android {self.current_version} ({self.current_letter.upper()})";"""), |
| 167 | " "*2)) |
| 168 | add_lines_above("system/libvintf/include/vintf/Level.h", |
| 169 | " // To add new values:", |
| 170 | f" {self.current_letter.upper()} = {self.current_level},") |
| 171 | add_lines_above("system/libvintf/include/vintf/Level.h", |
| 172 | " Level::UNSPECIFIED,", |
| 173 | f" Level::{self.current_letter.upper()},") |
| 174 | add_lines_above("system/libvintf/RuntimeInfo.cpp", |
| 175 | " // Add more levels above this line.", |
| 176 | textwrap.indent(textwrap.dedent(f"""\ |
| 177 | case {self.current_version}: {{ |
| 178 | ret = Level::{self.current_letter.upper()}; |
| 179 | }} break;"""), |
| 180 | " "*3)) |
| 181 | |
| 182 | |
| 183 | def add_lines_above(file, pattern, lines): |
| 184 | with open(file, 'r+') as f: |
| 185 | text = f.read() |
| 186 | split_text = re.split(rf"\n{pattern}\n", text) |
| 187 | if len(split_text) != 2: |
| 188 | # Only one pattern must be found, otherwise the source must be |
| 189 | # changed unexpectedly. |
| 190 | raise Exception( |
| 191 | f'Pattern "{pattern}" not found or multiple patterns found in {file}') |
| 192 | f.seek(0) |
| 193 | f.write(f"\n{lines}\n{pattern}\n".join(split_text)) |
| 194 | f.truncate() |
| 195 | |
Yifan Hong | ace13de | 2023-04-28 15:54:04 -0700 | [diff] [blame] | 196 | |
| 197 | def main(): |
| 198 | parser = argparse.ArgumentParser(description=__doc__) |
Devin Moore | 0425916 | 2024-02-06 22:52:32 +0000 | [diff] [blame] | 199 | parser.add_argument("current_level", |
Yifan Hong | ace13de | 2023-04-28 15:54:04 -0700 | [diff] [blame] | 200 | type=str, |
Justin Yun | cb8fb43 | 2024-07-19 09:29:45 +0900 | [diff] [blame] | 201 | help="VINTF level of the current version (e.g. 202404)") |
Devin Moore | 0425916 | 2024-02-06 22:52:32 +0000 | [diff] [blame] | 202 | parser.add_argument("next_level", |
Yifan Hong | ace13de | 2023-04-28 15:54:04 -0700 | [diff] [blame] | 203 | type=str, |
Justin Yun | cb8fb43 | 2024-07-19 09:29:45 +0900 | [diff] [blame] | 204 | help="VINTF level of the next version (e.g. 202504)") |
Devin Moore | 0425916 | 2024-02-06 22:52:32 +0000 | [diff] [blame] | 205 | parser.add_argument("current_letter", |
| 206 | type=str, |
| 207 | help="Letter of the API level of the current version (e.g. v)") |
| 208 | parser.add_argument("next_letter", |
| 209 | type=str, |
| 210 | help="Letter of the API level of the next version (e.g. w)") |
Justin Yun | cb8fb43 | 2024-07-19 09:29:45 +0900 | [diff] [blame] | 211 | parser.add_argument("platform_version", |
| 212 | type=str, |
| 213 | nargs="?", |
| 214 | help="Android release version number number (e.g. 15)") |
Yifan Hong | ace13de | 2023-04-28 15:54:04 -0700 | [diff] [blame] | 215 | cmdline_args = parser.parse_args() |
| 216 | |
| 217 | Bump(cmdline_args).run() |
| 218 | |
| 219 | |
| 220 | if __name__ == "__main__": |
| 221 | main() |