diff --git a/core/Makefile b/core/Makefile index bf8b02b4f3..46350f6b38 100644 --- a/core/Makefile +++ b/core/Makefile @@ -4827,25 +4827,24 @@ ifeq (,$(TARGET_BUILD_UNBUNDLED)) intermediates := $(call intermediates-dir-for,PACKAGING,check_vintf_all) check_vintf_all_deps := -APEX_OUT := $(PRODUCT_OUT)/apex # ----------------------------------------------------------------- -# Create apex-info-file.xml +# Activate vendor APEXes for checkvintf apex_dirs := \ - $(TARGET_OUT)/apex/% \ - $(TARGET_OUT_SYSTEM_EXT)/apex/% \ $(TARGET_OUT_VENDOR)/apex/% \ - $(TARGET_OUT_ODM)/apex/% \ - $(TARGET_OUT_PRODUCT)/apex/% \ apex_files := $(sort $(filter $(apex_dirs), $(INTERNAL_ALLIMAGES_FILES))) + +APEX_OUT := $(intermediates)/apex APEX_INFO_FILE := $(APEX_OUT)/apex-info-list.xml -# dump_apex_info scans $(PRODUCT_OUT)/apex and writes apex-info-list.xml there. -# This relies on the fact that rules for .apex files install the contents in $(PRODUCT_OUT)/apex. -$(APEX_INFO_FILE): $(HOST_OUT_EXECUTABLES)/dump_apex_info $(apex_files) - @echo "Creating apex-info-file in $(PRODUCT_OUT) " - $< --root_dir $(PRODUCT_OUT) +# apexd_host scans/activates APEX files and writes /apex/apex-info-list.xml +$(APEX_INFO_FILE): $(HOST_OUT_EXECUTABLES)/apexd_host $(apex_files) + @echo "Extracting apexes..." + @rm -rf $(APEX_OUT) + @mkdir -p $(APEX_OUT) + $< --vendor_path $(TARGET_OUT_VENDOR) \ + --apex_path $(APEX_OUT) apex_files := apex_dirs := @@ -5301,7 +5300,6 @@ INTERNAL_OTATOOLS_MODULES += \ apex_compression_tool \ deapexer \ debugfs_static \ - dump_apex_info \ fsck.erofs \ make_erofs \ merge_zips \ diff --git a/tools/releasetools/Android.bp b/tools/releasetools/Android.bp index a76dc8a8bc..7a2dcb76e3 100644 --- a/tools/releasetools/Android.bp +++ b/tools/releasetools/Android.bp @@ -99,9 +99,8 @@ python_defaults { "releasetools_common", ], required: [ + "apexd_host", "checkvintf", - "deapexer", - "dump_apex_info", ], } diff --git a/tools/releasetools/check_target_files_vintf.py b/tools/releasetools/check_target_files_vintf.py index 906ad1f35b..33624f5085 100755 --- a/tools/releasetools/check_target_files_vintf.py +++ b/tools/releasetools/check_target_files_vintf.py @@ -129,8 +129,9 @@ def CheckVintfFromExtractedTargetFiles(input_tmp, info_dict=None): dirmap = GetDirmap(input_tmp) - # Simulate apexd from target-files. - dirmap['/apex'] = PrepareApexDirectory(input_tmp) + # Simulate apexd with target-files. + # add a mapping('/apex' => ${input_tmp}/APEX) to dirmap + PrepareApexDirectory(input_tmp, dirmap) args_for_skus = GetArgsForSkus(info_dict) shipping_api_level_args = GetArgsForShippingApiLevel(info_dict) @@ -204,7 +205,8 @@ def GetVintfApexUnzipPatterns(): return patterns -def PrepareApexDirectory(inp): + +def PrepareApexDirectory(inp, dirmap): """ Prepare /apex directory before running checkvintf Apex binaries do not support dirmaps, in order to use these binaries we @@ -212,93 +214,25 @@ def PrepareApexDirectory(inp): expected device locations. This simulates how apexd activates APEXes. - 1. create {inp}/APEX which is treated as a "/" on device. - 2. copy apexes from target-files to {root}/{partition}/apex. - 3. mount apexes under {root}/{partition}/apex at {root}/apex. - 4. generate info files with dump_apex_info. - - We'll get the following layout - {inp}/APEX/apex # Activated APEXes + some info files - {inp}/APEX/system/apex # System APEXes - {inp}/APEX/vendor/apex # Vendor APEXes - ... - - Args: - inp: path to the directory that contains the extracted target files archive. - - Returns: - directory representing /apex on device + 1. create {inp}/APEX which is treated as a "/apex" on device. + 2. invoke apexd_host with vendor APEXes. """ - deapexer = 'deapexer' - debugfs_path = 'debugfs' - fsckerofs_path = 'fsck.erofs' - if OPTIONS.search_path: - debugfs_path = os.path.join(OPTIONS.search_path, 'bin', 'debugfs_static') - deapexer_path = os.path.join(OPTIONS.search_path, 'bin', 'deapexer') - fsckerofs_path = os.path.join(OPTIONS.search_path, 'bin', 'fsck.erofs') - if os.path.isfile(deapexer_path): - deapexer = deapexer_path - - def ExtractApexes(path, outp): - # Extract all APEXes found in input path. - logger.info('Extracting APEXs in %s', path) - for f in os.listdir(path): - logger.info(' adding APEX %s', os.path.basename(f)) - apex = os.path.join(path, f) - if os.path.isdir(apex) and os.path.isfile(os.path.join(apex, 'apex_manifest.pb')): - info = ParseApexManifest(os.path.join(apex, 'apex_manifest.pb')) - # Flattened APEXes may have symlinks for libs (linked to /system/lib) - # We need to blindly copy them all. - shutil.copytree(apex, os.path.join(outp, info.name), symlinks=True) - elif os.path.isfile(apex) and apex.endswith(('.apex', '.capex')): - cmd = [deapexer, - '--debugfs_path', debugfs_path, - 'info', - apex] - info = json.loads(common.RunAndCheckOutput(cmd)) - - cmd = [deapexer, - '--debugfs_path', debugfs_path, - '--fsckerofs_path', fsckerofs_path, - 'extract', - apex, - os.path.join(outp, info['name'])] - common.RunAndCheckOutput(cmd) - else: - logger.info(' .. skipping %s (is it APEX?)', path) - - root_dir_name = 'APEX' - root_dir = os.path.join(inp, root_dir_name) - extracted_root = os.path.join(root_dir, 'apex') + apex_dir = os.path.join(inp, 'APEX') + # checkvintf needs /apex dirmap + dirmap['/apex'] = apex_dir # Always create /apex directory for dirmap - os.makedirs(extracted_root) + os.makedirs(apex_dir) - create_info_file = False + # Invoke apexd_host to activate vendor APEXes for checkvintf + apex_host = os.path.join(OPTIONS.search_path, 'bin', 'apexd_host') + cmd = [apex_host, '--tool_path', OPTIONS.search_path] + cmd += ['--apex_path', dirmap['/apex']] + if '/vendor' in dirmap: + cmd += ['--vendor_path', dirmap['/vendor']] + common.RunAndCheckOutput(cmd) - # Loop through search path looking for and processing apex/ directories. - for device_path, target_files_rel_paths in DIR_SEARCH_PATHS.items(): - # checkvintf only needs vendor apexes. skip other partitions for efficiency - if device_path not in ['/vendor', '/odm']: - continue - # First, copy VENDOR/apex/foo.apex to APEX/vendor/apex/foo.apex - # Then, extract the contents to APEX/apex/foo/ - for target_files_rel_path in target_files_rel_paths: - inp_partition = os.path.join(inp, target_files_rel_path,"apex") - if os.path.exists(inp_partition): - apex_dir = root_dir + os.path.join(device_path + "/apex"); - os.makedirs(root_dir + device_path) - shutil.copytree(inp_partition, apex_dir, symlinks=True) - ExtractApexes(apex_dir, extracted_root) - create_info_file = True - - if create_info_file: - ### Dump apex info files - dump_cmd = ['dump_apex_info', '--root_dir', root_dir] - common.RunAndCheckOutput(dump_cmd) - - return extracted_root def CheckVintfFromTargetFiles(inp, info_dict=None): """ diff --git a/tools/releasetools/merge/Android.bp b/tools/releasetools/merge/Android.bp index 219acf8dbe..96ec73e637 100644 --- a/tools/releasetools/merge/Android.bp +++ b/tools/releasetools/merge/Android.bp @@ -50,6 +50,7 @@ python_binary_host { "releasetools_ota_from_target_files", ], required: [ + "apexd_host", "checkvintf", "host_init_verifier", "secilc", diff --git a/tools/releasetools/merge/merge_dexopt.py b/tools/releasetools/merge/merge_dexopt.py index 1dd591b743..1c0c7433e5 100644 --- a/tools/releasetools/merge/merge_dexopt.py +++ b/tools/releasetools/merge/merge_dexopt.py @@ -72,7 +72,6 @@ def MergeDexopt(temp_dir, output_target_files_dir): # # system -> output/SYSTEM # vendor -> output/VENDOR - # apex -> output/SYSTEM/apex (only for flattened APEX builds) # apex/ (extracted updatable APEX) # / # ... @@ -114,68 +113,20 @@ def MergeDexopt(temp_dir, output_target_files_dir): os.path.join(output_target_files_dir, 'VENDOR'), os.path.join(temp_dir, 'vendor')) - # The directory structure for flatteded APEXes is: - # - # SYSTEM - # apex - # - # apex_manifest.pb - # apex_pubkey - # etc/ - # javalib/ - # lib/ - # lib64/ - # priv-app/ - # - # The directory structure for updatable APEXes is: - # - # SYSTEM - # apex - # com.android.adbd.apex - # com.android.appsearch.apex - # com.android.art.apex - # ... - apex_root = os.path.join(output_target_files_dir, 'SYSTEM', 'apex') + # Extract APEX. + logging.info('extracting APEX') + apex_extract_root_dir = os.path.join(temp_dir, 'apex') + os.makedirs(apex_extract_root_dir) - # Check for flattended versus updatable APEX. - if OPTIONS.framework_misc_info.get('target_flatten_apex') == 'false': - # Extract APEX. - logging.info('extracting APEX') - - apex_extract_root_dir = os.path.join(temp_dir, 'apex') - os.makedirs(apex_extract_root_dir) - - for apex in (glob.glob(os.path.join(apex_root, '*.apex')) + - glob.glob(os.path.join(apex_root, '*.capex'))): - logging.info(' apex: %s', apex) - # deapexer is in the same directory as the merge_target_files binary extracted - # from otatools.zip. - apex_json_info = subprocess.check_output(['deapexer', 'info', apex]) - logging.info(' info: %s', apex_json_info) - apex_info = json.loads(apex_json_info) - apex_name = apex_info['name'] - logging.info(' name: %s', apex_name) - - apex_extract_dir = os.path.join(apex_extract_root_dir, apex_name) - os.makedirs(apex_extract_dir) - - # deapexer uses debugfs_static, which is part of otatools.zip. - command = [ - 'deapexer', - '--debugfs_path', - 'debugfs_static', - '--fsckerofs_path', - 'fsck.erofs', - 'extract', - apex, - apex_extract_dir, - ] - logging.info(' running %s', command) - subprocess.check_call(command) - else: - # Flattened APEXes don't need to be extracted since they have the necessary - # directory structure. - os.symlink(os.path.join(apex_root), os.path.join(temp_dir, 'apex')) + command = [ + 'apexd_host', + '--system_path', + os.path.join(temp_dir, 'system'), + '--apex_path', + apex_extract_root_dir, + ] + logging.info(' running %s', command) + subprocess.check_call(command) # Modify system config to point to the tools that have been extracted. # Absolute or .. paths are not allowed by the dexpreopt_gen tool in