blob: 216318d046069f8f5168c9427674205eda8604c2 [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 Normane5b134a2019-04-17 14:54:06 -070016"""This script merges two partial target files packages.
Bill Peckhame9eb5f92019-02-01 15:52:10 -080017
Daniel Normand5d70ea2019-06-05 15:13:43 -070018One package contains framework files, and the other contains vendor files.
Daniel Normane5b134a2019-04-17 14:54:06 -070019It produces a complete target files package that can be used to generate an
20OTA package.
Bill Peckhame9eb5f92019-02-01 15:52:10 -080021
22Usage: merge_target_files.py [args]
23
Daniel Normand5d70ea2019-06-05 15:13:43 -070024 --framework-target-files framework-target-files-zip-archive
25 The input target files package containing framework bits. This is a zip
Bill Peckhame9eb5f92019-02-01 15:52:10 -080026 archive.
27
Daniel Normand5d70ea2019-06-05 15:13:43 -070028 --framework-item-list framework-item-list-file
Daniel Norman2c99c5b2019-03-07 13:01:48 -080029 The optional path to a newline-separated config file that replaces the
Daniel Normand5d70ea2019-06-05 15:13:43 -070030 contents of DEFAULT_FRAMEWORK_ITEM_LIST if provided.
Daniel Norman2c99c5b2019-03-07 13:01:48 -080031
Daniel Normand5d70ea2019-06-05 15:13:43 -070032 --framework-misc-info-keys framework-misc-info-keys-file
Daniel Norman2c99c5b2019-03-07 13:01:48 -080033 The optional path to a newline-separated config file that replaces the
Daniel Normand5d70ea2019-06-05 15:13:43 -070034 contents of DEFAULT_FRAMEWORK_MISC_INFO_KEYS if provided.
Daniel Norman2c99c5b2019-03-07 13:01:48 -080035
Daniel Normand5d70ea2019-06-05 15:13:43 -070036 --vendor-target-files vendor-target-files-zip-archive
37 The input target files package containing vendor bits. This is a zip
Bill Peckhame9eb5f92019-02-01 15:52:10 -080038 archive.
39
Daniel Normand5d70ea2019-06-05 15:13:43 -070040 --vendor-item-list vendor-item-list-file
Daniel Norman2c99c5b2019-03-07 13:01:48 -080041 The optional path to a newline-separated config file that replaces the
Daniel Normand5d70ea2019-06-05 15:13:43 -070042 contents of DEFAULT_VENDOR_ITEM_LIST if provided.
Daniel Norman2c99c5b2019-03-07 13:01:48 -080043
Bill Peckhame9eb5f92019-02-01 15:52:10 -080044 --output-target-files output-target-files-package
Daniel Normanfdb38812019-04-15 09:47:24 -070045 If provided, the output merged target files package. Also a zip archive.
46
47 --output-dir output-directory
48 If provided, the destination directory for saving merged files. Requires
49 the --output-item-list flag.
50 Can be provided alongside --output-target-files, or by itself.
51
52 --output-item-list output-item-list-file.
53 The optional path to a newline-separated config file that specifies the
54 file patterns to copy into the --output-dir. Required if providing
55 the --output-dir flag.
Daniel Normana4911da2019-03-15 14:36:21 -070056
Daniel Norman3b64ce12019-04-16 16:11:35 -070057 --output-ota output-ota-package
58 The output ota package. This is a zip archive. Use of this flag may
59 require passing the --path common flag; see common.py.
60
Daniel Norman1bd2a1d2019-04-18 12:32:18 -070061 --output-img output-img-package
62 The output img package, suitable for use with 'fastboot update'. Use of
63 this flag may require passing the --path common flag; see common.py.
64
Daniel Normanf0318252019-04-15 11:34:56 -070065 --output-super-empty output-super-empty-image
66 If provided, creates a super_empty.img file from the merged target
67 files package and saves it at this path.
68
Daniel Normana4911da2019-03-15 14:36:21 -070069 --rebuild_recovery
70 Rebuild the recovery patch used by non-A/B devices and write it to the
71 system image.
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
Daniel Normanfdb38812019-04-15 09:47:24 -070082import shutil
Bill Peckham540d91a2019-04-25 14:18:16 -070083import subprocess
Bill Peckhame9eb5f92019-02-01 15:52:10 -080084import sys
85import zipfile
86
Bill Peckhame9eb5f92019-02-01 15:52:10 -080087import add_img_to_target_files
Daniel Normanf0318252019-04-15 11:34:56 -070088import build_super_image
89import common
Daniel Norman1bd2a1d2019-04-18 12:32:18 -070090import img_from_target_files
Daniel Norman3b64ce12019-04-16 16:11:35 -070091import ota_from_target_files
Bill Peckhame9eb5f92019-02-01 15:52:10 -080092
93logger = logging.getLogger(__name__)
94OPTIONS = common.OPTIONS
95OPTIONS.verbose = True
Daniel Normand5d70ea2019-06-05 15:13:43 -070096OPTIONS.framework_target_files = None
97OPTIONS.framework_item_list = None
98OPTIONS.framework_misc_info_keys = None
99OPTIONS.vendor_target_files = None
100OPTIONS.vendor_item_list = None
Bill Peckhamf753e152019-02-19 18:02:46 -0800101OPTIONS.output_target_files = None
Daniel Normanfdb38812019-04-15 09:47:24 -0700102OPTIONS.output_dir = None
103OPTIONS.output_item_list = None
Daniel Norman3b64ce12019-04-16 16:11:35 -0700104OPTIONS.output_ota = None
Daniel Norman1bd2a1d2019-04-18 12:32:18 -0700105OPTIONS.output_img = None
Daniel Normanf0318252019-04-15 11:34:56 -0700106OPTIONS.output_super_empty = None
Daniel Normana4911da2019-03-15 14:36:21 -0700107OPTIONS.rebuild_recovery = False
Bill Peckhamf753e152019-02-19 18:02:46 -0800108OPTIONS.keep_tmp = False
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800109
Daniel Normand5d70ea2019-06-05 15:13:43 -0700110# DEFAULT_FRAMEWORK_ITEM_LIST is a list of items to extract from the partial
111# framework target files package as is, meaning these items will land in the
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800112# output target files package exactly as they appear in the input partial
Daniel Normand5d70ea2019-06-05 15:13:43 -0700113# framework target files package.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800114
Daniel Normand5d70ea2019-06-05 15:13:43 -0700115DEFAULT_FRAMEWORK_ITEM_LIST = (
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800116 'META/apkcerts.txt',
117 'META/filesystem_config.txt',
118 'META/root_filesystem_config.txt',
119 'META/system_manifest.xml',
120 'META/system_matrix.xml',
121 'META/update_engine_config.txt',
122 'PRODUCT/*',
123 'ROOT/*',
124 'SYSTEM/*',
Daniel Normanedf12472019-05-22 10:47:08 -0700125)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800126
Daniel Normand5d70ea2019-06-05 15:13:43 -0700127# FRAMEWORK_EXTRACT_SPECIAL_ITEM_LIST is a list of items to extract from the
128# partial framework target files package that need some special processing, such
129# as some sort of combination with items from the partial vendor target files
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800130# package.
131
Daniel Normand5d70ea2019-06-05 15:13:43 -0700132FRAMEWORK_EXTRACT_SPECIAL_ITEM_LIST = ('META/*',)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800133
Daniel Normand5d70ea2019-06-05 15:13:43 -0700134# DEFAULT_FRAMEWORK_MISC_INFO_KEYS is a list of keys to obtain from the
135# framework instance of META/misc_info.txt. The remaining keys from the
136# vendor instance.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800137
Daniel Normand5d70ea2019-06-05 15:13:43 -0700138DEFAULT_FRAMEWORK_MISC_INFO_KEYS = (
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800139 'avb_system_hashtree_enable',
140 'avb_system_add_hashtree_footer_args',
141 'avb_system_key_path',
142 'avb_system_algorithm',
143 'avb_system_rollback_index_location',
144 'avb_product_hashtree_enable',
145 'avb_product_add_hashtree_footer_args',
146 'avb_product_services_hashtree_enable',
147 'avb_product_services_add_hashtree_footer_args',
148 'system_root_image',
149 'root_dir',
150 'ab_update',
151 'default_system_dev_certificate',
152 'system_size',
Daniel Normanedf12472019-05-22 10:47:08 -0700153)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800154
Daniel Normand5d70ea2019-06-05 15:13:43 -0700155# DEFAULT_VENDOR_ITEM_LIST is a list of items to extract from the partial
156# vendor target files package as is, meaning these items will land in the output
157# target files package exactly as they appear in the input partial vendor target
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800158# files package.
159
Daniel Normand5d70ea2019-06-05 15:13:43 -0700160DEFAULT_VENDOR_ITEM_LIST = (
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800161 'META/boot_filesystem_config.txt',
162 'META/otakeys.txt',
163 'META/releasetools.py',
164 'META/vendor_filesystem_config.txt',
165 'META/vendor_manifest.xml',
166 'META/vendor_matrix.xml',
167 'BOOT/*',
168 'DATA/*',
169 'ODM/*',
170 'OTA/android-info.txt',
171 'PREBUILT_IMAGES/*',
172 'RADIO/*',
173 'VENDOR/*',
Daniel Normanedf12472019-05-22 10:47:08 -0700174)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800175
Daniel Normand5d70ea2019-06-05 15:13:43 -0700176# VENDOR_EXTRACT_SPECIAL_ITEM_LIST is a list of items to extract from the
177# partial vendor target files package that need some special processing, such as
178# some sort of combination with items from the partial framework target files
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800179# package.
180
Daniel Normand5d70ea2019-06-05 15:13:43 -0700181VENDOR_EXTRACT_SPECIAL_ITEM_LIST = ('META/*',)
Daniel Normanedf12472019-05-22 10:47:08 -0700182
183# The merge config lists should not attempt to extract items from both
184# builds for any of the following partitions. The partitions in
185# SINGLE_BUILD_PARTITIONS should come entirely from a single build (either
Daniel Normand5d70ea2019-06-05 15:13:43 -0700186# framework or vendor, but not both).
Daniel Normanedf12472019-05-22 10:47:08 -0700187
188SINGLE_BUILD_PARTITIONS = (
189 'BOOT/',
190 'DATA/',
191 'ODM/',
192 'PRODUCT/',
193 'PRODUCT_SERVICES/',
194 'RADIO/',
195 'RECOVERY/',
196 'ROOT/',
197 'SYSTEM/',
198 'SYSTEM_OTHER/',
199 'VENDOR/',
200)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800201
202
Chris Grossfabf50a2019-05-02 12:42:09 -0700203def write_sorted_data(data, path):
204 """Write the sorted contents of either a list or dict to file.
205
206 This function sorts the contents of the list or dict and then
207 writes the resulting sorted contents to a file specified by path.
208
209 Args:
210 data: The list or dict to sort and write.
211 path: Path to the file to write the sorted values to. The file at path will
212 be overridden if it exists.
213 """
214 with open(path, 'w') as output:
Daniel Normand5d70ea2019-06-05 15:13:43 -0700215 for entry in sorted(data):
Chris Grossfabf50a2019-05-02 12:42:09 -0700216 out_str = '{}={}\n'.format(entry, data[entry]) if isinstance(
217 data, dict) else '{}\n'.format(entry)
218 output.write(out_str)
219
220
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800221def extract_items(target_files, target_files_temp_dir, extract_item_list):
222 """Extract items from target files to temporary directory.
223
224 This function extracts from the specified target files zip archive into the
225 specified temporary directory, the items specified in the extract item list.
226
227 Args:
228 target_files: The target files zip archive from which to extract items.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800229 target_files_temp_dir: The temporary directory where the extracted items
Daniel Normane5b134a2019-04-17 14:54:06 -0700230 will land.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800231 extract_item_list: A list of items to extract.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800232 """
233
234 logger.info('extracting from %s', target_files)
235
236 # Filter the extract_item_list to remove any items that do not exist in the
237 # zip file. Otherwise, the extraction step will fail.
238
239 with zipfile.ZipFile(
Daniel Normane5b134a2019-04-17 14:54:06 -0700240 target_files, 'r', allowZip64=True) as target_files_zipfile:
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800241 target_files_namelist = target_files_zipfile.namelist()
242
243 filtered_extract_item_list = []
244 for pattern in extract_item_list:
245 matching_namelist = fnmatch.filter(target_files_namelist, pattern)
246 if not matching_namelist:
247 logger.warning('no match for %s', pattern)
248 else:
249 filtered_extract_item_list.append(pattern)
250
Bill Peckham8ff3fbd2019-02-22 10:57:43 -0800251 # Extract from target_files into target_files_temp_dir the
252 # filtered_extract_item_list.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800253
Daniel Normane5b134a2019-04-17 14:54:06 -0700254 common.UnzipToDir(target_files, target_files_temp_dir,
255 filtered_extract_item_list)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800256
257
Daniel Normanfdb38812019-04-15 09:47:24 -0700258def copy_items(from_dir, to_dir, patterns):
259 """Similar to extract_items() except uses an input dir instead of zip."""
260 file_paths = []
261 for dirpath, _, filenames in os.walk(from_dir):
Daniel Normane5b134a2019-04-17 14:54:06 -0700262 file_paths.extend(
263 os.path.relpath(path=os.path.join(dirpath, filename), start=from_dir)
264 for filename in filenames)
Daniel Normanfdb38812019-04-15 09:47:24 -0700265
266 filtered_file_paths = set()
267 for pattern in patterns:
268 filtered_file_paths.update(fnmatch.filter(file_paths, pattern))
269
270 for file_path in filtered_file_paths:
271 original_file_path = os.path.join(from_dir, file_path)
272 copied_file_path = os.path.join(to_dir, file_path)
273 copied_file_dir = os.path.dirname(copied_file_path)
274 if not os.path.exists(copied_file_dir):
275 os.makedirs(copied_file_dir)
276 if os.path.islink(original_file_path):
277 os.symlink(os.readlink(original_file_path), copied_file_path)
278 else:
279 shutil.copyfile(original_file_path, copied_file_path)
280
281
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800282def read_config_list(config_file_path):
283 """Reads a config file into a list of strings.
284
285 Expects the file to be newline-separated.
286
287 Args:
288 config_file_path: The path to the config file to open and read.
Daniel Normane5b134a2019-04-17 14:54:06 -0700289
290 Returns:
291 The list of strings in the config file.
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800292 """
293 with open(config_file_path) as config_file:
294 return config_file.read().splitlines()
295
296
Daniel Normand5d70ea2019-06-05 15:13:43 -0700297def validate_config_lists(framework_item_list, framework_misc_info_keys,
298 vendor_item_list):
Daniel Normane5964522019-03-19 10:32:03 -0700299 """Performs validations on the merge config lists.
300
301 Args:
Daniel Normand5d70ea2019-06-05 15:13:43 -0700302 framework_item_list: The list of items to extract from the partial framework
Daniel Normane5b134a2019-04-17 14:54:06 -0700303 target files package as is.
Daniel Normand5d70ea2019-06-05 15:13:43 -0700304 framework_misc_info_keys: A list of keys to obtain from the framework
305 instance of META/misc_info.txt. The remaining keys from the vendor
306 instance.
307 vendor_item_list: The list of items to extract from the partial vendor
308 target files package as is.
Daniel Normane5964522019-03-19 10:32:03 -0700309
310 Returns:
311 False if a validation fails, otherwise true.
312 """
Daniel Normanedf12472019-05-22 10:47:08 -0700313 has_error = False
314
Daniel Normand5d70ea2019-06-05 15:13:43 -0700315 default_combined_item_set = set(DEFAULT_FRAMEWORK_ITEM_LIST)
316 default_combined_item_set.update(DEFAULT_VENDOR_ITEM_LIST)
Daniel Normane5964522019-03-19 10:32:03 -0700317
Daniel Normand5d70ea2019-06-05 15:13:43 -0700318 combined_item_set = set(framework_item_list)
319 combined_item_set.update(vendor_item_list)
Daniel Normane5964522019-03-19 10:32:03 -0700320
321 # Check that the merge config lists are not missing any item specified
322 # by the default config lists.
323 difference = default_combined_item_set.difference(combined_item_set)
324 if difference:
Daniel Normane5b134a2019-04-17 14:54:06 -0700325 logger.error('Missing merge config items: %s', list(difference))
Daniel Normane5964522019-03-19 10:32:03 -0700326 logger.error('Please ensure missing items are in either the '
Daniel Normand5d70ea2019-06-05 15:13:43 -0700327 'framework-item-list or vendor-item-list files provided to '
Daniel Normane5964522019-03-19 10:32:03 -0700328 'this script.')
Daniel Normanedf12472019-05-22 10:47:08 -0700329 has_error = True
330
331 for partition in SINGLE_BUILD_PARTITIONS:
Daniel Normand5d70ea2019-06-05 15:13:43 -0700332 in_framework = any(
333 item.startswith(partition) for item in framework_item_list)
334 in_vendor = any(item.startswith(partition) for item in vendor_item_list)
335 if in_framework and in_vendor:
Daniel Normanedf12472019-05-22 10:47:08 -0700336 logger.error(
Kiyoung Kimebe7c9c2019-06-25 17:09:55 +0900337 'Cannot extract items from {0} for both the framework and vendor'
338 ' builds. Please ensure only one merge config item list'
339 ' includes {0}.'.format(partition))
Daniel Normanedf12472019-05-22 10:47:08 -0700340 has_error = True
Daniel Normane5964522019-03-19 10:32:03 -0700341
Daniel Normand5d70ea2019-06-05 15:13:43 -0700342 if ('dynamic_partition_list' in framework_misc_info_keys) or (
343 'super_partition_groups' in framework_misc_info_keys):
Daniel Norman19b9fe92019-03-19 14:48:02 -0700344 logger.error('Dynamic partition misc info keys should come from '
Daniel Normand5d70ea2019-06-05 15:13:43 -0700345 'the vendor instance of META/misc_info.txt.')
Daniel Normanedf12472019-05-22 10:47:08 -0700346 has_error = True
Daniel Norman19b9fe92019-03-19 14:48:02 -0700347
Daniel Normanedf12472019-05-22 10:47:08 -0700348 return not has_error
Daniel Normane5964522019-03-19 10:32:03 -0700349
350
Daniel Normand5d70ea2019-06-05 15:13:43 -0700351def process_ab_partitions_txt(framework_target_files_temp_dir,
352 vendor_target_files_temp_dir,
Daniel Normane5b134a2019-04-17 14:54:06 -0700353 output_target_files_temp_dir):
354 """Perform special processing for META/ab_partitions.txt.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800355
356 This function merges the contents of the META/ab_partitions.txt files from
Daniel Normand5d70ea2019-06-05 15:13:43 -0700357 the framework directory and the vendor directory, placing the merged result in
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800358 the output directory. The precondition in that the files are already
359 extracted. The post condition is that the output META/ab_partitions.txt
360 contains the merged content. The format for each ab_partitions.txt a one
361 partition name per line. The output file contains the union of the parition
362 names.
363
364 Args:
Daniel Normand5d70ea2019-06-05 15:13:43 -0700365 framework_target_files_temp_dir: The name of a directory containing the
366 special items extracted from the framework target files package.
367 vendor_target_files_temp_dir: The name of a directory containing the special
368 items extracted from the vendor target files package.
Daniel Normane5b134a2019-04-17 14:54:06 -0700369 output_target_files_temp_dir: The name of a directory that will be used to
370 create the output target files package after all the special cases are
371 processed.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800372 """
373
Daniel Normand5d70ea2019-06-05 15:13:43 -0700374 framework_ab_partitions_txt = os.path.join(framework_target_files_temp_dir,
375 'META', 'ab_partitions.txt')
376
377 vendor_ab_partitions_txt = os.path.join(vendor_target_files_temp_dir, 'META',
Daniel Normane5b134a2019-04-17 14:54:06 -0700378 'ab_partitions.txt')
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800379
Daniel Normand5d70ea2019-06-05 15:13:43 -0700380 with open(framework_ab_partitions_txt) as f:
381 framework_ab_partitions = f.read().splitlines()
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800382
Daniel Normand5d70ea2019-06-05 15:13:43 -0700383 with open(vendor_ab_partitions_txt) as f:
384 vendor_ab_partitions = f.read().splitlines()
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800385
Daniel Normand5d70ea2019-06-05 15:13:43 -0700386 output_ab_partitions = set(framework_ab_partitions + vendor_ab_partitions)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800387
Daniel Normane5b134a2019-04-17 14:54:06 -0700388 output_ab_partitions_txt = os.path.join(output_target_files_temp_dir, 'META',
389 'ab_partitions.txt')
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800390
Chris Grossfabf50a2019-05-02 12:42:09 -0700391 write_sorted_data(data=output_ab_partitions, path=output_ab_partitions_txt)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800392
393
Bill Peckham364c1cc2019-03-29 18:27:23 -0700394def append_recovery_to_filesystem_config(output_target_files_temp_dir):
Daniel Normane5b134a2019-04-17 14:54:06 -0700395 """Perform special processing for META/filesystem_config.txt.
Bill Peckham364c1cc2019-03-29 18:27:23 -0700396
397 This function appends recovery information to META/filesystem_config.txt
398 so that recovery patch regeneration will succeed.
399
400 Args:
Daniel Normane5b134a2019-04-17 14:54:06 -0700401 output_target_files_temp_dir: The name of a directory that will be used to
402 create the output target files package after all the special cases are
403 processed. We find filesystem_config.txt here.
Bill Peckham364c1cc2019-03-29 18:27:23 -0700404 """
405
Daniel Normane5b134a2019-04-17 14:54:06 -0700406 filesystem_config_txt = os.path.join(output_target_files_temp_dir, 'META',
407 'filesystem_config.txt')
Bill Peckham364c1cc2019-03-29 18:27:23 -0700408
409 with open(filesystem_config_txt, 'a') as f:
410 # TODO(bpeckham) this data is hard coded. It should be generated
411 # programmatically.
Daniel Normane5b134a2019-04-17 14:54:06 -0700412 f.write('system/bin/install-recovery.sh 0 0 750 '
413 'selabel=u:object_r:install_recovery_exec:s0 capabilities=0x0\n')
414 f.write('system/recovery-from-boot.p 0 0 644 '
415 'selabel=u:object_r:system_file:s0 capabilities=0x0\n')
416 f.write('system/etc/recovery.img 0 0 440 '
417 'selabel=u:object_r:install_recovery_exec:s0 capabilities=0x0\n')
Bill Peckham364c1cc2019-03-29 18:27:23 -0700418
419
Daniel Normand5d70ea2019-06-05 15:13:43 -0700420def merge_dynamic_partition_info_dicts(framework_dict,
421 vendor_dict,
Daniel Normana61cde02019-05-03 14:19:13 -0700422 include_dynamic_partition_list=True,
423 size_prefix='',
424 size_suffix='',
425 list_prefix='',
426 list_suffix=''):
427 """Merges dynamic partition info variables.
428
429 Args:
Daniel Normand5d70ea2019-06-05 15:13:43 -0700430 framework_dict: The dictionary of dynamic partition info variables from the
431 partial framework target files.
432 vendor_dict: The dictionary of dynamic partition info variables from the
433 partial vendor target files.
Daniel Normana61cde02019-05-03 14:19:13 -0700434 include_dynamic_partition_list: If true, merges the dynamic_partition_list
435 variable. Not all use cases need this variable merged.
436 size_prefix: The prefix in partition group size variables that precedes the
437 name of the partition group. For example, partition group 'group_a' with
438 corresponding size variable 'super_group_a_group_size' would have the
439 size_prefix 'super_'.
440 size_suffix: Similar to size_prefix but for the variable's suffix. For
441 example, 'super_group_a_group_size' would have size_suffix '_group_size'.
442 list_prefix: Similar to size_prefix but for the partition group's
443 partition_list variable.
444 list_suffix: Similar to size_suffix but for the partition group's
445 partition_list variable.
446
447 Returns:
448 The merged dynamic partition info dictionary.
449 """
450 merged_dict = {}
Daniel Normand5d70ea2019-06-05 15:13:43 -0700451 # Partition groups and group sizes are defined by the vendor dict because
452 # these values may vary for each board that uses a shared system image.
453 merged_dict['super_partition_groups'] = vendor_dict['super_partition_groups']
Daniel Normana61cde02019-05-03 14:19:13 -0700454 if include_dynamic_partition_list:
Daniel Normand5d70ea2019-06-05 15:13:43 -0700455 framework_dynamic_partition_list = framework_dict.get(
456 'dynamic_partition_list', '')
457 vendor_dynamic_partition_list = vendor_dict.get('dynamic_partition_list',
Daniel Normana61cde02019-05-03 14:19:13 -0700458 '')
Daniel Normana61cde02019-05-03 14:19:13 -0700459 merged_dict['dynamic_partition_list'] = (
Daniel Normand5d70ea2019-06-05 15:13:43 -0700460 '%s %s' % (framework_dynamic_partition_list,
461 vendor_dynamic_partition_list)).strip()
Daniel Normana61cde02019-05-03 14:19:13 -0700462 for partition_group in merged_dict['super_partition_groups'].split(' '):
Daniel Normand5d70ea2019-06-05 15:13:43 -0700463 # Set the partition group's size using the value from the vendor dict.
Daniel Normana61cde02019-05-03 14:19:13 -0700464 key = '%s%s%s' % (size_prefix, partition_group, size_suffix)
Daniel Normand5d70ea2019-06-05 15:13:43 -0700465 if key not in vendor_dict:
466 raise ValueError('Vendor dict does not contain required key %s.' % key)
467 merged_dict[key] = vendor_dict[key]
Daniel Normana61cde02019-05-03 14:19:13 -0700468
469 # Set the partition group's partition list using a concatenation of the
Daniel Normand5d70ea2019-06-05 15:13:43 -0700470 # framework and vendor partition lists.
Daniel Normana61cde02019-05-03 14:19:13 -0700471 key = '%s%s%s' % (list_prefix, partition_group, list_suffix)
472 merged_dict[key] = (
Daniel Normand5d70ea2019-06-05 15:13:43 -0700473 '%s %s' %
474 (framework_dict.get(key, ''), vendor_dict.get(key, ''))).strip()
Daniel Normana61cde02019-05-03 14:19:13 -0700475 return merged_dict
476
477
Daniel Normand5d70ea2019-06-05 15:13:43 -0700478def process_misc_info_txt(framework_target_files_temp_dir,
479 vendor_target_files_temp_dir,
480 output_target_files_temp_dir,
481 framework_misc_info_keys):
Daniel Normane5b134a2019-04-17 14:54:06 -0700482 """Perform special processing for META/misc_info.txt.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800483
484 This function merges the contents of the META/misc_info.txt files from the
Daniel Normand5d70ea2019-06-05 15:13:43 -0700485 framework directory and the vendor directory, placing the merged result in the
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800486 output directory. The precondition in that the files are already extracted.
487 The post condition is that the output META/misc_info.txt contains the merged
488 content.
489
490 Args:
Daniel Normand5d70ea2019-06-05 15:13:43 -0700491 framework_target_files_temp_dir: The name of a directory containing the
492 special items extracted from the framework target files package.
493 vendor_target_files_temp_dir: The name of a directory containing the special
494 items extracted from the vendor target files package.
Daniel Normane5b134a2019-04-17 14:54:06 -0700495 output_target_files_temp_dir: The name of a directory that will be used to
496 create the output target files package after all the special cases are
497 processed.
Daniel Normand5d70ea2019-06-05 15:13:43 -0700498 framework_misc_info_keys: A list of keys to obtain from the framework
499 instance of META/misc_info.txt. The remaining keys from the vendor
500 instance.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800501 """
502
Kiyoung Kimebe7c9c2019-06-25 17:09:55 +0900503 misc_info_path = ['META', 'misc_info.txt']
504 framework_dict = common.LoadDictionaryFromFile(
505 os.path.join(framework_target_files_temp_dir, *misc_info_path))
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800506
Daniel Normand5d70ea2019-06-05 15:13:43 -0700507 # We take most of the misc info from the vendor target files.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800508
Kiyoung Kimebe7c9c2019-06-25 17:09:55 +0900509 merged_dict = common.LoadDictionaryFromFile(
510 os.path.join(vendor_target_files_temp_dir, *misc_info_path))
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800511
Daniel Normand5d70ea2019-06-05 15:13:43 -0700512 # Replace certain values in merged_dict with values from
513 # framework_dict.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800514
Daniel Normand5d70ea2019-06-05 15:13:43 -0700515 for key in framework_misc_info_keys:
516 merged_dict[key] = framework_dict[key]
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800517
Daniel Norman19b9fe92019-03-19 14:48:02 -0700518 # Merge misc info keys used for Dynamic Partitions.
Daniel Normand5d70ea2019-06-05 15:13:43 -0700519 if (merged_dict.get('use_dynamic_partitions') == 'true') and (
520 framework_dict.get('use_dynamic_partitions') == 'true'):
Daniel Normana61cde02019-05-03 14:19:13 -0700521 merged_dynamic_partitions_dict = merge_dynamic_partition_info_dicts(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700522 framework_dict=framework_dict,
523 vendor_dict=merged_dict,
Daniel Normana61cde02019-05-03 14:19:13 -0700524 size_prefix='super_',
525 size_suffix='_group_size',
526 list_prefix='super_',
527 list_suffix='_partition_list')
Daniel Normand5d70ea2019-06-05 15:13:43 -0700528 merged_dict.update(merged_dynamic_partitions_dict)
Tao Bao48a2feb2019-06-28 11:00:05 -0700529 # Ensure that add_img_to_target_files rebuilds super split images for
530 # devices that retrofit dynamic partitions. This flag may have been set to
531 # false in the partial builds to prevent duplicate building of super.img.
Daniel Norman0bf940c2019-06-10 12:50:19 -0700532 merged_dict['build_super_partition'] = 'true'
Daniel Norman19b9fe92019-03-19 14:48:02 -0700533
Daniel Normand5d70ea2019-06-05 15:13:43 -0700534 # Replace <image>_selinux_fc values with framework or vendor file_contexts.bin
Daniel Norman72c626f2019-05-13 15:58:14 -0700535 # depending on which dictionary the key came from.
536 # Only the file basename is required because all selinux_fc properties are
537 # replaced with the full path to the file under META/ when misc_info.txt is
538 # loaded from target files for repacking. See common.py LoadInfoDict().
Daniel Normand5d70ea2019-06-05 15:13:43 -0700539 for key in merged_dict:
Daniel Norman72c626f2019-05-13 15:58:14 -0700540 if key.endswith('_selinux_fc'):
Daniel Normand5d70ea2019-06-05 15:13:43 -0700541 merged_dict[key] = 'vendor_file_contexts.bin'
542 for key in framework_dict:
Daniel Norman72c626f2019-05-13 15:58:14 -0700543 if key.endswith('_selinux_fc'):
Daniel Normand5d70ea2019-06-05 15:13:43 -0700544 merged_dict[key] = 'framework_file_contexts.bin'
Daniel Norman72c626f2019-05-13 15:58:14 -0700545
Daniel Normane5b134a2019-04-17 14:54:06 -0700546 output_misc_info_txt = os.path.join(output_target_files_temp_dir, 'META',
547 'misc_info.txt')
Daniel Normand5d70ea2019-06-05 15:13:43 -0700548 write_sorted_data(data=merged_dict, path=output_misc_info_txt)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800549
550
Daniel Normand5d70ea2019-06-05 15:13:43 -0700551def process_dynamic_partitions_info_txt(framework_target_files_dir,
552 vendor_target_files_dir,
Daniel Normana61cde02019-05-03 14:19:13 -0700553 output_target_files_dir):
554 """Perform special processing for META/dynamic_partitions_info.txt.
555
556 This function merges the contents of the META/dynamic_partitions_info.txt
Daniel Normand5d70ea2019-06-05 15:13:43 -0700557 files from the framework directory and the vendor directory, placing the
558 merged result in the output directory.
Daniel Normana61cde02019-05-03 14:19:13 -0700559
Daniel Normand5d70ea2019-06-05 15:13:43 -0700560 This function does nothing if META/dynamic_partitions_info.txt from the vendor
Daniel Normana61cde02019-05-03 14:19:13 -0700561 directory does not exist.
562
563 Args:
Daniel Normand5d70ea2019-06-05 15:13:43 -0700564 framework_target_files_dir: The name of a directory containing the special
565 items extracted from the framework target files package.
566 vendor_target_files_dir: The name of a directory containing the special
567 items extracted from the vendor target files package.
Daniel Normana61cde02019-05-03 14:19:13 -0700568 output_target_files_dir: The name of a directory that will be used to create
569 the output target files package after all the special cases are processed.
570 """
571
572 if not os.path.exists(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700573 os.path.join(vendor_target_files_dir, 'META',
Daniel Normana61cde02019-05-03 14:19:13 -0700574 'dynamic_partitions_info.txt')):
575 return
576
Kiyoung Kimebe7c9c2019-06-25 17:09:55 +0900577 dynamic_partitions_info_path = ['META', 'dynamic_partitions_info.txt']
Daniel Normana61cde02019-05-03 14:19:13 -0700578
Kiyoung Kimebe7c9c2019-06-25 17:09:55 +0900579 framework_dynamic_partitions_dict = common.LoadDictionaryFromFile(
580 os.path.join(framework_target_files_dir, *dynamic_partitions_info_path))
581 vendor_dynamic_partitions_dict = common.LoadDictionaryFromFile(
582 os.path.join(vendor_target_files_dir, *dynamic_partitions_info_path))
Daniel Normana61cde02019-05-03 14:19:13 -0700583
584 merged_dynamic_partitions_dict = merge_dynamic_partition_info_dicts(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700585 framework_dict=framework_dynamic_partitions_dict,
586 vendor_dict=vendor_dynamic_partitions_dict,
Daniel Normana61cde02019-05-03 14:19:13 -0700587 # META/dynamic_partitions_info.txt does not use dynamic_partition_list.
588 include_dynamic_partition_list=False,
589 size_suffix='_size',
590 list_suffix='_partition_list')
591
592 output_dynamic_partitions_info_txt = os.path.join(
593 output_target_files_dir, 'META', 'dynamic_partitions_info.txt')
Chris Grossfabf50a2019-05-02 12:42:09 -0700594 write_sorted_data(
595 data=merged_dynamic_partitions_dict,
596 path=output_dynamic_partitions_info_txt)
597
598
Daniel Normand5d70ea2019-06-05 15:13:43 -0700599def process_apex_keys_apk_certs_common(framework_target_files_dir,
600 vendor_target_files_dir,
Chris Grossfabf50a2019-05-02 12:42:09 -0700601 output_target_files_dir, file_name):
602 """Perform special processing for META/apexkeys.txt or META/apkcerts.txt.
603
604 This function merges the contents of the META/apexkeys.txt or
Daniel Normand5d70ea2019-06-05 15:13:43 -0700605 META/apkcerts.txt files from the framework directory and the vendor
606 directory, placing the merged result in the output directory. The
607 precondition in that the files are already extracted. The post condition
608 is that the output META/apexkeys.txt or META/apkcerts.txt contains the
609 merged content.
Chris Grossfabf50a2019-05-02 12:42:09 -0700610
611 Args:
Daniel Normand5d70ea2019-06-05 15:13:43 -0700612 framework_target_files_dir: The name of a directory containing the special
613 items extracted from the framework target files package.
614 vendor_target_files_dir: The name of a directory containing the special
615 items extracted from the vendor target files package.
Chris Grossfabf50a2019-05-02 12:42:09 -0700616 output_target_files_dir: The name of a directory that will be used to create
617 the output target files package after all the special cases are processed.
618 file_name: The name of the file to merge. One of apkcerts.txt or
619 apexkeys.txt.
620 """
621
622 def read_helper(d):
623 temp = {}
624 file_path = os.path.join(d, 'META', file_name)
625 with open(file_path) as f:
626 for line in f:
627 if line.strip():
628 temp[line.split()[0]] = line.strip()
629 return temp
630
Daniel Normand5d70ea2019-06-05 15:13:43 -0700631 framework_dict = read_helper(framework_target_files_dir)
632 vendor_dict = read_helper(vendor_target_files_dir)
Chris Grossfabf50a2019-05-02 12:42:09 -0700633
Daniel Normand5d70ea2019-06-05 15:13:43 -0700634 for key in framework_dict:
635 if key in vendor_dict and vendor_dict[key] != framework_dict[key]:
Chris Grossfabf50a2019-05-02 12:42:09 -0700636 raise ValueError('Conflicting entries found in %s:\n %s and\n %s' %
Daniel Normand5d70ea2019-06-05 15:13:43 -0700637 (file_name, framework_dict[key], vendor_dict[key]))
638 vendor_dict[key] = framework_dict[key]
Chris Grossfabf50a2019-05-02 12:42:09 -0700639
640 output_file = os.path.join(output_target_files_dir, 'META', file_name)
641
Daniel Normand5d70ea2019-06-05 15:13:43 -0700642 write_sorted_data(data=vendor_dict.values(), path=output_file)
Daniel Normana61cde02019-05-03 14:19:13 -0700643
644
Daniel Normand5d70ea2019-06-05 15:13:43 -0700645def copy_file_contexts(framework_target_files_dir, vendor_target_files_dir,
Daniel Norman72c626f2019-05-13 15:58:14 -0700646 output_target_files_dir):
647 """Creates named copies of each build's file_contexts.bin in output META/."""
Daniel Normand5d70ea2019-06-05 15:13:43 -0700648 framework_fc_path = os.path.join(framework_target_files_dir, 'META',
649 'framework_file_contexts.bin')
650 if not os.path.exists(framework_fc_path):
651 framework_fc_path = os.path.join(framework_target_files_dir, 'META',
652 'file_contexts.bin')
653 if not os.path.exists(framework_fc_path):
654 raise ValueError('Missing framework file_contexts.bin.')
655 shutil.copyfile(
656 framework_fc_path,
657 os.path.join(output_target_files_dir, 'META',
658 'framework_file_contexts.bin'))
659
660 vendor_fc_path = os.path.join(vendor_target_files_dir, 'META',
661 'vendor_file_contexts.bin')
662 if not os.path.exists(vendor_fc_path):
663 vendor_fc_path = os.path.join(vendor_target_files_dir, 'META',
Daniel Normanedf12472019-05-22 10:47:08 -0700664 'file_contexts.bin')
Daniel Normand5d70ea2019-06-05 15:13:43 -0700665 if not os.path.exists(vendor_fc_path):
666 raise ValueError('Missing vendor file_contexts.bin.')
Daniel Norman72c626f2019-05-13 15:58:14 -0700667 shutil.copyfile(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700668 vendor_fc_path,
669 os.path.join(output_target_files_dir, 'META', 'vendor_file_contexts.bin'))
Daniel Norman72c626f2019-05-13 15:58:14 -0700670
671
Daniel Normand5d70ea2019-06-05 15:13:43 -0700672def process_special_cases(framework_target_files_temp_dir,
673 vendor_target_files_temp_dir,
674 output_target_files_temp_dir,
675 framework_misc_info_keys, rebuild_recovery):
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800676 """Perform special-case processing for certain target files items.
677
678 Certain files in the output target files package require special-case
679 processing. This function performs all that special-case processing.
680
681 Args:
Daniel Normand5d70ea2019-06-05 15:13:43 -0700682 framework_target_files_temp_dir: The name of a directory containing the
683 special items extracted from the framework target files package.
684 vendor_target_files_temp_dir: The name of a directory containing the special
685 items extracted from the vendor target files package.
Daniel Normane5b134a2019-04-17 14:54:06 -0700686 output_target_files_temp_dir: The name of a directory that will be used to
687 create the output target files package after all the special cases are
688 processed.
Daniel Normand5d70ea2019-06-05 15:13:43 -0700689 framework_misc_info_keys: A list of keys to obtain from the framework
690 instance of META/misc_info.txt. The remaining keys from the vendor
691 instance.
Bill Peckham364c1cc2019-03-29 18:27:23 -0700692 rebuild_recovery: If true, rebuild the recovery patch used by non-A/B
Daniel Normane5b134a2019-04-17 14:54:06 -0700693 devices and write it to the system image.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800694 """
695
Daniel Normand5d70ea2019-06-05 15:13:43 -0700696 if 'ab_update' in framework_misc_info_keys:
Bill Peckham364c1cc2019-03-29 18:27:23 -0700697 process_ab_partitions_txt(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700698 framework_target_files_temp_dir=framework_target_files_temp_dir,
699 vendor_target_files_temp_dir=vendor_target_files_temp_dir,
Bill Peckham364c1cc2019-03-29 18:27:23 -0700700 output_target_files_temp_dir=output_target_files_temp_dir)
701
702 if rebuild_recovery:
703 append_recovery_to_filesystem_config(
704 output_target_files_temp_dir=output_target_files_temp_dir)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800705
Daniel Norman72c626f2019-05-13 15:58:14 -0700706 copy_file_contexts(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700707 framework_target_files_dir=framework_target_files_temp_dir,
708 vendor_target_files_dir=vendor_target_files_temp_dir,
Daniel Norman72c626f2019-05-13 15:58:14 -0700709 output_target_files_dir=output_target_files_temp_dir)
710
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800711 process_misc_info_txt(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700712 framework_target_files_temp_dir=framework_target_files_temp_dir,
713 vendor_target_files_temp_dir=vendor_target_files_temp_dir,
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800714 output_target_files_temp_dir=output_target_files_temp_dir,
Daniel Normand5d70ea2019-06-05 15:13:43 -0700715 framework_misc_info_keys=framework_misc_info_keys)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800716
Daniel Normana61cde02019-05-03 14:19:13 -0700717 process_dynamic_partitions_info_txt(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700718 framework_target_files_dir=framework_target_files_temp_dir,
719 vendor_target_files_dir=vendor_target_files_temp_dir,
Daniel Norman714bd122019-05-08 16:20:02 -0700720 output_target_files_dir=output_target_files_temp_dir)
Daniel Normana61cde02019-05-03 14:19:13 -0700721
Chris Grossfabf50a2019-05-02 12:42:09 -0700722 process_apex_keys_apk_certs_common(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700723 framework_target_files_dir=framework_target_files_temp_dir,
724 vendor_target_files_dir=vendor_target_files_temp_dir,
Chris Grossfabf50a2019-05-02 12:42:09 -0700725 output_target_files_dir=output_target_files_temp_dir,
726 file_name='apkcerts.txt')
727
728 process_apex_keys_apk_certs_common(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700729 framework_target_files_dir=framework_target_files_temp_dir,
730 vendor_target_files_dir=vendor_target_files_temp_dir,
Chris Grossfabf50a2019-05-02 12:42:09 -0700731 output_target_files_dir=output_target_files_temp_dir,
732 file_name='apexkeys.txt')
733
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800734
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900735def files_from_path(target_path, extra_args=None):
736 """Get files under given path.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800737
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900738 Get (sub)files from given target path and return sorted list.
739
740 Args:
741 target_path: Target path to get subfiles.
742 extra_args: List of extra argument for find command. Optional.
743
744 Returns:
745 Sorted files and directories list.
746 """
747
748 find_command = ['find', target_path] + (extra_args or [])
749 find_process = common.Run(find_command, stdout=subprocess.PIPE, verbose=False)
750 return common.RunAndCheckOutput(['sort'], stdin=find_process.stdout,
751 verbose=False)
752
753
754def create_merged_package(temp_dir, framework_target_files, framework_item_list,
755 vendor_target_files, vendor_item_list,
756 framework_misc_info_keys,
757 rebuild_recovery):
758 """Merge two target files packages into one target files structure.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800759
760 Args:
761 temp_dir: The name of a directory we use when we extract items from the
Daniel Normane5b134a2019-04-17 14:54:06 -0700762 input target files packages, and also a scratch directory that we use for
763 temporary files.
Daniel Normand5d70ea2019-06-05 15:13:43 -0700764 framework_target_files: The name of the zip archive containing the framework
Daniel Normane5b134a2019-04-17 14:54:06 -0700765 partial target files package.
Daniel Normand5d70ea2019-06-05 15:13:43 -0700766 framework_item_list: The list of items to extract from the partial framework
Daniel Normane5b134a2019-04-17 14:54:06 -0700767 target files package as is, meaning these items will land in the output
Daniel Normand5d70ea2019-06-05 15:13:43 -0700768 target files package exactly as they appear in the input partial framework
Daniel Normane5b134a2019-04-17 14:54:06 -0700769 target files package.
Daniel Normand5d70ea2019-06-05 15:13:43 -0700770 vendor_target_files: The name of the zip archive containing the vendor
771 partial target files package.
772 vendor_item_list: The list of items to extract from the partial vendor
773 target files package as is, meaning these items will land in the output
774 target files package exactly as they appear in the input partial vendor
Daniel Normane5b134a2019-04-17 14:54:06 -0700775 target files package.
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900776 framework_misc_info_keys: The list of keys to obtain from the framework
777 instance of META/misc_info.txt. The remaining keys from the vendor
778 instance.
Daniel Normana4911da2019-03-15 14:36:21 -0700779 rebuild_recovery: If true, rebuild the recovery patch used by non-A/B
Daniel Normane5b134a2019-04-17 14:54:06 -0700780 devices and write it to the system image.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800781
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900782 Returns:
783 Path to merged package under temp directory.
784 """
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800785
Daniel Normand5d70ea2019-06-05 15:13:43 -0700786 # Create directory names that we'll use when we extract files from framework,
787 # and vendor, and for zipping the final output.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800788
Daniel Normand5d70ea2019-06-05 15:13:43 -0700789 framework_target_files_temp_dir = os.path.join(temp_dir, 'framework')
790 vendor_target_files_temp_dir = os.path.join(temp_dir, 'vendor')
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800791 output_target_files_temp_dir = os.path.join(temp_dir, 'output')
792
Daniel Normand5d70ea2019-06-05 15:13:43 -0700793 # Extract "as is" items from the input framework partial target files package.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800794 # We extract them directly into the output temporary directory since the
795 # items do not need special case processing.
796
Bill Peckham889b0c62019-02-21 18:53:37 -0800797 extract_items(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700798 target_files=framework_target_files,
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800799 target_files_temp_dir=output_target_files_temp_dir,
Daniel Normand5d70ea2019-06-05 15:13:43 -0700800 extract_item_list=framework_item_list)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800801
Daniel Normand5d70ea2019-06-05 15:13:43 -0700802 # Extract "as is" items from the input vendor partial target files package. We
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800803 # extract them directly into the output temporary directory since the items
804 # do not need special case processing.
805
Bill Peckham889b0c62019-02-21 18:53:37 -0800806 extract_items(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700807 target_files=vendor_target_files,
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800808 target_files_temp_dir=output_target_files_temp_dir,
Daniel Normand5d70ea2019-06-05 15:13:43 -0700809 extract_item_list=vendor_item_list)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800810
Daniel Normand5d70ea2019-06-05 15:13:43 -0700811 # Extract "special" items from the input framework partial target files
812 # package. We extract these items to different directory since they require
813 # special processing before they will end up in the output directory.
814
815 extract_items(
816 target_files=framework_target_files,
817 target_files_temp_dir=framework_target_files_temp_dir,
818 extract_item_list=FRAMEWORK_EXTRACT_SPECIAL_ITEM_LIST)
819
820 # Extract "special" items from the input vendor partial target files package.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800821 # We extract these items to different directory since they require special
822 # processing before they will end up in the output directory.
823
Bill Peckham889b0c62019-02-21 18:53:37 -0800824 extract_items(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700825 target_files=vendor_target_files,
826 target_files_temp_dir=vendor_target_files_temp_dir,
827 extract_item_list=VENDOR_EXTRACT_SPECIAL_ITEM_LIST)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800828
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800829 # Now that the temporary directories contain all the extracted files, perform
830 # special case processing on any items that need it. After this function
831 # completes successfully, all the files we need to create the output target
832 # files package are in place.
833
Bill Peckham889b0c62019-02-21 18:53:37 -0800834 process_special_cases(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700835 framework_target_files_temp_dir=framework_target_files_temp_dir,
836 vendor_target_files_temp_dir=vendor_target_files_temp_dir,
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800837 output_target_files_temp_dir=output_target_files_temp_dir,
Daniel Normand5d70ea2019-06-05 15:13:43 -0700838 framework_misc_info_keys=framework_misc_info_keys,
Bill Peckham364c1cc2019-03-29 18:27:23 -0700839 rebuild_recovery=rebuild_recovery)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800840
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900841 return output_target_files_temp_dir
842
843
844def generate_images(target_files_dir, rebuild_recovery):
845 """Generate images from target files.
846
847 This function takes merged output temporary directory and create images
848 from it.
849
850 Args:
851 target_files_dir: Path to merged temp directory.
852 rebuild_recovery: If true, rebuild the recovery patch used by non-A/B
853 devices and write it to the system image.
854 """
855
856 # Regenerate IMAGES in the target directory.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800857
Daniel Normana4911da2019-03-15 14:36:21 -0700858 add_img_args = ['--verbose']
859 if rebuild_recovery:
860 add_img_args.append('--rebuild_recovery')
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900861 add_img_args.append(target_files_dir)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800862
863 add_img_to_target_files.main(add_img_args)
864
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900865
866def generate_super_empty_image(target_dir, output_super_empty):
867 """ Generate super_empty image from target package.
868
869 Args:
870 target_dir: Path to the target file package which contains misc_info.txt for
871 detailed information for super image.
872 output_super_empty: If provided, copies a super_empty.img file from the
873 target files package to this path.
874 """
Daniel Norman1bd2a1d2019-04-18 12:32:18 -0700875 # Create super_empty.img using the merged misc_info.txt.
876
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900877 misc_info_txt = os.path.join(target_dir, 'META',
Daniel Norman1bd2a1d2019-04-18 12:32:18 -0700878 'misc_info.txt')
879
Kiyoung Kimebe7c9c2019-06-25 17:09:55 +0900880 use_dynamic_partitions = common.LoadDictionaryFromFile(misc_info_txt).get(
881 'use_dynamic_partitions')
Daniel Norman1bd2a1d2019-04-18 12:32:18 -0700882
883 if use_dynamic_partitions != 'true' and output_super_empty:
884 raise ValueError(
885 'Building super_empty.img requires use_dynamic_partitions=true.')
886 elif use_dynamic_partitions == 'true':
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900887 super_empty_img = os.path.join(target_dir, 'IMAGES',
Daniel Norman1bd2a1d2019-04-18 12:32:18 -0700888 'super_empty.img')
889 build_super_image_args = [
890 misc_info_txt,
891 super_empty_img,
892 ]
893 build_super_image.main(build_super_image_args)
894
895 # Copy super_empty.img to the user-provided output_super_empty location.
896 if output_super_empty:
897 shutil.copyfile(super_empty_img, output_super_empty)
898
Daniel Normanb8a2f9d2019-04-24 12:55:51 -0700899
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900900def create_img_archive(source_path, target_path):
901 """ Create IMG archive in target path from source package.
Daniel Normanb8a2f9d2019-04-24 12:55:51 -0700902
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900903 Args:
904 source_path: Path of the source package to be packed.
905 target_path: Create IMG package from the source package.
906 """
Daniel Normanfdb38812019-04-15 09:47:24 -0700907
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900908 img_from_target_files_args = [
909 source_path,
910 target_path,
911 ]
912 img_from_target_files.main(img_from_target_files_args)
Daniel Normanfdb38812019-04-15 09:47:24 -0700913
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800914
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900915def create_target_files_archive(output_file, source_dir, temp_dir):
916 """ Create archive from target package.
917
918 Args:
919 output_file: The name of the zip archive target files package.
920 source_dir: The target directory contains package to be archived.
921 temp_dir: Path to temporary directory for any intermediate files.
922 """
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800923 output_target_files_list = os.path.join(temp_dir, 'output.list')
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900924 output_zip = os.path.abspath(output_file)
925 output_target_files_meta_dir = os.path.join(source_dir,
Daniel Normane5b134a2019-04-17 14:54:06 -0700926 'META')
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800927
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900928 meta_content = files_from_path(output_target_files_meta_dir)
929 other_content = files_from_path(source_dir,
930 ['-path', output_target_files_meta_dir,
931 '-prune', '-o', '-print'])
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800932
933 with open(output_target_files_list, 'wb') as f:
934 f.write(meta_content)
935 f.write(other_content)
936
937 command = [
Bill Peckhamf753e152019-02-19 18:02:46 -0800938 'soong_zip',
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800939 '-d',
Daniel Normane5b134a2019-04-17 14:54:06 -0700940 '-o',
941 output_zip,
942 '-C',
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900943 source_dir,
Daniel Normane5b134a2019-04-17 14:54:06 -0700944 '-l',
945 output_target_files_list,
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800946 ]
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900947
948 logger.info('creating %s', output_file)
Bill Peckham889b0c62019-02-21 18:53:37 -0800949 common.RunAndWait(command, verbose=True)
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900950 logger.info('finished creating %s', output_file)
951
952 return output_zip
953
954
955def create_ota_package(zip_package, output_ota):
956 """ Create OTA package from archived package.
957
958 Args:
959 zip_package: The name of the zip archived package.
960 output_ota: The name of the output zip archive ota package.
961 """
962 ota_from_target_files_args = [
963 zip_package,
964 output_ota,
965 ]
966 ota_from_target_files.main(ota_from_target_files_args)
967
968
969def merge_target_files(temp_dir, framework_target_files, framework_item_list,
970 framework_misc_info_keys, vendor_target_files,
971 vendor_item_list, output_target_files, output_dir,
972 output_item_list, output_ota, output_img,
973 output_super_empty, rebuild_recovery):
974 """Merge two target files packages together.
975
976 This function takes framework and vendor target files packages as input,
977 performs various file extractions, special case processing, and finally
978 creates a merged zip archive as output.
979
980 Args:
981 temp_dir: The name of a directory we use when we extract items from the
982 input target files packages, and also a scratch directory that we use for
983 temporary files.
984 framework_target_files: The name of the zip archive containing the framework
985 partial target files package.
986 framework_item_list: The list of items to extract from the partial framework
987 target files package as is, meaning these items will land in the output
988 target files package exactly as they appear in the input partial framework
989 target files package.
990 framework_misc_info_keys: The list of keys to obtain from the framework
991 instance of META/misc_info.txt. The remaining keys from the vendor
992 instance.
993 vendor_target_files: The name of the zip archive containing the vendor
994 partial target files package.
995 vendor_item_list: The list of items to extract from the partial vendor
996 target files package as is, meaning these items will land in the output
997 target files package exactly as they appear in the input partial vendor
998 target files package.
999 output_target_files: The name of the output zip archive target files package
1000 created by merging framework and vendor.
1001 output_dir: The destination directory for saving merged files.
1002 output_item_list: The list of items to copy into the output_dir.
1003 output_ota: The name of the output zip archive ota package.
1004 output_img: The name of the output zip archive img package.
1005 output_super_empty: If provided, creates a super_empty.img file from the
1006 merged target files package and saves it at this path.
1007 rebuild_recovery: If true, rebuild the recovery patch used by non-A/B
1008 devices and write it to the system image.
1009 """
1010
1011 logger.info('starting: merge framework %s and vendor %s into output %s',
1012 framework_target_files, vendor_target_files, output_target_files)
1013
1014 output_target_files_temp_dir = create_merged_package(
1015 temp_dir, framework_target_files, framework_item_list,
1016 vendor_target_files, vendor_item_list, framework_misc_info_keys,
1017 rebuild_recovery)
1018
1019 generate_images(output_target_files_temp_dir, rebuild_recovery)
1020
1021 generate_super_empty_image(output_target_files_temp_dir, output_super_empty)
1022
1023 if output_img:
1024 # Create the IMG package from the merged target files (before zipping, in
1025 # order to avoid an unnecessary unzip and copy).
1026 create_img_archive(output_target_files_temp_dir, output_img)
1027
1028 # Finally, create the output target files zip archive and/or copy the
1029 # output items to the output target files directory.
1030
1031 if output_dir:
1032 copy_items(output_target_files_temp_dir, output_dir, output_item_list)
1033
1034 if not output_target_files:
1035 return
1036
1037 output_zip = create_target_files_archive(output_target_files,
1038 output_target_files_temp_dir,
1039 temp_dir)
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001040
Daniel Norman3b64ce12019-04-16 16:11:35 -07001041 # Create the OTA package from the merged target files package.
1042
1043 if output_ota:
Kiyoung Kim7cbeda72019-06-28 13:26:04 +09001044 create_ota_package(output_zip, output_ota)
Daniel Norman3b64ce12019-04-16 16:11:35 -07001045
Daniel Norman1bd2a1d2019-04-18 12:32:18 -07001046
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001047def call_func_with_temp_dir(func, keep_tmp):
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001048 """Manage the creation and cleanup of the temporary directory.
1049
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001050 This function calls the given function after first creating a temporary
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001051 directory. It also cleans up the temporary directory.
1052
1053 Args:
Daniel Normane5b134a2019-04-17 14:54:06 -07001054 func: The function to call. Should accept one parameter, the path to the
1055 temporary directory.
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001056 keep_tmp: Keep the temporary directory after processing is complete.
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001057 """
1058
1059 # Create a temporary directory. This will serve as the parent of directories
1060 # we use when we extract items from the input target files packages, and also
1061 # a scratch directory that we use for temporary files.
1062
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001063 temp_dir = common.MakeTempDir(prefix='merge_target_files_')
1064
1065 try:
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001066 func(temp_dir)
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001067 finally:
1068 if keep_tmp:
1069 logger.info('keeping %s', temp_dir)
1070 else:
1071 common.Cleanup()
1072
1073
1074def main():
1075 """The main function.
1076
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001077 Process command line arguments, then call merge_target_files to
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001078 perform the heavy lifting.
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001079 """
1080
1081 common.InitLogging()
1082
Bill Peckhamf753e152019-02-19 18:02:46 -08001083 def option_handler(o, a):
1084 if o == '--system-target-files':
Daniel Normand5d70ea2019-06-05 15:13:43 -07001085 logger.warning(
1086 '--system-target-files has been renamed to --framework-target-files')
1087 OPTIONS.framework_target_files = a
1088 elif o == '--framework-target-files':
1089 OPTIONS.framework_target_files = a
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001090 elif o == '--system-item-list':
Daniel Normand5d70ea2019-06-05 15:13:43 -07001091 logger.warning(
1092 '--system-item-list has been renamed to --framework-item-list')
1093 OPTIONS.framework_item_list = a
1094 elif o == '--framework-item-list':
1095 OPTIONS.framework_item_list = a
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001096 elif o == '--system-misc-info-keys':
Daniel Normand5d70ea2019-06-05 15:13:43 -07001097 logger.warning(
Kiyoung Kimebe7c9c2019-06-25 17:09:55 +09001098 '--system-misc-info-keys has been renamed to '
1099 '--framework-misc-info-keys'
Daniel Normand5d70ea2019-06-05 15:13:43 -07001100 )
1101 OPTIONS.framework_misc_info_keys = a
1102 elif o == '--framework-misc-info-keys':
1103 OPTIONS.framework_misc_info_keys = a
Bill Peckhamf753e152019-02-19 18:02:46 -08001104 elif o == '--other-target-files':
Daniel Normand5d70ea2019-06-05 15:13:43 -07001105 logger.warning(
1106 '--other-target-files has been renamed to --vendor-target-files')
1107 OPTIONS.vendor_target_files = a
1108 elif o == '--vendor-target-files':
1109 OPTIONS.vendor_target_files = a
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001110 elif o == '--other-item-list':
Daniel Normand5d70ea2019-06-05 15:13:43 -07001111 logger.warning('--other-item-list has been renamed to --vendor-item-list')
1112 OPTIONS.vendor_item_list = a
1113 elif o == '--vendor-item-list':
1114 OPTIONS.vendor_item_list = a
Bill Peckhamf753e152019-02-19 18:02:46 -08001115 elif o == '--output-target-files':
1116 OPTIONS.output_target_files = a
Daniel Normanfdb38812019-04-15 09:47:24 -07001117 elif o == '--output-dir':
1118 OPTIONS.output_dir = a
1119 elif o == '--output-item-list':
1120 OPTIONS.output_item_list = a
Daniel Norman3b64ce12019-04-16 16:11:35 -07001121 elif o == '--output-ota':
1122 OPTIONS.output_ota = a
Daniel Norman1bd2a1d2019-04-18 12:32:18 -07001123 elif o == '--output-img':
1124 OPTIONS.output_img = a
Daniel Normanf0318252019-04-15 11:34:56 -07001125 elif o == '--output-super-empty':
1126 OPTIONS.output_super_empty = a
Daniel Normana4911da2019-03-15 14:36:21 -07001127 elif o == '--rebuild_recovery':
1128 OPTIONS.rebuild_recovery = True
Bill Peckham364c1cc2019-03-29 18:27:23 -07001129 elif o == '--keep-tmp':
Bill Peckhamf753e152019-02-19 18:02:46 -08001130 OPTIONS.keep_tmp = True
1131 else:
1132 return False
1133 return True
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001134
Bill Peckhamf753e152019-02-19 18:02:46 -08001135 args = common.ParseOptions(
Daniel Normane5b134a2019-04-17 14:54:06 -07001136 sys.argv[1:],
1137 __doc__,
Bill Peckhamf753e152019-02-19 18:02:46 -08001138 extra_long_opts=[
1139 'system-target-files=',
Daniel Normand5d70ea2019-06-05 15:13:43 -07001140 'framework-target-files=',
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001141 'system-item-list=',
Daniel Normand5d70ea2019-06-05 15:13:43 -07001142 'framework-item-list=',
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001143 'system-misc-info-keys=',
Daniel Normand5d70ea2019-06-05 15:13:43 -07001144 'framework-misc-info-keys=',
Bill Peckhamf753e152019-02-19 18:02:46 -08001145 'other-target-files=',
Daniel Normand5d70ea2019-06-05 15:13:43 -07001146 'vendor-target-files=',
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001147 'other-item-list=',
Daniel Normand5d70ea2019-06-05 15:13:43 -07001148 'vendor-item-list=',
Bill Peckhamf753e152019-02-19 18:02:46 -08001149 'output-target-files=',
Daniel Normanfdb38812019-04-15 09:47:24 -07001150 'output-dir=',
1151 'output-item-list=',
Daniel Norman3b64ce12019-04-16 16:11:35 -07001152 'output-ota=',
Daniel Norman1bd2a1d2019-04-18 12:32:18 -07001153 'output-img=',
Daniel Normanf0318252019-04-15 11:34:56 -07001154 'output-super-empty=',
Daniel Normana4911da2019-03-15 14:36:21 -07001155 'rebuild_recovery',
Bill Peckham364c1cc2019-03-29 18:27:23 -07001156 'keep-tmp',
Bill Peckhamf753e152019-02-19 18:02:46 -08001157 ],
1158 extra_option_handler=option_handler)
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001159
Daniel Normand5d70ea2019-06-05 15:13:43 -07001160 if (args or OPTIONS.framework_target_files is None or
1161 OPTIONS.vendor_target_files is None or
Daniel Normane5b134a2019-04-17 14:54:06 -07001162 (OPTIONS.output_target_files is None and OPTIONS.output_dir is None) or
1163 (OPTIONS.output_dir is not None and OPTIONS.output_item_list is None)):
Bill Peckhamf753e152019-02-19 18:02:46 -08001164 common.Usage(__doc__)
Bill Peckham889b0c62019-02-21 18:53:37 -08001165 sys.exit(1)
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001166
Daniel Normand5d70ea2019-06-05 15:13:43 -07001167 if OPTIONS.framework_item_list:
1168 framework_item_list = read_config_list(OPTIONS.framework_item_list)
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001169 else:
Daniel Normand5d70ea2019-06-05 15:13:43 -07001170 framework_item_list = DEFAULT_FRAMEWORK_ITEM_LIST
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001171
Daniel Normand5d70ea2019-06-05 15:13:43 -07001172 if OPTIONS.framework_misc_info_keys:
1173 framework_misc_info_keys = read_config_list(
1174 OPTIONS.framework_misc_info_keys)
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001175 else:
Daniel Normand5d70ea2019-06-05 15:13:43 -07001176 framework_misc_info_keys = DEFAULT_FRAMEWORK_MISC_INFO_KEYS
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001177
Daniel Normand5d70ea2019-06-05 15:13:43 -07001178 if OPTIONS.vendor_item_list:
1179 vendor_item_list = read_config_list(OPTIONS.vendor_item_list)
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001180 else:
Daniel Normand5d70ea2019-06-05 15:13:43 -07001181 vendor_item_list = DEFAULT_VENDOR_ITEM_LIST
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001182
Daniel Normanfdb38812019-04-15 09:47:24 -07001183 if OPTIONS.output_item_list:
1184 output_item_list = read_config_list(OPTIONS.output_item_list)
1185 else:
1186 output_item_list = None
1187
Daniel Normane5964522019-03-19 10:32:03 -07001188 if not validate_config_lists(
Daniel Normand5d70ea2019-06-05 15:13:43 -07001189 framework_item_list=framework_item_list,
1190 framework_misc_info_keys=framework_misc_info_keys,
1191 vendor_item_list=vendor_item_list):
Daniel Normane5964522019-03-19 10:32:03 -07001192 sys.exit(1)
1193
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001194 call_func_with_temp_dir(
1195 lambda temp_dir: merge_target_files(
1196 temp_dir=temp_dir,
Daniel Normand5d70ea2019-06-05 15:13:43 -07001197 framework_target_files=OPTIONS.framework_target_files,
1198 framework_item_list=framework_item_list,
1199 framework_misc_info_keys=framework_misc_info_keys,
1200 vendor_target_files=OPTIONS.vendor_target_files,
1201 vendor_item_list=vendor_item_list,
Daniel Normana4911da2019-03-15 14:36:21 -07001202 output_target_files=OPTIONS.output_target_files,
Daniel Normanfdb38812019-04-15 09:47:24 -07001203 output_dir=OPTIONS.output_dir,
1204 output_item_list=output_item_list,
Daniel Norman3b64ce12019-04-16 16:11:35 -07001205 output_ota=OPTIONS.output_ota,
Daniel Norman1bd2a1d2019-04-18 12:32:18 -07001206 output_img=OPTIONS.output_img,
Daniel Normanf0318252019-04-15 11:34:56 -07001207 output_super_empty=OPTIONS.output_super_empty,
Daniel Normane5b134a2019-04-17 14:54:06 -07001208 rebuild_recovery=OPTIONS.rebuild_recovery), OPTIONS.keep_tmp)
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001209
1210
1211if __name__ == '__main__':
Bill Peckham889b0c62019-02-21 18:53:37 -08001212 main()