1*4d7e907cSAndroid Build Coastguard Worker#!/usr/bin/env python3 2*4d7e907cSAndroid Build Coastguard Worker# 3*4d7e907cSAndroid Build Coastguard Worker# Copyright (C) 2023 The Android Open Source Project 4*4d7e907cSAndroid Build Coastguard Worker# 5*4d7e907cSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); 6*4d7e907cSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License. 7*4d7e907cSAndroid Build Coastguard Worker# You may obtain a copy of the License at 8*4d7e907cSAndroid Build Coastguard Worker# 9*4d7e907cSAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0 10*4d7e907cSAndroid Build Coastguard Worker# 11*4d7e907cSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 12*4d7e907cSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS, 13*4d7e907cSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14*4d7e907cSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and 15*4d7e907cSAndroid Build Coastguard Worker# limitations under the License. 16*4d7e907cSAndroid Build Coastguard Worker# 17*4d7e907cSAndroid Build Coastguard Worker""" 18*4d7e907cSAndroid Build Coastguard WorkerCreates the next compatibility matrix. 19*4d7e907cSAndroid Build Coastguard Worker""" 20*4d7e907cSAndroid Build Coastguard Worker 21*4d7e907cSAndroid Build Coastguard Workerimport argparse 22*4d7e907cSAndroid Build Coastguard Workerimport os 23*4d7e907cSAndroid Build Coastguard Workerimport pathlib 24*4d7e907cSAndroid Build Coastguard Workerimport re 25*4d7e907cSAndroid Build Coastguard Workerimport subprocess 26*4d7e907cSAndroid Build Coastguard Workerimport textwrap 27*4d7e907cSAndroid Build Coastguard Worker 28*4d7e907cSAndroid Build Coastguard Worker 29*4d7e907cSAndroid Build Coastguard Workerdef check_call(*args, **kwargs): 30*4d7e907cSAndroid Build Coastguard Worker print(args) 31*4d7e907cSAndroid Build Coastguard Worker subprocess.check_call(*args, **kwargs) 32*4d7e907cSAndroid Build Coastguard Worker 33*4d7e907cSAndroid Build Coastguard Worker 34*4d7e907cSAndroid Build Coastguard Workerdef check_output(*args, **kwargs): 35*4d7e907cSAndroid Build Coastguard Worker print(args) 36*4d7e907cSAndroid Build Coastguard Worker return subprocess.check_output(*args, **kwargs) 37*4d7e907cSAndroid Build Coastguard Worker 38*4d7e907cSAndroid Build Coastguard Worker 39*4d7e907cSAndroid Build Coastguard Workerclass Bump(object): 40*4d7e907cSAndroid Build Coastguard Worker 41*4d7e907cSAndroid Build Coastguard Worker def __init__(self, cmdline_args): 42*4d7e907cSAndroid Build Coastguard Worker self.top = pathlib.Path(os.environ["ANDROID_BUILD_TOP"]) 43*4d7e907cSAndroid Build Coastguard Worker self.interfaces_dir = self.top / "hardware/interfaces" 44*4d7e907cSAndroid Build Coastguard Worker 45*4d7e907cSAndroid Build Coastguard Worker self.current_level = cmdline_args.current_level 46*4d7e907cSAndroid Build Coastguard Worker self.current_letter = cmdline_args.current_letter 47*4d7e907cSAndroid Build Coastguard Worker self.current_version = cmdline_args.platform_version 48*4d7e907cSAndroid Build Coastguard Worker self.current_module_name = f"framework_compatibility_matrix.{self.current_level}.xml" 49*4d7e907cSAndroid Build Coastguard Worker self.current_xml = self.interfaces_dir / f"compatibility_matrices/compatibility_matrix.{self.current_level}.xml" 50*4d7e907cSAndroid Build Coastguard Worker self.device_module_name = "framework_compatibility_matrix.device.xml" 51*4d7e907cSAndroid Build Coastguard Worker 52*4d7e907cSAndroid Build Coastguard Worker self.next_level = cmdline_args.next_level 53*4d7e907cSAndroid Build Coastguard Worker self.next_letter = cmdline_args.next_letter 54*4d7e907cSAndroid Build Coastguard Worker self.next_module_name = f"framework_compatibility_matrix.{self.next_level}.xml" 55*4d7e907cSAndroid Build Coastguard Worker self.next_xml = self.interfaces_dir / f"compatibility_matrices/compatibility_matrix.{self.next_level}.xml" 56*4d7e907cSAndroid Build Coastguard Worker 57*4d7e907cSAndroid Build Coastguard Worker def run(self): 58*4d7e907cSAndroid Build Coastguard Worker self.bump_kernel_configs() 59*4d7e907cSAndroid Build Coastguard Worker self.copy_matrix() 60*4d7e907cSAndroid Build Coastguard Worker self.edit_android_bp() 61*4d7e907cSAndroid Build Coastguard Worker self.bump_libvintf() 62*4d7e907cSAndroid Build Coastguard Worker 63*4d7e907cSAndroid Build Coastguard Worker def bump_kernel_configs(self): 64*4d7e907cSAndroid Build Coastguard Worker check_call([ 65*4d7e907cSAndroid Build Coastguard Worker self.top / "kernel/configs/tools/bump.py", 66*4d7e907cSAndroid Build Coastguard Worker self.current_letter.lower(), 67*4d7e907cSAndroid Build Coastguard Worker self.next_letter.lower(), 68*4d7e907cSAndroid Build Coastguard Worker ]) 69*4d7e907cSAndroid Build Coastguard Worker 70*4d7e907cSAndroid Build Coastguard Worker def copy_matrix(self): 71*4d7e907cSAndroid Build Coastguard Worker with open(self.current_xml) as f_current, open(self.next_xml, "w") as f_next: 72*4d7e907cSAndroid Build Coastguard Worker f_next.write(f_current.read().replace(f"level=\"{self.current_level}\"", f"level=\"{self.next_level}\"")) 73*4d7e907cSAndroid Build Coastguard Worker 74*4d7e907cSAndroid Build Coastguard Worker def edit_android_bp(self): 75*4d7e907cSAndroid Build Coastguard Worker android_bp = self.interfaces_dir / "compatibility_matrices/Android.bp" 76*4d7e907cSAndroid Build Coastguard Worker 77*4d7e907cSAndroid Build Coastguard Worker with open(android_bp, "r+") as f: 78*4d7e907cSAndroid Build Coastguard Worker if self.next_module_name not in f.read(): 79*4d7e907cSAndroid Build Coastguard Worker f.seek(0, 2) # end of file 80*4d7e907cSAndroid Build Coastguard Worker f.write("\n") 81*4d7e907cSAndroid Build Coastguard Worker f.write( 82*4d7e907cSAndroid Build Coastguard Worker textwrap.dedent(f"""\ 83*4d7e907cSAndroid Build Coastguard Worker vintf_compatibility_matrix {{ 84*4d7e907cSAndroid Build Coastguard Worker name: "{self.next_module_name}", 85*4d7e907cSAndroid Build Coastguard Worker }} 86*4d7e907cSAndroid Build Coastguard Worker """)) 87*4d7e907cSAndroid Build Coastguard Worker 88*4d7e907cSAndroid Build Coastguard Worker next_kernel_configs = check_output( 89*4d7e907cSAndroid Build Coastguard Worker """grep -rh name: | sed -E 's/^.*"(.*)".*/\\1/g'""", 90*4d7e907cSAndroid Build Coastguard Worker cwd=self.top / "kernel/configs" / 91*4d7e907cSAndroid Build Coastguard Worker self.next_letter.lower(), 92*4d7e907cSAndroid Build Coastguard Worker text=True, 93*4d7e907cSAndroid Build Coastguard Worker shell=True, 94*4d7e907cSAndroid Build Coastguard Worker ).splitlines() 95*4d7e907cSAndroid Build Coastguard Worker print(next_kernel_configs) 96*4d7e907cSAndroid Build Coastguard Worker 97*4d7e907cSAndroid Build Coastguard Worker check_call([ 98*4d7e907cSAndroid Build Coastguard Worker "bpmodify", "-w", "-m", self.next_module_name, "-property", "stem", 99*4d7e907cSAndroid Build Coastguard Worker "-str", self.next_xml.name, android_bp 100*4d7e907cSAndroid Build Coastguard Worker ]) 101*4d7e907cSAndroid Build Coastguard Worker 102*4d7e907cSAndroid Build Coastguard Worker check_call([ 103*4d7e907cSAndroid Build Coastguard Worker "bpmodify", "-w", "-m", self.next_module_name, "-property", "srcs", 104*4d7e907cSAndroid Build Coastguard Worker "-a", 105*4d7e907cSAndroid Build Coastguard Worker self.next_xml.relative_to(android_bp.parent), android_bp 106*4d7e907cSAndroid Build Coastguard Worker ]) 107*4d7e907cSAndroid Build Coastguard Worker 108*4d7e907cSAndroid Build Coastguard Worker check_call([ 109*4d7e907cSAndroid Build Coastguard Worker "bpmodify", "-w", "-m", self.next_module_name, "-property", 110*4d7e907cSAndroid Build Coastguard Worker "kernel_configs", "-a", " ".join(next_kernel_configs), android_bp 111*4d7e907cSAndroid Build Coastguard Worker ]) 112*4d7e907cSAndroid Build Coastguard Worker 113*4d7e907cSAndroid Build Coastguard Worker # update the SYSTEM_MATRIX_DEPS variable and the phony module's 114*4d7e907cSAndroid Build Coastguard Worker # product_variables entry. 115*4d7e907cSAndroid Build Coastguard Worker lines = [] 116*4d7e907cSAndroid Build Coastguard Worker with open(android_bp) as f: 117*4d7e907cSAndroid Build Coastguard Worker for line in f: 118*4d7e907cSAndroid Build Coastguard Worker if f" \"{self.device_module_name}\",\n" in line: 119*4d7e907cSAndroid Build Coastguard Worker lines.append(f" \"{self.current_module_name}\",\n") 120*4d7e907cSAndroid Build Coastguard Worker 121*4d7e907cSAndroid Build Coastguard Worker if f" \"{self.current_module_name}\",\n" in line: 122*4d7e907cSAndroid Build Coastguard Worker lines.append(f" \"{self.next_module_name}\",\n") 123*4d7e907cSAndroid Build Coastguard Worker else: 124*4d7e907cSAndroid Build Coastguard Worker lines.append(line) 125*4d7e907cSAndroid Build Coastguard Worker 126*4d7e907cSAndroid Build Coastguard Worker with open(android_bp, "w") as f: 127*4d7e907cSAndroid Build Coastguard Worker f.write("".join(lines)) 128*4d7e907cSAndroid Build Coastguard Worker 129*4d7e907cSAndroid Build Coastguard Worker def bump_libvintf(self): 130*4d7e907cSAndroid Build Coastguard Worker if not self.current_version: 131*4d7e907cSAndroid Build Coastguard Worker print("Skip libvintf update...") 132*4d7e907cSAndroid Build Coastguard Worker return 133*4d7e907cSAndroid Build Coastguard Worker try: 134*4d7e907cSAndroid Build Coastguard Worker check_call(["grep", "-h", 135*4d7e907cSAndroid Build Coastguard Worker f"{self.current_letter.upper()} = {self.current_level}", 136*4d7e907cSAndroid Build Coastguard Worker "system/libvintf/include/vintf/Level.h"]) 137*4d7e907cSAndroid Build Coastguard Worker except subprocess.CalledProcessError: 138*4d7e907cSAndroid Build Coastguard Worker print("Adding new API level to libvintf") 139*4d7e907cSAndroid Build Coastguard Worker add_lines_above("system/libvintf/analyze_matrix/analyze_matrix.cpp", 140*4d7e907cSAndroid Build Coastguard Worker " case Level::UNSPECIFIED:", 141*4d7e907cSAndroid Build Coastguard Worker textwrap.indent(textwrap.dedent(f"""\ 142*4d7e907cSAndroid Build Coastguard Worker case Level::{self.current_letter.upper()}: 143*4d7e907cSAndroid Build Coastguard Worker return "Android {self.current_version} ({self.current_letter.upper()})";"""), 144*4d7e907cSAndroid Build Coastguard Worker " "*2)) 145*4d7e907cSAndroid Build Coastguard Worker add_lines_above("system/libvintf/include/vintf/Level.h", 146*4d7e907cSAndroid Build Coastguard Worker " // To add new values:", 147*4d7e907cSAndroid Build Coastguard Worker f" {self.current_letter.upper()} = {self.current_level},") 148*4d7e907cSAndroid Build Coastguard Worker add_lines_above("system/libvintf/include/vintf/Level.h", 149*4d7e907cSAndroid Build Coastguard Worker " Level::UNSPECIFIED,", 150*4d7e907cSAndroid Build Coastguard Worker f" Level::{self.current_letter.upper()},") 151*4d7e907cSAndroid Build Coastguard Worker add_lines_above("system/libvintf/RuntimeInfo.cpp", 152*4d7e907cSAndroid Build Coastguard Worker " // Add more levels above this line.", 153*4d7e907cSAndroid Build Coastguard Worker textwrap.indent(textwrap.dedent(f"""\ 154*4d7e907cSAndroid Build Coastguard Worker case {self.current_version}: {{ 155*4d7e907cSAndroid Build Coastguard Worker ret = Level::{self.current_letter.upper()}; 156*4d7e907cSAndroid Build Coastguard Worker }} break;"""), 157*4d7e907cSAndroid Build Coastguard Worker " "*3)) 158*4d7e907cSAndroid Build Coastguard Worker 159*4d7e907cSAndroid Build Coastguard Worker 160*4d7e907cSAndroid Build Coastguard Workerdef add_lines_above(file, pattern, lines): 161*4d7e907cSAndroid Build Coastguard Worker with open(file, 'r+') as f: 162*4d7e907cSAndroid Build Coastguard Worker text = f.read() 163*4d7e907cSAndroid Build Coastguard Worker split_text = re.split(rf"\n{pattern}\n", text) 164*4d7e907cSAndroid Build Coastguard Worker if len(split_text) != 2: 165*4d7e907cSAndroid Build Coastguard Worker # Only one pattern must be found, otherwise the source must be 166*4d7e907cSAndroid Build Coastguard Worker # changed unexpectedly. 167*4d7e907cSAndroid Build Coastguard Worker raise Exception( 168*4d7e907cSAndroid Build Coastguard Worker f'Pattern "{pattern}" not found or multiple patterns found in {file}') 169*4d7e907cSAndroid Build Coastguard Worker f.seek(0) 170*4d7e907cSAndroid Build Coastguard Worker f.write(f"\n{lines}\n{pattern}\n".join(split_text)) 171*4d7e907cSAndroid Build Coastguard Worker f.truncate() 172*4d7e907cSAndroid Build Coastguard Worker 173*4d7e907cSAndroid Build Coastguard Worker 174*4d7e907cSAndroid Build Coastguard Workerdef main(): 175*4d7e907cSAndroid Build Coastguard Worker parser = argparse.ArgumentParser(description=__doc__) 176*4d7e907cSAndroid Build Coastguard Worker parser.add_argument("current_level", 177*4d7e907cSAndroid Build Coastguard Worker type=str, 178*4d7e907cSAndroid Build Coastguard Worker help="VINTF level of the current version (e.g. 202404)") 179*4d7e907cSAndroid Build Coastguard Worker parser.add_argument("next_level", 180*4d7e907cSAndroid Build Coastguard Worker type=str, 181*4d7e907cSAndroid Build Coastguard Worker help="VINTF level of the next version (e.g. 202504)") 182*4d7e907cSAndroid Build Coastguard Worker parser.add_argument("current_letter", 183*4d7e907cSAndroid Build Coastguard Worker type=str, 184*4d7e907cSAndroid Build Coastguard Worker help="Letter of the API level of the current version (e.g. v)") 185*4d7e907cSAndroid Build Coastguard Worker parser.add_argument("next_letter", 186*4d7e907cSAndroid Build Coastguard Worker type=str, 187*4d7e907cSAndroid Build Coastguard Worker help="Letter of the API level of the next version (e.g. w)") 188*4d7e907cSAndroid Build Coastguard Worker parser.add_argument("platform_version", 189*4d7e907cSAndroid Build Coastguard Worker type=str, 190*4d7e907cSAndroid Build Coastguard Worker nargs="?", 191*4d7e907cSAndroid Build Coastguard Worker help="Android release version number number (e.g. 15)") 192*4d7e907cSAndroid Build Coastguard Worker cmdline_args = parser.parse_args() 193*4d7e907cSAndroid Build Coastguard Worker 194*4d7e907cSAndroid Build Coastguard Worker Bump(cmdline_args).run() 195*4d7e907cSAndroid Build Coastguard Worker 196*4d7e907cSAndroid Build Coastguard Worker 197*4d7e907cSAndroid Build Coastguard Workerif __name__ == "__main__": 198*4d7e907cSAndroid Build Coastguard Worker main() 199