1*9e94795aSAndroid Build Coastguard Worker#!/usr/bin/env python 2*9e94795aSAndroid Build Coastguard Worker# 3*9e94795aSAndroid Build Coastguard Worker# Copyright (C) 2022 The Android Open Source Project 4*9e94795aSAndroid Build Coastguard Worker# 5*9e94795aSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); you may not 6*9e94795aSAndroid Build Coastguard Worker# use this file except in compliance with the License. You may obtain a copy of 7*9e94795aSAndroid Build Coastguard Worker# the License at 8*9e94795aSAndroid Build Coastguard Worker# 9*9e94795aSAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0 10*9e94795aSAndroid Build Coastguard Worker# 11*9e94795aSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 12*9e94795aSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13*9e94795aSAndroid Build Coastguard Worker# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 14*9e94795aSAndroid Build Coastguard Worker# License for the specific language governing permissions and limitations under 15*9e94795aSAndroid Build Coastguard Worker# the License. 16*9e94795aSAndroid Build Coastguard Worker# 17*9e94795aSAndroid Build Coastguard Worker"""Functions for merging META/* files from partial builds. 18*9e94795aSAndroid Build Coastguard Worker 19*9e94795aSAndroid Build Coastguard WorkerExpects items in OPTIONS prepared by merge_target_files.py. 20*9e94795aSAndroid Build Coastguard Worker""" 21*9e94795aSAndroid Build Coastguard Worker 22*9e94795aSAndroid Build Coastguard Workerimport logging 23*9e94795aSAndroid Build Coastguard Workerimport os 24*9e94795aSAndroid Build Coastguard Workerimport re 25*9e94795aSAndroid Build Coastguard Workerimport shutil 26*9e94795aSAndroid Build Coastguard Worker 27*9e94795aSAndroid Build Coastguard Workerimport build_image 28*9e94795aSAndroid Build Coastguard Workerimport common 29*9e94795aSAndroid Build Coastguard Workerimport merge_utils 30*9e94795aSAndroid Build Coastguard Workerimport sparse_img 31*9e94795aSAndroid Build Coastguard Workerimport verity_utils 32*9e94795aSAndroid Build Coastguard Workerfrom ota_utils import ParseUpdateEngineConfig 33*9e94795aSAndroid Build Coastguard Worker 34*9e94795aSAndroid Build Coastguard Workerfrom common import ExternalError 35*9e94795aSAndroid Build Coastguard Worker 36*9e94795aSAndroid Build Coastguard Workerlogger = logging.getLogger(__name__) 37*9e94795aSAndroid Build Coastguard Worker 38*9e94795aSAndroid Build Coastguard WorkerOPTIONS = common.OPTIONS 39*9e94795aSAndroid Build Coastguard Worker 40*9e94795aSAndroid Build Coastguard Worker# In apexkeys.txt or apkcerts.txt, we will find partition tags on each entry in 41*9e94795aSAndroid Build Coastguard Worker# the file. We use these partition tags to filter the entries in those files 42*9e94795aSAndroid Build Coastguard Worker# from the two different target files packages to produce a merged apexkeys.txt 43*9e94795aSAndroid Build Coastguard Worker# or apkcerts.txt file. A partition tag (e.g., for the product partition) looks 44*9e94795aSAndroid Build Coastguard Worker# like this: 'partition="product"'. We use the group syntax grab the value of 45*9e94795aSAndroid Build Coastguard Worker# the tag. We use non-greedy matching in case there are other fields on the 46*9e94795aSAndroid Build Coastguard Worker# same line. 47*9e94795aSAndroid Build Coastguard Worker 48*9e94795aSAndroid Build Coastguard WorkerPARTITION_TAG_PATTERN = re.compile(r'partition="(.*?)"') 49*9e94795aSAndroid Build Coastguard Worker 50*9e94795aSAndroid Build Coastguard Worker# The sorting algorithm for apexkeys.txt and apkcerts.txt does not include the 51*9e94795aSAndroid Build Coastguard Worker# ".apex" or ".apk" suffix, so we use the following pattern to extract a key. 52*9e94795aSAndroid Build Coastguard Worker 53*9e94795aSAndroid Build Coastguard WorkerMODULE_KEY_PATTERN = re.compile(r'name="(.+)\.(apex|apk)"') 54*9e94795aSAndroid Build Coastguard Worker 55*9e94795aSAndroid Build Coastguard Worker 56*9e94795aSAndroid Build Coastguard Workerdef MergeUpdateEngineConfig(framework_meta_dir, vendor_meta_dir, 57*9e94795aSAndroid Build Coastguard Worker merged_meta_dir): 58*9e94795aSAndroid Build Coastguard Worker """Merges META/update_engine_config.txt. 59*9e94795aSAndroid Build Coastguard Worker 60*9e94795aSAndroid Build Coastguard Worker The output is the configuration for maximum compatibility. 61*9e94795aSAndroid Build Coastguard Worker """ 62*9e94795aSAndroid Build Coastguard Worker _CONFIG_NAME = 'update_engine_config.txt' 63*9e94795aSAndroid Build Coastguard Worker framework_config_path = os.path.join(framework_meta_dir, _CONFIG_NAME) 64*9e94795aSAndroid Build Coastguard Worker vendor_config_path = os.path.join(vendor_meta_dir, _CONFIG_NAME) 65*9e94795aSAndroid Build Coastguard Worker merged_config_path = os.path.join(merged_meta_dir, _CONFIG_NAME) 66*9e94795aSAndroid Build Coastguard Worker 67*9e94795aSAndroid Build Coastguard Worker if os.path.exists(framework_config_path): 68*9e94795aSAndroid Build Coastguard Worker framework_config = ParseUpdateEngineConfig(framework_config_path) 69*9e94795aSAndroid Build Coastguard Worker vendor_config = ParseUpdateEngineConfig(vendor_config_path) 70*9e94795aSAndroid Build Coastguard Worker # Copy older config to merged target files for maximum compatibility 71*9e94795aSAndroid Build Coastguard Worker # update_engine in system partition is from system side, but 72*9e94795aSAndroid Build Coastguard Worker # update_engine_sideload in recovery is from vendor side. 73*9e94795aSAndroid Build Coastguard Worker if framework_config < vendor_config: 74*9e94795aSAndroid Build Coastguard Worker shutil.copy(framework_config_path, merged_config_path) 75*9e94795aSAndroid Build Coastguard Worker else: 76*9e94795aSAndroid Build Coastguard Worker shutil.copy(vendor_config_path, merged_config_path) 77*9e94795aSAndroid Build Coastguard Worker else: 78*9e94795aSAndroid Build Coastguard Worker if not OPTIONS.allow_partial_ab: 79*9e94795aSAndroid Build Coastguard Worker raise FileNotFoundError(framework_config_path) 80*9e94795aSAndroid Build Coastguard Worker shutil.copy(vendor_config_path, merged_config_path) 81*9e94795aSAndroid Build Coastguard Worker 82*9e94795aSAndroid Build Coastguard Worker 83*9e94795aSAndroid Build Coastguard Workerdef MergeMetaFiles(temp_dir, merged_dir, framework_partitions): 84*9e94795aSAndroid Build Coastguard Worker """Merges various files in META/*.""" 85*9e94795aSAndroid Build Coastguard Worker 86*9e94795aSAndroid Build Coastguard Worker framework_meta_dir = os.path.join(temp_dir, 'framework_meta', 'META') 87*9e94795aSAndroid Build Coastguard Worker merge_utils.CollectTargetFiles( 88*9e94795aSAndroid Build Coastguard Worker input_zipfile_or_dir=OPTIONS.framework_target_files, 89*9e94795aSAndroid Build Coastguard Worker output_dir=os.path.dirname(framework_meta_dir), 90*9e94795aSAndroid Build Coastguard Worker item_list=('META/*',)) 91*9e94795aSAndroid Build Coastguard Worker 92*9e94795aSAndroid Build Coastguard Worker vendor_meta_dir = os.path.join(temp_dir, 'vendor_meta', 'META') 93*9e94795aSAndroid Build Coastguard Worker merge_utils.CollectTargetFiles( 94*9e94795aSAndroid Build Coastguard Worker input_zipfile_or_dir=OPTIONS.vendor_target_files, 95*9e94795aSAndroid Build Coastguard Worker output_dir=os.path.dirname(vendor_meta_dir), 96*9e94795aSAndroid Build Coastguard Worker item_list=('META/*',)) 97*9e94795aSAndroid Build Coastguard Worker 98*9e94795aSAndroid Build Coastguard Worker merged_meta_dir = os.path.join(merged_dir, 'META') 99*9e94795aSAndroid Build Coastguard Worker 100*9e94795aSAndroid Build Coastguard Worker # Merge META/misc_info.txt into OPTIONS.merged_misc_info, 101*9e94795aSAndroid Build Coastguard Worker # but do not write it yet. The following functions may further 102*9e94795aSAndroid Build Coastguard Worker # modify this dict. 103*9e94795aSAndroid Build Coastguard Worker OPTIONS.merged_misc_info = MergeMiscInfo( 104*9e94795aSAndroid Build Coastguard Worker framework_meta_dir=framework_meta_dir, 105*9e94795aSAndroid Build Coastguard Worker vendor_meta_dir=vendor_meta_dir, 106*9e94795aSAndroid Build Coastguard Worker merged_meta_dir=merged_meta_dir) 107*9e94795aSAndroid Build Coastguard Worker 108*9e94795aSAndroid Build Coastguard Worker CopyNamedFileContexts( 109*9e94795aSAndroid Build Coastguard Worker framework_meta_dir=framework_meta_dir, 110*9e94795aSAndroid Build Coastguard Worker vendor_meta_dir=vendor_meta_dir, 111*9e94795aSAndroid Build Coastguard Worker merged_meta_dir=merged_meta_dir) 112*9e94795aSAndroid Build Coastguard Worker 113*9e94795aSAndroid Build Coastguard Worker if OPTIONS.merged_misc_info.get('use_dynamic_partitions') == 'true': 114*9e94795aSAndroid Build Coastguard Worker MergeDynamicPartitionsInfo( 115*9e94795aSAndroid Build Coastguard Worker framework_meta_dir=framework_meta_dir, 116*9e94795aSAndroid Build Coastguard Worker vendor_meta_dir=vendor_meta_dir, 117*9e94795aSAndroid Build Coastguard Worker merged_meta_dir=merged_meta_dir) 118*9e94795aSAndroid Build Coastguard Worker 119*9e94795aSAndroid Build Coastguard Worker if OPTIONS.merged_misc_info.get('ab_update') == 'true': 120*9e94795aSAndroid Build Coastguard Worker MergeAbPartitions( 121*9e94795aSAndroid Build Coastguard Worker framework_meta_dir=framework_meta_dir, 122*9e94795aSAndroid Build Coastguard Worker vendor_meta_dir=vendor_meta_dir, 123*9e94795aSAndroid Build Coastguard Worker merged_meta_dir=merged_meta_dir, 124*9e94795aSAndroid Build Coastguard Worker framework_partitions=framework_partitions) 125*9e94795aSAndroid Build Coastguard Worker UpdateCareMapImageSizeProps(images_dir=os.path.join(merged_dir, 'IMAGES')) 126*9e94795aSAndroid Build Coastguard Worker 127*9e94795aSAndroid Build Coastguard Worker for file_name in ('apkcerts.txt', 'apexkeys.txt'): 128*9e94795aSAndroid Build Coastguard Worker MergePackageKeys( 129*9e94795aSAndroid Build Coastguard Worker framework_meta_dir=framework_meta_dir, 130*9e94795aSAndroid Build Coastguard Worker vendor_meta_dir=vendor_meta_dir, 131*9e94795aSAndroid Build Coastguard Worker merged_meta_dir=merged_meta_dir, 132*9e94795aSAndroid Build Coastguard Worker file_name=file_name) 133*9e94795aSAndroid Build Coastguard Worker 134*9e94795aSAndroid Build Coastguard Worker if OPTIONS.merged_misc_info.get('ab_update') == 'true': 135*9e94795aSAndroid Build Coastguard Worker MergeUpdateEngineConfig( 136*9e94795aSAndroid Build Coastguard Worker framework_meta_dir, vendor_meta_dir, merged_meta_dir) 137*9e94795aSAndroid Build Coastguard Worker 138*9e94795aSAndroid Build Coastguard Worker # Write the now-finalized OPTIONS.merged_misc_info. 139*9e94795aSAndroid Build Coastguard Worker merge_utils.WriteSortedData( 140*9e94795aSAndroid Build Coastguard Worker data=OPTIONS.merged_misc_info, 141*9e94795aSAndroid Build Coastguard Worker path=os.path.join(merged_meta_dir, 'misc_info.txt')) 142*9e94795aSAndroid Build Coastguard Worker 143*9e94795aSAndroid Build Coastguard Worker 144*9e94795aSAndroid Build Coastguard Workerdef MergeAbPartitions(framework_meta_dir, vendor_meta_dir, merged_meta_dir, 145*9e94795aSAndroid Build Coastguard Worker framework_partitions): 146*9e94795aSAndroid Build Coastguard Worker """Merges META/ab_partitions.txt. 147*9e94795aSAndroid Build Coastguard Worker 148*9e94795aSAndroid Build Coastguard Worker The output contains the union of the partition names. 149*9e94795aSAndroid Build Coastguard Worker """ 150*9e94795aSAndroid Build Coastguard Worker framework_ab_partitions = [] 151*9e94795aSAndroid Build Coastguard Worker framework_ab_config = os.path.join(framework_meta_dir, 'ab_partitions.txt') 152*9e94795aSAndroid Build Coastguard Worker if os.path.exists(framework_ab_config): 153*9e94795aSAndroid Build Coastguard Worker with open(framework_ab_config) as f: 154*9e94795aSAndroid Build Coastguard Worker # Filter out some partitions here to support the case that the 155*9e94795aSAndroid Build Coastguard Worker # ab_partitions.txt of framework-target-files has non-framework 156*9e94795aSAndroid Build Coastguard Worker # partitions. This case happens when we use a complete merged target 157*9e94795aSAndroid Build Coastguard Worker # files package as the framework-target-files. 158*9e94795aSAndroid Build Coastguard Worker framework_ab_partitions.extend([ 159*9e94795aSAndroid Build Coastguard Worker partition 160*9e94795aSAndroid Build Coastguard Worker for partition in f.read().splitlines() 161*9e94795aSAndroid Build Coastguard Worker if partition in framework_partitions 162*9e94795aSAndroid Build Coastguard Worker ]) 163*9e94795aSAndroid Build Coastguard Worker else: 164*9e94795aSAndroid Build Coastguard Worker if not OPTIONS.allow_partial_ab: 165*9e94795aSAndroid Build Coastguard Worker raise FileNotFoundError(framework_ab_config) 166*9e94795aSAndroid Build Coastguard Worker logger.info('Use partial AB because framework ab_partitions.txt does not ' 167*9e94795aSAndroid Build Coastguard Worker 'exist.') 168*9e94795aSAndroid Build Coastguard Worker 169*9e94795aSAndroid Build Coastguard Worker with open(os.path.join(vendor_meta_dir, 'ab_partitions.txt')) as f: 170*9e94795aSAndroid Build Coastguard Worker vendor_ab_partitions = f.read().splitlines() 171*9e94795aSAndroid Build Coastguard Worker 172*9e94795aSAndroid Build Coastguard Worker merge_utils.WriteSortedData( 173*9e94795aSAndroid Build Coastguard Worker data=set(framework_ab_partitions + vendor_ab_partitions), 174*9e94795aSAndroid Build Coastguard Worker path=os.path.join(merged_meta_dir, 'ab_partitions.txt')) 175*9e94795aSAndroid Build Coastguard Worker 176*9e94795aSAndroid Build Coastguard Worker 177*9e94795aSAndroid Build Coastguard Workerdef MergeMiscInfo(framework_meta_dir, vendor_meta_dir, merged_meta_dir): 178*9e94795aSAndroid Build Coastguard Worker """Merges META/misc_info.txt. 179*9e94795aSAndroid Build Coastguard Worker 180*9e94795aSAndroid Build Coastguard Worker The output contains a combination of key=value pairs from both inputs. 181*9e94795aSAndroid Build Coastguard Worker Most pairs are taken from the vendor input, while some are taken from 182*9e94795aSAndroid Build Coastguard Worker the framework input. 183*9e94795aSAndroid Build Coastguard Worker """ 184*9e94795aSAndroid Build Coastguard Worker 185*9e94795aSAndroid Build Coastguard Worker OPTIONS.framework_misc_info = common.LoadDictionaryFromFile( 186*9e94795aSAndroid Build Coastguard Worker os.path.join(framework_meta_dir, 'misc_info.txt')) 187*9e94795aSAndroid Build Coastguard Worker OPTIONS.vendor_misc_info = common.LoadDictionaryFromFile( 188*9e94795aSAndroid Build Coastguard Worker os.path.join(vendor_meta_dir, 'misc_info.txt')) 189*9e94795aSAndroid Build Coastguard Worker 190*9e94795aSAndroid Build Coastguard Worker # Merged misc info is a combination of vendor misc info plus certain values 191*9e94795aSAndroid Build Coastguard Worker # from the framework misc info. 192*9e94795aSAndroid Build Coastguard Worker 193*9e94795aSAndroid Build Coastguard Worker merged_dict = OPTIONS.vendor_misc_info 194*9e94795aSAndroid Build Coastguard Worker for key in OPTIONS.framework_misc_info_keys: 195*9e94795aSAndroid Build Coastguard Worker if key in OPTIONS.framework_misc_info: 196*9e94795aSAndroid Build Coastguard Worker merged_dict[key] = OPTIONS.framework_misc_info[key] 197*9e94795aSAndroid Build Coastguard Worker 198*9e94795aSAndroid Build Coastguard Worker # If AVB is enabled then ensure that we build vbmeta.img. 199*9e94795aSAndroid Build Coastguard Worker # Partial builds with AVB enabled may set PRODUCT_BUILD_VBMETA_IMAGE=false to 200*9e94795aSAndroid Build Coastguard Worker # skip building an incomplete vbmeta.img. 201*9e94795aSAndroid Build Coastguard Worker if merged_dict.get('avb_enable') == 'true': 202*9e94795aSAndroid Build Coastguard Worker merged_dict['avb_building_vbmeta_image'] = 'true' 203*9e94795aSAndroid Build Coastguard Worker 204*9e94795aSAndroid Build Coastguard Worker return merged_dict 205*9e94795aSAndroid Build Coastguard Worker 206*9e94795aSAndroid Build Coastguard Worker 207*9e94795aSAndroid Build Coastguard Workerdef MergeDynamicPartitionsInfo(framework_meta_dir, vendor_meta_dir, 208*9e94795aSAndroid Build Coastguard Worker merged_meta_dir): 209*9e94795aSAndroid Build Coastguard Worker """Merge META/dynamic_partitions_info.txt.""" 210*9e94795aSAndroid Build Coastguard Worker framework_dynamic_partitions_dict = common.LoadDictionaryFromFile( 211*9e94795aSAndroid Build Coastguard Worker os.path.join(framework_meta_dir, 'dynamic_partitions_info.txt')) 212*9e94795aSAndroid Build Coastguard Worker vendor_dynamic_partitions_dict = common.LoadDictionaryFromFile( 213*9e94795aSAndroid Build Coastguard Worker os.path.join(vendor_meta_dir, 'dynamic_partitions_info.txt')) 214*9e94795aSAndroid Build Coastguard Worker 215*9e94795aSAndroid Build Coastguard Worker merged_dynamic_partitions_dict = common.MergeDynamicPartitionInfoDicts( 216*9e94795aSAndroid Build Coastguard Worker framework_dict=framework_dynamic_partitions_dict, 217*9e94795aSAndroid Build Coastguard Worker vendor_dict=vendor_dynamic_partitions_dict) 218*9e94795aSAndroid Build Coastguard Worker 219*9e94795aSAndroid Build Coastguard Worker merge_utils.WriteSortedData( 220*9e94795aSAndroid Build Coastguard Worker data=merged_dynamic_partitions_dict, 221*9e94795aSAndroid Build Coastguard Worker path=os.path.join(merged_meta_dir, 'dynamic_partitions_info.txt')) 222*9e94795aSAndroid Build Coastguard Worker 223*9e94795aSAndroid Build Coastguard Worker # Merge misc info keys used for Dynamic Partitions. 224*9e94795aSAndroid Build Coastguard Worker OPTIONS.merged_misc_info.update(merged_dynamic_partitions_dict) 225*9e94795aSAndroid Build Coastguard Worker # Ensure that add_img_to_target_files rebuilds super split images for 226*9e94795aSAndroid Build Coastguard Worker # devices that retrofit dynamic partitions. This flag may have been set to 227*9e94795aSAndroid Build Coastguard Worker # false in the partial builds to prevent duplicate building of super.img. 228*9e94795aSAndroid Build Coastguard Worker OPTIONS.merged_misc_info['build_super_partition'] = 'true' 229*9e94795aSAndroid Build Coastguard Worker 230*9e94795aSAndroid Build Coastguard Worker 231*9e94795aSAndroid Build Coastguard Workerdef MergePackageKeys(framework_meta_dir, vendor_meta_dir, merged_meta_dir, 232*9e94795aSAndroid Build Coastguard Worker file_name): 233*9e94795aSAndroid Build Coastguard Worker """Merges APK/APEX key list files.""" 234*9e94795aSAndroid Build Coastguard Worker 235*9e94795aSAndroid Build Coastguard Worker if file_name not in ('apkcerts.txt', 'apexkeys.txt'): 236*9e94795aSAndroid Build Coastguard Worker raise ExternalError( 237*9e94795aSAndroid Build Coastguard Worker 'Unexpected file_name provided to merge_package_keys_txt: %s', 238*9e94795aSAndroid Build Coastguard Worker file_name) 239*9e94795aSAndroid Build Coastguard Worker 240*9e94795aSAndroid Build Coastguard Worker def read_helper(d): 241*9e94795aSAndroid Build Coastguard Worker temp = {} 242*9e94795aSAndroid Build Coastguard Worker with open(os.path.join(d, file_name)) as f: 243*9e94795aSAndroid Build Coastguard Worker for line in f.read().splitlines(): 244*9e94795aSAndroid Build Coastguard Worker line = line.strip() 245*9e94795aSAndroid Build Coastguard Worker if line: 246*9e94795aSAndroid Build Coastguard Worker name_search = MODULE_KEY_PATTERN.search(line.split()[0]) 247*9e94795aSAndroid Build Coastguard Worker temp[name_search.group(1)] = line 248*9e94795aSAndroid Build Coastguard Worker return temp 249*9e94795aSAndroid Build Coastguard Worker 250*9e94795aSAndroid Build Coastguard Worker framework_dict = read_helper(framework_meta_dir) 251*9e94795aSAndroid Build Coastguard Worker vendor_dict = read_helper(vendor_meta_dir) 252*9e94795aSAndroid Build Coastguard Worker merged_dict = {} 253*9e94795aSAndroid Build Coastguard Worker 254*9e94795aSAndroid Build Coastguard Worker def filter_into_merged_dict(item_dict, partition_set): 255*9e94795aSAndroid Build Coastguard Worker for key, value in item_dict.items(): 256*9e94795aSAndroid Build Coastguard Worker tag_search = PARTITION_TAG_PATTERN.search(value) 257*9e94795aSAndroid Build Coastguard Worker 258*9e94795aSAndroid Build Coastguard Worker if tag_search is None: 259*9e94795aSAndroid Build Coastguard Worker raise ValueError('Entry missing partition tag: %s' % value) 260*9e94795aSAndroid Build Coastguard Worker 261*9e94795aSAndroid Build Coastguard Worker partition_tag = tag_search.group(1) 262*9e94795aSAndroid Build Coastguard Worker 263*9e94795aSAndroid Build Coastguard Worker if partition_tag in partition_set: 264*9e94795aSAndroid Build Coastguard Worker if key in merged_dict: 265*9e94795aSAndroid Build Coastguard Worker if OPTIONS.allow_duplicate_apkapex_keys: 266*9e94795aSAndroid Build Coastguard Worker # TODO(b/150582573) Always raise on duplicates. 267*9e94795aSAndroid Build Coastguard Worker logger.warning('Duplicate key %s' % key) 268*9e94795aSAndroid Build Coastguard Worker continue 269*9e94795aSAndroid Build Coastguard Worker else: 270*9e94795aSAndroid Build Coastguard Worker raise ValueError('Duplicate key %s' % key) 271*9e94795aSAndroid Build Coastguard Worker 272*9e94795aSAndroid Build Coastguard Worker merged_dict[key] = value 273*9e94795aSAndroid Build Coastguard Worker 274*9e94795aSAndroid Build Coastguard Worker # Prioritize framework keys first. 275*9e94795aSAndroid Build Coastguard Worker # Duplicate keys from vendor are an error, or ignored. 276*9e94795aSAndroid Build Coastguard Worker filter_into_merged_dict(framework_dict, OPTIONS.framework_partition_set) 277*9e94795aSAndroid Build Coastguard Worker filter_into_merged_dict(vendor_dict, OPTIONS.vendor_partition_set) 278*9e94795aSAndroid Build Coastguard Worker 279*9e94795aSAndroid Build Coastguard Worker # The following code is similar to WriteSortedData, but different enough 280*9e94795aSAndroid Build Coastguard Worker # that we couldn't use that function. We need the output to be sorted by the 281*9e94795aSAndroid Build Coastguard Worker # basename of the apex/apk (without the ".apex" or ".apk" suffix). This 282*9e94795aSAndroid Build Coastguard Worker # allows the sort to be consistent with the framework/vendor input data and 283*9e94795aSAndroid Build Coastguard Worker # eases comparison of input data with merged data. 284*9e94795aSAndroid Build Coastguard Worker with open(os.path.join(merged_meta_dir, file_name), 'w') as output: 285*9e94795aSAndroid Build Coastguard Worker for key, value in sorted(merged_dict.items()): 286*9e94795aSAndroid Build Coastguard Worker output.write(value + '\n') 287*9e94795aSAndroid Build Coastguard Worker 288*9e94795aSAndroid Build Coastguard Worker 289*9e94795aSAndroid Build Coastguard Workerdef CopyNamedFileContexts(framework_meta_dir, vendor_meta_dir, merged_meta_dir): 290*9e94795aSAndroid Build Coastguard Worker """Creates named copies of each partial build's file_contexts.bin. 291*9e94795aSAndroid Build Coastguard Worker 292*9e94795aSAndroid Build Coastguard Worker Used when regenerating images from the partial build. 293*9e94795aSAndroid Build Coastguard Worker """ 294*9e94795aSAndroid Build Coastguard Worker 295*9e94795aSAndroid Build Coastguard Worker def copy_fc_file(source_dir, file_name): 296*9e94795aSAndroid Build Coastguard Worker for name in (file_name, 'file_contexts.bin'): 297*9e94795aSAndroid Build Coastguard Worker fc_path = os.path.join(source_dir, name) 298*9e94795aSAndroid Build Coastguard Worker if os.path.exists(fc_path): 299*9e94795aSAndroid Build Coastguard Worker shutil.copyfile(fc_path, os.path.join(merged_meta_dir, file_name)) 300*9e94795aSAndroid Build Coastguard Worker return 301*9e94795aSAndroid Build Coastguard Worker raise ValueError('Missing file_contexts file from %s: %s', source_dir, 302*9e94795aSAndroid Build Coastguard Worker file_name) 303*9e94795aSAndroid Build Coastguard Worker 304*9e94795aSAndroid Build Coastguard Worker copy_fc_file(framework_meta_dir, 'framework_file_contexts.bin') 305*9e94795aSAndroid Build Coastguard Worker copy_fc_file(vendor_meta_dir, 'vendor_file_contexts.bin') 306*9e94795aSAndroid Build Coastguard Worker 307*9e94795aSAndroid Build Coastguard Worker # Replace <image>_selinux_fc values with framework or vendor file_contexts.bin 308*9e94795aSAndroid Build Coastguard Worker # depending on which dictionary the key came from. 309*9e94795aSAndroid Build Coastguard Worker # Only the file basename is required because all selinux_fc properties are 310*9e94795aSAndroid Build Coastguard Worker # replaced with the full path to the file under META/ when misc_info.txt is 311*9e94795aSAndroid Build Coastguard Worker # loaded from target files for repacking. See common.py LoadInfoDict(). 312*9e94795aSAndroid Build Coastguard Worker for key in OPTIONS.vendor_misc_info: 313*9e94795aSAndroid Build Coastguard Worker if key.endswith('_selinux_fc'): 314*9e94795aSAndroid Build Coastguard Worker OPTIONS.merged_misc_info[key] = 'vendor_file_contexts.bin' 315*9e94795aSAndroid Build Coastguard Worker for key in OPTIONS.framework_misc_info: 316*9e94795aSAndroid Build Coastguard Worker if key.endswith('_selinux_fc'): 317*9e94795aSAndroid Build Coastguard Worker OPTIONS.merged_misc_info[key] = 'framework_file_contexts.bin' 318*9e94795aSAndroid Build Coastguard Worker 319*9e94795aSAndroid Build Coastguard Worker 320*9e94795aSAndroid Build Coastguard Workerdef UpdateCareMapImageSizeProps(images_dir): 321*9e94795aSAndroid Build Coastguard Worker """Sets <partition>_image_size props in misc_info. 322*9e94795aSAndroid Build Coastguard Worker 323*9e94795aSAndroid Build Coastguard Worker add_images_to_target_files uses these props to generate META/care_map.pb. 324*9e94795aSAndroid Build Coastguard Worker Regenerated images will have this property set during regeneration. 325*9e94795aSAndroid Build Coastguard Worker 326*9e94795aSAndroid Build Coastguard Worker However, images copied directly from input partial target files packages 327*9e94795aSAndroid Build Coastguard Worker need this value calculated here. 328*9e94795aSAndroid Build Coastguard Worker """ 329*9e94795aSAndroid Build Coastguard Worker for partition in common.PARTITIONS_WITH_CARE_MAP: 330*9e94795aSAndroid Build Coastguard Worker image_path = os.path.join(images_dir, '{}.img'.format(partition)) 331*9e94795aSAndroid Build Coastguard Worker if os.path.exists(image_path): 332*9e94795aSAndroid Build Coastguard Worker partition_size = sparse_img.GetImagePartitionSize(image_path) 333*9e94795aSAndroid Build Coastguard Worker image_props = build_image.ImagePropFromGlobalDict( 334*9e94795aSAndroid Build Coastguard Worker OPTIONS.merged_misc_info, partition) 335*9e94795aSAndroid Build Coastguard Worker verity_image_builder = verity_utils.CreateVerityImageBuilder(image_props) 336*9e94795aSAndroid Build Coastguard Worker image_size = verity_image_builder.CalculateMaxImageSize(partition_size) 337*9e94795aSAndroid Build Coastguard Worker OPTIONS.merged_misc_info['{}_image_size'.format(partition)] = image_size 338