blob: 407ee7e8a345d934fca093d1a4bd3ff95a8dace7 [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.
Tao Bao2ad4b822019-06-27 16:52:12 -070016
17"""
18This script merges two partial target files packages.
Bill Peckhame9eb5f92019-02-01 15:52:10 -080019
Daniel Normand5d70ea2019-06-05 15:13:43 -070020One package contains framework files, and the other contains vendor files.
Daniel Normane5b134a2019-04-17 14:54:06 -070021It produces a complete target files package that can be used to generate an
22OTA package.
Bill Peckhame9eb5f92019-02-01 15:52:10 -080023
24Usage: merge_target_files.py [args]
25
Daniel Normand5d70ea2019-06-05 15:13:43 -070026 --framework-target-files framework-target-files-zip-archive
27 The input target files package containing framework bits. This is a zip
Bill Peckhame9eb5f92019-02-01 15:52:10 -080028 archive.
29
Daniel Normand5d70ea2019-06-05 15:13:43 -070030 --framework-item-list framework-item-list-file
Daniel Norman2c99c5b2019-03-07 13:01:48 -080031 The optional path to a newline-separated config file that replaces the
Daniel Normand5d70ea2019-06-05 15:13:43 -070032 contents of DEFAULT_FRAMEWORK_ITEM_LIST if provided.
Daniel Norman2c99c5b2019-03-07 13:01:48 -080033
Daniel Normand5d70ea2019-06-05 15:13:43 -070034 --framework-misc-info-keys framework-misc-info-keys-file
Daniel Norman2c99c5b2019-03-07 13:01:48 -080035 The optional path to a newline-separated config file that replaces the
Daniel Normand5d70ea2019-06-05 15:13:43 -070036 contents of DEFAULT_FRAMEWORK_MISC_INFO_KEYS if provided.
Daniel Norman2c99c5b2019-03-07 13:01:48 -080037
Daniel Normand5d70ea2019-06-05 15:13:43 -070038 --vendor-target-files vendor-target-files-zip-archive
39 The input target files package containing vendor bits. This is a zip
Bill Peckhame9eb5f92019-02-01 15:52:10 -080040 archive.
41
Daniel Normand5d70ea2019-06-05 15:13:43 -070042 --vendor-item-list vendor-item-list-file
Daniel Norman2c99c5b2019-03-07 13:01:48 -080043 The optional path to a newline-separated config file that replaces the
Daniel Normand5d70ea2019-06-05 15:13:43 -070044 contents of DEFAULT_VENDOR_ITEM_LIST if provided.
Daniel Norman2c99c5b2019-03-07 13:01:48 -080045
Bill Peckhame9eb5f92019-02-01 15:52:10 -080046 --output-target-files output-target-files-package
Daniel Normanfdb38812019-04-15 09:47:24 -070047 If provided, the output merged target files package. Also a zip archive.
48
49 --output-dir output-directory
50 If provided, the destination directory for saving merged files. Requires
51 the --output-item-list flag.
52 Can be provided alongside --output-target-files, or by itself.
53
54 --output-item-list output-item-list-file.
55 The optional path to a newline-separated config file that specifies the
56 file patterns to copy into the --output-dir. Required if providing
57 the --output-dir flag.
Daniel Normana4911da2019-03-15 14:36:21 -070058
Daniel Norman3b64ce12019-04-16 16:11:35 -070059 --output-ota output-ota-package
60 The output ota package. This is a zip archive. Use of this flag may
61 require passing the --path common flag; see common.py.
62
Daniel Norman1bd2a1d2019-04-18 12:32:18 -070063 --output-img output-img-package
64 The output img package, suitable for use with 'fastboot update'. Use of
65 this flag may require passing the --path common flag; see common.py.
66
Daniel Normanf0318252019-04-15 11:34:56 -070067 --output-super-empty output-super-empty-image
68 If provided, creates a super_empty.img file from the merged target
69 files package and saves it at this path.
70
Daniel Normana4911da2019-03-15 14:36:21 -070071 --rebuild_recovery
72 Rebuild the recovery patch used by non-A/B devices and write it to the
73 system image.
Bill Peckham364c1cc2019-03-29 18:27:23 -070074
75 --keep-tmp
76 Keep tempoary files for debugging purposes.
Bill Peckhame9eb5f92019-02-01 15:52:10 -080077"""
78
79from __future__ import print_function
80
Bill Peckhame9eb5f92019-02-01 15:52:10 -080081import fnmatch
82import logging
83import os
Daniel Normanfdb38812019-04-15 09:47:24 -070084import shutil
Bill Peckham540d91a2019-04-25 14:18:16 -070085import subprocess
Bill Peckhame9eb5f92019-02-01 15:52:10 -080086import sys
87import zipfile
88
Bill Peckhame9eb5f92019-02-01 15:52:10 -080089import add_img_to_target_files
Daniel Normanf0318252019-04-15 11:34:56 -070090import build_super_image
91import 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
98OPTIONS.verbose = True
Daniel Normand5d70ea2019-06-05 15:13:43 -070099OPTIONS.framework_target_files = None
100OPTIONS.framework_item_list = None
101OPTIONS.framework_misc_info_keys = None
102OPTIONS.vendor_target_files = None
103OPTIONS.vendor_item_list = None
Bill Peckhamf753e152019-02-19 18:02:46 -0800104OPTIONS.output_target_files = None
Daniel Normanfdb38812019-04-15 09:47:24 -0700105OPTIONS.output_dir = None
106OPTIONS.output_item_list = None
Daniel Norman3b64ce12019-04-16 16:11:35 -0700107OPTIONS.output_ota = None
Daniel Norman1bd2a1d2019-04-18 12:32:18 -0700108OPTIONS.output_img = None
Daniel Normanf0318252019-04-15 11:34:56 -0700109OPTIONS.output_super_empty = None
Daniel Normana4911da2019-03-15 14:36:21 -0700110OPTIONS.rebuild_recovery = False
Bill Peckhamf753e152019-02-19 18:02:46 -0800111OPTIONS.keep_tmp = False
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800112
Daniel Normand5d70ea2019-06-05 15:13:43 -0700113# DEFAULT_FRAMEWORK_ITEM_LIST is a list of items to extract from the partial
114# framework target files package as is, meaning these items will land in the
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800115# output target files package exactly as they appear in the input partial
Daniel Normand5d70ea2019-06-05 15:13:43 -0700116# framework target files package.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800117
Daniel Normand5d70ea2019-06-05 15:13:43 -0700118DEFAULT_FRAMEWORK_ITEM_LIST = (
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800119 'META/apkcerts.txt',
120 'META/filesystem_config.txt',
121 'META/root_filesystem_config.txt',
122 'META/system_manifest.xml',
123 'META/system_matrix.xml',
124 'META/update_engine_config.txt',
125 'PRODUCT/*',
126 'ROOT/*',
127 'SYSTEM/*',
Daniel Normanedf12472019-05-22 10:47:08 -0700128)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800129
Daniel Normand5d70ea2019-06-05 15:13:43 -0700130# FRAMEWORK_EXTRACT_SPECIAL_ITEM_LIST is a list of items to extract from the
131# partial framework target files package that need some special processing, such
132# as some sort of combination with items from the partial vendor target files
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800133# package.
134
Daniel Normand5d70ea2019-06-05 15:13:43 -0700135FRAMEWORK_EXTRACT_SPECIAL_ITEM_LIST = ('META/*',)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800136
Daniel Normand5d70ea2019-06-05 15:13:43 -0700137# DEFAULT_FRAMEWORK_MISC_INFO_KEYS is a list of keys to obtain from the
138# framework instance of META/misc_info.txt. The remaining keys from the
139# vendor instance.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800140
Daniel Normand5d70ea2019-06-05 15:13:43 -0700141DEFAULT_FRAMEWORK_MISC_INFO_KEYS = (
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800142 'avb_system_hashtree_enable',
143 'avb_system_add_hashtree_footer_args',
144 'avb_system_key_path',
145 'avb_system_algorithm',
146 'avb_system_rollback_index_location',
147 'avb_product_hashtree_enable',
148 'avb_product_add_hashtree_footer_args',
149 'avb_product_services_hashtree_enable',
150 'avb_product_services_add_hashtree_footer_args',
151 'system_root_image',
152 'root_dir',
153 'ab_update',
154 'default_system_dev_certificate',
155 'system_size',
Daniel Normanedf12472019-05-22 10:47:08 -0700156)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800157
Daniel Normand5d70ea2019-06-05 15:13:43 -0700158# DEFAULT_VENDOR_ITEM_LIST is a list of items to extract from the partial
159# vendor target files package as is, meaning these items will land in the output
160# target files package exactly as they appear in the input partial vendor target
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800161# files package.
162
Daniel Normand5d70ea2019-06-05 15:13:43 -0700163DEFAULT_VENDOR_ITEM_LIST = (
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800164 'META/boot_filesystem_config.txt',
165 'META/otakeys.txt',
166 'META/releasetools.py',
167 'META/vendor_filesystem_config.txt',
168 'META/vendor_manifest.xml',
169 'META/vendor_matrix.xml',
170 'BOOT/*',
171 'DATA/*',
172 'ODM/*',
173 'OTA/android-info.txt',
174 'PREBUILT_IMAGES/*',
175 'RADIO/*',
176 'VENDOR/*',
Daniel Normanedf12472019-05-22 10:47:08 -0700177)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800178
Daniel Normand5d70ea2019-06-05 15:13:43 -0700179# VENDOR_EXTRACT_SPECIAL_ITEM_LIST is a list of items to extract from the
180# partial vendor target files package that need some special processing, such as
181# some sort of combination with items from the partial framework target files
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800182# package.
183
Daniel Normand5d70ea2019-06-05 15:13:43 -0700184VENDOR_EXTRACT_SPECIAL_ITEM_LIST = ('META/*',)
Daniel Normanedf12472019-05-22 10:47:08 -0700185
186# The merge config lists should not attempt to extract items from both
187# builds for any of the following partitions. The partitions in
188# SINGLE_BUILD_PARTITIONS should come entirely from a single build (either
Daniel Normand5d70ea2019-06-05 15:13:43 -0700189# framework or vendor, but not both).
Daniel Normanedf12472019-05-22 10:47:08 -0700190
191SINGLE_BUILD_PARTITIONS = (
192 'BOOT/',
193 'DATA/',
194 'ODM/',
195 'PRODUCT/',
196 'PRODUCT_SERVICES/',
197 'RADIO/',
198 'RECOVERY/',
199 'ROOT/',
200 'SYSTEM/',
201 'SYSTEM_OTHER/',
202 'VENDOR/',
203)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800204
205
Chris Grossfabf50a2019-05-02 12:42:09 -0700206def write_sorted_data(data, path):
Tao Bao2ad4b822019-06-27 16:52:12 -0700207 """Writes the sorted contents of either a list or dict to file.
Chris Grossfabf50a2019-05-02 12:42:09 -0700208
Tao Bao2ad4b822019-06-27 16:52:12 -0700209 This function sorts the contents of the list or dict and then writes the
210 resulting sorted contents to a file specified by path.
Chris Grossfabf50a2019-05-02 12:42:09 -0700211
212 Args:
213 data: The list or dict to sort and write.
214 path: Path to the file to write the sorted values to. The file at path will
215 be overridden if it exists.
216 """
217 with open(path, 'w') as output:
Daniel Normand5d70ea2019-06-05 15:13:43 -0700218 for entry in sorted(data):
Chris Grossfabf50a2019-05-02 12:42:09 -0700219 out_str = '{}={}\n'.format(entry, data[entry]) if isinstance(
220 data, dict) else '{}\n'.format(entry)
221 output.write(out_str)
222
223
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800224def extract_items(target_files, target_files_temp_dir, extract_item_list):
Tao Bao2ad4b822019-06-27 16:52:12 -0700225 """Extracts items from target files to temporary directory.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800226
227 This function extracts from the specified target files zip archive into the
228 specified temporary directory, the items specified in the extract item list.
229
230 Args:
231 target_files: The target files zip archive from which to extract items.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800232 target_files_temp_dir: The temporary directory where the extracted items
Daniel Normane5b134a2019-04-17 14:54:06 -0700233 will land.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800234 extract_item_list: A list of items to extract.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800235 """
236
237 logger.info('extracting from %s', target_files)
238
239 # Filter the extract_item_list to remove any items that do not exist in the
240 # zip file. Otherwise, the extraction step will fail.
241
242 with zipfile.ZipFile(
Tao Bao2ad4b822019-06-27 16:52:12 -0700243 target_files, allowZip64=True) as target_files_zipfile:
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800244 target_files_namelist = target_files_zipfile.namelist()
245
246 filtered_extract_item_list = []
247 for pattern in extract_item_list:
248 matching_namelist = fnmatch.filter(target_files_namelist, pattern)
249 if not matching_namelist:
250 logger.warning('no match for %s', pattern)
251 else:
252 filtered_extract_item_list.append(pattern)
253
Bill Peckham8ff3fbd2019-02-22 10:57:43 -0800254 # Extract from target_files into target_files_temp_dir the
255 # filtered_extract_item_list.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800256
Daniel Normane5b134a2019-04-17 14:54:06 -0700257 common.UnzipToDir(target_files, target_files_temp_dir,
258 filtered_extract_item_list)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800259
260
Daniel Normanfdb38812019-04-15 09:47:24 -0700261def copy_items(from_dir, to_dir, patterns):
262 """Similar to extract_items() except uses an input dir instead of zip."""
263 file_paths = []
264 for dirpath, _, filenames in os.walk(from_dir):
Daniel Normane5b134a2019-04-17 14:54:06 -0700265 file_paths.extend(
266 os.path.relpath(path=os.path.join(dirpath, filename), start=from_dir)
267 for filename in filenames)
Daniel Normanfdb38812019-04-15 09:47:24 -0700268
269 filtered_file_paths = set()
270 for pattern in patterns:
271 filtered_file_paths.update(fnmatch.filter(file_paths, pattern))
272
273 for file_path in filtered_file_paths:
274 original_file_path = os.path.join(from_dir, file_path)
275 copied_file_path = os.path.join(to_dir, file_path)
276 copied_file_dir = os.path.dirname(copied_file_path)
277 if not os.path.exists(copied_file_dir):
278 os.makedirs(copied_file_dir)
279 if os.path.islink(original_file_path):
280 os.symlink(os.readlink(original_file_path), copied_file_path)
281 else:
282 shutil.copyfile(original_file_path, copied_file_path)
283
284
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800285def read_config_list(config_file_path):
286 """Reads a config file into a list of strings.
287
288 Expects the file to be newline-separated.
289
290 Args:
291 config_file_path: The path to the config file to open and read.
Daniel Normane5b134a2019-04-17 14:54:06 -0700292
293 Returns:
294 The list of strings in the config file.
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800295 """
296 with open(config_file_path) as config_file:
297 return config_file.read().splitlines()
298
299
Daniel Normand5d70ea2019-06-05 15:13:43 -0700300def validate_config_lists(framework_item_list, framework_misc_info_keys,
301 vendor_item_list):
Daniel Normane5964522019-03-19 10:32:03 -0700302 """Performs validations on the merge config lists.
303
304 Args:
Daniel Normand5d70ea2019-06-05 15:13:43 -0700305 framework_item_list: The list of items to extract from the partial framework
Daniel Normane5b134a2019-04-17 14:54:06 -0700306 target files package as is.
Daniel Normand5d70ea2019-06-05 15:13:43 -0700307 framework_misc_info_keys: A list of keys to obtain from the framework
308 instance of META/misc_info.txt. The remaining keys from the vendor
309 instance.
310 vendor_item_list: The list of items to extract from the partial vendor
311 target files package as is.
Daniel Normane5964522019-03-19 10:32:03 -0700312
313 Returns:
314 False if a validation fails, otherwise true.
315 """
Daniel Normanedf12472019-05-22 10:47:08 -0700316 has_error = False
317
Daniel Normand5d70ea2019-06-05 15:13:43 -0700318 default_combined_item_set = set(DEFAULT_FRAMEWORK_ITEM_LIST)
319 default_combined_item_set.update(DEFAULT_VENDOR_ITEM_LIST)
Daniel Normane5964522019-03-19 10:32:03 -0700320
Daniel Normand5d70ea2019-06-05 15:13:43 -0700321 combined_item_set = set(framework_item_list)
322 combined_item_set.update(vendor_item_list)
Daniel Normane5964522019-03-19 10:32:03 -0700323
324 # Check that the merge config lists are not missing any item specified
325 # by the default config lists.
326 difference = default_combined_item_set.difference(combined_item_set)
327 if difference:
Daniel Normane5b134a2019-04-17 14:54:06 -0700328 logger.error('Missing merge config items: %s', list(difference))
Daniel Normane5964522019-03-19 10:32:03 -0700329 logger.error('Please ensure missing items are in either the '
Daniel Normand5d70ea2019-06-05 15:13:43 -0700330 'framework-item-list or vendor-item-list files provided to '
Daniel Normane5964522019-03-19 10:32:03 -0700331 'this script.')
Daniel Normanedf12472019-05-22 10:47:08 -0700332 has_error = True
333
334 for partition in SINGLE_BUILD_PARTITIONS:
Daniel Normand5d70ea2019-06-05 15:13:43 -0700335 in_framework = any(
336 item.startswith(partition) for item in framework_item_list)
337 in_vendor = any(item.startswith(partition) for item in vendor_item_list)
338 if in_framework and in_vendor:
Daniel Normanedf12472019-05-22 10:47:08 -0700339 logger.error(
Tao Bao2ad4b822019-06-27 16:52:12 -0700340 'Cannot extract items from %s for both the framework and vendor'
Kiyoung Kimebe7c9c2019-06-25 17:09:55 +0900341 ' builds. Please ensure only one merge config item list'
Tao Bao2ad4b822019-06-27 16:52:12 -0700342 ' includes %s.', partition, partition)
Daniel Normanedf12472019-05-22 10:47:08 -0700343 has_error = True
Daniel Normane5964522019-03-19 10:32:03 -0700344
Daniel Normand5d70ea2019-06-05 15:13:43 -0700345 if ('dynamic_partition_list' in framework_misc_info_keys) or (
346 'super_partition_groups' in framework_misc_info_keys):
Daniel Norman19b9fe92019-03-19 14:48:02 -0700347 logger.error('Dynamic partition misc info keys should come from '
Daniel Normand5d70ea2019-06-05 15:13:43 -0700348 'the vendor instance of META/misc_info.txt.')
Daniel Normanedf12472019-05-22 10:47:08 -0700349 has_error = True
Daniel Norman19b9fe92019-03-19 14:48:02 -0700350
Daniel Normanedf12472019-05-22 10:47:08 -0700351 return not has_error
Daniel Normane5964522019-03-19 10:32:03 -0700352
353
Daniel Normand5d70ea2019-06-05 15:13:43 -0700354def process_ab_partitions_txt(framework_target_files_temp_dir,
355 vendor_target_files_temp_dir,
Daniel Normane5b134a2019-04-17 14:54:06 -0700356 output_target_files_temp_dir):
Tao Bao2ad4b822019-06-27 16:52:12 -0700357 """Performs special processing for META/ab_partitions.txt.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800358
Tao Bao2ad4b822019-06-27 16:52:12 -0700359 This function merges the contents of the META/ab_partitions.txt files from the
360 framework directory and the vendor directory, placing the merged result in the
361 output directory. The precondition in that the files are already extracted.
362 The post condition is that the output META/ab_partitions.txt contains the
363 merged content. The format for each ab_partitions.txt a one partition name per
364 line. The output file contains the union of the parition names.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800365
366 Args:
Daniel Normand5d70ea2019-06-05 15:13:43 -0700367 framework_target_files_temp_dir: The name of a directory containing the
368 special items extracted from the framework target files package.
369 vendor_target_files_temp_dir: The name of a directory containing the special
370 items extracted from the vendor target files package.
Daniel Normane5b134a2019-04-17 14:54:06 -0700371 output_target_files_temp_dir: The name of a directory that will be used to
372 create the output target files package after all the special cases are
373 processed.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800374 """
375
Daniel Normand5d70ea2019-06-05 15:13:43 -0700376 framework_ab_partitions_txt = os.path.join(framework_target_files_temp_dir,
377 'META', 'ab_partitions.txt')
378
379 vendor_ab_partitions_txt = os.path.join(vendor_target_files_temp_dir, 'META',
Daniel Normane5b134a2019-04-17 14:54:06 -0700380 'ab_partitions.txt')
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800381
Daniel Normand5d70ea2019-06-05 15:13:43 -0700382 with open(framework_ab_partitions_txt) as f:
383 framework_ab_partitions = f.read().splitlines()
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800384
Daniel Normand5d70ea2019-06-05 15:13:43 -0700385 with open(vendor_ab_partitions_txt) as f:
386 vendor_ab_partitions = f.read().splitlines()
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800387
Daniel Normand5d70ea2019-06-05 15:13:43 -0700388 output_ab_partitions = set(framework_ab_partitions + vendor_ab_partitions)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800389
Daniel Normane5b134a2019-04-17 14:54:06 -0700390 output_ab_partitions_txt = os.path.join(output_target_files_temp_dir, 'META',
391 'ab_partitions.txt')
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800392
Chris Grossfabf50a2019-05-02 12:42:09 -0700393 write_sorted_data(data=output_ab_partitions, path=output_ab_partitions_txt)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800394
395
Bill Peckham364c1cc2019-03-29 18:27:23 -0700396def append_recovery_to_filesystem_config(output_target_files_temp_dir):
Tao Bao2ad4b822019-06-27 16:52:12 -0700397 """Performs special processing for META/filesystem_config.txt.
Bill Peckham364c1cc2019-03-29 18:27:23 -0700398
Tao Bao2ad4b822019-06-27 16:52:12 -0700399 This function appends recovery information to META/filesystem_config.txt so
400 that recovery patch regeneration will succeed.
Bill Peckham364c1cc2019-03-29 18:27:23 -0700401
402 Args:
Daniel Normane5b134a2019-04-17 14:54:06 -0700403 output_target_files_temp_dir: The name of a directory that will be used to
404 create the output target files package after all the special cases are
405 processed. We find filesystem_config.txt here.
Bill Peckham364c1cc2019-03-29 18:27:23 -0700406 """
407
Daniel Normane5b134a2019-04-17 14:54:06 -0700408 filesystem_config_txt = os.path.join(output_target_files_temp_dir, 'META',
409 'filesystem_config.txt')
Bill Peckham364c1cc2019-03-29 18:27:23 -0700410
411 with open(filesystem_config_txt, 'a') as f:
412 # TODO(bpeckham) this data is hard coded. It should be generated
413 # programmatically.
Daniel Normane5b134a2019-04-17 14:54:06 -0700414 f.write('system/bin/install-recovery.sh 0 0 750 '
415 'selabel=u:object_r:install_recovery_exec:s0 capabilities=0x0\n')
416 f.write('system/recovery-from-boot.p 0 0 644 '
417 'selabel=u:object_r:system_file:s0 capabilities=0x0\n')
418 f.write('system/etc/recovery.img 0 0 440 '
419 'selabel=u:object_r:install_recovery_exec:s0 capabilities=0x0\n')
Bill Peckham364c1cc2019-03-29 18:27:23 -0700420
421
Daniel Normand5d70ea2019-06-05 15:13:43 -0700422def merge_dynamic_partition_info_dicts(framework_dict,
423 vendor_dict,
Daniel Normana61cde02019-05-03 14:19:13 -0700424 include_dynamic_partition_list=True,
425 size_prefix='',
426 size_suffix='',
427 list_prefix='',
428 list_suffix=''):
429 """Merges dynamic partition info variables.
430
431 Args:
Daniel Normand5d70ea2019-06-05 15:13:43 -0700432 framework_dict: The dictionary of dynamic partition info variables from the
433 partial framework target files.
434 vendor_dict: The dictionary of dynamic partition info variables from the
435 partial vendor target files.
Daniel Normana61cde02019-05-03 14:19:13 -0700436 include_dynamic_partition_list: If true, merges the dynamic_partition_list
437 variable. Not all use cases need this variable merged.
438 size_prefix: The prefix in partition group size variables that precedes the
439 name of the partition group. For example, partition group 'group_a' with
440 corresponding size variable 'super_group_a_group_size' would have the
441 size_prefix 'super_'.
442 size_suffix: Similar to size_prefix but for the variable's suffix. For
443 example, 'super_group_a_group_size' would have size_suffix '_group_size'.
444 list_prefix: Similar to size_prefix but for the partition group's
445 partition_list variable.
446 list_suffix: Similar to size_suffix but for the partition group's
447 partition_list variable.
448
449 Returns:
450 The merged dynamic partition info dictionary.
451 """
452 merged_dict = {}
Daniel Normand5d70ea2019-06-05 15:13:43 -0700453 # Partition groups and group sizes are defined by the vendor dict because
454 # these values may vary for each board that uses a shared system image.
455 merged_dict['super_partition_groups'] = vendor_dict['super_partition_groups']
Daniel Normana61cde02019-05-03 14:19:13 -0700456 if include_dynamic_partition_list:
Daniel Normand5d70ea2019-06-05 15:13:43 -0700457 framework_dynamic_partition_list = framework_dict.get(
458 'dynamic_partition_list', '')
459 vendor_dynamic_partition_list = vendor_dict.get('dynamic_partition_list',
Daniel Normana61cde02019-05-03 14:19:13 -0700460 '')
Daniel Normana61cde02019-05-03 14:19:13 -0700461 merged_dict['dynamic_partition_list'] = (
Daniel Normand5d70ea2019-06-05 15:13:43 -0700462 '%s %s' % (framework_dynamic_partition_list,
463 vendor_dynamic_partition_list)).strip()
Daniel Normana61cde02019-05-03 14:19:13 -0700464 for partition_group in merged_dict['super_partition_groups'].split(' '):
Daniel Normand5d70ea2019-06-05 15:13:43 -0700465 # Set the partition group's size using the value from the vendor dict.
Daniel Normana61cde02019-05-03 14:19:13 -0700466 key = '%s%s%s' % (size_prefix, partition_group, size_suffix)
Daniel Normand5d70ea2019-06-05 15:13:43 -0700467 if key not in vendor_dict:
468 raise ValueError('Vendor dict does not contain required key %s.' % key)
469 merged_dict[key] = vendor_dict[key]
Daniel Normana61cde02019-05-03 14:19:13 -0700470
471 # Set the partition group's partition list using a concatenation of the
Daniel Normand5d70ea2019-06-05 15:13:43 -0700472 # framework and vendor partition lists.
Daniel Normana61cde02019-05-03 14:19:13 -0700473 key = '%s%s%s' % (list_prefix, partition_group, list_suffix)
474 merged_dict[key] = (
Daniel Normand5d70ea2019-06-05 15:13:43 -0700475 '%s %s' %
476 (framework_dict.get(key, ''), vendor_dict.get(key, ''))).strip()
Daniel Normana61cde02019-05-03 14:19:13 -0700477 return merged_dict
478
479
Daniel Normand5d70ea2019-06-05 15:13:43 -0700480def process_misc_info_txt(framework_target_files_temp_dir,
481 vendor_target_files_temp_dir,
482 output_target_files_temp_dir,
483 framework_misc_info_keys):
Tao Bao2ad4b822019-06-27 16:52:12 -0700484 """Performs special processing for META/misc_info.txt.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800485
486 This function merges the contents of the META/misc_info.txt files from the
Daniel Normand5d70ea2019-06-05 15:13:43 -0700487 framework directory and the vendor directory, placing the merged result in the
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800488 output directory. The precondition in that the files are already extracted.
489 The post condition is that the output META/misc_info.txt contains the merged
490 content.
491
492 Args:
Daniel Normand5d70ea2019-06-05 15:13:43 -0700493 framework_target_files_temp_dir: The name of a directory containing the
494 special items extracted from the framework target files package.
495 vendor_target_files_temp_dir: The name of a directory containing the special
496 items extracted from the vendor target files package.
Daniel Normane5b134a2019-04-17 14:54:06 -0700497 output_target_files_temp_dir: The name of a directory that will be used to
498 create the output target files package after all the special cases are
499 processed.
Daniel Normand5d70ea2019-06-05 15:13:43 -0700500 framework_misc_info_keys: A list of keys to obtain from the framework
501 instance of META/misc_info.txt. The remaining keys from the vendor
502 instance.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800503 """
504
Kiyoung Kimebe7c9c2019-06-25 17:09:55 +0900505 misc_info_path = ['META', 'misc_info.txt']
506 framework_dict = common.LoadDictionaryFromFile(
507 os.path.join(framework_target_files_temp_dir, *misc_info_path))
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800508
Daniel Normand5d70ea2019-06-05 15:13:43 -0700509 # We take most of the misc info from the vendor target files.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800510
Kiyoung Kimebe7c9c2019-06-25 17:09:55 +0900511 merged_dict = common.LoadDictionaryFromFile(
512 os.path.join(vendor_target_files_temp_dir, *misc_info_path))
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800513
Daniel Normand5d70ea2019-06-05 15:13:43 -0700514 # Replace certain values in merged_dict with values from
515 # framework_dict.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800516
Daniel Normand5d70ea2019-06-05 15:13:43 -0700517 for key in framework_misc_info_keys:
518 merged_dict[key] = framework_dict[key]
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800519
Daniel Norman19b9fe92019-03-19 14:48:02 -0700520 # Merge misc info keys used for Dynamic Partitions.
Daniel Normand5d70ea2019-06-05 15:13:43 -0700521 if (merged_dict.get('use_dynamic_partitions') == 'true') and (
522 framework_dict.get('use_dynamic_partitions') == 'true'):
Daniel Normana61cde02019-05-03 14:19:13 -0700523 merged_dynamic_partitions_dict = merge_dynamic_partition_info_dicts(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700524 framework_dict=framework_dict,
525 vendor_dict=merged_dict,
Daniel Normana61cde02019-05-03 14:19:13 -0700526 size_prefix='super_',
527 size_suffix='_group_size',
528 list_prefix='super_',
529 list_suffix='_partition_list')
Daniel Normand5d70ea2019-06-05 15:13:43 -0700530 merged_dict.update(merged_dynamic_partitions_dict)
Tao Bao48a2feb2019-06-28 11:00:05 -0700531 # Ensure that add_img_to_target_files rebuilds super split images for
532 # devices that retrofit dynamic partitions. This flag may have been set to
533 # false in the partial builds to prevent duplicate building of super.img.
Daniel Norman0bf940c2019-06-10 12:50:19 -0700534 merged_dict['build_super_partition'] = 'true'
Daniel Norman19b9fe92019-03-19 14:48:02 -0700535
Daniel Normand5d70ea2019-06-05 15:13:43 -0700536 # Replace <image>_selinux_fc values with framework or vendor file_contexts.bin
Daniel Norman72c626f2019-05-13 15:58:14 -0700537 # depending on which dictionary the key came from.
538 # Only the file basename is required because all selinux_fc properties are
539 # replaced with the full path to the file under META/ when misc_info.txt is
540 # loaded from target files for repacking. See common.py LoadInfoDict().
Daniel Normand5d70ea2019-06-05 15:13:43 -0700541 for key in merged_dict:
Daniel Norman72c626f2019-05-13 15:58:14 -0700542 if key.endswith('_selinux_fc'):
Daniel Normand5d70ea2019-06-05 15:13:43 -0700543 merged_dict[key] = 'vendor_file_contexts.bin'
544 for key in framework_dict:
Daniel Norman72c626f2019-05-13 15:58:14 -0700545 if key.endswith('_selinux_fc'):
Daniel Normand5d70ea2019-06-05 15:13:43 -0700546 merged_dict[key] = 'framework_file_contexts.bin'
Daniel Norman72c626f2019-05-13 15:58:14 -0700547
Daniel Normane5b134a2019-04-17 14:54:06 -0700548 output_misc_info_txt = os.path.join(output_target_files_temp_dir, 'META',
549 'misc_info.txt')
Daniel Normand5d70ea2019-06-05 15:13:43 -0700550 write_sorted_data(data=merged_dict, path=output_misc_info_txt)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800551
552
Daniel Normand5d70ea2019-06-05 15:13:43 -0700553def process_dynamic_partitions_info_txt(framework_target_files_dir,
554 vendor_target_files_dir,
Daniel Normana61cde02019-05-03 14:19:13 -0700555 output_target_files_dir):
Tao Bao2ad4b822019-06-27 16:52:12 -0700556 """Performs special processing for META/dynamic_partitions_info.txt.
Daniel Normana61cde02019-05-03 14:19:13 -0700557
558 This function merges the contents of the META/dynamic_partitions_info.txt
Daniel Normand5d70ea2019-06-05 15:13:43 -0700559 files from the framework directory and the vendor directory, placing the
560 merged result in the output directory.
Daniel Normana61cde02019-05-03 14:19:13 -0700561
Daniel Normand5d70ea2019-06-05 15:13:43 -0700562 This function does nothing if META/dynamic_partitions_info.txt from the vendor
Daniel Normana61cde02019-05-03 14:19:13 -0700563 directory does not exist.
564
565 Args:
Daniel Normand5d70ea2019-06-05 15:13:43 -0700566 framework_target_files_dir: The name of a directory containing the special
567 items extracted from the framework target files package.
568 vendor_target_files_dir: The name of a directory containing the special
569 items extracted from the vendor target files package.
Daniel Normana61cde02019-05-03 14:19:13 -0700570 output_target_files_dir: The name of a directory that will be used to create
571 the output target files package after all the special cases are processed.
572 """
573
574 if not os.path.exists(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700575 os.path.join(vendor_target_files_dir, 'META',
Daniel Normana61cde02019-05-03 14:19:13 -0700576 'dynamic_partitions_info.txt')):
577 return
578
Kiyoung Kimebe7c9c2019-06-25 17:09:55 +0900579 dynamic_partitions_info_path = ['META', 'dynamic_partitions_info.txt']
Daniel Normana61cde02019-05-03 14:19:13 -0700580
Kiyoung Kimebe7c9c2019-06-25 17:09:55 +0900581 framework_dynamic_partitions_dict = common.LoadDictionaryFromFile(
582 os.path.join(framework_target_files_dir, *dynamic_partitions_info_path))
583 vendor_dynamic_partitions_dict = common.LoadDictionaryFromFile(
584 os.path.join(vendor_target_files_dir, *dynamic_partitions_info_path))
Daniel Normana61cde02019-05-03 14:19:13 -0700585
586 merged_dynamic_partitions_dict = merge_dynamic_partition_info_dicts(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700587 framework_dict=framework_dynamic_partitions_dict,
588 vendor_dict=vendor_dynamic_partitions_dict,
Daniel Normana61cde02019-05-03 14:19:13 -0700589 # META/dynamic_partitions_info.txt does not use dynamic_partition_list.
590 include_dynamic_partition_list=False,
591 size_suffix='_size',
592 list_suffix='_partition_list')
593
594 output_dynamic_partitions_info_txt = os.path.join(
595 output_target_files_dir, 'META', 'dynamic_partitions_info.txt')
Chris Grossfabf50a2019-05-02 12:42:09 -0700596 write_sorted_data(
597 data=merged_dynamic_partitions_dict,
598 path=output_dynamic_partitions_info_txt)
599
600
Daniel Normand5d70ea2019-06-05 15:13:43 -0700601def process_apex_keys_apk_certs_common(framework_target_files_dir,
602 vendor_target_files_dir,
Chris Grossfabf50a2019-05-02 12:42:09 -0700603 output_target_files_dir, file_name):
Tao Bao2ad4b822019-06-27 16:52:12 -0700604 """Performs special processing for META/apexkeys.txt or META/apkcerts.txt.
Chris Grossfabf50a2019-05-02 12:42:09 -0700605
606 This function merges the contents of the META/apexkeys.txt or
Tao Bao2ad4b822019-06-27 16:52:12 -0700607 META/apkcerts.txt files from the framework directory and the vendor directory,
608 placing the merged result in the output directory. The precondition in that
609 the files are already extracted. The post condition is that the output
610 META/apexkeys.txt or META/apkcerts.txt contains the merged content.
Chris Grossfabf50a2019-05-02 12:42:09 -0700611
612 Args:
Daniel Normand5d70ea2019-06-05 15:13:43 -0700613 framework_target_files_dir: The name of a directory containing the special
614 items extracted from the framework target files package.
615 vendor_target_files_dir: The name of a directory containing the special
616 items extracted from the vendor target files package.
Chris Grossfabf50a2019-05-02 12:42:09 -0700617 output_target_files_dir: The name of a directory that will be used to create
618 the output target files package after all the special cases are processed.
619 file_name: The name of the file to merge. One of apkcerts.txt or
620 apexkeys.txt.
621 """
622
623 def read_helper(d):
624 temp = {}
625 file_path = os.path.join(d, 'META', file_name)
626 with open(file_path) as f:
627 for line in f:
628 if line.strip():
629 temp[line.split()[0]] = line.strip()
630 return temp
631
Daniel Normand5d70ea2019-06-05 15:13:43 -0700632 framework_dict = read_helper(framework_target_files_dir)
633 vendor_dict = read_helper(vendor_target_files_dir)
Chris Grossfabf50a2019-05-02 12:42:09 -0700634
Daniel Normand5d70ea2019-06-05 15:13:43 -0700635 for key in framework_dict:
636 if key in vendor_dict and vendor_dict[key] != framework_dict[key]:
Chris Grossfabf50a2019-05-02 12:42:09 -0700637 raise ValueError('Conflicting entries found in %s:\n %s and\n %s' %
Daniel Normand5d70ea2019-06-05 15:13:43 -0700638 (file_name, framework_dict[key], vendor_dict[key]))
639 vendor_dict[key] = framework_dict[key]
Chris Grossfabf50a2019-05-02 12:42:09 -0700640
641 output_file = os.path.join(output_target_files_dir, 'META', file_name)
642
Daniel Normand5d70ea2019-06-05 15:13:43 -0700643 write_sorted_data(data=vendor_dict.values(), path=output_file)
Daniel Normana61cde02019-05-03 14:19:13 -0700644
645
Daniel Normand5d70ea2019-06-05 15:13:43 -0700646def copy_file_contexts(framework_target_files_dir, vendor_target_files_dir,
Daniel Norman72c626f2019-05-13 15:58:14 -0700647 output_target_files_dir):
648 """Creates named copies of each build's file_contexts.bin in output META/."""
Daniel Normand5d70ea2019-06-05 15:13:43 -0700649 framework_fc_path = os.path.join(framework_target_files_dir, 'META',
650 'framework_file_contexts.bin')
651 if not os.path.exists(framework_fc_path):
652 framework_fc_path = os.path.join(framework_target_files_dir, 'META',
653 'file_contexts.bin')
654 if not os.path.exists(framework_fc_path):
655 raise ValueError('Missing framework file_contexts.bin.')
656 shutil.copyfile(
657 framework_fc_path,
658 os.path.join(output_target_files_dir, 'META',
659 'framework_file_contexts.bin'))
660
661 vendor_fc_path = os.path.join(vendor_target_files_dir, 'META',
662 'vendor_file_contexts.bin')
663 if not os.path.exists(vendor_fc_path):
664 vendor_fc_path = os.path.join(vendor_target_files_dir, 'META',
Daniel Normanedf12472019-05-22 10:47:08 -0700665 'file_contexts.bin')
Daniel Normand5d70ea2019-06-05 15:13:43 -0700666 if not os.path.exists(vendor_fc_path):
667 raise ValueError('Missing vendor file_contexts.bin.')
Daniel Norman72c626f2019-05-13 15:58:14 -0700668 shutil.copyfile(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700669 vendor_fc_path,
670 os.path.join(output_target_files_dir, 'META', 'vendor_file_contexts.bin'))
Daniel Norman72c626f2019-05-13 15:58:14 -0700671
672
Daniel Normand5d70ea2019-06-05 15:13:43 -0700673def process_special_cases(framework_target_files_temp_dir,
674 vendor_target_files_temp_dir,
675 output_target_files_temp_dir,
676 framework_misc_info_keys, rebuild_recovery):
Tao Bao2ad4b822019-06-27 16:52:12 -0700677 """Performs special-case processing for certain target files items.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800678
679 Certain files in the output target files package require special-case
680 processing. This function performs all that special-case processing.
681
682 Args:
Daniel Normand5d70ea2019-06-05 15:13:43 -0700683 framework_target_files_temp_dir: The name of a directory containing the
684 special items extracted from the framework target files package.
685 vendor_target_files_temp_dir: The name of a directory containing the special
686 items extracted from the vendor target files package.
Daniel Normane5b134a2019-04-17 14:54:06 -0700687 output_target_files_temp_dir: The name of a directory that will be used to
688 create the output target files package after all the special cases are
689 processed.
Daniel Normand5d70ea2019-06-05 15:13:43 -0700690 framework_misc_info_keys: A list of keys to obtain from the framework
691 instance of META/misc_info.txt. The remaining keys from the vendor
692 instance.
Bill Peckham364c1cc2019-03-29 18:27:23 -0700693 rebuild_recovery: If true, rebuild the recovery patch used by non-A/B
Daniel Normane5b134a2019-04-17 14:54:06 -0700694 devices and write it to the system image.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800695 """
696
Daniel Normand5d70ea2019-06-05 15:13:43 -0700697 if 'ab_update' in framework_misc_info_keys:
Bill Peckham364c1cc2019-03-29 18:27:23 -0700698 process_ab_partitions_txt(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700699 framework_target_files_temp_dir=framework_target_files_temp_dir,
700 vendor_target_files_temp_dir=vendor_target_files_temp_dir,
Bill Peckham364c1cc2019-03-29 18:27:23 -0700701 output_target_files_temp_dir=output_target_files_temp_dir)
702
703 if rebuild_recovery:
704 append_recovery_to_filesystem_config(
705 output_target_files_temp_dir=output_target_files_temp_dir)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800706
Daniel Norman72c626f2019-05-13 15:58:14 -0700707 copy_file_contexts(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700708 framework_target_files_dir=framework_target_files_temp_dir,
709 vendor_target_files_dir=vendor_target_files_temp_dir,
Daniel Norman72c626f2019-05-13 15:58:14 -0700710 output_target_files_dir=output_target_files_temp_dir)
711
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800712 process_misc_info_txt(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700713 framework_target_files_temp_dir=framework_target_files_temp_dir,
714 vendor_target_files_temp_dir=vendor_target_files_temp_dir,
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800715 output_target_files_temp_dir=output_target_files_temp_dir,
Daniel Normand5d70ea2019-06-05 15:13:43 -0700716 framework_misc_info_keys=framework_misc_info_keys)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800717
Daniel Normana61cde02019-05-03 14:19:13 -0700718 process_dynamic_partitions_info_txt(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700719 framework_target_files_dir=framework_target_files_temp_dir,
720 vendor_target_files_dir=vendor_target_files_temp_dir,
Daniel Norman714bd122019-05-08 16:20:02 -0700721 output_target_files_dir=output_target_files_temp_dir)
Daniel Normana61cde02019-05-03 14:19:13 -0700722
Chris Grossfabf50a2019-05-02 12:42:09 -0700723 process_apex_keys_apk_certs_common(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700724 framework_target_files_dir=framework_target_files_temp_dir,
725 vendor_target_files_dir=vendor_target_files_temp_dir,
Chris Grossfabf50a2019-05-02 12:42:09 -0700726 output_target_files_dir=output_target_files_temp_dir,
727 file_name='apkcerts.txt')
728
729 process_apex_keys_apk_certs_common(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700730 framework_target_files_dir=framework_target_files_temp_dir,
731 vendor_target_files_dir=vendor_target_files_temp_dir,
Chris Grossfabf50a2019-05-02 12:42:09 -0700732 output_target_files_dir=output_target_files_temp_dir,
733 file_name='apexkeys.txt')
734
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800735
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900736def files_from_path(target_path, extra_args=None):
Tao Bao2ad4b822019-06-27 16:52:12 -0700737 """Gets files under given path.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800738
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900739 Get (sub)files from given target path and return sorted list.
740
741 Args:
742 target_path: Target path to get subfiles.
743 extra_args: List of extra argument for find command. Optional.
744
745 Returns:
746 Sorted files and directories list.
747 """
748
749 find_command = ['find', target_path] + (extra_args or [])
750 find_process = common.Run(find_command, stdout=subprocess.PIPE, verbose=False)
751 return common.RunAndCheckOutput(['sort'], stdin=find_process.stdout,
752 verbose=False)
753
754
755def create_merged_package(temp_dir, framework_target_files, framework_item_list,
756 vendor_target_files, vendor_item_list,
757 framework_misc_info_keys,
758 rebuild_recovery):
Tao Bao2ad4b822019-06-27 16:52:12 -0700759 """Merges two target files packages into one target files structure.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800760
761 Args:
762 temp_dir: The name of a directory we use when we extract items from the
Daniel Normane5b134a2019-04-17 14:54:06 -0700763 input target files packages, and also a scratch directory that we use for
764 temporary files.
Daniel Normand5d70ea2019-06-05 15:13:43 -0700765 framework_target_files: The name of the zip archive containing the framework
Daniel Normane5b134a2019-04-17 14:54:06 -0700766 partial target files package.
Daniel Normand5d70ea2019-06-05 15:13:43 -0700767 framework_item_list: The list of items to extract from the partial framework
Daniel Normane5b134a2019-04-17 14:54:06 -0700768 target files package as is, meaning these items will land in the output
Daniel Normand5d70ea2019-06-05 15:13:43 -0700769 target files package exactly as they appear in the input partial framework
Daniel Normane5b134a2019-04-17 14:54:06 -0700770 target files package.
Daniel Normand5d70ea2019-06-05 15:13:43 -0700771 vendor_target_files: The name of the zip archive containing the vendor
772 partial target files package.
773 vendor_item_list: The list of items to extract from the partial vendor
774 target files package as is, meaning these items will land in the output
775 target files package exactly as they appear in the input partial vendor
Daniel Normane5b134a2019-04-17 14:54:06 -0700776 target files package.
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900777 framework_misc_info_keys: The list of keys to obtain from the framework
778 instance of META/misc_info.txt. The remaining keys from the vendor
779 instance.
Daniel Normana4911da2019-03-15 14:36:21 -0700780 rebuild_recovery: If true, rebuild the recovery patch used by non-A/B
Daniel Normane5b134a2019-04-17 14:54:06 -0700781 devices and write it to the system image.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800782
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900783 Returns:
784 Path to merged package under temp directory.
785 """
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800786
Daniel Normand5d70ea2019-06-05 15:13:43 -0700787 # Create directory names that we'll use when we extract files from framework,
788 # and vendor, and for zipping the final output.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800789
Daniel Normand5d70ea2019-06-05 15:13:43 -0700790 framework_target_files_temp_dir = os.path.join(temp_dir, 'framework')
791 vendor_target_files_temp_dir = os.path.join(temp_dir, 'vendor')
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800792 output_target_files_temp_dir = os.path.join(temp_dir, 'output')
793
Daniel Normand5d70ea2019-06-05 15:13:43 -0700794 # Extract "as is" items from the input framework partial target files package.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800795 # We extract them directly into the output temporary directory since the
796 # items do not need special case processing.
797
Bill Peckham889b0c62019-02-21 18:53:37 -0800798 extract_items(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700799 target_files=framework_target_files,
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800800 target_files_temp_dir=output_target_files_temp_dir,
Daniel Normand5d70ea2019-06-05 15:13:43 -0700801 extract_item_list=framework_item_list)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800802
Daniel Normand5d70ea2019-06-05 15:13:43 -0700803 # Extract "as is" items from the input vendor partial target files package. We
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800804 # extract them directly into the output temporary directory since the items
805 # do not need special case processing.
806
Bill Peckham889b0c62019-02-21 18:53:37 -0800807 extract_items(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700808 target_files=vendor_target_files,
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800809 target_files_temp_dir=output_target_files_temp_dir,
Daniel Normand5d70ea2019-06-05 15:13:43 -0700810 extract_item_list=vendor_item_list)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800811
Daniel Normand5d70ea2019-06-05 15:13:43 -0700812 # Extract "special" items from the input framework partial target files
813 # package. We extract these items to different directory since they require
814 # special processing before they will end up in the output directory.
815
816 extract_items(
817 target_files=framework_target_files,
818 target_files_temp_dir=framework_target_files_temp_dir,
819 extract_item_list=FRAMEWORK_EXTRACT_SPECIAL_ITEM_LIST)
820
821 # Extract "special" items from the input vendor partial target files package.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800822 # We extract these items to different directory since they require special
823 # processing before they will end up in the output directory.
824
Bill Peckham889b0c62019-02-21 18:53:37 -0800825 extract_items(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700826 target_files=vendor_target_files,
827 target_files_temp_dir=vendor_target_files_temp_dir,
828 extract_item_list=VENDOR_EXTRACT_SPECIAL_ITEM_LIST)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800829
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800830 # Now that the temporary directories contain all the extracted files, perform
831 # special case processing on any items that need it. After this function
832 # completes successfully, all the files we need to create the output target
833 # files package are in place.
834
Bill Peckham889b0c62019-02-21 18:53:37 -0800835 process_special_cases(
Daniel Normand5d70ea2019-06-05 15:13:43 -0700836 framework_target_files_temp_dir=framework_target_files_temp_dir,
837 vendor_target_files_temp_dir=vendor_target_files_temp_dir,
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800838 output_target_files_temp_dir=output_target_files_temp_dir,
Daniel Normand5d70ea2019-06-05 15:13:43 -0700839 framework_misc_info_keys=framework_misc_info_keys,
Bill Peckham364c1cc2019-03-29 18:27:23 -0700840 rebuild_recovery=rebuild_recovery)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800841
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900842 return output_target_files_temp_dir
843
844
845def generate_images(target_files_dir, rebuild_recovery):
846 """Generate images from target files.
847
848 This function takes merged output temporary directory and create images
849 from it.
850
851 Args:
852 target_files_dir: Path to merged temp directory.
853 rebuild_recovery: If true, rebuild the recovery patch used by non-A/B
854 devices and write it to the system image.
855 """
856
857 # Regenerate IMAGES in the target directory.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800858
Daniel Normana4911da2019-03-15 14:36:21 -0700859 add_img_args = ['--verbose']
860 if rebuild_recovery:
861 add_img_args.append('--rebuild_recovery')
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900862 add_img_args.append(target_files_dir)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800863
864 add_img_to_target_files.main(add_img_args)
865
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900866
867def generate_super_empty_image(target_dir, output_super_empty):
Tao Bao2ad4b822019-06-27 16:52:12 -0700868 """Generates super_empty image from target package.
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900869
870 Args:
871 target_dir: Path to the target file package which contains misc_info.txt for
872 detailed information for super image.
873 output_super_empty: If provided, copies a super_empty.img file from the
874 target files package to this path.
875 """
Daniel Norman1bd2a1d2019-04-18 12:32:18 -0700876 # Create super_empty.img using the merged misc_info.txt.
877
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900878 misc_info_txt = os.path.join(target_dir, 'META',
Daniel Norman1bd2a1d2019-04-18 12:32:18 -0700879 'misc_info.txt')
880
Kiyoung Kimebe7c9c2019-06-25 17:09:55 +0900881 use_dynamic_partitions = common.LoadDictionaryFromFile(misc_info_txt).get(
882 'use_dynamic_partitions')
Daniel Norman1bd2a1d2019-04-18 12:32:18 -0700883
884 if use_dynamic_partitions != 'true' and output_super_empty:
885 raise ValueError(
886 'Building super_empty.img requires use_dynamic_partitions=true.')
887 elif use_dynamic_partitions == 'true':
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900888 super_empty_img = os.path.join(target_dir, 'IMAGES',
Daniel Norman1bd2a1d2019-04-18 12:32:18 -0700889 'super_empty.img')
890 build_super_image_args = [
891 misc_info_txt,
892 super_empty_img,
893 ]
894 build_super_image.main(build_super_image_args)
895
896 # Copy super_empty.img to the user-provided output_super_empty location.
897 if output_super_empty:
898 shutil.copyfile(super_empty_img, output_super_empty)
899
Daniel Normanb8a2f9d2019-04-24 12:55:51 -0700900
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900901def create_img_archive(source_path, target_path):
Tao Bao2ad4b822019-06-27 16:52:12 -0700902 """Creates IMG archive in target path from source package.
Daniel Normanb8a2f9d2019-04-24 12:55:51 -0700903
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900904 Args:
905 source_path: Path of the source package to be packed.
906 target_path: Create IMG package from the source package.
907 """
Daniel Normanfdb38812019-04-15 09:47:24 -0700908
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900909 img_from_target_files_args = [
910 source_path,
911 target_path,
912 ]
913 img_from_target_files.main(img_from_target_files_args)
Daniel Normanfdb38812019-04-15 09:47:24 -0700914
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800915
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900916def create_target_files_archive(output_file, source_dir, temp_dir):
Tao Bao2ad4b822019-06-27 16:52:12 -0700917 """Creates archive from target package.
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900918
919 Args:
920 output_file: The name of the zip archive target files package.
921 source_dir: The target directory contains package to be archived.
922 temp_dir: Path to temporary directory for any intermediate files.
923 """
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800924 output_target_files_list = os.path.join(temp_dir, 'output.list')
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900925 output_zip = os.path.abspath(output_file)
926 output_target_files_meta_dir = os.path.join(source_dir,
Daniel Normane5b134a2019-04-17 14:54:06 -0700927 'META')
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800928
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900929 meta_content = files_from_path(output_target_files_meta_dir)
930 other_content = files_from_path(source_dir,
931 ['-path', output_target_files_meta_dir,
932 '-prune', '-o', '-print'])
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800933
Tao Bao2ad4b822019-06-27 16:52:12 -0700934 with open(output_target_files_list, 'w') as f:
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800935 f.write(meta_content)
936 f.write(other_content)
937
938 command = [
Bill Peckhamf753e152019-02-19 18:02:46 -0800939 'soong_zip',
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800940 '-d',
Daniel Normane5b134a2019-04-17 14:54:06 -0700941 '-o',
942 output_zip,
943 '-C',
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900944 source_dir,
Daniel Normane5b134a2019-04-17 14:54:06 -0700945 '-l',
946 output_target_files_list,
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800947 ]
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900948
949 logger.info('creating %s', output_file)
Bill Peckham889b0c62019-02-21 18:53:37 -0800950 common.RunAndWait(command, verbose=True)
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900951 logger.info('finished creating %s', output_file)
952
953 return output_zip
954
955
956def create_ota_package(zip_package, output_ota):
Tao Bao2ad4b822019-06-27 16:52:12 -0700957 """Creates OTA package from archived package.
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900958
959 Args:
960 zip_package: The name of the zip archived package.
961 output_ota: The name of the output zip archive ota package.
962 """
963 ota_from_target_files_args = [
964 zip_package,
965 output_ota,
966 ]
967 ota_from_target_files.main(ota_from_target_files_args)
968
969
970def merge_target_files(temp_dir, framework_target_files, framework_item_list,
971 framework_misc_info_keys, vendor_target_files,
972 vendor_item_list, output_target_files, output_dir,
973 output_item_list, output_ota, output_img,
974 output_super_empty, rebuild_recovery):
Tao Bao2ad4b822019-06-27 16:52:12 -0700975 """Merges two target files packages together.
Kiyoung Kim7cbeda72019-06-28 13:26:04 +0900976
977 This function takes framework and vendor target files packages as input,
978 performs various file extractions, special case processing, and finally
979 creates a merged zip archive as output.
980
981 Args:
982 temp_dir: The name of a directory we use when we extract items from the
983 input target files packages, and also a scratch directory that we use for
984 temporary files.
985 framework_target_files: The name of the zip archive containing the framework
986 partial target files package.
987 framework_item_list: The list of items to extract from the partial framework
988 target files package as is, meaning these items will land in the output
989 target files package exactly as they appear in the input partial framework
990 target files package.
991 framework_misc_info_keys: The list of keys to obtain from the framework
992 instance of META/misc_info.txt. The remaining keys from the vendor
993 instance.
994 vendor_target_files: The name of the zip archive containing the vendor
995 partial target files package.
996 vendor_item_list: The list of items to extract from the partial vendor
997 target files package as is, meaning these items will land in the output
998 target files package exactly as they appear in the input partial vendor
999 target files package.
1000 output_target_files: The name of the output zip archive target files package
1001 created by merging framework and vendor.
1002 output_dir: The destination directory for saving merged files.
1003 output_item_list: The list of items to copy into the output_dir.
1004 output_ota: The name of the output zip archive ota package.
1005 output_img: The name of the output zip archive img package.
1006 output_super_empty: If provided, creates a super_empty.img file from the
1007 merged target files package and saves it at this path.
1008 rebuild_recovery: If true, rebuild the recovery patch used by non-A/B
1009 devices and write it to the system image.
1010 """
1011
1012 logger.info('starting: merge framework %s and vendor %s into output %s',
1013 framework_target_files, vendor_target_files, output_target_files)
1014
1015 output_target_files_temp_dir = create_merged_package(
1016 temp_dir, framework_target_files, framework_item_list,
1017 vendor_target_files, vendor_item_list, framework_misc_info_keys,
1018 rebuild_recovery)
1019
1020 generate_images(output_target_files_temp_dir, rebuild_recovery)
1021
1022 generate_super_empty_image(output_target_files_temp_dir, output_super_empty)
1023
1024 if output_img:
1025 # Create the IMG package from the merged target files (before zipping, in
1026 # order to avoid an unnecessary unzip and copy).
1027 create_img_archive(output_target_files_temp_dir, output_img)
1028
1029 # Finally, create the output target files zip archive and/or copy the
1030 # output items to the output target files directory.
1031
1032 if output_dir:
1033 copy_items(output_target_files_temp_dir, output_dir, output_item_list)
1034
1035 if not output_target_files:
1036 return
1037
1038 output_zip = create_target_files_archive(output_target_files,
1039 output_target_files_temp_dir,
1040 temp_dir)
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001041
Daniel Norman3b64ce12019-04-16 16:11:35 -07001042 # Create the OTA package from the merged target files package.
1043
1044 if output_ota:
Kiyoung Kim7cbeda72019-06-28 13:26:04 +09001045 create_ota_package(output_zip, output_ota)
Daniel Norman3b64ce12019-04-16 16:11:35 -07001046
Daniel Norman1bd2a1d2019-04-18 12:32:18 -07001047
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001048def call_func_with_temp_dir(func, keep_tmp):
Tao Bao2ad4b822019-06-27 16:52:12 -07001049 """Manages the creation and cleanup of the temporary directory.
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001050
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001051 This function calls the given function after first creating a temporary
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001052 directory. It also cleans up the temporary directory.
1053
1054 Args:
Daniel Normane5b134a2019-04-17 14:54:06 -07001055 func: The function to call. Should accept one parameter, the path to the
1056 temporary directory.
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001057 keep_tmp: Keep the temporary directory after processing is complete.
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001058 """
1059
1060 # Create a temporary directory. This will serve as the parent of directories
1061 # we use when we extract items from the input target files packages, and also
1062 # a scratch directory that we use for temporary files.
1063
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001064 temp_dir = common.MakeTempDir(prefix='merge_target_files_')
1065
1066 try:
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001067 func(temp_dir)
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001068 finally:
1069 if keep_tmp:
1070 logger.info('keeping %s', temp_dir)
1071 else:
1072 common.Cleanup()
1073
1074
1075def main():
1076 """The main function.
1077
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001078 Process command line arguments, then call merge_target_files to
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001079 perform the heavy lifting.
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001080 """
1081
1082 common.InitLogging()
1083
Bill Peckhamf753e152019-02-19 18:02:46 -08001084 def option_handler(o, a):
1085 if o == '--system-target-files':
Daniel Normand5d70ea2019-06-05 15:13:43 -07001086 logger.warning(
1087 '--system-target-files has been renamed to --framework-target-files')
1088 OPTIONS.framework_target_files = a
1089 elif o == '--framework-target-files':
1090 OPTIONS.framework_target_files = a
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001091 elif o == '--system-item-list':
Daniel Normand5d70ea2019-06-05 15:13:43 -07001092 logger.warning(
1093 '--system-item-list has been renamed to --framework-item-list')
1094 OPTIONS.framework_item_list = a
1095 elif o == '--framework-item-list':
1096 OPTIONS.framework_item_list = a
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001097 elif o == '--system-misc-info-keys':
Daniel Normand5d70ea2019-06-05 15:13:43 -07001098 logger.warning(
Kiyoung Kimebe7c9c2019-06-25 17:09:55 +09001099 '--system-misc-info-keys has been renamed to '
1100 '--framework-misc-info-keys'
Daniel Normand5d70ea2019-06-05 15:13:43 -07001101 )
1102 OPTIONS.framework_misc_info_keys = a
1103 elif o == '--framework-misc-info-keys':
1104 OPTIONS.framework_misc_info_keys = a
Bill Peckhamf753e152019-02-19 18:02:46 -08001105 elif o == '--other-target-files':
Daniel Normand5d70ea2019-06-05 15:13:43 -07001106 logger.warning(
1107 '--other-target-files has been renamed to --vendor-target-files')
1108 OPTIONS.vendor_target_files = a
1109 elif o == '--vendor-target-files':
1110 OPTIONS.vendor_target_files = a
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001111 elif o == '--other-item-list':
Daniel Normand5d70ea2019-06-05 15:13:43 -07001112 logger.warning('--other-item-list has been renamed to --vendor-item-list')
1113 OPTIONS.vendor_item_list = a
1114 elif o == '--vendor-item-list':
1115 OPTIONS.vendor_item_list = a
Bill Peckhamf753e152019-02-19 18:02:46 -08001116 elif o == '--output-target-files':
1117 OPTIONS.output_target_files = a
Daniel Normanfdb38812019-04-15 09:47:24 -07001118 elif o == '--output-dir':
1119 OPTIONS.output_dir = a
1120 elif o == '--output-item-list':
1121 OPTIONS.output_item_list = a
Daniel Norman3b64ce12019-04-16 16:11:35 -07001122 elif o == '--output-ota':
1123 OPTIONS.output_ota = a
Daniel Norman1bd2a1d2019-04-18 12:32:18 -07001124 elif o == '--output-img':
1125 OPTIONS.output_img = a
Daniel Normanf0318252019-04-15 11:34:56 -07001126 elif o == '--output-super-empty':
1127 OPTIONS.output_super_empty = a
Daniel Normana4911da2019-03-15 14:36:21 -07001128 elif o == '--rebuild_recovery':
1129 OPTIONS.rebuild_recovery = True
Bill Peckham364c1cc2019-03-29 18:27:23 -07001130 elif o == '--keep-tmp':
Bill Peckhamf753e152019-02-19 18:02:46 -08001131 OPTIONS.keep_tmp = True
1132 else:
1133 return False
1134 return True
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001135
Bill Peckhamf753e152019-02-19 18:02:46 -08001136 args = common.ParseOptions(
Daniel Normane5b134a2019-04-17 14:54:06 -07001137 sys.argv[1:],
1138 __doc__,
Bill Peckhamf753e152019-02-19 18:02:46 -08001139 extra_long_opts=[
1140 'system-target-files=',
Daniel Normand5d70ea2019-06-05 15:13:43 -07001141 'framework-target-files=',
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001142 'system-item-list=',
Daniel Normand5d70ea2019-06-05 15:13:43 -07001143 'framework-item-list=',
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001144 'system-misc-info-keys=',
Daniel Normand5d70ea2019-06-05 15:13:43 -07001145 'framework-misc-info-keys=',
Bill Peckhamf753e152019-02-19 18:02:46 -08001146 'other-target-files=',
Daniel Normand5d70ea2019-06-05 15:13:43 -07001147 'vendor-target-files=',
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001148 'other-item-list=',
Daniel Normand5d70ea2019-06-05 15:13:43 -07001149 'vendor-item-list=',
Bill Peckhamf753e152019-02-19 18:02:46 -08001150 'output-target-files=',
Daniel Normanfdb38812019-04-15 09:47:24 -07001151 'output-dir=',
1152 'output-item-list=',
Daniel Norman3b64ce12019-04-16 16:11:35 -07001153 'output-ota=',
Daniel Norman1bd2a1d2019-04-18 12:32:18 -07001154 'output-img=',
Daniel Normanf0318252019-04-15 11:34:56 -07001155 'output-super-empty=',
Daniel Normana4911da2019-03-15 14:36:21 -07001156 'rebuild_recovery',
Bill Peckham364c1cc2019-03-29 18:27:23 -07001157 'keep-tmp',
Bill Peckhamf753e152019-02-19 18:02:46 -08001158 ],
1159 extra_option_handler=option_handler)
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001160
Tao Bao2ad4b822019-06-27 16:52:12 -07001161 # pylint: disable=too-many-boolean-expressions
Daniel Normand5d70ea2019-06-05 15:13:43 -07001162 if (args or OPTIONS.framework_target_files is None or
1163 OPTIONS.vendor_target_files is None or
Daniel Normane5b134a2019-04-17 14:54:06 -07001164 (OPTIONS.output_target_files is None and OPTIONS.output_dir is None) or
1165 (OPTIONS.output_dir is not None and OPTIONS.output_item_list is None)):
Bill Peckhamf753e152019-02-19 18:02:46 -08001166 common.Usage(__doc__)
Bill Peckham889b0c62019-02-21 18:53:37 -08001167 sys.exit(1)
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001168
Daniel Normand5d70ea2019-06-05 15:13:43 -07001169 if OPTIONS.framework_item_list:
1170 framework_item_list = read_config_list(OPTIONS.framework_item_list)
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001171 else:
Daniel Normand5d70ea2019-06-05 15:13:43 -07001172 framework_item_list = DEFAULT_FRAMEWORK_ITEM_LIST
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001173
Daniel Normand5d70ea2019-06-05 15:13:43 -07001174 if OPTIONS.framework_misc_info_keys:
1175 framework_misc_info_keys = read_config_list(
1176 OPTIONS.framework_misc_info_keys)
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001177 else:
Daniel Normand5d70ea2019-06-05 15:13:43 -07001178 framework_misc_info_keys = DEFAULT_FRAMEWORK_MISC_INFO_KEYS
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001179
Daniel Normand5d70ea2019-06-05 15:13:43 -07001180 if OPTIONS.vendor_item_list:
1181 vendor_item_list = read_config_list(OPTIONS.vendor_item_list)
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001182 else:
Daniel Normand5d70ea2019-06-05 15:13:43 -07001183 vendor_item_list = DEFAULT_VENDOR_ITEM_LIST
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001184
Daniel Normanfdb38812019-04-15 09:47:24 -07001185 if OPTIONS.output_item_list:
1186 output_item_list = read_config_list(OPTIONS.output_item_list)
1187 else:
1188 output_item_list = None
1189
Daniel Normane5964522019-03-19 10:32:03 -07001190 if not validate_config_lists(
Daniel Normand5d70ea2019-06-05 15:13:43 -07001191 framework_item_list=framework_item_list,
1192 framework_misc_info_keys=framework_misc_info_keys,
1193 vendor_item_list=vendor_item_list):
Daniel Normane5964522019-03-19 10:32:03 -07001194 sys.exit(1)
1195
Daniel Norman2c99c5b2019-03-07 13:01:48 -08001196 call_func_with_temp_dir(
1197 lambda temp_dir: merge_target_files(
1198 temp_dir=temp_dir,
Daniel Normand5d70ea2019-06-05 15:13:43 -07001199 framework_target_files=OPTIONS.framework_target_files,
1200 framework_item_list=framework_item_list,
1201 framework_misc_info_keys=framework_misc_info_keys,
1202 vendor_target_files=OPTIONS.vendor_target_files,
1203 vendor_item_list=vendor_item_list,
Daniel Normana4911da2019-03-15 14:36:21 -07001204 output_target_files=OPTIONS.output_target_files,
Daniel Normanfdb38812019-04-15 09:47:24 -07001205 output_dir=OPTIONS.output_dir,
1206 output_item_list=output_item_list,
Daniel Norman3b64ce12019-04-16 16:11:35 -07001207 output_ota=OPTIONS.output_ota,
Daniel Norman1bd2a1d2019-04-18 12:32:18 -07001208 output_img=OPTIONS.output_img,
Daniel Normanf0318252019-04-15 11:34:56 -07001209 output_super_empty=OPTIONS.output_super_empty,
Daniel Normane5b134a2019-04-17 14:54:06 -07001210 rebuild_recovery=OPTIONS.rebuild_recovery), OPTIONS.keep_tmp)
Bill Peckhame9eb5f92019-02-01 15:52:10 -08001211
1212
1213if __name__ == '__main__':
Bill Peckham889b0c62019-02-21 18:53:37 -08001214 main()