blob: 0d135d625e9413f798382e577294c79477a66d65 [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
88import logging
89import os
Bill Peckham19c3feb2020-03-20 18:31:43 -070090import re
Daniel Normanfdb38812019-04-15 09:47:24 -070091import shutil
Bill Peckham540d91a2019-04-25 14:18:16 -070092import subprocess
Bill Peckhame9eb5f92019-02-01 15:52:10 -080093import sys
94import zipfile
95
Bill Peckhame9eb5f92019-02-01 15:52:10 -080096import add_img_to_target_files
Daniel Normanf0318252019-04-15 11:34:56 -070097import build_super_image
Yifan Hongade0d3f2019-08-21 16:37:11 -070098import check_target_files_vintf
Daniel Normanf0318252019-04-15 11:34:56 -070099import common
Daniel Norman1bd2a1d2019-04-18 12:32:18 -0700100import img_from_target_files
Daniel Normanb8d52a22020-10-26 17:55:00 -0700101import find_shareduid_violation
Daniel Norman3b64ce12019-04-16 16:11:35 -0700102import ota_from_target_files
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800103
104logger = logging.getLogger(__name__)
Tao Bao2ad4b822019-06-27 16:52:12 -0700105
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800106OPTIONS = common.OPTIONS
Bill Peckhamcb848172020-04-03 12:50:47 -0700107# Always turn on verbose logging.
108OPTIONS.verbose = True
Daniel Normand5d70ea2019-06-05 15:13:43 -0700109OPTIONS.framework_target_files = None
110OPTIONS.framework_item_list = None
111OPTIONS.framework_misc_info_keys = None
112OPTIONS.vendor_target_files = None
113OPTIONS.vendor_item_list = None
Bill Peckhamf753e152019-02-19 18:02:46 -0800114OPTIONS.output_target_files = None
Daniel Normanfdb38812019-04-15 09:47:24 -0700115OPTIONS.output_dir = None
116OPTIONS.output_item_list = None
Daniel Norman3b64ce12019-04-16 16:11:35 -0700117OPTIONS.output_ota = None
Daniel Norman1bd2a1d2019-04-18 12:32:18 -0700118OPTIONS.output_img = None
Daniel Normanf0318252019-04-15 11:34:56 -0700119OPTIONS.output_super_empty = None
Bill Peckhame868aec2019-09-17 17:06:47 -0700120# TODO(b/132730255): Remove this option.
Daniel Normana4911da2019-03-15 14:36:21 -0700121OPTIONS.rebuild_recovery = False
Daniel Normanb0c75912020-09-24 14:30:21 -0700122# TODO(b/150582573): Remove this option.
123OPTIONS.allow_duplicate_apkapex_keys = False
Bill Peckhamf753e152019-02-19 18:02:46 -0800124OPTIONS.keep_tmp = False
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800125
Bill Peckham19c3feb2020-03-20 18:31:43 -0700126# In an item list (framework or vendor), we may see entries that select whole
127# partitions. Such an entry might look like this 'SYSTEM/*' (e.g., for the
128# system partition). The following regex matches this and extracts the
129# partition name.
130
131PARTITION_ITEM_PATTERN = re.compile(r'^([A-Z_]+)/\*$')
132
Bill Peckham5c7b0342020-04-03 15:36:23 -0700133# In apexkeys.txt or apkcerts.txt, we will find partition tags on each entry in
134# the file. We use these partition tags to filter the entries in those files
135# from the two different target files packages to produce a merged apexkeys.txt
136# or apkcerts.txt file. A partition tag (e.g., for the product partition) looks
137# like this: 'partition="product"'. We use the group syntax grab the value of
138# the tag. We use non-greedy matching in case there are other fields on the
139# same line.
Bill Peckham19c3feb2020-03-20 18:31:43 -0700140
Bill Peckham5c7b0342020-04-03 15:36:23 -0700141PARTITION_TAG_PATTERN = re.compile(r'partition="(.*?)"')
Bill Peckham19c3feb2020-03-20 18:31:43 -0700142
143# The sorting algorithm for apexkeys.txt and apkcerts.txt does not include the
144# ".apex" or ".apk" suffix, so we use the following pattern to extract a key.
145
146MODULE_KEY_PATTERN = re.compile(r'name="(.+)\.(apex|apk)"')
147
Daniel Normand5d70ea2019-06-05 15:13:43 -0700148# DEFAULT_FRAMEWORK_ITEM_LIST is a list of items to extract from the partial
149# framework target files package as is, meaning these items will land in the
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800150# output target files package exactly as they appear in the input partial
Daniel Normand5d70ea2019-06-05 15:13:43 -0700151# framework target files package.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800152
Daniel Normand5d70ea2019-06-05 15:13:43 -0700153DEFAULT_FRAMEWORK_ITEM_LIST = (
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800154 'META/apkcerts.txt',
155 'META/filesystem_config.txt',
156 'META/root_filesystem_config.txt',
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800157 'META/update_engine_config.txt',
158 'PRODUCT/*',
159 'ROOT/*',
160 'SYSTEM/*',
Daniel Normanedf12472019-05-22 10:47:08 -0700161)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800162
Daniel Normand5d70ea2019-06-05 15:13:43 -0700163# DEFAULT_FRAMEWORK_MISC_INFO_KEYS is a list of keys to obtain from the
Daniel Normandbbf5a32020-10-22 16:03:32 -0700164# framework instance of META/misc_info.txt. The remaining keys should come
165# from the vendor instance.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800166
Daniel Normand5d70ea2019-06-05 15:13:43 -0700167DEFAULT_FRAMEWORK_MISC_INFO_KEYS = (
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800168 'avb_system_hashtree_enable',
169 'avb_system_add_hashtree_footer_args',
170 'avb_system_key_path',
171 'avb_system_algorithm',
172 'avb_system_rollback_index_location',
173 'avb_product_hashtree_enable',
174 'avb_product_add_hashtree_footer_args',
Justin Yun6151e3f2019-06-25 15:58:13 +0900175 'avb_system_ext_hashtree_enable',
176 'avb_system_ext_add_hashtree_footer_args',
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800177 'system_root_image',
178 'root_dir',
179 'ab_update',
180 'default_system_dev_certificate',
181 'system_size',
Chris Gross203191b2020-05-30 02:39:12 +0000182 'building_system_image',
183 'building_system_ext_image',
184 'building_product_image',
Daniel Normanedf12472019-05-22 10:47:08 -0700185)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800186
Daniel Normand5d70ea2019-06-05 15:13:43 -0700187# DEFAULT_VENDOR_ITEM_LIST is a list of items to extract from the partial
188# vendor target files package as is, meaning these items will land in the output
189# target files package exactly as they appear in the input partial vendor target
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800190# files package.
191
Daniel Normand5d70ea2019-06-05 15:13:43 -0700192DEFAULT_VENDOR_ITEM_LIST = (
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800193 'META/boot_filesystem_config.txt',
194 'META/otakeys.txt',
195 'META/releasetools.py',
196 'META/vendor_filesystem_config.txt',
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800197 'BOOT/*',
198 'DATA/*',
199 'ODM/*',
200 'OTA/android-info.txt',
201 'PREBUILT_IMAGES/*',
202 'RADIO/*',
203 'VENDOR/*',
Daniel Normanedf12472019-05-22 10:47:08 -0700204)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800205
Daniel Normanedf12472019-05-22 10:47:08 -0700206# The merge config lists should not attempt to extract items from both
207# builds for any of the following partitions. The partitions in
208# SINGLE_BUILD_PARTITIONS should come entirely from a single build (either
Daniel Normand5d70ea2019-06-05 15:13:43 -0700209# framework or vendor, but not both).
Daniel Normanedf12472019-05-22 10:47:08 -0700210
211SINGLE_BUILD_PARTITIONS = (
212 'BOOT/',
213 'DATA/',
214 'ODM/',
215 'PRODUCT/',
Justin Yun6151e3f2019-06-25 15:58:13 +0900216 'SYSTEM_EXT/',
Daniel Normanedf12472019-05-22 10:47:08 -0700217 'RADIO/',
218 'RECOVERY/',
219 'ROOT/',
220 'SYSTEM/',
221 'SYSTEM_OTHER/',
222 'VENDOR/',
Yifan Hongcfb917a2020-05-07 14:58:20 -0700223 'VENDOR_DLKM/',
Yifan Hongf496f1b2020-07-15 16:52:59 -0700224 'ODM_DLKM/',
Daniel Normanedf12472019-05-22 10:47:08 -0700225)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800226
227
Chris Grossfabf50a2019-05-02 12:42:09 -0700228def write_sorted_data(data, path):
Tao Bao2ad4b822019-06-27 16:52:12 -0700229 """Writes the sorted contents of either a list or dict to file.
Chris Grossfabf50a2019-05-02 12:42:09 -0700230
Tao Bao2ad4b822019-06-27 16:52:12 -0700231 This function sorts the contents of the list or dict and then writes the
232 resulting sorted contents to a file specified by path.
Chris Grossfabf50a2019-05-02 12:42:09 -0700233
234 Args:
235 data: The list or dict to sort and write.
236 path: Path to the file to write the sorted values to. The file at path will
237 be overridden if it exists.
238 """
239 with open(path, 'w') as output:
Daniel Normand5d70ea2019-06-05 15:13:43 -0700240 for entry in sorted(data):
Chris Grossfabf50a2019-05-02 12:42:09 -0700241 out_str = '{}={}\n'.format(entry, data[entry]) if isinstance(
242 data, dict) else '{}\n'.format(entry)
243 output.write(out_str)
244
245
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800246def extract_items(target_files, target_files_temp_dir, extract_item_list):
Tao Bao2ad4b822019-06-27 16:52:12 -0700247 """Extracts items from target files to temporary directory.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800248
249 This function extracts from the specified target files zip archive into the
250 specified temporary directory, the items specified in the extract item list.
251
252 Args:
253 target_files: The target files zip archive from which to extract items.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800254 target_files_temp_dir: The temporary directory where the extracted items
Daniel Normane5b134a2019-04-17 14:54:06 -0700255 will land.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800256 extract_item_list: A list of items to extract.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800257 """
258
259 logger.info('extracting from %s', target_files)
260
261 # Filter the extract_item_list to remove any items that do not exist in the
262 # zip file. Otherwise, the extraction step will fail.
263
Daniel Norman4cc9df62019-07-18 10:11:07 -0700264 with zipfile.ZipFile(target_files, allowZip64=True) as target_files_zipfile:
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800265 target_files_namelist = target_files_zipfile.namelist()
266
267 filtered_extract_item_list = []
268 for pattern in extract_item_list:
269 matching_namelist = fnmatch.filter(target_files_namelist, pattern)
270 if not matching_namelist:
271 logger.warning('no match for %s', pattern)
272 else:
273 filtered_extract_item_list.append(pattern)
274
Bill Peckham8ff3fbd2019-02-22 10:57:43 -0800275 # Extract from target_files into target_files_temp_dir the
276 # filtered_extract_item_list.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800277
Daniel Normane5b134a2019-04-17 14:54:06 -0700278 common.UnzipToDir(target_files, target_files_temp_dir,
279 filtered_extract_item_list)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800280
281
Daniel Normanfdb38812019-04-15 09:47:24 -0700282def copy_items(from_dir, to_dir, patterns):
283 """Similar to extract_items() except uses an input dir instead of zip."""
284 file_paths = []
285 for dirpath, _, filenames in os.walk(from_dir):
Daniel Normane5b134a2019-04-17 14:54:06 -0700286 file_paths.extend(
287 os.path.relpath(path=os.path.join(dirpath, filename), start=from_dir)
288 for filename in filenames)
Daniel Normanfdb38812019-04-15 09:47:24 -0700289
290 filtered_file_paths = set()
291 for pattern in patterns:
292 filtered_file_paths.update(fnmatch.filter(file_paths, pattern))
293
294 for file_path in filtered_file_paths:
295 original_file_path = os.path.join(from_dir, file_path)
296 copied_file_path = os.path.join(to_dir, file_path)
297 copied_file_dir = os.path.dirname(copied_file_path)
298 if not os.path.exists(copied_file_dir):
299 os.makedirs(copied_file_dir)
300 if os.path.islink(original_file_path):
301 os.symlink(os.readlink(original_file_path), copied_file_path)
302 else:
303 shutil.copyfile(original_file_path, copied_file_path)
304
305
Daniel Normand5d70ea2019-06-05 15:13:43 -0700306def validate_config_lists(framework_item_list, framework_misc_info_keys,
307 vendor_item_list):
Daniel Normane5964522019-03-19 10:32:03 -0700308 """Performs validations on the merge config lists.
309
310 Args:
Daniel Normand5d70ea2019-06-05 15:13:43 -0700311 framework_item_list: The list of items to extract from the partial framework
Daniel Normane5b134a2019-04-17 14:54:06 -0700312 target files package as is.
Daniel Normand5d70ea2019-06-05 15:13:43 -0700313 framework_misc_info_keys: A list of keys to obtain from the framework
Daniel Normandbbf5a32020-10-22 16:03:32 -0700314 instance of META/misc_info.txt. The remaining keys should come from the
315 vendor instance.
Daniel Normand5d70ea2019-06-05 15:13:43 -0700316 vendor_item_list: The list of items to extract from the partial vendor
317 target files package as is.
Daniel Normane5964522019-03-19 10:32:03 -0700318
319 Returns:
320 False if a validation fails, otherwise true.
321 """
Daniel Normanedf12472019-05-22 10:47:08 -0700322 has_error = False
323
Daniel Normand5d70ea2019-06-05 15:13:43 -0700324 default_combined_item_set = set(DEFAULT_FRAMEWORK_ITEM_LIST)
325 default_combined_item_set.update(DEFAULT_VENDOR_ITEM_LIST)
Daniel Normane5964522019-03-19 10:32:03 -0700326
Daniel Normand5d70ea2019-06-05 15:13:43 -0700327 combined_item_set = set(framework_item_list)
328 combined_item_set.update(vendor_item_list)
Daniel Normane5964522019-03-19 10:32:03 -0700329
330 # Check that the merge config lists are not missing any item specified
331 # by the default config lists.
332 difference = default_combined_item_set.difference(combined_item_set)
333 if difference:
Daniel Normane5b134a2019-04-17 14:54:06 -0700334 logger.error('Missing merge config items: %s', list(difference))
Daniel Normane5964522019-03-19 10:32:03 -0700335 logger.error('Please ensure missing items are in either the '
Daniel Normand5d70ea2019-06-05 15:13:43 -0700336 'framework-item-list or vendor-item-list files provided to '
Daniel Normane5964522019-03-19 10:32:03 -0700337 'this script.')
Daniel Normanedf12472019-05-22 10:47:08 -0700338 has_error = True
339
Daniel Normandbbf5a32020-10-22 16:03:32 -0700340 # Check that partitions only come from one input.
Daniel Normanedf12472019-05-22 10:47:08 -0700341 for partition in SINGLE_BUILD_PARTITIONS:
Daniel Normandbbf5a32020-10-22 16:03:32 -0700342 image_path = 'IMAGES/{}.img'.format(partition.lower().replace('/', ''))
343 in_framework = (
344 any(item.startswith(partition) for item in framework_item_list) or
345 image_path in framework_item_list)
346 in_vendor = (
347 any(item.startswith(partition) for item in vendor_item_list) or
348 image_path in vendor_item_list)
Daniel Normand5d70ea2019-06-05 15:13:43 -0700349 if in_framework and in_vendor:
Daniel Normanedf12472019-05-22 10:47:08 -0700350 logger.error(
Tao Bao2ad4b822019-06-27 16:52:12 -0700351 'Cannot extract items from %s for both the framework and vendor'
Kiyoung Kimebe7c9c2019-06-25 17:09:55 +0900352 ' builds. Please ensure only one merge config item list'
Tao Bao2ad4b822019-06-27 16:52:12 -0700353 ' includes %s.', partition, partition)
Daniel Normanedf12472019-05-22 10:47:08 -0700354 has_error = True
Daniel Normane5964522019-03-19 10:32:03 -0700355
Daniel Normand5d70ea2019-06-05 15:13:43 -0700356 if ('dynamic_partition_list' in framework_misc_info_keys) or (
357 'super_partition_groups' in framework_misc_info_keys):
Daniel Norman19b9fe92019-03-19 14:48:02 -0700358 logger.error('Dynamic partition misc info keys should come from '
Daniel Normand5d70ea2019-06-05 15:13:43 -0700359 'the vendor instance of META/misc_info.txt.')
Daniel Normanedf12472019-05-22 10:47:08 -0700360 has_error = True
Daniel Norman19b9fe92019-03-19 14:48:02 -0700361
Daniel Normanedf12472019-05-22 10:47:08 -0700362 return not has_error
Daniel Normane5964522019-03-19 10:32:03 -0700363
364
Daniel Normand5d70ea2019-06-05 15:13:43 -0700365def process_ab_partitions_txt(framework_target_files_temp_dir,
366 vendor_target_files_temp_dir,
Daniel Normane5b134a2019-04-17 14:54:06 -0700367 output_target_files_temp_dir):
Tao Bao2ad4b822019-06-27 16:52:12 -0700368 """Performs special processing for META/ab_partitions.txt.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800369
Tao Bao2ad4b822019-06-27 16:52:12 -0700370 This function merges the contents of the META/ab_partitions.txt files from the
371 framework directory and the vendor directory, placing the merged result in the
372 output directory. The precondition in that the files are already extracted.
373 The post condition is that the output META/ab_partitions.txt contains the
Daniel Normandbbf5a32020-10-22 16:03:32 -0700374 merged content. The format for each ab_partitions.txt is one partition name
375 per line. The output file contains the union of the partition names.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800376
377 Args:
Daniel Normand5d70ea2019-06-05 15:13:43 -0700378 framework_target_files_temp_dir: The name of a directory containing the
379 special items extracted from the framework target files package.
380 vendor_target_files_temp_dir: The name of a directory containing the special
381 items extracted from the vendor target files package.
Daniel Normane5b134a2019-04-17 14:54:06 -0700382 output_target_files_temp_dir: The name of a directory that will be used to
383 create the output target files package after all the special cases are
384 processed.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800385 """
386
Daniel Normand5d70ea2019-06-05 15:13:43 -0700387 framework_ab_partitions_txt = os.path.join(framework_target_files_temp_dir,
388 'META', 'ab_partitions.txt')
389
390 vendor_ab_partitions_txt = os.path.join(vendor_target_files_temp_dir, 'META',
Daniel Normane5b134a2019-04-17 14:54:06 -0700391 'ab_partitions.txt')
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800392
Daniel Normand5d70ea2019-06-05 15:13:43 -0700393 with open(framework_ab_partitions_txt) as f:
394 framework_ab_partitions = f.read().splitlines()
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800395
Daniel Normand5d70ea2019-06-05 15:13:43 -0700396 with open(vendor_ab_partitions_txt) as f:
397 vendor_ab_partitions = f.read().splitlines()
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800398
Daniel Normand5d70ea2019-06-05 15:13:43 -0700399 output_ab_partitions = set(framework_ab_partitions + vendor_ab_partitions)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800400
Daniel Normane5b134a2019-04-17 14:54:06 -0700401 output_ab_partitions_txt = os.path.join(output_target_files_temp_dir, 'META',
402 'ab_partitions.txt')
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800403
Chris Grossfabf50a2019-05-02 12:42:09 -0700404 write_sorted_data(data=output_ab_partitions, path=output_ab_partitions_txt)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800405
406
Daniel Normand5d70ea2019-06-05 15:13:43 -0700407def process_misc_info_txt(framework_target_files_temp_dir,
408 vendor_target_files_temp_dir,
409 output_target_files_temp_dir,
410 framework_misc_info_keys):
Tao Bao2ad4b822019-06-27 16:52:12 -0700411 """Performs special processing for META/misc_info.txt.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800412
413 This function merges the contents of the META/misc_info.txt files from the
Daniel Normand5d70ea2019-06-05 15:13:43 -0700414 framework directory and the vendor directory, placing the merged result in the
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800415 output directory. The precondition in that the files are already extracted.
416 The post condition is that the output META/misc_info.txt contains the merged
417 content.
418
419 Args:
Daniel Normand5d70ea2019-06-05 15:13:43 -0700420 framework_target_files_temp_dir: The name of a directory containing the
421 special items extracted from the framework target files package.
422 vendor_target_files_temp_dir: The name of a directory containing the special
423 items extracted from the vendor target files package.
Daniel Normane5b134a2019-04-17 14:54:06 -0700424 output_target_files_temp_dir: The name of a directory that will be used to
425 create the output target files package after all the special cases are
426 processed.
Daniel Normand5d70ea2019-06-05 15:13:43 -0700427 framework_misc_info_keys: A list of keys to obtain from the framework
Daniel Normandbbf5a32020-10-22 16:03:32 -0700428 instance of META/misc_info.txt. The remaining keys should come from the
429 vendor instance.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800430 """
431
Kiyoung Kimebe7c9c2019-06-25 17:09:55 +0900432 misc_info_path = ['META', 'misc_info.txt']
433 framework_dict = common.LoadDictionaryFromFile(
434 os.path.join(framework_target_files_temp_dir, *misc_info_path))
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800435
Daniel Normand5d70ea2019-06-05 15:13:43 -0700436 # We take most of the misc info from the vendor target files.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800437
Kiyoung Kimebe7c9c2019-06-25 17:09:55 +0900438 merged_dict = common.LoadDictionaryFromFile(
439 os.path.join(vendor_target_files_temp_dir, *misc_info_path))
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800440
Daniel Normand5d70ea2019-06-05 15:13:43 -0700441 # Replace certain values in merged_dict with values from
442 # framework_dict.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800443
Daniel Normand5d70ea2019-06-05 15:13:43 -0700444 for key in framework_misc_info_keys:
445 merged_dict[key] = framework_dict[key]
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800446
Daniel Norman19b9fe92019-03-19 14:48:02 -0700447 # Merge misc info keys used for Dynamic Partitions.
Daniel Normand5d70ea2019-06-05 15:13:43 -0700448 if (merged_dict.get('use_dynamic_partitions') == 'true') and (
449 framework_dict.get('use_dynamic_partitions') == 'true'):
Daniel Normanbfc51ef2019-07-24 14:34:54 -0700450 merged_dynamic_partitions_dict = common.MergeDynamicPartitionInfoDicts(
Daniel Norman55417142019-11-25 16:04:36 -0800451 framework_dict=framework_dict, vendor_dict=merged_dict)
Daniel Normand5d70ea2019-06-05 15:13:43 -0700452 merged_dict.update(merged_dynamic_partitions_dict)
Tao Bao48a2feb2019-06-28 11:00:05 -0700453 # Ensure that add_img_to_target_files rebuilds super split images for
454 # devices that retrofit dynamic partitions. This flag may have been set to
455 # false in the partial builds to prevent duplicate building of super.img.
Daniel Norman0bf940c2019-06-10 12:50:19 -0700456 merged_dict['build_super_partition'] = 'true'
Daniel Norman19b9fe92019-03-19 14:48:02 -0700457
Daniel Normand5d70ea2019-06-05 15:13:43 -0700458 # Replace <image>_selinux_fc values with framework or vendor file_contexts.bin
Daniel Norman72c626f2019-05-13 15:58:14 -0700459 # depending on which dictionary the key came from.
460 # Only the file basename is required because all selinux_fc properties are
461 # replaced with the full path to the file under META/ when misc_info.txt is
462 # loaded from target files for repacking. See common.py LoadInfoDict().
Daniel Normand5d70ea2019-06-05 15:13:43 -0700463 for key in merged_dict:
Daniel Norman72c626f2019-05-13 15:58:14 -0700464 if key.endswith('_selinux_fc'):
Daniel Normand5d70ea2019-06-05 15:13:43 -0700465 merged_dict[key] = 'vendor_file_contexts.bin'
466 for key in framework_dict:
Daniel Norman72c626f2019-05-13 15:58:14 -0700467 if key.endswith('_selinux_fc'):
Daniel Normand5d70ea2019-06-05 15:13:43 -0700468 merged_dict[key] = 'framework_file_contexts.bin'
Daniel Norman72c626f2019-05-13 15:58:14 -0700469
Daniel Normane5b134a2019-04-17 14:54:06 -0700470 output_misc_info_txt = os.path.join(output_target_files_temp_dir, 'META',
471 'misc_info.txt')
Daniel Normand5d70ea2019-06-05 15:13:43 -0700472 write_sorted_data(data=merged_dict, path=output_misc_info_txt)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800473
474
Daniel Normand5d70ea2019-06-05 15:13:43 -0700475def process_dynamic_partitions_info_txt(framework_target_files_dir,
476 vendor_target_files_dir,
Daniel Normana61cde02019-05-03 14:19:13 -0700477 output_target_files_dir):
Tao Bao2ad4b822019-06-27 16:52:12 -0700478 """Performs special processing for META/dynamic_partitions_info.txt.
Daniel Normana61cde02019-05-03 14:19:13 -0700479
480 This function merges the contents of the META/dynamic_partitions_info.txt
Daniel Normand5d70ea2019-06-05 15:13:43 -0700481 files from the framework directory and the vendor directory, placing the
482 merged result in the output directory.
Daniel Normana61cde02019-05-03 14:19:13 -0700483
Daniel Normand5d70ea2019-06-05 15:13:43 -0700484 This function does nothing if META/dynamic_partitions_info.txt from the vendor
Daniel Normana61cde02019-05-03 14:19:13 -0700485 directory does not exist.
486
487 Args:
Daniel Normand5d70ea2019-06-05 15:13:43 -0700488 framework_target_files_dir: The name of a directory containing the special
489 items extracted from the framework target files package.
490 vendor_target_files_dir: The name of a directory containing the special
491 items extracted from the vendor target files package.
Daniel Normana61cde02019-05-03 14:19:13 -0700492 output_target_files_dir: The name of a directory that will be used to create
493 the output target files package after all the special cases are processed.
494 """
495
496 if not os.path.exists(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700497 os.path.join(vendor_target_files_dir, 'META',
Daniel Normana61cde02019-05-03 14:19:13 -0700498 'dynamic_partitions_info.txt')):
499 return
500
Kiyoung Kimebe7c9c2019-06-25 17:09:55 +0900501 dynamic_partitions_info_path = ['META', 'dynamic_partitions_info.txt']
Daniel Normana61cde02019-05-03 14:19:13 -0700502
Kiyoung Kimebe7c9c2019-06-25 17:09:55 +0900503 framework_dynamic_partitions_dict = common.LoadDictionaryFromFile(
504 os.path.join(framework_target_files_dir, *dynamic_partitions_info_path))
505 vendor_dynamic_partitions_dict = common.LoadDictionaryFromFile(
506 os.path.join(vendor_target_files_dir, *dynamic_partitions_info_path))
Daniel Normana61cde02019-05-03 14:19:13 -0700507
Daniel Normanbfc51ef2019-07-24 14:34:54 -0700508 merged_dynamic_partitions_dict = common.MergeDynamicPartitionInfoDicts(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700509 framework_dict=framework_dynamic_partitions_dict,
Daniel Norman55417142019-11-25 16:04:36 -0800510 vendor_dict=vendor_dynamic_partitions_dict)
Daniel Normana61cde02019-05-03 14:19:13 -0700511
512 output_dynamic_partitions_info_txt = os.path.join(
513 output_target_files_dir, 'META', 'dynamic_partitions_info.txt')
Chris Grossfabf50a2019-05-02 12:42:09 -0700514 write_sorted_data(
515 data=merged_dynamic_partitions_dict,
516 path=output_dynamic_partitions_info_txt)
517
518
Bill Peckham19c3feb2020-03-20 18:31:43 -0700519def item_list_to_partition_set(item_list):
520 """Converts a target files item list to a partition set.
521
522 The item list contains items that might look like 'SYSTEM/*' or 'VENDOR/*' or
523 'OTA/android-info.txt'. Items that end in '/*' are assumed to match entire
524 directories where 'SYSTEM' or 'VENDOR' is a directory name that identifies the
525 contents of a partition of the same name. Other items in the list, such as the
526 'OTA' example contain metadata. This function iterates such a list, returning
527 a set that contains the partition entries.
528
529 Args:
530 item_list: A list of items in a target files package.
Daniel Normanb0c75912020-09-24 14:30:21 -0700531
Bill Peckham19c3feb2020-03-20 18:31:43 -0700532 Returns:
533 A set of partitions extracted from the list of items.
534 """
535
536 partition_set = set()
537
538 for item in item_list:
539 match = PARTITION_ITEM_PATTERN.search(item.strip())
540 partition_tag = match.group(1).lower() if match else None
541
542 if partition_tag:
543 partition_set.add(partition_tag)
544
545 return partition_set
546
547
Daniel Normand5d70ea2019-06-05 15:13:43 -0700548def process_apex_keys_apk_certs_common(framework_target_files_dir,
549 vendor_target_files_dir,
Bill Peckham19c3feb2020-03-20 18:31:43 -0700550 output_target_files_dir,
551 framework_partition_set,
552 vendor_partition_set, file_name):
Tao Bao2ad4b822019-06-27 16:52:12 -0700553 """Performs special processing for META/apexkeys.txt or META/apkcerts.txt.
Chris Grossfabf50a2019-05-02 12:42:09 -0700554
555 This function merges the contents of the META/apexkeys.txt or
Tao Bao2ad4b822019-06-27 16:52:12 -0700556 META/apkcerts.txt files from the framework directory and the vendor directory,
557 placing the merged result in the output directory. The precondition in that
558 the files are already extracted. The post condition is that the output
559 META/apexkeys.txt or META/apkcerts.txt contains the merged content.
Chris Grossfabf50a2019-05-02 12:42:09 -0700560
561 Args:
Daniel Normand5d70ea2019-06-05 15:13:43 -0700562 framework_target_files_dir: The name of a directory containing the special
563 items extracted from the framework target files package.
564 vendor_target_files_dir: The name of a directory containing the special
565 items extracted from the vendor target files package.
Chris Grossfabf50a2019-05-02 12:42:09 -0700566 output_target_files_dir: The name of a directory that will be used to create
567 the output target files package after all the special cases are processed.
Bill Peckham19c3feb2020-03-20 18:31:43 -0700568 framework_partition_set: Partitions that are considered framework
569 partitions. Used to filter apexkeys.txt and apkcerts.txt.
570 vendor_partition_set: Partitions that are considered vendor partitions. Used
571 to filter apexkeys.txt and apkcerts.txt.
Chris Grossfabf50a2019-05-02 12:42:09 -0700572 file_name: The name of the file to merge. One of apkcerts.txt or
573 apexkeys.txt.
574 """
575
576 def read_helper(d):
577 temp = {}
578 file_path = os.path.join(d, 'META', file_name)
579 with open(file_path) as f:
580 for line in f:
581 if line.strip():
Bill Peckham19c3feb2020-03-20 18:31:43 -0700582 name = line.split()[0]
583 match = MODULE_KEY_PATTERN.search(name)
584 temp[match.group(1)] = line.strip()
Chris Grossfabf50a2019-05-02 12:42:09 -0700585 return temp
586
Daniel Normand5d70ea2019-06-05 15:13:43 -0700587 framework_dict = read_helper(framework_target_files_dir)
588 vendor_dict = read_helper(vendor_target_files_dir)
Bill Peckham19c3feb2020-03-20 18:31:43 -0700589 merged_dict = {}
Chris Grossfabf50a2019-05-02 12:42:09 -0700590
Bill Peckham19c3feb2020-03-20 18:31:43 -0700591 def filter_into_merged_dict(item_dict, partition_set):
592 for key, value in item_dict.items():
593 match = PARTITION_TAG_PATTERN.search(value)
594
595 if match is None:
596 raise ValueError('Entry missing partition tag: %s' % value)
597
598 partition_tag = match.group(1)
599
600 if partition_tag in partition_set:
601 if key in merged_dict:
Daniel Normanb0c75912020-09-24 14:30:21 -0700602 if OPTIONS.allow_duplicate_apkapex_keys:
603 # TODO(b/150582573) Always raise on duplicates.
604 logger.warning('Duplicate key %s' % key)
605 continue
606 else:
607 raise ValueError('Duplicate key %s' % key)
Bill Peckham19c3feb2020-03-20 18:31:43 -0700608
609 merged_dict[key] = value
610
611 filter_into_merged_dict(framework_dict, framework_partition_set)
612 filter_into_merged_dict(vendor_dict, vendor_partition_set)
Chris Grossfabf50a2019-05-02 12:42:09 -0700613
614 output_file = os.path.join(output_target_files_dir, 'META', file_name)
615
Bill Peckham19c3feb2020-03-20 18:31:43 -0700616 # The following code is similar to write_sorted_data, but different enough
617 # that we couldn't use that function. We need the output to be sorted by the
618 # basename of the apex/apk (without the ".apex" or ".apk" suffix). This
619 # allows the sort to be consistent with the framework/vendor input data and
620 # eases comparison of input data with merged data.
621 with open(output_file, 'w') as output:
622 for key in sorted(merged_dict.keys()):
623 out_str = merged_dict[key] + '\n'
624 output.write(out_str)
Daniel Normana61cde02019-05-03 14:19:13 -0700625
626
Daniel Normand5d70ea2019-06-05 15:13:43 -0700627def copy_file_contexts(framework_target_files_dir, vendor_target_files_dir,
Daniel Norman72c626f2019-05-13 15:58:14 -0700628 output_target_files_dir):
629 """Creates named copies of each build's file_contexts.bin in output META/."""
Daniel Normand5d70ea2019-06-05 15:13:43 -0700630 framework_fc_path = os.path.join(framework_target_files_dir, 'META',
631 'framework_file_contexts.bin')
632 if not os.path.exists(framework_fc_path):
633 framework_fc_path = os.path.join(framework_target_files_dir, 'META',
634 'file_contexts.bin')
635 if not os.path.exists(framework_fc_path):
636 raise ValueError('Missing framework file_contexts.bin.')
637 shutil.copyfile(
638 framework_fc_path,
639 os.path.join(output_target_files_dir, 'META',
640 'framework_file_contexts.bin'))
641
642 vendor_fc_path = os.path.join(vendor_target_files_dir, 'META',
643 'vendor_file_contexts.bin')
644 if not os.path.exists(vendor_fc_path):
645 vendor_fc_path = os.path.join(vendor_target_files_dir, 'META',
Daniel Normanedf12472019-05-22 10:47:08 -0700646 'file_contexts.bin')
Daniel Normand5d70ea2019-06-05 15:13:43 -0700647 if not os.path.exists(vendor_fc_path):
648 raise ValueError('Missing vendor file_contexts.bin.')
Daniel Norman72c626f2019-05-13 15:58:14 -0700649 shutil.copyfile(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700650 vendor_fc_path,
651 os.path.join(output_target_files_dir, 'META', 'vendor_file_contexts.bin'))
Daniel Norman72c626f2019-05-13 15:58:14 -0700652
653
Daniel Normand5d70ea2019-06-05 15:13:43 -0700654def process_special_cases(framework_target_files_temp_dir,
655 vendor_target_files_temp_dir,
656 output_target_files_temp_dir,
Daniel Normanb0c75912020-09-24 14:30:21 -0700657 framework_misc_info_keys, framework_partition_set,
Bill Peckham19c3feb2020-03-20 18:31:43 -0700658 vendor_partition_set):
Tao Bao2ad4b822019-06-27 16:52:12 -0700659 """Performs special-case processing for certain target files items.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800660
661 Certain files in the output target files package require special-case
662 processing. This function performs all that special-case processing.
663
664 Args:
Daniel Normand5d70ea2019-06-05 15:13:43 -0700665 framework_target_files_temp_dir: The name of a directory containing the
666 special items extracted from the framework target files package.
667 vendor_target_files_temp_dir: The name of a directory containing the special
668 items extracted from the vendor target files package.
Daniel Normane5b134a2019-04-17 14:54:06 -0700669 output_target_files_temp_dir: The name of a directory that will be used to
670 create the output target files package after all the special cases are
671 processed.
Daniel Normand5d70ea2019-06-05 15:13:43 -0700672 framework_misc_info_keys: A list of keys to obtain from the framework
Daniel Normandbbf5a32020-10-22 16:03:32 -0700673 instance of META/misc_info.txt. The remaining keys should come from the
674 vendor instance.
Bill Peckham19c3feb2020-03-20 18:31:43 -0700675 framework_partition_set: Partitions that are considered framework
676 partitions. Used to filter apexkeys.txt and apkcerts.txt.
677 vendor_partition_set: Partitions that are considered vendor partitions. Used
678 to filter apexkeys.txt and apkcerts.txt.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800679 """
680
Daniel Normand5d70ea2019-06-05 15:13:43 -0700681 if 'ab_update' in framework_misc_info_keys:
Bill Peckham364c1cc2019-03-29 18:27:23 -0700682 process_ab_partitions_txt(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700683 framework_target_files_temp_dir=framework_target_files_temp_dir,
684 vendor_target_files_temp_dir=vendor_target_files_temp_dir,
Bill Peckham364c1cc2019-03-29 18:27:23 -0700685 output_target_files_temp_dir=output_target_files_temp_dir)
686
Daniel Norman72c626f2019-05-13 15:58:14 -0700687 copy_file_contexts(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700688 framework_target_files_dir=framework_target_files_temp_dir,
689 vendor_target_files_dir=vendor_target_files_temp_dir,
Daniel Norman72c626f2019-05-13 15:58:14 -0700690 output_target_files_dir=output_target_files_temp_dir)
691
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800692 process_misc_info_txt(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700693 framework_target_files_temp_dir=framework_target_files_temp_dir,
694 vendor_target_files_temp_dir=vendor_target_files_temp_dir,
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800695 output_target_files_temp_dir=output_target_files_temp_dir,
Daniel Normand5d70ea2019-06-05 15:13:43 -0700696 framework_misc_info_keys=framework_misc_info_keys)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800697
Daniel Normana61cde02019-05-03 14:19:13 -0700698 process_dynamic_partitions_info_txt(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700699 framework_target_files_dir=framework_target_files_temp_dir,
700 vendor_target_files_dir=vendor_target_files_temp_dir,
Daniel Norman714bd122019-05-08 16:20:02 -0700701 output_target_files_dir=output_target_files_temp_dir)
Daniel Normana61cde02019-05-03 14:19:13 -0700702
Chris Grossfabf50a2019-05-02 12:42:09 -0700703 process_apex_keys_apk_certs_common(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700704 framework_target_files_dir=framework_target_files_temp_dir,
705 vendor_target_files_dir=vendor_target_files_temp_dir,
Chris Grossfabf50a2019-05-02 12:42:09 -0700706 output_target_files_dir=output_target_files_temp_dir,
Bill Peckham19c3feb2020-03-20 18:31:43 -0700707 framework_partition_set=framework_partition_set,
708 vendor_partition_set=vendor_partition_set,
Chris Grossfabf50a2019-05-02 12:42:09 -0700709 file_name='apkcerts.txt')
710
711 process_apex_keys_apk_certs_common(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700712 framework_target_files_dir=framework_target_files_temp_dir,
713 vendor_target_files_dir=vendor_target_files_temp_dir,
Chris Grossfabf50a2019-05-02 12:42:09 -0700714 output_target_files_dir=output_target_files_temp_dir,
Bill Peckham19c3feb2020-03-20 18:31:43 -0700715 framework_partition_set=framework_partition_set,
716 vendor_partition_set=vendor_partition_set,
Chris Grossfabf50a2019-05-02 12:42:09 -0700717 file_name='apexkeys.txt')
718
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800719
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900720def create_merged_package(temp_dir, framework_target_files, framework_item_list,
721 vendor_target_files, vendor_item_list,
Daniel Norman4cc9df62019-07-18 10:11:07 -0700722 framework_misc_info_keys, rebuild_recovery):
Tao Bao2ad4b822019-06-27 16:52:12 -0700723 """Merges two target files packages into one target files structure.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800724
725 Args:
726 temp_dir: The name of a directory we use when we extract items from the
Daniel Normane5b134a2019-04-17 14:54:06 -0700727 input target files packages, and also a scratch directory that we use for
728 temporary files.
Daniel Normand5d70ea2019-06-05 15:13:43 -0700729 framework_target_files: The name of the zip archive containing the framework
Daniel Normane5b134a2019-04-17 14:54:06 -0700730 partial target files package.
Daniel Normand5d70ea2019-06-05 15:13:43 -0700731 framework_item_list: The list of items to extract from the partial framework
Daniel Normane5b134a2019-04-17 14:54:06 -0700732 target files package as is, meaning these items will land in the output
Daniel Normand5d70ea2019-06-05 15:13:43 -0700733 target files package exactly as they appear in the input partial framework
Daniel Normane5b134a2019-04-17 14:54:06 -0700734 target files package.
Daniel Normand5d70ea2019-06-05 15:13:43 -0700735 vendor_target_files: The name of the zip archive containing the vendor
736 partial target files package.
737 vendor_item_list: The list of items to extract from the partial vendor
738 target files package as is, meaning these items will land in the output
739 target files package exactly as they appear in the input partial vendor
Daniel Normane5b134a2019-04-17 14:54:06 -0700740 target files package.
Daniel Normandbbf5a32020-10-22 16:03:32 -0700741 framework_misc_info_keys: A list of keys to obtain from the framework
742 instance of META/misc_info.txt. The remaining keys should come from the
743 vendor instance.
Daniel Normana4911da2019-03-15 14:36:21 -0700744 rebuild_recovery: If true, rebuild the recovery patch used by non-A/B
Daniel Normane5b134a2019-04-17 14:54:06 -0700745 devices and write it to the system image.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800746
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900747 Returns:
748 Path to merged package under temp directory.
749 """
Daniel Normandbbf5a32020-10-22 16:03:32 -0700750 # Extract "as is" items from the input framework and vendor partial target
751 # files packages directly into the output temporary directory, since these items
752 # do not need special case processing.
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800753
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800754 output_target_files_temp_dir = os.path.join(temp_dir, 'output')
Bill Peckham889b0c62019-02-21 18:53:37 -0800755 extract_items(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700756 target_files=framework_target_files,
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800757 target_files_temp_dir=output_target_files_temp_dir,
Daniel Normand5d70ea2019-06-05 15:13:43 -0700758 extract_item_list=framework_item_list)
Bill Peckham889b0c62019-02-21 18:53:37 -0800759 extract_items(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700760 target_files=vendor_target_files,
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800761 target_files_temp_dir=output_target_files_temp_dir,
Daniel Normand5d70ea2019-06-05 15:13:43 -0700762 extract_item_list=vendor_item_list)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800763
Daniel Normandbbf5a32020-10-22 16:03:32 -0700764 # Perform special case processing on META/* items.
765 # After this function completes successfully, all the files we need to create
766 # the output target files package are in place.
767 framework_target_files_temp_dir = os.path.join(temp_dir, 'framework')
768 vendor_target_files_temp_dir = os.path.join(temp_dir, 'vendor')
Daniel Normand5d70ea2019-06-05 15:13:43 -0700769 extract_items(
770 target_files=framework_target_files,
771 target_files_temp_dir=framework_target_files_temp_dir,
Daniel Normandbbf5a32020-10-22 16:03:32 -0700772 extract_item_list=('META/*',))
Bill Peckham889b0c62019-02-21 18:53:37 -0800773 extract_items(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700774 target_files=vendor_target_files,
775 target_files_temp_dir=vendor_target_files_temp_dir,
Daniel Normandbbf5a32020-10-22 16:03:32 -0700776 extract_item_list=('META/*',))
Bill Peckham889b0c62019-02-21 18:53:37 -0800777 process_special_cases(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700778 framework_target_files_temp_dir=framework_target_files_temp_dir,
779 vendor_target_files_temp_dir=vendor_target_files_temp_dir,
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800780 output_target_files_temp_dir=output_target_files_temp_dir,
Bill Peckham19c3feb2020-03-20 18:31:43 -0700781 framework_misc_info_keys=framework_misc_info_keys,
782 framework_partition_set=item_list_to_partition_set(framework_item_list),
783 vendor_partition_set=item_list_to_partition_set(vendor_item_list))
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800784
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900785 return output_target_files_temp_dir
786
787
788def generate_images(target_files_dir, rebuild_recovery):
789 """Generate images from target files.
790
791 This function takes merged output temporary directory and create images
792 from it.
793
794 Args:
795 target_files_dir: Path to merged temp directory.
796 rebuild_recovery: If true, rebuild the recovery patch used by non-A/B
797 devices and write it to the system image.
798 """
799
800 # Regenerate IMAGES in the target directory.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800801
Daniel Normandbbf5a32020-10-22 16:03:32 -0700802 add_img_args = [
803 '--verbose',
804 '--add_missing',
805 ]
Bill Peckhame868aec2019-09-17 17:06:47 -0700806 # TODO(b/132730255): Remove this if statement.
Daniel Normana4911da2019-03-15 14:36:21 -0700807 if rebuild_recovery:
808 add_img_args.append('--rebuild_recovery')
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900809 add_img_args.append(target_files_dir)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800810
811 add_img_to_target_files.main(add_img_args)
812
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900813
814def generate_super_empty_image(target_dir, output_super_empty):
Tao Bao2ad4b822019-06-27 16:52:12 -0700815 """Generates super_empty image from target package.
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900816
817 Args:
818 target_dir: Path to the target file package which contains misc_info.txt for
819 detailed information for super image.
820 output_super_empty: If provided, copies a super_empty.img file from the
821 target files package to this path.
822 """
Daniel Norman1bd2a1d2019-04-18 12:32:18 -0700823 # Create super_empty.img using the merged misc_info.txt.
824
Daniel Norman4cc9df62019-07-18 10:11:07 -0700825 misc_info_txt = os.path.join(target_dir, 'META', 'misc_info.txt')
Daniel Norman1bd2a1d2019-04-18 12:32:18 -0700826
Kiyoung Kimebe7c9c2019-06-25 17:09:55 +0900827 use_dynamic_partitions = common.LoadDictionaryFromFile(misc_info_txt).get(
828 'use_dynamic_partitions')
Daniel Norman1bd2a1d2019-04-18 12:32:18 -0700829
830 if use_dynamic_partitions != 'true' and output_super_empty:
831 raise ValueError(
832 'Building super_empty.img requires use_dynamic_partitions=true.')
833 elif use_dynamic_partitions == 'true':
Daniel Norman4cc9df62019-07-18 10:11:07 -0700834 super_empty_img = os.path.join(target_dir, 'IMAGES', 'super_empty.img')
Daniel Norman1bd2a1d2019-04-18 12:32:18 -0700835 build_super_image_args = [
836 misc_info_txt,
837 super_empty_img,
838 ]
839 build_super_image.main(build_super_image_args)
840
841 # Copy super_empty.img to the user-provided output_super_empty location.
842 if output_super_empty:
843 shutil.copyfile(super_empty_img, output_super_empty)
844
Daniel Normanb8a2f9d2019-04-24 12:55:51 -0700845
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900846def create_target_files_archive(output_file, source_dir, temp_dir):
Tao Bao2ad4b822019-06-27 16:52:12 -0700847 """Creates archive from target package.
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900848
849 Args:
850 output_file: The name of the zip archive target files package.
851 source_dir: The target directory contains package to be archived.
852 temp_dir: Path to temporary directory for any intermediate files.
853 """
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800854 output_target_files_list = os.path.join(temp_dir, 'output.list')
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900855 output_zip = os.path.abspath(output_file)
Daniel Norman4cc9df62019-07-18 10:11:07 -0700856 output_target_files_meta_dir = os.path.join(source_dir, 'META')
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800857
Daniel Normandbbf5a32020-10-22 16:03:32 -0700858 def files_from_path(target_path, extra_args=None):
859 """Gets files under the given path and return a sorted list."""
860 find_command = ['find', target_path] + (extra_args or [])
861 find_process = common.Run(
862 find_command, stdout=subprocess.PIPE, verbose=False)
863 return common.RunAndCheckOutput(['sort'],
864 stdin=find_process.stdout,
865 verbose=False)
866
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900867 meta_content = files_from_path(output_target_files_meta_dir)
Daniel Norman4cc9df62019-07-18 10:11:07 -0700868 other_content = files_from_path(
869 source_dir,
870 ['-path', output_target_files_meta_dir, '-prune', '-o', '-print'])
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800871
Tao Bao2ad4b822019-06-27 16:52:12 -0700872 with open(output_target_files_list, 'w') as f:
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800873 f.write(meta_content)
874 f.write(other_content)
875
876 command = [
Bill Peckhamf753e152019-02-19 18:02:46 -0800877 'soong_zip',
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800878 '-d',
Daniel Normane5b134a2019-04-17 14:54:06 -0700879 '-o',
880 output_zip,
881 '-C',
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900882 source_dir,
Daniel Normane5b134a2019-04-17 14:54:06 -0700883 '-l',
884 output_target_files_list,
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800885 ]
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900886
887 logger.info('creating %s', output_file)
Bill Peckham889b0c62019-02-21 18:53:37 -0800888 common.RunAndWait(command, verbose=True)
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900889 logger.info('finished creating %s', output_file)
890
891 return output_zip
892
893
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900894def merge_target_files(temp_dir, framework_target_files, framework_item_list,
895 framework_misc_info_keys, vendor_target_files,
896 vendor_item_list, output_target_files, output_dir,
897 output_item_list, output_ota, output_img,
898 output_super_empty, rebuild_recovery):
Tao Bao2ad4b822019-06-27 16:52:12 -0700899 """Merges two target files packages together.
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900900
901 This function takes framework and vendor target files packages as input,
902 performs various file extractions, special case processing, and finally
903 creates a merged zip archive as output.
904
905 Args:
906 temp_dir: The name of a directory we use when we extract items from the
907 input target files packages, and also a scratch directory that we use for
908 temporary files.
909 framework_target_files: The name of the zip archive containing the framework
910 partial target files package.
911 framework_item_list: The list of items to extract from the partial framework
912 target files package as is, meaning these items will land in the output
913 target files package exactly as they appear in the input partial framework
914 target files package.
Daniel Normandbbf5a32020-10-22 16:03:32 -0700915 framework_misc_info_keys: A list of keys to obtain from the framework
916 instance of META/misc_info.txt. The remaining keys should come from the
917 vendor instance.
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900918 vendor_target_files: The name of the zip archive containing the vendor
919 partial target files package.
920 vendor_item_list: The list of items to extract from the partial vendor
921 target files package as is, meaning these items will land in the output
922 target files package exactly as they appear in the input partial vendor
923 target files package.
924 output_target_files: The name of the output zip archive target files package
925 created by merging framework and vendor.
926 output_dir: The destination directory for saving merged files.
927 output_item_list: The list of items to copy into the output_dir.
928 output_ota: The name of the output zip archive ota package.
929 output_img: The name of the output zip archive img package.
930 output_super_empty: If provided, creates a super_empty.img file from the
931 merged target files package and saves it at this path.
932 rebuild_recovery: If true, rebuild the recovery patch used by non-A/B
933 devices and write it to the system image.
934 """
935
936 logger.info('starting: merge framework %s and vendor %s into output %s',
937 framework_target_files, vendor_target_files, output_target_files)
938
939 output_target_files_temp_dir = create_merged_package(
940 temp_dir, framework_target_files, framework_item_list,
941 vendor_target_files, vendor_item_list, framework_misc_info_keys,
942 rebuild_recovery)
943
Yifan Hongade0d3f2019-08-21 16:37:11 -0700944 if not check_target_files_vintf.CheckVintf(output_target_files_temp_dir):
Daniel Normanb0c75912020-09-24 14:30:21 -0700945 raise RuntimeError('Incompatible VINTF metadata')
Yifan Hongade0d3f2019-08-21 16:37:11 -0700946
Daniel Normanb8d52a22020-10-26 17:55:00 -0700947 shareduid_violation_modules = os.path.join(
948 output_target_files_temp_dir, 'META', 'shareduid_violation_modules.json')
949 with open(shareduid_violation_modules, 'w') as f:
950 partition_map = {
951 'system': 'SYSTEM',
952 'vendor': 'VENDOR',
953 'product': 'PRODUCT',
954 'system_ext': 'SYSTEM_EXT',
955 }
956 violation = find_shareduid_violation.FindShareduidViolation(
957 output_target_files_temp_dir, partition_map)
958 f.write(violation)
959 # TODO(b/171431774): Add a check to common.py to check if the
960 # shared UIDs cross the input build partition boundary.
961
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900962 generate_images(output_target_files_temp_dir, rebuild_recovery)
963
964 generate_super_empty_image(output_target_files_temp_dir, output_super_empty)
965
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900966 # Finally, create the output target files zip archive and/or copy the
967 # output items to the output target files directory.
968
969 if output_dir:
970 copy_items(output_target_files_temp_dir, output_dir, output_item_list)
971
972 if not output_target_files:
973 return
974
975 output_zip = create_target_files_archive(output_target_files,
976 output_target_files_temp_dir,
977 temp_dir)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800978
Daniel Norman74eb74b2019-09-18 14:01:48 -0700979 # Create the IMG package from the merged target files package.
980
981 if output_img:
982 img_from_target_files.main([output_zip, output_img])
983
Daniel Norman3b64ce12019-04-16 16:11:35 -0700984 # Create the OTA package from the merged target files package.
985
986 if output_ota:
Daniel Norman4cc9df62019-07-18 10:11:07 -0700987 ota_from_target_files.main([output_zip, output_ota])
Daniel Norman3b64ce12019-04-16 16:11:35 -0700988
Daniel Norman1bd2a1d2019-04-18 12:32:18 -0700989
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800990def call_func_with_temp_dir(func, keep_tmp):
Tao Bao2ad4b822019-06-27 16:52:12 -0700991 """Manages the creation and cleanup of the temporary directory.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800992
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800993 This function calls the given function after first creating a temporary
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800994 directory. It also cleans up the temporary directory.
995
996 Args:
Daniel Normane5b134a2019-04-17 14:54:06 -0700997 func: The function to call. Should accept one parameter, the path to the
998 temporary directory.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800999 keep_tmp: Keep the temporary directory after processing is complete.
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001000 """
1001
1002 # Create a temporary directory. This will serve as the parent of directories
1003 # we use when we extract items from the input target files packages, and also
1004 # a scratch directory that we use for temporary files.
1005
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001006 temp_dir = common.MakeTempDir(prefix='merge_target_files_')
1007
1008 try:
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001009 func(temp_dir)
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001010 finally:
1011 if keep_tmp:
1012 logger.info('keeping %s', temp_dir)
1013 else:
1014 common.Cleanup()
1015
1016
1017def main():
1018 """The main function.
1019
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001020 Process command line arguments, then call merge_target_files to
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001021 perform the heavy lifting.
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001022 """
1023
1024 common.InitLogging()
1025
Bill Peckhamf753e152019-02-19 18:02:46 -08001026 def option_handler(o, a):
1027 if o == '--system-target-files':
Daniel Normand5d70ea2019-06-05 15:13:43 -07001028 logger.warning(
1029 '--system-target-files has been renamed to --framework-target-files')
1030 OPTIONS.framework_target_files = a
1031 elif o == '--framework-target-files':
1032 OPTIONS.framework_target_files = a
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001033 elif o == '--system-item-list':
Daniel Normand5d70ea2019-06-05 15:13:43 -07001034 logger.warning(
1035 '--system-item-list has been renamed to --framework-item-list')
1036 OPTIONS.framework_item_list = a
1037 elif o == '--framework-item-list':
1038 OPTIONS.framework_item_list = a
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001039 elif o == '--system-misc-info-keys':
Daniel Norman4cc9df62019-07-18 10:11:07 -07001040 logger.warning('--system-misc-info-keys has been renamed to '
1041 '--framework-misc-info-keys')
Daniel Normand5d70ea2019-06-05 15:13:43 -07001042 OPTIONS.framework_misc_info_keys = a
1043 elif o == '--framework-misc-info-keys':
1044 OPTIONS.framework_misc_info_keys = a
Bill Peckhamf753e152019-02-19 18:02:46 -08001045 elif o == '--other-target-files':
Daniel Normand5d70ea2019-06-05 15:13:43 -07001046 logger.warning(
1047 '--other-target-files has been renamed to --vendor-target-files')
1048 OPTIONS.vendor_target_files = a
1049 elif o == '--vendor-target-files':
1050 OPTIONS.vendor_target_files = a
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001051 elif o == '--other-item-list':
Daniel Normand5d70ea2019-06-05 15:13:43 -07001052 logger.warning('--other-item-list has been renamed to --vendor-item-list')
1053 OPTIONS.vendor_item_list = a
1054 elif o == '--vendor-item-list':
1055 OPTIONS.vendor_item_list = a
Bill Peckhamf753e152019-02-19 18:02:46 -08001056 elif o == '--output-target-files':
1057 OPTIONS.output_target_files = a
Daniel Normanfdb38812019-04-15 09:47:24 -07001058 elif o == '--output-dir':
1059 OPTIONS.output_dir = a
1060 elif o == '--output-item-list':
1061 OPTIONS.output_item_list = a
Daniel Norman3b64ce12019-04-16 16:11:35 -07001062 elif o == '--output-ota':
1063 OPTIONS.output_ota = a
Daniel Norman1bd2a1d2019-04-18 12:32:18 -07001064 elif o == '--output-img':
1065 OPTIONS.output_img = a
Daniel Normanf0318252019-04-15 11:34:56 -07001066 elif o == '--output-super-empty':
1067 OPTIONS.output_super_empty = a
Daniel Normanb0c75912020-09-24 14:30:21 -07001068 elif o == '--rebuild_recovery': # TODO(b/132730255): Warn
Daniel Normana4911da2019-03-15 14:36:21 -07001069 OPTIONS.rebuild_recovery = True
Daniel Normanb0c75912020-09-24 14:30:21 -07001070 elif o == '--allow-duplicate-apkapex-keys':
1071 OPTIONS.allow_duplicate_apkapex_keys = True
Bill Peckham364c1cc2019-03-29 18:27:23 -07001072 elif o == '--keep-tmp':
Bill Peckhamf753e152019-02-19 18:02:46 -08001073 OPTIONS.keep_tmp = True
1074 else:
1075 return False
1076 return True
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001077
Bill Peckhamf753e152019-02-19 18:02:46 -08001078 args = common.ParseOptions(
Daniel Normane5b134a2019-04-17 14:54:06 -07001079 sys.argv[1:],
1080 __doc__,
Bill Peckhamf753e152019-02-19 18:02:46 -08001081 extra_long_opts=[
1082 'system-target-files=',
Daniel Normand5d70ea2019-06-05 15:13:43 -07001083 'framework-target-files=',
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001084 'system-item-list=',
Daniel Normand5d70ea2019-06-05 15:13:43 -07001085 'framework-item-list=',
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001086 'system-misc-info-keys=',
Daniel Normand5d70ea2019-06-05 15:13:43 -07001087 'framework-misc-info-keys=',
Bill Peckhamf753e152019-02-19 18:02:46 -08001088 'other-target-files=',
Daniel Normand5d70ea2019-06-05 15:13:43 -07001089 'vendor-target-files=',
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001090 'other-item-list=',
Daniel Normand5d70ea2019-06-05 15:13:43 -07001091 'vendor-item-list=',
Bill Peckhamf753e152019-02-19 18:02:46 -08001092 'output-target-files=',
Daniel Normanfdb38812019-04-15 09:47:24 -07001093 'output-dir=',
1094 'output-item-list=',
Daniel Norman3b64ce12019-04-16 16:11:35 -07001095 'output-ota=',
Daniel Norman1bd2a1d2019-04-18 12:32:18 -07001096 'output-img=',
Daniel Normanf0318252019-04-15 11:34:56 -07001097 'output-super-empty=',
Daniel Normana4911da2019-03-15 14:36:21 -07001098 'rebuild_recovery',
Daniel Normanb0c75912020-09-24 14:30:21 -07001099 'allow-duplicate-apkapex-keys',
Bill Peckham364c1cc2019-03-29 18:27:23 -07001100 'keep-tmp',
Bill Peckhamf753e152019-02-19 18:02:46 -08001101 ],
1102 extra_option_handler=option_handler)
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001103
Tao Bao2ad4b822019-06-27 16:52:12 -07001104 # pylint: disable=too-many-boolean-expressions
Daniel Normand5d70ea2019-06-05 15:13:43 -07001105 if (args or OPTIONS.framework_target_files is None or
1106 OPTIONS.vendor_target_files is None or
Daniel Normane5b134a2019-04-17 14:54:06 -07001107 (OPTIONS.output_target_files is None and OPTIONS.output_dir is None) or
1108 (OPTIONS.output_dir is not None and OPTIONS.output_item_list is None)):
Bill Peckhamf753e152019-02-19 18:02:46 -08001109 common.Usage(__doc__)
Bill Peckham889b0c62019-02-21 18:53:37 -08001110 sys.exit(1)
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001111
Daniel Normand5d70ea2019-06-05 15:13:43 -07001112 if OPTIONS.framework_item_list:
Daniel Norman4cc9df62019-07-18 10:11:07 -07001113 framework_item_list = common.LoadListFromFile(OPTIONS.framework_item_list)
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001114 else:
Daniel Normand5d70ea2019-06-05 15:13:43 -07001115 framework_item_list = DEFAULT_FRAMEWORK_ITEM_LIST
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001116
Daniel Normand5d70ea2019-06-05 15:13:43 -07001117 if OPTIONS.framework_misc_info_keys:
Daniel Norman4cc9df62019-07-18 10:11:07 -07001118 framework_misc_info_keys = common.LoadListFromFile(
Daniel Normand5d70ea2019-06-05 15:13:43 -07001119 OPTIONS.framework_misc_info_keys)
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001120 else:
Daniel Normand5d70ea2019-06-05 15:13:43 -07001121 framework_misc_info_keys = DEFAULT_FRAMEWORK_MISC_INFO_KEYS
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001122
Daniel Normand5d70ea2019-06-05 15:13:43 -07001123 if OPTIONS.vendor_item_list:
Daniel Norman4cc9df62019-07-18 10:11:07 -07001124 vendor_item_list = common.LoadListFromFile(OPTIONS.vendor_item_list)
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001125 else:
Daniel Normand5d70ea2019-06-05 15:13:43 -07001126 vendor_item_list = DEFAULT_VENDOR_ITEM_LIST
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001127
Daniel Normanfdb38812019-04-15 09:47:24 -07001128 if OPTIONS.output_item_list:
Daniel Norman4cc9df62019-07-18 10:11:07 -07001129 output_item_list = common.LoadListFromFile(OPTIONS.output_item_list)
Daniel Normanfdb38812019-04-15 09:47:24 -07001130 else:
1131 output_item_list = None
1132
Daniel Normane5964522019-03-19 10:32:03 -07001133 if not validate_config_lists(
Daniel Normand5d70ea2019-06-05 15:13:43 -07001134 framework_item_list=framework_item_list,
1135 framework_misc_info_keys=framework_misc_info_keys,
1136 vendor_item_list=vendor_item_list):
Daniel Normane5964522019-03-19 10:32:03 -07001137 sys.exit(1)
1138
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001139 call_func_with_temp_dir(
1140 lambda temp_dir: merge_target_files(
1141 temp_dir=temp_dir,
Daniel Normand5d70ea2019-06-05 15:13:43 -07001142 framework_target_files=OPTIONS.framework_target_files,
1143 framework_item_list=framework_item_list,
1144 framework_misc_info_keys=framework_misc_info_keys,
1145 vendor_target_files=OPTIONS.vendor_target_files,
1146 vendor_item_list=vendor_item_list,
Daniel Normana4911da2019-03-15 14:36:21 -07001147 output_target_files=OPTIONS.output_target_files,
Daniel Normanfdb38812019-04-15 09:47:24 -07001148 output_dir=OPTIONS.output_dir,
1149 output_item_list=output_item_list,
Daniel Norman3b64ce12019-04-16 16:11:35 -07001150 output_ota=OPTIONS.output_ota,
Daniel Norman1bd2a1d2019-04-18 12:32:18 -07001151 output_img=OPTIONS.output_img,
Daniel Normanf0318252019-04-15 11:34:56 -07001152 output_super_empty=OPTIONS.output_super_empty,
Daniel Normane5b134a2019-04-17 14:54:06 -07001153 rebuild_recovery=OPTIONS.rebuild_recovery), OPTIONS.keep_tmp)
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001154
1155
1156if __name__ == '__main__':
Bill Peckham889b0c62019-02-21 18:53:37 -08001157 main()