blob: d9d38540563016587f1ec7b6178d6ae632e5cd80 [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',
Daniel Normanedf12472019-05-22 10:47:08 -0700178)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800179
Daniel Normand5d70ea2019-06-05 15:13:43 -0700180# DEFAULT_VENDOR_ITEM_LIST is a list of items to extract from the partial
181# vendor target files package as is, meaning these items will land in the output
182# target files package exactly as they appear in the input partial vendor target
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800183# files package.
184
Daniel Normand5d70ea2019-06-05 15:13:43 -0700185DEFAULT_VENDOR_ITEM_LIST = (
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800186 'META/boot_filesystem_config.txt',
187 'META/otakeys.txt',
188 'META/releasetools.py',
189 'META/vendor_filesystem_config.txt',
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800190 'BOOT/*',
191 'DATA/*',
192 'ODM/*',
193 'OTA/android-info.txt',
194 'PREBUILT_IMAGES/*',
195 'RADIO/*',
196 'VENDOR/*',
Daniel Normanedf12472019-05-22 10:47:08 -0700197)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800198
Daniel Normand5d70ea2019-06-05 15:13:43 -0700199# VENDOR_EXTRACT_SPECIAL_ITEM_LIST is a list of items to extract from the
200# partial vendor target files package that need some special processing, such as
201# some sort of combination with items from the partial framework target files
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800202# package.
203
Daniel Normand5d70ea2019-06-05 15:13:43 -0700204VENDOR_EXTRACT_SPECIAL_ITEM_LIST = ('META/*',)
Daniel Normanedf12472019-05-22 10:47:08 -0700205
206# 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/',
223)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800224
225
Chris Grossfabf50a2019-05-02 12:42:09 -0700226def write_sorted_data(data, path):
Tao Bao2ad4b822019-06-27 16:52:12 -0700227 """Writes the sorted contents of either a list or dict to file.
Chris Grossfabf50a2019-05-02 12:42:09 -0700228
Tao Bao2ad4b822019-06-27 16:52:12 -0700229 This function sorts the contents of the list or dict and then writes the
230 resulting sorted contents to a file specified by path.
Chris Grossfabf50a2019-05-02 12:42:09 -0700231
232 Args:
233 data: The list or dict to sort and write.
234 path: Path to the file to write the sorted values to. The file at path will
235 be overridden if it exists.
236 """
237 with open(path, 'w') as output:
Daniel Normand5d70ea2019-06-05 15:13:43 -0700238 for entry in sorted(data):
Chris Grossfabf50a2019-05-02 12:42:09 -0700239 out_str = '{}={}\n'.format(entry, data[entry]) if isinstance(
240 data, dict) else '{}\n'.format(entry)
241 output.write(out_str)
242
243
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800244def extract_items(target_files, target_files_temp_dir, extract_item_list):
Tao Bao2ad4b822019-06-27 16:52:12 -0700245 """Extracts items from target files to temporary directory.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800246
247 This function extracts from the specified target files zip archive into the
248 specified temporary directory, the items specified in the extract item list.
249
250 Args:
251 target_files: The target files zip archive from which to extract items.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800252 target_files_temp_dir: The temporary directory where the extracted items
Daniel Normane5b134a2019-04-17 14:54:06 -0700253 will land.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800254 extract_item_list: A list of items to extract.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800255 """
256
257 logger.info('extracting from %s', target_files)
258
259 # Filter the extract_item_list to remove any items that do not exist in the
260 # zip file. Otherwise, the extraction step will fail.
261
Daniel Norman4cc9df62019-07-18 10:11:07 -0700262 with zipfile.ZipFile(target_files, allowZip64=True) as target_files_zipfile:
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800263 target_files_namelist = target_files_zipfile.namelist()
264
265 filtered_extract_item_list = []
266 for pattern in extract_item_list:
267 matching_namelist = fnmatch.filter(target_files_namelist, pattern)
268 if not matching_namelist:
269 logger.warning('no match for %s', pattern)
270 else:
271 filtered_extract_item_list.append(pattern)
272
Bill Peckham8ff3fbd2019-02-22 10:57:43 -0800273 # Extract from target_files into target_files_temp_dir the
274 # filtered_extract_item_list.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800275
Daniel Normane5b134a2019-04-17 14:54:06 -0700276 common.UnzipToDir(target_files, target_files_temp_dir,
277 filtered_extract_item_list)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800278
279
Daniel Normanfdb38812019-04-15 09:47:24 -0700280def copy_items(from_dir, to_dir, patterns):
281 """Similar to extract_items() except uses an input dir instead of zip."""
282 file_paths = []
283 for dirpath, _, filenames in os.walk(from_dir):
Daniel Normane5b134a2019-04-17 14:54:06 -0700284 file_paths.extend(
285 os.path.relpath(path=os.path.join(dirpath, filename), start=from_dir)
286 for filename in filenames)
Daniel Normanfdb38812019-04-15 09:47:24 -0700287
288 filtered_file_paths = set()
289 for pattern in patterns:
290 filtered_file_paths.update(fnmatch.filter(file_paths, pattern))
291
292 for file_path in filtered_file_paths:
293 original_file_path = os.path.join(from_dir, file_path)
294 copied_file_path = os.path.join(to_dir, file_path)
295 copied_file_dir = os.path.dirname(copied_file_path)
296 if not os.path.exists(copied_file_dir):
297 os.makedirs(copied_file_dir)
298 if os.path.islink(original_file_path):
299 os.symlink(os.readlink(original_file_path), copied_file_path)
300 else:
301 shutil.copyfile(original_file_path, copied_file_path)
302
303
Daniel Normand5d70ea2019-06-05 15:13:43 -0700304def validate_config_lists(framework_item_list, framework_misc_info_keys,
305 vendor_item_list):
Daniel Normane5964522019-03-19 10:32:03 -0700306 """Performs validations on the merge config lists.
307
308 Args:
Daniel Normand5d70ea2019-06-05 15:13:43 -0700309 framework_item_list: The list of items to extract from the partial framework
Daniel Normane5b134a2019-04-17 14:54:06 -0700310 target files package as is.
Daniel Normand5d70ea2019-06-05 15:13:43 -0700311 framework_misc_info_keys: A list of keys to obtain from the framework
312 instance of META/misc_info.txt. The remaining keys from the vendor
313 instance.
314 vendor_item_list: The list of items to extract from the partial vendor
315 target files package as is.
Daniel Normane5964522019-03-19 10:32:03 -0700316
317 Returns:
318 False if a validation fails, otherwise true.
319 """
Daniel Normanedf12472019-05-22 10:47:08 -0700320 has_error = False
321
Daniel Normand5d70ea2019-06-05 15:13:43 -0700322 default_combined_item_set = set(DEFAULT_FRAMEWORK_ITEM_LIST)
323 default_combined_item_set.update(DEFAULT_VENDOR_ITEM_LIST)
Daniel Normane5964522019-03-19 10:32:03 -0700324
Daniel Normand5d70ea2019-06-05 15:13:43 -0700325 combined_item_set = set(framework_item_list)
326 combined_item_set.update(vendor_item_list)
Daniel Normane5964522019-03-19 10:32:03 -0700327
328 # Check that the merge config lists are not missing any item specified
329 # by the default config lists.
330 difference = default_combined_item_set.difference(combined_item_set)
331 if difference:
Daniel Normane5b134a2019-04-17 14:54:06 -0700332 logger.error('Missing merge config items: %s', list(difference))
Daniel Normane5964522019-03-19 10:32:03 -0700333 logger.error('Please ensure missing items are in either the '
Daniel Normand5d70ea2019-06-05 15:13:43 -0700334 'framework-item-list or vendor-item-list files provided to '
Daniel Normane5964522019-03-19 10:32:03 -0700335 'this script.')
Daniel Normanedf12472019-05-22 10:47:08 -0700336 has_error = True
337
338 for partition in SINGLE_BUILD_PARTITIONS:
Daniel Normand5d70ea2019-06-05 15:13:43 -0700339 in_framework = any(
340 item.startswith(partition) for item in framework_item_list)
341 in_vendor = any(item.startswith(partition) for item in vendor_item_list)
342 if in_framework and in_vendor:
Daniel Normanedf12472019-05-22 10:47:08 -0700343 logger.error(
Tao Bao2ad4b822019-06-27 16:52:12 -0700344 'Cannot extract items from %s for both the framework and vendor'
Kiyoung Kimebe7c9c2019-06-25 17:09:55 +0900345 ' builds. Please ensure only one merge config item list'
Tao Bao2ad4b822019-06-27 16:52:12 -0700346 ' includes %s.', partition, partition)
Daniel Normanedf12472019-05-22 10:47:08 -0700347 has_error = True
Daniel Normane5964522019-03-19 10:32:03 -0700348
Daniel Normand5d70ea2019-06-05 15:13:43 -0700349 if ('dynamic_partition_list' in framework_misc_info_keys) or (
350 'super_partition_groups' in framework_misc_info_keys):
Daniel Norman19b9fe92019-03-19 14:48:02 -0700351 logger.error('Dynamic partition misc info keys should come from '
Daniel Normand5d70ea2019-06-05 15:13:43 -0700352 'the vendor instance of META/misc_info.txt.')
Daniel Normanedf12472019-05-22 10:47:08 -0700353 has_error = True
Daniel Norman19b9fe92019-03-19 14:48:02 -0700354
Daniel Normanedf12472019-05-22 10:47:08 -0700355 return not has_error
Daniel Normane5964522019-03-19 10:32:03 -0700356
357
Daniel Normand5d70ea2019-06-05 15:13:43 -0700358def process_ab_partitions_txt(framework_target_files_temp_dir,
359 vendor_target_files_temp_dir,
Daniel Normane5b134a2019-04-17 14:54:06 -0700360 output_target_files_temp_dir):
Tao Bao2ad4b822019-06-27 16:52:12 -0700361 """Performs special processing for META/ab_partitions.txt.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800362
Tao Bao2ad4b822019-06-27 16:52:12 -0700363 This function merges the contents of the META/ab_partitions.txt files from the
364 framework directory and the vendor directory, placing the merged result in the
365 output directory. The precondition in that the files are already extracted.
366 The post condition is that the output META/ab_partitions.txt contains the
367 merged content. The format for each ab_partitions.txt a one partition name per
368 line. The output file contains the union of the parition names.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800369
370 Args:
Daniel Normand5d70ea2019-06-05 15:13:43 -0700371 framework_target_files_temp_dir: The name of a directory containing the
372 special items extracted from the framework target files package.
373 vendor_target_files_temp_dir: The name of a directory containing the special
374 items extracted from the vendor target files package.
Daniel Normane5b134a2019-04-17 14:54:06 -0700375 output_target_files_temp_dir: The name of a directory that will be used to
376 create the output target files package after all the special cases are
377 processed.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800378 """
379
Daniel Normand5d70ea2019-06-05 15:13:43 -0700380 framework_ab_partitions_txt = os.path.join(framework_target_files_temp_dir,
381 'META', 'ab_partitions.txt')
382
383 vendor_ab_partitions_txt = os.path.join(vendor_target_files_temp_dir, 'META',
Daniel Normane5b134a2019-04-17 14:54:06 -0700384 'ab_partitions.txt')
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800385
Daniel Normand5d70ea2019-06-05 15:13:43 -0700386 with open(framework_ab_partitions_txt) as f:
387 framework_ab_partitions = f.read().splitlines()
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800388
Daniel Normand5d70ea2019-06-05 15:13:43 -0700389 with open(vendor_ab_partitions_txt) as f:
390 vendor_ab_partitions = f.read().splitlines()
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800391
Daniel Normand5d70ea2019-06-05 15:13:43 -0700392 output_ab_partitions = set(framework_ab_partitions + vendor_ab_partitions)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800393
Daniel Normane5b134a2019-04-17 14:54:06 -0700394 output_ab_partitions_txt = os.path.join(output_target_files_temp_dir, 'META',
395 'ab_partitions.txt')
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800396
Chris Grossfabf50a2019-05-02 12:42:09 -0700397 write_sorted_data(data=output_ab_partitions, path=output_ab_partitions_txt)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800398
399
Daniel Normand5d70ea2019-06-05 15:13:43 -0700400def process_misc_info_txt(framework_target_files_temp_dir,
401 vendor_target_files_temp_dir,
402 output_target_files_temp_dir,
403 framework_misc_info_keys):
Tao Bao2ad4b822019-06-27 16:52:12 -0700404 """Performs special processing for META/misc_info.txt.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800405
406 This function merges the contents of the META/misc_info.txt files from the
Daniel Normand5d70ea2019-06-05 15:13:43 -0700407 framework directory and the vendor directory, placing the merged result in the
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800408 output directory. The precondition in that the files are already extracted.
409 The post condition is that the output META/misc_info.txt contains the merged
410 content.
411
412 Args:
Daniel Normand5d70ea2019-06-05 15:13:43 -0700413 framework_target_files_temp_dir: The name of a directory containing the
414 special items extracted from the framework target files package.
415 vendor_target_files_temp_dir: The name of a directory containing the special
416 items extracted from the vendor target files package.
Daniel Normane5b134a2019-04-17 14:54:06 -0700417 output_target_files_temp_dir: The name of a directory that will be used to
418 create the output target files package after all the special cases are
419 processed.
Daniel Normand5d70ea2019-06-05 15:13:43 -0700420 framework_misc_info_keys: A list of keys to obtain from the framework
421 instance of META/misc_info.txt. The remaining keys from the vendor
422 instance.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800423 """
424
Kiyoung Kimebe7c9c2019-06-25 17:09:55 +0900425 misc_info_path = ['META', 'misc_info.txt']
426 framework_dict = common.LoadDictionaryFromFile(
427 os.path.join(framework_target_files_temp_dir, *misc_info_path))
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800428
Daniel Normand5d70ea2019-06-05 15:13:43 -0700429 # We take most of the misc info from the vendor target files.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800430
Kiyoung Kimebe7c9c2019-06-25 17:09:55 +0900431 merged_dict = common.LoadDictionaryFromFile(
432 os.path.join(vendor_target_files_temp_dir, *misc_info_path))
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800433
Daniel Normand5d70ea2019-06-05 15:13:43 -0700434 # Replace certain values in merged_dict with values from
435 # framework_dict.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800436
Daniel Normand5d70ea2019-06-05 15:13:43 -0700437 for key in framework_misc_info_keys:
438 merged_dict[key] = framework_dict[key]
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800439
Daniel Norman19b9fe92019-03-19 14:48:02 -0700440 # Merge misc info keys used for Dynamic Partitions.
Daniel Normand5d70ea2019-06-05 15:13:43 -0700441 if (merged_dict.get('use_dynamic_partitions') == 'true') and (
442 framework_dict.get('use_dynamic_partitions') == 'true'):
Daniel Normanbfc51ef2019-07-24 14:34:54 -0700443 merged_dynamic_partitions_dict = common.MergeDynamicPartitionInfoDicts(
Daniel Norman55417142019-11-25 16:04:36 -0800444 framework_dict=framework_dict, vendor_dict=merged_dict)
Daniel Normand5d70ea2019-06-05 15:13:43 -0700445 merged_dict.update(merged_dynamic_partitions_dict)
Tao Bao48a2feb2019-06-28 11:00:05 -0700446 # Ensure that add_img_to_target_files rebuilds super split images for
447 # devices that retrofit dynamic partitions. This flag may have been set to
448 # false in the partial builds to prevent duplicate building of super.img.
Daniel Norman0bf940c2019-06-10 12:50:19 -0700449 merged_dict['build_super_partition'] = 'true'
Daniel Norman19b9fe92019-03-19 14:48:02 -0700450
Daniel Normand5d70ea2019-06-05 15:13:43 -0700451 # Replace <image>_selinux_fc values with framework or vendor file_contexts.bin
Daniel Norman72c626f2019-05-13 15:58:14 -0700452 # depending on which dictionary the key came from.
453 # Only the file basename is required because all selinux_fc properties are
454 # replaced with the full path to the file under META/ when misc_info.txt is
455 # loaded from target files for repacking. See common.py LoadInfoDict().
Daniel Normand5d70ea2019-06-05 15:13:43 -0700456 for key in merged_dict:
Daniel Norman72c626f2019-05-13 15:58:14 -0700457 if key.endswith('_selinux_fc'):
Daniel Normand5d70ea2019-06-05 15:13:43 -0700458 merged_dict[key] = 'vendor_file_contexts.bin'
459 for key in framework_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] = 'framework_file_contexts.bin'
Daniel Norman72c626f2019-05-13 15:58:14 -0700462
Daniel Normane5b134a2019-04-17 14:54:06 -0700463 output_misc_info_txt = os.path.join(output_target_files_temp_dir, 'META',
464 'misc_info.txt')
Daniel Normand5d70ea2019-06-05 15:13:43 -0700465 write_sorted_data(data=merged_dict, path=output_misc_info_txt)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800466
467
Daniel Normand5d70ea2019-06-05 15:13:43 -0700468def process_dynamic_partitions_info_txt(framework_target_files_dir,
469 vendor_target_files_dir,
Daniel Normana61cde02019-05-03 14:19:13 -0700470 output_target_files_dir):
Tao Bao2ad4b822019-06-27 16:52:12 -0700471 """Performs special processing for META/dynamic_partitions_info.txt.
Daniel Normana61cde02019-05-03 14:19:13 -0700472
473 This function merges the contents of the META/dynamic_partitions_info.txt
Daniel Normand5d70ea2019-06-05 15:13:43 -0700474 files from the framework directory and the vendor directory, placing the
475 merged result in the output directory.
Daniel Normana61cde02019-05-03 14:19:13 -0700476
Daniel Normand5d70ea2019-06-05 15:13:43 -0700477 This function does nothing if META/dynamic_partitions_info.txt from the vendor
Daniel Normana61cde02019-05-03 14:19:13 -0700478 directory does not exist.
479
480 Args:
Daniel Normand5d70ea2019-06-05 15:13:43 -0700481 framework_target_files_dir: The name of a directory containing the special
482 items extracted from the framework target files package.
483 vendor_target_files_dir: The name of a directory containing the special
484 items extracted from the vendor target files package.
Daniel Normana61cde02019-05-03 14:19:13 -0700485 output_target_files_dir: The name of a directory that will be used to create
486 the output target files package after all the special cases are processed.
487 """
488
489 if not os.path.exists(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700490 os.path.join(vendor_target_files_dir, 'META',
Daniel Normana61cde02019-05-03 14:19:13 -0700491 'dynamic_partitions_info.txt')):
492 return
493
Kiyoung Kimebe7c9c2019-06-25 17:09:55 +0900494 dynamic_partitions_info_path = ['META', 'dynamic_partitions_info.txt']
Daniel Normana61cde02019-05-03 14:19:13 -0700495
Kiyoung Kimebe7c9c2019-06-25 17:09:55 +0900496 framework_dynamic_partitions_dict = common.LoadDictionaryFromFile(
497 os.path.join(framework_target_files_dir, *dynamic_partitions_info_path))
498 vendor_dynamic_partitions_dict = common.LoadDictionaryFromFile(
499 os.path.join(vendor_target_files_dir, *dynamic_partitions_info_path))
Daniel Normana61cde02019-05-03 14:19:13 -0700500
Daniel Normanbfc51ef2019-07-24 14:34:54 -0700501 merged_dynamic_partitions_dict = common.MergeDynamicPartitionInfoDicts(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700502 framework_dict=framework_dynamic_partitions_dict,
Daniel Norman55417142019-11-25 16:04:36 -0800503 vendor_dict=vendor_dynamic_partitions_dict)
Daniel Normana61cde02019-05-03 14:19:13 -0700504
505 output_dynamic_partitions_info_txt = os.path.join(
506 output_target_files_dir, 'META', 'dynamic_partitions_info.txt')
Chris Grossfabf50a2019-05-02 12:42:09 -0700507 write_sorted_data(
508 data=merged_dynamic_partitions_dict,
509 path=output_dynamic_partitions_info_txt)
510
511
Bill Peckham19c3feb2020-03-20 18:31:43 -0700512def item_list_to_partition_set(item_list):
513 """Converts a target files item list to a partition set.
514
515 The item list contains items that might look like 'SYSTEM/*' or 'VENDOR/*' or
516 'OTA/android-info.txt'. Items that end in '/*' are assumed to match entire
517 directories where 'SYSTEM' or 'VENDOR' is a directory name that identifies the
518 contents of a partition of the same name. Other items in the list, such as the
519 'OTA' example contain metadata. This function iterates such a list, returning
520 a set that contains the partition entries.
521
522 Args:
523 item_list: A list of items in a target files package.
524 Returns:
525 A set of partitions extracted from the list of items.
526 """
527
528 partition_set = set()
529
530 for item in item_list:
531 match = PARTITION_ITEM_PATTERN.search(item.strip())
532 partition_tag = match.group(1).lower() if match else None
533
534 if partition_tag:
535 partition_set.add(partition_tag)
536
537 return partition_set
538
539
Daniel Normand5d70ea2019-06-05 15:13:43 -0700540def process_apex_keys_apk_certs_common(framework_target_files_dir,
541 vendor_target_files_dir,
Bill Peckham19c3feb2020-03-20 18:31:43 -0700542 output_target_files_dir,
543 framework_partition_set,
544 vendor_partition_set, file_name):
545
Tao Bao2ad4b822019-06-27 16:52:12 -0700546 """Performs special processing for META/apexkeys.txt or META/apkcerts.txt.
Chris Grossfabf50a2019-05-02 12:42:09 -0700547
548 This function merges the contents of the META/apexkeys.txt or
Tao Bao2ad4b822019-06-27 16:52:12 -0700549 META/apkcerts.txt files from the framework directory and the vendor directory,
550 placing the merged result in the output directory. The precondition in that
551 the files are already extracted. The post condition is that the output
552 META/apexkeys.txt or META/apkcerts.txt contains the merged content.
Chris Grossfabf50a2019-05-02 12:42:09 -0700553
554 Args:
Daniel Normand5d70ea2019-06-05 15:13:43 -0700555 framework_target_files_dir: The name of a directory containing the special
556 items extracted from the framework target files package.
557 vendor_target_files_dir: The name of a directory containing the special
558 items extracted from the vendor target files package.
Chris Grossfabf50a2019-05-02 12:42:09 -0700559 output_target_files_dir: The name of a directory that will be used to create
560 the output target files package after all the special cases are processed.
Bill Peckham19c3feb2020-03-20 18:31:43 -0700561 framework_partition_set: Partitions that are considered framework
562 partitions. Used to filter apexkeys.txt and apkcerts.txt.
563 vendor_partition_set: Partitions that are considered vendor partitions. Used
564 to filter apexkeys.txt and apkcerts.txt.
Chris Grossfabf50a2019-05-02 12:42:09 -0700565 file_name: The name of the file to merge. One of apkcerts.txt or
566 apexkeys.txt.
567 """
568
569 def read_helper(d):
570 temp = {}
571 file_path = os.path.join(d, 'META', file_name)
572 with open(file_path) as f:
573 for line in f:
574 if line.strip():
Bill Peckham19c3feb2020-03-20 18:31:43 -0700575 name = line.split()[0]
576 match = MODULE_KEY_PATTERN.search(name)
577 temp[match.group(1)] = line.strip()
Chris Grossfabf50a2019-05-02 12:42:09 -0700578 return temp
579
Daniel Normand5d70ea2019-06-05 15:13:43 -0700580 framework_dict = read_helper(framework_target_files_dir)
581 vendor_dict = read_helper(vendor_target_files_dir)
Bill Peckham19c3feb2020-03-20 18:31:43 -0700582 merged_dict = {}
Chris Grossfabf50a2019-05-02 12:42:09 -0700583
Bill Peckham19c3feb2020-03-20 18:31:43 -0700584 def filter_into_merged_dict(item_dict, partition_set):
585 for key, value in item_dict.items():
586 match = PARTITION_TAG_PATTERN.search(value)
587
588 if match is None:
589 raise ValueError('Entry missing partition tag: %s' % value)
590
591 partition_tag = match.group(1)
592
593 if partition_tag in partition_set:
594 if key in merged_dict:
595 raise ValueError('Duplicate key %s' % key)
596
597 merged_dict[key] = value
598
599 filter_into_merged_dict(framework_dict, framework_partition_set)
600 filter_into_merged_dict(vendor_dict, vendor_partition_set)
Chris Grossfabf50a2019-05-02 12:42:09 -0700601
602 output_file = os.path.join(output_target_files_dir, 'META', file_name)
603
Bill Peckham19c3feb2020-03-20 18:31:43 -0700604 # The following code is similar to write_sorted_data, but different enough
605 # that we couldn't use that function. We need the output to be sorted by the
606 # basename of the apex/apk (without the ".apex" or ".apk" suffix). This
607 # allows the sort to be consistent with the framework/vendor input data and
608 # eases comparison of input data with merged data.
609 with open(output_file, 'w') as output:
610 for key in sorted(merged_dict.keys()):
611 out_str = merged_dict[key] + '\n'
612 output.write(out_str)
Daniel Normana61cde02019-05-03 14:19:13 -0700613
614
Daniel Normand5d70ea2019-06-05 15:13:43 -0700615def copy_file_contexts(framework_target_files_dir, vendor_target_files_dir,
Daniel Norman72c626f2019-05-13 15:58:14 -0700616 output_target_files_dir):
617 """Creates named copies of each build's file_contexts.bin in output META/."""
Daniel Normand5d70ea2019-06-05 15:13:43 -0700618 framework_fc_path = os.path.join(framework_target_files_dir, 'META',
619 'framework_file_contexts.bin')
620 if not os.path.exists(framework_fc_path):
621 framework_fc_path = os.path.join(framework_target_files_dir, 'META',
622 'file_contexts.bin')
623 if not os.path.exists(framework_fc_path):
624 raise ValueError('Missing framework file_contexts.bin.')
625 shutil.copyfile(
626 framework_fc_path,
627 os.path.join(output_target_files_dir, 'META',
628 'framework_file_contexts.bin'))
629
630 vendor_fc_path = os.path.join(vendor_target_files_dir, 'META',
631 'vendor_file_contexts.bin')
632 if not os.path.exists(vendor_fc_path):
633 vendor_fc_path = os.path.join(vendor_target_files_dir, 'META',
Daniel Normanedf12472019-05-22 10:47:08 -0700634 'file_contexts.bin')
Daniel Normand5d70ea2019-06-05 15:13:43 -0700635 if not os.path.exists(vendor_fc_path):
636 raise ValueError('Missing vendor file_contexts.bin.')
Daniel Norman72c626f2019-05-13 15:58:14 -0700637 shutil.copyfile(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700638 vendor_fc_path,
639 os.path.join(output_target_files_dir, 'META', 'vendor_file_contexts.bin'))
Daniel Norman72c626f2019-05-13 15:58:14 -0700640
641
Daniel Normand5d70ea2019-06-05 15:13:43 -0700642def process_special_cases(framework_target_files_temp_dir,
643 vendor_target_files_temp_dir,
644 output_target_files_temp_dir,
Bill Peckham19c3feb2020-03-20 18:31:43 -0700645 framework_misc_info_keys,
646 framework_partition_set,
647 vendor_partition_set):
Tao Bao2ad4b822019-06-27 16:52:12 -0700648 """Performs special-case processing for certain target files items.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800649
650 Certain files in the output target files package require special-case
651 processing. This function performs all that special-case processing.
652
653 Args:
Daniel Normand5d70ea2019-06-05 15:13:43 -0700654 framework_target_files_temp_dir: The name of a directory containing the
655 special items extracted from the framework target files package.
656 vendor_target_files_temp_dir: The name of a directory containing the special
657 items extracted from the vendor target files package.
Daniel Normane5b134a2019-04-17 14:54:06 -0700658 output_target_files_temp_dir: The name of a directory that will be used to
659 create the output target files package after all the special cases are
660 processed.
Daniel Normand5d70ea2019-06-05 15:13:43 -0700661 framework_misc_info_keys: A list of keys to obtain from the framework
662 instance of META/misc_info.txt. The remaining keys from the vendor
663 instance.
Bill Peckham19c3feb2020-03-20 18:31:43 -0700664 framework_partition_set: Partitions that are considered framework
665 partitions. Used to filter apexkeys.txt and apkcerts.txt.
666 vendor_partition_set: Partitions that are considered vendor partitions. Used
667 to filter apexkeys.txt and apkcerts.txt.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800668 """
669
Daniel Normand5d70ea2019-06-05 15:13:43 -0700670 if 'ab_update' in framework_misc_info_keys:
Bill Peckham364c1cc2019-03-29 18:27:23 -0700671 process_ab_partitions_txt(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700672 framework_target_files_temp_dir=framework_target_files_temp_dir,
673 vendor_target_files_temp_dir=vendor_target_files_temp_dir,
Bill Peckham364c1cc2019-03-29 18:27:23 -0700674 output_target_files_temp_dir=output_target_files_temp_dir)
675
Daniel Norman72c626f2019-05-13 15:58:14 -0700676 copy_file_contexts(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700677 framework_target_files_dir=framework_target_files_temp_dir,
678 vendor_target_files_dir=vendor_target_files_temp_dir,
Daniel Norman72c626f2019-05-13 15:58:14 -0700679 output_target_files_dir=output_target_files_temp_dir)
680
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800681 process_misc_info_txt(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700682 framework_target_files_temp_dir=framework_target_files_temp_dir,
683 vendor_target_files_temp_dir=vendor_target_files_temp_dir,
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800684 output_target_files_temp_dir=output_target_files_temp_dir,
Daniel Normand5d70ea2019-06-05 15:13:43 -0700685 framework_misc_info_keys=framework_misc_info_keys)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800686
Daniel Normana61cde02019-05-03 14:19:13 -0700687 process_dynamic_partitions_info_txt(
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 Norman714bd122019-05-08 16:20:02 -0700690 output_target_files_dir=output_target_files_temp_dir)
Daniel Normana61cde02019-05-03 14:19:13 -0700691
Chris Grossfabf50a2019-05-02 12:42:09 -0700692 process_apex_keys_apk_certs_common(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700693 framework_target_files_dir=framework_target_files_temp_dir,
694 vendor_target_files_dir=vendor_target_files_temp_dir,
Chris Grossfabf50a2019-05-02 12:42:09 -0700695 output_target_files_dir=output_target_files_temp_dir,
Bill Peckham19c3feb2020-03-20 18:31:43 -0700696 framework_partition_set=framework_partition_set,
697 vendor_partition_set=vendor_partition_set,
Chris Grossfabf50a2019-05-02 12:42:09 -0700698 file_name='apkcerts.txt')
699
700 process_apex_keys_apk_certs_common(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700701 framework_target_files_dir=framework_target_files_temp_dir,
702 vendor_target_files_dir=vendor_target_files_temp_dir,
Chris Grossfabf50a2019-05-02 12:42:09 -0700703 output_target_files_dir=output_target_files_temp_dir,
Bill Peckham19c3feb2020-03-20 18:31:43 -0700704 framework_partition_set=framework_partition_set,
705 vendor_partition_set=vendor_partition_set,
Chris Grossfabf50a2019-05-02 12:42:09 -0700706 file_name='apexkeys.txt')
707
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800708
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900709def files_from_path(target_path, extra_args=None):
Tao Bao2ad4b822019-06-27 16:52:12 -0700710 """Gets files under given path.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800711
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900712 Get (sub)files from given target path and return sorted list.
713
714 Args:
715 target_path: Target path to get subfiles.
716 extra_args: List of extra argument for find command. Optional.
717
718 Returns:
719 Sorted files and directories list.
720 """
721
722 find_command = ['find', target_path] + (extra_args or [])
723 find_process = common.Run(find_command, stdout=subprocess.PIPE, verbose=False)
Daniel Norman4cc9df62019-07-18 10:11:07 -0700724 return common.RunAndCheckOutput(['sort'],
725 stdin=find_process.stdout,
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900726 verbose=False)
727
728
729def create_merged_package(temp_dir, framework_target_files, framework_item_list,
730 vendor_target_files, vendor_item_list,
Daniel Norman4cc9df62019-07-18 10:11:07 -0700731 framework_misc_info_keys, rebuild_recovery):
Tao Bao2ad4b822019-06-27 16:52:12 -0700732 """Merges two target files packages into one target files structure.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800733
734 Args:
735 temp_dir: The name of a directory we use when we extract items from the
Daniel Normane5b134a2019-04-17 14:54:06 -0700736 input target files packages, and also a scratch directory that we use for
737 temporary files.
Daniel Normand5d70ea2019-06-05 15:13:43 -0700738 framework_target_files: The name of the zip archive containing the framework
Daniel Normane5b134a2019-04-17 14:54:06 -0700739 partial target files package.
Daniel Normand5d70ea2019-06-05 15:13:43 -0700740 framework_item_list: The list of items to extract from the partial framework
Daniel Normane5b134a2019-04-17 14:54:06 -0700741 target files package as is, meaning these items will land in the output
Daniel Normand5d70ea2019-06-05 15:13:43 -0700742 target files package exactly as they appear in the input partial framework
Daniel Normane5b134a2019-04-17 14:54:06 -0700743 target files package.
Daniel Normand5d70ea2019-06-05 15:13:43 -0700744 vendor_target_files: The name of the zip archive containing the vendor
745 partial target files package.
746 vendor_item_list: The list of items to extract from the partial vendor
747 target files package as is, meaning these items will land in the output
748 target files package exactly as they appear in the input partial vendor
Daniel Normane5b134a2019-04-17 14:54:06 -0700749 target files package.
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900750 framework_misc_info_keys: The list of keys to obtain from the framework
751 instance of META/misc_info.txt. The remaining keys from the vendor
752 instance.
Daniel Normana4911da2019-03-15 14:36:21 -0700753 rebuild_recovery: If true, rebuild the recovery patch used by non-A/B
Daniel Normane5b134a2019-04-17 14:54:06 -0700754 devices and write it to the system image.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800755
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900756 Returns:
757 Path to merged package under temp directory.
758 """
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800759
Daniel Normand5d70ea2019-06-05 15:13:43 -0700760 # Create directory names that we'll use when we extract files from framework,
761 # and vendor, and for zipping the final output.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800762
Daniel Normand5d70ea2019-06-05 15:13:43 -0700763 framework_target_files_temp_dir = os.path.join(temp_dir, 'framework')
764 vendor_target_files_temp_dir = os.path.join(temp_dir, 'vendor')
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800765 output_target_files_temp_dir = os.path.join(temp_dir, 'output')
766
Daniel Normand5d70ea2019-06-05 15:13:43 -0700767 # Extract "as is" items from the input framework partial target files package.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800768 # We extract them directly into the output temporary directory since the
769 # items do not need special case processing.
770
Bill Peckham889b0c62019-02-21 18:53:37 -0800771 extract_items(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700772 target_files=framework_target_files,
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800773 target_files_temp_dir=output_target_files_temp_dir,
Daniel Normand5d70ea2019-06-05 15:13:43 -0700774 extract_item_list=framework_item_list)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800775
Daniel Normand5d70ea2019-06-05 15:13:43 -0700776 # Extract "as is" items from the input vendor partial target files package. We
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800777 # extract them directly into the output temporary directory since the items
778 # do not need special case processing.
779
Bill Peckham889b0c62019-02-21 18:53:37 -0800780 extract_items(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700781 target_files=vendor_target_files,
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800782 target_files_temp_dir=output_target_files_temp_dir,
Daniel Normand5d70ea2019-06-05 15:13:43 -0700783 extract_item_list=vendor_item_list)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800784
Daniel Normand5d70ea2019-06-05 15:13:43 -0700785 # Extract "special" items from the input framework partial target files
786 # package. We extract these items to different directory since they require
787 # special processing before they will end up in the output directory.
788
789 extract_items(
790 target_files=framework_target_files,
791 target_files_temp_dir=framework_target_files_temp_dir,
792 extract_item_list=FRAMEWORK_EXTRACT_SPECIAL_ITEM_LIST)
793
794 # Extract "special" items from the input vendor partial target files package.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800795 # We extract these items to different directory since they require special
796 # processing before they will end up in the output directory.
797
Bill Peckham889b0c62019-02-21 18:53:37 -0800798 extract_items(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700799 target_files=vendor_target_files,
800 target_files_temp_dir=vendor_target_files_temp_dir,
801 extract_item_list=VENDOR_EXTRACT_SPECIAL_ITEM_LIST)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800802
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800803 # Now that the temporary directories contain all the extracted files, perform
804 # special case processing on any items that need it. After this function
805 # completes successfully, all the files we need to create the output target
806 # files package are in place.
807
Bill Peckham889b0c62019-02-21 18:53:37 -0800808 process_special_cases(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700809 framework_target_files_temp_dir=framework_target_files_temp_dir,
810 vendor_target_files_temp_dir=vendor_target_files_temp_dir,
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800811 output_target_files_temp_dir=output_target_files_temp_dir,
Bill Peckham19c3feb2020-03-20 18:31:43 -0700812 framework_misc_info_keys=framework_misc_info_keys,
813 framework_partition_set=item_list_to_partition_set(framework_item_list),
814 vendor_partition_set=item_list_to_partition_set(vendor_item_list))
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800815
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900816 return output_target_files_temp_dir
817
818
819def generate_images(target_files_dir, rebuild_recovery):
820 """Generate images from target files.
821
822 This function takes merged output temporary directory and create images
823 from it.
824
825 Args:
826 target_files_dir: Path to merged temp directory.
827 rebuild_recovery: If true, rebuild the recovery patch used by non-A/B
828 devices and write it to the system image.
829 """
830
831 # Regenerate IMAGES in the target directory.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800832
Daniel Normana4911da2019-03-15 14:36:21 -0700833 add_img_args = ['--verbose']
Paul Trautrimbc3600c2019-08-13 18:07:03 +0900834 add_img_args.append('--add_missing')
Bill Peckhame868aec2019-09-17 17:06:47 -0700835 # TODO(b/132730255): Remove this if statement.
Daniel Normana4911da2019-03-15 14:36:21 -0700836 if rebuild_recovery:
837 add_img_args.append('--rebuild_recovery')
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900838 add_img_args.append(target_files_dir)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800839
840 add_img_to_target_files.main(add_img_args)
841
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900842
843def generate_super_empty_image(target_dir, output_super_empty):
Tao Bao2ad4b822019-06-27 16:52:12 -0700844 """Generates super_empty image from target package.
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900845
846 Args:
847 target_dir: Path to the target file package which contains misc_info.txt for
848 detailed information for super image.
849 output_super_empty: If provided, copies a super_empty.img file from the
850 target files package to this path.
851 """
Daniel Norman1bd2a1d2019-04-18 12:32:18 -0700852 # Create super_empty.img using the merged misc_info.txt.
853
Daniel Norman4cc9df62019-07-18 10:11:07 -0700854 misc_info_txt = os.path.join(target_dir, 'META', 'misc_info.txt')
Daniel Norman1bd2a1d2019-04-18 12:32:18 -0700855
Kiyoung Kimebe7c9c2019-06-25 17:09:55 +0900856 use_dynamic_partitions = common.LoadDictionaryFromFile(misc_info_txt).get(
857 'use_dynamic_partitions')
Daniel Norman1bd2a1d2019-04-18 12:32:18 -0700858
859 if use_dynamic_partitions != 'true' and output_super_empty:
860 raise ValueError(
861 'Building super_empty.img requires use_dynamic_partitions=true.')
862 elif use_dynamic_partitions == 'true':
Daniel Norman4cc9df62019-07-18 10:11:07 -0700863 super_empty_img = os.path.join(target_dir, 'IMAGES', 'super_empty.img')
Daniel Norman1bd2a1d2019-04-18 12:32:18 -0700864 build_super_image_args = [
865 misc_info_txt,
866 super_empty_img,
867 ]
868 build_super_image.main(build_super_image_args)
869
870 # Copy super_empty.img to the user-provided output_super_empty location.
871 if output_super_empty:
872 shutil.copyfile(super_empty_img, output_super_empty)
873
Daniel Normanb8a2f9d2019-04-24 12:55:51 -0700874
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900875def create_target_files_archive(output_file, source_dir, temp_dir):
Tao Bao2ad4b822019-06-27 16:52:12 -0700876 """Creates archive from target package.
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900877
878 Args:
879 output_file: The name of the zip archive target files package.
880 source_dir: The target directory contains package to be archived.
881 temp_dir: Path to temporary directory for any intermediate files.
882 """
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800883 output_target_files_list = os.path.join(temp_dir, 'output.list')
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900884 output_zip = os.path.abspath(output_file)
Daniel Norman4cc9df62019-07-18 10:11:07 -0700885 output_target_files_meta_dir = os.path.join(source_dir, 'META')
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800886
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900887 meta_content = files_from_path(output_target_files_meta_dir)
Daniel Norman4cc9df62019-07-18 10:11:07 -0700888 other_content = files_from_path(
889 source_dir,
890 ['-path', output_target_files_meta_dir, '-prune', '-o', '-print'])
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800891
Tao Bao2ad4b822019-06-27 16:52:12 -0700892 with open(output_target_files_list, 'w') as f:
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800893 f.write(meta_content)
894 f.write(other_content)
895
896 command = [
Bill Peckhamf753e152019-02-19 18:02:46 -0800897 'soong_zip',
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800898 '-d',
Daniel Normane5b134a2019-04-17 14:54:06 -0700899 '-o',
900 output_zip,
901 '-C',
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900902 source_dir,
Daniel Normane5b134a2019-04-17 14:54:06 -0700903 '-l',
904 output_target_files_list,
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800905 ]
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900906
907 logger.info('creating %s', output_file)
Bill Peckham889b0c62019-02-21 18:53:37 -0800908 common.RunAndWait(command, verbose=True)
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900909 logger.info('finished creating %s', output_file)
910
911 return output_zip
912
913
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900914def merge_target_files(temp_dir, framework_target_files, framework_item_list,
915 framework_misc_info_keys, vendor_target_files,
916 vendor_item_list, output_target_files, output_dir,
917 output_item_list, output_ota, output_img,
918 output_super_empty, rebuild_recovery):
Tao Bao2ad4b822019-06-27 16:52:12 -0700919 """Merges two target files packages together.
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900920
921 This function takes framework and vendor target files packages as input,
922 performs various file extractions, special case processing, and finally
923 creates a merged zip archive as output.
924
925 Args:
926 temp_dir: The name of a directory we use when we extract items from the
927 input target files packages, and also a scratch directory that we use for
928 temporary files.
929 framework_target_files: The name of the zip archive containing the framework
930 partial target files package.
931 framework_item_list: The list of items to extract from the partial framework
932 target files package as is, meaning these items will land in the output
933 target files package exactly as they appear in the input partial framework
934 target files package.
935 framework_misc_info_keys: The list of keys to obtain from the framework
936 instance of META/misc_info.txt. The remaining keys from the vendor
937 instance.
938 vendor_target_files: The name of the zip archive containing the vendor
939 partial target files package.
940 vendor_item_list: The list of items to extract from the partial vendor
941 target files package as is, meaning these items will land in the output
942 target files package exactly as they appear in the input partial vendor
943 target files package.
944 output_target_files: The name of the output zip archive target files package
945 created by merging framework and vendor.
946 output_dir: The destination directory for saving merged files.
947 output_item_list: The list of items to copy into the output_dir.
948 output_ota: The name of the output zip archive ota package.
949 output_img: The name of the output zip archive img package.
950 output_super_empty: If provided, creates a super_empty.img file from the
951 merged target files package and saves it at this path.
952 rebuild_recovery: If true, rebuild the recovery patch used by non-A/B
953 devices and write it to the system image.
954 """
955
956 logger.info('starting: merge framework %s and vendor %s into output %s',
957 framework_target_files, vendor_target_files, output_target_files)
958
959 output_target_files_temp_dir = create_merged_package(
960 temp_dir, framework_target_files, framework_item_list,
961 vendor_target_files, vendor_item_list, framework_misc_info_keys,
962 rebuild_recovery)
963
Yifan Hongade0d3f2019-08-21 16:37:11 -0700964 if not check_target_files_vintf.CheckVintf(output_target_files_temp_dir):
965 raise RuntimeError("Incompatible VINTF metadata")
966
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900967 generate_images(output_target_files_temp_dir, rebuild_recovery)
968
969 generate_super_empty_image(output_target_files_temp_dir, output_super_empty)
970
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900971 # Finally, create the output target files zip archive and/or copy the
972 # output items to the output target files directory.
973
974 if output_dir:
975 copy_items(output_target_files_temp_dir, output_dir, output_item_list)
976
977 if not output_target_files:
978 return
979
980 output_zip = create_target_files_archive(output_target_files,
981 output_target_files_temp_dir,
982 temp_dir)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800983
Daniel Norman74eb74b2019-09-18 14:01:48 -0700984 # Create the IMG package from the merged target files package.
985
986 if output_img:
987 img_from_target_files.main([output_zip, output_img])
988
Daniel Norman3b64ce12019-04-16 16:11:35 -0700989 # Create the OTA package from the merged target files package.
990
991 if output_ota:
Daniel Norman4cc9df62019-07-18 10:11:07 -0700992 ota_from_target_files.main([output_zip, output_ota])
Daniel Norman3b64ce12019-04-16 16:11:35 -0700993
Daniel Norman1bd2a1d2019-04-18 12:32:18 -0700994
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800995def call_func_with_temp_dir(func, keep_tmp):
Tao Bao2ad4b822019-06-27 16:52:12 -0700996 """Manages the creation and cleanup of the temporary directory.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800997
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800998 This function calls the given function after first creating a temporary
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800999 directory. It also cleans up the temporary directory.
1000
1001 Args:
Daniel Normane5b134a2019-04-17 14:54:06 -07001002 func: The function to call. Should accept one parameter, the path to the
1003 temporary directory.
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001004 keep_tmp: Keep the temporary directory after processing is complete.
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001005 """
1006
1007 # Create a temporary directory. This will serve as the parent of directories
1008 # we use when we extract items from the input target files packages, and also
1009 # a scratch directory that we use for temporary files.
1010
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001011 temp_dir = common.MakeTempDir(prefix='merge_target_files_')
1012
1013 try:
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001014 func(temp_dir)
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001015 finally:
1016 if keep_tmp:
1017 logger.info('keeping %s', temp_dir)
1018 else:
1019 common.Cleanup()
1020
1021
1022def main():
1023 """The main function.
1024
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001025 Process command line arguments, then call merge_target_files to
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001026 perform the heavy lifting.
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001027 """
1028
1029 common.InitLogging()
1030
Bill Peckhamf753e152019-02-19 18:02:46 -08001031 def option_handler(o, a):
1032 if o == '--system-target-files':
Daniel Normand5d70ea2019-06-05 15:13:43 -07001033 logger.warning(
1034 '--system-target-files has been renamed to --framework-target-files')
1035 OPTIONS.framework_target_files = a
1036 elif o == '--framework-target-files':
1037 OPTIONS.framework_target_files = a
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001038 elif o == '--system-item-list':
Daniel Normand5d70ea2019-06-05 15:13:43 -07001039 logger.warning(
1040 '--system-item-list has been renamed to --framework-item-list')
1041 OPTIONS.framework_item_list = a
1042 elif o == '--framework-item-list':
1043 OPTIONS.framework_item_list = a
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001044 elif o == '--system-misc-info-keys':
Daniel Norman4cc9df62019-07-18 10:11:07 -07001045 logger.warning('--system-misc-info-keys has been renamed to '
1046 '--framework-misc-info-keys')
Daniel Normand5d70ea2019-06-05 15:13:43 -07001047 OPTIONS.framework_misc_info_keys = a
1048 elif o == '--framework-misc-info-keys':
1049 OPTIONS.framework_misc_info_keys = a
Bill Peckhamf753e152019-02-19 18:02:46 -08001050 elif o == '--other-target-files':
Daniel Normand5d70ea2019-06-05 15:13:43 -07001051 logger.warning(
1052 '--other-target-files has been renamed to --vendor-target-files')
1053 OPTIONS.vendor_target_files = a
1054 elif o == '--vendor-target-files':
1055 OPTIONS.vendor_target_files = a
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001056 elif o == '--other-item-list':
Daniel Normand5d70ea2019-06-05 15:13:43 -07001057 logger.warning('--other-item-list has been renamed to --vendor-item-list')
1058 OPTIONS.vendor_item_list = a
1059 elif o == '--vendor-item-list':
1060 OPTIONS.vendor_item_list = a
Bill Peckhamf753e152019-02-19 18:02:46 -08001061 elif o == '--output-target-files':
1062 OPTIONS.output_target_files = a
Daniel Normanfdb38812019-04-15 09:47:24 -07001063 elif o == '--output-dir':
1064 OPTIONS.output_dir = a
1065 elif o == '--output-item-list':
1066 OPTIONS.output_item_list = a
Daniel Norman3b64ce12019-04-16 16:11:35 -07001067 elif o == '--output-ota':
1068 OPTIONS.output_ota = a
Daniel Norman1bd2a1d2019-04-18 12:32:18 -07001069 elif o == '--output-img':
1070 OPTIONS.output_img = a
Daniel Normanf0318252019-04-15 11:34:56 -07001071 elif o == '--output-super-empty':
1072 OPTIONS.output_super_empty = a
Bill Peckhame868aec2019-09-17 17:06:47 -07001073 elif o == '--rebuild_recovery': # TODO(b/132730255): Warn
Daniel Normana4911da2019-03-15 14:36:21 -07001074 OPTIONS.rebuild_recovery = True
Bill Peckham364c1cc2019-03-29 18:27:23 -07001075 elif o == '--keep-tmp':
Bill Peckhamf753e152019-02-19 18:02:46 -08001076 OPTIONS.keep_tmp = True
1077 else:
1078 return False
1079 return True
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001080
Bill Peckhamf753e152019-02-19 18:02:46 -08001081 args = common.ParseOptions(
Daniel Normane5b134a2019-04-17 14:54:06 -07001082 sys.argv[1:],
1083 __doc__,
Bill Peckhamf753e152019-02-19 18:02:46 -08001084 extra_long_opts=[
1085 'system-target-files=',
Daniel Normand5d70ea2019-06-05 15:13:43 -07001086 'framework-target-files=',
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001087 'system-item-list=',
Daniel Normand5d70ea2019-06-05 15:13:43 -07001088 'framework-item-list=',
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001089 'system-misc-info-keys=',
Daniel Normand5d70ea2019-06-05 15:13:43 -07001090 'framework-misc-info-keys=',
Bill Peckhamf753e152019-02-19 18:02:46 -08001091 'other-target-files=',
Daniel Normand5d70ea2019-06-05 15:13:43 -07001092 'vendor-target-files=',
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001093 'other-item-list=',
Daniel Normand5d70ea2019-06-05 15:13:43 -07001094 'vendor-item-list=',
Bill Peckhamf753e152019-02-19 18:02:46 -08001095 'output-target-files=',
Daniel Normanfdb38812019-04-15 09:47:24 -07001096 'output-dir=',
1097 'output-item-list=',
Daniel Norman3b64ce12019-04-16 16:11:35 -07001098 'output-ota=',
Daniel Norman1bd2a1d2019-04-18 12:32:18 -07001099 'output-img=',
Daniel Normanf0318252019-04-15 11:34:56 -07001100 'output-super-empty=',
Daniel Normana4911da2019-03-15 14:36:21 -07001101 'rebuild_recovery',
Bill Peckham364c1cc2019-03-29 18:27:23 -07001102 'keep-tmp',
Bill Peckhamf753e152019-02-19 18:02:46 -08001103 ],
1104 extra_option_handler=option_handler)
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001105
Tao Bao2ad4b822019-06-27 16:52:12 -07001106 # pylint: disable=too-many-boolean-expressions
Daniel Normand5d70ea2019-06-05 15:13:43 -07001107 if (args or OPTIONS.framework_target_files is None or
1108 OPTIONS.vendor_target_files is None or
Daniel Normane5b134a2019-04-17 14:54:06 -07001109 (OPTIONS.output_target_files is None and OPTIONS.output_dir is None) or
1110 (OPTIONS.output_dir is not None and OPTIONS.output_item_list is None)):
Bill Peckhamf753e152019-02-19 18:02:46 -08001111 common.Usage(__doc__)
Bill Peckham889b0c62019-02-21 18:53:37 -08001112 sys.exit(1)
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001113
Daniel Normand5d70ea2019-06-05 15:13:43 -07001114 if OPTIONS.framework_item_list:
Daniel Norman4cc9df62019-07-18 10:11:07 -07001115 framework_item_list = common.LoadListFromFile(OPTIONS.framework_item_list)
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001116 else:
Daniel Normand5d70ea2019-06-05 15:13:43 -07001117 framework_item_list = DEFAULT_FRAMEWORK_ITEM_LIST
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001118
Daniel Normand5d70ea2019-06-05 15:13:43 -07001119 if OPTIONS.framework_misc_info_keys:
Daniel Norman4cc9df62019-07-18 10:11:07 -07001120 framework_misc_info_keys = common.LoadListFromFile(
Daniel Normand5d70ea2019-06-05 15:13:43 -07001121 OPTIONS.framework_misc_info_keys)
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001122 else:
Daniel Normand5d70ea2019-06-05 15:13:43 -07001123 framework_misc_info_keys = DEFAULT_FRAMEWORK_MISC_INFO_KEYS
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001124
Daniel Normand5d70ea2019-06-05 15:13:43 -07001125 if OPTIONS.vendor_item_list:
Daniel Norman4cc9df62019-07-18 10:11:07 -07001126 vendor_item_list = common.LoadListFromFile(OPTIONS.vendor_item_list)
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001127 else:
Daniel Normand5d70ea2019-06-05 15:13:43 -07001128 vendor_item_list = DEFAULT_VENDOR_ITEM_LIST
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001129
Daniel Normanfdb38812019-04-15 09:47:24 -07001130 if OPTIONS.output_item_list:
Daniel Norman4cc9df62019-07-18 10:11:07 -07001131 output_item_list = common.LoadListFromFile(OPTIONS.output_item_list)
Daniel Normanfdb38812019-04-15 09:47:24 -07001132 else:
1133 output_item_list = None
1134
Daniel Normane5964522019-03-19 10:32:03 -07001135 if not validate_config_lists(
Daniel Normand5d70ea2019-06-05 15:13:43 -07001136 framework_item_list=framework_item_list,
1137 framework_misc_info_keys=framework_misc_info_keys,
1138 vendor_item_list=vendor_item_list):
Daniel Normane5964522019-03-19 10:32:03 -07001139 sys.exit(1)
1140
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001141 call_func_with_temp_dir(
1142 lambda temp_dir: merge_target_files(
1143 temp_dir=temp_dir,
Daniel Normand5d70ea2019-06-05 15:13:43 -07001144 framework_target_files=OPTIONS.framework_target_files,
1145 framework_item_list=framework_item_list,
1146 framework_misc_info_keys=framework_misc_info_keys,
1147 vendor_target_files=OPTIONS.vendor_target_files,
1148 vendor_item_list=vendor_item_list,
Daniel Normana4911da2019-03-15 14:36:21 -07001149 output_target_files=OPTIONS.output_target_files,
Daniel Normanfdb38812019-04-15 09:47:24 -07001150 output_dir=OPTIONS.output_dir,
1151 output_item_list=output_item_list,
Daniel Norman3b64ce12019-04-16 16:11:35 -07001152 output_ota=OPTIONS.output_ota,
Daniel Norman1bd2a1d2019-04-18 12:32:18 -07001153 output_img=OPTIONS.output_img,
Daniel Normanf0318252019-04-15 11:34:56 -07001154 output_super_empty=OPTIONS.output_super_empty,
Daniel Normane5b134a2019-04-17 14:54:06 -07001155 rebuild_recovery=OPTIONS.rebuild_recovery), OPTIONS.keep_tmp)
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001156
1157
1158if __name__ == '__main__':
Bill Peckham889b0c62019-02-21 18:53:37 -08001159 main()