Use apexd_host for host-side APEX extraction
Host-side simulation of APEX activation is done by a new tool 'apexd_host'. This simplies checkvintf invocation for local builds and for target-files. For local builds, checkvintf no londer depends on $OUT/apex, a flattened view of APEXes. In fact, the build system doesn't need to install $OUT/apex. They are installed for now only for its side-effect of installing symbol files. We'd better not rely on $OUT/apex. For target-files, scanning/activating apexes are extracted and moved to the new tool. Now check_target_files_vintf is not more efficient because it doesn't copy .apex files to a temporary directory. Bug: 260358957 Bug: 288826922 Test: m (running checkvintf) # for local builds Test: m target-files-package && check_garget_files_vintf target-files.zip Test: atest releasetools_test Change-Id: Iba23f429d96f9ec31814196aa14bdbb800649218
This commit is contained in:
parent
2ac1f2fabc
commit
c9542abbbd
5 changed files with 39 additions and 134 deletions
|
@ -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 :=
|
||||
|
@ -5299,7 +5298,6 @@ INTERNAL_OTATOOLS_MODULES += \
|
|||
apex_compression_tool \
|
||||
deapexer \
|
||||
debugfs_static \
|
||||
dump_apex_info \
|
||||
fsck.erofs \
|
||||
make_erofs \
|
||||
merge_zips \
|
||||
|
|
|
@ -99,9 +99,8 @@ python_defaults {
|
|||
"releasetools_common",
|
||||
],
|
||||
required: [
|
||||
"apexd_host",
|
||||
"checkvintf",
|
||||
"deapexer",
|
||||
"dump_apex_info",
|
||||
],
|
||||
}
|
||||
|
||||
|
|
|
@ -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):
|
||||
"""
|
||||
|
|
|
@ -50,6 +50,7 @@ python_binary_host {
|
|||
"releasetools_ota_from_target_files",
|
||||
],
|
||||
required: [
|
||||
"apexd_host",
|
||||
"checkvintf",
|
||||
"host_init_verifier",
|
||||
"secilc",
|
||||
|
|
|
@ -118,42 +118,15 @@ def MergeDexopt(temp_dir, output_target_files_dir):
|
|||
apex_extract_root_dir = os.path.join(temp_dir, 'apex')
|
||||
os.makedirs(apex_extract_root_dir)
|
||||
|
||||
# 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')
|
||||
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/fsck.erofs from 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)
|
||||
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
|
||||
|
|
Loading…
Reference in a new issue