blob: c2fd45073b07b60c94310bfa96676b3dbf1f709b [file] [log] [blame]
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001#!/usr/bin/env python
2#
3# Copyright (C) 2019 The Android Open Source Project
4#
5# Licensed under the Apache License, Version 2.0 (the "License"); you may not
6# use this file except in compliance with the License. You may obtain a copy of
7# 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, WITHOUT
13# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14# License for the specific language governing permissions and limitations under
15# the License.
Daniel Norman4cc9df62019-07-18 10:11:07 -070016#
17"""This script merges two partial target files packages.
Bill Peckhame9eb5f92019-02-01 15:52:10 -080018
Daniel Normandbbf5a32020-10-22 16:03:32 -070019One input package contains framework files, and the other contains vendor files.
Bill Peckhame9eb5f92019-02-01 15:52:10 -080020
Daniel Normandbbf5a32020-10-22 16:03:32 -070021This script produces a complete, merged target files package:
22 - This package can be used to generate a flashable IMG package.
23 See --output-img.
24 - This package can be used to generate an OTA package. See --output-ota.
25 - The merged package is checked for compatibility between the two inputs.
26
27Usage: merge_target_files [args]
Bill Peckhame9eb5f92019-02-01 15:52:10 -080028
Daniel Normand5d70ea2019-06-05 15:13:43 -070029 --framework-target-files framework-target-files-zip-archive
30 The input target files package containing framework bits. This is a zip
Bill Peckhame9eb5f92019-02-01 15:52:10 -080031 archive.
32
Daniel Normand5d70ea2019-06-05 15:13:43 -070033 --framework-item-list framework-item-list-file
Daniel Norman2c99c5b2019-03-07 13:01:48 -080034 The optional path to a newline-separated config file that replaces the
Daniel Normand5d70ea2019-06-05 15:13:43 -070035 contents of DEFAULT_FRAMEWORK_ITEM_LIST if provided.
Daniel Norman2c99c5b2019-03-07 13:01:48 -080036
Daniel Normand5d70ea2019-06-05 15:13:43 -070037 --framework-misc-info-keys framework-misc-info-keys-file
Daniel Norman2c99c5b2019-03-07 13:01:48 -080038 The optional path to a newline-separated config file that replaces the
Daniel Normand5d70ea2019-06-05 15:13:43 -070039 contents of DEFAULT_FRAMEWORK_MISC_INFO_KEYS if provided.
Daniel Norman2c99c5b2019-03-07 13:01:48 -080040
Daniel Normand5d70ea2019-06-05 15:13:43 -070041 --vendor-target-files vendor-target-files-zip-archive
42 The input target files package containing vendor bits. This is a zip
Bill Peckhame9eb5f92019-02-01 15:52:10 -080043 archive.
44
Daniel Normand5d70ea2019-06-05 15:13:43 -070045 --vendor-item-list vendor-item-list-file
Daniel Norman2c99c5b2019-03-07 13:01:48 -080046 The optional path to a newline-separated config file that replaces the
Daniel Normand5d70ea2019-06-05 15:13:43 -070047 contents of DEFAULT_VENDOR_ITEM_LIST if provided.
Daniel Norman2c99c5b2019-03-07 13:01:48 -080048
Bill Peckhame9eb5f92019-02-01 15:52:10 -080049 --output-target-files output-target-files-package
Daniel Normanfdb38812019-04-15 09:47:24 -070050 If provided, the output merged target files package. Also a zip archive.
51
52 --output-dir output-directory
53 If provided, the destination directory for saving merged files. Requires
54 the --output-item-list flag.
55 Can be provided alongside --output-target-files, or by itself.
56
57 --output-item-list output-item-list-file.
58 The optional path to a newline-separated config file that specifies the
59 file patterns to copy into the --output-dir. Required if providing
60 the --output-dir flag.
Daniel Normana4911da2019-03-15 14:36:21 -070061
Daniel Norman3b64ce12019-04-16 16:11:35 -070062 --output-ota output-ota-package
63 The output ota package. This is a zip archive. Use of this flag may
64 require passing the --path common flag; see common.py.
65
Daniel Norman1bd2a1d2019-04-18 12:32:18 -070066 --output-img output-img-package
67 The output img package, suitable for use with 'fastboot update'. Use of
68 this flag may require passing the --path common flag; see common.py.
69
Daniel Normanf0318252019-04-15 11:34:56 -070070 --output-super-empty output-super-empty-image
71 If provided, creates a super_empty.img file from the merged target
72 files package and saves it at this path.
73
Daniel Normana4911da2019-03-15 14:36:21 -070074 --rebuild_recovery
Bill Peckhame868aec2019-09-17 17:06:47 -070075 Deprecated; does nothing.
Bill Peckham364c1cc2019-03-29 18:27:23 -070076
Daniel Normanb0c75912020-09-24 14:30:21 -070077 --allow-duplicate-apkapex-keys
78 If provided, duplicate APK/APEX keys are ignored and the value from the
79 framework is used.
80
Bill Peckham364c1cc2019-03-29 18:27:23 -070081 --keep-tmp
82 Keep tempoary files for debugging purposes.
Bill Peckhame9eb5f92019-02-01 15:52:10 -080083"""
84
85from __future__ import print_function
86
Bill Peckhame9eb5f92019-02-01 15:52:10 -080087import fnmatch
Daniel Normand3351562020-10-29 12:33:11 -070088import json
Bill Peckhame9eb5f92019-02-01 15:52:10 -080089import logging
90import os
Bill Peckham19c3feb2020-03-20 18:31:43 -070091import re
Daniel Normanfdb38812019-04-15 09:47:24 -070092import shutil
Bill Peckham540d91a2019-04-25 14:18:16 -070093import subprocess
Bill Peckhame9eb5f92019-02-01 15:52:10 -080094import sys
95import zipfile
Daniel Norman48603ff2021-02-22 15:15:24 -080096from xml.etree import ElementTree
Bill Peckhame9eb5f92019-02-01 15:52:10 -080097
Bill Peckhame9eb5f92019-02-01 15:52:10 -080098import add_img_to_target_files
Daniel Normanf0318252019-04-15 11:34:56 -070099import build_super_image
Yifan Hongade0d3f2019-08-21 16:37:11 -0700100import check_target_files_vintf
Daniel Normanf0318252019-04-15 11:34:56 -0700101import common
Daniel Norman1bd2a1d2019-04-18 12:32:18 -0700102import img_from_target_files
Daniel Normanb8d52a22020-10-26 17:55:00 -0700103import find_shareduid_violation
Daniel Norman3b64ce12019-04-16 16:11:35 -0700104import ota_from_target_files
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800105
Kelvin Zhangc184fa12021-03-22 15:38:38 -0400106from common import AddCareMapForAbOta, ExternalError, PARTITIONS_WITH_CARE_MAP
107
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800108logger = logging.getLogger(__name__)
Tao Bao2ad4b822019-06-27 16:52:12 -0700109
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800110OPTIONS = common.OPTIONS
Bill Peckhamcb848172020-04-03 12:50:47 -0700111# Always turn on verbose logging.
112OPTIONS.verbose = True
Daniel Normand5d70ea2019-06-05 15:13:43 -0700113OPTIONS.framework_target_files = None
114OPTIONS.framework_item_list = None
115OPTIONS.framework_misc_info_keys = None
116OPTIONS.vendor_target_files = None
117OPTIONS.vendor_item_list = None
Bill Peckhamf753e152019-02-19 18:02:46 -0800118OPTIONS.output_target_files = None
Daniel Normanfdb38812019-04-15 09:47:24 -0700119OPTIONS.output_dir = None
120OPTIONS.output_item_list = None
Daniel Norman3b64ce12019-04-16 16:11:35 -0700121OPTIONS.output_ota = None
Daniel Norman1bd2a1d2019-04-18 12:32:18 -0700122OPTIONS.output_img = None
Daniel Normanf0318252019-04-15 11:34:56 -0700123OPTIONS.output_super_empty = None
Bill Peckhame868aec2019-09-17 17:06:47 -0700124# TODO(b/132730255): Remove this option.
Daniel Normana4911da2019-03-15 14:36:21 -0700125OPTIONS.rebuild_recovery = False
Daniel Normanb0c75912020-09-24 14:30:21 -0700126# TODO(b/150582573): Remove this option.
127OPTIONS.allow_duplicate_apkapex_keys = False
Bill Peckhamf753e152019-02-19 18:02:46 -0800128OPTIONS.keep_tmp = False
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800129
Bill Peckham19c3feb2020-03-20 18:31:43 -0700130# In an item list (framework or vendor), we may see entries that select whole
131# partitions. Such an entry might look like this 'SYSTEM/*' (e.g., for the
132# system partition). The following regex matches this and extracts the
133# partition name.
134
135PARTITION_ITEM_PATTERN = re.compile(r'^([A-Z_]+)/\*$')
136
Bill Peckham5c7b0342020-04-03 15:36:23 -0700137# In apexkeys.txt or apkcerts.txt, we will find partition tags on each entry in
138# the file. We use these partition tags to filter the entries in those files
139# from the two different target files packages to produce a merged apexkeys.txt
140# or apkcerts.txt file. A partition tag (e.g., for the product partition) looks
141# like this: 'partition="product"'. We use the group syntax grab the value of
142# the tag. We use non-greedy matching in case there are other fields on the
143# same line.
Bill Peckham19c3feb2020-03-20 18:31:43 -0700144
Bill Peckham5c7b0342020-04-03 15:36:23 -0700145PARTITION_TAG_PATTERN = re.compile(r'partition="(.*?)"')
Bill Peckham19c3feb2020-03-20 18:31:43 -0700146
147# The sorting algorithm for apexkeys.txt and apkcerts.txt does not include the
148# ".apex" or ".apk" suffix, so we use the following pattern to extract a key.
149
150MODULE_KEY_PATTERN = re.compile(r'name="(.+)\.(apex|apk)"')
151
Daniel Normand5d70ea2019-06-05 15:13:43 -0700152# DEFAULT_FRAMEWORK_ITEM_LIST is a list of items to extract from the partial
153# framework target files package as is, meaning these items will land in the
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800154# output target files package exactly as they appear in the input partial
Daniel Normand5d70ea2019-06-05 15:13:43 -0700155# framework target files package.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800156
Daniel Normand5d70ea2019-06-05 15:13:43 -0700157DEFAULT_FRAMEWORK_ITEM_LIST = (
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800158 'META/apkcerts.txt',
159 'META/filesystem_config.txt',
160 'META/root_filesystem_config.txt',
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800161 'META/update_engine_config.txt',
162 'PRODUCT/*',
163 'ROOT/*',
164 'SYSTEM/*',
Daniel Normanedf12472019-05-22 10:47:08 -0700165)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800166
Daniel Normand5d70ea2019-06-05 15:13:43 -0700167# DEFAULT_FRAMEWORK_MISC_INFO_KEYS is a list of keys to obtain from the
Daniel Normandbbf5a32020-10-22 16:03:32 -0700168# framework instance of META/misc_info.txt. The remaining keys should come
169# from the vendor instance.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800170
Daniel Normand5d70ea2019-06-05 15:13:43 -0700171DEFAULT_FRAMEWORK_MISC_INFO_KEYS = (
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800172 'avb_system_hashtree_enable',
173 'avb_system_add_hashtree_footer_args',
174 'avb_system_key_path',
175 'avb_system_algorithm',
176 'avb_system_rollback_index_location',
177 'avb_product_hashtree_enable',
178 'avb_product_add_hashtree_footer_args',
Justin Yun6151e3f2019-06-25 15:58:13 +0900179 'avb_system_ext_hashtree_enable',
180 'avb_system_ext_add_hashtree_footer_args',
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800181 'system_root_image',
182 'root_dir',
183 'ab_update',
184 'default_system_dev_certificate',
185 'system_size',
Chris Gross203191b2020-05-30 02:39:12 +0000186 'building_system_image',
187 'building_system_ext_image',
188 'building_product_image',
Daniel Normanedf12472019-05-22 10:47:08 -0700189)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800190
Daniel Normand5d70ea2019-06-05 15:13:43 -0700191# DEFAULT_VENDOR_ITEM_LIST is a list of items to extract from the partial
192# vendor target files package as is, meaning these items will land in the output
193# target files package exactly as they appear in the input partial vendor target
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800194# files package.
195
Daniel Normand5d70ea2019-06-05 15:13:43 -0700196DEFAULT_VENDOR_ITEM_LIST = (
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800197 'META/boot_filesystem_config.txt',
198 'META/otakeys.txt',
199 'META/releasetools.py',
200 'META/vendor_filesystem_config.txt',
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800201 'BOOT/*',
202 'DATA/*',
203 'ODM/*',
204 'OTA/android-info.txt',
205 'PREBUILT_IMAGES/*',
206 'RADIO/*',
207 'VENDOR/*',
Daniel Normanedf12472019-05-22 10:47:08 -0700208)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800209
Daniel Normanedf12472019-05-22 10:47:08 -0700210# The merge config lists should not attempt to extract items from both
211# builds for any of the following partitions. The partitions in
212# SINGLE_BUILD_PARTITIONS should come entirely from a single build (either
Daniel Normand5d70ea2019-06-05 15:13:43 -0700213# framework or vendor, but not both).
Daniel Normanedf12472019-05-22 10:47:08 -0700214
215SINGLE_BUILD_PARTITIONS = (
216 'BOOT/',
217 'DATA/',
218 'ODM/',
219 'PRODUCT/',
Justin Yun6151e3f2019-06-25 15:58:13 +0900220 'SYSTEM_EXT/',
Daniel Normanedf12472019-05-22 10:47:08 -0700221 'RADIO/',
222 'RECOVERY/',
223 'ROOT/',
224 'SYSTEM/',
225 'SYSTEM_OTHER/',
226 'VENDOR/',
Yifan Hongcfb917a2020-05-07 14:58:20 -0700227 'VENDOR_DLKM/',
Yifan Hongf496f1b2020-07-15 16:52:59 -0700228 'ODM_DLKM/',
Daniel Normanedf12472019-05-22 10:47:08 -0700229)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800230
231
Chris Grossfabf50a2019-05-02 12:42:09 -0700232def write_sorted_data(data, path):
Tao Bao2ad4b822019-06-27 16:52:12 -0700233 """Writes the sorted contents of either a list or dict to file.
Chris Grossfabf50a2019-05-02 12:42:09 -0700234
Tao Bao2ad4b822019-06-27 16:52:12 -0700235 This function sorts the contents of the list or dict and then writes the
236 resulting sorted contents to a file specified by path.
Chris Grossfabf50a2019-05-02 12:42:09 -0700237
238 Args:
239 data: The list or dict to sort and write.
240 path: Path to the file to write the sorted values to. The file at path will
241 be overridden if it exists.
242 """
243 with open(path, 'w') as output:
Daniel Normand5d70ea2019-06-05 15:13:43 -0700244 for entry in sorted(data):
Chris Grossfabf50a2019-05-02 12:42:09 -0700245 out_str = '{}={}\n'.format(entry, data[entry]) if isinstance(
246 data, dict) else '{}\n'.format(entry)
247 output.write(out_str)
248
249
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800250def extract_items(target_files, target_files_temp_dir, extract_item_list):
Tao Bao2ad4b822019-06-27 16:52:12 -0700251 """Extracts items from target files to temporary directory.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800252
253 This function extracts from the specified target files zip archive into the
254 specified temporary directory, the items specified in the extract item list.
255
256 Args:
257 target_files: The target files zip archive from which to extract items.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800258 target_files_temp_dir: The temporary directory where the extracted items
Daniel Normane5b134a2019-04-17 14:54:06 -0700259 will land.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800260 extract_item_list: A list of items to extract.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800261 """
262
263 logger.info('extracting from %s', target_files)
264
265 # Filter the extract_item_list to remove any items that do not exist in the
266 # zip file. Otherwise, the extraction step will fail.
267
Daniel Norman4cc9df62019-07-18 10:11:07 -0700268 with zipfile.ZipFile(target_files, allowZip64=True) as target_files_zipfile:
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800269 target_files_namelist = target_files_zipfile.namelist()
270
271 filtered_extract_item_list = []
272 for pattern in extract_item_list:
273 matching_namelist = fnmatch.filter(target_files_namelist, pattern)
274 if not matching_namelist:
275 logger.warning('no match for %s', pattern)
276 else:
277 filtered_extract_item_list.append(pattern)
278
Bill Peckham8ff3fbd2019-02-22 10:57:43 -0800279 # Extract from target_files into target_files_temp_dir the
280 # filtered_extract_item_list.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800281
Daniel Normane5b134a2019-04-17 14:54:06 -0700282 common.UnzipToDir(target_files, target_files_temp_dir,
283 filtered_extract_item_list)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800284
285
Daniel Normanfdb38812019-04-15 09:47:24 -0700286def copy_items(from_dir, to_dir, patterns):
287 """Similar to extract_items() except uses an input dir instead of zip."""
288 file_paths = []
289 for dirpath, _, filenames in os.walk(from_dir):
Daniel Normane5b134a2019-04-17 14:54:06 -0700290 file_paths.extend(
291 os.path.relpath(path=os.path.join(dirpath, filename), start=from_dir)
292 for filename in filenames)
Daniel Normanfdb38812019-04-15 09:47:24 -0700293
294 filtered_file_paths = set()
295 for pattern in patterns:
296 filtered_file_paths.update(fnmatch.filter(file_paths, pattern))
297
298 for file_path in filtered_file_paths:
299 original_file_path = os.path.join(from_dir, file_path)
300 copied_file_path = os.path.join(to_dir, file_path)
301 copied_file_dir = os.path.dirname(copied_file_path)
302 if not os.path.exists(copied_file_dir):
303 os.makedirs(copied_file_dir)
304 if os.path.islink(original_file_path):
305 os.symlink(os.readlink(original_file_path), copied_file_path)
306 else:
307 shutil.copyfile(original_file_path, copied_file_path)
308
309
Daniel Normand5d70ea2019-06-05 15:13:43 -0700310def validate_config_lists(framework_item_list, framework_misc_info_keys,
311 vendor_item_list):
Daniel Normane5964522019-03-19 10:32:03 -0700312 """Performs validations on the merge config lists.
313
314 Args:
Daniel Normand5d70ea2019-06-05 15:13:43 -0700315 framework_item_list: The list of items to extract from the partial framework
Daniel Normane5b134a2019-04-17 14:54:06 -0700316 target files package as is.
Daniel Normand5d70ea2019-06-05 15:13:43 -0700317 framework_misc_info_keys: A list of keys to obtain from the framework
Daniel Normandbbf5a32020-10-22 16:03:32 -0700318 instance of META/misc_info.txt. The remaining keys should come from the
319 vendor instance.
Daniel Normand5d70ea2019-06-05 15:13:43 -0700320 vendor_item_list: The list of items to extract from the partial vendor
321 target files package as is.
Daniel Normane5964522019-03-19 10:32:03 -0700322
323 Returns:
324 False if a validation fails, otherwise true.
325 """
Daniel Normanedf12472019-05-22 10:47:08 -0700326 has_error = False
327
Daniel Normand5d70ea2019-06-05 15:13:43 -0700328 default_combined_item_set = set(DEFAULT_FRAMEWORK_ITEM_LIST)
329 default_combined_item_set.update(DEFAULT_VENDOR_ITEM_LIST)
Daniel Normane5964522019-03-19 10:32:03 -0700330
Daniel Normand5d70ea2019-06-05 15:13:43 -0700331 combined_item_set = set(framework_item_list)
332 combined_item_set.update(vendor_item_list)
Daniel Normane5964522019-03-19 10:32:03 -0700333
334 # Check that the merge config lists are not missing any item specified
335 # by the default config lists.
336 difference = default_combined_item_set.difference(combined_item_set)
337 if difference:
Daniel Normane5b134a2019-04-17 14:54:06 -0700338 logger.error('Missing merge config items: %s', list(difference))
Daniel Normane5964522019-03-19 10:32:03 -0700339 logger.error('Please ensure missing items are in either the '
Daniel Normand5d70ea2019-06-05 15:13:43 -0700340 'framework-item-list or vendor-item-list files provided to '
Daniel Normane5964522019-03-19 10:32:03 -0700341 'this script.')
Daniel Normanedf12472019-05-22 10:47:08 -0700342 has_error = True
343
Daniel Normandbbf5a32020-10-22 16:03:32 -0700344 # Check that partitions only come from one input.
Daniel Normanedf12472019-05-22 10:47:08 -0700345 for partition in SINGLE_BUILD_PARTITIONS:
Daniel Normandbbf5a32020-10-22 16:03:32 -0700346 image_path = 'IMAGES/{}.img'.format(partition.lower().replace('/', ''))
347 in_framework = (
348 any(item.startswith(partition) for item in framework_item_list) or
349 image_path in framework_item_list)
350 in_vendor = (
351 any(item.startswith(partition) for item in vendor_item_list) or
352 image_path in vendor_item_list)
Daniel Normand5d70ea2019-06-05 15:13:43 -0700353 if in_framework and in_vendor:
Daniel Normanedf12472019-05-22 10:47:08 -0700354 logger.error(
Tao Bao2ad4b822019-06-27 16:52:12 -0700355 'Cannot extract items from %s for both the framework and vendor'
Kiyoung Kimebe7c9c2019-06-25 17:09:55 +0900356 ' builds. Please ensure only one merge config item list'
Tao Bao2ad4b822019-06-27 16:52:12 -0700357 ' includes %s.', partition, partition)
Daniel Normanedf12472019-05-22 10:47:08 -0700358 has_error = True
Daniel Normane5964522019-03-19 10:32:03 -0700359
Daniel Normand5d70ea2019-06-05 15:13:43 -0700360 if ('dynamic_partition_list' in framework_misc_info_keys) or (
Kelvin Zhangc184fa12021-03-22 15:38:38 -0400361 'super_partition_groups' in framework_misc_info_keys):
Daniel Norman19b9fe92019-03-19 14:48:02 -0700362 logger.error('Dynamic partition misc info keys should come from '
Daniel Normand5d70ea2019-06-05 15:13:43 -0700363 'the vendor instance of META/misc_info.txt.')
Daniel Normanedf12472019-05-22 10:47:08 -0700364 has_error = True
Daniel Norman19b9fe92019-03-19 14:48:02 -0700365
Daniel Normanedf12472019-05-22 10:47:08 -0700366 return not has_error
Daniel Normane5964522019-03-19 10:32:03 -0700367
368
Daniel Normand5d70ea2019-06-05 15:13:43 -0700369def process_ab_partitions_txt(framework_target_files_temp_dir,
370 vendor_target_files_temp_dir,
Daniel Normane5b134a2019-04-17 14:54:06 -0700371 output_target_files_temp_dir):
Tao Bao2ad4b822019-06-27 16:52:12 -0700372 """Performs special processing for META/ab_partitions.txt.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800373
Tao Bao2ad4b822019-06-27 16:52:12 -0700374 This function merges the contents of the META/ab_partitions.txt files from the
375 framework directory and the vendor directory, placing the merged result in the
376 output directory. The precondition in that the files are already extracted.
377 The post condition is that the output META/ab_partitions.txt contains the
Daniel Normandbbf5a32020-10-22 16:03:32 -0700378 merged content. The format for each ab_partitions.txt is one partition name
379 per line. The output file contains the union of the partition names.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800380
381 Args:
Daniel Normand5d70ea2019-06-05 15:13:43 -0700382 framework_target_files_temp_dir: The name of a directory containing the
383 special items extracted from the framework target files package.
384 vendor_target_files_temp_dir: The name of a directory containing the special
385 items extracted from the vendor target files package.
Daniel Normane5b134a2019-04-17 14:54:06 -0700386 output_target_files_temp_dir: The name of a directory that will be used to
387 create the output target files package after all the special cases are
388 processed.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800389 """
390
Daniel Normand5d70ea2019-06-05 15:13:43 -0700391 framework_ab_partitions_txt = os.path.join(framework_target_files_temp_dir,
392 'META', 'ab_partitions.txt')
393
394 vendor_ab_partitions_txt = os.path.join(vendor_target_files_temp_dir, 'META',
Daniel Normane5b134a2019-04-17 14:54:06 -0700395 'ab_partitions.txt')
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800396
Daniel Normand5d70ea2019-06-05 15:13:43 -0700397 with open(framework_ab_partitions_txt) as f:
398 framework_ab_partitions = f.read().splitlines()
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800399
Daniel Normand5d70ea2019-06-05 15:13:43 -0700400 with open(vendor_ab_partitions_txt) as f:
401 vendor_ab_partitions = f.read().splitlines()
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800402
Daniel Normand5d70ea2019-06-05 15:13:43 -0700403 output_ab_partitions = set(framework_ab_partitions + vendor_ab_partitions)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800404
Daniel Normane5b134a2019-04-17 14:54:06 -0700405 output_ab_partitions_txt = os.path.join(output_target_files_temp_dir, 'META',
406 'ab_partitions.txt')
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800407
Chris Grossfabf50a2019-05-02 12:42:09 -0700408 write_sorted_data(data=output_ab_partitions, path=output_ab_partitions_txt)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800409
410
Daniel Normand5d70ea2019-06-05 15:13:43 -0700411def process_misc_info_txt(framework_target_files_temp_dir,
412 vendor_target_files_temp_dir,
413 output_target_files_temp_dir,
414 framework_misc_info_keys):
Tao Bao2ad4b822019-06-27 16:52:12 -0700415 """Performs special processing for META/misc_info.txt.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800416
417 This function merges the contents of the META/misc_info.txt files from the
Daniel Normand5d70ea2019-06-05 15:13:43 -0700418 framework directory and the vendor directory, placing the merged result in the
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800419 output directory. The precondition in that the files are already extracted.
420 The post condition is that the output META/misc_info.txt contains the merged
421 content.
422
423 Args:
Daniel Normand5d70ea2019-06-05 15:13:43 -0700424 framework_target_files_temp_dir: The name of a directory containing the
425 special items extracted from the framework target files package.
426 vendor_target_files_temp_dir: The name of a directory containing the special
427 items extracted from the vendor target files package.
Daniel Normane5b134a2019-04-17 14:54:06 -0700428 output_target_files_temp_dir: The name of a directory that will be used to
429 create the output target files package after all the special cases are
430 processed.
Daniel Normand5d70ea2019-06-05 15:13:43 -0700431 framework_misc_info_keys: A list of keys to obtain from the framework
Daniel Normandbbf5a32020-10-22 16:03:32 -0700432 instance of META/misc_info.txt. The remaining keys should come from the
433 vendor instance.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800434 """
435
Kiyoung Kimebe7c9c2019-06-25 17:09:55 +0900436 misc_info_path = ['META', 'misc_info.txt']
437 framework_dict = common.LoadDictionaryFromFile(
438 os.path.join(framework_target_files_temp_dir, *misc_info_path))
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800439
Daniel Normand5d70ea2019-06-05 15:13:43 -0700440 # We take most of the misc info from the vendor target files.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800441
Kiyoung Kimebe7c9c2019-06-25 17:09:55 +0900442 merged_dict = common.LoadDictionaryFromFile(
443 os.path.join(vendor_target_files_temp_dir, *misc_info_path))
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800444
Daniel Normand5d70ea2019-06-05 15:13:43 -0700445 # Replace certain values in merged_dict with values from
446 # framework_dict.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800447
Daniel Normand5d70ea2019-06-05 15:13:43 -0700448 for key in framework_misc_info_keys:
449 merged_dict[key] = framework_dict[key]
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800450
Daniel Norman19b9fe92019-03-19 14:48:02 -0700451 # Merge misc info keys used for Dynamic Partitions.
Daniel Normand5d70ea2019-06-05 15:13:43 -0700452 if (merged_dict.get('use_dynamic_partitions') == 'true') and (
Kelvin Zhangc184fa12021-03-22 15:38:38 -0400453 framework_dict.get('use_dynamic_partitions') == 'true'):
Daniel Normanbfc51ef2019-07-24 14:34:54 -0700454 merged_dynamic_partitions_dict = common.MergeDynamicPartitionInfoDicts(
Daniel Norman55417142019-11-25 16:04:36 -0800455 framework_dict=framework_dict, vendor_dict=merged_dict)
Daniel Normand5d70ea2019-06-05 15:13:43 -0700456 merged_dict.update(merged_dynamic_partitions_dict)
Tao Bao48a2feb2019-06-28 11:00:05 -0700457 # Ensure that add_img_to_target_files rebuilds super split images for
458 # devices that retrofit dynamic partitions. This flag may have been set to
459 # false in the partial builds to prevent duplicate building of super.img.
Daniel Norman0bf940c2019-06-10 12:50:19 -0700460 merged_dict['build_super_partition'] = 'true'
Daniel Norman19b9fe92019-03-19 14:48:02 -0700461
Daniel Norman38888d32020-11-19 14:51:15 -0800462 # If AVB is enabled then ensure that we build vbmeta.img.
463 # Partial builds with AVB enabled may set PRODUCT_BUILD_VBMETA_IMAGE=false to
464 # skip building an incomplete vbmeta.img.
465 if merged_dict.get('avb_enable') == 'true':
466 merged_dict['avb_building_vbmeta_image'] = 'true'
467
Daniel Normand5d70ea2019-06-05 15:13:43 -0700468 # Replace <image>_selinux_fc values with framework or vendor file_contexts.bin
Daniel Norman72c626f2019-05-13 15:58:14 -0700469 # depending on which dictionary the key came from.
470 # Only the file basename is required because all selinux_fc properties are
471 # replaced with the full path to the file under META/ when misc_info.txt is
472 # loaded from target files for repacking. See common.py LoadInfoDict().
Daniel Normand5d70ea2019-06-05 15:13:43 -0700473 for key in merged_dict:
Daniel Norman72c626f2019-05-13 15:58:14 -0700474 if key.endswith('_selinux_fc'):
Daniel Normand5d70ea2019-06-05 15:13:43 -0700475 merged_dict[key] = 'vendor_file_contexts.bin'
476 for key in framework_dict:
Daniel Norman72c626f2019-05-13 15:58:14 -0700477 if key.endswith('_selinux_fc'):
Daniel Normand5d70ea2019-06-05 15:13:43 -0700478 merged_dict[key] = 'framework_file_contexts.bin'
Daniel Norman72c626f2019-05-13 15:58:14 -0700479
Daniel Normane5b134a2019-04-17 14:54:06 -0700480 output_misc_info_txt = os.path.join(output_target_files_temp_dir, 'META',
481 'misc_info.txt')
Daniel Normand5d70ea2019-06-05 15:13:43 -0700482 write_sorted_data(data=merged_dict, path=output_misc_info_txt)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800483
484
Daniel Normand5d70ea2019-06-05 15:13:43 -0700485def process_dynamic_partitions_info_txt(framework_target_files_dir,
486 vendor_target_files_dir,
Daniel Normana61cde02019-05-03 14:19:13 -0700487 output_target_files_dir):
Tao Bao2ad4b822019-06-27 16:52:12 -0700488 """Performs special processing for META/dynamic_partitions_info.txt.
Daniel Normana61cde02019-05-03 14:19:13 -0700489
490 This function merges the contents of the META/dynamic_partitions_info.txt
Daniel Normand5d70ea2019-06-05 15:13:43 -0700491 files from the framework directory and the vendor directory, placing the
492 merged result in the output directory.
Daniel Normana61cde02019-05-03 14:19:13 -0700493
Daniel Normand5d70ea2019-06-05 15:13:43 -0700494 This function does nothing if META/dynamic_partitions_info.txt from the vendor
Daniel Normana61cde02019-05-03 14:19:13 -0700495 directory does not exist.
496
497 Args:
Daniel Normand5d70ea2019-06-05 15:13:43 -0700498 framework_target_files_dir: The name of a directory containing the special
499 items extracted from the framework target files package.
500 vendor_target_files_dir: The name of a directory containing the special
501 items extracted from the vendor target files package.
Daniel Normana61cde02019-05-03 14:19:13 -0700502 output_target_files_dir: The name of a directory that will be used to create
503 the output target files package after all the special cases are processed.
504 """
505
506 if not os.path.exists(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700507 os.path.join(vendor_target_files_dir, 'META',
Daniel Normana61cde02019-05-03 14:19:13 -0700508 'dynamic_partitions_info.txt')):
509 return
510
Kiyoung Kimebe7c9c2019-06-25 17:09:55 +0900511 dynamic_partitions_info_path = ['META', 'dynamic_partitions_info.txt']
Daniel Normana61cde02019-05-03 14:19:13 -0700512
Kiyoung Kimebe7c9c2019-06-25 17:09:55 +0900513 framework_dynamic_partitions_dict = common.LoadDictionaryFromFile(
514 os.path.join(framework_target_files_dir, *dynamic_partitions_info_path))
515 vendor_dynamic_partitions_dict = common.LoadDictionaryFromFile(
516 os.path.join(vendor_target_files_dir, *dynamic_partitions_info_path))
Daniel Normana61cde02019-05-03 14:19:13 -0700517
Daniel Normanbfc51ef2019-07-24 14:34:54 -0700518 merged_dynamic_partitions_dict = common.MergeDynamicPartitionInfoDicts(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700519 framework_dict=framework_dynamic_partitions_dict,
Daniel Norman55417142019-11-25 16:04:36 -0800520 vendor_dict=vendor_dynamic_partitions_dict)
Daniel Normana61cde02019-05-03 14:19:13 -0700521
522 output_dynamic_partitions_info_txt = os.path.join(
523 output_target_files_dir, 'META', 'dynamic_partitions_info.txt')
Chris Grossfabf50a2019-05-02 12:42:09 -0700524 write_sorted_data(
525 data=merged_dynamic_partitions_dict,
526 path=output_dynamic_partitions_info_txt)
527
528
Bill Peckham19c3feb2020-03-20 18:31:43 -0700529def item_list_to_partition_set(item_list):
530 """Converts a target files item list to a partition set.
531
532 The item list contains items that might look like 'SYSTEM/*' or 'VENDOR/*' or
533 'OTA/android-info.txt'. Items that end in '/*' are assumed to match entire
534 directories where 'SYSTEM' or 'VENDOR' is a directory name that identifies the
535 contents of a partition of the same name. Other items in the list, such as the
536 'OTA' example contain metadata. This function iterates such a list, returning
537 a set that contains the partition entries.
538
539 Args:
540 item_list: A list of items in a target files package.
Daniel Normanb0c75912020-09-24 14:30:21 -0700541
Bill Peckham19c3feb2020-03-20 18:31:43 -0700542 Returns:
543 A set of partitions extracted from the list of items.
544 """
545
546 partition_set = set()
547
548 for item in item_list:
549 match = PARTITION_ITEM_PATTERN.search(item.strip())
550 partition_tag = match.group(1).lower() if match else None
551
552 if partition_tag:
553 partition_set.add(partition_tag)
554
555 return partition_set
556
557
Daniel Normand5d70ea2019-06-05 15:13:43 -0700558def process_apex_keys_apk_certs_common(framework_target_files_dir,
559 vendor_target_files_dir,
Bill Peckham19c3feb2020-03-20 18:31:43 -0700560 output_target_files_dir,
561 framework_partition_set,
562 vendor_partition_set, file_name):
Tao Bao2ad4b822019-06-27 16:52:12 -0700563 """Performs special processing for META/apexkeys.txt or META/apkcerts.txt.
Chris Grossfabf50a2019-05-02 12:42:09 -0700564
565 This function merges the contents of the META/apexkeys.txt or
Tao Bao2ad4b822019-06-27 16:52:12 -0700566 META/apkcerts.txt files from the framework directory and the vendor directory,
567 placing the merged result in the output directory. The precondition in that
568 the files are already extracted. The post condition is that the output
569 META/apexkeys.txt or META/apkcerts.txt contains the merged content.
Chris Grossfabf50a2019-05-02 12:42:09 -0700570
571 Args:
Daniel Normand5d70ea2019-06-05 15:13:43 -0700572 framework_target_files_dir: The name of a directory containing the special
573 items extracted from the framework target files package.
574 vendor_target_files_dir: The name of a directory containing the special
575 items extracted from the vendor target files package.
Chris Grossfabf50a2019-05-02 12:42:09 -0700576 output_target_files_dir: The name of a directory that will be used to create
577 the output target files package after all the special cases are processed.
Bill Peckham19c3feb2020-03-20 18:31:43 -0700578 framework_partition_set: Partitions that are considered framework
579 partitions. Used to filter apexkeys.txt and apkcerts.txt.
580 vendor_partition_set: Partitions that are considered vendor partitions. Used
581 to filter apexkeys.txt and apkcerts.txt.
Chris Grossfabf50a2019-05-02 12:42:09 -0700582 file_name: The name of the file to merge. One of apkcerts.txt or
583 apexkeys.txt.
584 """
585
586 def read_helper(d):
587 temp = {}
588 file_path = os.path.join(d, 'META', file_name)
589 with open(file_path) as f:
590 for line in f:
591 if line.strip():
Bill Peckham19c3feb2020-03-20 18:31:43 -0700592 name = line.split()[0]
593 match = MODULE_KEY_PATTERN.search(name)
594 temp[match.group(1)] = line.strip()
Chris Grossfabf50a2019-05-02 12:42:09 -0700595 return temp
596
Daniel Normand5d70ea2019-06-05 15:13:43 -0700597 framework_dict = read_helper(framework_target_files_dir)
598 vendor_dict = read_helper(vendor_target_files_dir)
Bill Peckham19c3feb2020-03-20 18:31:43 -0700599 merged_dict = {}
Chris Grossfabf50a2019-05-02 12:42:09 -0700600
Bill Peckham19c3feb2020-03-20 18:31:43 -0700601 def filter_into_merged_dict(item_dict, partition_set):
602 for key, value in item_dict.items():
603 match = PARTITION_TAG_PATTERN.search(value)
604
605 if match is None:
606 raise ValueError('Entry missing partition tag: %s' % value)
607
608 partition_tag = match.group(1)
609
610 if partition_tag in partition_set:
611 if key in merged_dict:
Daniel Normanb0c75912020-09-24 14:30:21 -0700612 if OPTIONS.allow_duplicate_apkapex_keys:
613 # TODO(b/150582573) Always raise on duplicates.
614 logger.warning('Duplicate key %s' % key)
615 continue
616 else:
617 raise ValueError('Duplicate key %s' % key)
Bill Peckham19c3feb2020-03-20 18:31:43 -0700618
619 merged_dict[key] = value
620
621 filter_into_merged_dict(framework_dict, framework_partition_set)
622 filter_into_merged_dict(vendor_dict, vendor_partition_set)
Chris Grossfabf50a2019-05-02 12:42:09 -0700623
624 output_file = os.path.join(output_target_files_dir, 'META', file_name)
625
Bill Peckham19c3feb2020-03-20 18:31:43 -0700626 # The following code is similar to write_sorted_data, but different enough
627 # that we couldn't use that function. We need the output to be sorted by the
628 # basename of the apex/apk (without the ".apex" or ".apk" suffix). This
629 # allows the sort to be consistent with the framework/vendor input data and
630 # eases comparison of input data with merged data.
631 with open(output_file, 'w') as output:
632 for key in sorted(merged_dict.keys()):
633 out_str = merged_dict[key] + '\n'
634 output.write(out_str)
Daniel Normana61cde02019-05-03 14:19:13 -0700635
636
Daniel Normand5d70ea2019-06-05 15:13:43 -0700637def copy_file_contexts(framework_target_files_dir, vendor_target_files_dir,
Daniel Norman72c626f2019-05-13 15:58:14 -0700638 output_target_files_dir):
639 """Creates named copies of each build's file_contexts.bin in output META/."""
Daniel Normand5d70ea2019-06-05 15:13:43 -0700640 framework_fc_path = os.path.join(framework_target_files_dir, 'META',
641 'framework_file_contexts.bin')
642 if not os.path.exists(framework_fc_path):
643 framework_fc_path = os.path.join(framework_target_files_dir, 'META',
644 'file_contexts.bin')
645 if not os.path.exists(framework_fc_path):
646 raise ValueError('Missing framework file_contexts.bin.')
647 shutil.copyfile(
648 framework_fc_path,
649 os.path.join(output_target_files_dir, 'META',
650 'framework_file_contexts.bin'))
651
652 vendor_fc_path = os.path.join(vendor_target_files_dir, 'META',
653 'vendor_file_contexts.bin')
654 if not os.path.exists(vendor_fc_path):
655 vendor_fc_path = os.path.join(vendor_target_files_dir, 'META',
Daniel Normanedf12472019-05-22 10:47:08 -0700656 'file_contexts.bin')
Daniel Normand5d70ea2019-06-05 15:13:43 -0700657 if not os.path.exists(vendor_fc_path):
658 raise ValueError('Missing vendor file_contexts.bin.')
Daniel Norman72c626f2019-05-13 15:58:14 -0700659 shutil.copyfile(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700660 vendor_fc_path,
661 os.path.join(output_target_files_dir, 'META', 'vendor_file_contexts.bin'))
Daniel Norman72c626f2019-05-13 15:58:14 -0700662
663
Daniel Norman48603ff2021-02-22 15:15:24 -0800664def compile_split_sepolicy(product_out, partition_map, output_policy):
665 """Uses secilc to compile a split sepolicy file.
666
667 Depends on various */etc/selinux/* and */etc/vintf/* files within partitions.
668
669 Args:
670 product_out: PRODUCT_OUT directory, containing partition directories.
671 partition_map: A map of partition name -> relative path within product_out.
672 output_policy: The name of the output policy created by secilc.
673
674 Returns:
675 A command list that can be executed to create the compiled sepolicy.
676 """
677
678 def get_file(partition, path):
679 if partition not in partition_map:
680 logger.warning('Cannot load SEPolicy files for missing partition %s',
681 partition)
682 return None
683 return os.path.join(product_out, partition_map[partition], path)
684
685 # Load the kernel sepolicy version from the FCM. This is normally provided
686 # directly to selinux.cpp as a build flag, but is also available in this file.
687 fcm_file = get_file('system', 'etc/vintf/compatibility_matrix.device.xml')
688 if not fcm_file or not os.path.exists(fcm_file):
689 raise ExternalError('Missing required file for loading sepolicy: %s', fcm)
690 kernel_sepolicy_version = ElementTree.parse(fcm_file).getroot().find(
691 'sepolicy/kernel-sepolicy-version').text
692
693 # Load the vendor's plat sepolicy version. This is the version used for
694 # locating sepolicy mapping files.
695 vendor_plat_version_file = get_file('vendor',
696 'etc/selinux/plat_sepolicy_vers.txt')
697 if not vendor_plat_version_file or not os.path.exists(
Kelvin Zhangc184fa12021-03-22 15:38:38 -0400698 vendor_plat_version_file):
Daniel Norman48603ff2021-02-22 15:15:24 -0800699 raise ExternalError('Missing required sepolicy file %s',
700 vendor_plat_version_file)
701 with open(vendor_plat_version_file) as f:
702 vendor_plat_version = f.read().strip()
703
704 # Use the same flags and arguments as selinux.cpp OpenSplitPolicy().
705 cmd = ['secilc', '-m', '-M', 'true', '-G', '-N']
706 cmd.extend(['-c', kernel_sepolicy_version])
707 cmd.extend(['-o', output_policy])
708 cmd.extend(['-f', '/dev/null'])
709
710 required_policy_files = (
711 ('system', 'etc/selinux/plat_sepolicy.cil'),
712 ('system', 'etc/selinux/mapping/%s.cil' % vendor_plat_version),
713 ('vendor', 'etc/selinux/vendor_sepolicy.cil'),
714 ('vendor', 'etc/selinux/plat_pub_versioned.cil'),
715 )
716 for policy in (map(lambda partition_and_path: get_file(*partition_and_path),
717 required_policy_files)):
718 if not policy or not os.path.exists(policy):
719 raise ExternalError('Missing required sepolicy file %s', policy)
720 cmd.append(policy)
721
722 optional_policy_files = (
723 ('system', 'etc/selinux/mapping/%s.compat.cil' % vendor_plat_version),
724 ('system_ext', 'etc/selinux/system_ext_sepolicy.cil'),
725 ('system_ext', 'etc/selinux/mapping/%s.cil' % vendor_plat_version),
726 ('product', 'etc/selinux/product_sepolicy.cil'),
727 ('product', 'etc/selinux/mapping/%s.cil' % vendor_plat_version),
728 ('odm', 'etc/selinux/odm_sepolicy.cil'),
729 )
730 for policy in (map(lambda partition_and_path: get_file(*partition_and_path),
731 optional_policy_files)):
732 if policy and os.path.exists(policy):
733 cmd.append(policy)
734
735 return cmd
736
737
Daniel Normand5d70ea2019-06-05 15:13:43 -0700738def process_special_cases(framework_target_files_temp_dir,
739 vendor_target_files_temp_dir,
740 output_target_files_temp_dir,
Daniel Normanb0c75912020-09-24 14:30:21 -0700741 framework_misc_info_keys, framework_partition_set,
Bill Peckham19c3feb2020-03-20 18:31:43 -0700742 vendor_partition_set):
Tao Bao2ad4b822019-06-27 16:52:12 -0700743 """Performs special-case processing for certain target files items.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800744
745 Certain files in the output target files package require special-case
746 processing. This function performs all that special-case processing.
747
748 Args:
Daniel Normand5d70ea2019-06-05 15:13:43 -0700749 framework_target_files_temp_dir: The name of a directory containing the
750 special items extracted from the framework target files package.
751 vendor_target_files_temp_dir: The name of a directory containing the special
752 items extracted from the vendor target files package.
Daniel Normane5b134a2019-04-17 14:54:06 -0700753 output_target_files_temp_dir: The name of a directory that will be used to
754 create the output target files package after all the special cases are
755 processed.
Daniel Normand5d70ea2019-06-05 15:13:43 -0700756 framework_misc_info_keys: A list of keys to obtain from the framework
Daniel Normandbbf5a32020-10-22 16:03:32 -0700757 instance of META/misc_info.txt. The remaining keys should come from the
758 vendor instance.
Bill Peckham19c3feb2020-03-20 18:31:43 -0700759 framework_partition_set: Partitions that are considered framework
760 partitions. Used to filter apexkeys.txt and apkcerts.txt.
761 vendor_partition_set: Partitions that are considered vendor partitions. Used
762 to filter apexkeys.txt and apkcerts.txt.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800763 """
764
Daniel Normand5d70ea2019-06-05 15:13:43 -0700765 if 'ab_update' in framework_misc_info_keys:
Bill Peckham364c1cc2019-03-29 18:27:23 -0700766 process_ab_partitions_txt(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700767 framework_target_files_temp_dir=framework_target_files_temp_dir,
768 vendor_target_files_temp_dir=vendor_target_files_temp_dir,
Bill Peckham364c1cc2019-03-29 18:27:23 -0700769 output_target_files_temp_dir=output_target_files_temp_dir)
770
Daniel Norman72c626f2019-05-13 15:58:14 -0700771 copy_file_contexts(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700772 framework_target_files_dir=framework_target_files_temp_dir,
773 vendor_target_files_dir=vendor_target_files_temp_dir,
Daniel Norman72c626f2019-05-13 15:58:14 -0700774 output_target_files_dir=output_target_files_temp_dir)
775
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800776 process_misc_info_txt(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700777 framework_target_files_temp_dir=framework_target_files_temp_dir,
778 vendor_target_files_temp_dir=vendor_target_files_temp_dir,
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800779 output_target_files_temp_dir=output_target_files_temp_dir,
Daniel Normand5d70ea2019-06-05 15:13:43 -0700780 framework_misc_info_keys=framework_misc_info_keys)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800781
Daniel Normana61cde02019-05-03 14:19:13 -0700782 process_dynamic_partitions_info_txt(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700783 framework_target_files_dir=framework_target_files_temp_dir,
784 vendor_target_files_dir=vendor_target_files_temp_dir,
Daniel Norman714bd122019-05-08 16:20:02 -0700785 output_target_files_dir=output_target_files_temp_dir)
Daniel Normana61cde02019-05-03 14:19:13 -0700786
Chris Grossfabf50a2019-05-02 12:42:09 -0700787 process_apex_keys_apk_certs_common(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700788 framework_target_files_dir=framework_target_files_temp_dir,
789 vendor_target_files_dir=vendor_target_files_temp_dir,
Chris Grossfabf50a2019-05-02 12:42:09 -0700790 output_target_files_dir=output_target_files_temp_dir,
Bill Peckham19c3feb2020-03-20 18:31:43 -0700791 framework_partition_set=framework_partition_set,
792 vendor_partition_set=vendor_partition_set,
Chris Grossfabf50a2019-05-02 12:42:09 -0700793 file_name='apkcerts.txt')
794
795 process_apex_keys_apk_certs_common(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700796 framework_target_files_dir=framework_target_files_temp_dir,
797 vendor_target_files_dir=vendor_target_files_temp_dir,
Chris Grossfabf50a2019-05-02 12:42:09 -0700798 output_target_files_dir=output_target_files_temp_dir,
Bill Peckham19c3feb2020-03-20 18:31:43 -0700799 framework_partition_set=framework_partition_set,
800 vendor_partition_set=vendor_partition_set,
Chris Grossfabf50a2019-05-02 12:42:09 -0700801 file_name='apexkeys.txt')
802
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800803
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900804def create_merged_package(temp_dir, framework_target_files, framework_item_list,
805 vendor_target_files, vendor_item_list,
Daniel Norman4cc9df62019-07-18 10:11:07 -0700806 framework_misc_info_keys, rebuild_recovery):
Tao Bao2ad4b822019-06-27 16:52:12 -0700807 """Merges two target files packages into one target files structure.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800808
809 Args:
810 temp_dir: The name of a directory we use when we extract items from the
Daniel Normane5b134a2019-04-17 14:54:06 -0700811 input target files packages, and also a scratch directory that we use for
812 temporary files.
Daniel Normand5d70ea2019-06-05 15:13:43 -0700813 framework_target_files: The name of the zip archive containing the framework
Daniel Normane5b134a2019-04-17 14:54:06 -0700814 partial target files package.
Daniel Normand5d70ea2019-06-05 15:13:43 -0700815 framework_item_list: The list of items to extract from the partial framework
Daniel Normane5b134a2019-04-17 14:54:06 -0700816 target files package as is, meaning these items will land in the output
Daniel Normand5d70ea2019-06-05 15:13:43 -0700817 target files package exactly as they appear in the input partial framework
Daniel Normane5b134a2019-04-17 14:54:06 -0700818 target files package.
Daniel Normand5d70ea2019-06-05 15:13:43 -0700819 vendor_target_files: The name of the zip archive containing the vendor
820 partial target files package.
821 vendor_item_list: The list of items to extract from the partial vendor
822 target files package as is, meaning these items will land in the output
823 target files package exactly as they appear in the input partial vendor
Daniel Normane5b134a2019-04-17 14:54:06 -0700824 target files package.
Daniel Normandbbf5a32020-10-22 16:03:32 -0700825 framework_misc_info_keys: A list of keys to obtain from the framework
826 instance of META/misc_info.txt. The remaining keys should come from the
827 vendor instance.
Daniel Normana4911da2019-03-15 14:36:21 -0700828 rebuild_recovery: If true, rebuild the recovery patch used by non-A/B
Daniel Normane5b134a2019-04-17 14:54:06 -0700829 devices and write it to the system image.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800830
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900831 Returns:
832 Path to merged package under temp directory.
833 """
Daniel Normandbbf5a32020-10-22 16:03:32 -0700834 # Extract "as is" items from the input framework and vendor partial target
835 # files packages directly into the output temporary directory, since these items
836 # do not need special case processing.
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800837
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800838 output_target_files_temp_dir = os.path.join(temp_dir, 'output')
Bill Peckham889b0c62019-02-21 18:53:37 -0800839 extract_items(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700840 target_files=framework_target_files,
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800841 target_files_temp_dir=output_target_files_temp_dir,
Daniel Normand5d70ea2019-06-05 15:13:43 -0700842 extract_item_list=framework_item_list)
Bill Peckham889b0c62019-02-21 18:53:37 -0800843 extract_items(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700844 target_files=vendor_target_files,
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800845 target_files_temp_dir=output_target_files_temp_dir,
Daniel Normand5d70ea2019-06-05 15:13:43 -0700846 extract_item_list=vendor_item_list)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800847
Daniel Normandbbf5a32020-10-22 16:03:32 -0700848 # Perform special case processing on META/* items.
849 # After this function completes successfully, all the files we need to create
850 # the output target files package are in place.
851 framework_target_files_temp_dir = os.path.join(temp_dir, 'framework')
852 vendor_target_files_temp_dir = os.path.join(temp_dir, 'vendor')
Daniel Normand5d70ea2019-06-05 15:13:43 -0700853 extract_items(
854 target_files=framework_target_files,
855 target_files_temp_dir=framework_target_files_temp_dir,
Daniel Normandbbf5a32020-10-22 16:03:32 -0700856 extract_item_list=('META/*',))
Bill Peckham889b0c62019-02-21 18:53:37 -0800857 extract_items(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700858 target_files=vendor_target_files,
859 target_files_temp_dir=vendor_target_files_temp_dir,
Daniel Normandbbf5a32020-10-22 16:03:32 -0700860 extract_item_list=('META/*',))
Bill Peckham889b0c62019-02-21 18:53:37 -0800861 process_special_cases(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700862 framework_target_files_temp_dir=framework_target_files_temp_dir,
863 vendor_target_files_temp_dir=vendor_target_files_temp_dir,
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800864 output_target_files_temp_dir=output_target_files_temp_dir,
Bill Peckham19c3feb2020-03-20 18:31:43 -0700865 framework_misc_info_keys=framework_misc_info_keys,
866 framework_partition_set=item_list_to_partition_set(framework_item_list),
867 vendor_partition_set=item_list_to_partition_set(vendor_item_list))
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800868
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900869 return output_target_files_temp_dir
870
871
872def generate_images(target_files_dir, rebuild_recovery):
873 """Generate images from target files.
874
875 This function takes merged output temporary directory and create images
876 from it.
877
878 Args:
879 target_files_dir: Path to merged temp directory.
880 rebuild_recovery: If true, rebuild the recovery patch used by non-A/B
881 devices and write it to the system image.
882 """
883
884 # Regenerate IMAGES in the target directory.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800885
Daniel Normandbbf5a32020-10-22 16:03:32 -0700886 add_img_args = [
887 '--verbose',
888 '--add_missing',
889 ]
Bill Peckhame868aec2019-09-17 17:06:47 -0700890 # TODO(b/132730255): Remove this if statement.
Daniel Normana4911da2019-03-15 14:36:21 -0700891 if rebuild_recovery:
892 add_img_args.append('--rebuild_recovery')
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900893 add_img_args.append(target_files_dir)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800894
895 add_img_to_target_files.main(add_img_args)
896
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900897
898def generate_super_empty_image(target_dir, output_super_empty):
Tao Bao2ad4b822019-06-27 16:52:12 -0700899 """Generates super_empty image from target package.
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900900
901 Args:
902 target_dir: Path to the target file package which contains misc_info.txt for
903 detailed information for super image.
904 output_super_empty: If provided, copies a super_empty.img file from the
905 target files package to this path.
906 """
Daniel Norman1bd2a1d2019-04-18 12:32:18 -0700907 # Create super_empty.img using the merged misc_info.txt.
908
Daniel Norman4cc9df62019-07-18 10:11:07 -0700909 misc_info_txt = os.path.join(target_dir, 'META', 'misc_info.txt')
Daniel Norman1bd2a1d2019-04-18 12:32:18 -0700910
Kiyoung Kimebe7c9c2019-06-25 17:09:55 +0900911 use_dynamic_partitions = common.LoadDictionaryFromFile(misc_info_txt).get(
912 'use_dynamic_partitions')
Daniel Norman1bd2a1d2019-04-18 12:32:18 -0700913
914 if use_dynamic_partitions != 'true' and output_super_empty:
915 raise ValueError(
916 'Building super_empty.img requires use_dynamic_partitions=true.')
917 elif use_dynamic_partitions == 'true':
Daniel Norman4cc9df62019-07-18 10:11:07 -0700918 super_empty_img = os.path.join(target_dir, 'IMAGES', 'super_empty.img')
Daniel Norman1bd2a1d2019-04-18 12:32:18 -0700919 build_super_image_args = [
920 misc_info_txt,
921 super_empty_img,
922 ]
923 build_super_image.main(build_super_image_args)
924
925 # Copy super_empty.img to the user-provided output_super_empty location.
926 if output_super_empty:
927 shutil.copyfile(super_empty_img, output_super_empty)
928
Daniel Normanb8a2f9d2019-04-24 12:55:51 -0700929
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900930def create_target_files_archive(output_file, source_dir, temp_dir):
Tao Bao2ad4b822019-06-27 16:52:12 -0700931 """Creates archive from target package.
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900932
933 Args:
934 output_file: The name of the zip archive target files package.
935 source_dir: The target directory contains package to be archived.
936 temp_dir: Path to temporary directory for any intermediate files.
937 """
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800938 output_target_files_list = os.path.join(temp_dir, 'output.list')
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900939 output_zip = os.path.abspath(output_file)
Daniel Norman4cc9df62019-07-18 10:11:07 -0700940 output_target_files_meta_dir = os.path.join(source_dir, 'META')
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800941
Daniel Normandbbf5a32020-10-22 16:03:32 -0700942 def files_from_path(target_path, extra_args=None):
943 """Gets files under the given path and return a sorted list."""
944 find_command = ['find', target_path] + (extra_args or [])
945 find_process = common.Run(
946 find_command, stdout=subprocess.PIPE, verbose=False)
947 return common.RunAndCheckOutput(['sort'],
948 stdin=find_process.stdout,
949 verbose=False)
950
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900951 meta_content = files_from_path(output_target_files_meta_dir)
Daniel Norman4cc9df62019-07-18 10:11:07 -0700952 other_content = files_from_path(
953 source_dir,
954 ['-path', output_target_files_meta_dir, '-prune', '-o', '-print'])
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800955
Tao Bao2ad4b822019-06-27 16:52:12 -0700956 with open(output_target_files_list, 'w') as f:
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800957 f.write(meta_content)
958 f.write(other_content)
959
960 command = [
Bill Peckhamf753e152019-02-19 18:02:46 -0800961 'soong_zip',
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800962 '-d',
Daniel Normane5b134a2019-04-17 14:54:06 -0700963 '-o',
964 output_zip,
965 '-C',
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900966 source_dir,
Daniel Normaneaf5c1d2021-02-09 11:01:42 -0800967 '-r',
Daniel Normane5b134a2019-04-17 14:54:06 -0700968 output_target_files_list,
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800969 ]
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900970
971 logger.info('creating %s', output_file)
Daniel Normaneaf5c1d2021-02-09 11:01:42 -0800972 common.RunAndCheckOutput(command, verbose=True)
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900973 logger.info('finished creating %s', output_file)
974
975 return output_zip
976
977
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900978def merge_target_files(temp_dir, framework_target_files, framework_item_list,
979 framework_misc_info_keys, vendor_target_files,
980 vendor_item_list, output_target_files, output_dir,
981 output_item_list, output_ota, output_img,
982 output_super_empty, rebuild_recovery):
Tao Bao2ad4b822019-06-27 16:52:12 -0700983 """Merges two target files packages together.
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900984
985 This function takes framework and vendor target files packages as input,
986 performs various file extractions, special case processing, and finally
987 creates a merged zip archive as output.
988
989 Args:
990 temp_dir: The name of a directory we use when we extract items from the
991 input target files packages, and also a scratch directory that we use for
992 temporary files.
993 framework_target_files: The name of the zip archive containing the framework
994 partial target files package.
995 framework_item_list: The list of items to extract from the partial framework
996 target files package as is, meaning these items will land in the output
997 target files package exactly as they appear in the input partial framework
998 target files package.
Daniel Normandbbf5a32020-10-22 16:03:32 -0700999 framework_misc_info_keys: A list of keys to obtain from the framework
1000 instance of META/misc_info.txt. The remaining keys should come from the
1001 vendor instance.
Kiyoung Kim7cbeda72019-06-28 13:26:04 +09001002 vendor_target_files: The name of the zip archive containing the vendor
1003 partial target files package.
1004 vendor_item_list: The list of items to extract from the partial vendor
1005 target files package as is, meaning these items will land in the output
1006 target files package exactly as they appear in the input partial vendor
1007 target files package.
1008 output_target_files: The name of the output zip archive target files package
1009 created by merging framework and vendor.
1010 output_dir: The destination directory for saving merged files.
1011 output_item_list: The list of items to copy into the output_dir.
1012 output_ota: The name of the output zip archive ota package.
1013 output_img: The name of the output zip archive img package.
1014 output_super_empty: If provided, creates a super_empty.img file from the
1015 merged target files package and saves it at this path.
1016 rebuild_recovery: If true, rebuild the recovery patch used by non-A/B
1017 devices and write it to the system image.
1018 """
1019
1020 logger.info('starting: merge framework %s and vendor %s into output %s',
1021 framework_target_files, vendor_target_files, output_target_files)
1022
1023 output_target_files_temp_dir = create_merged_package(
1024 temp_dir, framework_target_files, framework_item_list,
1025 vendor_target_files, vendor_item_list, framework_misc_info_keys,
1026 rebuild_recovery)
1027
Yifan Hongade0d3f2019-08-21 16:37:11 -07001028 if not check_target_files_vintf.CheckVintf(output_target_files_temp_dir):
Daniel Normanb0c75912020-09-24 14:30:21 -07001029 raise RuntimeError('Incompatible VINTF metadata')
Yifan Hongade0d3f2019-08-21 16:37:11 -07001030
Daniel Norman21c34f72020-11-11 17:25:50 -08001031 partition_map = common.PartitionMapFromTargetFiles(
1032 output_target_files_temp_dir)
1033
Daniel Normand3351562020-10-29 12:33:11 -07001034 # Generate and check for cross-partition violations of sharedUserId
1035 # values in APKs. This requires the input target-files packages to contain
1036 # *.apk files.
Daniel Normanb8d52a22020-10-26 17:55:00 -07001037 shareduid_violation_modules = os.path.join(
1038 output_target_files_temp_dir, 'META', 'shareduid_violation_modules.json')
1039 with open(shareduid_violation_modules, 'w') as f:
Daniel Normanb8d52a22020-10-26 17:55:00 -07001040 violation = find_shareduid_violation.FindShareduidViolation(
1041 output_target_files_temp_dir, partition_map)
Daniel Normand3351562020-10-29 12:33:11 -07001042
1043 # Write the output to a file to enable debugging.
Daniel Normanb8d52a22020-10-26 17:55:00 -07001044 f.write(violation)
Daniel Normand3351562020-10-29 12:33:11 -07001045
1046 # Check for violations across the input builds' partition groups.
Daniel Norman21c34f72020-11-11 17:25:50 -08001047 framework_partitions = item_list_to_partition_set(framework_item_list)
1048 vendor_partitions = item_list_to_partition_set(vendor_item_list)
Daniel Normand3351562020-10-29 12:33:11 -07001049 shareduid_errors = common.SharedUidPartitionViolations(
1050 json.loads(violation), [framework_partitions, vendor_partitions])
1051 if shareduid_errors:
1052 for error in shareduid_errors:
1053 logger.error(error)
1054 raise ValueError('sharedUserId APK error. See %s' %
1055 shareduid_violation_modules)
Daniel Normanb8d52a22020-10-26 17:55:00 -07001056
Daniel Norman48603ff2021-02-22 15:15:24 -08001057 # host_init_verifier and secilc check only the following partitions:
Daniel Norman21c34f72020-11-11 17:25:50 -08001058 filtered_partitions = {
1059 partition: path
1060 for partition, path in partition_map.items()
Daniel Norman21c34f72020-11-11 17:25:50 -08001061 if partition in ['system', 'system_ext', 'product', 'vendor', 'odm']
1062 }
Daniel Norman48603ff2021-02-22 15:15:24 -08001063
1064 # Run host_init_verifier on the combined init rc files.
Daniel Norman21c34f72020-11-11 17:25:50 -08001065 common.RunHostInitVerifier(
1066 product_out=output_target_files_temp_dir,
1067 partition_map=filtered_partitions)
1068
Daniel Norman48603ff2021-02-22 15:15:24 -08001069 # Check that the split sepolicy from the multiple builds can compile.
1070 split_sepolicy_cmd = compile_split_sepolicy(
1071 product_out=output_target_files_temp_dir,
1072 partition_map=filtered_partitions,
1073 output_policy=os.path.join(output_target_files_temp_dir,
1074 'META/combined.policy'))
1075 logger.info('Compiling split sepolicy: %s', ' '.join(split_sepolicy_cmd))
1076 common.RunAndCheckOutput(split_sepolicy_cmd)
1077 # TODO(b/178864050): Run tests on the combined.policy file.
1078
Kiyoung Kim7cbeda72019-06-28 13:26:04 +09001079 generate_images(output_target_files_temp_dir, rebuild_recovery)
1080
1081 generate_super_empty_image(output_target_files_temp_dir, output_super_empty)
1082
Kiyoung Kim7cbeda72019-06-28 13:26:04 +09001083 # Finally, create the output target files zip archive and/or copy the
1084 # output items to the output target files directory.
1085
1086 if output_dir:
1087 copy_items(output_target_files_temp_dir, output_dir, output_item_list)
1088
1089 if not output_target_files:
1090 return
1091
1092 output_zip = create_target_files_archive(output_target_files,
1093 output_target_files_temp_dir,
1094 temp_dir)
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001095
Daniel Norman74eb74b2019-09-18 14:01:48 -07001096 # Create the IMG package from the merged target files package.
Kelvin Zhangc184fa12021-03-22 15:38:38 -04001097 with zipfile.ZipFile(output_zip, allowZip64=True) as zfp:
1098 AddCareMapForAbOta(zfp, PARTITIONS_WITH_CARE_MAP, partition_map)
Daniel Norman74eb74b2019-09-18 14:01:48 -07001099
1100 if output_img:
1101 img_from_target_files.main([output_zip, output_img])
1102
Daniel Norman3b64ce12019-04-16 16:11:35 -07001103 # Create the OTA package from the merged target files package.
1104
1105 if output_ota:
Daniel Norman4cc9df62019-07-18 10:11:07 -07001106 ota_from_target_files.main([output_zip, output_ota])
Daniel Norman3b64ce12019-04-16 16:11:35 -07001107
Daniel Norman1bd2a1d2019-04-18 12:32:18 -07001108
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001109def call_func_with_temp_dir(func, keep_tmp):
Tao Bao2ad4b822019-06-27 16:52:12 -07001110 """Manages the creation and cleanup of the temporary directory.
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001111
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001112 This function calls the given function after first creating a temporary
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001113 directory. It also cleans up the temporary directory.
1114
1115 Args:
Daniel Normane5b134a2019-04-17 14:54:06 -07001116 func: The function to call. Should accept one parameter, the path to the
1117 temporary directory.
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001118 keep_tmp: Keep the temporary directory after processing is complete.
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001119 """
1120
1121 # Create a temporary directory. This will serve as the parent of directories
1122 # we use when we extract items from the input target files packages, and also
1123 # a scratch directory that we use for temporary files.
1124
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001125 temp_dir = common.MakeTempDir(prefix='merge_target_files_')
1126
1127 try:
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001128 func(temp_dir)
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001129 finally:
1130 if keep_tmp:
1131 logger.info('keeping %s', temp_dir)
1132 else:
1133 common.Cleanup()
1134
1135
1136def main():
1137 """The main function.
1138
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001139 Process command line arguments, then call merge_target_files to
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001140 perform the heavy lifting.
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001141 """
1142
1143 common.InitLogging()
1144
Bill Peckhamf753e152019-02-19 18:02:46 -08001145 def option_handler(o, a):
1146 if o == '--system-target-files':
Daniel Normand5d70ea2019-06-05 15:13:43 -07001147 logger.warning(
1148 '--system-target-files has been renamed to --framework-target-files')
1149 OPTIONS.framework_target_files = a
1150 elif o == '--framework-target-files':
1151 OPTIONS.framework_target_files = a
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001152 elif o == '--system-item-list':
Daniel Normand5d70ea2019-06-05 15:13:43 -07001153 logger.warning(
1154 '--system-item-list has been renamed to --framework-item-list')
1155 OPTIONS.framework_item_list = a
1156 elif o == '--framework-item-list':
1157 OPTIONS.framework_item_list = a
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001158 elif o == '--system-misc-info-keys':
Daniel Norman4cc9df62019-07-18 10:11:07 -07001159 logger.warning('--system-misc-info-keys has been renamed to '
1160 '--framework-misc-info-keys')
Daniel Normand5d70ea2019-06-05 15:13:43 -07001161 OPTIONS.framework_misc_info_keys = a
1162 elif o == '--framework-misc-info-keys':
1163 OPTIONS.framework_misc_info_keys = a
Bill Peckhamf753e152019-02-19 18:02:46 -08001164 elif o == '--other-target-files':
Daniel Normand5d70ea2019-06-05 15:13:43 -07001165 logger.warning(
1166 '--other-target-files has been renamed to --vendor-target-files')
1167 OPTIONS.vendor_target_files = a
1168 elif o == '--vendor-target-files':
1169 OPTIONS.vendor_target_files = a
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001170 elif o == '--other-item-list':
Kelvin Zhangc184fa12021-03-22 15:38:38 -04001171 logger.warning(
1172 '--other-item-list has been renamed to --vendor-item-list')
Daniel Normand5d70ea2019-06-05 15:13:43 -07001173 OPTIONS.vendor_item_list = a
1174 elif o == '--vendor-item-list':
1175 OPTIONS.vendor_item_list = a
Bill Peckhamf753e152019-02-19 18:02:46 -08001176 elif o == '--output-target-files':
1177 OPTIONS.output_target_files = a
Daniel Normanfdb38812019-04-15 09:47:24 -07001178 elif o == '--output-dir':
1179 OPTIONS.output_dir = a
1180 elif o == '--output-item-list':
1181 OPTIONS.output_item_list = a
Daniel Norman3b64ce12019-04-16 16:11:35 -07001182 elif o == '--output-ota':
1183 OPTIONS.output_ota = a
Daniel Norman1bd2a1d2019-04-18 12:32:18 -07001184 elif o == '--output-img':
1185 OPTIONS.output_img = a
Daniel Normanf0318252019-04-15 11:34:56 -07001186 elif o == '--output-super-empty':
1187 OPTIONS.output_super_empty = a
Daniel Normanb0c75912020-09-24 14:30:21 -07001188 elif o == '--rebuild_recovery': # TODO(b/132730255): Warn
Daniel Normana4911da2019-03-15 14:36:21 -07001189 OPTIONS.rebuild_recovery = True
Daniel Normanb0c75912020-09-24 14:30:21 -07001190 elif o == '--allow-duplicate-apkapex-keys':
1191 OPTIONS.allow_duplicate_apkapex_keys = True
Bill Peckham364c1cc2019-03-29 18:27:23 -07001192 elif o == '--keep-tmp':
Bill Peckhamf753e152019-02-19 18:02:46 -08001193 OPTIONS.keep_tmp = True
1194 else:
1195 return False
1196 return True
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001197
Bill Peckhamf753e152019-02-19 18:02:46 -08001198 args = common.ParseOptions(
Daniel Normane5b134a2019-04-17 14:54:06 -07001199 sys.argv[1:],
1200 __doc__,
Bill Peckhamf753e152019-02-19 18:02:46 -08001201 extra_long_opts=[
1202 'system-target-files=',
Daniel Normand5d70ea2019-06-05 15:13:43 -07001203 'framework-target-files=',
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001204 'system-item-list=',
Daniel Normand5d70ea2019-06-05 15:13:43 -07001205 'framework-item-list=',
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001206 'system-misc-info-keys=',
Daniel Normand5d70ea2019-06-05 15:13:43 -07001207 'framework-misc-info-keys=',
Bill Peckhamf753e152019-02-19 18:02:46 -08001208 'other-target-files=',
Daniel Normand5d70ea2019-06-05 15:13:43 -07001209 'vendor-target-files=',
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001210 'other-item-list=',
Daniel Normand5d70ea2019-06-05 15:13:43 -07001211 'vendor-item-list=',
Bill Peckhamf753e152019-02-19 18:02:46 -08001212 'output-target-files=',
Daniel Normanfdb38812019-04-15 09:47:24 -07001213 'output-dir=',
1214 'output-item-list=',
Daniel Norman3b64ce12019-04-16 16:11:35 -07001215 'output-ota=',
Daniel Norman1bd2a1d2019-04-18 12:32:18 -07001216 'output-img=',
Daniel Normanf0318252019-04-15 11:34:56 -07001217 'output-super-empty=',
Daniel Normana4911da2019-03-15 14:36:21 -07001218 'rebuild_recovery',
Daniel Normanb0c75912020-09-24 14:30:21 -07001219 'allow-duplicate-apkapex-keys',
Bill Peckham364c1cc2019-03-29 18:27:23 -07001220 'keep-tmp',
Bill Peckhamf753e152019-02-19 18:02:46 -08001221 ],
1222 extra_option_handler=option_handler)
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001223
Tao Bao2ad4b822019-06-27 16:52:12 -07001224 # pylint: disable=too-many-boolean-expressions
Daniel Normand5d70ea2019-06-05 15:13:43 -07001225 if (args or OPTIONS.framework_target_files is None or
1226 OPTIONS.vendor_target_files is None or
Daniel Normane5b134a2019-04-17 14:54:06 -07001227 (OPTIONS.output_target_files is None and OPTIONS.output_dir is None) or
Kelvin Zhangc184fa12021-03-22 15:38:38 -04001228 (OPTIONS.output_dir is not None and OPTIONS.output_item_list is None)):
Bill Peckhamf753e152019-02-19 18:02:46 -08001229 common.Usage(__doc__)
Bill Peckham889b0c62019-02-21 18:53:37 -08001230 sys.exit(1)
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001231
Daniel Normand5d70ea2019-06-05 15:13:43 -07001232 if OPTIONS.framework_item_list:
Daniel Norman4cc9df62019-07-18 10:11:07 -07001233 framework_item_list = common.LoadListFromFile(OPTIONS.framework_item_list)
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001234 else:
Daniel Normand5d70ea2019-06-05 15:13:43 -07001235 framework_item_list = DEFAULT_FRAMEWORK_ITEM_LIST
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001236
Daniel Normand5d70ea2019-06-05 15:13:43 -07001237 if OPTIONS.framework_misc_info_keys:
Daniel Norman4cc9df62019-07-18 10:11:07 -07001238 framework_misc_info_keys = common.LoadListFromFile(
Daniel Normand5d70ea2019-06-05 15:13:43 -07001239 OPTIONS.framework_misc_info_keys)
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001240 else:
Daniel Normand5d70ea2019-06-05 15:13:43 -07001241 framework_misc_info_keys = DEFAULT_FRAMEWORK_MISC_INFO_KEYS
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001242
Daniel Normand5d70ea2019-06-05 15:13:43 -07001243 if OPTIONS.vendor_item_list:
Daniel Norman4cc9df62019-07-18 10:11:07 -07001244 vendor_item_list = common.LoadListFromFile(OPTIONS.vendor_item_list)
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001245 else:
Daniel Normand5d70ea2019-06-05 15:13:43 -07001246 vendor_item_list = DEFAULT_VENDOR_ITEM_LIST
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001247
Daniel Normanfdb38812019-04-15 09:47:24 -07001248 if OPTIONS.output_item_list:
Daniel Norman4cc9df62019-07-18 10:11:07 -07001249 output_item_list = common.LoadListFromFile(OPTIONS.output_item_list)
Daniel Normanfdb38812019-04-15 09:47:24 -07001250 else:
1251 output_item_list = None
1252
Daniel Normane5964522019-03-19 10:32:03 -07001253 if not validate_config_lists(
Kelvin Zhangc184fa12021-03-22 15:38:38 -04001254 framework_item_list=framework_item_list,
1255 framework_misc_info_keys=framework_misc_info_keys,
1256 vendor_item_list=vendor_item_list):
Daniel Normane5964522019-03-19 10:32:03 -07001257 sys.exit(1)
1258
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001259 call_func_with_temp_dir(
1260 lambda temp_dir: merge_target_files(
1261 temp_dir=temp_dir,
Daniel Normand5d70ea2019-06-05 15:13:43 -07001262 framework_target_files=OPTIONS.framework_target_files,
1263 framework_item_list=framework_item_list,
1264 framework_misc_info_keys=framework_misc_info_keys,
1265 vendor_target_files=OPTIONS.vendor_target_files,
1266 vendor_item_list=vendor_item_list,
Daniel Normana4911da2019-03-15 14:36:21 -07001267 output_target_files=OPTIONS.output_target_files,
Daniel Normanfdb38812019-04-15 09:47:24 -07001268 output_dir=OPTIONS.output_dir,
1269 output_item_list=output_item_list,
Daniel Norman3b64ce12019-04-16 16:11:35 -07001270 output_ota=OPTIONS.output_ota,
Daniel Norman1bd2a1d2019-04-18 12:32:18 -07001271 output_img=OPTIONS.output_img,
Daniel Normanf0318252019-04-15 11:34:56 -07001272 output_super_empty=OPTIONS.output_super_empty,
Daniel Normane5b134a2019-04-17 14:54:06 -07001273 rebuild_recovery=OPTIONS.rebuild_recovery), OPTIONS.keep_tmp)
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001274
1275
1276if __name__ == '__main__':
Bill Peckham889b0c62019-02-21 18:53:37 -08001277 main()