1*105f6285SAndroid Build Coastguard Worker#!/usr/bin/python3 2*105f6285SAndroid Build Coastguard Worker# 3*105f6285SAndroid Build Coastguard Worker# Copyright (C) 2023 The Android Open Source Project 4*105f6285SAndroid Build Coastguard Worker# 5*105f6285SAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); you may not 6*105f6285SAndroid Build Coastguard Worker# use this file except in compliance with the License. You may obtain a copy of 7*105f6285SAndroid Build Coastguard Worker# the License at 8*105f6285SAndroid Build Coastguard Worker# 9*105f6285SAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0 10*105f6285SAndroid Build Coastguard Worker# 11*105f6285SAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 12*105f6285SAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13*105f6285SAndroid Build Coastguard Worker# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 14*105f6285SAndroid Build Coastguard Worker# License for the specific language governing permissions and limitations under 15*105f6285SAndroid Build Coastguard Worker# the License. 16*105f6285SAndroid Build Coastguard Worker 17*105f6285SAndroid Build Coastguard Workerimport argparse 18*105f6285SAndroid Build Coastguard Workerimport glob 19*105f6285SAndroid Build Coastguard Workerimport os 20*105f6285SAndroid Build Coastguard Workerimport subprocess 21*105f6285SAndroid Build Coastguard Workerimport tempfile 22*105f6285SAndroid Build Coastguard Worker 23*105f6285SAndroid Build Coastguard Workerfrom build_chd_debug_ramdisk import build_chd_debug_ramdisk, ImageOptions 24*105f6285SAndroid Build Coastguard Workerfrom build_chd_utils import copy_files, merge_chd_sepolicy, unzip_otatools 25*105f6285SAndroid Build Coastguard Worker 26*105f6285SAndroid Build Coastguard Worker"""Test command: 27*105f6285SAndroid Build Coastguard Worker 28*105f6285SAndroid Build Coastguard WorkerWORKSPACE=out/dist && \ 29*105f6285SAndroid Build Coastguard Workerpython3 tools/treble/cuttlefish/build_cf_hybrid_device.py \ 30*105f6285SAndroid Build Coastguard Worker --build_id 123456 \ 31*105f6285SAndroid Build Coastguard Worker --otatools_zip $WORKSPACE/otatools.zip \ 32*105f6285SAndroid Build Coastguard Worker --target chd-target \ 33*105f6285SAndroid Build Coastguard Worker --output_dir $WORKSPACE \ 34*105f6285SAndroid Build Coastguard Worker --framework_target_files_zip $WORKSPACE/device-target_files-*.zip \ 35*105f6285SAndroid Build Coastguard Worker --vendor_target_files_zip $WORKSPACE/cf_arm64_only_phone-target_files-*.zip 36*105f6285SAndroid Build Coastguard Worker""" 37*105f6285SAndroid Build Coastguard Worker 38*105f6285SAndroid Build Coastguard Worker 39*105f6285SAndroid Build Coastguard Workerdef _parse_args() -> argparse.Namespace: 40*105f6285SAndroid Build Coastguard Worker """Parse the arguments for building cuttlefish hybrid devices. 41*105f6285SAndroid Build Coastguard Worker 42*105f6285SAndroid Build Coastguard Worker Returns: 43*105f6285SAndroid Build Coastguard Worker An object of the parsed arguments. 44*105f6285SAndroid Build Coastguard Worker """ 45*105f6285SAndroid Build Coastguard Worker parser = argparse.ArgumentParser() 46*105f6285SAndroid Build Coastguard Worker 47*105f6285SAndroid Build Coastguard Worker parser.add_argument('--build_id', required=True, 48*105f6285SAndroid Build Coastguard Worker help='Build id.') 49*105f6285SAndroid Build Coastguard Worker parser.add_argument('--target', required=True, 50*105f6285SAndroid Build Coastguard Worker help='Target name of the cuttlefish hybrid build.') 51*105f6285SAndroid Build Coastguard Worker parser.add_argument('--otatools_zip', required=True, 52*105f6285SAndroid Build Coastguard Worker help='Path to the otatools.zip.') 53*105f6285SAndroid Build Coastguard Worker parser.add_argument('--output_dir', required=True, 54*105f6285SAndroid Build Coastguard Worker help='Path to the output directory of the hybrid build.') 55*105f6285SAndroid Build Coastguard Worker parser.add_argument('--framework_target_files_zip', required=True, 56*105f6285SAndroid Build Coastguard Worker help='glob pattern of framework target_files zip.') 57*105f6285SAndroid Build Coastguard Worker parser.add_argument('--vendor_target_files_zip', required=True, 58*105f6285SAndroid Build Coastguard Worker help='glob pattern of vendor target_files zip.') 59*105f6285SAndroid Build Coastguard Worker parser.add_argument('--copy_file', action='append', default=[], 60*105f6285SAndroid Build Coastguard Worker help='The file to be copied to output directory. ' 61*105f6285SAndroid Build Coastguard Worker 'The format is <src glob pattern>:<dst path>.') 62*105f6285SAndroid Build Coastguard Worker return parser.parse_args() 63*105f6285SAndroid Build Coastguard Worker 64*105f6285SAndroid Build Coastguard Worker 65*105f6285SAndroid Build Coastguard Workerdef run(temp_dir: str) -> None: 66*105f6285SAndroid Build Coastguard Worker args = _parse_args() 67*105f6285SAndroid Build Coastguard Worker 68*105f6285SAndroid Build Coastguard Worker # unzip otatools 69*105f6285SAndroid Build Coastguard Worker otatools = os.path.join(temp_dir, 'otatools') 70*105f6285SAndroid Build Coastguard Worker unzip_otatools(args.otatools_zip, otatools) 71*105f6285SAndroid Build Coastguard Worker 72*105f6285SAndroid Build Coastguard Worker # get framework and vendor target files 73*105f6285SAndroid Build Coastguard Worker matched_framework_target_files = glob.glob(args.framework_target_files_zip) 74*105f6285SAndroid Build Coastguard Worker if not matched_framework_target_files: 75*105f6285SAndroid Build Coastguard Worker raise ValueError('framework target files zip ' 76*105f6285SAndroid Build Coastguard Worker f'{args.framework_target_files_zip} not found.') 77*105f6285SAndroid Build Coastguard Worker matched_vendor_target_files = glob.glob(args.vendor_target_files_zip) 78*105f6285SAndroid Build Coastguard Worker if not matched_vendor_target_files: 79*105f6285SAndroid Build Coastguard Worker raise ValueError('vendor target files zip ' 80*105f6285SAndroid Build Coastguard Worker f'{args.vendor_target_files_zip} not found.') 81*105f6285SAndroid Build Coastguard Worker 82*105f6285SAndroid Build Coastguard Worker # merge target files 83*105f6285SAndroid Build Coastguard Worker framework_target_files = matched_framework_target_files[0] 84*105f6285SAndroid Build Coastguard Worker vendor_target_files = matched_vendor_target_files[0] 85*105f6285SAndroid Build Coastguard Worker merged_target_files = os.path.join( 86*105f6285SAndroid Build Coastguard Worker args.output_dir, 87*105f6285SAndroid Build Coastguard Worker f'{args.target}-target_files-{args.build_id}.zip') 88*105f6285SAndroid Build Coastguard Worker command = [ 89*105f6285SAndroid Build Coastguard Worker os.path.join(otatools, 'bin', 'merge_target_files'), 90*105f6285SAndroid Build Coastguard Worker '--path', otatools, 91*105f6285SAndroid Build Coastguard Worker '--framework-target-files', framework_target_files, 92*105f6285SAndroid Build Coastguard Worker '--vendor-target-files', vendor_target_files, 93*105f6285SAndroid Build Coastguard Worker '--output-target-files', merged_target_files, 94*105f6285SAndroid Build Coastguard Worker '--avb-resolve-rollback-index-location-conflict' 95*105f6285SAndroid Build Coastguard Worker ] 96*105f6285SAndroid Build Coastguard Worker subprocess.run(command, check=True) 97*105f6285SAndroid Build Coastguard Worker 98*105f6285SAndroid Build Coastguard Worker # create images from the merged target files 99*105f6285SAndroid Build Coastguard Worker img_zip_path = os.path.join(args.output_dir, 100*105f6285SAndroid Build Coastguard Worker f'{args.target}-img-{args.build_id}.zip') 101*105f6285SAndroid Build Coastguard Worker command = [ 102*105f6285SAndroid Build Coastguard Worker os.path.join(otatools, 'bin', 'img_from_target_files'), 103*105f6285SAndroid Build Coastguard Worker merged_target_files, 104*105f6285SAndroid Build Coastguard Worker img_zip_path] 105*105f6285SAndroid Build Coastguard Worker subprocess.run(command, check=True) 106*105f6285SAndroid Build Coastguard Worker 107*105f6285SAndroid Build Coastguard Worker # merge CHD debug sepolicy 108*105f6285SAndroid Build Coastguard Worker # TODO (b/315474132): remove this when the CHD sepolicy issue is resolved. 109*105f6285SAndroid Build Coastguard Worker chd_sepolicy = None 110*105f6285SAndroid Build Coastguard Worker try: 111*105f6285SAndroid Build Coastguard Worker chd_sepolicy = merge_chd_sepolicy( 112*105f6285SAndroid Build Coastguard Worker framework_target_files, vendor_target_files, otatools, args.output_dir) 113*105f6285SAndroid Build Coastguard Worker except Exception as error: 114*105f6285SAndroid Build Coastguard Worker print(f'Warning - cannot generate chd_merged_sepolicy: {error}') 115*105f6285SAndroid Build Coastguard Worker 116*105f6285SAndroid Build Coastguard Worker # copy files 117*105f6285SAndroid Build Coastguard Worker copy_files(args.copy_file, args.output_dir) 118*105f6285SAndroid Build Coastguard Worker 119*105f6285SAndroid Build Coastguard Worker # build the CHD vendor boot debug image by adding chd_sepolicy and 120*105f6285SAndroid Build Coastguard Worker # chd_debug_prop (if present) into the Cuttlefish's vendor_boot-debug.img. 121*105f6285SAndroid Build Coastguard Worker files_to_add = [] 122*105f6285SAndroid Build Coastguard Worker if chd_sepolicy and os.path.exists(chd_sepolicy): 123*105f6285SAndroid Build Coastguard Worker files_to_add.append(f'{chd_sepolicy}:precompiled_sepolicy') 124*105f6285SAndroid Build Coastguard Worker chd_debug_prop = os.path.join(args.output_dir, 'chd_debug.prop') 125*105f6285SAndroid Build Coastguard Worker if os.path.exists(chd_debug_prop): 126*105f6285SAndroid Build Coastguard Worker # rename the debug prop file as `adb_debug.prop` because this is the 127*105f6285SAndroid Build Coastguard Worker # file name that property init expects. 128*105f6285SAndroid Build Coastguard Worker files_to_add.append(f'{chd_debug_prop}:adb_debug.prop') 129*105f6285SAndroid Build Coastguard Worker 130*105f6285SAndroid Build Coastguard Worker cf_debug_img = os.path.join(args.output_dir, 'vendor_boot-debug.img') 131*105f6285SAndroid Build Coastguard Worker chd_debug_image_userdebug = 'vendor_boot-chd_debug.img' 132*105f6285SAndroid Build Coastguard Worker chd_debug_image_user = 'vendor_boot-chd_debug_user.img' 133*105f6285SAndroid Build Coastguard Worker if os.path.exists(cf_debug_img): 134*105f6285SAndroid Build Coastguard Worker for image_name in [chd_debug_image_userdebug, chd_debug_image_user]: 135*105f6285SAndroid Build Coastguard Worker image_path = os.path.join(args.output_dir, image_name) 136*105f6285SAndroid Build Coastguard Worker image_dir = os.path.join(temp_dir, image_name) 137*105f6285SAndroid Build Coastguard Worker os.mkdir(image_dir) 138*105f6285SAndroid Build Coastguard Worker image_option = ImageOptions( 139*105f6285SAndroid Build Coastguard Worker input_image=cf_debug_img, 140*105f6285SAndroid Build Coastguard Worker output_image=image_path, 141*105f6285SAndroid Build Coastguard Worker otatools_dir=otatools, 142*105f6285SAndroid Build Coastguard Worker temp_dir=image_dir, 143*105f6285SAndroid Build Coastguard Worker files_to_add=files_to_add) 144*105f6285SAndroid Build Coastguard Worker 145*105f6285SAndroid Build Coastguard Worker # Remove userdebug_plat_sepolicy.cil from CHD's debug ramdisk to build a 146*105f6285SAndroid Build Coastguard Worker # debug ramdisk for user builds. 147*105f6285SAndroid Build Coastguard Worker if image_name == chd_debug_image_user: 148*105f6285SAndroid Build Coastguard Worker image_option.files_to_remove = ['userdebug_plat_sepolicy.cil'] 149*105f6285SAndroid Build Coastguard Worker 150*105f6285SAndroid Build Coastguard Worker try: 151*105f6285SAndroid Build Coastguard Worker build_chd_debug_ramdisk(image_option) 152*105f6285SAndroid Build Coastguard Worker except Exception as error: 153*105f6285SAndroid Build Coastguard Worker print(f'Warning - cannot build {image_name}: {error}') 154*105f6285SAndroid Build Coastguard Worker 155*105f6285SAndroid Build Coastguard Worker 156*105f6285SAndroid Build Coastguard Workerif __name__ == '__main__': 157*105f6285SAndroid Build Coastguard Worker with tempfile.TemporaryDirectory() as temp_dir: 158*105f6285SAndroid Build Coastguard Worker run(temp_dir) 159