blob: 9360d7bc8d078fd6d033b0b6f2c19a6ddb58ce73 [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
96
Bill Peckhame9eb5f92019-02-01 15:52:10 -080097import add_img_to_target_files
Daniel Normanf0318252019-04-15 11:34:56 -070098import build_super_image
Yifan Hongade0d3f2019-08-21 16:37:11 -070099import check_target_files_vintf
Daniel Normanf0318252019-04-15 11:34:56 -0700100import common
Daniel Norman1bd2a1d2019-04-18 12:32:18 -0700101import img_from_target_files
Daniel Normanb8d52a22020-10-26 17:55:00 -0700102import find_shareduid_violation
Daniel Norman3b64ce12019-04-16 16:11:35 -0700103import ota_from_target_files
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800104
105logger = logging.getLogger(__name__)
Tao Bao2ad4b822019-06-27 16:52:12 -0700106
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800107OPTIONS = common.OPTIONS
Bill Peckhamcb848172020-04-03 12:50:47 -0700108# Always turn on verbose logging.
109OPTIONS.verbose = True
Daniel Normand5d70ea2019-06-05 15:13:43 -0700110OPTIONS.framework_target_files = None
111OPTIONS.framework_item_list = None
112OPTIONS.framework_misc_info_keys = None
113OPTIONS.vendor_target_files = None
114OPTIONS.vendor_item_list = None
Bill Peckhamf753e152019-02-19 18:02:46 -0800115OPTIONS.output_target_files = None
Daniel Normanfdb38812019-04-15 09:47:24 -0700116OPTIONS.output_dir = None
117OPTIONS.output_item_list = None
Daniel Norman3b64ce12019-04-16 16:11:35 -0700118OPTIONS.output_ota = None
Daniel Norman1bd2a1d2019-04-18 12:32:18 -0700119OPTIONS.output_img = None
Daniel Normanf0318252019-04-15 11:34:56 -0700120OPTIONS.output_super_empty = None
Bill Peckhame868aec2019-09-17 17:06:47 -0700121# TODO(b/132730255): Remove this option.
Daniel Normana4911da2019-03-15 14:36:21 -0700122OPTIONS.rebuild_recovery = False
Daniel Normanb0c75912020-09-24 14:30:21 -0700123# TODO(b/150582573): Remove this option.
124OPTIONS.allow_duplicate_apkapex_keys = False
Bill Peckhamf753e152019-02-19 18:02:46 -0800125OPTIONS.keep_tmp = False
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800126
Bill Peckham19c3feb2020-03-20 18:31:43 -0700127# In an item list (framework or vendor), we may see entries that select whole
128# partitions. Such an entry might look like this 'SYSTEM/*' (e.g., for the
129# system partition). The following regex matches this and extracts the
130# partition name.
131
132PARTITION_ITEM_PATTERN = re.compile(r'^([A-Z_]+)/\*$')
133
Bill Peckham5c7b0342020-04-03 15:36:23 -0700134# In apexkeys.txt or apkcerts.txt, we will find partition tags on each entry in
135# the file. We use these partition tags to filter the entries in those files
136# from the two different target files packages to produce a merged apexkeys.txt
137# or apkcerts.txt file. A partition tag (e.g., for the product partition) looks
138# like this: 'partition="product"'. We use the group syntax grab the value of
139# the tag. We use non-greedy matching in case there are other fields on the
140# same line.
Bill Peckham19c3feb2020-03-20 18:31:43 -0700141
Bill Peckham5c7b0342020-04-03 15:36:23 -0700142PARTITION_TAG_PATTERN = re.compile(r'partition="(.*?)"')
Bill Peckham19c3feb2020-03-20 18:31:43 -0700143
144# The sorting algorithm for apexkeys.txt and apkcerts.txt does not include the
145# ".apex" or ".apk" suffix, so we use the following pattern to extract a key.
146
147MODULE_KEY_PATTERN = re.compile(r'name="(.+)\.(apex|apk)"')
148
Daniel Normand5d70ea2019-06-05 15:13:43 -0700149# DEFAULT_FRAMEWORK_ITEM_LIST is a list of items to extract from the partial
150# framework target files package as is, meaning these items will land in the
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800151# output target files package exactly as they appear in the input partial
Daniel Normand5d70ea2019-06-05 15:13:43 -0700152# framework target files package.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800153
Daniel Normand5d70ea2019-06-05 15:13:43 -0700154DEFAULT_FRAMEWORK_ITEM_LIST = (
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800155 'META/apkcerts.txt',
156 'META/filesystem_config.txt',
157 'META/root_filesystem_config.txt',
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800158 'META/update_engine_config.txt',
159 'PRODUCT/*',
160 'ROOT/*',
161 'SYSTEM/*',
Daniel Normanedf12472019-05-22 10:47:08 -0700162)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800163
Daniel Normand5d70ea2019-06-05 15:13:43 -0700164# DEFAULT_FRAMEWORK_MISC_INFO_KEYS is a list of keys to obtain from the
Daniel Normandbbf5a32020-10-22 16:03:32 -0700165# framework instance of META/misc_info.txt. The remaining keys should come
166# from the vendor instance.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800167
Daniel Normand5d70ea2019-06-05 15:13:43 -0700168DEFAULT_FRAMEWORK_MISC_INFO_KEYS = (
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800169 'avb_system_hashtree_enable',
170 'avb_system_add_hashtree_footer_args',
171 'avb_system_key_path',
172 'avb_system_algorithm',
173 'avb_system_rollback_index_location',
174 'avb_product_hashtree_enable',
175 'avb_product_add_hashtree_footer_args',
Justin Yun6151e3f2019-06-25 15:58:13 +0900176 'avb_system_ext_hashtree_enable',
177 'avb_system_ext_add_hashtree_footer_args',
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800178 'system_root_image',
179 'root_dir',
180 'ab_update',
181 'default_system_dev_certificate',
182 'system_size',
Chris Gross203191b2020-05-30 02:39:12 +0000183 'building_system_image',
184 'building_system_ext_image',
185 'building_product_image',
Daniel Normanedf12472019-05-22 10:47:08 -0700186)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800187
Daniel Normand5d70ea2019-06-05 15:13:43 -0700188# DEFAULT_VENDOR_ITEM_LIST is a list of items to extract from the partial
189# vendor target files package as is, meaning these items will land in the output
190# target files package exactly as they appear in the input partial vendor target
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800191# files package.
192
Daniel Normand5d70ea2019-06-05 15:13:43 -0700193DEFAULT_VENDOR_ITEM_LIST = (
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800194 'META/boot_filesystem_config.txt',
195 'META/otakeys.txt',
196 'META/releasetools.py',
197 'META/vendor_filesystem_config.txt',
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800198 'BOOT/*',
199 'DATA/*',
200 'ODM/*',
201 'OTA/android-info.txt',
202 'PREBUILT_IMAGES/*',
203 'RADIO/*',
204 'VENDOR/*',
Daniel Normanedf12472019-05-22 10:47:08 -0700205)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800206
Daniel Normanedf12472019-05-22 10:47:08 -0700207# The merge config lists should not attempt to extract items from both
208# builds for any of the following partitions. The partitions in
209# SINGLE_BUILD_PARTITIONS should come entirely from a single build (either
Daniel Normand5d70ea2019-06-05 15:13:43 -0700210# framework or vendor, but not both).
Daniel Normanedf12472019-05-22 10:47:08 -0700211
212SINGLE_BUILD_PARTITIONS = (
213 'BOOT/',
214 'DATA/',
215 'ODM/',
216 'PRODUCT/',
Justin Yun6151e3f2019-06-25 15:58:13 +0900217 'SYSTEM_EXT/',
Daniel Normanedf12472019-05-22 10:47:08 -0700218 'RADIO/',
219 'RECOVERY/',
220 'ROOT/',
221 'SYSTEM/',
222 'SYSTEM_OTHER/',
223 'VENDOR/',
Yifan Hongcfb917a2020-05-07 14:58:20 -0700224 'VENDOR_DLKM/',
Yifan Hongf496f1b2020-07-15 16:52:59 -0700225 'ODM_DLKM/',
Daniel Normanedf12472019-05-22 10:47:08 -0700226)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800227
228
Chris Grossfabf50a2019-05-02 12:42:09 -0700229def write_sorted_data(data, path):
Tao Bao2ad4b822019-06-27 16:52:12 -0700230 """Writes the sorted contents of either a list or dict to file.
Chris Grossfabf50a2019-05-02 12:42:09 -0700231
Tao Bao2ad4b822019-06-27 16:52:12 -0700232 This function sorts the contents of the list or dict and then writes the
233 resulting sorted contents to a file specified by path.
Chris Grossfabf50a2019-05-02 12:42:09 -0700234
235 Args:
236 data: The list or dict to sort and write.
237 path: Path to the file to write the sorted values to. The file at path will
238 be overridden if it exists.
239 """
240 with open(path, 'w') as output:
Daniel Normand5d70ea2019-06-05 15:13:43 -0700241 for entry in sorted(data):
Chris Grossfabf50a2019-05-02 12:42:09 -0700242 out_str = '{}={}\n'.format(entry, data[entry]) if isinstance(
243 data, dict) else '{}\n'.format(entry)
244 output.write(out_str)
245
246
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800247def extract_items(target_files, target_files_temp_dir, extract_item_list):
Tao Bao2ad4b822019-06-27 16:52:12 -0700248 """Extracts items from target files to temporary directory.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800249
250 This function extracts from the specified target files zip archive into the
251 specified temporary directory, the items specified in the extract item list.
252
253 Args:
254 target_files: The target files zip archive from which to extract items.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800255 target_files_temp_dir: The temporary directory where the extracted items
Daniel Normane5b134a2019-04-17 14:54:06 -0700256 will land.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800257 extract_item_list: A list of items to extract.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800258 """
259
260 logger.info('extracting from %s', target_files)
261
262 # Filter the extract_item_list to remove any items that do not exist in the
263 # zip file. Otherwise, the extraction step will fail.
264
Daniel Norman4cc9df62019-07-18 10:11:07 -0700265 with zipfile.ZipFile(target_files, allowZip64=True) as target_files_zipfile:
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800266 target_files_namelist = target_files_zipfile.namelist()
267
268 filtered_extract_item_list = []
269 for pattern in extract_item_list:
270 matching_namelist = fnmatch.filter(target_files_namelist, pattern)
271 if not matching_namelist:
272 logger.warning('no match for %s', pattern)
273 else:
274 filtered_extract_item_list.append(pattern)
275
Bill Peckham8ff3fbd2019-02-22 10:57:43 -0800276 # Extract from target_files into target_files_temp_dir the
277 # filtered_extract_item_list.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800278
Daniel Normane5b134a2019-04-17 14:54:06 -0700279 common.UnzipToDir(target_files, target_files_temp_dir,
280 filtered_extract_item_list)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800281
282
Daniel Normanfdb38812019-04-15 09:47:24 -0700283def copy_items(from_dir, to_dir, patterns):
284 """Similar to extract_items() except uses an input dir instead of zip."""
285 file_paths = []
286 for dirpath, _, filenames in os.walk(from_dir):
Daniel Normane5b134a2019-04-17 14:54:06 -0700287 file_paths.extend(
288 os.path.relpath(path=os.path.join(dirpath, filename), start=from_dir)
289 for filename in filenames)
Daniel Normanfdb38812019-04-15 09:47:24 -0700290
291 filtered_file_paths = set()
292 for pattern in patterns:
293 filtered_file_paths.update(fnmatch.filter(file_paths, pattern))
294
295 for file_path in filtered_file_paths:
296 original_file_path = os.path.join(from_dir, file_path)
297 copied_file_path = os.path.join(to_dir, file_path)
298 copied_file_dir = os.path.dirname(copied_file_path)
299 if not os.path.exists(copied_file_dir):
300 os.makedirs(copied_file_dir)
301 if os.path.islink(original_file_path):
302 os.symlink(os.readlink(original_file_path), copied_file_path)
303 else:
304 shutil.copyfile(original_file_path, copied_file_path)
305
306
Daniel Normand5d70ea2019-06-05 15:13:43 -0700307def validate_config_lists(framework_item_list, framework_misc_info_keys,
308 vendor_item_list):
Daniel Normane5964522019-03-19 10:32:03 -0700309 """Performs validations on the merge config lists.
310
311 Args:
Daniel Normand5d70ea2019-06-05 15:13:43 -0700312 framework_item_list: The list of items to extract from the partial framework
Daniel Normane5b134a2019-04-17 14:54:06 -0700313 target files package as is.
Daniel Normand5d70ea2019-06-05 15:13:43 -0700314 framework_misc_info_keys: A list of keys to obtain from the framework
Daniel Normandbbf5a32020-10-22 16:03:32 -0700315 instance of META/misc_info.txt. The remaining keys should come from the
316 vendor instance.
Daniel Normand5d70ea2019-06-05 15:13:43 -0700317 vendor_item_list: The list of items to extract from the partial vendor
318 target files package as is.
Daniel Normane5964522019-03-19 10:32:03 -0700319
320 Returns:
321 False if a validation fails, otherwise true.
322 """
Daniel Normanedf12472019-05-22 10:47:08 -0700323 has_error = False
324
Daniel Normand5d70ea2019-06-05 15:13:43 -0700325 default_combined_item_set = set(DEFAULT_FRAMEWORK_ITEM_LIST)
326 default_combined_item_set.update(DEFAULT_VENDOR_ITEM_LIST)
Daniel Normane5964522019-03-19 10:32:03 -0700327
Daniel Normand5d70ea2019-06-05 15:13:43 -0700328 combined_item_set = set(framework_item_list)
329 combined_item_set.update(vendor_item_list)
Daniel Normane5964522019-03-19 10:32:03 -0700330
331 # Check that the merge config lists are not missing any item specified
332 # by the default config lists.
333 difference = default_combined_item_set.difference(combined_item_set)
334 if difference:
Daniel Normane5b134a2019-04-17 14:54:06 -0700335 logger.error('Missing merge config items: %s', list(difference))
Daniel Normane5964522019-03-19 10:32:03 -0700336 logger.error('Please ensure missing items are in either the '
Daniel Normand5d70ea2019-06-05 15:13:43 -0700337 'framework-item-list or vendor-item-list files provided to '
Daniel Normane5964522019-03-19 10:32:03 -0700338 'this script.')
Daniel Normanedf12472019-05-22 10:47:08 -0700339 has_error = True
340
Daniel Normandbbf5a32020-10-22 16:03:32 -0700341 # Check that partitions only come from one input.
Daniel Normanedf12472019-05-22 10:47:08 -0700342 for partition in SINGLE_BUILD_PARTITIONS:
Daniel Normandbbf5a32020-10-22 16:03:32 -0700343 image_path = 'IMAGES/{}.img'.format(partition.lower().replace('/', ''))
344 in_framework = (
345 any(item.startswith(partition) for item in framework_item_list) or
346 image_path in framework_item_list)
347 in_vendor = (
348 any(item.startswith(partition) for item in vendor_item_list) or
349 image_path in vendor_item_list)
Daniel Normand5d70ea2019-06-05 15:13:43 -0700350 if in_framework and in_vendor:
Daniel Normanedf12472019-05-22 10:47:08 -0700351 logger.error(
Tao Bao2ad4b822019-06-27 16:52:12 -0700352 'Cannot extract items from %s for both the framework and vendor'
Kiyoung Kimebe7c9c2019-06-25 17:09:55 +0900353 ' builds. Please ensure only one merge config item list'
Tao Bao2ad4b822019-06-27 16:52:12 -0700354 ' includes %s.', partition, partition)
Daniel Normanedf12472019-05-22 10:47:08 -0700355 has_error = True
Daniel Normane5964522019-03-19 10:32:03 -0700356
Daniel Normand5d70ea2019-06-05 15:13:43 -0700357 if ('dynamic_partition_list' in framework_misc_info_keys) or (
358 'super_partition_groups' in framework_misc_info_keys):
Daniel Norman19b9fe92019-03-19 14:48:02 -0700359 logger.error('Dynamic partition misc info keys should come from '
Daniel Normand5d70ea2019-06-05 15:13:43 -0700360 'the vendor instance of META/misc_info.txt.')
Daniel Normanedf12472019-05-22 10:47:08 -0700361 has_error = True
Daniel Norman19b9fe92019-03-19 14:48:02 -0700362
Daniel Normanedf12472019-05-22 10:47:08 -0700363 return not has_error
Daniel Normane5964522019-03-19 10:32:03 -0700364
365
Daniel Normand5d70ea2019-06-05 15:13:43 -0700366def process_ab_partitions_txt(framework_target_files_temp_dir,
367 vendor_target_files_temp_dir,
Daniel Normane5b134a2019-04-17 14:54:06 -0700368 output_target_files_temp_dir):
Tao Bao2ad4b822019-06-27 16:52:12 -0700369 """Performs special processing for META/ab_partitions.txt.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800370
Tao Bao2ad4b822019-06-27 16:52:12 -0700371 This function merges the contents of the META/ab_partitions.txt files from the
372 framework directory and the vendor directory, placing the merged result in the
373 output directory. The precondition in that the files are already extracted.
374 The post condition is that the output META/ab_partitions.txt contains the
Daniel Normandbbf5a32020-10-22 16:03:32 -0700375 merged content. The format for each ab_partitions.txt is one partition name
376 per line. The output file contains the union of the partition names.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800377
378 Args:
Daniel Normand5d70ea2019-06-05 15:13:43 -0700379 framework_target_files_temp_dir: The name of a directory containing the
380 special items extracted from the framework target files package.
381 vendor_target_files_temp_dir: The name of a directory containing the special
382 items extracted from the vendor target files package.
Daniel Normane5b134a2019-04-17 14:54:06 -0700383 output_target_files_temp_dir: The name of a directory that will be used to
384 create the output target files package after all the special cases are
385 processed.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800386 """
387
Daniel Normand5d70ea2019-06-05 15:13:43 -0700388 framework_ab_partitions_txt = os.path.join(framework_target_files_temp_dir,
389 'META', 'ab_partitions.txt')
390
391 vendor_ab_partitions_txt = os.path.join(vendor_target_files_temp_dir, 'META',
Daniel Normane5b134a2019-04-17 14:54:06 -0700392 'ab_partitions.txt')
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800393
Daniel Normand5d70ea2019-06-05 15:13:43 -0700394 with open(framework_ab_partitions_txt) as f:
395 framework_ab_partitions = f.read().splitlines()
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800396
Daniel Normand5d70ea2019-06-05 15:13:43 -0700397 with open(vendor_ab_partitions_txt) as f:
398 vendor_ab_partitions = f.read().splitlines()
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800399
Daniel Normand5d70ea2019-06-05 15:13:43 -0700400 output_ab_partitions = set(framework_ab_partitions + vendor_ab_partitions)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800401
Daniel Normane5b134a2019-04-17 14:54:06 -0700402 output_ab_partitions_txt = os.path.join(output_target_files_temp_dir, 'META',
403 'ab_partitions.txt')
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800404
Chris Grossfabf50a2019-05-02 12:42:09 -0700405 write_sorted_data(data=output_ab_partitions, path=output_ab_partitions_txt)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800406
407
Daniel Normand5d70ea2019-06-05 15:13:43 -0700408def process_misc_info_txt(framework_target_files_temp_dir,
409 vendor_target_files_temp_dir,
410 output_target_files_temp_dir,
411 framework_misc_info_keys):
Tao Bao2ad4b822019-06-27 16:52:12 -0700412 """Performs special processing for META/misc_info.txt.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800413
414 This function merges the contents of the META/misc_info.txt files from the
Daniel Normand5d70ea2019-06-05 15:13:43 -0700415 framework directory and the vendor directory, placing the merged result in the
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800416 output directory. The precondition in that the files are already extracted.
417 The post condition is that the output META/misc_info.txt contains the merged
418 content.
419
420 Args:
Daniel Normand5d70ea2019-06-05 15:13:43 -0700421 framework_target_files_temp_dir: The name of a directory containing the
422 special items extracted from the framework target files package.
423 vendor_target_files_temp_dir: The name of a directory containing the special
424 items extracted from the vendor target files package.
Daniel Normane5b134a2019-04-17 14:54:06 -0700425 output_target_files_temp_dir: The name of a directory that will be used to
426 create the output target files package after all the special cases are
427 processed.
Daniel Normand5d70ea2019-06-05 15:13:43 -0700428 framework_misc_info_keys: A list of keys to obtain from the framework
Daniel Normandbbf5a32020-10-22 16:03:32 -0700429 instance of META/misc_info.txt. The remaining keys should come from the
430 vendor instance.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800431 """
432
Kiyoung Kimebe7c9c2019-06-25 17:09:55 +0900433 misc_info_path = ['META', 'misc_info.txt']
434 framework_dict = common.LoadDictionaryFromFile(
435 os.path.join(framework_target_files_temp_dir, *misc_info_path))
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800436
Daniel Normand5d70ea2019-06-05 15:13:43 -0700437 # We take most of the misc info from the vendor target files.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800438
Kiyoung Kimebe7c9c2019-06-25 17:09:55 +0900439 merged_dict = common.LoadDictionaryFromFile(
440 os.path.join(vendor_target_files_temp_dir, *misc_info_path))
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800441
Daniel Normand5d70ea2019-06-05 15:13:43 -0700442 # Replace certain values in merged_dict with values from
443 # framework_dict.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800444
Daniel Normand5d70ea2019-06-05 15:13:43 -0700445 for key in framework_misc_info_keys:
446 merged_dict[key] = framework_dict[key]
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800447
Daniel Norman19b9fe92019-03-19 14:48:02 -0700448 # Merge misc info keys used for Dynamic Partitions.
Daniel Normand5d70ea2019-06-05 15:13:43 -0700449 if (merged_dict.get('use_dynamic_partitions') == 'true') and (
450 framework_dict.get('use_dynamic_partitions') == 'true'):
Daniel Normanbfc51ef2019-07-24 14:34:54 -0700451 merged_dynamic_partitions_dict = common.MergeDynamicPartitionInfoDicts(
Daniel Norman55417142019-11-25 16:04:36 -0800452 framework_dict=framework_dict, vendor_dict=merged_dict)
Daniel Normand5d70ea2019-06-05 15:13:43 -0700453 merged_dict.update(merged_dynamic_partitions_dict)
Tao Bao48a2feb2019-06-28 11:00:05 -0700454 # Ensure that add_img_to_target_files rebuilds super split images for
455 # devices that retrofit dynamic partitions. This flag may have been set to
456 # false in the partial builds to prevent duplicate building of super.img.
Daniel Norman0bf940c2019-06-10 12:50:19 -0700457 merged_dict['build_super_partition'] = 'true'
Daniel Norman19b9fe92019-03-19 14:48:02 -0700458
Daniel Norman38888d32020-11-19 14:51:15 -0800459 # If AVB is enabled then ensure that we build vbmeta.img.
460 # Partial builds with AVB enabled may set PRODUCT_BUILD_VBMETA_IMAGE=false to
461 # skip building an incomplete vbmeta.img.
462 if merged_dict.get('avb_enable') == 'true':
463 merged_dict['avb_building_vbmeta_image'] = 'true'
464
Daniel Normand5d70ea2019-06-05 15:13:43 -0700465 # Replace <image>_selinux_fc values with framework or vendor file_contexts.bin
Daniel Norman72c626f2019-05-13 15:58:14 -0700466 # depending on which dictionary the key came from.
467 # Only the file basename is required because all selinux_fc properties are
468 # replaced with the full path to the file under META/ when misc_info.txt is
469 # loaded from target files for repacking. See common.py LoadInfoDict().
Daniel Normand5d70ea2019-06-05 15:13:43 -0700470 for key in merged_dict:
Daniel Norman72c626f2019-05-13 15:58:14 -0700471 if key.endswith('_selinux_fc'):
Daniel Normand5d70ea2019-06-05 15:13:43 -0700472 merged_dict[key] = 'vendor_file_contexts.bin'
473 for key in framework_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] = 'framework_file_contexts.bin'
Daniel Norman72c626f2019-05-13 15:58:14 -0700476
Daniel Normane5b134a2019-04-17 14:54:06 -0700477 output_misc_info_txt = os.path.join(output_target_files_temp_dir, 'META',
478 'misc_info.txt')
Daniel Normand5d70ea2019-06-05 15:13:43 -0700479 write_sorted_data(data=merged_dict, path=output_misc_info_txt)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800480
481
Daniel Normand5d70ea2019-06-05 15:13:43 -0700482def process_dynamic_partitions_info_txt(framework_target_files_dir,
483 vendor_target_files_dir,
Daniel Normana61cde02019-05-03 14:19:13 -0700484 output_target_files_dir):
Tao Bao2ad4b822019-06-27 16:52:12 -0700485 """Performs special processing for META/dynamic_partitions_info.txt.
Daniel Normana61cde02019-05-03 14:19:13 -0700486
487 This function merges the contents of the META/dynamic_partitions_info.txt
Daniel Normand5d70ea2019-06-05 15:13:43 -0700488 files from the framework directory and the vendor directory, placing the
489 merged result in the output directory.
Daniel Normana61cde02019-05-03 14:19:13 -0700490
Daniel Normand5d70ea2019-06-05 15:13:43 -0700491 This function does nothing if META/dynamic_partitions_info.txt from the vendor
Daniel Normana61cde02019-05-03 14:19:13 -0700492 directory does not exist.
493
494 Args:
Daniel Normand5d70ea2019-06-05 15:13:43 -0700495 framework_target_files_dir: The name of a directory containing the special
496 items extracted from the framework target files package.
497 vendor_target_files_dir: The name of a directory containing the special
498 items extracted from the vendor target files package.
Daniel Normana61cde02019-05-03 14:19:13 -0700499 output_target_files_dir: The name of a directory that will be used to create
500 the output target files package after all the special cases are processed.
501 """
502
503 if not os.path.exists(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700504 os.path.join(vendor_target_files_dir, 'META',
Daniel Normana61cde02019-05-03 14:19:13 -0700505 'dynamic_partitions_info.txt')):
506 return
507
Kiyoung Kimebe7c9c2019-06-25 17:09:55 +0900508 dynamic_partitions_info_path = ['META', 'dynamic_partitions_info.txt']
Daniel Normana61cde02019-05-03 14:19:13 -0700509
Kiyoung Kimebe7c9c2019-06-25 17:09:55 +0900510 framework_dynamic_partitions_dict = common.LoadDictionaryFromFile(
511 os.path.join(framework_target_files_dir, *dynamic_partitions_info_path))
512 vendor_dynamic_partitions_dict = common.LoadDictionaryFromFile(
513 os.path.join(vendor_target_files_dir, *dynamic_partitions_info_path))
Daniel Normana61cde02019-05-03 14:19:13 -0700514
Daniel Normanbfc51ef2019-07-24 14:34:54 -0700515 merged_dynamic_partitions_dict = common.MergeDynamicPartitionInfoDicts(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700516 framework_dict=framework_dynamic_partitions_dict,
Daniel Norman55417142019-11-25 16:04:36 -0800517 vendor_dict=vendor_dynamic_partitions_dict)
Daniel Normana61cde02019-05-03 14:19:13 -0700518
519 output_dynamic_partitions_info_txt = os.path.join(
520 output_target_files_dir, 'META', 'dynamic_partitions_info.txt')
Chris Grossfabf50a2019-05-02 12:42:09 -0700521 write_sorted_data(
522 data=merged_dynamic_partitions_dict,
523 path=output_dynamic_partitions_info_txt)
524
525
Bill Peckham19c3feb2020-03-20 18:31:43 -0700526def item_list_to_partition_set(item_list):
527 """Converts a target files item list to a partition set.
528
529 The item list contains items that might look like 'SYSTEM/*' or 'VENDOR/*' or
530 'OTA/android-info.txt'. Items that end in '/*' are assumed to match entire
531 directories where 'SYSTEM' or 'VENDOR' is a directory name that identifies the
532 contents of a partition of the same name. Other items in the list, such as the
533 'OTA' example contain metadata. This function iterates such a list, returning
534 a set that contains the partition entries.
535
536 Args:
537 item_list: A list of items in a target files package.
Daniel Normanb0c75912020-09-24 14:30:21 -0700538
Bill Peckham19c3feb2020-03-20 18:31:43 -0700539 Returns:
540 A set of partitions extracted from the list of items.
541 """
542
543 partition_set = set()
544
545 for item in item_list:
546 match = PARTITION_ITEM_PATTERN.search(item.strip())
547 partition_tag = match.group(1).lower() if match else None
548
549 if partition_tag:
550 partition_set.add(partition_tag)
551
552 return partition_set
553
554
Daniel Normand5d70ea2019-06-05 15:13:43 -0700555def process_apex_keys_apk_certs_common(framework_target_files_dir,
556 vendor_target_files_dir,
Bill Peckham19c3feb2020-03-20 18:31:43 -0700557 output_target_files_dir,
558 framework_partition_set,
559 vendor_partition_set, file_name):
Tao Bao2ad4b822019-06-27 16:52:12 -0700560 """Performs special processing for META/apexkeys.txt or META/apkcerts.txt.
Chris Grossfabf50a2019-05-02 12:42:09 -0700561
562 This function merges the contents of the META/apexkeys.txt or
Tao Bao2ad4b822019-06-27 16:52:12 -0700563 META/apkcerts.txt files from the framework directory and the vendor directory,
564 placing the merged result in the output directory. The precondition in that
565 the files are already extracted. The post condition is that the output
566 META/apexkeys.txt or META/apkcerts.txt contains the merged content.
Chris Grossfabf50a2019-05-02 12:42:09 -0700567
568 Args:
Daniel Normand5d70ea2019-06-05 15:13:43 -0700569 framework_target_files_dir: The name of a directory containing the special
570 items extracted from the framework target files package.
571 vendor_target_files_dir: The name of a directory containing the special
572 items extracted from the vendor target files package.
Chris Grossfabf50a2019-05-02 12:42:09 -0700573 output_target_files_dir: The name of a directory that will be used to create
574 the output target files package after all the special cases are processed.
Bill Peckham19c3feb2020-03-20 18:31:43 -0700575 framework_partition_set: Partitions that are considered framework
576 partitions. Used to filter apexkeys.txt and apkcerts.txt.
577 vendor_partition_set: Partitions that are considered vendor partitions. Used
578 to filter apexkeys.txt and apkcerts.txt.
Chris Grossfabf50a2019-05-02 12:42:09 -0700579 file_name: The name of the file to merge. One of apkcerts.txt or
580 apexkeys.txt.
581 """
582
583 def read_helper(d):
584 temp = {}
585 file_path = os.path.join(d, 'META', file_name)
586 with open(file_path) as f:
587 for line in f:
588 if line.strip():
Bill Peckham19c3feb2020-03-20 18:31:43 -0700589 name = line.split()[0]
590 match = MODULE_KEY_PATTERN.search(name)
591 temp[match.group(1)] = line.strip()
Chris Grossfabf50a2019-05-02 12:42:09 -0700592 return temp
593
Daniel Normand5d70ea2019-06-05 15:13:43 -0700594 framework_dict = read_helper(framework_target_files_dir)
595 vendor_dict = read_helper(vendor_target_files_dir)
Bill Peckham19c3feb2020-03-20 18:31:43 -0700596 merged_dict = {}
Chris Grossfabf50a2019-05-02 12:42:09 -0700597
Bill Peckham19c3feb2020-03-20 18:31:43 -0700598 def filter_into_merged_dict(item_dict, partition_set):
599 for key, value in item_dict.items():
600 match = PARTITION_TAG_PATTERN.search(value)
601
602 if match is None:
603 raise ValueError('Entry missing partition tag: %s' % value)
604
605 partition_tag = match.group(1)
606
607 if partition_tag in partition_set:
608 if key in merged_dict:
Daniel Normanb0c75912020-09-24 14:30:21 -0700609 if OPTIONS.allow_duplicate_apkapex_keys:
610 # TODO(b/150582573) Always raise on duplicates.
611 logger.warning('Duplicate key %s' % key)
612 continue
613 else:
614 raise ValueError('Duplicate key %s' % key)
Bill Peckham19c3feb2020-03-20 18:31:43 -0700615
616 merged_dict[key] = value
617
618 filter_into_merged_dict(framework_dict, framework_partition_set)
619 filter_into_merged_dict(vendor_dict, vendor_partition_set)
Chris Grossfabf50a2019-05-02 12:42:09 -0700620
621 output_file = os.path.join(output_target_files_dir, 'META', file_name)
622
Bill Peckham19c3feb2020-03-20 18:31:43 -0700623 # The following code is similar to write_sorted_data, but different enough
624 # that we couldn't use that function. We need the output to be sorted by the
625 # basename of the apex/apk (without the ".apex" or ".apk" suffix). This
626 # allows the sort to be consistent with the framework/vendor input data and
627 # eases comparison of input data with merged data.
628 with open(output_file, 'w') as output:
629 for key in sorted(merged_dict.keys()):
630 out_str = merged_dict[key] + '\n'
631 output.write(out_str)
Daniel Normana61cde02019-05-03 14:19:13 -0700632
633
Daniel Normand5d70ea2019-06-05 15:13:43 -0700634def copy_file_contexts(framework_target_files_dir, vendor_target_files_dir,
Daniel Norman72c626f2019-05-13 15:58:14 -0700635 output_target_files_dir):
636 """Creates named copies of each build's file_contexts.bin in output META/."""
Daniel Normand5d70ea2019-06-05 15:13:43 -0700637 framework_fc_path = os.path.join(framework_target_files_dir, 'META',
638 'framework_file_contexts.bin')
639 if not os.path.exists(framework_fc_path):
640 framework_fc_path = os.path.join(framework_target_files_dir, 'META',
641 'file_contexts.bin')
642 if not os.path.exists(framework_fc_path):
643 raise ValueError('Missing framework file_contexts.bin.')
644 shutil.copyfile(
645 framework_fc_path,
646 os.path.join(output_target_files_dir, 'META',
647 'framework_file_contexts.bin'))
648
649 vendor_fc_path = os.path.join(vendor_target_files_dir, 'META',
650 'vendor_file_contexts.bin')
651 if not os.path.exists(vendor_fc_path):
652 vendor_fc_path = os.path.join(vendor_target_files_dir, 'META',
Daniel Normanedf12472019-05-22 10:47:08 -0700653 'file_contexts.bin')
Daniel Normand5d70ea2019-06-05 15:13:43 -0700654 if not os.path.exists(vendor_fc_path):
655 raise ValueError('Missing vendor file_contexts.bin.')
Daniel Norman72c626f2019-05-13 15:58:14 -0700656 shutil.copyfile(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700657 vendor_fc_path,
658 os.path.join(output_target_files_dir, 'META', 'vendor_file_contexts.bin'))
Daniel Norman72c626f2019-05-13 15:58:14 -0700659
660
Daniel Normand5d70ea2019-06-05 15:13:43 -0700661def process_special_cases(framework_target_files_temp_dir,
662 vendor_target_files_temp_dir,
663 output_target_files_temp_dir,
Daniel Normanb0c75912020-09-24 14:30:21 -0700664 framework_misc_info_keys, framework_partition_set,
Bill Peckham19c3feb2020-03-20 18:31:43 -0700665 vendor_partition_set):
Tao Bao2ad4b822019-06-27 16:52:12 -0700666 """Performs special-case processing for certain target files items.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800667
668 Certain files in the output target files package require special-case
669 processing. This function performs all that special-case processing.
670
671 Args:
Daniel Normand5d70ea2019-06-05 15:13:43 -0700672 framework_target_files_temp_dir: The name of a directory containing the
673 special items extracted from the framework target files package.
674 vendor_target_files_temp_dir: The name of a directory containing the special
675 items extracted from the vendor target files package.
Daniel Normane5b134a2019-04-17 14:54:06 -0700676 output_target_files_temp_dir: The name of a directory that will be used to
677 create the output target files package after all the special cases are
678 processed.
Daniel Normand5d70ea2019-06-05 15:13:43 -0700679 framework_misc_info_keys: A list of keys to obtain from the framework
Daniel Normandbbf5a32020-10-22 16:03:32 -0700680 instance of META/misc_info.txt. The remaining keys should come from the
681 vendor instance.
Bill Peckham19c3feb2020-03-20 18:31:43 -0700682 framework_partition_set: Partitions that are considered framework
683 partitions. Used to filter apexkeys.txt and apkcerts.txt.
684 vendor_partition_set: Partitions that are considered vendor partitions. Used
685 to filter apexkeys.txt and apkcerts.txt.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800686 """
687
Daniel Normand5d70ea2019-06-05 15:13:43 -0700688 if 'ab_update' in framework_misc_info_keys:
Bill Peckham364c1cc2019-03-29 18:27:23 -0700689 process_ab_partitions_txt(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700690 framework_target_files_temp_dir=framework_target_files_temp_dir,
691 vendor_target_files_temp_dir=vendor_target_files_temp_dir,
Bill Peckham364c1cc2019-03-29 18:27:23 -0700692 output_target_files_temp_dir=output_target_files_temp_dir)
693
Daniel Norman72c626f2019-05-13 15:58:14 -0700694 copy_file_contexts(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700695 framework_target_files_dir=framework_target_files_temp_dir,
696 vendor_target_files_dir=vendor_target_files_temp_dir,
Daniel Norman72c626f2019-05-13 15:58:14 -0700697 output_target_files_dir=output_target_files_temp_dir)
698
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800699 process_misc_info_txt(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700700 framework_target_files_temp_dir=framework_target_files_temp_dir,
701 vendor_target_files_temp_dir=vendor_target_files_temp_dir,
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800702 output_target_files_temp_dir=output_target_files_temp_dir,
Daniel Normand5d70ea2019-06-05 15:13:43 -0700703 framework_misc_info_keys=framework_misc_info_keys)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800704
Daniel Normana61cde02019-05-03 14:19:13 -0700705 process_dynamic_partitions_info_txt(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700706 framework_target_files_dir=framework_target_files_temp_dir,
707 vendor_target_files_dir=vendor_target_files_temp_dir,
Daniel Norman714bd122019-05-08 16:20:02 -0700708 output_target_files_dir=output_target_files_temp_dir)
Daniel Normana61cde02019-05-03 14:19:13 -0700709
Chris Grossfabf50a2019-05-02 12:42:09 -0700710 process_apex_keys_apk_certs_common(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700711 framework_target_files_dir=framework_target_files_temp_dir,
712 vendor_target_files_dir=vendor_target_files_temp_dir,
Chris Grossfabf50a2019-05-02 12:42:09 -0700713 output_target_files_dir=output_target_files_temp_dir,
Bill Peckham19c3feb2020-03-20 18:31:43 -0700714 framework_partition_set=framework_partition_set,
715 vendor_partition_set=vendor_partition_set,
Chris Grossfabf50a2019-05-02 12:42:09 -0700716 file_name='apkcerts.txt')
717
718 process_apex_keys_apk_certs_common(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700719 framework_target_files_dir=framework_target_files_temp_dir,
720 vendor_target_files_dir=vendor_target_files_temp_dir,
Chris Grossfabf50a2019-05-02 12:42:09 -0700721 output_target_files_dir=output_target_files_temp_dir,
Bill Peckham19c3feb2020-03-20 18:31:43 -0700722 framework_partition_set=framework_partition_set,
723 vendor_partition_set=vendor_partition_set,
Chris Grossfabf50a2019-05-02 12:42:09 -0700724 file_name='apexkeys.txt')
725
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800726
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900727def create_merged_package(temp_dir, framework_target_files, framework_item_list,
728 vendor_target_files, vendor_item_list,
Daniel Norman4cc9df62019-07-18 10:11:07 -0700729 framework_misc_info_keys, rebuild_recovery):
Tao Bao2ad4b822019-06-27 16:52:12 -0700730 """Merges two target files packages into one target files structure.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800731
732 Args:
733 temp_dir: The name of a directory we use when we extract items from the
Daniel Normane5b134a2019-04-17 14:54:06 -0700734 input target files packages, and also a scratch directory that we use for
735 temporary files.
Daniel Normand5d70ea2019-06-05 15:13:43 -0700736 framework_target_files: The name of the zip archive containing the framework
Daniel Normane5b134a2019-04-17 14:54:06 -0700737 partial target files package.
Daniel Normand5d70ea2019-06-05 15:13:43 -0700738 framework_item_list: The list of items to extract from the partial framework
Daniel Normane5b134a2019-04-17 14:54:06 -0700739 target files package as is, meaning these items will land in the output
Daniel Normand5d70ea2019-06-05 15:13:43 -0700740 target files package exactly as they appear in the input partial framework
Daniel Normane5b134a2019-04-17 14:54:06 -0700741 target files package.
Daniel Normand5d70ea2019-06-05 15:13:43 -0700742 vendor_target_files: The name of the zip archive containing the vendor
743 partial target files package.
744 vendor_item_list: The list of items to extract from the partial vendor
745 target files package as is, meaning these items will land in the output
746 target files package exactly as they appear in the input partial vendor
Daniel Normane5b134a2019-04-17 14:54:06 -0700747 target files package.
Daniel Normandbbf5a32020-10-22 16:03:32 -0700748 framework_misc_info_keys: A list of keys to obtain from the framework
749 instance of META/misc_info.txt. The remaining keys should come from the
750 vendor instance.
Daniel Normana4911da2019-03-15 14:36:21 -0700751 rebuild_recovery: If true, rebuild the recovery patch used by non-A/B
Daniel Normane5b134a2019-04-17 14:54:06 -0700752 devices and write it to the system image.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800753
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900754 Returns:
755 Path to merged package under temp directory.
756 """
Daniel Normandbbf5a32020-10-22 16:03:32 -0700757 # Extract "as is" items from the input framework and vendor partial target
758 # files packages directly into the output temporary directory, since these items
759 # do not need special case processing.
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800760
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800761 output_target_files_temp_dir = os.path.join(temp_dir, 'output')
Bill Peckham889b0c62019-02-21 18:53:37 -0800762 extract_items(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700763 target_files=framework_target_files,
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800764 target_files_temp_dir=output_target_files_temp_dir,
Daniel Normand5d70ea2019-06-05 15:13:43 -0700765 extract_item_list=framework_item_list)
Bill Peckham889b0c62019-02-21 18:53:37 -0800766 extract_items(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700767 target_files=vendor_target_files,
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800768 target_files_temp_dir=output_target_files_temp_dir,
Daniel Normand5d70ea2019-06-05 15:13:43 -0700769 extract_item_list=vendor_item_list)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800770
Daniel Normandbbf5a32020-10-22 16:03:32 -0700771 # Perform special case processing on META/* items.
772 # After this function completes successfully, all the files we need to create
773 # the output target files package are in place.
774 framework_target_files_temp_dir = os.path.join(temp_dir, 'framework')
775 vendor_target_files_temp_dir = os.path.join(temp_dir, 'vendor')
Daniel Normand5d70ea2019-06-05 15:13:43 -0700776 extract_items(
777 target_files=framework_target_files,
778 target_files_temp_dir=framework_target_files_temp_dir,
Daniel Normandbbf5a32020-10-22 16:03:32 -0700779 extract_item_list=('META/*',))
Bill Peckham889b0c62019-02-21 18:53:37 -0800780 extract_items(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700781 target_files=vendor_target_files,
782 target_files_temp_dir=vendor_target_files_temp_dir,
Daniel Normandbbf5a32020-10-22 16:03:32 -0700783 extract_item_list=('META/*',))
Bill Peckham889b0c62019-02-21 18:53:37 -0800784 process_special_cases(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700785 framework_target_files_temp_dir=framework_target_files_temp_dir,
786 vendor_target_files_temp_dir=vendor_target_files_temp_dir,
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800787 output_target_files_temp_dir=output_target_files_temp_dir,
Bill Peckham19c3feb2020-03-20 18:31:43 -0700788 framework_misc_info_keys=framework_misc_info_keys,
789 framework_partition_set=item_list_to_partition_set(framework_item_list),
790 vendor_partition_set=item_list_to_partition_set(vendor_item_list))
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800791
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900792 return output_target_files_temp_dir
793
794
795def generate_images(target_files_dir, rebuild_recovery):
796 """Generate images from target files.
797
798 This function takes merged output temporary directory and create images
799 from it.
800
801 Args:
802 target_files_dir: Path to merged temp directory.
803 rebuild_recovery: If true, rebuild the recovery patch used by non-A/B
804 devices and write it to the system image.
805 """
806
807 # Regenerate IMAGES in the target directory.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800808
Daniel Normandbbf5a32020-10-22 16:03:32 -0700809 add_img_args = [
810 '--verbose',
811 '--add_missing',
812 ]
Bill Peckhame868aec2019-09-17 17:06:47 -0700813 # TODO(b/132730255): Remove this if statement.
Daniel Normana4911da2019-03-15 14:36:21 -0700814 if rebuild_recovery:
815 add_img_args.append('--rebuild_recovery')
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900816 add_img_args.append(target_files_dir)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800817
818 add_img_to_target_files.main(add_img_args)
819
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900820
821def generate_super_empty_image(target_dir, output_super_empty):
Tao Bao2ad4b822019-06-27 16:52:12 -0700822 """Generates super_empty image from target package.
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900823
824 Args:
825 target_dir: Path to the target file package which contains misc_info.txt for
826 detailed information for super image.
827 output_super_empty: If provided, copies a super_empty.img file from the
828 target files package to this path.
829 """
Daniel Norman1bd2a1d2019-04-18 12:32:18 -0700830 # Create super_empty.img using the merged misc_info.txt.
831
Daniel Norman4cc9df62019-07-18 10:11:07 -0700832 misc_info_txt = os.path.join(target_dir, 'META', 'misc_info.txt')
Daniel Norman1bd2a1d2019-04-18 12:32:18 -0700833
Kiyoung Kimebe7c9c2019-06-25 17:09:55 +0900834 use_dynamic_partitions = common.LoadDictionaryFromFile(misc_info_txt).get(
835 'use_dynamic_partitions')
Daniel Norman1bd2a1d2019-04-18 12:32:18 -0700836
837 if use_dynamic_partitions != 'true' and output_super_empty:
838 raise ValueError(
839 'Building super_empty.img requires use_dynamic_partitions=true.')
840 elif use_dynamic_partitions == 'true':
Daniel Norman4cc9df62019-07-18 10:11:07 -0700841 super_empty_img = os.path.join(target_dir, 'IMAGES', 'super_empty.img')
Daniel Norman1bd2a1d2019-04-18 12:32:18 -0700842 build_super_image_args = [
843 misc_info_txt,
844 super_empty_img,
845 ]
846 build_super_image.main(build_super_image_args)
847
848 # Copy super_empty.img to the user-provided output_super_empty location.
849 if output_super_empty:
850 shutil.copyfile(super_empty_img, output_super_empty)
851
Daniel Normanb8a2f9d2019-04-24 12:55:51 -0700852
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900853def create_target_files_archive(output_file, source_dir, temp_dir):
Tao Bao2ad4b822019-06-27 16:52:12 -0700854 """Creates archive from target package.
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900855
856 Args:
857 output_file: The name of the zip archive target files package.
858 source_dir: The target directory contains package to be archived.
859 temp_dir: Path to temporary directory for any intermediate files.
860 """
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800861 output_target_files_list = os.path.join(temp_dir, 'output.list')
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900862 output_zip = os.path.abspath(output_file)
Daniel Norman4cc9df62019-07-18 10:11:07 -0700863 output_target_files_meta_dir = os.path.join(source_dir, 'META')
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800864
Daniel Normandbbf5a32020-10-22 16:03:32 -0700865 def files_from_path(target_path, extra_args=None):
866 """Gets files under the given path and return a sorted list."""
867 find_command = ['find', target_path] + (extra_args or [])
868 find_process = common.Run(
869 find_command, stdout=subprocess.PIPE, verbose=False)
870 return common.RunAndCheckOutput(['sort'],
871 stdin=find_process.stdout,
872 verbose=False)
873
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900874 meta_content = files_from_path(output_target_files_meta_dir)
Daniel Norman4cc9df62019-07-18 10:11:07 -0700875 other_content = files_from_path(
876 source_dir,
877 ['-path', output_target_files_meta_dir, '-prune', '-o', '-print'])
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800878
Tao Bao2ad4b822019-06-27 16:52:12 -0700879 with open(output_target_files_list, 'w') as f:
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800880 f.write(meta_content)
881 f.write(other_content)
882
883 command = [
Bill Peckhamf753e152019-02-19 18:02:46 -0800884 'soong_zip',
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800885 '-d',
Daniel Normane5b134a2019-04-17 14:54:06 -0700886 '-o',
887 output_zip,
888 '-C',
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900889 source_dir,
Daniel Normane5b134a2019-04-17 14:54:06 -0700890 '-l',
891 output_target_files_list,
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800892 ]
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900893
894 logger.info('creating %s', output_file)
Bill Peckham889b0c62019-02-21 18:53:37 -0800895 common.RunAndWait(command, verbose=True)
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900896 logger.info('finished creating %s', output_file)
897
898 return output_zip
899
900
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900901def merge_target_files(temp_dir, framework_target_files, framework_item_list,
902 framework_misc_info_keys, vendor_target_files,
903 vendor_item_list, output_target_files, output_dir,
904 output_item_list, output_ota, output_img,
905 output_super_empty, rebuild_recovery):
Tao Bao2ad4b822019-06-27 16:52:12 -0700906 """Merges two target files packages together.
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900907
908 This function takes framework and vendor target files packages as input,
909 performs various file extractions, special case processing, and finally
910 creates a merged zip archive as output.
911
912 Args:
913 temp_dir: The name of a directory we use when we extract items from the
914 input target files packages, and also a scratch directory that we use for
915 temporary files.
916 framework_target_files: The name of the zip archive containing the framework
917 partial target files package.
918 framework_item_list: The list of items to extract from the partial framework
919 target files package as is, meaning these items will land in the output
920 target files package exactly as they appear in the input partial framework
921 target files package.
Daniel Normandbbf5a32020-10-22 16:03:32 -0700922 framework_misc_info_keys: A list of keys to obtain from the framework
923 instance of META/misc_info.txt. The remaining keys should come from the
924 vendor instance.
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900925 vendor_target_files: The name of the zip archive containing the vendor
926 partial target files package.
927 vendor_item_list: The list of items to extract from the partial vendor
928 target files package as is, meaning these items will land in the output
929 target files package exactly as they appear in the input partial vendor
930 target files package.
931 output_target_files: The name of the output zip archive target files package
932 created by merging framework and vendor.
933 output_dir: The destination directory for saving merged files.
934 output_item_list: The list of items to copy into the output_dir.
935 output_ota: The name of the output zip archive ota package.
936 output_img: The name of the output zip archive img package.
937 output_super_empty: If provided, creates a super_empty.img file from the
938 merged target files package and saves it at this path.
939 rebuild_recovery: If true, rebuild the recovery patch used by non-A/B
940 devices and write it to the system image.
941 """
942
943 logger.info('starting: merge framework %s and vendor %s into output %s',
944 framework_target_files, vendor_target_files, output_target_files)
945
946 output_target_files_temp_dir = create_merged_package(
947 temp_dir, framework_target_files, framework_item_list,
948 vendor_target_files, vendor_item_list, framework_misc_info_keys,
949 rebuild_recovery)
950
Yifan Hongade0d3f2019-08-21 16:37:11 -0700951 if not check_target_files_vintf.CheckVintf(output_target_files_temp_dir):
Daniel Normanb0c75912020-09-24 14:30:21 -0700952 raise RuntimeError('Incompatible VINTF metadata')
Yifan Hongade0d3f2019-08-21 16:37:11 -0700953
Daniel Norman21c34f72020-11-11 17:25:50 -0800954 partition_map = common.PartitionMapFromTargetFiles(
955 output_target_files_temp_dir)
956
Daniel Normand3351562020-10-29 12:33:11 -0700957 # Generate and check for cross-partition violations of sharedUserId
958 # values in APKs. This requires the input target-files packages to contain
959 # *.apk files.
Daniel Normanb8d52a22020-10-26 17:55:00 -0700960 shareduid_violation_modules = os.path.join(
961 output_target_files_temp_dir, 'META', 'shareduid_violation_modules.json')
962 with open(shareduid_violation_modules, 'w') as f:
Daniel Normanb8d52a22020-10-26 17:55:00 -0700963 violation = find_shareduid_violation.FindShareduidViolation(
964 output_target_files_temp_dir, partition_map)
Daniel Normand3351562020-10-29 12:33:11 -0700965
966 # Write the output to a file to enable debugging.
Daniel Normanb8d52a22020-10-26 17:55:00 -0700967 f.write(violation)
Daniel Normand3351562020-10-29 12:33:11 -0700968
969 # Check for violations across the input builds' partition groups.
Daniel Norman21c34f72020-11-11 17:25:50 -0800970 framework_partitions = item_list_to_partition_set(framework_item_list)
971 vendor_partitions = item_list_to_partition_set(vendor_item_list)
Daniel Normand3351562020-10-29 12:33:11 -0700972 shareduid_errors = common.SharedUidPartitionViolations(
973 json.loads(violation), [framework_partitions, vendor_partitions])
974 if shareduid_errors:
975 for error in shareduid_errors:
976 logger.error(error)
977 raise ValueError('sharedUserId APK error. See %s' %
978 shareduid_violation_modules)
Daniel Normanb8d52a22020-10-26 17:55:00 -0700979
Daniel Norman21c34f72020-11-11 17:25:50 -0800980 # Run host_init_verifier on the combined init rc files.
981 filtered_partitions = {
982 partition: path
983 for partition, path in partition_map.items()
984 # host_init_verifier checks only the following partitions:
985 if partition in ['system', 'system_ext', 'product', 'vendor', 'odm']
986 }
987 common.RunHostInitVerifier(
988 product_out=output_target_files_temp_dir,
989 partition_map=filtered_partitions)
990
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900991 generate_images(output_target_files_temp_dir, rebuild_recovery)
992
993 generate_super_empty_image(output_target_files_temp_dir, output_super_empty)
994
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900995 # Finally, create the output target files zip archive and/or copy the
996 # output items to the output target files directory.
997
998 if output_dir:
999 copy_items(output_target_files_temp_dir, output_dir, output_item_list)
1000
1001 if not output_target_files:
1002 return
1003
1004 output_zip = create_target_files_archive(output_target_files,
1005 output_target_files_temp_dir,
1006 temp_dir)
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001007
Daniel Norman74eb74b2019-09-18 14:01:48 -07001008 # Create the IMG package from the merged target files package.
1009
1010 if output_img:
1011 img_from_target_files.main([output_zip, output_img])
1012
Daniel Norman3b64ce12019-04-16 16:11:35 -07001013 # Create the OTA package from the merged target files package.
1014
1015 if output_ota:
Daniel Norman4cc9df62019-07-18 10:11:07 -07001016 ota_from_target_files.main([output_zip, output_ota])
Daniel Norman3b64ce12019-04-16 16:11:35 -07001017
Daniel Norman1bd2a1d2019-04-18 12:32:18 -07001018
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001019def call_func_with_temp_dir(func, keep_tmp):
Tao Bao2ad4b822019-06-27 16:52:12 -07001020 """Manages the creation and cleanup of the temporary directory.
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001021
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001022 This function calls the given function after first creating a temporary
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001023 directory. It also cleans up the temporary directory.
1024
1025 Args:
Daniel Normane5b134a2019-04-17 14:54:06 -07001026 func: The function to call. Should accept one parameter, the path to the
1027 temporary directory.
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001028 keep_tmp: Keep the temporary directory after processing is complete.
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001029 """
1030
1031 # Create a temporary directory. This will serve as the parent of directories
1032 # we use when we extract items from the input target files packages, and also
1033 # a scratch directory that we use for temporary files.
1034
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001035 temp_dir = common.MakeTempDir(prefix='merge_target_files_')
1036
1037 try:
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001038 func(temp_dir)
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001039 finally:
1040 if keep_tmp:
1041 logger.info('keeping %s', temp_dir)
1042 else:
1043 common.Cleanup()
1044
1045
1046def main():
1047 """The main function.
1048
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001049 Process command line arguments, then call merge_target_files to
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001050 perform the heavy lifting.
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001051 """
1052
1053 common.InitLogging()
1054
Bill Peckhamf753e152019-02-19 18:02:46 -08001055 def option_handler(o, a):
1056 if o == '--system-target-files':
Daniel Normand5d70ea2019-06-05 15:13:43 -07001057 logger.warning(
1058 '--system-target-files has been renamed to --framework-target-files')
1059 OPTIONS.framework_target_files = a
1060 elif o == '--framework-target-files':
1061 OPTIONS.framework_target_files = a
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001062 elif o == '--system-item-list':
Daniel Normand5d70ea2019-06-05 15:13:43 -07001063 logger.warning(
1064 '--system-item-list has been renamed to --framework-item-list')
1065 OPTIONS.framework_item_list = a
1066 elif o == '--framework-item-list':
1067 OPTIONS.framework_item_list = a
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001068 elif o == '--system-misc-info-keys':
Daniel Norman4cc9df62019-07-18 10:11:07 -07001069 logger.warning('--system-misc-info-keys has been renamed to '
1070 '--framework-misc-info-keys')
Daniel Normand5d70ea2019-06-05 15:13:43 -07001071 OPTIONS.framework_misc_info_keys = a
1072 elif o == '--framework-misc-info-keys':
1073 OPTIONS.framework_misc_info_keys = a
Bill Peckhamf753e152019-02-19 18:02:46 -08001074 elif o == '--other-target-files':
Daniel Normand5d70ea2019-06-05 15:13:43 -07001075 logger.warning(
1076 '--other-target-files has been renamed to --vendor-target-files')
1077 OPTIONS.vendor_target_files = a
1078 elif o == '--vendor-target-files':
1079 OPTIONS.vendor_target_files = a
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001080 elif o == '--other-item-list':
Daniel Normand5d70ea2019-06-05 15:13:43 -07001081 logger.warning('--other-item-list has been renamed to --vendor-item-list')
1082 OPTIONS.vendor_item_list = a
1083 elif o == '--vendor-item-list':
1084 OPTIONS.vendor_item_list = a
Bill Peckhamf753e152019-02-19 18:02:46 -08001085 elif o == '--output-target-files':
1086 OPTIONS.output_target_files = a
Daniel Normanfdb38812019-04-15 09:47:24 -07001087 elif o == '--output-dir':
1088 OPTIONS.output_dir = a
1089 elif o == '--output-item-list':
1090 OPTIONS.output_item_list = a
Daniel Norman3b64ce12019-04-16 16:11:35 -07001091 elif o == '--output-ota':
1092 OPTIONS.output_ota = a
Daniel Norman1bd2a1d2019-04-18 12:32:18 -07001093 elif o == '--output-img':
1094 OPTIONS.output_img = a
Daniel Normanf0318252019-04-15 11:34:56 -07001095 elif o == '--output-super-empty':
1096 OPTIONS.output_super_empty = a
Daniel Normanb0c75912020-09-24 14:30:21 -07001097 elif o == '--rebuild_recovery': # TODO(b/132730255): Warn
Daniel Normana4911da2019-03-15 14:36:21 -07001098 OPTIONS.rebuild_recovery = True
Daniel Normanb0c75912020-09-24 14:30:21 -07001099 elif o == '--allow-duplicate-apkapex-keys':
1100 OPTIONS.allow_duplicate_apkapex_keys = True
Bill Peckham364c1cc2019-03-29 18:27:23 -07001101 elif o == '--keep-tmp':
Bill Peckhamf753e152019-02-19 18:02:46 -08001102 OPTIONS.keep_tmp = True
1103 else:
1104 return False
1105 return True
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001106
Bill Peckhamf753e152019-02-19 18:02:46 -08001107 args = common.ParseOptions(
Daniel Normane5b134a2019-04-17 14:54:06 -07001108 sys.argv[1:],
1109 __doc__,
Bill Peckhamf753e152019-02-19 18:02:46 -08001110 extra_long_opts=[
1111 'system-target-files=',
Daniel Normand5d70ea2019-06-05 15:13:43 -07001112 'framework-target-files=',
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001113 'system-item-list=',
Daniel Normand5d70ea2019-06-05 15:13:43 -07001114 'framework-item-list=',
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001115 'system-misc-info-keys=',
Daniel Normand5d70ea2019-06-05 15:13:43 -07001116 'framework-misc-info-keys=',
Bill Peckhamf753e152019-02-19 18:02:46 -08001117 'other-target-files=',
Daniel Normand5d70ea2019-06-05 15:13:43 -07001118 'vendor-target-files=',
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001119 'other-item-list=',
Daniel Normand5d70ea2019-06-05 15:13:43 -07001120 'vendor-item-list=',
Bill Peckhamf753e152019-02-19 18:02:46 -08001121 'output-target-files=',
Daniel Normanfdb38812019-04-15 09:47:24 -07001122 'output-dir=',
1123 'output-item-list=',
Daniel Norman3b64ce12019-04-16 16:11:35 -07001124 'output-ota=',
Daniel Norman1bd2a1d2019-04-18 12:32:18 -07001125 'output-img=',
Daniel Normanf0318252019-04-15 11:34:56 -07001126 'output-super-empty=',
Daniel Normana4911da2019-03-15 14:36:21 -07001127 'rebuild_recovery',
Daniel Normanb0c75912020-09-24 14:30:21 -07001128 'allow-duplicate-apkapex-keys',
Bill Peckham364c1cc2019-03-29 18:27:23 -07001129 'keep-tmp',
Bill Peckhamf753e152019-02-19 18:02:46 -08001130 ],
1131 extra_option_handler=option_handler)
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001132
Tao Bao2ad4b822019-06-27 16:52:12 -07001133 # pylint: disable=too-many-boolean-expressions
Daniel Normand5d70ea2019-06-05 15:13:43 -07001134 if (args or OPTIONS.framework_target_files is None or
1135 OPTIONS.vendor_target_files is None or
Daniel Normane5b134a2019-04-17 14:54:06 -07001136 (OPTIONS.output_target_files is None and OPTIONS.output_dir is None) or
1137 (OPTIONS.output_dir is not None and OPTIONS.output_item_list is None)):
Bill Peckhamf753e152019-02-19 18:02:46 -08001138 common.Usage(__doc__)
Bill Peckham889b0c62019-02-21 18:53:37 -08001139 sys.exit(1)
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001140
Daniel Normand5d70ea2019-06-05 15:13:43 -07001141 if OPTIONS.framework_item_list:
Daniel Norman4cc9df62019-07-18 10:11:07 -07001142 framework_item_list = common.LoadListFromFile(OPTIONS.framework_item_list)
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001143 else:
Daniel Normand5d70ea2019-06-05 15:13:43 -07001144 framework_item_list = DEFAULT_FRAMEWORK_ITEM_LIST
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001145
Daniel Normand5d70ea2019-06-05 15:13:43 -07001146 if OPTIONS.framework_misc_info_keys:
Daniel Norman4cc9df62019-07-18 10:11:07 -07001147 framework_misc_info_keys = common.LoadListFromFile(
Daniel Normand5d70ea2019-06-05 15:13:43 -07001148 OPTIONS.framework_misc_info_keys)
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001149 else:
Daniel Normand5d70ea2019-06-05 15:13:43 -07001150 framework_misc_info_keys = DEFAULT_FRAMEWORK_MISC_INFO_KEYS
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001151
Daniel Normand5d70ea2019-06-05 15:13:43 -07001152 if OPTIONS.vendor_item_list:
Daniel Norman4cc9df62019-07-18 10:11:07 -07001153 vendor_item_list = common.LoadListFromFile(OPTIONS.vendor_item_list)
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001154 else:
Daniel Normand5d70ea2019-06-05 15:13:43 -07001155 vendor_item_list = DEFAULT_VENDOR_ITEM_LIST
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001156
Daniel Normanfdb38812019-04-15 09:47:24 -07001157 if OPTIONS.output_item_list:
Daniel Norman4cc9df62019-07-18 10:11:07 -07001158 output_item_list = common.LoadListFromFile(OPTIONS.output_item_list)
Daniel Normanfdb38812019-04-15 09:47:24 -07001159 else:
1160 output_item_list = None
1161
Daniel Normane5964522019-03-19 10:32:03 -07001162 if not validate_config_lists(
Daniel Normand5d70ea2019-06-05 15:13:43 -07001163 framework_item_list=framework_item_list,
1164 framework_misc_info_keys=framework_misc_info_keys,
1165 vendor_item_list=vendor_item_list):
Daniel Normane5964522019-03-19 10:32:03 -07001166 sys.exit(1)
1167
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001168 call_func_with_temp_dir(
1169 lambda temp_dir: merge_target_files(
1170 temp_dir=temp_dir,
Daniel Normand5d70ea2019-06-05 15:13:43 -07001171 framework_target_files=OPTIONS.framework_target_files,
1172 framework_item_list=framework_item_list,
1173 framework_misc_info_keys=framework_misc_info_keys,
1174 vendor_target_files=OPTIONS.vendor_target_files,
1175 vendor_item_list=vendor_item_list,
Daniel Normana4911da2019-03-15 14:36:21 -07001176 output_target_files=OPTIONS.output_target_files,
Daniel Normanfdb38812019-04-15 09:47:24 -07001177 output_dir=OPTIONS.output_dir,
1178 output_item_list=output_item_list,
Daniel Norman3b64ce12019-04-16 16:11:35 -07001179 output_ota=OPTIONS.output_ota,
Daniel Norman1bd2a1d2019-04-18 12:32:18 -07001180 output_img=OPTIONS.output_img,
Daniel Normanf0318252019-04-15 11:34:56 -07001181 output_super_empty=OPTIONS.output_super_empty,
Daniel Normane5b134a2019-04-17 14:54:06 -07001182 rebuild_recovery=OPTIONS.rebuild_recovery), OPTIONS.keep_tmp)
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001183
1184
1185if __name__ == '__main__':
Bill Peckham889b0c62019-02-21 18:53:37 -08001186 main()