Merge changes from topic "apexd_host"

* changes:
  Use apexd_host for host-side APEX extraction
  Deprecate flattened apexes
This commit is contained in:
Jooyung Han 2023-06-28 17:36:15 +00:00 committed by Gerrit Code Review
commit c269ec3538
5 changed files with 43 additions and 160 deletions

View file

@ -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 \

View file

@ -99,9 +99,8 @@ python_defaults {
"releasetools_common",
],
required: [
"apexd_host",
"checkvintf",
"deapexer",
"dump_apex_info",
],
}

View file

@ -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):
"""

View file

@ -50,6 +50,7 @@ python_binary_host {
"releasetools_ota_from_target_files",
],
required: [
"apexd_host",
"checkvintf",
"host_init_verifier",
"secilc",

View file

@ -72,7 +72,6 @@ def MergeDexopt(temp_dir, output_target_files_dir):
# <contents of vendor dexpreopt_config.zip>
# system -> output/SYSTEM
# vendor -> output/VENDOR
# apex -> output/SYSTEM/apex (only for flattened APEX builds)
# apex/ (extracted updatable APEX)
# <apex 1>/
# ...
@ -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 name, e.g., com.android.wifi>
# 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