blob: 3c6bfbfc9cf9eed3aa97064a6c563304a7311058 [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.
16
17"""
18This script merges two partial target files packages (one of which contains
19system files, and the other contains non-system files) together, producing a
20complete target files package that can be used to generate an OTA package.
21
22Usage: merge_target_files.py [args]
23
24 --system-target-files system-target-files-zip-archive
25 The input target files package containing system bits. This is a zip
26 archive.
27
Daniel Norman2c99c5b2019-03-07 13:01:48 -080028 --system-item-list system-item-list-file
29 The optional path to a newline-separated config file that replaces the
30 contents of default_system_item_list if provided.
31
32 --system-misc-info-keys system-misc-info-keys-file
33 The optional path to a newline-separated config file that replaces the
34 contents of default_system_misc_info_keys if provided.
35
Bill Peckhame9eb5f92019-02-01 15:52:10 -080036 --other-target-files other-target-files-zip-archive
37 The input target files package containing other bits. This is a zip
38 archive.
39
Daniel Norman2c99c5b2019-03-07 13:01:48 -080040 --other-item-list other-item-list-file
41 The optional path to a newline-separated config file that replaces the
42 contents of default_other_item_list if provided.
43
Bill Peckhame9eb5f92019-02-01 15:52:10 -080044 --output-target-files output-target-files-package
45 The output merged target files package. Also a zip archive.
Daniel Normana4911da2019-03-15 14:36:21 -070046
47 --rebuild_recovery
48 Rebuild the recovery patch used by non-A/B devices and write it to the
49 system image.
Bill Peckhame9eb5f92019-02-01 15:52:10 -080050"""
51
52from __future__ import print_function
53
Bill Peckhame9eb5f92019-02-01 15:52:10 -080054import fnmatch
55import logging
56import os
57import sys
58import zipfile
59
60import common
61import add_img_to_target_files
62
63logger = logging.getLogger(__name__)
64OPTIONS = common.OPTIONS
65OPTIONS.verbose = True
Bill Peckhamf753e152019-02-19 18:02:46 -080066OPTIONS.system_target_files = None
Daniel Norman2c99c5b2019-03-07 13:01:48 -080067OPTIONS.system_item_list = None
68OPTIONS.system_misc_info_keys = None
Bill Peckhamf753e152019-02-19 18:02:46 -080069OPTIONS.other_target_files = None
Daniel Norman2c99c5b2019-03-07 13:01:48 -080070OPTIONS.other_item_list = None
Bill Peckhamf753e152019-02-19 18:02:46 -080071OPTIONS.output_target_files = None
Daniel Normana4911da2019-03-15 14:36:21 -070072OPTIONS.rebuild_recovery = False
Bill Peckhamf753e152019-02-19 18:02:46 -080073OPTIONS.keep_tmp = False
Bill Peckhame9eb5f92019-02-01 15:52:10 -080074
Daniel Norman2c99c5b2019-03-07 13:01:48 -080075# default_system_item_list is a list of items to extract from the partial
Bill Peckhame9eb5f92019-02-01 15:52:10 -080076# system target files package as is, meaning these items will land in the
77# output target files package exactly as they appear in the input partial
78# system target files package.
79
Daniel Norman2c99c5b2019-03-07 13:01:48 -080080default_system_item_list = [
Bill Peckhame9eb5f92019-02-01 15:52:10 -080081 'META/apkcerts.txt',
82 'META/filesystem_config.txt',
83 'META/root_filesystem_config.txt',
84 'META/system_manifest.xml',
85 'META/system_matrix.xml',
86 'META/update_engine_config.txt',
87 'PRODUCT/*',
88 'ROOT/*',
89 'SYSTEM/*',
90]
91
92# system_extract_special_item_list is a list of items to extract from the
93# partial system target files package that need some special processing, such
94# as some sort of combination with items from the partial other target files
95# package.
96
97system_extract_special_item_list = [
98 'META/*',
99]
100
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800101# default_system_misc_info_keys is a list of keys to obtain from the system instance of
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800102# META/misc_info.txt. The remaining keys from the other instance.
103
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800104default_system_misc_info_keys = [
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800105 'avb_system_hashtree_enable',
106 'avb_system_add_hashtree_footer_args',
107 'avb_system_key_path',
108 'avb_system_algorithm',
109 'avb_system_rollback_index_location',
110 'avb_product_hashtree_enable',
111 'avb_product_add_hashtree_footer_args',
112 'avb_product_services_hashtree_enable',
113 'avb_product_services_add_hashtree_footer_args',
114 'system_root_image',
115 'root_dir',
116 'ab_update',
117 'default_system_dev_certificate',
118 'system_size',
119]
120
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800121# default_other_item_list is a list of items to extract from the partial
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800122# other target files package as is, meaning these items will land in the output
123# target files package exactly as they appear in the input partial other target
124# files package.
125
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800126default_other_item_list = [
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800127 'META/boot_filesystem_config.txt',
128 'META/otakeys.txt',
129 'META/releasetools.py',
130 'META/vendor_filesystem_config.txt',
131 'META/vendor_manifest.xml',
132 'META/vendor_matrix.xml',
133 'BOOT/*',
134 'DATA/*',
135 'ODM/*',
136 'OTA/android-info.txt',
137 'PREBUILT_IMAGES/*',
138 'RADIO/*',
139 'VENDOR/*',
140]
141
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800142# other_extract_special_item_list is a list of items to extract from the
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800143# partial other target files package that need some special processing, such as
144# some sort of combination with items from the partial system target files
145# package.
146
147other_extract_special_item_list = [
148 'META/*',
149]
150
151
152def extract_items(target_files, target_files_temp_dir, extract_item_list):
153 """Extract items from target files to temporary directory.
154
155 This function extracts from the specified target files zip archive into the
156 specified temporary directory, the items specified in the extract item list.
157
158 Args:
159 target_files: The target files zip archive from which to extract items.
160
161 target_files_temp_dir: The temporary directory where the extracted items
162 will land.
163
164 extract_item_list: A list of items to extract.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800165 """
166
167 logger.info('extracting from %s', target_files)
168
169 # Filter the extract_item_list to remove any items that do not exist in the
170 # zip file. Otherwise, the extraction step will fail.
171
172 with zipfile.ZipFile(
173 target_files,
174 'r',
175 allowZip64=True) as target_files_zipfile:
176 target_files_namelist = target_files_zipfile.namelist()
177
178 filtered_extract_item_list = []
179 for pattern in extract_item_list:
180 matching_namelist = fnmatch.filter(target_files_namelist, pattern)
181 if not matching_namelist:
182 logger.warning('no match for %s', pattern)
183 else:
184 filtered_extract_item_list.append(pattern)
185
Bill Peckham8ff3fbd2019-02-22 10:57:43 -0800186 # Extract from target_files into target_files_temp_dir the
187 # filtered_extract_item_list.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800188
Bill Peckham8ff3fbd2019-02-22 10:57:43 -0800189 common.UnzipToDir(
190 target_files,
191 target_files_temp_dir,
192 filtered_extract_item_list)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800193
194
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800195def read_config_list(config_file_path):
196 """Reads a config file into a list of strings.
197
198 Expects the file to be newline-separated.
199
200 Args:
201 config_file_path: The path to the config file to open and read.
202 """
203 with open(config_file_path) as config_file:
204 return config_file.read().splitlines()
205
206
Daniel Norman19b9fe92019-03-19 14:48:02 -0700207def validate_config_lists(
208 system_item_list,
209 system_misc_info_keys,
210 other_item_list):
Daniel Normane5964522019-03-19 10:32:03 -0700211 """Performs validations on the merge config lists.
212
213 Args:
214 system_item_list: The list of items to extract from the partial
215 system target files package as is.
216
Daniel Norman19b9fe92019-03-19 14:48:02 -0700217 system_misc_info_keys: A list of keys to obtain from the system instance
218 of META/misc_info.txt. The remaining keys from the other instance.
219
Daniel Normane5964522019-03-19 10:32:03 -0700220 other_item_list: The list of items to extract from the partial
221 other target files package as is.
222
223 Returns:
224 False if a validation fails, otherwise true.
225 """
226 default_combined_item_set = set(default_system_item_list)
227 default_combined_item_set.update(default_other_item_list)
228
229 combined_item_set = set(system_item_list)
230 combined_item_set.update(other_item_list)
231
232 # Check that the merge config lists are not missing any item specified
233 # by the default config lists.
234 difference = default_combined_item_set.difference(combined_item_set)
235 if difference:
236 logger.error('Missing merge config items: %s' % list(difference))
237 logger.error('Please ensure missing items are in either the '
238 'system-item-list or other-item-list files provided to '
239 'this script.')
240 return False
241
Daniel Norman19b9fe92019-03-19 14:48:02 -0700242 if ('dynamic_partition_list' in system_misc_info_keys) or (
243 'super_partition_groups' in system_misc_info_keys):
244 logger.error('Dynamic partition misc info keys should come from '
245 'the other instance of META/misc_info.txt.')
246 return False
247
Daniel Normane5964522019-03-19 10:32:03 -0700248 return True
249
250
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800251def process_ab_partitions_txt(
252 system_target_files_temp_dir,
253 other_target_files_temp_dir,
254 output_target_files_temp_dir):
255 """Perform special processing for META/ab_partitions.txt
256
257 This function merges the contents of the META/ab_partitions.txt files from
258 the system directory and the other directory, placing the merged result in
259 the output directory. The precondition in that the files are already
260 extracted. The post condition is that the output META/ab_partitions.txt
261 contains the merged content. The format for each ab_partitions.txt a one
262 partition name per line. The output file contains the union of the parition
263 names.
264
265 Args:
266 system_target_files_temp_dir: The name of a directory containing the
267 special items extracted from the system target files package.
268
269 other_target_files_temp_dir: The name of a directory containing the
270 special items extracted from the other target files package.
271
272 output_target_files_temp_dir: The name of a directory that will be used
273 to create the output target files package after all the special cases
274 are processed.
275 """
276
277 system_ab_partitions_txt = os.path.join(
278 system_target_files_temp_dir, 'META', 'ab_partitions.txt')
279
280 other_ab_partitions_txt = os.path.join(
281 other_target_files_temp_dir, 'META', 'ab_partitions.txt')
282
283 with open(system_ab_partitions_txt) as f:
284 system_ab_partitions = f.read().splitlines()
285
286 with open(other_ab_partitions_txt) as f:
287 other_ab_partitions = f.read().splitlines()
288
289 output_ab_partitions = set(system_ab_partitions + other_ab_partitions)
290
291 output_ab_partitions_txt = os.path.join(
292 output_target_files_temp_dir, 'META', 'ab_partitions.txt')
293
294 with open(output_ab_partitions_txt, 'w') as output:
295 for partition in sorted(output_ab_partitions):
296 output.write('%s\n' % partition)
297
298
299def process_misc_info_txt(
300 system_target_files_temp_dir,
301 other_target_files_temp_dir,
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800302 output_target_files_temp_dir,
303 system_misc_info_keys):
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800304 """Perform special processing for META/misc_info.txt
305
306 This function merges the contents of the META/misc_info.txt files from the
307 system directory and the other directory, placing the merged result in the
308 output directory. The precondition in that the files are already extracted.
309 The post condition is that the output META/misc_info.txt contains the merged
310 content.
311
312 Args:
313 system_target_files_temp_dir: The name of a directory containing the
314 special items extracted from the system target files package.
315
316 other_target_files_temp_dir: The name of a directory containing the
317 special items extracted from the other target files package.
318
319 output_target_files_temp_dir: The name of a directory that will be used
320 to create the output target files package after all the special cases
321 are processed.
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800322
323 system_misc_info_keys: A list of keys to obtain from the system instance
324 of META/misc_info.txt. The remaining keys from the other instance.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800325 """
326
327 def read_helper(d):
328 misc_info_txt = os.path.join(d, 'META', 'misc_info.txt')
329 with open(misc_info_txt) as f:
330 return list(f.read().splitlines())
331
332 system_info_dict = common.LoadDictionaryFromLines(
333 read_helper(system_target_files_temp_dir))
334
335 # We take most of the misc info from the other target files.
336
337 merged_info_dict = common.LoadDictionaryFromLines(
338 read_helper(other_target_files_temp_dir))
339
340 # Replace certain values in merged_info_dict with values from
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800341 # system_info_dict.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800342
343 for key in system_misc_info_keys:
344 merged_info_dict[key] = system_info_dict[key]
345
Daniel Norman19b9fe92019-03-19 14:48:02 -0700346 # Merge misc info keys used for Dynamic Partitions.
347 if (merged_info_dict.get('use_dynamic_partitions') == 'true') and (
348 system_info_dict.get('use_dynamic_partitions') == 'true'):
349 merged_info_dict['dynamic_partition_list'] = '%s %s' % (
350 system_info_dict.get('dynamic_partition_list', ''),
351 merged_info_dict.get('dynamic_partition_list', ''))
352 # Partition groups and group sizes are defined by the other (non-system)
353 # misc info file because these values may vary for each board that uses
354 # a shared system image.
355 for partition_group in merged_info_dict['super_partition_groups'].split(' '):
356 if ('super_%s_group_size' % partition_group) not in merged_info_dict:
357 raise common.ExternalError(
358 'Other META/misc_info.txt does not contain required key '
359 'super_%s_group_size.' % partition_group)
360 key = 'super_%s_partition_list' % partition_group
361 merged_info_dict[key] = '%s %s' % (
362 system_info_dict.get(key, ''),
363 merged_info_dict.get(key, ''))
364
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800365 output_misc_info_txt = os.path.join(
366 output_target_files_temp_dir,
367 'META', 'misc_info.txt')
368
369 sorted_keys = sorted(merged_info_dict.keys())
370
371 with open(output_misc_info_txt, 'w') as output:
372 for key in sorted_keys:
373 output.write('{}={}\n'.format(key, merged_info_dict[key]))
374
375
376def process_file_contexts_bin(temp_dir, output_target_files_temp_dir):
377 """Perform special processing for META/file_contexts.bin.
378
379 This function combines plat_file_contexts and vendor_file_contexts, which are
380 expected to already be extracted in temp_dir, to produce a merged
381 file_contexts.bin that will land in temp_dir at META/file_contexts.bin.
382
383 Args:
384 temp_dir: The name of a scratch directory that this function can use for
385 intermediate files generated during processing.
386
387 output_target_files_temp_dir: The name of the working directory that must
388 already contain plat_file_contexts and vendor_file_contexts (in the
389 appropriate sub directories), and to which META/file_contexts.bin will be
390 written.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800391 """
392
393 # To create a merged file_contexts.bin file, we use the system and vendor
394 # file contexts files as input, the m4 tool to combine them, the sorting tool
395 # to sort, and finally the sefcontext_compile tool to generate the final
396 # output. We currently omit a checkfc step since the files had been checked
397 # as part of the build.
398
399 # The m4 step concatenates the two input files contexts files. Since m4
400 # writes to stdout, we receive that into an array of bytes, and then write it
401 # to a file.
402
403 # Collect the file contexts that we're going to combine from SYSTEM, VENDOR,
404 # PRODUCT, and ODM. We require SYSTEM and VENDOR, but others are optional.
405
406 file_contexts_list = []
407
408 for partition in ['SYSTEM', 'VENDOR', 'PRODUCT', 'ODM']:
409 prefix = 'plat' if partition == 'SYSTEM' else partition.lower()
410
411 file_contexts = os.path.join(
412 output_target_files_temp_dir,
413 partition, 'etc', 'selinux', prefix + '_file_contexts')
414
415 mandatory = partition in ['SYSTEM', 'VENDOR']
416
417 if mandatory or os.path.isfile(file_contexts):
418 file_contexts_list.append(file_contexts)
419 else:
420 logger.warning('file not found: %s', file_contexts)
421
422 command = ['m4', '--fatal-warnings', '-s'] + file_contexts_list
423
424 merged_content = common.RunAndCheckOutput(command, verbose=False)
425
426 merged_file_contexts_txt = os.path.join(temp_dir, 'merged_file_contexts.txt')
427
428 with open(merged_file_contexts_txt, 'wb') as f:
429 f.write(merged_content)
430
431 # The sort step sorts the concatenated file.
432
433 sorted_file_contexts_txt = os.path.join(temp_dir, 'sorted_file_contexts.txt')
434 command = ['fc_sort', merged_file_contexts_txt, sorted_file_contexts_txt]
Bill Peckham889b0c62019-02-21 18:53:37 -0800435 common.RunAndWait(command, verbose=True)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800436
437 # Finally, the compile step creates the final META/file_contexts.bin.
438
439 file_contexts_bin = os.path.join(
440 output_target_files_temp_dir,
441 'META', 'file_contexts.bin')
442
443 command = [
444 'sefcontext_compile',
445 '-o', file_contexts_bin,
446 sorted_file_contexts_txt,
447 ]
448
Bill Peckham889b0c62019-02-21 18:53:37 -0800449 common.RunAndWait(command, verbose=True)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800450
451
452def process_special_cases(
453 temp_dir,
454 system_target_files_temp_dir,
455 other_target_files_temp_dir,
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800456 output_target_files_temp_dir,
457 system_misc_info_keys):
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800458 """Perform special-case processing for certain target files items.
459
460 Certain files in the output target files package require special-case
461 processing. This function performs all that special-case processing.
462
463 Args:
464 temp_dir: The name of a scratch directory that this function can use for
465 intermediate files generated during processing.
466
467 system_target_files_temp_dir: The name of a directory containing the
468 special items extracted from the system target files package.
469
470 other_target_files_temp_dir: The name of a directory containing the
471 special items extracted from the other target files package.
472
473 output_target_files_temp_dir: The name of a directory that will be used
474 to create the output target files package after all the special cases
475 are processed.
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800476
477 system_misc_info_keys: A list of keys to obtain from the system instance
478 of META/misc_info.txt. The remaining keys from the other instance.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800479 """
480
481 process_ab_partitions_txt(
482 system_target_files_temp_dir=system_target_files_temp_dir,
483 other_target_files_temp_dir=other_target_files_temp_dir,
484 output_target_files_temp_dir=output_target_files_temp_dir)
485
486 process_misc_info_txt(
487 system_target_files_temp_dir=system_target_files_temp_dir,
488 other_target_files_temp_dir=other_target_files_temp_dir,
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800489 output_target_files_temp_dir=output_target_files_temp_dir,
490 system_misc_info_keys=system_misc_info_keys)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800491
Bill Peckham889b0c62019-02-21 18:53:37 -0800492 process_file_contexts_bin(
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800493 temp_dir=temp_dir,
494 output_target_files_temp_dir=output_target_files_temp_dir)
495
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800496
497def merge_target_files(
498 temp_dir,
499 system_target_files,
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800500 system_item_list,
501 system_misc_info_keys,
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800502 other_target_files,
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800503 other_item_list,
Daniel Normana4911da2019-03-15 14:36:21 -0700504 output_target_files,
505 rebuild_recovery):
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800506 """Merge two target files packages together.
507
508 This function takes system and other target files packages as input, performs
509 various file extractions, special case processing, and finally creates a
510 merged zip archive as output.
511
512 Args:
513 temp_dir: The name of a directory we use when we extract items from the
514 input target files packages, and also a scratch directory that we use for
515 temporary files.
516
517 system_target_files: The name of the zip archive containing the system
518 partial target files package.
519
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800520 system_item_list: The list of items to extract from the partial system
521 target files package as is, meaning these items will land in the output
522 target files package exactly as they appear in the input partial system
523 target files package.
524
525 system_misc_info_keys: The list of keys to obtain from the system instance
526 of META/misc_info.txt. The remaining keys from the other instance.
527
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800528 other_target_files: The name of the zip archive containing the other
529 partial target files package.
530
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800531 other_item_list: The list of items to extract from the partial other
532 target files package as is, meaning these items will land in the output
533 target files package exactly as they appear in the input partial other
534 target files package.
535
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800536 output_target_files: The name of the output zip archive target files
537 package created by merging system and other.
Daniel Normana4911da2019-03-15 14:36:21 -0700538
539 rebuild_recovery: If true, rebuild the recovery patch used by non-A/B
540 devices and write it to the system image.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800541 """
542
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800543 logger.info(
544 'starting: merge system %s and other %s into output %s',
545 system_target_files,
546 other_target_files,
547 output_target_files)
548
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800549 # Create directory names that we'll use when we extract files from system,
550 # and other, and for zipping the final output.
551
552 system_target_files_temp_dir = os.path.join(temp_dir, 'system')
553 other_target_files_temp_dir = os.path.join(temp_dir, 'other')
554 output_target_files_temp_dir = os.path.join(temp_dir, 'output')
555
556 # Extract "as is" items from the input system partial target files package.
557 # We extract them directly into the output temporary directory since the
558 # items do not need special case processing.
559
Bill Peckham889b0c62019-02-21 18:53:37 -0800560 extract_items(
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800561 target_files=system_target_files,
562 target_files_temp_dir=output_target_files_temp_dir,
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800563 extract_item_list=system_item_list)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800564
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800565 # Extract "as is" items from the input other partial target files package. We
566 # extract them directly into the output temporary directory since the items
567 # do not need special case processing.
568
Bill Peckham889b0c62019-02-21 18:53:37 -0800569 extract_items(
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800570 target_files=other_target_files,
571 target_files_temp_dir=output_target_files_temp_dir,
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800572 extract_item_list=other_item_list)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800573
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800574 # Extract "special" items from the input system partial target files package.
575 # We extract these items to different directory since they require special
576 # processing before they will end up in the output directory.
577
Bill Peckham889b0c62019-02-21 18:53:37 -0800578 extract_items(
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800579 target_files=system_target_files,
580 target_files_temp_dir=system_target_files_temp_dir,
581 extract_item_list=system_extract_special_item_list)
582
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800583 # Extract "special" items from the input other partial target files package.
584 # We extract these items to different directory since they require special
585 # processing before they will end up in the output directory.
586
Bill Peckham889b0c62019-02-21 18:53:37 -0800587 extract_items(
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800588 target_files=other_target_files,
589 target_files_temp_dir=other_target_files_temp_dir,
590 extract_item_list=other_extract_special_item_list)
591
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800592 # Now that the temporary directories contain all the extracted files, perform
593 # special case processing on any items that need it. After this function
594 # completes successfully, all the files we need to create the output target
595 # files package are in place.
596
Bill Peckham889b0c62019-02-21 18:53:37 -0800597 process_special_cases(
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800598 temp_dir=temp_dir,
599 system_target_files_temp_dir=system_target_files_temp_dir,
600 other_target_files_temp_dir=other_target_files_temp_dir,
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800601 output_target_files_temp_dir=output_target_files_temp_dir,
602 system_misc_info_keys=system_misc_info_keys)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800603
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800604 # Regenerate IMAGES in the temporary directory.
605
Daniel Normana4911da2019-03-15 14:36:21 -0700606 add_img_args = ['--verbose']
607 if rebuild_recovery:
608 add_img_args.append('--rebuild_recovery')
609 add_img_args.append(output_target_files_temp_dir)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800610
611 add_img_to_target_files.main(add_img_args)
612
613 # Finally, create the output target files zip archive.
614
615 output_zip = os.path.abspath(output_target_files)
616 output_target_files_list = os.path.join(temp_dir, 'output.list')
617 output_target_files_meta_dir = os.path.join(
618 output_target_files_temp_dir, 'META')
619
620 command = [
621 'find',
622 output_target_files_meta_dir,
623 ]
624 # TODO(bpeckham): sort this to be more like build.
625 meta_content = common.RunAndCheckOutput(command, verbose=False)
626 command = [
627 'find',
628 output_target_files_temp_dir,
629 '-path',
630 output_target_files_meta_dir,
631 '-prune',
632 '-o',
633 '-print'
634 ]
635 # TODO(bpeckham): sort this to be more like build.
636 other_content = common.RunAndCheckOutput(command, verbose=False)
637
638 with open(output_target_files_list, 'wb') as f:
639 f.write(meta_content)
640 f.write(other_content)
641
642 command = [
Bill Peckhamf753e152019-02-19 18:02:46 -0800643 'soong_zip',
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800644 '-d',
645 '-o', output_zip,
646 '-C', output_target_files_temp_dir,
647 '-l', output_target_files_list,
648 ]
649 logger.info('creating %s', output_target_files)
Bill Peckham889b0c62019-02-21 18:53:37 -0800650 common.RunAndWait(command, verbose=True)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800651
652
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800653def call_func_with_temp_dir(func, keep_tmp):
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800654 """Manage the creation and cleanup of the temporary directory.
655
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800656 This function calls the given function after first creating a temporary
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800657 directory. It also cleans up the temporary directory.
658
659 Args:
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800660 func: The function to call. Should accept one parameter, the path to
661 the temporary directory.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800662
663 keep_tmp: Keep the temporary directory after processing is complete.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800664 """
665
666 # Create a temporary directory. This will serve as the parent of directories
667 # we use when we extract items from the input target files packages, and also
668 # a scratch directory that we use for temporary files.
669
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800670 temp_dir = common.MakeTempDir(prefix='merge_target_files_')
671
672 try:
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800673 func(temp_dir)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800674 except:
675 raise
676 finally:
677 if keep_tmp:
678 logger.info('keeping %s', temp_dir)
679 else:
680 common.Cleanup()
681
682
683def main():
684 """The main function.
685
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800686 Process command line arguments, then call merge_target_files to
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800687 perform the heavy lifting.
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800688 """
689
690 common.InitLogging()
691
Bill Peckhamf753e152019-02-19 18:02:46 -0800692 def option_handler(o, a):
693 if o == '--system-target-files':
694 OPTIONS.system_target_files = a
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800695 elif o == '--system-item-list':
696 OPTIONS.system_item_list = a
697 elif o == '--system-misc-info-keys':
698 OPTIONS.system_misc_info_keys = a
Bill Peckhamf753e152019-02-19 18:02:46 -0800699 elif o == '--other-target-files':
700 OPTIONS.other_target_files = a
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800701 elif o == '--other-item-list':
702 OPTIONS.other_item_list = a
Bill Peckhamf753e152019-02-19 18:02:46 -0800703 elif o == '--output-target-files':
704 OPTIONS.output_target_files = a
Daniel Normana4911da2019-03-15 14:36:21 -0700705 elif o == '--rebuild_recovery':
706 OPTIONS.rebuild_recovery = True
Bill Peckhamf753e152019-02-19 18:02:46 -0800707 elif o == '--keep_tmp':
708 OPTIONS.keep_tmp = True
709 else:
710 return False
711 return True
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800712
Bill Peckhamf753e152019-02-19 18:02:46 -0800713 args = common.ParseOptions(
714 sys.argv[1:], __doc__,
715 extra_long_opts=[
716 'system-target-files=',
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800717 'system-item-list=',
718 'system-misc-info-keys=',
Bill Peckhamf753e152019-02-19 18:02:46 -0800719 'other-target-files=',
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800720 'other-item-list=',
Bill Peckhamf753e152019-02-19 18:02:46 -0800721 'output-target-files=',
Daniel Normana4911da2019-03-15 14:36:21 -0700722 'rebuild_recovery',
Bill Peckhamf753e152019-02-19 18:02:46 -0800723 "keep_tmp",
724 ],
725 extra_option_handler=option_handler)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800726
Bill Peckham889b0c62019-02-21 18:53:37 -0800727 if (len(args) != 0 or
Bill Peckhamf753e152019-02-19 18:02:46 -0800728 OPTIONS.system_target_files is None or
729 OPTIONS.other_target_files is None or
730 OPTIONS.output_target_files is None):
731 common.Usage(__doc__)
Bill Peckham889b0c62019-02-21 18:53:37 -0800732 sys.exit(1)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800733
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800734 if OPTIONS.system_item_list:
735 system_item_list = read_config_list(OPTIONS.system_item_list)
736 else:
737 system_item_list = default_system_item_list
738
739 if OPTIONS.system_misc_info_keys:
740 system_misc_info_keys = read_config_list(OPTIONS.system_misc_info_keys)
741 else:
742 system_misc_info_keys = default_system_misc_info_keys
743
744 if OPTIONS.other_item_list:
745 other_item_list = read_config_list(OPTIONS.other_item_list)
746 else:
747 other_item_list = default_other_item_list
748
Daniel Normane5964522019-03-19 10:32:03 -0700749 if not validate_config_lists(
750 system_item_list=system_item_list,
Daniel Norman19b9fe92019-03-19 14:48:02 -0700751 system_misc_info_keys=system_misc_info_keys,
Daniel Normane5964522019-03-19 10:32:03 -0700752 other_item_list=other_item_list):
753 sys.exit(1)
754
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800755 call_func_with_temp_dir(
756 lambda temp_dir: merge_target_files(
757 temp_dir=temp_dir,
758 system_target_files=OPTIONS.system_target_files,
759 system_item_list=system_item_list,
760 system_misc_info_keys=system_misc_info_keys,
761 other_target_files=OPTIONS.other_target_files,
762 other_item_list=other_item_list,
Daniel Normana4911da2019-03-15 14:36:21 -0700763 output_target_files=OPTIONS.output_target_files,
764 rebuild_recovery=OPTIONS.rebuild_recovery),
Daniel Norman2c99c5b2019-03-07 13:01:48 -0800765 OPTIONS.keep_tmp)
Bill Peckhame9eb5f92019-02-01 15:52:10 -0800766
767
768if __name__ == '__main__':
Bill Peckham889b0c62019-02-21 18:53:37 -0800769 main()