blob: ba9e740674656f11f9f15f14c1a98f1a1cce773c [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 Normand5d70ea2019-06-05 15:13:43 -0700459 # Replace <image>_selinux_fc values with framework or vendor file_contexts.bin
Daniel Norman72c626f2019-05-13 15:58:14 -0700460 # depending on which dictionary the key came from.
461 # Only the file basename is required because all selinux_fc properties are
462 # replaced with the full path to the file under META/ when misc_info.txt is
463 # loaded from target files for repacking. See common.py LoadInfoDict().
Daniel Normand5d70ea2019-06-05 15:13:43 -0700464 for key in merged_dict:
Daniel Norman72c626f2019-05-13 15:58:14 -0700465 if key.endswith('_selinux_fc'):
Daniel Normand5d70ea2019-06-05 15:13:43 -0700466 merged_dict[key] = 'vendor_file_contexts.bin'
467 for key in framework_dict:
Daniel Norman72c626f2019-05-13 15:58:14 -0700468 if key.endswith('_selinux_fc'):
Daniel Normand5d70ea2019-06-05 15:13:43 -0700469 merged_dict[key] = 'framework_file_contexts.bin'
Daniel Norman72c626f2019-05-13 15:58:14 -0700470
Daniel Normane5b134a2019-04-17 14:54:06 -0700471 output_misc_info_txt = os.path.join(output_target_files_temp_dir, 'META',
472 'misc_info.txt')
Daniel Normand5d70ea2019-06-05 15:13:43 -0700473 write_sorted_data(data=merged_dict, path=output_misc_info_txt)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800474
475
Daniel Normand5d70ea2019-06-05 15:13:43 -0700476def process_dynamic_partitions_info_txt(framework_target_files_dir,
477 vendor_target_files_dir,
Daniel Normana61cde02019-05-03 14:19:13 -0700478 output_target_files_dir):
Tao Bao2ad4b822019-06-27 16:52:12 -0700479 """Performs special processing for META/dynamic_partitions_info.txt.
Daniel Normana61cde02019-05-03 14:19:13 -0700480
481 This function merges the contents of the META/dynamic_partitions_info.txt
Daniel Normand5d70ea2019-06-05 15:13:43 -0700482 files from the framework directory and the vendor directory, placing the
483 merged result in the output directory.
Daniel Normana61cde02019-05-03 14:19:13 -0700484
Daniel Normand5d70ea2019-06-05 15:13:43 -0700485 This function does nothing if META/dynamic_partitions_info.txt from the vendor
Daniel Normana61cde02019-05-03 14:19:13 -0700486 directory does not exist.
487
488 Args:
Daniel Normand5d70ea2019-06-05 15:13:43 -0700489 framework_target_files_dir: The name of a directory containing the special
490 items extracted from the framework target files package.
491 vendor_target_files_dir: The name of a directory containing the special
492 items extracted from the vendor target files package.
Daniel Normana61cde02019-05-03 14:19:13 -0700493 output_target_files_dir: The name of a directory that will be used to create
494 the output target files package after all the special cases are processed.
495 """
496
497 if not os.path.exists(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700498 os.path.join(vendor_target_files_dir, 'META',
Daniel Normana61cde02019-05-03 14:19:13 -0700499 'dynamic_partitions_info.txt')):
500 return
501
Kiyoung Kimebe7c9c2019-06-25 17:09:55 +0900502 dynamic_partitions_info_path = ['META', 'dynamic_partitions_info.txt']
Daniel Normana61cde02019-05-03 14:19:13 -0700503
Kiyoung Kimebe7c9c2019-06-25 17:09:55 +0900504 framework_dynamic_partitions_dict = common.LoadDictionaryFromFile(
505 os.path.join(framework_target_files_dir, *dynamic_partitions_info_path))
506 vendor_dynamic_partitions_dict = common.LoadDictionaryFromFile(
507 os.path.join(vendor_target_files_dir, *dynamic_partitions_info_path))
Daniel Normana61cde02019-05-03 14:19:13 -0700508
Daniel Normanbfc51ef2019-07-24 14:34:54 -0700509 merged_dynamic_partitions_dict = common.MergeDynamicPartitionInfoDicts(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700510 framework_dict=framework_dynamic_partitions_dict,
Daniel Norman55417142019-11-25 16:04:36 -0800511 vendor_dict=vendor_dynamic_partitions_dict)
Daniel Normana61cde02019-05-03 14:19:13 -0700512
513 output_dynamic_partitions_info_txt = os.path.join(
514 output_target_files_dir, 'META', 'dynamic_partitions_info.txt')
Chris Grossfabf50a2019-05-02 12:42:09 -0700515 write_sorted_data(
516 data=merged_dynamic_partitions_dict,
517 path=output_dynamic_partitions_info_txt)
518
519
Bill Peckham19c3feb2020-03-20 18:31:43 -0700520def item_list_to_partition_set(item_list):
521 """Converts a target files item list to a partition set.
522
523 The item list contains items that might look like 'SYSTEM/*' or 'VENDOR/*' or
524 'OTA/android-info.txt'. Items that end in '/*' are assumed to match entire
525 directories where 'SYSTEM' or 'VENDOR' is a directory name that identifies the
526 contents of a partition of the same name. Other items in the list, such as the
527 'OTA' example contain metadata. This function iterates such a list, returning
528 a set that contains the partition entries.
529
530 Args:
531 item_list: A list of items in a target files package.
Daniel Normanb0c75912020-09-24 14:30:21 -0700532
Bill Peckham19c3feb2020-03-20 18:31:43 -0700533 Returns:
534 A set of partitions extracted from the list of items.
535 """
536
537 partition_set = set()
538
539 for item in item_list:
540 match = PARTITION_ITEM_PATTERN.search(item.strip())
541 partition_tag = match.group(1).lower() if match else None
542
543 if partition_tag:
544 partition_set.add(partition_tag)
545
546 return partition_set
547
548
Daniel Normand5d70ea2019-06-05 15:13:43 -0700549def process_apex_keys_apk_certs_common(framework_target_files_dir,
550 vendor_target_files_dir,
Bill Peckham19c3feb2020-03-20 18:31:43 -0700551 output_target_files_dir,
552 framework_partition_set,
553 vendor_partition_set, file_name):
Tao Bao2ad4b822019-06-27 16:52:12 -0700554 """Performs special processing for META/apexkeys.txt or META/apkcerts.txt.
Chris Grossfabf50a2019-05-02 12:42:09 -0700555
556 This function merges the contents of the META/apexkeys.txt or
Tao Bao2ad4b822019-06-27 16:52:12 -0700557 META/apkcerts.txt files from the framework directory and the vendor directory,
558 placing the merged result in the output directory. The precondition in that
559 the files are already extracted. The post condition is that the output
560 META/apexkeys.txt or META/apkcerts.txt contains the merged content.
Chris Grossfabf50a2019-05-02 12:42:09 -0700561
562 Args:
Daniel Normand5d70ea2019-06-05 15:13:43 -0700563 framework_target_files_dir: The name of a directory containing the special
564 items extracted from the framework target files package.
565 vendor_target_files_dir: The name of a directory containing the special
566 items extracted from the vendor target files package.
Chris Grossfabf50a2019-05-02 12:42:09 -0700567 output_target_files_dir: The name of a directory that will be used to create
568 the output target files package after all the special cases are processed.
Bill Peckham19c3feb2020-03-20 18:31:43 -0700569 framework_partition_set: Partitions that are considered framework
570 partitions. Used to filter apexkeys.txt and apkcerts.txt.
571 vendor_partition_set: Partitions that are considered vendor partitions. Used
572 to filter apexkeys.txt and apkcerts.txt.
Chris Grossfabf50a2019-05-02 12:42:09 -0700573 file_name: The name of the file to merge. One of apkcerts.txt or
574 apexkeys.txt.
575 """
576
577 def read_helper(d):
578 temp = {}
579 file_path = os.path.join(d, 'META', file_name)
580 with open(file_path) as f:
581 for line in f:
582 if line.strip():
Bill Peckham19c3feb2020-03-20 18:31:43 -0700583 name = line.split()[0]
584 match = MODULE_KEY_PATTERN.search(name)
585 temp[match.group(1)] = line.strip()
Chris Grossfabf50a2019-05-02 12:42:09 -0700586 return temp
587
Daniel Normand5d70ea2019-06-05 15:13:43 -0700588 framework_dict = read_helper(framework_target_files_dir)
589 vendor_dict = read_helper(vendor_target_files_dir)
Bill Peckham19c3feb2020-03-20 18:31:43 -0700590 merged_dict = {}
Chris Grossfabf50a2019-05-02 12:42:09 -0700591
Bill Peckham19c3feb2020-03-20 18:31:43 -0700592 def filter_into_merged_dict(item_dict, partition_set):
593 for key, value in item_dict.items():
594 match = PARTITION_TAG_PATTERN.search(value)
595
596 if match is None:
597 raise ValueError('Entry missing partition tag: %s' % value)
598
599 partition_tag = match.group(1)
600
601 if partition_tag in partition_set:
602 if key in merged_dict:
Daniel Normanb0c75912020-09-24 14:30:21 -0700603 if OPTIONS.allow_duplicate_apkapex_keys:
604 # TODO(b/150582573) Always raise on duplicates.
605 logger.warning('Duplicate key %s' % key)
606 continue
607 else:
608 raise ValueError('Duplicate key %s' % key)
Bill Peckham19c3feb2020-03-20 18:31:43 -0700609
610 merged_dict[key] = value
611
612 filter_into_merged_dict(framework_dict, framework_partition_set)
613 filter_into_merged_dict(vendor_dict, vendor_partition_set)
Chris Grossfabf50a2019-05-02 12:42:09 -0700614
615 output_file = os.path.join(output_target_files_dir, 'META', file_name)
616
Bill Peckham19c3feb2020-03-20 18:31:43 -0700617 # The following code is similar to write_sorted_data, but different enough
618 # that we couldn't use that function. We need the output to be sorted by the
619 # basename of the apex/apk (without the ".apex" or ".apk" suffix). This
620 # allows the sort to be consistent with the framework/vendor input data and
621 # eases comparison of input data with merged data.
622 with open(output_file, 'w') as output:
623 for key in sorted(merged_dict.keys()):
624 out_str = merged_dict[key] + '\n'
625 output.write(out_str)
Daniel Normana61cde02019-05-03 14:19:13 -0700626
627
Daniel Normand5d70ea2019-06-05 15:13:43 -0700628def copy_file_contexts(framework_target_files_dir, vendor_target_files_dir,
Daniel Norman72c626f2019-05-13 15:58:14 -0700629 output_target_files_dir):
630 """Creates named copies of each build's file_contexts.bin in output META/."""
Daniel Normand5d70ea2019-06-05 15:13:43 -0700631 framework_fc_path = os.path.join(framework_target_files_dir, 'META',
632 'framework_file_contexts.bin')
633 if not os.path.exists(framework_fc_path):
634 framework_fc_path = os.path.join(framework_target_files_dir, 'META',
635 'file_contexts.bin')
636 if not os.path.exists(framework_fc_path):
637 raise ValueError('Missing framework file_contexts.bin.')
638 shutil.copyfile(
639 framework_fc_path,
640 os.path.join(output_target_files_dir, 'META',
641 'framework_file_contexts.bin'))
642
643 vendor_fc_path = os.path.join(vendor_target_files_dir, 'META',
644 'vendor_file_contexts.bin')
645 if not os.path.exists(vendor_fc_path):
646 vendor_fc_path = os.path.join(vendor_target_files_dir, 'META',
Daniel Normanedf12472019-05-22 10:47:08 -0700647 'file_contexts.bin')
Daniel Normand5d70ea2019-06-05 15:13:43 -0700648 if not os.path.exists(vendor_fc_path):
649 raise ValueError('Missing vendor file_contexts.bin.')
Daniel Norman72c626f2019-05-13 15:58:14 -0700650 shutil.copyfile(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700651 vendor_fc_path,
652 os.path.join(output_target_files_dir, 'META', 'vendor_file_contexts.bin'))
Daniel Norman72c626f2019-05-13 15:58:14 -0700653
654
Daniel Normand5d70ea2019-06-05 15:13:43 -0700655def process_special_cases(framework_target_files_temp_dir,
656 vendor_target_files_temp_dir,
657 output_target_files_temp_dir,
Daniel Normanb0c75912020-09-24 14:30:21 -0700658 framework_misc_info_keys, framework_partition_set,
Bill Peckham19c3feb2020-03-20 18:31:43 -0700659 vendor_partition_set):
Tao Bao2ad4b822019-06-27 16:52:12 -0700660 """Performs special-case processing for certain target files items.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800661
662 Certain files in the output target files package require special-case
663 processing. This function performs all that special-case processing.
664
665 Args:
Daniel Normand5d70ea2019-06-05 15:13:43 -0700666 framework_target_files_temp_dir: The name of a directory containing the
667 special items extracted from the framework target files package.
668 vendor_target_files_temp_dir: The name of a directory containing the special
669 items extracted from the vendor target files package.
Daniel Normane5b134a2019-04-17 14:54:06 -0700670 output_target_files_temp_dir: The name of a directory that will be used to
671 create the output target files package after all the special cases are
672 processed.
Daniel Normand5d70ea2019-06-05 15:13:43 -0700673 framework_misc_info_keys: A list of keys to obtain from the framework
Daniel Normandbbf5a32020-10-22 16:03:32 -0700674 instance of META/misc_info.txt. The remaining keys should come from the
675 vendor instance.
Bill Peckham19c3feb2020-03-20 18:31:43 -0700676 framework_partition_set: Partitions that are considered framework
677 partitions. Used to filter apexkeys.txt and apkcerts.txt.
678 vendor_partition_set: Partitions that are considered vendor partitions. Used
679 to filter apexkeys.txt and apkcerts.txt.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800680 """
681
Daniel Normand5d70ea2019-06-05 15:13:43 -0700682 if 'ab_update' in framework_misc_info_keys:
Bill Peckham364c1cc2019-03-29 18:27:23 -0700683 process_ab_partitions_txt(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700684 framework_target_files_temp_dir=framework_target_files_temp_dir,
685 vendor_target_files_temp_dir=vendor_target_files_temp_dir,
Bill Peckham364c1cc2019-03-29 18:27:23 -0700686 output_target_files_temp_dir=output_target_files_temp_dir)
687
Daniel Norman72c626f2019-05-13 15:58:14 -0700688 copy_file_contexts(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700689 framework_target_files_dir=framework_target_files_temp_dir,
690 vendor_target_files_dir=vendor_target_files_temp_dir,
Daniel Norman72c626f2019-05-13 15:58:14 -0700691 output_target_files_dir=output_target_files_temp_dir)
692
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800693 process_misc_info_txt(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700694 framework_target_files_temp_dir=framework_target_files_temp_dir,
695 vendor_target_files_temp_dir=vendor_target_files_temp_dir,
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800696 output_target_files_temp_dir=output_target_files_temp_dir,
Daniel Normand5d70ea2019-06-05 15:13:43 -0700697 framework_misc_info_keys=framework_misc_info_keys)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800698
Daniel Normana61cde02019-05-03 14:19:13 -0700699 process_dynamic_partitions_info_txt(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700700 framework_target_files_dir=framework_target_files_temp_dir,
701 vendor_target_files_dir=vendor_target_files_temp_dir,
Daniel Norman714bd122019-05-08 16:20:02 -0700702 output_target_files_dir=output_target_files_temp_dir)
Daniel Normana61cde02019-05-03 14:19:13 -0700703
Chris Grossfabf50a2019-05-02 12:42:09 -0700704 process_apex_keys_apk_certs_common(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700705 framework_target_files_dir=framework_target_files_temp_dir,
706 vendor_target_files_dir=vendor_target_files_temp_dir,
Chris Grossfabf50a2019-05-02 12:42:09 -0700707 output_target_files_dir=output_target_files_temp_dir,
Bill Peckham19c3feb2020-03-20 18:31:43 -0700708 framework_partition_set=framework_partition_set,
709 vendor_partition_set=vendor_partition_set,
Chris Grossfabf50a2019-05-02 12:42:09 -0700710 file_name='apkcerts.txt')
711
712 process_apex_keys_apk_certs_common(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700713 framework_target_files_dir=framework_target_files_temp_dir,
714 vendor_target_files_dir=vendor_target_files_temp_dir,
Chris Grossfabf50a2019-05-02 12:42:09 -0700715 output_target_files_dir=output_target_files_temp_dir,
Bill Peckham19c3feb2020-03-20 18:31:43 -0700716 framework_partition_set=framework_partition_set,
717 vendor_partition_set=vendor_partition_set,
Chris Grossfabf50a2019-05-02 12:42:09 -0700718 file_name='apexkeys.txt')
719
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800720
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900721def create_merged_package(temp_dir, framework_target_files, framework_item_list,
722 vendor_target_files, vendor_item_list,
Daniel Norman4cc9df62019-07-18 10:11:07 -0700723 framework_misc_info_keys, rebuild_recovery):
Tao Bao2ad4b822019-06-27 16:52:12 -0700724 """Merges two target files packages into one target files structure.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800725
726 Args:
727 temp_dir: The name of a directory we use when we extract items from the
Daniel Normane5b134a2019-04-17 14:54:06 -0700728 input target files packages, and also a scratch directory that we use for
729 temporary files.
Daniel Normand5d70ea2019-06-05 15:13:43 -0700730 framework_target_files: The name of the zip archive containing the framework
Daniel Normane5b134a2019-04-17 14:54:06 -0700731 partial target files package.
Daniel Normand5d70ea2019-06-05 15:13:43 -0700732 framework_item_list: The list of items to extract from the partial framework
Daniel Normane5b134a2019-04-17 14:54:06 -0700733 target files package as is, meaning these items will land in the output
Daniel Normand5d70ea2019-06-05 15:13:43 -0700734 target files package exactly as they appear in the input partial framework
Daniel Normane5b134a2019-04-17 14:54:06 -0700735 target files package.
Daniel Normand5d70ea2019-06-05 15:13:43 -0700736 vendor_target_files: The name of the zip archive containing the vendor
737 partial target files package.
738 vendor_item_list: The list of items to extract from the partial vendor
739 target files package as is, meaning these items will land in the output
740 target files package exactly as they appear in the input partial vendor
Daniel Normane5b134a2019-04-17 14:54:06 -0700741 target files package.
Daniel Normandbbf5a32020-10-22 16:03:32 -0700742 framework_misc_info_keys: A list of keys to obtain from the framework
743 instance of META/misc_info.txt. The remaining keys should come from the
744 vendor instance.
Daniel Normana4911da2019-03-15 14:36:21 -0700745 rebuild_recovery: If true, rebuild the recovery patch used by non-A/B
Daniel Normane5b134a2019-04-17 14:54:06 -0700746 devices and write it to the system image.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800747
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900748 Returns:
749 Path to merged package under temp directory.
750 """
Daniel Normandbbf5a32020-10-22 16:03:32 -0700751 # Extract "as is" items from the input framework and vendor partial target
752 # files packages directly into the output temporary directory, since these items
753 # do not need special case processing.
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800754
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800755 output_target_files_temp_dir = os.path.join(temp_dir, 'output')
Bill Peckham889b0c62019-02-21 18:53:37 -0800756 extract_items(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700757 target_files=framework_target_files,
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800758 target_files_temp_dir=output_target_files_temp_dir,
Daniel Normand5d70ea2019-06-05 15:13:43 -0700759 extract_item_list=framework_item_list)
Bill Peckham889b0c62019-02-21 18:53:37 -0800760 extract_items(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700761 target_files=vendor_target_files,
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800762 target_files_temp_dir=output_target_files_temp_dir,
Daniel Normand5d70ea2019-06-05 15:13:43 -0700763 extract_item_list=vendor_item_list)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800764
Daniel Normandbbf5a32020-10-22 16:03:32 -0700765 # Perform special case processing on META/* items.
766 # After this function completes successfully, all the files we need to create
767 # the output target files package are in place.
768 framework_target_files_temp_dir = os.path.join(temp_dir, 'framework')
769 vendor_target_files_temp_dir = os.path.join(temp_dir, 'vendor')
Daniel Normand5d70ea2019-06-05 15:13:43 -0700770 extract_items(
771 target_files=framework_target_files,
772 target_files_temp_dir=framework_target_files_temp_dir,
Daniel Normandbbf5a32020-10-22 16:03:32 -0700773 extract_item_list=('META/*',))
Bill Peckham889b0c62019-02-21 18:53:37 -0800774 extract_items(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700775 target_files=vendor_target_files,
776 target_files_temp_dir=vendor_target_files_temp_dir,
Daniel Normandbbf5a32020-10-22 16:03:32 -0700777 extract_item_list=('META/*',))
Bill Peckham889b0c62019-02-21 18:53:37 -0800778 process_special_cases(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700779 framework_target_files_temp_dir=framework_target_files_temp_dir,
780 vendor_target_files_temp_dir=vendor_target_files_temp_dir,
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800781 output_target_files_temp_dir=output_target_files_temp_dir,
Bill Peckham19c3feb2020-03-20 18:31:43 -0700782 framework_misc_info_keys=framework_misc_info_keys,
783 framework_partition_set=item_list_to_partition_set(framework_item_list),
784 vendor_partition_set=item_list_to_partition_set(vendor_item_list))
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800785
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900786 return output_target_files_temp_dir
787
788
789def generate_images(target_files_dir, rebuild_recovery):
790 """Generate images from target files.
791
792 This function takes merged output temporary directory and create images
793 from it.
794
795 Args:
796 target_files_dir: Path to merged temp directory.
797 rebuild_recovery: If true, rebuild the recovery patch used by non-A/B
798 devices and write it to the system image.
799 """
800
801 # Regenerate IMAGES in the target directory.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800802
Daniel Normandbbf5a32020-10-22 16:03:32 -0700803 add_img_args = [
804 '--verbose',
805 '--add_missing',
806 ]
Bill Peckhame868aec2019-09-17 17:06:47 -0700807 # TODO(b/132730255): Remove this if statement.
Daniel Normana4911da2019-03-15 14:36:21 -0700808 if rebuild_recovery:
809 add_img_args.append('--rebuild_recovery')
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900810 add_img_args.append(target_files_dir)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800811
812 add_img_to_target_files.main(add_img_args)
813
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900814
815def generate_super_empty_image(target_dir, output_super_empty):
Tao Bao2ad4b822019-06-27 16:52:12 -0700816 """Generates super_empty image from target package.
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900817
818 Args:
819 target_dir: Path to the target file package which contains misc_info.txt for
820 detailed information for super image.
821 output_super_empty: If provided, copies a super_empty.img file from the
822 target files package to this path.
823 """
Daniel Norman1bd2a1d2019-04-18 12:32:18 -0700824 # Create super_empty.img using the merged misc_info.txt.
825
Daniel Norman4cc9df62019-07-18 10:11:07 -0700826 misc_info_txt = os.path.join(target_dir, 'META', 'misc_info.txt')
Daniel Norman1bd2a1d2019-04-18 12:32:18 -0700827
Kiyoung Kimebe7c9c2019-06-25 17:09:55 +0900828 use_dynamic_partitions = common.LoadDictionaryFromFile(misc_info_txt).get(
829 'use_dynamic_partitions')
Daniel Norman1bd2a1d2019-04-18 12:32:18 -0700830
831 if use_dynamic_partitions != 'true' and output_super_empty:
832 raise ValueError(
833 'Building super_empty.img requires use_dynamic_partitions=true.')
834 elif use_dynamic_partitions == 'true':
Daniel Norman4cc9df62019-07-18 10:11:07 -0700835 super_empty_img = os.path.join(target_dir, 'IMAGES', 'super_empty.img')
Daniel Norman1bd2a1d2019-04-18 12:32:18 -0700836 build_super_image_args = [
837 misc_info_txt,
838 super_empty_img,
839 ]
840 build_super_image.main(build_super_image_args)
841
842 # Copy super_empty.img to the user-provided output_super_empty location.
843 if output_super_empty:
844 shutil.copyfile(super_empty_img, output_super_empty)
845
Daniel Normanb8a2f9d2019-04-24 12:55:51 -0700846
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900847def create_target_files_archive(output_file, source_dir, temp_dir):
Tao Bao2ad4b822019-06-27 16:52:12 -0700848 """Creates archive from target package.
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900849
850 Args:
851 output_file: The name of the zip archive target files package.
852 source_dir: The target directory contains package to be archived.
853 temp_dir: Path to temporary directory for any intermediate files.
854 """
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800855 output_target_files_list = os.path.join(temp_dir, 'output.list')
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900856 output_zip = os.path.abspath(output_file)
Daniel Norman4cc9df62019-07-18 10:11:07 -0700857 output_target_files_meta_dir = os.path.join(source_dir, 'META')
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800858
Daniel Normandbbf5a32020-10-22 16:03:32 -0700859 def files_from_path(target_path, extra_args=None):
860 """Gets files under the given path and return a sorted list."""
861 find_command = ['find', target_path] + (extra_args or [])
862 find_process = common.Run(
863 find_command, stdout=subprocess.PIPE, verbose=False)
864 return common.RunAndCheckOutput(['sort'],
865 stdin=find_process.stdout,
866 verbose=False)
867
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900868 meta_content = files_from_path(output_target_files_meta_dir)
Daniel Norman4cc9df62019-07-18 10:11:07 -0700869 other_content = files_from_path(
870 source_dir,
871 ['-path', output_target_files_meta_dir, '-prune', '-o', '-print'])
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800872
Tao Bao2ad4b822019-06-27 16:52:12 -0700873 with open(output_target_files_list, 'w') as f:
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800874 f.write(meta_content)
875 f.write(other_content)
876
877 command = [
Bill Peckhamf753e152019-02-19 18:02:46 -0800878 'soong_zip',
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800879 '-d',
Daniel Normane5b134a2019-04-17 14:54:06 -0700880 '-o',
881 output_zip,
882 '-C',
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900883 source_dir,
Daniel Normane5b134a2019-04-17 14:54:06 -0700884 '-l',
885 output_target_files_list,
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800886 ]
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900887
888 logger.info('creating %s', output_file)
Bill Peckham889b0c62019-02-21 18:53:37 -0800889 common.RunAndWait(command, verbose=True)
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900890 logger.info('finished creating %s', output_file)
891
892 return output_zip
893
894
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900895def merge_target_files(temp_dir, framework_target_files, framework_item_list,
896 framework_misc_info_keys, vendor_target_files,
897 vendor_item_list, output_target_files, output_dir,
898 output_item_list, output_ota, output_img,
899 output_super_empty, rebuild_recovery):
Tao Bao2ad4b822019-06-27 16:52:12 -0700900 """Merges two target files packages together.
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900901
902 This function takes framework and vendor target files packages as input,
903 performs various file extractions, special case processing, and finally
904 creates a merged zip archive as output.
905
906 Args:
907 temp_dir: The name of a directory we use when we extract items from the
908 input target files packages, and also a scratch directory that we use for
909 temporary files.
910 framework_target_files: The name of the zip archive containing the framework
911 partial target files package.
912 framework_item_list: The list of items to extract from the partial framework
913 target files package as is, meaning these items will land in the output
914 target files package exactly as they appear in the input partial framework
915 target files package.
Daniel Normandbbf5a32020-10-22 16:03:32 -0700916 framework_misc_info_keys: A list of keys to obtain from the framework
917 instance of META/misc_info.txt. The remaining keys should come from the
918 vendor instance.
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900919 vendor_target_files: The name of the zip archive containing the vendor
920 partial target files package.
921 vendor_item_list: The list of items to extract from the partial vendor
922 target files package as is, meaning these items will land in the output
923 target files package exactly as they appear in the input partial vendor
924 target files package.
925 output_target_files: The name of the output zip archive target files package
926 created by merging framework and vendor.
927 output_dir: The destination directory for saving merged files.
928 output_item_list: The list of items to copy into the output_dir.
929 output_ota: The name of the output zip archive ota package.
930 output_img: The name of the output zip archive img package.
931 output_super_empty: If provided, creates a super_empty.img file from the
932 merged target files package and saves it at this path.
933 rebuild_recovery: If true, rebuild the recovery patch used by non-A/B
934 devices and write it to the system image.
935 """
936
937 logger.info('starting: merge framework %s and vendor %s into output %s',
938 framework_target_files, vendor_target_files, output_target_files)
939
940 output_target_files_temp_dir = create_merged_package(
941 temp_dir, framework_target_files, framework_item_list,
942 vendor_target_files, vendor_item_list, framework_misc_info_keys,
943 rebuild_recovery)
944
Yifan Hongade0d3f2019-08-21 16:37:11 -0700945 if not check_target_files_vintf.CheckVintf(output_target_files_temp_dir):
Daniel Normanb0c75912020-09-24 14:30:21 -0700946 raise RuntimeError('Incompatible VINTF metadata')
Yifan Hongade0d3f2019-08-21 16:37:11 -0700947
Daniel Normand3351562020-10-29 12:33:11 -0700948 # Generate and check for cross-partition violations of sharedUserId
949 # values in APKs. This requires the input target-files packages to contain
950 # *.apk files.
Daniel Normanb8d52a22020-10-26 17:55:00 -0700951 shareduid_violation_modules = os.path.join(
952 output_target_files_temp_dir, 'META', 'shareduid_violation_modules.json')
953 with open(shareduid_violation_modules, 'w') as f:
Daniel Normand3351562020-10-29 12:33:11 -0700954 framework_partitions = item_list_to_partition_set(framework_item_list)
955 vendor_partitions = item_list_to_partition_set(vendor_item_list)
956
957 partition_map = {}
958 for partition in (framework_partitions.union(vendor_partitions)):
959 partition_map[partition.lower()] = partition.upper()
Daniel Normanb8d52a22020-10-26 17:55:00 -0700960 violation = find_shareduid_violation.FindShareduidViolation(
961 output_target_files_temp_dir, partition_map)
Daniel Normand3351562020-10-29 12:33:11 -0700962
963 # Write the output to a file to enable debugging.
Daniel Normanb8d52a22020-10-26 17:55:00 -0700964 f.write(violation)
Daniel Normand3351562020-10-29 12:33:11 -0700965
966 # Check for violations across the input builds' partition groups.
967 shareduid_errors = common.SharedUidPartitionViolations(
968 json.loads(violation), [framework_partitions, vendor_partitions])
969 if shareduid_errors:
970 for error in shareduid_errors:
971 logger.error(error)
972 raise ValueError('sharedUserId APK error. See %s' %
973 shareduid_violation_modules)
Daniel Normanb8d52a22020-10-26 17:55:00 -0700974
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900975 generate_images(output_target_files_temp_dir, rebuild_recovery)
976
977 generate_super_empty_image(output_target_files_temp_dir, output_super_empty)
978
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900979 # Finally, create the output target files zip archive and/or copy the
980 # output items to the output target files directory.
981
982 if output_dir:
983 copy_items(output_target_files_temp_dir, output_dir, output_item_list)
984
985 if not output_target_files:
986 return
987
988 output_zip = create_target_files_archive(output_target_files,
989 output_target_files_temp_dir,
990 temp_dir)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800991
Daniel Norman74eb74b2019-09-18 14:01:48 -0700992 # Create the IMG package from the merged target files package.
993
994 if output_img:
995 img_from_target_files.main([output_zip, output_img])
996
Daniel Norman3b64ce12019-04-16 16:11:35 -0700997 # Create the OTA package from the merged target files package.
998
999 if output_ota:
Daniel Norman4cc9df62019-07-18 10:11:07 -07001000 ota_from_target_files.main([output_zip, output_ota])
Daniel Norman3b64ce12019-04-16 16:11:35 -07001001
Daniel Norman1bd2a1d2019-04-18 12:32:18 -07001002
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001003def call_func_with_temp_dir(func, keep_tmp):
Tao Bao2ad4b822019-06-27 16:52:12 -07001004 """Manages the creation and cleanup of the temporary directory.
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001005
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001006 This function calls the given function after first creating a temporary
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001007 directory. It also cleans up the temporary directory.
1008
1009 Args:
Daniel Normane5b134a2019-04-17 14:54:06 -07001010 func: The function to call. Should accept one parameter, the path to the
1011 temporary directory.
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001012 keep_tmp: Keep the temporary directory after processing is complete.
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001013 """
1014
1015 # Create a temporary directory. This will serve as the parent of directories
1016 # we use when we extract items from the input target files packages, and also
1017 # a scratch directory that we use for temporary files.
1018
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001019 temp_dir = common.MakeTempDir(prefix='merge_target_files_')
1020
1021 try:
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001022 func(temp_dir)
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001023 finally:
1024 if keep_tmp:
1025 logger.info('keeping %s', temp_dir)
1026 else:
1027 common.Cleanup()
1028
1029
1030def main():
1031 """The main function.
1032
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001033 Process command line arguments, then call merge_target_files to
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001034 perform the heavy lifting.
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001035 """
1036
1037 common.InitLogging()
1038
Bill Peckhamf753e152019-02-19 18:02:46 -08001039 def option_handler(o, a):
1040 if o == '--system-target-files':
Daniel Normand5d70ea2019-06-05 15:13:43 -07001041 logger.warning(
1042 '--system-target-files has been renamed to --framework-target-files')
1043 OPTIONS.framework_target_files = a
1044 elif o == '--framework-target-files':
1045 OPTIONS.framework_target_files = a
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001046 elif o == '--system-item-list':
Daniel Normand5d70ea2019-06-05 15:13:43 -07001047 logger.warning(
1048 '--system-item-list has been renamed to --framework-item-list')
1049 OPTIONS.framework_item_list = a
1050 elif o == '--framework-item-list':
1051 OPTIONS.framework_item_list = a
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001052 elif o == '--system-misc-info-keys':
Daniel Norman4cc9df62019-07-18 10:11:07 -07001053 logger.warning('--system-misc-info-keys has been renamed to '
1054 '--framework-misc-info-keys')
Daniel Normand5d70ea2019-06-05 15:13:43 -07001055 OPTIONS.framework_misc_info_keys = a
1056 elif o == '--framework-misc-info-keys':
1057 OPTIONS.framework_misc_info_keys = a
Bill Peckhamf753e152019-02-19 18:02:46 -08001058 elif o == '--other-target-files':
Daniel Normand5d70ea2019-06-05 15:13:43 -07001059 logger.warning(
1060 '--other-target-files has been renamed to --vendor-target-files')
1061 OPTIONS.vendor_target_files = a
1062 elif o == '--vendor-target-files':
1063 OPTIONS.vendor_target_files = a
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001064 elif o == '--other-item-list':
Daniel Normand5d70ea2019-06-05 15:13:43 -07001065 logger.warning('--other-item-list has been renamed to --vendor-item-list')
1066 OPTIONS.vendor_item_list = a
1067 elif o == '--vendor-item-list':
1068 OPTIONS.vendor_item_list = a
Bill Peckhamf753e152019-02-19 18:02:46 -08001069 elif o == '--output-target-files':
1070 OPTIONS.output_target_files = a
Daniel Normanfdb38812019-04-15 09:47:24 -07001071 elif o == '--output-dir':
1072 OPTIONS.output_dir = a
1073 elif o == '--output-item-list':
1074 OPTIONS.output_item_list = a
Daniel Norman3b64ce12019-04-16 16:11:35 -07001075 elif o == '--output-ota':
1076 OPTIONS.output_ota = a
Daniel Norman1bd2a1d2019-04-18 12:32:18 -07001077 elif o == '--output-img':
1078 OPTIONS.output_img = a
Daniel Normanf0318252019-04-15 11:34:56 -07001079 elif o == '--output-super-empty':
1080 OPTIONS.output_super_empty = a
Daniel Normanb0c75912020-09-24 14:30:21 -07001081 elif o == '--rebuild_recovery': # TODO(b/132730255): Warn
Daniel Normana4911da2019-03-15 14:36:21 -07001082 OPTIONS.rebuild_recovery = True
Daniel Normanb0c75912020-09-24 14:30:21 -07001083 elif o == '--allow-duplicate-apkapex-keys':
1084 OPTIONS.allow_duplicate_apkapex_keys = True
Bill Peckham364c1cc2019-03-29 18:27:23 -07001085 elif o == '--keep-tmp':
Bill Peckhamf753e152019-02-19 18:02:46 -08001086 OPTIONS.keep_tmp = True
1087 else:
1088 return False
1089 return True
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001090
Bill Peckhamf753e152019-02-19 18:02:46 -08001091 args = common.ParseOptions(
Daniel Normane5b134a2019-04-17 14:54:06 -07001092 sys.argv[1:],
1093 __doc__,
Bill Peckhamf753e152019-02-19 18:02:46 -08001094 extra_long_opts=[
1095 'system-target-files=',
Daniel Normand5d70ea2019-06-05 15:13:43 -07001096 'framework-target-files=',
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001097 'system-item-list=',
Daniel Normand5d70ea2019-06-05 15:13:43 -07001098 'framework-item-list=',
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001099 'system-misc-info-keys=',
Daniel Normand5d70ea2019-06-05 15:13:43 -07001100 'framework-misc-info-keys=',
Bill Peckhamf753e152019-02-19 18:02:46 -08001101 'other-target-files=',
Daniel Normand5d70ea2019-06-05 15:13:43 -07001102 'vendor-target-files=',
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001103 'other-item-list=',
Daniel Normand5d70ea2019-06-05 15:13:43 -07001104 'vendor-item-list=',
Bill Peckhamf753e152019-02-19 18:02:46 -08001105 'output-target-files=',
Daniel Normanfdb38812019-04-15 09:47:24 -07001106 'output-dir=',
1107 'output-item-list=',
Daniel Norman3b64ce12019-04-16 16:11:35 -07001108 'output-ota=',
Daniel Norman1bd2a1d2019-04-18 12:32:18 -07001109 'output-img=',
Daniel Normanf0318252019-04-15 11:34:56 -07001110 'output-super-empty=',
Daniel Normana4911da2019-03-15 14:36:21 -07001111 'rebuild_recovery',
Daniel Normanb0c75912020-09-24 14:30:21 -07001112 'allow-duplicate-apkapex-keys',
Bill Peckham364c1cc2019-03-29 18:27:23 -07001113 'keep-tmp',
Bill Peckhamf753e152019-02-19 18:02:46 -08001114 ],
1115 extra_option_handler=option_handler)
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001116
Tao Bao2ad4b822019-06-27 16:52:12 -07001117 # pylint: disable=too-many-boolean-expressions
Daniel Normand5d70ea2019-06-05 15:13:43 -07001118 if (args or OPTIONS.framework_target_files is None or
1119 OPTIONS.vendor_target_files is None or
Daniel Normane5b134a2019-04-17 14:54:06 -07001120 (OPTIONS.output_target_files is None and OPTIONS.output_dir is None) or
1121 (OPTIONS.output_dir is not None and OPTIONS.output_item_list is None)):
Bill Peckhamf753e152019-02-19 18:02:46 -08001122 common.Usage(__doc__)
Bill Peckham889b0c62019-02-21 18:53:37 -08001123 sys.exit(1)
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001124
Daniel Normand5d70ea2019-06-05 15:13:43 -07001125 if OPTIONS.framework_item_list:
Daniel Norman4cc9df62019-07-18 10:11:07 -07001126 framework_item_list = common.LoadListFromFile(OPTIONS.framework_item_list)
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001127 else:
Daniel Normand5d70ea2019-06-05 15:13:43 -07001128 framework_item_list = DEFAULT_FRAMEWORK_ITEM_LIST
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001129
Daniel Normand5d70ea2019-06-05 15:13:43 -07001130 if OPTIONS.framework_misc_info_keys:
Daniel Norman4cc9df62019-07-18 10:11:07 -07001131 framework_misc_info_keys = common.LoadListFromFile(
Daniel Normand5d70ea2019-06-05 15:13:43 -07001132 OPTIONS.framework_misc_info_keys)
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001133 else:
Daniel Normand5d70ea2019-06-05 15:13:43 -07001134 framework_misc_info_keys = DEFAULT_FRAMEWORK_MISC_INFO_KEYS
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001135
Daniel Normand5d70ea2019-06-05 15:13:43 -07001136 if OPTIONS.vendor_item_list:
Daniel Norman4cc9df62019-07-18 10:11:07 -07001137 vendor_item_list = common.LoadListFromFile(OPTIONS.vendor_item_list)
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001138 else:
Daniel Normand5d70ea2019-06-05 15:13:43 -07001139 vendor_item_list = DEFAULT_VENDOR_ITEM_LIST
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001140
Daniel Normanfdb38812019-04-15 09:47:24 -07001141 if OPTIONS.output_item_list:
Daniel Norman4cc9df62019-07-18 10:11:07 -07001142 output_item_list = common.LoadListFromFile(OPTIONS.output_item_list)
Daniel Normanfdb38812019-04-15 09:47:24 -07001143 else:
1144 output_item_list = None
1145
Daniel Normane5964522019-03-19 10:32:03 -07001146 if not validate_config_lists(
Daniel Normand5d70ea2019-06-05 15:13:43 -07001147 framework_item_list=framework_item_list,
1148 framework_misc_info_keys=framework_misc_info_keys,
1149 vendor_item_list=vendor_item_list):
Daniel Normane5964522019-03-19 10:32:03 -07001150 sys.exit(1)
1151
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001152 call_func_with_temp_dir(
1153 lambda temp_dir: merge_target_files(
1154 temp_dir=temp_dir,
Daniel Normand5d70ea2019-06-05 15:13:43 -07001155 framework_target_files=OPTIONS.framework_target_files,
1156 framework_item_list=framework_item_list,
1157 framework_misc_info_keys=framework_misc_info_keys,
1158 vendor_target_files=OPTIONS.vendor_target_files,
1159 vendor_item_list=vendor_item_list,
Daniel Normana4911da2019-03-15 14:36:21 -07001160 output_target_files=OPTIONS.output_target_files,
Daniel Normanfdb38812019-04-15 09:47:24 -07001161 output_dir=OPTIONS.output_dir,
1162 output_item_list=output_item_list,
Daniel Norman3b64ce12019-04-16 16:11:35 -07001163 output_ota=OPTIONS.output_ota,
Daniel Norman1bd2a1d2019-04-18 12:32:18 -07001164 output_img=OPTIONS.output_img,
Daniel Normanf0318252019-04-15 11:34:56 -07001165 output_super_empty=OPTIONS.output_super_empty,
Daniel Normane5b134a2019-04-17 14:54:06 -07001166 rebuild_recovery=OPTIONS.rebuild_recovery), OPTIONS.keep_tmp)
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001167
1168
1169if __name__ == '__main__':
Bill Peckham889b0c62019-02-21 18:53:37 -08001170 main()