blob: ed42b20d28a382a4476658f3780b061324d748a7 [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
73 --keep-tmp
74 Keep tempoary files for debugging purposes.
Bill Peckhame9eb5f92019-02-01 15:52:10 -080075"""
76
77from __future__ import print_function
78
Bill Peckhame9eb5f92019-02-01 15:52:10 -080079import fnmatch
80import logging
81import os
Bill Peckham19c3feb2020-03-20 18:31:43 -070082import re
Daniel Normanfdb38812019-04-15 09:47:24 -070083import shutil
Bill Peckham540d91a2019-04-25 14:18:16 -070084import subprocess
Bill Peckhame9eb5f92019-02-01 15:52:10 -080085import sys
86import zipfile
87
Bill Peckhame9eb5f92019-02-01 15:52:10 -080088import add_img_to_target_files
Daniel Normanf0318252019-04-15 11:34:56 -070089import build_super_image
Yifan Hongade0d3f2019-08-21 16:37:11 -070090import check_target_files_vintf
Daniel Normanf0318252019-04-15 11:34:56 -070091import common
Daniel Norman1bd2a1d2019-04-18 12:32:18 -070092import img_from_target_files
Daniel Norman3b64ce12019-04-16 16:11:35 -070093import ota_from_target_files
Bill Peckhame9eb5f92019-02-01 15:52:10 -080094
95logger = logging.getLogger(__name__)
Tao Bao2ad4b822019-06-27 16:52:12 -070096
Bill Peckhame9eb5f92019-02-01 15:52:10 -080097OPTIONS = common.OPTIONS
Bill Peckhamcb848172020-04-03 12:50:47 -070098# Always turn on verbose logging.
99OPTIONS.verbose = True
Daniel Normand5d70ea2019-06-05 15:13:43 -0700100OPTIONS.framework_target_files = None
101OPTIONS.framework_item_list = None
102OPTIONS.framework_misc_info_keys = None
103OPTIONS.vendor_target_files = None
104OPTIONS.vendor_item_list = None
Bill Peckhamf753e152019-02-19 18:02:46 -0800105OPTIONS.output_target_files = None
Daniel Normanfdb38812019-04-15 09:47:24 -0700106OPTIONS.output_dir = None
107OPTIONS.output_item_list = None
Daniel Norman3b64ce12019-04-16 16:11:35 -0700108OPTIONS.output_ota = None
Daniel Norman1bd2a1d2019-04-18 12:32:18 -0700109OPTIONS.output_img = None
Daniel Normanf0318252019-04-15 11:34:56 -0700110OPTIONS.output_super_empty = None
Bill Peckhame868aec2019-09-17 17:06:47 -0700111# TODO(b/132730255): Remove this option.
Daniel Normana4911da2019-03-15 14:36:21 -0700112OPTIONS.rebuild_recovery = False
Bill Peckhamf753e152019-02-19 18:02:46 -0800113OPTIONS.keep_tmp = False
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800114
Bill Peckham19c3feb2020-03-20 18:31:43 -0700115# In an item list (framework or vendor), we may see entries that select whole
116# partitions. Such an entry might look like this 'SYSTEM/*' (e.g., for the
117# system partition). The following regex matches this and extracts the
118# partition name.
119
120PARTITION_ITEM_PATTERN = re.compile(r'^([A-Z_]+)/\*$')
121
Bill Peckham5c7b0342020-04-03 15:36:23 -0700122# In apexkeys.txt or apkcerts.txt, we will find partition tags on each entry in
123# the file. We use these partition tags to filter the entries in those files
124# from the two different target files packages to produce a merged apexkeys.txt
125# or apkcerts.txt file. A partition tag (e.g., for the product partition) looks
126# like this: 'partition="product"'. We use the group syntax grab the value of
127# the tag. We use non-greedy matching in case there are other fields on the
128# same line.
Bill Peckham19c3feb2020-03-20 18:31:43 -0700129
Bill Peckham5c7b0342020-04-03 15:36:23 -0700130PARTITION_TAG_PATTERN = re.compile(r'partition="(.*?)"')
Bill Peckham19c3feb2020-03-20 18:31:43 -0700131
132# The sorting algorithm for apexkeys.txt and apkcerts.txt does not include the
133# ".apex" or ".apk" suffix, so we use the following pattern to extract a key.
134
135MODULE_KEY_PATTERN = re.compile(r'name="(.+)\.(apex|apk)"')
136
Daniel Normand5d70ea2019-06-05 15:13:43 -0700137# DEFAULT_FRAMEWORK_ITEM_LIST is a list of items to extract from the partial
138# framework target files package as is, meaning these items will land in the
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800139# output target files package exactly as they appear in the input partial
Daniel Normand5d70ea2019-06-05 15:13:43 -0700140# framework target files package.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800141
Daniel Normand5d70ea2019-06-05 15:13:43 -0700142DEFAULT_FRAMEWORK_ITEM_LIST = (
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800143 'META/apkcerts.txt',
144 'META/filesystem_config.txt',
145 'META/root_filesystem_config.txt',
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800146 'META/update_engine_config.txt',
147 'PRODUCT/*',
148 'ROOT/*',
149 'SYSTEM/*',
Daniel Normanedf12472019-05-22 10:47:08 -0700150)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800151
Daniel Normand5d70ea2019-06-05 15:13:43 -0700152# FRAMEWORK_EXTRACT_SPECIAL_ITEM_LIST is a list of items to extract from the
153# partial framework target files package that need some special processing, such
154# as some sort of combination with items from the partial vendor target files
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800155# package.
156
Daniel Normand5d70ea2019-06-05 15:13:43 -0700157FRAMEWORK_EXTRACT_SPECIAL_ITEM_LIST = ('META/*',)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800158
Daniel Normand5d70ea2019-06-05 15:13:43 -0700159# DEFAULT_FRAMEWORK_MISC_INFO_KEYS is a list of keys to obtain from the
160# framework instance of META/misc_info.txt. The remaining keys from the
161# vendor instance.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800162
Daniel Normand5d70ea2019-06-05 15:13:43 -0700163DEFAULT_FRAMEWORK_MISC_INFO_KEYS = (
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800164 'avb_system_hashtree_enable',
165 'avb_system_add_hashtree_footer_args',
166 'avb_system_key_path',
167 'avb_system_algorithm',
168 'avb_system_rollback_index_location',
169 'avb_product_hashtree_enable',
170 'avb_product_add_hashtree_footer_args',
Justin Yun6151e3f2019-06-25 15:58:13 +0900171 'avb_system_ext_hashtree_enable',
172 'avb_system_ext_add_hashtree_footer_args',
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800173 'system_root_image',
174 'root_dir',
175 'ab_update',
176 'default_system_dev_certificate',
177 'system_size',
Chris Gross203191b2020-05-30 02:39:12 +0000178 'building_system_image',
179 'building_system_ext_image',
180 'building_product_image',
Daniel Normanedf12472019-05-22 10:47:08 -0700181)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800182
Daniel Normand5d70ea2019-06-05 15:13:43 -0700183# DEFAULT_VENDOR_ITEM_LIST is a list of items to extract from the partial
184# vendor target files package as is, meaning these items will land in the output
185# target files package exactly as they appear in the input partial vendor target
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800186# files package.
187
Daniel Normand5d70ea2019-06-05 15:13:43 -0700188DEFAULT_VENDOR_ITEM_LIST = (
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800189 'META/boot_filesystem_config.txt',
190 'META/otakeys.txt',
191 'META/releasetools.py',
192 'META/vendor_filesystem_config.txt',
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800193 'BOOT/*',
194 'DATA/*',
195 'ODM/*',
196 'OTA/android-info.txt',
197 'PREBUILT_IMAGES/*',
198 'RADIO/*',
199 'VENDOR/*',
Daniel Normanedf12472019-05-22 10:47:08 -0700200)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800201
Daniel Normand5d70ea2019-06-05 15:13:43 -0700202# VENDOR_EXTRACT_SPECIAL_ITEM_LIST is a list of items to extract from the
203# partial vendor target files package that need some special processing, such as
204# some sort of combination with items from the partial framework target files
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800205# package.
206
Daniel Normand5d70ea2019-06-05 15:13:43 -0700207VENDOR_EXTRACT_SPECIAL_ITEM_LIST = ('META/*',)
Daniel Normanedf12472019-05-22 10:47:08 -0700208
209# The merge config lists should not attempt to extract items from both
210# builds for any of the following partitions. The partitions in
211# SINGLE_BUILD_PARTITIONS should come entirely from a single build (either
Daniel Normand5d70ea2019-06-05 15:13:43 -0700212# framework or vendor, but not both).
Daniel Normanedf12472019-05-22 10:47:08 -0700213
214SINGLE_BUILD_PARTITIONS = (
215 'BOOT/',
216 'DATA/',
217 'ODM/',
218 'PRODUCT/',
Justin Yun6151e3f2019-06-25 15:58:13 +0900219 'SYSTEM_EXT/',
Daniel Normanedf12472019-05-22 10:47:08 -0700220 'RADIO/',
221 'RECOVERY/',
222 'ROOT/',
223 'SYSTEM/',
224 'SYSTEM_OTHER/',
225 'VENDOR/',
226)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800227
228
Chris Grossfabf50a2019-05-02 12:42:09 -0700229def write_sorted_data(data, path):
Tao Bao2ad4b822019-06-27 16:52:12 -0700230 """Writes the sorted contents of either a list or dict to file.
Chris Grossfabf50a2019-05-02 12:42:09 -0700231
Tao Bao2ad4b822019-06-27 16:52:12 -0700232 This function sorts the contents of the list or dict and then writes the
233 resulting sorted contents to a file specified by path.
Chris Grossfabf50a2019-05-02 12:42:09 -0700234
235 Args:
236 data: The list or dict to sort and write.
237 path: Path to the file to write the sorted values to. The file at path will
238 be overridden if it exists.
239 """
240 with open(path, 'w') as output:
Daniel Normand5d70ea2019-06-05 15:13:43 -0700241 for entry in sorted(data):
Chris Grossfabf50a2019-05-02 12:42:09 -0700242 out_str = '{}={}\n'.format(entry, data[entry]) if isinstance(
243 data, dict) else '{}\n'.format(entry)
244 output.write(out_str)
245
246
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800247def extract_items(target_files, target_files_temp_dir, extract_item_list):
Tao Bao2ad4b822019-06-27 16:52:12 -0700248 """Extracts items from target files to temporary directory.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800249
250 This function extracts from the specified target files zip archive into the
251 specified temporary directory, the items specified in the extract item list.
252
253 Args:
254 target_files: The target files zip archive from which to extract items.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800255 target_files_temp_dir: The temporary directory where the extracted items
Daniel Normane5b134a2019-04-17 14:54:06 -0700256 will land.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800257 extract_item_list: A list of items to extract.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800258 """
259
260 logger.info('extracting from %s', target_files)
261
262 # Filter the extract_item_list to remove any items that do not exist in the
263 # zip file. Otherwise, the extraction step will fail.
264
Daniel Norman4cc9df62019-07-18 10:11:07 -0700265 with zipfile.ZipFile(target_files, allowZip64=True) as target_files_zipfile:
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800266 target_files_namelist = target_files_zipfile.namelist()
267
268 filtered_extract_item_list = []
269 for pattern in extract_item_list:
270 matching_namelist = fnmatch.filter(target_files_namelist, pattern)
271 if not matching_namelist:
272 logger.warning('no match for %s', pattern)
273 else:
274 filtered_extract_item_list.append(pattern)
275
Bill Peckham8ff3fbd2019-02-22 10:57:43 -0800276 # Extract from target_files into target_files_temp_dir the
277 # filtered_extract_item_list.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800278
Daniel Normane5b134a2019-04-17 14:54:06 -0700279 common.UnzipToDir(target_files, target_files_temp_dir,
280 filtered_extract_item_list)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800281
282
Daniel Normanfdb38812019-04-15 09:47:24 -0700283def copy_items(from_dir, to_dir, patterns):
284 """Similar to extract_items() except uses an input dir instead of zip."""
285 file_paths = []
286 for dirpath, _, filenames in os.walk(from_dir):
Daniel Normane5b134a2019-04-17 14:54:06 -0700287 file_paths.extend(
288 os.path.relpath(path=os.path.join(dirpath, filename), start=from_dir)
289 for filename in filenames)
Daniel Normanfdb38812019-04-15 09:47:24 -0700290
291 filtered_file_paths = set()
292 for pattern in patterns:
293 filtered_file_paths.update(fnmatch.filter(file_paths, pattern))
294
295 for file_path in filtered_file_paths:
296 original_file_path = os.path.join(from_dir, file_path)
297 copied_file_path = os.path.join(to_dir, file_path)
298 copied_file_dir = os.path.dirname(copied_file_path)
299 if not os.path.exists(copied_file_dir):
300 os.makedirs(copied_file_dir)
301 if os.path.islink(original_file_path):
302 os.symlink(os.readlink(original_file_path), copied_file_path)
303 else:
304 shutil.copyfile(original_file_path, copied_file_path)
305
306
Daniel Normand5d70ea2019-06-05 15:13:43 -0700307def validate_config_lists(framework_item_list, framework_misc_info_keys,
308 vendor_item_list):
Daniel Normane5964522019-03-19 10:32:03 -0700309 """Performs validations on the merge config lists.
310
311 Args:
Daniel Normand5d70ea2019-06-05 15:13:43 -0700312 framework_item_list: The list of items to extract from the partial framework
Daniel Normane5b134a2019-04-17 14:54:06 -0700313 target files package as is.
Daniel Normand5d70ea2019-06-05 15:13:43 -0700314 framework_misc_info_keys: A list of keys to obtain from the framework
315 instance of META/misc_info.txt. The remaining keys from the vendor
316 instance.
317 vendor_item_list: The list of items to extract from the partial vendor
318 target files package as is.
Daniel Normane5964522019-03-19 10:32:03 -0700319
320 Returns:
321 False if a validation fails, otherwise true.
322 """
Daniel Normanedf12472019-05-22 10:47:08 -0700323 has_error = False
324
Daniel Normand5d70ea2019-06-05 15:13:43 -0700325 default_combined_item_set = set(DEFAULT_FRAMEWORK_ITEM_LIST)
326 default_combined_item_set.update(DEFAULT_VENDOR_ITEM_LIST)
Daniel Normane5964522019-03-19 10:32:03 -0700327
Daniel Normand5d70ea2019-06-05 15:13:43 -0700328 combined_item_set = set(framework_item_list)
329 combined_item_set.update(vendor_item_list)
Daniel Normane5964522019-03-19 10:32:03 -0700330
331 # Check that the merge config lists are not missing any item specified
332 # by the default config lists.
333 difference = default_combined_item_set.difference(combined_item_set)
334 if difference:
Daniel Normane5b134a2019-04-17 14:54:06 -0700335 logger.error('Missing merge config items: %s', list(difference))
Daniel Normane5964522019-03-19 10:32:03 -0700336 logger.error('Please ensure missing items are in either the '
Daniel Normand5d70ea2019-06-05 15:13:43 -0700337 'framework-item-list or vendor-item-list files provided to '
Daniel Normane5964522019-03-19 10:32:03 -0700338 'this script.')
Daniel Normanedf12472019-05-22 10:47:08 -0700339 has_error = True
340
341 for partition in SINGLE_BUILD_PARTITIONS:
Daniel Normand5d70ea2019-06-05 15:13:43 -0700342 in_framework = any(
343 item.startswith(partition) for item in framework_item_list)
344 in_vendor = any(item.startswith(partition) for item in vendor_item_list)
345 if in_framework and in_vendor:
Daniel Normanedf12472019-05-22 10:47:08 -0700346 logger.error(
Tao Bao2ad4b822019-06-27 16:52:12 -0700347 'Cannot extract items from %s for both the framework and vendor'
Kiyoung Kimebe7c9c2019-06-25 17:09:55 +0900348 ' builds. Please ensure only one merge config item list'
Tao Bao2ad4b822019-06-27 16:52:12 -0700349 ' includes %s.', partition, partition)
Daniel Normanedf12472019-05-22 10:47:08 -0700350 has_error = True
Daniel Normane5964522019-03-19 10:32:03 -0700351
Daniel Normand5d70ea2019-06-05 15:13:43 -0700352 if ('dynamic_partition_list' in framework_misc_info_keys) or (
353 'super_partition_groups' in framework_misc_info_keys):
Daniel Norman19b9fe92019-03-19 14:48:02 -0700354 logger.error('Dynamic partition misc info keys should come from '
Daniel Normand5d70ea2019-06-05 15:13:43 -0700355 'the vendor instance of META/misc_info.txt.')
Daniel Normanedf12472019-05-22 10:47:08 -0700356 has_error = True
Daniel Norman19b9fe92019-03-19 14:48:02 -0700357
Daniel Normanedf12472019-05-22 10:47:08 -0700358 return not has_error
Daniel Normane5964522019-03-19 10:32:03 -0700359
360
Daniel Normand5d70ea2019-06-05 15:13:43 -0700361def process_ab_partitions_txt(framework_target_files_temp_dir,
362 vendor_target_files_temp_dir,
Daniel Normane5b134a2019-04-17 14:54:06 -0700363 output_target_files_temp_dir):
Tao Bao2ad4b822019-06-27 16:52:12 -0700364 """Performs special processing for META/ab_partitions.txt.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800365
Tao Bao2ad4b822019-06-27 16:52:12 -0700366 This function merges the contents of the META/ab_partitions.txt files from the
367 framework directory and the vendor directory, placing the merged result in the
368 output directory. The precondition in that the files are already extracted.
369 The post condition is that the output META/ab_partitions.txt contains the
370 merged content. The format for each ab_partitions.txt a one partition name per
371 line. The output file contains the union of the parition names.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800372
373 Args:
Daniel Normand5d70ea2019-06-05 15:13:43 -0700374 framework_target_files_temp_dir: The name of a directory containing the
375 special items extracted from the framework target files package.
376 vendor_target_files_temp_dir: The name of a directory containing the special
377 items extracted from the vendor target files package.
Daniel Normane5b134a2019-04-17 14:54:06 -0700378 output_target_files_temp_dir: The name of a directory that will be used to
379 create the output target files package after all the special cases are
380 processed.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800381 """
382
Daniel Normand5d70ea2019-06-05 15:13:43 -0700383 framework_ab_partitions_txt = os.path.join(framework_target_files_temp_dir,
384 'META', 'ab_partitions.txt')
385
386 vendor_ab_partitions_txt = os.path.join(vendor_target_files_temp_dir, 'META',
Daniel Normane5b134a2019-04-17 14:54:06 -0700387 'ab_partitions.txt')
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800388
Daniel Normand5d70ea2019-06-05 15:13:43 -0700389 with open(framework_ab_partitions_txt) as f:
390 framework_ab_partitions = f.read().splitlines()
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800391
Daniel Normand5d70ea2019-06-05 15:13:43 -0700392 with open(vendor_ab_partitions_txt) as f:
393 vendor_ab_partitions = f.read().splitlines()
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800394
Daniel Normand5d70ea2019-06-05 15:13:43 -0700395 output_ab_partitions = set(framework_ab_partitions + vendor_ab_partitions)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800396
Daniel Normane5b134a2019-04-17 14:54:06 -0700397 output_ab_partitions_txt = os.path.join(output_target_files_temp_dir, 'META',
398 'ab_partitions.txt')
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800399
Chris Grossfabf50a2019-05-02 12:42:09 -0700400 write_sorted_data(data=output_ab_partitions, path=output_ab_partitions_txt)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800401
402
Daniel Normand5d70ea2019-06-05 15:13:43 -0700403def process_misc_info_txt(framework_target_files_temp_dir,
404 vendor_target_files_temp_dir,
405 output_target_files_temp_dir,
406 framework_misc_info_keys):
Tao Bao2ad4b822019-06-27 16:52:12 -0700407 """Performs special processing for META/misc_info.txt.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800408
409 This function merges the contents of the META/misc_info.txt files from the
Daniel Normand5d70ea2019-06-05 15:13:43 -0700410 framework directory and the vendor directory, placing the merged result in the
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800411 output directory. The precondition in that the files are already extracted.
412 The post condition is that the output META/misc_info.txt contains the merged
413 content.
414
415 Args:
Daniel Normand5d70ea2019-06-05 15:13:43 -0700416 framework_target_files_temp_dir: The name of a directory containing the
417 special items extracted from the framework target files package.
418 vendor_target_files_temp_dir: The name of a directory containing the special
419 items extracted from the vendor target files package.
Daniel Normane5b134a2019-04-17 14:54:06 -0700420 output_target_files_temp_dir: The name of a directory that will be used to
421 create the output target files package after all the special cases are
422 processed.
Daniel Normand5d70ea2019-06-05 15:13:43 -0700423 framework_misc_info_keys: A list of keys to obtain from the framework
424 instance of META/misc_info.txt. The remaining keys from the vendor
425 instance.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800426 """
427
Kiyoung Kimebe7c9c2019-06-25 17:09:55 +0900428 misc_info_path = ['META', 'misc_info.txt']
429 framework_dict = common.LoadDictionaryFromFile(
430 os.path.join(framework_target_files_temp_dir, *misc_info_path))
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800431
Daniel Normand5d70ea2019-06-05 15:13:43 -0700432 # We take most of the misc info from the vendor target files.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800433
Kiyoung Kimebe7c9c2019-06-25 17:09:55 +0900434 merged_dict = common.LoadDictionaryFromFile(
435 os.path.join(vendor_target_files_temp_dir, *misc_info_path))
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800436
Daniel Normand5d70ea2019-06-05 15:13:43 -0700437 # Replace certain values in merged_dict with values from
438 # framework_dict.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800439
Daniel Normand5d70ea2019-06-05 15:13:43 -0700440 for key in framework_misc_info_keys:
441 merged_dict[key] = framework_dict[key]
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800442
Daniel Norman19b9fe92019-03-19 14:48:02 -0700443 # Merge misc info keys used for Dynamic Partitions.
Daniel Normand5d70ea2019-06-05 15:13:43 -0700444 if (merged_dict.get('use_dynamic_partitions') == 'true') and (
445 framework_dict.get('use_dynamic_partitions') == 'true'):
Daniel Normanbfc51ef2019-07-24 14:34:54 -0700446 merged_dynamic_partitions_dict = common.MergeDynamicPartitionInfoDicts(
Daniel Norman55417142019-11-25 16:04:36 -0800447 framework_dict=framework_dict, vendor_dict=merged_dict)
Daniel Normand5d70ea2019-06-05 15:13:43 -0700448 merged_dict.update(merged_dynamic_partitions_dict)
Tao Bao48a2feb2019-06-28 11:00:05 -0700449 # Ensure that add_img_to_target_files rebuilds super split images for
450 # devices that retrofit dynamic partitions. This flag may have been set to
451 # false in the partial builds to prevent duplicate building of super.img.
Daniel Norman0bf940c2019-06-10 12:50:19 -0700452 merged_dict['build_super_partition'] = 'true'
Daniel Norman19b9fe92019-03-19 14:48:02 -0700453
Daniel Normand5d70ea2019-06-05 15:13:43 -0700454 # Replace <image>_selinux_fc values with framework or vendor file_contexts.bin
Daniel Norman72c626f2019-05-13 15:58:14 -0700455 # depending on which dictionary the key came from.
456 # Only the file basename is required because all selinux_fc properties are
457 # replaced with the full path to the file under META/ when misc_info.txt is
458 # loaded from target files for repacking. See common.py LoadInfoDict().
Daniel Normand5d70ea2019-06-05 15:13:43 -0700459 for key in merged_dict:
Daniel Norman72c626f2019-05-13 15:58:14 -0700460 if key.endswith('_selinux_fc'):
Daniel Normand5d70ea2019-06-05 15:13:43 -0700461 merged_dict[key] = 'vendor_file_contexts.bin'
462 for key in framework_dict:
Daniel Norman72c626f2019-05-13 15:58:14 -0700463 if key.endswith('_selinux_fc'):
Daniel Normand5d70ea2019-06-05 15:13:43 -0700464 merged_dict[key] = 'framework_file_contexts.bin'
Daniel Norman72c626f2019-05-13 15:58:14 -0700465
Daniel Normane5b134a2019-04-17 14:54:06 -0700466 output_misc_info_txt = os.path.join(output_target_files_temp_dir, 'META',
467 'misc_info.txt')
Daniel Normand5d70ea2019-06-05 15:13:43 -0700468 write_sorted_data(data=merged_dict, path=output_misc_info_txt)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800469
470
Daniel Normand5d70ea2019-06-05 15:13:43 -0700471def process_dynamic_partitions_info_txt(framework_target_files_dir,
472 vendor_target_files_dir,
Daniel Normana61cde02019-05-03 14:19:13 -0700473 output_target_files_dir):
Tao Bao2ad4b822019-06-27 16:52:12 -0700474 """Performs special processing for META/dynamic_partitions_info.txt.
Daniel Normana61cde02019-05-03 14:19:13 -0700475
476 This function merges the contents of the META/dynamic_partitions_info.txt
Daniel Normand5d70ea2019-06-05 15:13:43 -0700477 files from the framework directory and the vendor directory, placing the
478 merged result in the output directory.
Daniel Normana61cde02019-05-03 14:19:13 -0700479
Daniel Normand5d70ea2019-06-05 15:13:43 -0700480 This function does nothing if META/dynamic_partitions_info.txt from the vendor
Daniel Normana61cde02019-05-03 14:19:13 -0700481 directory does not exist.
482
483 Args:
Daniel Normand5d70ea2019-06-05 15:13:43 -0700484 framework_target_files_dir: The name of a directory containing the special
485 items extracted from the framework target files package.
486 vendor_target_files_dir: The name of a directory containing the special
487 items extracted from the vendor target files package.
Daniel Normana61cde02019-05-03 14:19:13 -0700488 output_target_files_dir: The name of a directory that will be used to create
489 the output target files package after all the special cases are processed.
490 """
491
492 if not os.path.exists(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700493 os.path.join(vendor_target_files_dir, 'META',
Daniel Normana61cde02019-05-03 14:19:13 -0700494 'dynamic_partitions_info.txt')):
495 return
496
Kiyoung Kimebe7c9c2019-06-25 17:09:55 +0900497 dynamic_partitions_info_path = ['META', 'dynamic_partitions_info.txt']
Daniel Normana61cde02019-05-03 14:19:13 -0700498
Kiyoung Kimebe7c9c2019-06-25 17:09:55 +0900499 framework_dynamic_partitions_dict = common.LoadDictionaryFromFile(
500 os.path.join(framework_target_files_dir, *dynamic_partitions_info_path))
501 vendor_dynamic_partitions_dict = common.LoadDictionaryFromFile(
502 os.path.join(vendor_target_files_dir, *dynamic_partitions_info_path))
Daniel Normana61cde02019-05-03 14:19:13 -0700503
Daniel Normanbfc51ef2019-07-24 14:34:54 -0700504 merged_dynamic_partitions_dict = common.MergeDynamicPartitionInfoDicts(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700505 framework_dict=framework_dynamic_partitions_dict,
Daniel Norman55417142019-11-25 16:04:36 -0800506 vendor_dict=vendor_dynamic_partitions_dict)
Daniel Normana61cde02019-05-03 14:19:13 -0700507
508 output_dynamic_partitions_info_txt = os.path.join(
509 output_target_files_dir, 'META', 'dynamic_partitions_info.txt')
Chris Grossfabf50a2019-05-02 12:42:09 -0700510 write_sorted_data(
511 data=merged_dynamic_partitions_dict,
512 path=output_dynamic_partitions_info_txt)
513
514
Bill Peckham19c3feb2020-03-20 18:31:43 -0700515def item_list_to_partition_set(item_list):
516 """Converts a target files item list to a partition set.
517
518 The item list contains items that might look like 'SYSTEM/*' or 'VENDOR/*' or
519 'OTA/android-info.txt'. Items that end in '/*' are assumed to match entire
520 directories where 'SYSTEM' or 'VENDOR' is a directory name that identifies the
521 contents of a partition of the same name. Other items in the list, such as the
522 'OTA' example contain metadata. This function iterates such a list, returning
523 a set that contains the partition entries.
524
525 Args:
526 item_list: A list of items in a target files package.
527 Returns:
528 A set of partitions extracted from the list of items.
529 """
530
531 partition_set = set()
532
533 for item in item_list:
534 match = PARTITION_ITEM_PATTERN.search(item.strip())
535 partition_tag = match.group(1).lower() if match else None
536
537 if partition_tag:
538 partition_set.add(partition_tag)
539
540 return partition_set
541
542
Daniel Normand5d70ea2019-06-05 15:13:43 -0700543def process_apex_keys_apk_certs_common(framework_target_files_dir,
544 vendor_target_files_dir,
Bill Peckham19c3feb2020-03-20 18:31:43 -0700545 output_target_files_dir,
546 framework_partition_set,
547 vendor_partition_set, file_name):
548
Tao Bao2ad4b822019-06-27 16:52:12 -0700549 """Performs special processing for META/apexkeys.txt or META/apkcerts.txt.
Chris Grossfabf50a2019-05-02 12:42:09 -0700550
551 This function merges the contents of the META/apexkeys.txt or
Tao Bao2ad4b822019-06-27 16:52:12 -0700552 META/apkcerts.txt files from the framework directory and the vendor directory,
553 placing the merged result in the output directory. The precondition in that
554 the files are already extracted. The post condition is that the output
555 META/apexkeys.txt or META/apkcerts.txt contains the merged content.
Chris Grossfabf50a2019-05-02 12:42:09 -0700556
557 Args:
Daniel Normand5d70ea2019-06-05 15:13:43 -0700558 framework_target_files_dir: The name of a directory containing the special
559 items extracted from the framework target files package.
560 vendor_target_files_dir: The name of a directory containing the special
561 items extracted from the vendor target files package.
Chris Grossfabf50a2019-05-02 12:42:09 -0700562 output_target_files_dir: The name of a directory that will be used to create
563 the output target files package after all the special cases are processed.
Bill Peckham19c3feb2020-03-20 18:31:43 -0700564 framework_partition_set: Partitions that are considered framework
565 partitions. Used to filter apexkeys.txt and apkcerts.txt.
566 vendor_partition_set: Partitions that are considered vendor partitions. Used
567 to filter apexkeys.txt and apkcerts.txt.
Chris Grossfabf50a2019-05-02 12:42:09 -0700568 file_name: The name of the file to merge. One of apkcerts.txt or
569 apexkeys.txt.
570 """
571
572 def read_helper(d):
573 temp = {}
574 file_path = os.path.join(d, 'META', file_name)
575 with open(file_path) as f:
576 for line in f:
577 if line.strip():
Bill Peckham19c3feb2020-03-20 18:31:43 -0700578 name = line.split()[0]
579 match = MODULE_KEY_PATTERN.search(name)
580 temp[match.group(1)] = line.strip()
Chris Grossfabf50a2019-05-02 12:42:09 -0700581 return temp
582
Daniel Normand5d70ea2019-06-05 15:13:43 -0700583 framework_dict = read_helper(framework_target_files_dir)
584 vendor_dict = read_helper(vendor_target_files_dir)
Bill Peckham19c3feb2020-03-20 18:31:43 -0700585 merged_dict = {}
Chris Grossfabf50a2019-05-02 12:42:09 -0700586
Bill Peckham19c3feb2020-03-20 18:31:43 -0700587 def filter_into_merged_dict(item_dict, partition_set):
588 for key, value in item_dict.items():
589 match = PARTITION_TAG_PATTERN.search(value)
590
591 if match is None:
592 raise ValueError('Entry missing partition tag: %s' % value)
593
594 partition_tag = match.group(1)
595
596 if partition_tag in partition_set:
597 if key in merged_dict:
598 raise ValueError('Duplicate key %s' % key)
599
600 merged_dict[key] = value
601
602 filter_into_merged_dict(framework_dict, framework_partition_set)
603 filter_into_merged_dict(vendor_dict, vendor_partition_set)
Chris Grossfabf50a2019-05-02 12:42:09 -0700604
605 output_file = os.path.join(output_target_files_dir, 'META', file_name)
606
Bill Peckham19c3feb2020-03-20 18:31:43 -0700607 # The following code is similar to write_sorted_data, but different enough
608 # that we couldn't use that function. We need the output to be sorted by the
609 # basename of the apex/apk (without the ".apex" or ".apk" suffix). This
610 # allows the sort to be consistent with the framework/vendor input data and
611 # eases comparison of input data with merged data.
612 with open(output_file, 'w') as output:
613 for key in sorted(merged_dict.keys()):
614 out_str = merged_dict[key] + '\n'
615 output.write(out_str)
Daniel Normana61cde02019-05-03 14:19:13 -0700616
617
Daniel Normand5d70ea2019-06-05 15:13:43 -0700618def copy_file_contexts(framework_target_files_dir, vendor_target_files_dir,
Daniel Norman72c626f2019-05-13 15:58:14 -0700619 output_target_files_dir):
620 """Creates named copies of each build's file_contexts.bin in output META/."""
Daniel Normand5d70ea2019-06-05 15:13:43 -0700621 framework_fc_path = os.path.join(framework_target_files_dir, 'META',
622 'framework_file_contexts.bin')
623 if not os.path.exists(framework_fc_path):
624 framework_fc_path = os.path.join(framework_target_files_dir, 'META',
625 'file_contexts.bin')
626 if not os.path.exists(framework_fc_path):
627 raise ValueError('Missing framework file_contexts.bin.')
628 shutil.copyfile(
629 framework_fc_path,
630 os.path.join(output_target_files_dir, 'META',
631 'framework_file_contexts.bin'))
632
633 vendor_fc_path = os.path.join(vendor_target_files_dir, 'META',
634 'vendor_file_contexts.bin')
635 if not os.path.exists(vendor_fc_path):
636 vendor_fc_path = os.path.join(vendor_target_files_dir, 'META',
Daniel Normanedf12472019-05-22 10:47:08 -0700637 'file_contexts.bin')
Daniel Normand5d70ea2019-06-05 15:13:43 -0700638 if not os.path.exists(vendor_fc_path):
639 raise ValueError('Missing vendor file_contexts.bin.')
Daniel Norman72c626f2019-05-13 15:58:14 -0700640 shutil.copyfile(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700641 vendor_fc_path,
642 os.path.join(output_target_files_dir, 'META', 'vendor_file_contexts.bin'))
Daniel Norman72c626f2019-05-13 15:58:14 -0700643
644
Daniel Normand5d70ea2019-06-05 15:13:43 -0700645def process_special_cases(framework_target_files_temp_dir,
646 vendor_target_files_temp_dir,
647 output_target_files_temp_dir,
Bill Peckham19c3feb2020-03-20 18:31:43 -0700648 framework_misc_info_keys,
649 framework_partition_set,
650 vendor_partition_set):
Tao Bao2ad4b822019-06-27 16:52:12 -0700651 """Performs special-case processing for certain target files items.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800652
653 Certain files in the output target files package require special-case
654 processing. This function performs all that special-case processing.
655
656 Args:
Daniel Normand5d70ea2019-06-05 15:13:43 -0700657 framework_target_files_temp_dir: The name of a directory containing the
658 special items extracted from the framework target files package.
659 vendor_target_files_temp_dir: The name of a directory containing the special
660 items extracted from the vendor target files package.
Daniel Normane5b134a2019-04-17 14:54:06 -0700661 output_target_files_temp_dir: The name of a directory that will be used to
662 create the output target files package after all the special cases are
663 processed.
Daniel Normand5d70ea2019-06-05 15:13:43 -0700664 framework_misc_info_keys: A list of keys to obtain from the framework
665 instance of META/misc_info.txt. The remaining keys from the vendor
666 instance.
Bill Peckham19c3feb2020-03-20 18:31:43 -0700667 framework_partition_set: Partitions that are considered framework
668 partitions. Used to filter apexkeys.txt and apkcerts.txt.
669 vendor_partition_set: Partitions that are considered vendor partitions. Used
670 to filter apexkeys.txt and apkcerts.txt.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800671 """
672
Daniel Normand5d70ea2019-06-05 15:13:43 -0700673 if 'ab_update' in framework_misc_info_keys:
Bill Peckham364c1cc2019-03-29 18:27:23 -0700674 process_ab_partitions_txt(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700675 framework_target_files_temp_dir=framework_target_files_temp_dir,
676 vendor_target_files_temp_dir=vendor_target_files_temp_dir,
Bill Peckham364c1cc2019-03-29 18:27:23 -0700677 output_target_files_temp_dir=output_target_files_temp_dir)
678
Daniel Norman72c626f2019-05-13 15:58:14 -0700679 copy_file_contexts(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700680 framework_target_files_dir=framework_target_files_temp_dir,
681 vendor_target_files_dir=vendor_target_files_temp_dir,
Daniel Norman72c626f2019-05-13 15:58:14 -0700682 output_target_files_dir=output_target_files_temp_dir)
683
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800684 process_misc_info_txt(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700685 framework_target_files_temp_dir=framework_target_files_temp_dir,
686 vendor_target_files_temp_dir=vendor_target_files_temp_dir,
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800687 output_target_files_temp_dir=output_target_files_temp_dir,
Daniel Normand5d70ea2019-06-05 15:13:43 -0700688 framework_misc_info_keys=framework_misc_info_keys)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800689
Daniel Normana61cde02019-05-03 14:19:13 -0700690 process_dynamic_partitions_info_txt(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700691 framework_target_files_dir=framework_target_files_temp_dir,
692 vendor_target_files_dir=vendor_target_files_temp_dir,
Daniel Norman714bd122019-05-08 16:20:02 -0700693 output_target_files_dir=output_target_files_temp_dir)
Daniel Normana61cde02019-05-03 14:19:13 -0700694
Chris Grossfabf50a2019-05-02 12:42:09 -0700695 process_apex_keys_apk_certs_common(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700696 framework_target_files_dir=framework_target_files_temp_dir,
697 vendor_target_files_dir=vendor_target_files_temp_dir,
Chris Grossfabf50a2019-05-02 12:42:09 -0700698 output_target_files_dir=output_target_files_temp_dir,
Bill Peckham19c3feb2020-03-20 18:31:43 -0700699 framework_partition_set=framework_partition_set,
700 vendor_partition_set=vendor_partition_set,
Chris Grossfabf50a2019-05-02 12:42:09 -0700701 file_name='apkcerts.txt')
702
703 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='apexkeys.txt')
710
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800711
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900712def files_from_path(target_path, extra_args=None):
Tao Bao2ad4b822019-06-27 16:52:12 -0700713 """Gets files under given path.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800714
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900715 Get (sub)files from given target path and return sorted list.
716
717 Args:
718 target_path: Target path to get subfiles.
719 extra_args: List of extra argument for find command. Optional.
720
721 Returns:
722 Sorted files and directories list.
723 """
724
725 find_command = ['find', target_path] + (extra_args or [])
726 find_process = common.Run(find_command, stdout=subprocess.PIPE, verbose=False)
Daniel Norman4cc9df62019-07-18 10:11:07 -0700727 return common.RunAndCheckOutput(['sort'],
728 stdin=find_process.stdout,
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900729 verbose=False)
730
731
732def create_merged_package(temp_dir, framework_target_files, framework_item_list,
733 vendor_target_files, vendor_item_list,
Daniel Norman4cc9df62019-07-18 10:11:07 -0700734 framework_misc_info_keys, rebuild_recovery):
Tao Bao2ad4b822019-06-27 16:52:12 -0700735 """Merges two target files packages into one target files structure.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800736
737 Args:
738 temp_dir: The name of a directory we use when we extract items from the
Daniel Normane5b134a2019-04-17 14:54:06 -0700739 input target files packages, and also a scratch directory that we use for
740 temporary files.
Daniel Normand5d70ea2019-06-05 15:13:43 -0700741 framework_target_files: The name of the zip archive containing the framework
Daniel Normane5b134a2019-04-17 14:54:06 -0700742 partial target files package.
Daniel Normand5d70ea2019-06-05 15:13:43 -0700743 framework_item_list: The list of items to extract from the partial framework
Daniel Normane5b134a2019-04-17 14:54:06 -0700744 target files package as is, meaning these items will land in the output
Daniel Normand5d70ea2019-06-05 15:13:43 -0700745 target files package exactly as they appear in the input partial framework
Daniel Normane5b134a2019-04-17 14:54:06 -0700746 target files package.
Daniel Normand5d70ea2019-06-05 15:13:43 -0700747 vendor_target_files: The name of the zip archive containing the vendor
748 partial target files package.
749 vendor_item_list: The list of items to extract from the partial vendor
750 target files package as is, meaning these items will land in the output
751 target files package exactly as they appear in the input partial vendor
Daniel Normane5b134a2019-04-17 14:54:06 -0700752 target files package.
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900753 framework_misc_info_keys: The list of keys to obtain from the framework
754 instance of META/misc_info.txt. The remaining keys from the vendor
755 instance.
Daniel Normana4911da2019-03-15 14:36:21 -0700756 rebuild_recovery: If true, rebuild the recovery patch used by non-A/B
Daniel Normane5b134a2019-04-17 14:54:06 -0700757 devices and write it to the system image.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800758
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900759 Returns:
760 Path to merged package under temp directory.
761 """
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800762
Daniel Normand5d70ea2019-06-05 15:13:43 -0700763 # Create directory names that we'll use when we extract files from framework,
764 # and vendor, and for zipping the final output.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800765
Daniel Normand5d70ea2019-06-05 15:13:43 -0700766 framework_target_files_temp_dir = os.path.join(temp_dir, 'framework')
767 vendor_target_files_temp_dir = os.path.join(temp_dir, 'vendor')
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800768 output_target_files_temp_dir = os.path.join(temp_dir, 'output')
769
Daniel Normand5d70ea2019-06-05 15:13:43 -0700770 # Extract "as is" items from the input framework partial target files package.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800771 # We extract them directly into the output temporary directory since the
772 # items do not need special case processing.
773
Bill Peckham889b0c62019-02-21 18:53:37 -0800774 extract_items(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700775 target_files=framework_target_files,
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800776 target_files_temp_dir=output_target_files_temp_dir,
Daniel Normand5d70ea2019-06-05 15:13:43 -0700777 extract_item_list=framework_item_list)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800778
Daniel Normand5d70ea2019-06-05 15:13:43 -0700779 # Extract "as is" items from the input vendor partial target files package. We
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800780 # extract them directly into the output temporary directory since the items
781 # do not need special case processing.
782
Bill Peckham889b0c62019-02-21 18:53:37 -0800783 extract_items(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700784 target_files=vendor_target_files,
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800785 target_files_temp_dir=output_target_files_temp_dir,
Daniel Normand5d70ea2019-06-05 15:13:43 -0700786 extract_item_list=vendor_item_list)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800787
Daniel Normand5d70ea2019-06-05 15:13:43 -0700788 # Extract "special" items from the input framework partial target files
789 # package. We extract these items to different directory since they require
790 # special processing before they will end up in the output directory.
791
792 extract_items(
793 target_files=framework_target_files,
794 target_files_temp_dir=framework_target_files_temp_dir,
795 extract_item_list=FRAMEWORK_EXTRACT_SPECIAL_ITEM_LIST)
796
797 # Extract "special" items from the input vendor partial target files package.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800798 # We extract these items to different directory since they require special
799 # processing before they will end up in the output directory.
800
Bill Peckham889b0c62019-02-21 18:53:37 -0800801 extract_items(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700802 target_files=vendor_target_files,
803 target_files_temp_dir=vendor_target_files_temp_dir,
804 extract_item_list=VENDOR_EXTRACT_SPECIAL_ITEM_LIST)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800805
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800806 # Now that the temporary directories contain all the extracted files, perform
807 # special case processing on any items that need it. After this function
808 # completes successfully, all the files we need to create the output target
809 # files package are in place.
810
Bill Peckham889b0c62019-02-21 18:53:37 -0800811 process_special_cases(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700812 framework_target_files_temp_dir=framework_target_files_temp_dir,
813 vendor_target_files_temp_dir=vendor_target_files_temp_dir,
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800814 output_target_files_temp_dir=output_target_files_temp_dir,
Bill Peckham19c3feb2020-03-20 18:31:43 -0700815 framework_misc_info_keys=framework_misc_info_keys,
816 framework_partition_set=item_list_to_partition_set(framework_item_list),
817 vendor_partition_set=item_list_to_partition_set(vendor_item_list))
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800818
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900819 return output_target_files_temp_dir
820
821
822def generate_images(target_files_dir, rebuild_recovery):
823 """Generate images from target files.
824
825 This function takes merged output temporary directory and create images
826 from it.
827
828 Args:
829 target_files_dir: Path to merged temp directory.
830 rebuild_recovery: If true, rebuild the recovery patch used by non-A/B
831 devices and write it to the system image.
832 """
833
834 # Regenerate IMAGES in the target directory.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800835
Daniel Normana4911da2019-03-15 14:36:21 -0700836 add_img_args = ['--verbose']
Paul Trautrimbc3600c2019-08-13 18:07:03 +0900837 add_img_args.append('--add_missing')
Bill Peckhame868aec2019-09-17 17:06:47 -0700838 # TODO(b/132730255): Remove this if statement.
Daniel Normana4911da2019-03-15 14:36:21 -0700839 if rebuild_recovery:
840 add_img_args.append('--rebuild_recovery')
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900841 add_img_args.append(target_files_dir)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800842
843 add_img_to_target_files.main(add_img_args)
844
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900845
846def generate_super_empty_image(target_dir, output_super_empty):
Tao Bao2ad4b822019-06-27 16:52:12 -0700847 """Generates super_empty image from target package.
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900848
849 Args:
850 target_dir: Path to the target file package which contains misc_info.txt for
851 detailed information for super image.
852 output_super_empty: If provided, copies a super_empty.img file from the
853 target files package to this path.
854 """
Daniel Norman1bd2a1d2019-04-18 12:32:18 -0700855 # Create super_empty.img using the merged misc_info.txt.
856
Daniel Norman4cc9df62019-07-18 10:11:07 -0700857 misc_info_txt = os.path.join(target_dir, 'META', 'misc_info.txt')
Daniel Norman1bd2a1d2019-04-18 12:32:18 -0700858
Kiyoung Kimebe7c9c2019-06-25 17:09:55 +0900859 use_dynamic_partitions = common.LoadDictionaryFromFile(misc_info_txt).get(
860 'use_dynamic_partitions')
Daniel Norman1bd2a1d2019-04-18 12:32:18 -0700861
862 if use_dynamic_partitions != 'true' and output_super_empty:
863 raise ValueError(
864 'Building super_empty.img requires use_dynamic_partitions=true.')
865 elif use_dynamic_partitions == 'true':
Daniel Norman4cc9df62019-07-18 10:11:07 -0700866 super_empty_img = os.path.join(target_dir, 'IMAGES', 'super_empty.img')
Daniel Norman1bd2a1d2019-04-18 12:32:18 -0700867 build_super_image_args = [
868 misc_info_txt,
869 super_empty_img,
870 ]
871 build_super_image.main(build_super_image_args)
872
873 # Copy super_empty.img to the user-provided output_super_empty location.
874 if output_super_empty:
875 shutil.copyfile(super_empty_img, output_super_empty)
876
Daniel Normanb8a2f9d2019-04-24 12:55:51 -0700877
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900878def create_target_files_archive(output_file, source_dir, temp_dir):
Tao Bao2ad4b822019-06-27 16:52:12 -0700879 """Creates archive from target package.
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900880
881 Args:
882 output_file: The name of the zip archive target files package.
883 source_dir: The target directory contains package to be archived.
884 temp_dir: Path to temporary directory for any intermediate files.
885 """
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800886 output_target_files_list = os.path.join(temp_dir, 'output.list')
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900887 output_zip = os.path.abspath(output_file)
Daniel Norman4cc9df62019-07-18 10:11:07 -0700888 output_target_files_meta_dir = os.path.join(source_dir, 'META')
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800889
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900890 meta_content = files_from_path(output_target_files_meta_dir)
Daniel Norman4cc9df62019-07-18 10:11:07 -0700891 other_content = files_from_path(
892 source_dir,
893 ['-path', output_target_files_meta_dir, '-prune', '-o', '-print'])
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800894
Tao Bao2ad4b822019-06-27 16:52:12 -0700895 with open(output_target_files_list, 'w') as f:
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800896 f.write(meta_content)
897 f.write(other_content)
898
899 command = [
Bill Peckhamf753e152019-02-19 18:02:46 -0800900 'soong_zip',
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800901 '-d',
Daniel Normane5b134a2019-04-17 14:54:06 -0700902 '-o',
903 output_zip,
904 '-C',
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900905 source_dir,
Daniel Normane5b134a2019-04-17 14:54:06 -0700906 '-l',
907 output_target_files_list,
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800908 ]
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900909
910 logger.info('creating %s', output_file)
Bill Peckham889b0c62019-02-21 18:53:37 -0800911 common.RunAndWait(command, verbose=True)
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900912 logger.info('finished creating %s', output_file)
913
914 return output_zip
915
916
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900917def merge_target_files(temp_dir, framework_target_files, framework_item_list,
918 framework_misc_info_keys, vendor_target_files,
919 vendor_item_list, output_target_files, output_dir,
920 output_item_list, output_ota, output_img,
921 output_super_empty, rebuild_recovery):
Tao Bao2ad4b822019-06-27 16:52:12 -0700922 """Merges two target files packages together.
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900923
924 This function takes framework and vendor target files packages as input,
925 performs various file extractions, special case processing, and finally
926 creates a merged zip archive as output.
927
928 Args:
929 temp_dir: The name of a directory we use when we extract items from the
930 input target files packages, and also a scratch directory that we use for
931 temporary files.
932 framework_target_files: The name of the zip archive containing the framework
933 partial target files package.
934 framework_item_list: The list of items to extract from the partial framework
935 target files package as is, meaning these items will land in the output
936 target files package exactly as they appear in the input partial framework
937 target files package.
938 framework_misc_info_keys: The list of keys to obtain from the framework
939 instance of META/misc_info.txt. The remaining keys from the vendor
940 instance.
941 vendor_target_files: The name of the zip archive containing the vendor
942 partial target files package.
943 vendor_item_list: The list of items to extract from the partial vendor
944 target files package as is, meaning these items will land in the output
945 target files package exactly as they appear in the input partial vendor
946 target files package.
947 output_target_files: The name of the output zip archive target files package
948 created by merging framework and vendor.
949 output_dir: The destination directory for saving merged files.
950 output_item_list: The list of items to copy into the output_dir.
951 output_ota: The name of the output zip archive ota package.
952 output_img: The name of the output zip archive img package.
953 output_super_empty: If provided, creates a super_empty.img file from the
954 merged target files package and saves it at this path.
955 rebuild_recovery: If true, rebuild the recovery patch used by non-A/B
956 devices and write it to the system image.
957 """
958
959 logger.info('starting: merge framework %s and vendor %s into output %s',
960 framework_target_files, vendor_target_files, output_target_files)
961
962 output_target_files_temp_dir = create_merged_package(
963 temp_dir, framework_target_files, framework_item_list,
964 vendor_target_files, vendor_item_list, framework_misc_info_keys,
965 rebuild_recovery)
966
Yifan Hongade0d3f2019-08-21 16:37:11 -0700967 if not check_target_files_vintf.CheckVintf(output_target_files_temp_dir):
968 raise RuntimeError("Incompatible VINTF metadata")
969
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900970 generate_images(output_target_files_temp_dir, rebuild_recovery)
971
972 generate_super_empty_image(output_target_files_temp_dir, output_super_empty)
973
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900974 # Finally, create the output target files zip archive and/or copy the
975 # output items to the output target files directory.
976
977 if output_dir:
978 copy_items(output_target_files_temp_dir, output_dir, output_item_list)
979
980 if not output_target_files:
981 return
982
983 output_zip = create_target_files_archive(output_target_files,
984 output_target_files_temp_dir,
985 temp_dir)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800986
Daniel Norman74eb74b2019-09-18 14:01:48 -0700987 # Create the IMG package from the merged target files package.
988
989 if output_img:
990 img_from_target_files.main([output_zip, output_img])
991
Daniel Norman3b64ce12019-04-16 16:11:35 -0700992 # Create the OTA package from the merged target files package.
993
994 if output_ota:
Daniel Norman4cc9df62019-07-18 10:11:07 -0700995 ota_from_target_files.main([output_zip, output_ota])
Daniel Norman3b64ce12019-04-16 16:11:35 -0700996
Daniel Norman1bd2a1d2019-04-18 12:32:18 -0700997
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800998def call_func_with_temp_dir(func, keep_tmp):
Tao Bao2ad4b822019-06-27 16:52:12 -0700999 """Manages the creation and cleanup of the temporary directory.
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001000
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001001 This function calls the given function after first creating a temporary
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001002 directory. It also cleans up the temporary directory.
1003
1004 Args:
Daniel Normane5b134a2019-04-17 14:54:06 -07001005 func: The function to call. Should accept one parameter, the path to the
1006 temporary directory.
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001007 keep_tmp: Keep the temporary directory after processing is complete.
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001008 """
1009
1010 # Create a temporary directory. This will serve as the parent of directories
1011 # we use when we extract items from the input target files packages, and also
1012 # a scratch directory that we use for temporary files.
1013
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001014 temp_dir = common.MakeTempDir(prefix='merge_target_files_')
1015
1016 try:
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001017 func(temp_dir)
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001018 finally:
1019 if keep_tmp:
1020 logger.info('keeping %s', temp_dir)
1021 else:
1022 common.Cleanup()
1023
1024
1025def main():
1026 """The main function.
1027
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001028 Process command line arguments, then call merge_target_files to
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001029 perform the heavy lifting.
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001030 """
1031
1032 common.InitLogging()
1033
Bill Peckhamf753e152019-02-19 18:02:46 -08001034 def option_handler(o, a):
1035 if o == '--system-target-files':
Daniel Normand5d70ea2019-06-05 15:13:43 -07001036 logger.warning(
1037 '--system-target-files has been renamed to --framework-target-files')
1038 OPTIONS.framework_target_files = a
1039 elif o == '--framework-target-files':
1040 OPTIONS.framework_target_files = a
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001041 elif o == '--system-item-list':
Daniel Normand5d70ea2019-06-05 15:13:43 -07001042 logger.warning(
1043 '--system-item-list has been renamed to --framework-item-list')
1044 OPTIONS.framework_item_list = a
1045 elif o == '--framework-item-list':
1046 OPTIONS.framework_item_list = a
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001047 elif o == '--system-misc-info-keys':
Daniel Norman4cc9df62019-07-18 10:11:07 -07001048 logger.warning('--system-misc-info-keys has been renamed to '
1049 '--framework-misc-info-keys')
Daniel Normand5d70ea2019-06-05 15:13:43 -07001050 OPTIONS.framework_misc_info_keys = a
1051 elif o == '--framework-misc-info-keys':
1052 OPTIONS.framework_misc_info_keys = a
Bill Peckhamf753e152019-02-19 18:02:46 -08001053 elif o == '--other-target-files':
Daniel Normand5d70ea2019-06-05 15:13:43 -07001054 logger.warning(
1055 '--other-target-files has been renamed to --vendor-target-files')
1056 OPTIONS.vendor_target_files = a
1057 elif o == '--vendor-target-files':
1058 OPTIONS.vendor_target_files = a
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001059 elif o == '--other-item-list':
Daniel Normand5d70ea2019-06-05 15:13:43 -07001060 logger.warning('--other-item-list has been renamed to --vendor-item-list')
1061 OPTIONS.vendor_item_list = a
1062 elif o == '--vendor-item-list':
1063 OPTIONS.vendor_item_list = a
Bill Peckhamf753e152019-02-19 18:02:46 -08001064 elif o == '--output-target-files':
1065 OPTIONS.output_target_files = a
Daniel Normanfdb38812019-04-15 09:47:24 -07001066 elif o == '--output-dir':
1067 OPTIONS.output_dir = a
1068 elif o == '--output-item-list':
1069 OPTIONS.output_item_list = a
Daniel Norman3b64ce12019-04-16 16:11:35 -07001070 elif o == '--output-ota':
1071 OPTIONS.output_ota = a
Daniel Norman1bd2a1d2019-04-18 12:32:18 -07001072 elif o == '--output-img':
1073 OPTIONS.output_img = a
Daniel Normanf0318252019-04-15 11:34:56 -07001074 elif o == '--output-super-empty':
1075 OPTIONS.output_super_empty = a
Bill Peckhame868aec2019-09-17 17:06:47 -07001076 elif o == '--rebuild_recovery': # TODO(b/132730255): Warn
Daniel Normana4911da2019-03-15 14:36:21 -07001077 OPTIONS.rebuild_recovery = True
Bill Peckham364c1cc2019-03-29 18:27:23 -07001078 elif o == '--keep-tmp':
Bill Peckhamf753e152019-02-19 18:02:46 -08001079 OPTIONS.keep_tmp = True
1080 else:
1081 return False
1082 return True
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001083
Bill Peckhamf753e152019-02-19 18:02:46 -08001084 args = common.ParseOptions(
Daniel Normane5b134a2019-04-17 14:54:06 -07001085 sys.argv[1:],
1086 __doc__,
Bill Peckhamf753e152019-02-19 18:02:46 -08001087 extra_long_opts=[
1088 'system-target-files=',
Daniel Normand5d70ea2019-06-05 15:13:43 -07001089 'framework-target-files=',
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001090 'system-item-list=',
Daniel Normand5d70ea2019-06-05 15:13:43 -07001091 'framework-item-list=',
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001092 'system-misc-info-keys=',
Daniel Normand5d70ea2019-06-05 15:13:43 -07001093 'framework-misc-info-keys=',
Bill Peckhamf753e152019-02-19 18:02:46 -08001094 'other-target-files=',
Daniel Normand5d70ea2019-06-05 15:13:43 -07001095 'vendor-target-files=',
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001096 'other-item-list=',
Daniel Normand5d70ea2019-06-05 15:13:43 -07001097 'vendor-item-list=',
Bill Peckhamf753e152019-02-19 18:02:46 -08001098 'output-target-files=',
Daniel Normanfdb38812019-04-15 09:47:24 -07001099 'output-dir=',
1100 'output-item-list=',
Daniel Norman3b64ce12019-04-16 16:11:35 -07001101 'output-ota=',
Daniel Norman1bd2a1d2019-04-18 12:32:18 -07001102 'output-img=',
Daniel Normanf0318252019-04-15 11:34:56 -07001103 'output-super-empty=',
Daniel Normana4911da2019-03-15 14:36:21 -07001104 'rebuild_recovery',
Bill Peckham364c1cc2019-03-29 18:27:23 -07001105 'keep-tmp',
Bill Peckhamf753e152019-02-19 18:02:46 -08001106 ],
1107 extra_option_handler=option_handler)
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001108
Tao Bao2ad4b822019-06-27 16:52:12 -07001109 # pylint: disable=too-many-boolean-expressions
Daniel Normand5d70ea2019-06-05 15:13:43 -07001110 if (args or OPTIONS.framework_target_files is None or
1111 OPTIONS.vendor_target_files is None or
Daniel Normane5b134a2019-04-17 14:54:06 -07001112 (OPTIONS.output_target_files is None and OPTIONS.output_dir is None) or
1113 (OPTIONS.output_dir is not None and OPTIONS.output_item_list is None)):
Bill Peckhamf753e152019-02-19 18:02:46 -08001114 common.Usage(__doc__)
Bill Peckham889b0c62019-02-21 18:53:37 -08001115 sys.exit(1)
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001116
Daniel Normand5d70ea2019-06-05 15:13:43 -07001117 if OPTIONS.framework_item_list:
Daniel Norman4cc9df62019-07-18 10:11:07 -07001118 framework_item_list = common.LoadListFromFile(OPTIONS.framework_item_list)
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001119 else:
Daniel Normand5d70ea2019-06-05 15:13:43 -07001120 framework_item_list = DEFAULT_FRAMEWORK_ITEM_LIST
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001121
Daniel Normand5d70ea2019-06-05 15:13:43 -07001122 if OPTIONS.framework_misc_info_keys:
Daniel Norman4cc9df62019-07-18 10:11:07 -07001123 framework_misc_info_keys = common.LoadListFromFile(
Daniel Normand5d70ea2019-06-05 15:13:43 -07001124 OPTIONS.framework_misc_info_keys)
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001125 else:
Daniel Normand5d70ea2019-06-05 15:13:43 -07001126 framework_misc_info_keys = DEFAULT_FRAMEWORK_MISC_INFO_KEYS
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001127
Daniel Normand5d70ea2019-06-05 15:13:43 -07001128 if OPTIONS.vendor_item_list:
Daniel Norman4cc9df62019-07-18 10:11:07 -07001129 vendor_item_list = common.LoadListFromFile(OPTIONS.vendor_item_list)
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001130 else:
Daniel Normand5d70ea2019-06-05 15:13:43 -07001131 vendor_item_list = DEFAULT_VENDOR_ITEM_LIST
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001132
Daniel Normanfdb38812019-04-15 09:47:24 -07001133 if OPTIONS.output_item_list:
Daniel Norman4cc9df62019-07-18 10:11:07 -07001134 output_item_list = common.LoadListFromFile(OPTIONS.output_item_list)
Daniel Normanfdb38812019-04-15 09:47:24 -07001135 else:
1136 output_item_list = None
1137
Daniel Normane5964522019-03-19 10:32:03 -07001138 if not validate_config_lists(
Daniel Normand5d70ea2019-06-05 15:13:43 -07001139 framework_item_list=framework_item_list,
1140 framework_misc_info_keys=framework_misc_info_keys,
1141 vendor_item_list=vendor_item_list):
Daniel Normane5964522019-03-19 10:32:03 -07001142 sys.exit(1)
1143
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001144 call_func_with_temp_dir(
1145 lambda temp_dir: merge_target_files(
1146 temp_dir=temp_dir,
Daniel Normand5d70ea2019-06-05 15:13:43 -07001147 framework_target_files=OPTIONS.framework_target_files,
1148 framework_item_list=framework_item_list,
1149 framework_misc_info_keys=framework_misc_info_keys,
1150 vendor_target_files=OPTIONS.vendor_target_files,
1151 vendor_item_list=vendor_item_list,
Daniel Normana4911da2019-03-15 14:36:21 -07001152 output_target_files=OPTIONS.output_target_files,
Daniel Normanfdb38812019-04-15 09:47:24 -07001153 output_dir=OPTIONS.output_dir,
1154 output_item_list=output_item_list,
Daniel Norman3b64ce12019-04-16 16:11:35 -07001155 output_ota=OPTIONS.output_ota,
Daniel Norman1bd2a1d2019-04-18 12:32:18 -07001156 output_img=OPTIONS.output_img,
Daniel Normanf0318252019-04-15 11:34:56 -07001157 output_super_empty=OPTIONS.output_super_empty,
Daniel Normane5b134a2019-04-17 14:54:06 -07001158 rebuild_recovery=OPTIONS.rebuild_recovery), OPTIONS.keep_tmp)
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001159
1160
1161if __name__ == '__main__':
Bill Peckham889b0c62019-02-21 18:53:37 -08001162 main()