blob: 6f414a50573e4b2d9d66905414f2044efceab6c1 [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 Normand5d70ea2019-06-05 15:13:43 -070019One package contains framework files, and the other contains vendor files.
Daniel Normane5b134a2019-04-17 14:54:06 -070020It produces a complete target files package that can be used to generate an
21OTA package.
Bill Peckhame9eb5f92019-02-01 15:52:10 -080022
23Usage: merge_target_files.py [args]
24
Daniel Normand5d70ea2019-06-05 15:13:43 -070025 --framework-target-files framework-target-files-zip-archive
26 The input target files package containing framework bits. This is a zip
Bill Peckhame9eb5f92019-02-01 15:52:10 -080027 archive.
28
Daniel Normand5d70ea2019-06-05 15:13:43 -070029 --framework-item-list framework-item-list-file
Daniel Norman2c99c5b2019-03-07 13:01:48 -080030 The optional path to a newline-separated config file that replaces the
Daniel Normand5d70ea2019-06-05 15:13:43 -070031 contents of DEFAULT_FRAMEWORK_ITEM_LIST if provided.
Daniel Norman2c99c5b2019-03-07 13:01:48 -080032
Daniel Normand5d70ea2019-06-05 15:13:43 -070033 --framework-misc-info-keys framework-misc-info-keys-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_MISC_INFO_KEYS if provided.
Daniel Norman2c99c5b2019-03-07 13:01:48 -080036
Daniel Normand5d70ea2019-06-05 15:13:43 -070037 --vendor-target-files vendor-target-files-zip-archive
38 The input target files package containing vendor bits. This is a zip
Bill Peckhame9eb5f92019-02-01 15:52:10 -080039 archive.
40
Daniel Normand5d70ea2019-06-05 15:13:43 -070041 --vendor-item-list vendor-item-list-file
Daniel Norman2c99c5b2019-03-07 13:01:48 -080042 The optional path to a newline-separated config file that replaces the
Daniel Normand5d70ea2019-06-05 15:13:43 -070043 contents of DEFAULT_VENDOR_ITEM_LIST if provided.
Daniel Norman2c99c5b2019-03-07 13:01:48 -080044
Bill Peckhame9eb5f92019-02-01 15:52:10 -080045 --output-target-files output-target-files-package
Daniel Normanfdb38812019-04-15 09:47:24 -070046 If provided, the output merged target files package. Also a zip archive.
47
48 --output-dir output-directory
49 If provided, the destination directory for saving merged files. Requires
50 the --output-item-list flag.
51 Can be provided alongside --output-target-files, or by itself.
52
53 --output-item-list output-item-list-file.
54 The optional path to a newline-separated config file that specifies the
55 file patterns to copy into the --output-dir. Required if providing
56 the --output-dir flag.
Daniel Normana4911da2019-03-15 14:36:21 -070057
Daniel Norman3b64ce12019-04-16 16:11:35 -070058 --output-ota output-ota-package
59 The output ota package. This is a zip archive. Use of this flag may
60 require passing the --path common flag; see common.py.
61
Daniel Norman1bd2a1d2019-04-18 12:32:18 -070062 --output-img output-img-package
63 The output img package, suitable for use with 'fastboot update'. Use of
64 this flag may require passing the --path common flag; see common.py.
65
Daniel Normanf0318252019-04-15 11:34:56 -070066 --output-super-empty output-super-empty-image
67 If provided, creates a super_empty.img file from the merged target
68 files package and saves it at this path.
69
Daniel Normana4911da2019-03-15 14:36:21 -070070 --rebuild_recovery
Bill Peckhame868aec2019-09-17 17:06:47 -070071 Deprecated; does nothing.
Bill Peckham364c1cc2019-03-29 18:27:23 -070072
Daniel Normanb0c75912020-09-24 14:30:21 -070073 --allow-duplicate-apkapex-keys
74 If provided, duplicate APK/APEX keys are ignored and the value from the
75 framework is used.
76
Bill Peckham364c1cc2019-03-29 18:27:23 -070077 --keep-tmp
78 Keep tempoary files for debugging purposes.
Bill Peckhame9eb5f92019-02-01 15:52:10 -080079"""
80
81from __future__ import print_function
82
Bill Peckhame9eb5f92019-02-01 15:52:10 -080083import fnmatch
84import logging
85import os
Bill Peckham19c3feb2020-03-20 18:31:43 -070086import re
Daniel Normanfdb38812019-04-15 09:47:24 -070087import shutil
Bill Peckham540d91a2019-04-25 14:18:16 -070088import subprocess
Bill Peckhame9eb5f92019-02-01 15:52:10 -080089import sys
90import zipfile
91
Bill Peckhame9eb5f92019-02-01 15:52:10 -080092import add_img_to_target_files
Daniel Normanf0318252019-04-15 11:34:56 -070093import build_super_image
Yifan Hongade0d3f2019-08-21 16:37:11 -070094import check_target_files_vintf
Daniel Normanf0318252019-04-15 11:34:56 -070095import common
Daniel Norman1bd2a1d2019-04-18 12:32:18 -070096import img_from_target_files
Daniel Norman3b64ce12019-04-16 16:11:35 -070097import ota_from_target_files
Bill Peckhame9eb5f92019-02-01 15:52:10 -080098
99logger = logging.getLogger(__name__)
Tao Bao2ad4b822019-06-27 16:52:12 -0700100
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800101OPTIONS = common.OPTIONS
Bill Peckhamcb848172020-04-03 12:50:47 -0700102# Always turn on verbose logging.
103OPTIONS.verbose = True
Daniel Normand5d70ea2019-06-05 15:13:43 -0700104OPTIONS.framework_target_files = None
105OPTIONS.framework_item_list = None
106OPTIONS.framework_misc_info_keys = None
107OPTIONS.vendor_target_files = None
108OPTIONS.vendor_item_list = None
Bill Peckhamf753e152019-02-19 18:02:46 -0800109OPTIONS.output_target_files = None
Daniel Normanfdb38812019-04-15 09:47:24 -0700110OPTIONS.output_dir = None
111OPTIONS.output_item_list = None
Daniel Norman3b64ce12019-04-16 16:11:35 -0700112OPTIONS.output_ota = None
Daniel Norman1bd2a1d2019-04-18 12:32:18 -0700113OPTIONS.output_img = None
Daniel Normanf0318252019-04-15 11:34:56 -0700114OPTIONS.output_super_empty = None
Bill Peckhame868aec2019-09-17 17:06:47 -0700115# TODO(b/132730255): Remove this option.
Daniel Normana4911da2019-03-15 14:36:21 -0700116OPTIONS.rebuild_recovery = False
Daniel Normanb0c75912020-09-24 14:30:21 -0700117# TODO(b/150582573): Remove this option.
118OPTIONS.allow_duplicate_apkapex_keys = False
Bill Peckhamf753e152019-02-19 18:02:46 -0800119OPTIONS.keep_tmp = False
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800120
Bill Peckham19c3feb2020-03-20 18:31:43 -0700121# In an item list (framework or vendor), we may see entries that select whole
122# partitions. Such an entry might look like this 'SYSTEM/*' (e.g., for the
123# system partition). The following regex matches this and extracts the
124# partition name.
125
126PARTITION_ITEM_PATTERN = re.compile(r'^([A-Z_]+)/\*$')
127
Bill Peckham5c7b0342020-04-03 15:36:23 -0700128# In apexkeys.txt or apkcerts.txt, we will find partition tags on each entry in
129# the file. We use these partition tags to filter the entries in those files
130# from the two different target files packages to produce a merged apexkeys.txt
131# or apkcerts.txt file. A partition tag (e.g., for the product partition) looks
132# like this: 'partition="product"'. We use the group syntax grab the value of
133# the tag. We use non-greedy matching in case there are other fields on the
134# same line.
Bill Peckham19c3feb2020-03-20 18:31:43 -0700135
Bill Peckham5c7b0342020-04-03 15:36:23 -0700136PARTITION_TAG_PATTERN = re.compile(r'partition="(.*?)"')
Bill Peckham19c3feb2020-03-20 18:31:43 -0700137
138# The sorting algorithm for apexkeys.txt and apkcerts.txt does not include the
139# ".apex" or ".apk" suffix, so we use the following pattern to extract a key.
140
141MODULE_KEY_PATTERN = re.compile(r'name="(.+)\.(apex|apk)"')
142
Daniel Normand5d70ea2019-06-05 15:13:43 -0700143# DEFAULT_FRAMEWORK_ITEM_LIST is a list of items to extract from the partial
144# framework target files package as is, meaning these items will land in the
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800145# output target files package exactly as they appear in the input partial
Daniel Normand5d70ea2019-06-05 15:13:43 -0700146# framework target files package.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800147
Daniel Normand5d70ea2019-06-05 15:13:43 -0700148DEFAULT_FRAMEWORK_ITEM_LIST = (
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800149 'META/apkcerts.txt',
150 'META/filesystem_config.txt',
151 'META/root_filesystem_config.txt',
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800152 'META/update_engine_config.txt',
153 'PRODUCT/*',
154 'ROOT/*',
155 'SYSTEM/*',
Daniel Normanedf12472019-05-22 10:47:08 -0700156)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800157
Daniel Normand5d70ea2019-06-05 15:13:43 -0700158# FRAMEWORK_EXTRACT_SPECIAL_ITEM_LIST is a list of items to extract from the
159# partial framework target files package that need some special processing, such
160# as some sort of combination with items from the partial vendor target files
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800161# package.
162
Daniel Normand5d70ea2019-06-05 15:13:43 -0700163FRAMEWORK_EXTRACT_SPECIAL_ITEM_LIST = ('META/*',)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800164
Daniel Normand5d70ea2019-06-05 15:13:43 -0700165# DEFAULT_FRAMEWORK_MISC_INFO_KEYS is a list of keys to obtain from the
166# framework instance of META/misc_info.txt. The remaining keys from the
167# vendor instance.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800168
Daniel Normand5d70ea2019-06-05 15:13:43 -0700169DEFAULT_FRAMEWORK_MISC_INFO_KEYS = (
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800170 'avb_system_hashtree_enable',
171 'avb_system_add_hashtree_footer_args',
172 'avb_system_key_path',
173 'avb_system_algorithm',
174 'avb_system_rollback_index_location',
175 'avb_product_hashtree_enable',
176 'avb_product_add_hashtree_footer_args',
Justin Yun6151e3f2019-06-25 15:58:13 +0900177 'avb_system_ext_hashtree_enable',
178 'avb_system_ext_add_hashtree_footer_args',
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800179 'system_root_image',
180 'root_dir',
181 'ab_update',
182 'default_system_dev_certificate',
183 'system_size',
Chris Gross203191b2020-05-30 02:39:12 +0000184 'building_system_image',
185 'building_system_ext_image',
186 'building_product_image',
Daniel Normanedf12472019-05-22 10:47:08 -0700187)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800188
Daniel Normand5d70ea2019-06-05 15:13:43 -0700189# DEFAULT_VENDOR_ITEM_LIST is a list of items to extract from the partial
190# vendor target files package as is, meaning these items will land in the output
191# target files package exactly as they appear in the input partial vendor target
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800192# files package.
193
Daniel Normand5d70ea2019-06-05 15:13:43 -0700194DEFAULT_VENDOR_ITEM_LIST = (
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800195 'META/boot_filesystem_config.txt',
196 'META/otakeys.txt',
197 'META/releasetools.py',
198 'META/vendor_filesystem_config.txt',
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800199 'BOOT/*',
200 'DATA/*',
201 'ODM/*',
202 'OTA/android-info.txt',
203 'PREBUILT_IMAGES/*',
204 'RADIO/*',
205 'VENDOR/*',
Daniel Normanedf12472019-05-22 10:47:08 -0700206)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800207
Daniel Normand5d70ea2019-06-05 15:13:43 -0700208# VENDOR_EXTRACT_SPECIAL_ITEM_LIST is a list of items to extract from the
209# partial vendor target files package that need some special processing, such as
210# some sort of combination with items from the partial framework target files
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800211# package.
212
Daniel Normand5d70ea2019-06-05 15:13:43 -0700213VENDOR_EXTRACT_SPECIAL_ITEM_LIST = ('META/*',)
Daniel Normanedf12472019-05-22 10:47:08 -0700214
215# The merge config lists should not attempt to extract items from both
216# builds for any of the following partitions. The partitions in
217# SINGLE_BUILD_PARTITIONS should come entirely from a single build (either
Daniel Normand5d70ea2019-06-05 15:13:43 -0700218# framework or vendor, but not both).
Daniel Normanedf12472019-05-22 10:47:08 -0700219
220SINGLE_BUILD_PARTITIONS = (
221 'BOOT/',
222 'DATA/',
223 'ODM/',
224 'PRODUCT/',
Justin Yun6151e3f2019-06-25 15:58:13 +0900225 'SYSTEM_EXT/',
Daniel Normanedf12472019-05-22 10:47:08 -0700226 'RADIO/',
227 'RECOVERY/',
228 'ROOT/',
229 'SYSTEM/',
230 'SYSTEM_OTHER/',
231 'VENDOR/',
Yifan Hongcfb917a2020-05-07 14:58:20 -0700232 'VENDOR_DLKM/',
Yifan Hongf496f1b2020-07-15 16:52:59 -0700233 'ODM_DLKM/',
Daniel Normanedf12472019-05-22 10:47:08 -0700234)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800235
236
Chris Grossfabf50a2019-05-02 12:42:09 -0700237def write_sorted_data(data, path):
Tao Bao2ad4b822019-06-27 16:52:12 -0700238 """Writes the sorted contents of either a list or dict to file.
Chris Grossfabf50a2019-05-02 12:42:09 -0700239
Tao Bao2ad4b822019-06-27 16:52:12 -0700240 This function sorts the contents of the list or dict and then writes the
241 resulting sorted contents to a file specified by path.
Chris Grossfabf50a2019-05-02 12:42:09 -0700242
243 Args:
244 data: The list or dict to sort and write.
245 path: Path to the file to write the sorted values to. The file at path will
246 be overridden if it exists.
247 """
248 with open(path, 'w') as output:
Daniel Normand5d70ea2019-06-05 15:13:43 -0700249 for entry in sorted(data):
Chris Grossfabf50a2019-05-02 12:42:09 -0700250 out_str = '{}={}\n'.format(entry, data[entry]) if isinstance(
251 data, dict) else '{}\n'.format(entry)
252 output.write(out_str)
253
254
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800255def extract_items(target_files, target_files_temp_dir, extract_item_list):
Tao Bao2ad4b822019-06-27 16:52:12 -0700256 """Extracts items from target files to temporary directory.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800257
258 This function extracts from the specified target files zip archive into the
259 specified temporary directory, the items specified in the extract item list.
260
261 Args:
262 target_files: The target files zip archive from which to extract items.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800263 target_files_temp_dir: The temporary directory where the extracted items
Daniel Normane5b134a2019-04-17 14:54:06 -0700264 will land.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800265 extract_item_list: A list of items to extract.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800266 """
267
268 logger.info('extracting from %s', target_files)
269
270 # Filter the extract_item_list to remove any items that do not exist in the
271 # zip file. Otherwise, the extraction step will fail.
272
Daniel Norman4cc9df62019-07-18 10:11:07 -0700273 with zipfile.ZipFile(target_files, allowZip64=True) as target_files_zipfile:
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800274 target_files_namelist = target_files_zipfile.namelist()
275
276 filtered_extract_item_list = []
277 for pattern in extract_item_list:
278 matching_namelist = fnmatch.filter(target_files_namelist, pattern)
279 if not matching_namelist:
280 logger.warning('no match for %s', pattern)
281 else:
282 filtered_extract_item_list.append(pattern)
283
Bill Peckham8ff3fbd2019-02-22 10:57:43 -0800284 # Extract from target_files into target_files_temp_dir the
285 # filtered_extract_item_list.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800286
Daniel Normane5b134a2019-04-17 14:54:06 -0700287 common.UnzipToDir(target_files, target_files_temp_dir,
288 filtered_extract_item_list)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800289
290
Daniel Normanfdb38812019-04-15 09:47:24 -0700291def copy_items(from_dir, to_dir, patterns):
292 """Similar to extract_items() except uses an input dir instead of zip."""
293 file_paths = []
294 for dirpath, _, filenames in os.walk(from_dir):
Daniel Normane5b134a2019-04-17 14:54:06 -0700295 file_paths.extend(
296 os.path.relpath(path=os.path.join(dirpath, filename), start=from_dir)
297 for filename in filenames)
Daniel Normanfdb38812019-04-15 09:47:24 -0700298
299 filtered_file_paths = set()
300 for pattern in patterns:
301 filtered_file_paths.update(fnmatch.filter(file_paths, pattern))
302
303 for file_path in filtered_file_paths:
304 original_file_path = os.path.join(from_dir, file_path)
305 copied_file_path = os.path.join(to_dir, file_path)
306 copied_file_dir = os.path.dirname(copied_file_path)
307 if not os.path.exists(copied_file_dir):
308 os.makedirs(copied_file_dir)
309 if os.path.islink(original_file_path):
310 os.symlink(os.readlink(original_file_path), copied_file_path)
311 else:
312 shutil.copyfile(original_file_path, copied_file_path)
313
314
Daniel Normand5d70ea2019-06-05 15:13:43 -0700315def validate_config_lists(framework_item_list, framework_misc_info_keys,
316 vendor_item_list):
Daniel Normane5964522019-03-19 10:32:03 -0700317 """Performs validations on the merge config lists.
318
319 Args:
Daniel Normand5d70ea2019-06-05 15:13:43 -0700320 framework_item_list: The list of items to extract from the partial framework
Daniel Normane5b134a2019-04-17 14:54:06 -0700321 target files package as is.
Daniel Normand5d70ea2019-06-05 15:13:43 -0700322 framework_misc_info_keys: A list of keys to obtain from the framework
323 instance of META/misc_info.txt. The remaining keys from the vendor
324 instance.
325 vendor_item_list: The list of items to extract from the partial vendor
326 target files package as is.
Daniel Normane5964522019-03-19 10:32:03 -0700327
328 Returns:
329 False if a validation fails, otherwise true.
330 """
Daniel Normanedf12472019-05-22 10:47:08 -0700331 has_error = False
332
Daniel Normand5d70ea2019-06-05 15:13:43 -0700333 default_combined_item_set = set(DEFAULT_FRAMEWORK_ITEM_LIST)
334 default_combined_item_set.update(DEFAULT_VENDOR_ITEM_LIST)
Daniel Normane5964522019-03-19 10:32:03 -0700335
Daniel Normand5d70ea2019-06-05 15:13:43 -0700336 combined_item_set = set(framework_item_list)
337 combined_item_set.update(vendor_item_list)
Daniel Normane5964522019-03-19 10:32:03 -0700338
339 # Check that the merge config lists are not missing any item specified
340 # by the default config lists.
341 difference = default_combined_item_set.difference(combined_item_set)
342 if difference:
Daniel Normane5b134a2019-04-17 14:54:06 -0700343 logger.error('Missing merge config items: %s', list(difference))
Daniel Normane5964522019-03-19 10:32:03 -0700344 logger.error('Please ensure missing items are in either the '
Daniel Normand5d70ea2019-06-05 15:13:43 -0700345 'framework-item-list or vendor-item-list files provided to '
Daniel Normane5964522019-03-19 10:32:03 -0700346 'this script.')
Daniel Normanedf12472019-05-22 10:47:08 -0700347 has_error = True
348
349 for partition in SINGLE_BUILD_PARTITIONS:
Daniel Normand5d70ea2019-06-05 15:13:43 -0700350 in_framework = any(
351 item.startswith(partition) for item in framework_item_list)
352 in_vendor = any(item.startswith(partition) for item in vendor_item_list)
353 if in_framework and in_vendor:
Daniel Normanedf12472019-05-22 10:47:08 -0700354 logger.error(
Tao Bao2ad4b822019-06-27 16:52:12 -0700355 'Cannot extract items from %s for both the framework and vendor'
Kiyoung Kimebe7c9c2019-06-25 17:09:55 +0900356 ' builds. Please ensure only one merge config item list'
Tao Bao2ad4b822019-06-27 16:52:12 -0700357 ' includes %s.', partition, partition)
Daniel Normanedf12472019-05-22 10:47:08 -0700358 has_error = True
Daniel Normane5964522019-03-19 10:32:03 -0700359
Daniel Normand5d70ea2019-06-05 15:13:43 -0700360 if ('dynamic_partition_list' in framework_misc_info_keys) or (
361 'super_partition_groups' in framework_misc_info_keys):
Daniel Norman19b9fe92019-03-19 14:48:02 -0700362 logger.error('Dynamic partition misc info keys should come from '
Daniel Normand5d70ea2019-06-05 15:13:43 -0700363 'the vendor instance of META/misc_info.txt.')
Daniel Normanedf12472019-05-22 10:47:08 -0700364 has_error = True
Daniel Norman19b9fe92019-03-19 14:48:02 -0700365
Daniel Normanedf12472019-05-22 10:47:08 -0700366 return not has_error
Daniel Normane5964522019-03-19 10:32:03 -0700367
368
Daniel Normand5d70ea2019-06-05 15:13:43 -0700369def process_ab_partitions_txt(framework_target_files_temp_dir,
370 vendor_target_files_temp_dir,
Daniel Normane5b134a2019-04-17 14:54:06 -0700371 output_target_files_temp_dir):
Tao Bao2ad4b822019-06-27 16:52:12 -0700372 """Performs special processing for META/ab_partitions.txt.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800373
Tao Bao2ad4b822019-06-27 16:52:12 -0700374 This function merges the contents of the META/ab_partitions.txt files from the
375 framework directory and the vendor directory, placing the merged result in the
376 output directory. The precondition in that the files are already extracted.
377 The post condition is that the output META/ab_partitions.txt contains the
378 merged content. The format for each ab_partitions.txt a one partition name per
379 line. The output file contains the union of the parition names.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800380
381 Args:
Daniel Normand5d70ea2019-06-05 15:13:43 -0700382 framework_target_files_temp_dir: The name of a directory containing the
383 special items extracted from the framework target files package.
384 vendor_target_files_temp_dir: The name of a directory containing the special
385 items extracted from the vendor target files package.
Daniel Normane5b134a2019-04-17 14:54:06 -0700386 output_target_files_temp_dir: The name of a directory that will be used to
387 create the output target files package after all the special cases are
388 processed.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800389 """
390
Daniel Normand5d70ea2019-06-05 15:13:43 -0700391 framework_ab_partitions_txt = os.path.join(framework_target_files_temp_dir,
392 'META', 'ab_partitions.txt')
393
394 vendor_ab_partitions_txt = os.path.join(vendor_target_files_temp_dir, 'META',
Daniel Normane5b134a2019-04-17 14:54:06 -0700395 'ab_partitions.txt')
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800396
Daniel Normand5d70ea2019-06-05 15:13:43 -0700397 with open(framework_ab_partitions_txt) as f:
398 framework_ab_partitions = f.read().splitlines()
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800399
Daniel Normand5d70ea2019-06-05 15:13:43 -0700400 with open(vendor_ab_partitions_txt) as f:
401 vendor_ab_partitions = f.read().splitlines()
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800402
Daniel Normand5d70ea2019-06-05 15:13:43 -0700403 output_ab_partitions = set(framework_ab_partitions + vendor_ab_partitions)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800404
Daniel Normane5b134a2019-04-17 14:54:06 -0700405 output_ab_partitions_txt = os.path.join(output_target_files_temp_dir, 'META',
406 'ab_partitions.txt')
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800407
Chris Grossfabf50a2019-05-02 12:42:09 -0700408 write_sorted_data(data=output_ab_partitions, path=output_ab_partitions_txt)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800409
410
Daniel Normand5d70ea2019-06-05 15:13:43 -0700411def process_misc_info_txt(framework_target_files_temp_dir,
412 vendor_target_files_temp_dir,
413 output_target_files_temp_dir,
414 framework_misc_info_keys):
Tao Bao2ad4b822019-06-27 16:52:12 -0700415 """Performs special processing for META/misc_info.txt.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800416
417 This function merges the contents of the META/misc_info.txt files from the
Daniel Normand5d70ea2019-06-05 15:13:43 -0700418 framework directory and the vendor directory, placing the merged result in the
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800419 output directory. The precondition in that the files are already extracted.
420 The post condition is that the output META/misc_info.txt contains the merged
421 content.
422
423 Args:
Daniel Normand5d70ea2019-06-05 15:13:43 -0700424 framework_target_files_temp_dir: The name of a directory containing the
425 special items extracted from the framework target files package.
426 vendor_target_files_temp_dir: The name of a directory containing the special
427 items extracted from the vendor target files package.
Daniel Normane5b134a2019-04-17 14:54:06 -0700428 output_target_files_temp_dir: The name of a directory that will be used to
429 create the output target files package after all the special cases are
430 processed.
Daniel Normand5d70ea2019-06-05 15:13:43 -0700431 framework_misc_info_keys: A list of keys to obtain from the framework
432 instance of META/misc_info.txt. The remaining keys from the vendor
433 instance.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800434 """
435
Kiyoung Kimebe7c9c2019-06-25 17:09:55 +0900436 misc_info_path = ['META', 'misc_info.txt']
437 framework_dict = common.LoadDictionaryFromFile(
438 os.path.join(framework_target_files_temp_dir, *misc_info_path))
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800439
Daniel Normand5d70ea2019-06-05 15:13:43 -0700440 # We take most of the misc info from the vendor target files.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800441
Kiyoung Kimebe7c9c2019-06-25 17:09:55 +0900442 merged_dict = common.LoadDictionaryFromFile(
443 os.path.join(vendor_target_files_temp_dir, *misc_info_path))
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800444
Daniel Normand5d70ea2019-06-05 15:13:43 -0700445 # Replace certain values in merged_dict with values from
446 # framework_dict.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800447
Daniel Normand5d70ea2019-06-05 15:13:43 -0700448 for key in framework_misc_info_keys:
449 merged_dict[key] = framework_dict[key]
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800450
Daniel Norman19b9fe92019-03-19 14:48:02 -0700451 # Merge misc info keys used for Dynamic Partitions.
Daniel Normand5d70ea2019-06-05 15:13:43 -0700452 if (merged_dict.get('use_dynamic_partitions') == 'true') and (
453 framework_dict.get('use_dynamic_partitions') == 'true'):
Daniel Normanbfc51ef2019-07-24 14:34:54 -0700454 merged_dynamic_partitions_dict = common.MergeDynamicPartitionInfoDicts(
Daniel Norman55417142019-11-25 16:04:36 -0800455 framework_dict=framework_dict, vendor_dict=merged_dict)
Daniel Normand5d70ea2019-06-05 15:13:43 -0700456 merged_dict.update(merged_dynamic_partitions_dict)
Tao Bao48a2feb2019-06-28 11:00:05 -0700457 # Ensure that add_img_to_target_files rebuilds super split images for
458 # devices that retrofit dynamic partitions. This flag may have been set to
459 # false in the partial builds to prevent duplicate building of super.img.
Daniel Norman0bf940c2019-06-10 12:50:19 -0700460 merged_dict['build_super_partition'] = 'true'
Daniel Norman19b9fe92019-03-19 14:48:02 -0700461
Daniel Normand5d70ea2019-06-05 15:13:43 -0700462 # Replace <image>_selinux_fc values with framework or vendor file_contexts.bin
Daniel Norman72c626f2019-05-13 15:58:14 -0700463 # depending on which dictionary the key came from.
464 # Only the file basename is required because all selinux_fc properties are
465 # replaced with the full path to the file under META/ when misc_info.txt is
466 # loaded from target files for repacking. See common.py LoadInfoDict().
Daniel Normand5d70ea2019-06-05 15:13:43 -0700467 for key in merged_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] = 'vendor_file_contexts.bin'
470 for key in framework_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] = 'framework_file_contexts.bin'
Daniel Norman72c626f2019-05-13 15:58:14 -0700473
Daniel Normane5b134a2019-04-17 14:54:06 -0700474 output_misc_info_txt = os.path.join(output_target_files_temp_dir, 'META',
475 'misc_info.txt')
Daniel Normand5d70ea2019-06-05 15:13:43 -0700476 write_sorted_data(data=merged_dict, path=output_misc_info_txt)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800477
478
Daniel Normand5d70ea2019-06-05 15:13:43 -0700479def process_dynamic_partitions_info_txt(framework_target_files_dir,
480 vendor_target_files_dir,
Daniel Normana61cde02019-05-03 14:19:13 -0700481 output_target_files_dir):
Tao Bao2ad4b822019-06-27 16:52:12 -0700482 """Performs special processing for META/dynamic_partitions_info.txt.
Daniel Normana61cde02019-05-03 14:19:13 -0700483
484 This function merges the contents of the META/dynamic_partitions_info.txt
Daniel Normand5d70ea2019-06-05 15:13:43 -0700485 files from the framework directory and the vendor directory, placing the
486 merged result in the output directory.
Daniel Normana61cde02019-05-03 14:19:13 -0700487
Daniel Normand5d70ea2019-06-05 15:13:43 -0700488 This function does nothing if META/dynamic_partitions_info.txt from the vendor
Daniel Normana61cde02019-05-03 14:19:13 -0700489 directory does not exist.
490
491 Args:
Daniel Normand5d70ea2019-06-05 15:13:43 -0700492 framework_target_files_dir: The name of a directory containing the special
493 items extracted from the framework target files package.
494 vendor_target_files_dir: The name of a directory containing the special
495 items extracted from the vendor target files package.
Daniel Normana61cde02019-05-03 14:19:13 -0700496 output_target_files_dir: The name of a directory that will be used to create
497 the output target files package after all the special cases are processed.
498 """
499
500 if not os.path.exists(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700501 os.path.join(vendor_target_files_dir, 'META',
Daniel Normana61cde02019-05-03 14:19:13 -0700502 'dynamic_partitions_info.txt')):
503 return
504
Kiyoung Kimebe7c9c2019-06-25 17:09:55 +0900505 dynamic_partitions_info_path = ['META', 'dynamic_partitions_info.txt']
Daniel Normana61cde02019-05-03 14:19:13 -0700506
Kiyoung Kimebe7c9c2019-06-25 17:09:55 +0900507 framework_dynamic_partitions_dict = common.LoadDictionaryFromFile(
508 os.path.join(framework_target_files_dir, *dynamic_partitions_info_path))
509 vendor_dynamic_partitions_dict = common.LoadDictionaryFromFile(
510 os.path.join(vendor_target_files_dir, *dynamic_partitions_info_path))
Daniel Normana61cde02019-05-03 14:19:13 -0700511
Daniel Normanbfc51ef2019-07-24 14:34:54 -0700512 merged_dynamic_partitions_dict = common.MergeDynamicPartitionInfoDicts(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700513 framework_dict=framework_dynamic_partitions_dict,
Daniel Norman55417142019-11-25 16:04:36 -0800514 vendor_dict=vendor_dynamic_partitions_dict)
Daniel Normana61cde02019-05-03 14:19:13 -0700515
516 output_dynamic_partitions_info_txt = os.path.join(
517 output_target_files_dir, 'META', 'dynamic_partitions_info.txt')
Chris Grossfabf50a2019-05-02 12:42:09 -0700518 write_sorted_data(
519 data=merged_dynamic_partitions_dict,
520 path=output_dynamic_partitions_info_txt)
521
522
Bill Peckham19c3feb2020-03-20 18:31:43 -0700523def item_list_to_partition_set(item_list):
524 """Converts a target files item list to a partition set.
525
526 The item list contains items that might look like 'SYSTEM/*' or 'VENDOR/*' or
527 'OTA/android-info.txt'. Items that end in '/*' are assumed to match entire
528 directories where 'SYSTEM' or 'VENDOR' is a directory name that identifies the
529 contents of a partition of the same name. Other items in the list, such as the
530 'OTA' example contain metadata. This function iterates such a list, returning
531 a set that contains the partition entries.
532
533 Args:
534 item_list: A list of items in a target files package.
Daniel Normanb0c75912020-09-24 14:30:21 -0700535
Bill Peckham19c3feb2020-03-20 18:31:43 -0700536 Returns:
537 A set of partitions extracted from the list of items.
538 """
539
540 partition_set = set()
541
542 for item in item_list:
543 match = PARTITION_ITEM_PATTERN.search(item.strip())
544 partition_tag = match.group(1).lower() if match else None
545
546 if partition_tag:
547 partition_set.add(partition_tag)
548
549 return partition_set
550
551
Daniel Normand5d70ea2019-06-05 15:13:43 -0700552def process_apex_keys_apk_certs_common(framework_target_files_dir,
553 vendor_target_files_dir,
Bill Peckham19c3feb2020-03-20 18:31:43 -0700554 output_target_files_dir,
555 framework_partition_set,
556 vendor_partition_set, file_name):
Tao Bao2ad4b822019-06-27 16:52:12 -0700557 """Performs special processing for META/apexkeys.txt or META/apkcerts.txt.
Chris Grossfabf50a2019-05-02 12:42:09 -0700558
559 This function merges the contents of the META/apexkeys.txt or
Tao Bao2ad4b822019-06-27 16:52:12 -0700560 META/apkcerts.txt files from the framework directory and the vendor directory,
561 placing the merged result in the output directory. The precondition in that
562 the files are already extracted. The post condition is that the output
563 META/apexkeys.txt or META/apkcerts.txt contains the merged content.
Chris Grossfabf50a2019-05-02 12:42:09 -0700564
565 Args:
Daniel Normand5d70ea2019-06-05 15:13:43 -0700566 framework_target_files_dir: The name of a directory containing the special
567 items extracted from the framework target files package.
568 vendor_target_files_dir: The name of a directory containing the special
569 items extracted from the vendor target files package.
Chris Grossfabf50a2019-05-02 12:42:09 -0700570 output_target_files_dir: The name of a directory that will be used to create
571 the output target files package after all the special cases are processed.
Bill Peckham19c3feb2020-03-20 18:31:43 -0700572 framework_partition_set: Partitions that are considered framework
573 partitions. Used to filter apexkeys.txt and apkcerts.txt.
574 vendor_partition_set: Partitions that are considered vendor partitions. Used
575 to filter apexkeys.txt and apkcerts.txt.
Chris Grossfabf50a2019-05-02 12:42:09 -0700576 file_name: The name of the file to merge. One of apkcerts.txt or
577 apexkeys.txt.
578 """
579
580 def read_helper(d):
581 temp = {}
582 file_path = os.path.join(d, 'META', file_name)
583 with open(file_path) as f:
584 for line in f:
585 if line.strip():
Bill Peckham19c3feb2020-03-20 18:31:43 -0700586 name = line.split()[0]
587 match = MODULE_KEY_PATTERN.search(name)
588 temp[match.group(1)] = line.strip()
Chris Grossfabf50a2019-05-02 12:42:09 -0700589 return temp
590
Daniel Normand5d70ea2019-06-05 15:13:43 -0700591 framework_dict = read_helper(framework_target_files_dir)
592 vendor_dict = read_helper(vendor_target_files_dir)
Bill Peckham19c3feb2020-03-20 18:31:43 -0700593 merged_dict = {}
Chris Grossfabf50a2019-05-02 12:42:09 -0700594
Bill Peckham19c3feb2020-03-20 18:31:43 -0700595 def filter_into_merged_dict(item_dict, partition_set):
596 for key, value in item_dict.items():
597 match = PARTITION_TAG_PATTERN.search(value)
598
599 if match is None:
600 raise ValueError('Entry missing partition tag: %s' % value)
601
602 partition_tag = match.group(1)
603
604 if partition_tag in partition_set:
605 if key in merged_dict:
Daniel Normanb0c75912020-09-24 14:30:21 -0700606 if OPTIONS.allow_duplicate_apkapex_keys:
607 # TODO(b/150582573) Always raise on duplicates.
608 logger.warning('Duplicate key %s' % key)
609 continue
610 else:
611 raise ValueError('Duplicate key %s' % key)
Bill Peckham19c3feb2020-03-20 18:31:43 -0700612
613 merged_dict[key] = value
614
615 filter_into_merged_dict(framework_dict, framework_partition_set)
616 filter_into_merged_dict(vendor_dict, vendor_partition_set)
Chris Grossfabf50a2019-05-02 12:42:09 -0700617
618 output_file = os.path.join(output_target_files_dir, 'META', file_name)
619
Bill Peckham19c3feb2020-03-20 18:31:43 -0700620 # The following code is similar to write_sorted_data, but different enough
621 # that we couldn't use that function. We need the output to be sorted by the
622 # basename of the apex/apk (without the ".apex" or ".apk" suffix). This
623 # allows the sort to be consistent with the framework/vendor input data and
624 # eases comparison of input data with merged data.
625 with open(output_file, 'w') as output:
626 for key in sorted(merged_dict.keys()):
627 out_str = merged_dict[key] + '\n'
628 output.write(out_str)
Daniel Normana61cde02019-05-03 14:19:13 -0700629
630
Daniel Normand5d70ea2019-06-05 15:13:43 -0700631def copy_file_contexts(framework_target_files_dir, vendor_target_files_dir,
Daniel Norman72c626f2019-05-13 15:58:14 -0700632 output_target_files_dir):
633 """Creates named copies of each build's file_contexts.bin in output META/."""
Daniel Normand5d70ea2019-06-05 15:13:43 -0700634 framework_fc_path = os.path.join(framework_target_files_dir, 'META',
635 'framework_file_contexts.bin')
636 if not os.path.exists(framework_fc_path):
637 framework_fc_path = os.path.join(framework_target_files_dir, 'META',
638 'file_contexts.bin')
639 if not os.path.exists(framework_fc_path):
640 raise ValueError('Missing framework file_contexts.bin.')
641 shutil.copyfile(
642 framework_fc_path,
643 os.path.join(output_target_files_dir, 'META',
644 'framework_file_contexts.bin'))
645
646 vendor_fc_path = os.path.join(vendor_target_files_dir, 'META',
647 'vendor_file_contexts.bin')
648 if not os.path.exists(vendor_fc_path):
649 vendor_fc_path = os.path.join(vendor_target_files_dir, 'META',
Daniel Normanedf12472019-05-22 10:47:08 -0700650 'file_contexts.bin')
Daniel Normand5d70ea2019-06-05 15:13:43 -0700651 if not os.path.exists(vendor_fc_path):
652 raise ValueError('Missing vendor file_contexts.bin.')
Daniel Norman72c626f2019-05-13 15:58:14 -0700653 shutil.copyfile(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700654 vendor_fc_path,
655 os.path.join(output_target_files_dir, 'META', 'vendor_file_contexts.bin'))
Daniel Norman72c626f2019-05-13 15:58:14 -0700656
657
Daniel Normand5d70ea2019-06-05 15:13:43 -0700658def process_special_cases(framework_target_files_temp_dir,
659 vendor_target_files_temp_dir,
660 output_target_files_temp_dir,
Daniel Normanb0c75912020-09-24 14:30:21 -0700661 framework_misc_info_keys, framework_partition_set,
Bill Peckham19c3feb2020-03-20 18:31:43 -0700662 vendor_partition_set):
Tao Bao2ad4b822019-06-27 16:52:12 -0700663 """Performs special-case processing for certain target files items.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800664
665 Certain files in the output target files package require special-case
666 processing. This function performs all that special-case processing.
667
668 Args:
Daniel Normand5d70ea2019-06-05 15:13:43 -0700669 framework_target_files_temp_dir: The name of a directory containing the
670 special items extracted from the framework target files package.
671 vendor_target_files_temp_dir: The name of a directory containing the special
672 items extracted from the vendor target files package.
Daniel Normane5b134a2019-04-17 14:54:06 -0700673 output_target_files_temp_dir: The name of a directory that will be used to
674 create the output target files package after all the special cases are
675 processed.
Daniel Normand5d70ea2019-06-05 15:13:43 -0700676 framework_misc_info_keys: A list of keys to obtain from the framework
677 instance of META/misc_info.txt. The remaining keys from the vendor
678 instance.
Bill Peckham19c3feb2020-03-20 18:31:43 -0700679 framework_partition_set: Partitions that are considered framework
680 partitions. Used to filter apexkeys.txt and apkcerts.txt.
681 vendor_partition_set: Partitions that are considered vendor partitions. Used
682 to filter apexkeys.txt and apkcerts.txt.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800683 """
684
Daniel Normand5d70ea2019-06-05 15:13:43 -0700685 if 'ab_update' in framework_misc_info_keys:
Bill Peckham364c1cc2019-03-29 18:27:23 -0700686 process_ab_partitions_txt(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700687 framework_target_files_temp_dir=framework_target_files_temp_dir,
688 vendor_target_files_temp_dir=vendor_target_files_temp_dir,
Bill Peckham364c1cc2019-03-29 18:27:23 -0700689 output_target_files_temp_dir=output_target_files_temp_dir)
690
Daniel Norman72c626f2019-05-13 15:58:14 -0700691 copy_file_contexts(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700692 framework_target_files_dir=framework_target_files_temp_dir,
693 vendor_target_files_dir=vendor_target_files_temp_dir,
Daniel Norman72c626f2019-05-13 15:58:14 -0700694 output_target_files_dir=output_target_files_temp_dir)
695
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800696 process_misc_info_txt(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700697 framework_target_files_temp_dir=framework_target_files_temp_dir,
698 vendor_target_files_temp_dir=vendor_target_files_temp_dir,
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800699 output_target_files_temp_dir=output_target_files_temp_dir,
Daniel Normand5d70ea2019-06-05 15:13:43 -0700700 framework_misc_info_keys=framework_misc_info_keys)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800701
Daniel Normana61cde02019-05-03 14:19:13 -0700702 process_dynamic_partitions_info_txt(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700703 framework_target_files_dir=framework_target_files_temp_dir,
704 vendor_target_files_dir=vendor_target_files_temp_dir,
Daniel Norman714bd122019-05-08 16:20:02 -0700705 output_target_files_dir=output_target_files_temp_dir)
Daniel Normana61cde02019-05-03 14:19:13 -0700706
Chris Grossfabf50a2019-05-02 12:42:09 -0700707 process_apex_keys_apk_certs_common(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700708 framework_target_files_dir=framework_target_files_temp_dir,
709 vendor_target_files_dir=vendor_target_files_temp_dir,
Chris Grossfabf50a2019-05-02 12:42:09 -0700710 output_target_files_dir=output_target_files_temp_dir,
Bill Peckham19c3feb2020-03-20 18:31:43 -0700711 framework_partition_set=framework_partition_set,
712 vendor_partition_set=vendor_partition_set,
Chris Grossfabf50a2019-05-02 12:42:09 -0700713 file_name='apkcerts.txt')
714
715 process_apex_keys_apk_certs_common(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700716 framework_target_files_dir=framework_target_files_temp_dir,
717 vendor_target_files_dir=vendor_target_files_temp_dir,
Chris Grossfabf50a2019-05-02 12:42:09 -0700718 output_target_files_dir=output_target_files_temp_dir,
Bill Peckham19c3feb2020-03-20 18:31:43 -0700719 framework_partition_set=framework_partition_set,
720 vendor_partition_set=vendor_partition_set,
Chris Grossfabf50a2019-05-02 12:42:09 -0700721 file_name='apexkeys.txt')
722
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800723
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900724def files_from_path(target_path, extra_args=None):
Tao Bao2ad4b822019-06-27 16:52:12 -0700725 """Gets files under given path.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800726
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900727 Get (sub)files from given target path and return sorted list.
728
729 Args:
730 target_path: Target path to get subfiles.
731 extra_args: List of extra argument for find command. Optional.
732
733 Returns:
734 Sorted files and directories list.
735 """
736
737 find_command = ['find', target_path] + (extra_args or [])
738 find_process = common.Run(find_command, stdout=subprocess.PIPE, verbose=False)
Daniel Norman4cc9df62019-07-18 10:11:07 -0700739 return common.RunAndCheckOutput(['sort'],
740 stdin=find_process.stdout,
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900741 verbose=False)
742
743
744def create_merged_package(temp_dir, framework_target_files, framework_item_list,
745 vendor_target_files, vendor_item_list,
Daniel Norman4cc9df62019-07-18 10:11:07 -0700746 framework_misc_info_keys, rebuild_recovery):
Tao Bao2ad4b822019-06-27 16:52:12 -0700747 """Merges two target files packages into one target files structure.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800748
749 Args:
750 temp_dir: The name of a directory we use when we extract items from the
Daniel Normane5b134a2019-04-17 14:54:06 -0700751 input target files packages, and also a scratch directory that we use for
752 temporary files.
Daniel Normand5d70ea2019-06-05 15:13:43 -0700753 framework_target_files: The name of the zip archive containing the framework
Daniel Normane5b134a2019-04-17 14:54:06 -0700754 partial target files package.
Daniel Normand5d70ea2019-06-05 15:13:43 -0700755 framework_item_list: The list of items to extract from the partial framework
Daniel Normane5b134a2019-04-17 14:54:06 -0700756 target files package as is, meaning these items will land in the output
Daniel Normand5d70ea2019-06-05 15:13:43 -0700757 target files package exactly as they appear in the input partial framework
Daniel Normane5b134a2019-04-17 14:54:06 -0700758 target files package.
Daniel Normand5d70ea2019-06-05 15:13:43 -0700759 vendor_target_files: The name of the zip archive containing the vendor
760 partial target files package.
761 vendor_item_list: The list of items to extract from the partial vendor
762 target files package as is, meaning these items will land in the output
763 target files package exactly as they appear in the input partial vendor
Daniel Normane5b134a2019-04-17 14:54:06 -0700764 target files package.
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900765 framework_misc_info_keys: The list of keys to obtain from the framework
766 instance of META/misc_info.txt. The remaining keys from the vendor
767 instance.
Daniel Normana4911da2019-03-15 14:36:21 -0700768 rebuild_recovery: If true, rebuild the recovery patch used by non-A/B
Daniel Normane5b134a2019-04-17 14:54:06 -0700769 devices and write it to the system image.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800770
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900771 Returns:
772 Path to merged package under temp directory.
773 """
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800774
Daniel Normand5d70ea2019-06-05 15:13:43 -0700775 # Create directory names that we'll use when we extract files from framework,
776 # and vendor, and for zipping the final output.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800777
Daniel Normand5d70ea2019-06-05 15:13:43 -0700778 framework_target_files_temp_dir = os.path.join(temp_dir, 'framework')
779 vendor_target_files_temp_dir = os.path.join(temp_dir, 'vendor')
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800780 output_target_files_temp_dir = os.path.join(temp_dir, 'output')
781
Daniel Normand5d70ea2019-06-05 15:13:43 -0700782 # Extract "as is" items from the input framework partial target files package.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800783 # We extract them directly into the output temporary directory since the
784 # items do not need special case processing.
785
Bill Peckham889b0c62019-02-21 18:53:37 -0800786 extract_items(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700787 target_files=framework_target_files,
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800788 target_files_temp_dir=output_target_files_temp_dir,
Daniel Normand5d70ea2019-06-05 15:13:43 -0700789 extract_item_list=framework_item_list)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800790
Daniel Normand5d70ea2019-06-05 15:13:43 -0700791 # Extract "as is" items from the input vendor partial target files package. We
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800792 # extract them directly into the output temporary directory since the items
793 # do not need special case processing.
794
Bill Peckham889b0c62019-02-21 18:53:37 -0800795 extract_items(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700796 target_files=vendor_target_files,
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800797 target_files_temp_dir=output_target_files_temp_dir,
Daniel Normand5d70ea2019-06-05 15:13:43 -0700798 extract_item_list=vendor_item_list)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800799
Daniel Normand5d70ea2019-06-05 15:13:43 -0700800 # Extract "special" items from the input framework partial target files
801 # package. We extract these items to different directory since they require
802 # special processing before they will end up in the output directory.
803
804 extract_items(
805 target_files=framework_target_files,
806 target_files_temp_dir=framework_target_files_temp_dir,
807 extract_item_list=FRAMEWORK_EXTRACT_SPECIAL_ITEM_LIST)
808
809 # Extract "special" items from the input vendor partial target files package.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800810 # We extract these items to different directory since they require special
811 # processing before they will end up in the output directory.
812
Bill Peckham889b0c62019-02-21 18:53:37 -0800813 extract_items(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700814 target_files=vendor_target_files,
815 target_files_temp_dir=vendor_target_files_temp_dir,
816 extract_item_list=VENDOR_EXTRACT_SPECIAL_ITEM_LIST)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800817
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800818 # Now that the temporary directories contain all the extracted files, perform
819 # special case processing on any items that need it. After this function
820 # completes successfully, all the files we need to create the output target
821 # files package are in place.
822
Bill Peckham889b0c62019-02-21 18:53:37 -0800823 process_special_cases(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700824 framework_target_files_temp_dir=framework_target_files_temp_dir,
825 vendor_target_files_temp_dir=vendor_target_files_temp_dir,
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800826 output_target_files_temp_dir=output_target_files_temp_dir,
Bill Peckham19c3feb2020-03-20 18:31:43 -0700827 framework_misc_info_keys=framework_misc_info_keys,
828 framework_partition_set=item_list_to_partition_set(framework_item_list),
829 vendor_partition_set=item_list_to_partition_set(vendor_item_list))
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800830
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900831 return output_target_files_temp_dir
832
833
834def generate_images(target_files_dir, rebuild_recovery):
835 """Generate images from target files.
836
837 This function takes merged output temporary directory and create images
838 from it.
839
840 Args:
841 target_files_dir: Path to merged temp directory.
842 rebuild_recovery: If true, rebuild the recovery patch used by non-A/B
843 devices and write it to the system image.
844 """
845
846 # Regenerate IMAGES in the target directory.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800847
Daniel Normana4911da2019-03-15 14:36:21 -0700848 add_img_args = ['--verbose']
Paul Trautrimbc3600c2019-08-13 18:07:03 +0900849 add_img_args.append('--add_missing')
Bill Peckhame868aec2019-09-17 17:06:47 -0700850 # TODO(b/132730255): Remove this if statement.
Daniel Normana4911da2019-03-15 14:36:21 -0700851 if rebuild_recovery:
852 add_img_args.append('--rebuild_recovery')
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900853 add_img_args.append(target_files_dir)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800854
855 add_img_to_target_files.main(add_img_args)
856
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900857
858def generate_super_empty_image(target_dir, output_super_empty):
Tao Bao2ad4b822019-06-27 16:52:12 -0700859 """Generates super_empty image from target package.
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900860
861 Args:
862 target_dir: Path to the target file package which contains misc_info.txt for
863 detailed information for super image.
864 output_super_empty: If provided, copies a super_empty.img file from the
865 target files package to this path.
866 """
Daniel Norman1bd2a1d2019-04-18 12:32:18 -0700867 # Create super_empty.img using the merged misc_info.txt.
868
Daniel Norman4cc9df62019-07-18 10:11:07 -0700869 misc_info_txt = os.path.join(target_dir, 'META', 'misc_info.txt')
Daniel Norman1bd2a1d2019-04-18 12:32:18 -0700870
Kiyoung Kimebe7c9c2019-06-25 17:09:55 +0900871 use_dynamic_partitions = common.LoadDictionaryFromFile(misc_info_txt).get(
872 'use_dynamic_partitions')
Daniel Norman1bd2a1d2019-04-18 12:32:18 -0700873
874 if use_dynamic_partitions != 'true' and output_super_empty:
875 raise ValueError(
876 'Building super_empty.img requires use_dynamic_partitions=true.')
877 elif use_dynamic_partitions == 'true':
Daniel Norman4cc9df62019-07-18 10:11:07 -0700878 super_empty_img = os.path.join(target_dir, 'IMAGES', 'super_empty.img')
Daniel Norman1bd2a1d2019-04-18 12:32:18 -0700879 build_super_image_args = [
880 misc_info_txt,
881 super_empty_img,
882 ]
883 build_super_image.main(build_super_image_args)
884
885 # Copy super_empty.img to the user-provided output_super_empty location.
886 if output_super_empty:
887 shutil.copyfile(super_empty_img, output_super_empty)
888
Daniel Normanb8a2f9d2019-04-24 12:55:51 -0700889
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900890def create_target_files_archive(output_file, source_dir, temp_dir):
Tao Bao2ad4b822019-06-27 16:52:12 -0700891 """Creates archive from target package.
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900892
893 Args:
894 output_file: The name of the zip archive target files package.
895 source_dir: The target directory contains package to be archived.
896 temp_dir: Path to temporary directory for any intermediate files.
897 """
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800898 output_target_files_list = os.path.join(temp_dir, 'output.list')
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900899 output_zip = os.path.abspath(output_file)
Daniel Norman4cc9df62019-07-18 10:11:07 -0700900 output_target_files_meta_dir = os.path.join(source_dir, 'META')
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800901
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900902 meta_content = files_from_path(output_target_files_meta_dir)
Daniel Norman4cc9df62019-07-18 10:11:07 -0700903 other_content = files_from_path(
904 source_dir,
905 ['-path', output_target_files_meta_dir, '-prune', '-o', '-print'])
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800906
Tao Bao2ad4b822019-06-27 16:52:12 -0700907 with open(output_target_files_list, 'w') as f:
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800908 f.write(meta_content)
909 f.write(other_content)
910
911 command = [
Bill Peckhamf753e152019-02-19 18:02:46 -0800912 'soong_zip',
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800913 '-d',
Daniel Normane5b134a2019-04-17 14:54:06 -0700914 '-o',
915 output_zip,
916 '-C',
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900917 source_dir,
Daniel Normane5b134a2019-04-17 14:54:06 -0700918 '-l',
919 output_target_files_list,
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800920 ]
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900921
922 logger.info('creating %s', output_file)
Bill Peckham889b0c62019-02-21 18:53:37 -0800923 common.RunAndWait(command, verbose=True)
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900924 logger.info('finished creating %s', output_file)
925
926 return output_zip
927
928
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900929def merge_target_files(temp_dir, framework_target_files, framework_item_list,
930 framework_misc_info_keys, vendor_target_files,
931 vendor_item_list, output_target_files, output_dir,
932 output_item_list, output_ota, output_img,
933 output_super_empty, rebuild_recovery):
Tao Bao2ad4b822019-06-27 16:52:12 -0700934 """Merges two target files packages together.
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900935
936 This function takes framework and vendor target files packages as input,
937 performs various file extractions, special case processing, and finally
938 creates a merged zip archive as output.
939
940 Args:
941 temp_dir: The name of a directory we use when we extract items from the
942 input target files packages, and also a scratch directory that we use for
943 temporary files.
944 framework_target_files: The name of the zip archive containing the framework
945 partial target files package.
946 framework_item_list: The list of items to extract from the partial framework
947 target files package as is, meaning these items will land in the output
948 target files package exactly as they appear in the input partial framework
949 target files package.
950 framework_misc_info_keys: The list of keys to obtain from the framework
951 instance of META/misc_info.txt. The remaining keys from the vendor
952 instance.
953 vendor_target_files: The name of the zip archive containing the vendor
954 partial target files package.
955 vendor_item_list: The list of items to extract from the partial vendor
956 target files package as is, meaning these items will land in the output
957 target files package exactly as they appear in the input partial vendor
958 target files package.
959 output_target_files: The name of the output zip archive target files package
960 created by merging framework and vendor.
961 output_dir: The destination directory for saving merged files.
962 output_item_list: The list of items to copy into the output_dir.
963 output_ota: The name of the output zip archive ota package.
964 output_img: The name of the output zip archive img package.
965 output_super_empty: If provided, creates a super_empty.img file from the
966 merged target files package and saves it at this path.
967 rebuild_recovery: If true, rebuild the recovery patch used by non-A/B
968 devices and write it to the system image.
969 """
970
971 logger.info('starting: merge framework %s and vendor %s into output %s',
972 framework_target_files, vendor_target_files, output_target_files)
973
974 output_target_files_temp_dir = create_merged_package(
975 temp_dir, framework_target_files, framework_item_list,
976 vendor_target_files, vendor_item_list, framework_misc_info_keys,
977 rebuild_recovery)
978
Yifan Hongade0d3f2019-08-21 16:37:11 -0700979 if not check_target_files_vintf.CheckVintf(output_target_files_temp_dir):
Daniel Normanb0c75912020-09-24 14:30:21 -0700980 raise RuntimeError('Incompatible VINTF metadata')
Yifan Hongade0d3f2019-08-21 16:37:11 -0700981
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900982 generate_images(output_target_files_temp_dir, rebuild_recovery)
983
984 generate_super_empty_image(output_target_files_temp_dir, output_super_empty)
985
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900986 # Finally, create the output target files zip archive and/or copy the
987 # output items to the output target files directory.
988
989 if output_dir:
990 copy_items(output_target_files_temp_dir, output_dir, output_item_list)
991
992 if not output_target_files:
993 return
994
995 output_zip = create_target_files_archive(output_target_files,
996 output_target_files_temp_dir,
997 temp_dir)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800998
Daniel Norman74eb74b2019-09-18 14:01:48 -0700999 # Create the IMG package from the merged target files package.
1000
1001 if output_img:
1002 img_from_target_files.main([output_zip, output_img])
1003
Daniel Norman3b64ce12019-04-16 16:11:35 -07001004 # Create the OTA package from the merged target files package.
1005
1006 if output_ota:
Daniel Norman4cc9df62019-07-18 10:11:07 -07001007 ota_from_target_files.main([output_zip, output_ota])
Daniel Norman3b64ce12019-04-16 16:11:35 -07001008
Daniel Norman1bd2a1d2019-04-18 12:32:18 -07001009
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001010def call_func_with_temp_dir(func, keep_tmp):
Tao Bao2ad4b822019-06-27 16:52:12 -07001011 """Manages the creation and cleanup of the temporary directory.
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001012
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001013 This function calls the given function after first creating a temporary
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001014 directory. It also cleans up the temporary directory.
1015
1016 Args:
Daniel Normane5b134a2019-04-17 14:54:06 -07001017 func: The function to call. Should accept one parameter, the path to the
1018 temporary directory.
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001019 keep_tmp: Keep the temporary directory after processing is complete.
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001020 """
1021
1022 # Create a temporary directory. This will serve as the parent of directories
1023 # we use when we extract items from the input target files packages, and also
1024 # a scratch directory that we use for temporary files.
1025
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001026 temp_dir = common.MakeTempDir(prefix='merge_target_files_')
1027
1028 try:
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001029 func(temp_dir)
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001030 finally:
1031 if keep_tmp:
1032 logger.info('keeping %s', temp_dir)
1033 else:
1034 common.Cleanup()
1035
1036
1037def main():
1038 """The main function.
1039
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001040 Process command line arguments, then call merge_target_files to
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001041 perform the heavy lifting.
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001042 """
1043
1044 common.InitLogging()
1045
Bill Peckhamf753e152019-02-19 18:02:46 -08001046 def option_handler(o, a):
1047 if o == '--system-target-files':
Daniel Normand5d70ea2019-06-05 15:13:43 -07001048 logger.warning(
1049 '--system-target-files has been renamed to --framework-target-files')
1050 OPTIONS.framework_target_files = a
1051 elif o == '--framework-target-files':
1052 OPTIONS.framework_target_files = a
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001053 elif o == '--system-item-list':
Daniel Normand5d70ea2019-06-05 15:13:43 -07001054 logger.warning(
1055 '--system-item-list has been renamed to --framework-item-list')
1056 OPTIONS.framework_item_list = a
1057 elif o == '--framework-item-list':
1058 OPTIONS.framework_item_list = a
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001059 elif o == '--system-misc-info-keys':
Daniel Norman4cc9df62019-07-18 10:11:07 -07001060 logger.warning('--system-misc-info-keys has been renamed to '
1061 '--framework-misc-info-keys')
Daniel Normand5d70ea2019-06-05 15:13:43 -07001062 OPTIONS.framework_misc_info_keys = a
1063 elif o == '--framework-misc-info-keys':
1064 OPTIONS.framework_misc_info_keys = a
Bill Peckhamf753e152019-02-19 18:02:46 -08001065 elif o == '--other-target-files':
Daniel Normand5d70ea2019-06-05 15:13:43 -07001066 logger.warning(
1067 '--other-target-files has been renamed to --vendor-target-files')
1068 OPTIONS.vendor_target_files = a
1069 elif o == '--vendor-target-files':
1070 OPTIONS.vendor_target_files = a
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001071 elif o == '--other-item-list':
Daniel Normand5d70ea2019-06-05 15:13:43 -07001072 logger.warning('--other-item-list has been renamed to --vendor-item-list')
1073 OPTIONS.vendor_item_list = a
1074 elif o == '--vendor-item-list':
1075 OPTIONS.vendor_item_list = a
Bill Peckhamf753e152019-02-19 18:02:46 -08001076 elif o == '--output-target-files':
1077 OPTIONS.output_target_files = a
Daniel Normanfdb38812019-04-15 09:47:24 -07001078 elif o == '--output-dir':
1079 OPTIONS.output_dir = a
1080 elif o == '--output-item-list':
1081 OPTIONS.output_item_list = a
Daniel Norman3b64ce12019-04-16 16:11:35 -07001082 elif o == '--output-ota':
1083 OPTIONS.output_ota = a
Daniel Norman1bd2a1d2019-04-18 12:32:18 -07001084 elif o == '--output-img':
1085 OPTIONS.output_img = a
Daniel Normanf0318252019-04-15 11:34:56 -07001086 elif o == '--output-super-empty':
1087 OPTIONS.output_super_empty = a
Daniel Normanb0c75912020-09-24 14:30:21 -07001088 elif o == '--rebuild_recovery': # TODO(b/132730255): Warn
Daniel Normana4911da2019-03-15 14:36:21 -07001089 OPTIONS.rebuild_recovery = True
Daniel Normanb0c75912020-09-24 14:30:21 -07001090 elif o == '--allow-duplicate-apkapex-keys':
1091 OPTIONS.allow_duplicate_apkapex_keys = True
Bill Peckham364c1cc2019-03-29 18:27:23 -07001092 elif o == '--keep-tmp':
Bill Peckhamf753e152019-02-19 18:02:46 -08001093 OPTIONS.keep_tmp = True
1094 else:
1095 return False
1096 return True
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001097
Bill Peckhamf753e152019-02-19 18:02:46 -08001098 args = common.ParseOptions(
Daniel Normane5b134a2019-04-17 14:54:06 -07001099 sys.argv[1:],
1100 __doc__,
Bill Peckhamf753e152019-02-19 18:02:46 -08001101 extra_long_opts=[
1102 'system-target-files=',
Daniel Normand5d70ea2019-06-05 15:13:43 -07001103 'framework-target-files=',
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001104 'system-item-list=',
Daniel Normand5d70ea2019-06-05 15:13:43 -07001105 'framework-item-list=',
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001106 'system-misc-info-keys=',
Daniel Normand5d70ea2019-06-05 15:13:43 -07001107 'framework-misc-info-keys=',
Bill Peckhamf753e152019-02-19 18:02:46 -08001108 'other-target-files=',
Daniel Normand5d70ea2019-06-05 15:13:43 -07001109 'vendor-target-files=',
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001110 'other-item-list=',
Daniel Normand5d70ea2019-06-05 15:13:43 -07001111 'vendor-item-list=',
Bill Peckhamf753e152019-02-19 18:02:46 -08001112 'output-target-files=',
Daniel Normanfdb38812019-04-15 09:47:24 -07001113 'output-dir=',
1114 'output-item-list=',
Daniel Norman3b64ce12019-04-16 16:11:35 -07001115 'output-ota=',
Daniel Norman1bd2a1d2019-04-18 12:32:18 -07001116 'output-img=',
Daniel Normanf0318252019-04-15 11:34:56 -07001117 'output-super-empty=',
Daniel Normana4911da2019-03-15 14:36:21 -07001118 'rebuild_recovery',
Daniel Normanb0c75912020-09-24 14:30:21 -07001119 'allow-duplicate-apkapex-keys',
Bill Peckham364c1cc2019-03-29 18:27:23 -07001120 'keep-tmp',
Bill Peckhamf753e152019-02-19 18:02:46 -08001121 ],
1122 extra_option_handler=option_handler)
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001123
Tao Bao2ad4b822019-06-27 16:52:12 -07001124 # pylint: disable=too-many-boolean-expressions
Daniel Normand5d70ea2019-06-05 15:13:43 -07001125 if (args or OPTIONS.framework_target_files is None or
1126 OPTIONS.vendor_target_files is None or
Daniel Normane5b134a2019-04-17 14:54:06 -07001127 (OPTIONS.output_target_files is None and OPTIONS.output_dir is None) or
1128 (OPTIONS.output_dir is not None and OPTIONS.output_item_list is None)):
Bill Peckhamf753e152019-02-19 18:02:46 -08001129 common.Usage(__doc__)
Bill Peckham889b0c62019-02-21 18:53:37 -08001130 sys.exit(1)
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001131
Daniel Normand5d70ea2019-06-05 15:13:43 -07001132 if OPTIONS.framework_item_list:
Daniel Norman4cc9df62019-07-18 10:11:07 -07001133 framework_item_list = common.LoadListFromFile(OPTIONS.framework_item_list)
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001134 else:
Daniel Normand5d70ea2019-06-05 15:13:43 -07001135 framework_item_list = DEFAULT_FRAMEWORK_ITEM_LIST
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001136
Daniel Normand5d70ea2019-06-05 15:13:43 -07001137 if OPTIONS.framework_misc_info_keys:
Daniel Norman4cc9df62019-07-18 10:11:07 -07001138 framework_misc_info_keys = common.LoadListFromFile(
Daniel Normand5d70ea2019-06-05 15:13:43 -07001139 OPTIONS.framework_misc_info_keys)
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001140 else:
Daniel Normand5d70ea2019-06-05 15:13:43 -07001141 framework_misc_info_keys = DEFAULT_FRAMEWORK_MISC_INFO_KEYS
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001142
Daniel Normand5d70ea2019-06-05 15:13:43 -07001143 if OPTIONS.vendor_item_list:
Daniel Norman4cc9df62019-07-18 10:11:07 -07001144 vendor_item_list = common.LoadListFromFile(OPTIONS.vendor_item_list)
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001145 else:
Daniel Normand5d70ea2019-06-05 15:13:43 -07001146 vendor_item_list = DEFAULT_VENDOR_ITEM_LIST
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001147
Daniel Normanfdb38812019-04-15 09:47:24 -07001148 if OPTIONS.output_item_list:
Daniel Norman4cc9df62019-07-18 10:11:07 -07001149 output_item_list = common.LoadListFromFile(OPTIONS.output_item_list)
Daniel Normanfdb38812019-04-15 09:47:24 -07001150 else:
1151 output_item_list = None
1152
Daniel Normane5964522019-03-19 10:32:03 -07001153 if not validate_config_lists(
Daniel Normand5d70ea2019-06-05 15:13:43 -07001154 framework_item_list=framework_item_list,
1155 framework_misc_info_keys=framework_misc_info_keys,
1156 vendor_item_list=vendor_item_list):
Daniel Normane5964522019-03-19 10:32:03 -07001157 sys.exit(1)
1158
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001159 call_func_with_temp_dir(
1160 lambda temp_dir: merge_target_files(
1161 temp_dir=temp_dir,
Daniel Normand5d70ea2019-06-05 15:13:43 -07001162 framework_target_files=OPTIONS.framework_target_files,
1163 framework_item_list=framework_item_list,
1164 framework_misc_info_keys=framework_misc_info_keys,
1165 vendor_target_files=OPTIONS.vendor_target_files,
1166 vendor_item_list=vendor_item_list,
Daniel Normana4911da2019-03-15 14:36:21 -07001167 output_target_files=OPTIONS.output_target_files,
Daniel Normanfdb38812019-04-15 09:47:24 -07001168 output_dir=OPTIONS.output_dir,
1169 output_item_list=output_item_list,
Daniel Norman3b64ce12019-04-16 16:11:35 -07001170 output_ota=OPTIONS.output_ota,
Daniel Norman1bd2a1d2019-04-18 12:32:18 -07001171 output_img=OPTIONS.output_img,
Daniel Normanf0318252019-04-15 11:34:56 -07001172 output_super_empty=OPTIONS.output_super_empty,
Daniel Normane5b134a2019-04-17 14:54:06 -07001173 rebuild_recovery=OPTIONS.rebuild_recovery), OPTIONS.keep_tmp)
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001174
1175
1176if __name__ == '__main__':
Bill Peckham889b0c62019-02-21 18:53:37 -08001177 main()