Merge changes from topic "vintf_ota_delete"

* changes:
  merge_target_files: Checks VINTF metadata of resulting target files
  Check VINTF compatibility at OTA generation time.
  releasetools: add tests for check_target_files_vintf
  Add a script to check VINTF compat of target files package.
This commit is contained in:
Yifan Hong 2019-08-28 23:19:21 +00:00 committed by Gerrit Code Review
commit bcba1cfdaf
12 changed files with 522 additions and 134 deletions

View File

@ -2698,12 +2698,19 @@ $(BUILT_ASSEMBLED_VENDOR_MANIFEST): PRIVATE_FLAGS :=
# -- Kernel version and configurations.
ifeq ($(PRODUCT_OTA_ENFORCE_VINTF_KERNEL_REQUIREMENTS),true)
intermediates := $(call intermediates-dir-for,ETC,$(notdir $(BUILT_ASSEMBLED_VENDOR_MANIFEST)))
BUILT_KERNEL_CONFIGS_FILE := $(intermediates)/kernel_configs.txt
BUILT_KERNEL_VERSION_FILE := $(intermediates)/kernel_version.txt
# BOARD_KERNEL_CONFIG_FILE and BOARD_KERNEL_VERSION can be used to override the values extracted
# from INSTALLED_KERNEL_TARGET.
ifdef BOARD_KERNEL_CONFIG_FILE
ifdef BOARD_KERNEL_VERSION
$(BUILT_ASSEMBLED_VENDOR_MANIFEST): $(BOARD_KERNEL_CONFIG_FILE)
$(BUILT_ASSEMBLED_VENDOR_MANIFEST): PRIVATE_FLAGS += --kernel $(BOARD_KERNEL_VERSION):$(BOARD_KERNEL_CONFIG_FILE)
$(BUILT_KERNEL_CONFIGS_FILE): $(BOARD_KERNEL_CONFIG_FILE)
cp $< $@
$(BUILT_KERNEL_VERSION_FILE):
echo $(BOARD_KERNEL_VERSION) > $@
my_board_extracted_kernel := true
endif # BOARD_KERNEL_VERSION
endif # BOARD_KERNEL_CONFIG_FILE
@ -2718,7 +2725,6 @@ $(warning No INSTALLED_KERNEL_TARGET is defined when PRODUCT_OTA_ENFORCE_VINTF_K
BOARD_KERNEL_VERSION manually; or (3) unsetting PRODUCT_OTA_ENFORCE_VINTF_KERNEL_REQUIREMENTS \
manually.)
else
intermediates := $(call intermediates-dir-for,ETC,$(notdir $(BUILT_ASSEMBLED_VENDOR_MANIFEST)))
# Tools for decompression that is not in PATH.
# Check $(EXTRACT_KERNEL) for decompression algorithms supported by the script.
@ -2726,29 +2732,25 @@ intermediates := $(call intermediates-dir-for,ETC,$(notdir $(BUILT_ASSEMBLED_VEN
my_decompress_tools := \
lz4:$(HOST_OUT_EXECUTABLES)/lz4 \
my_kernel_configs := $(intermediates)/kernel_configs.txt
my_kernel_version := $(intermediates)/kernel_version.txt
$(my_kernel_configs): .KATI_IMPLICIT_OUTPUTS := $(my_kernel_version)
$(my_kernel_configs): PRIVATE_KERNEL_VERSION_FILE := $(my_kernel_version)
$(my_kernel_configs): PRIVATE_DECOMPRESS_TOOLS := $(my_decompress_tools)
$(my_kernel_configs): $(foreach pair,$(my_decompress_tools),$(call word-colon,2,$(pair)))
$(my_kernel_configs): $(EXTRACT_KERNEL) $(INSTALLED_KERNEL_TARGET)
$(BUILT_KERNEL_CONFIGS_FILE): .KATI_IMPLICIT_OUTPUTS := $(BUILT_KERNEL_VERSION_FILE)
$(BUILT_KERNEL_CONFIGS_FILE): PRIVATE_DECOMPRESS_TOOLS := $(my_decompress_tools)
$(BUILT_KERNEL_CONFIGS_FILE): $(foreach pair,$(my_decompress_tools),$(call word-colon,2,$(pair)))
$(BUILT_KERNEL_CONFIGS_FILE): $(EXTRACT_KERNEL) $(INSTALLED_KERNEL_TARGET)
$< --tools $(PRIVATE_DECOMPRESS_TOOLS) --input $(INSTALLED_KERNEL_TARGET) \
--output-configs $@ \
--output-version $(PRIVATE_KERNEL_VERSION_FILE)
$(BUILT_ASSEMBLED_VENDOR_MANIFEST): $(my_kernel_configs) $(my_kernel_version)
$(BUILT_ASSEMBLED_VENDOR_MANIFEST): PRIVATE_FLAGS += --kernel $$(cat $(my_kernel_version)):$(my_kernel_configs)
--output-version $(BUILT_KERNEL_VERSION_FILE)
intermediates :=
my_kernel_configs :=
my_kernel_version :=
my_decompress_tools :=
endif # my_board_extracted_kernel
my_board_extracted_kernel :=
endif # INSTALLED_KERNEL_TARGET
$(BUILT_ASSEMBLED_VENDOR_MANIFEST): $(BUILT_KERNEL_CONFIGS_FILE) $(BUILT_KERNEL_VERSION_FILE)
$(BUILT_ASSEMBLED_VENDOR_MANIFEST): PRIVATE_FLAGS += --kernel $$(cat $(BUILT_KERNEL_VERSION_FILE)):$(BUILT_KERNEL_CONFIGS_FILE)
endif # PRODUCT_OTA_ENFORCE_VINTF_KERNEL_REQUIREMENTS
$(BUILT_ASSEMBLED_VENDOR_MANIFEST):
@ -3614,6 +3616,7 @@ INTERNAL_OTATOOLS_MODULES := \
care_map_generator \
check_ota_package_signature \
check_target_files_signatures \
check_target_files_vintf \
checkvintf \
delta_generator \
e2fsck \
@ -3846,6 +3849,13 @@ endif # BOARD_AVB_DTBO_KEY_PATH
endif # BOARD_AVB_ENABLE
endif # BOARD_PREBUILT_DTBOIMAGE
$(call dump-dynamic-partitions-info,$@)
@# VINTF checks
ifeq ($(PRODUCT_ENFORCE_VINTF_MANIFEST),true)
$(hide) echo "vintf_enforce=true" >> $@
endif
ifdef ODM_MANIFEST_SKUS
$(hide) echo "vintf_odm_manifest_skus=$(ODM_MANIFEST_SKUS)" >> $@
endif
.PHONY: misc_info
misc_info: $(INSTALLED_MISC_INFO_TARGET)
@ -4001,10 +4011,8 @@ $(BUILT_TARGET_FILES_PACKAGE): \
$(HOST_OUT_EXECUTABLES)/fs_config \
$(ADD_IMG_TO_TARGET_FILES) \
$(MAKE_RECOVERY_PATCH) \
$(BUILT_ASSEMBLED_FRAMEWORK_MANIFEST) \
$(BUILT_ASSEMBLED_VENDOR_MANIFEST) \
$(BUILT_SYSTEM_MATRIX) \
$(BUILT_VENDOR_MATRIX) \
$(BUILT_KERNEL_CONFIGS_FILE) \
$(BUILT_KERNEL_VERSION_FILE) \
| $(ACP)
@echo "Package target files: $@"
$(call create-system-vendor-symlink)
@ -4243,15 +4251,11 @@ ifdef BUILDING_SYSTEM_OTHER_IMAGE
$(hide) $(call fs_config,$(zip_root)/SYSTEM_OTHER,system/) > $(zip_root)/META/system_other_filesystem_config.txt
endif
@# Metadata for compatibility verification.
$(hide) cp $(BUILT_SYSTEM_MATRIX) $(zip_root)/META/system_matrix.xml
ifdef BUILT_ASSEMBLED_FRAMEWORK_MANIFEST
$(hide) cp $(BUILT_ASSEMBLED_FRAMEWORK_MANIFEST) $(zip_root)/META/system_manifest.xml
ifdef BUILT_KERNEL_CONFIGS_FILE
$(hide) cp $(BUILT_KERNEL_CONFIGS_FILE) $(zip_root)/META/kernel_configs.txt
endif
ifdef BUILT_ASSEMBLED_VENDOR_MANIFEST
$(hide) cp $(BUILT_ASSEMBLED_VENDOR_MANIFEST) $(zip_root)/META/vendor_manifest.xml
endif
ifdef BUILT_VENDOR_MATRIX
$(hide) cp $(BUILT_VENDOR_MATRIX) $(zip_root)/META/vendor_matrix.xml
ifdef BUILT_KERNEL_VERSION_FILE
$(hide) cp $(BUILT_KERNEL_VERSION_FILE) $(zip_root)/META/kernel_version.txt
endif
ifneq ($(BOARD_SUPER_PARTITION_GROUPS),)
$(hide) echo "super_partition_groups=$(BOARD_SUPER_PARTITION_GROUPS)" > $(zip_root)/META/dynamic_partitions_info.txt

View File

@ -75,6 +75,19 @@ python_defaults {
],
}
python_defaults {
name: "releasetools_check_target_files_vintf_defaults",
srcs: [
"check_target_files_vintf.py",
],
libs: [
"releasetools_common",
],
required: [
"checkvintf",
],
}
python_defaults {
name: "releasetools_ota_from_target_files_defaults",
srcs: [
@ -83,6 +96,7 @@ python_defaults {
"target_files_diff.py",
],
libs: [
"releasetools_check_target_files_vintf",
"releasetools_common",
"releasetools_verity_utils",
],
@ -142,6 +156,14 @@ python_library_host {
],
}
python_library_host {
name: "releasetools_check_target_files_vintf",
defaults: [
"releasetools_library_defaults",
"releasetools_check_target_files_vintf_defaults",
],
}
python_library_host {
name: "releasetools_common",
defaults: ["releasetools_library_defaults"],
@ -265,6 +287,14 @@ python_binary_host {
],
}
python_binary_host {
name: "check_target_files_vintf",
defaults: [
"releasetools_binary_defaults",
"releasetools_check_target_files_vintf_defaults"
],
}
python_binary_host {
name: "img_from_target_files",
defaults: [
@ -305,6 +335,7 @@ python_binary_host {
libs: [
"releasetools_add_img_to_target_files",
"releasetools_build_super_image",
"releasetools_check_target_files_vintf",
"releasetools_common",
"releasetools_img_from_target_files",
"releasetools_ota_from_target_files",
@ -396,13 +427,14 @@ python_defaults {
"releasetools_apex_utils",
"releasetools_build_image",
"releasetools_build_super_image",
"releasetools_check_target_files_vintf",
"releasetools_common",
"releasetools_img_from_target_files",
"releasetools_ota_from_target_files",
"releasetools_verity_utils",
],
data: [
"testdata/*",
"testdata/**/*",
],
required: [
"otatools",

View File

@ -0,0 +1,232 @@
#!/usr/bin/env python
#
# Copyright (C) 2019 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
Check VINTF compatibility from a target files package.
Usage: check_target_files_vintf target_files
target_files can be a ZIP file or an extracted target files directory.
"""
import logging
import subprocess
import sys
import os
import zipfile
import common
logger = logging.getLogger(__name__)
OPTIONS = common.OPTIONS
# Keys are paths that VINTF searches. Must keep in sync with libvintf's search
# paths (VintfObject.cpp).
# These paths are stored in different directories in target files package, so
# we have to search for the correct path and tell checkvintf to remap them.
DIR_SEARCH_PATHS = {
'/system': ('SYSTEM',),
'/vendor': ('VENDOR', 'SYSTEM/vendor'),
'/product': ('PRODUCT', 'SYSTEM/product'),
'/odm': ('ODM', 'VENDOR/odm'),
}
UNZIP_PATTERN = ['META/*', '*/build.prop']
def GetDirmap(input_tmp):
dirmap = {}
for device_path, target_files_rel_paths in DIR_SEARCH_PATHS.items():
for target_files_rel_path in target_files_rel_paths:
target_files_path = os.path.join(input_tmp, target_files_rel_path)
if os.path.isdir(target_files_path):
dirmap[device_path] = target_files_path
break
if device_path not in dirmap:
raise ValueError("Can't determine path for device path " + device_path +
". Searched the following:" +
("\n".join(target_files_rel_paths)))
return dirmap
def GetArgsForSkus(info_dict):
skus = info_dict.get('vintf_odm_manifest_skus', '').strip().split()
if not skus:
logger.info("ODM_MANIFEST_SKUS is not defined. Check once without SKUs.")
skus = ['']
return [['--property', 'ro.boot.product.hardware.sku=' + sku]
for sku in skus]
def GetArgsForShippingApiLevel(info_dict):
shipping_api_level = info_dict['vendor.build.prop'].get(
'ro.product.first_api_level')
if not shipping_api_level:
logger.warning('Cannot determine ro.product.first_api_level')
return []
return ['--property', 'ro.product.first_api_level=' + shipping_api_level]
def GetArgsForKernel(input_tmp):
version_path = os.path.join(input_tmp, 'META/kernel_version.txt')
config_path = os.path.join(input_tmp, 'META/kernel_configs.txt')
if not os.path.isfile(version_path) or not os.path.isfile(config_path):
logger.info('Skipping kernel config checks because ' +
'PRODUCT_OTA_ENFORCE_VINTF_KERNEL_REQUIREMENTS is not set')
return []
with open(version_path) as f:
version = f.read().strip()
return ['--kernel', '{}:{}'.format(version, config_path)]
def CheckVintfFromExtractedTargetFiles(input_tmp, info_dict=None):
"""
Checks VINTF metadata of an extracted target files directory.
Args:
inp: path to the directory that contains the extracted target files archive.
info_dict: The build-time info dict. If None, it will be loaded from inp.
Returns:
True if VINTF check is skipped or compatible, False if incompatible. Raise
a RuntimeError if any error occurs.
"""
if info_dict is None:
info_dict = common.LoadInfoDict(input_tmp)
if info_dict.get('vintf_enforce') != 'true':
logger.warning('PRODUCT_ENFORCE_VINTF_MANIFEST is not set, skipping checks')
return True
dirmap = GetDirmap(input_tmp)
args_for_skus = GetArgsForSkus(info_dict)
shipping_api_level_args = GetArgsForShippingApiLevel(info_dict)
kernel_args = GetArgsForKernel(input_tmp)
common_command = [
'checkvintf',
'--check-compat',
]
for device_path, real_path in dirmap.items():
common_command += ['--dirmap', '{}:{}'.format(device_path, real_path)]
common_command += kernel_args
common_command += shipping_api_level_args
success = True
for sku_args in args_for_skus:
command = common_command + sku_args
proc = common.Run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = proc.communicate()
if proc.returncode == 0:
logger.info("Command `%s` returns 'compatible'", ' '.join(command))
elif out.strip() == "INCOMPATIBLE":
logger.info("Command `%s` returns 'incompatible'", ' '.join(command))
success = False
else:
raise common.ExternalError(
"Failed to run command '{}' (exit code {}):\nstdout:{}\nstderr:{}"
.format(' '.join(command), proc.returncode, out, err))
logger.info("stdout: %s", out)
logger.info("stderr: %s", err)
return success
def GetVintfFileList():
"""
Returns a list of VINTF metadata files that should be read from a target files
package before executing checkvintf.
"""
def PathToPatterns(path):
if path[-1] == '/':
path += '*'
for device_path, target_files_rel_paths in DIR_SEARCH_PATHS.items():
if path.startswith(device_path):
suffix = path[len(device_path):]
return [rel_path + suffix for rel_path in target_files_rel_paths]
raise RuntimeError('Unrecognized path from checkvintf --dump-file-list: ' +
path)
out = common.RunAndCheckOutput(['checkvintf', '--dump-file-list'])
paths = out.strip().split('\n')
paths = sum((PathToPatterns(path) for path in paths if path), [])
return paths
def CheckVintfFromTargetFiles(inp, info_dict=None):
"""
Checks VINTF metadata of a target files zip.
Args:
inp: path to the target files archive.
info_dict: The build-time info dict. If None, it will be loaded from inp.
Returns:
True if VINTF check is skipped or compatible, False if incompatible. Raise
a RuntimeError if any error occurs.
"""
input_tmp = common.UnzipTemp(inp, GetVintfFileList() + UNZIP_PATTERN)
return CheckVintfFromExtractedTargetFiles(input_tmp, info_dict)
def CheckVintf(inp, info_dict=None):
"""
Checks VINTF metadata of a target files zip or extracted target files
directory.
Args:
inp: path to the (possibly extracted) target files archive.
info_dict: The build-time info dict. If None, it will be loaded from inp.
Returns:
True if VINTF check is skipped or compatible, False if incompatible. Raise
a RuntimeError if any error occurs.
"""
if os.path.isdir(inp):
logger.info('Checking VINTF compatibility extracted target files...')
return CheckVintfFromExtractedTargetFiles(inp, info_dict)
if zipfile.is_zipfile(inp):
logger.info('Checking VINTF compatibility target files...')
return CheckVintfFromTargetFiles(inp, info_dict)
raise ValueError('{} is not a valid directory or zip file'.format(inp))
def main(argv):
args = common.ParseOptions(argv, __doc__)
if len(args) != 1:
common.Usage(__doc__)
sys.exit(1)
common.InitLogging()
if not CheckVintf(args[0]):
sys.exit(1)
if __name__ == '__main__':
try:
common.CloseInheritedPipes()
main(sys.argv[1:])
except common.ExternalError:
logger.exception('\n ERROR:\n')
sys.exit(1)
finally:
common.Cleanup()

View File

@ -87,6 +87,7 @@ import zipfile
import add_img_to_target_files
import build_super_image
import check_target_files_vintf
import common
import img_from_target_files
import ota_from_target_files
@ -117,8 +118,6 @@ DEFAULT_FRAMEWORK_ITEM_LIST = (
'META/apkcerts.txt',
'META/filesystem_config.txt',
'META/root_filesystem_config.txt',
'META/system_manifest.xml',
'META/system_matrix.xml',
'META/update_engine_config.txt',
'PRODUCT/*',
'ROOT/*',
@ -163,8 +162,6 @@ DEFAULT_VENDOR_ITEM_LIST = (
'META/otakeys.txt',
'META/releasetools.py',
'META/vendor_filesystem_config.txt',
'META/vendor_manifest.xml',
'META/vendor_matrix.xml',
'BOOT/*',
'DATA/*',
'ODM/*',
@ -910,6 +907,9 @@ def merge_target_files(temp_dir, framework_target_files, framework_item_list,
vendor_target_files, vendor_item_list, framework_misc_info_keys,
rebuild_recovery)
if not check_target_files_vintf.CheckVintf(output_target_files_temp_dir):
raise RuntimeError("Incompatible VINTF metadata")
generate_images(output_target_files_temp_dir, rebuild_recovery)
generate_super_empty_image(output_target_files_temp_dir, output_super_empty)

View File

@ -72,7 +72,7 @@ Common options that apply to both of non-A/B and A/B OTAs
--skip_postinstall is implied.
--skip_compatibility_check
Skip adding the compatibility package to the generated OTA package.
Skip checking compatibility of the input target files package.
--output_metadata_path
Write a copy of the metadata to a separate file. Therefore, users can
@ -189,9 +189,9 @@ import shlex
import shutil
import struct
import sys
import tempfile
import zipfile
import check_target_files_vintf
import common
import edify_generator
import verity_utils
@ -723,20 +723,15 @@ def HasPartition(target_files_zip, partition):
return False
def HasVendorPartition(target_files_zip):
return HasPartition(target_files_zip, "vendor")
def HasTrebleEnabled(target_files, target_info):
def HasVendorPartition(target_files):
if os.path.isdir(target_files):
return os.path.isdir(os.path.join(target_files, "VENDOR"))
if zipfile.is_zipfile(target_files):
return HasPartition(zipfile.ZipFile(target_files), "vendor")
raise ValueError("Unknown target_files argument")
def HasProductPartition(target_files_zip):
return HasPartition(target_files_zip, "product")
def HasOdmPartition(target_files_zip):
return HasPartition(target_files_zip, "odm")
def HasTrebleEnabled(target_files_zip, target_info):
return (HasVendorPartition(target_files_zip) and
return (HasVendorPartition(target_files) and
target_info.GetBuildProp("ro.treble.enabled") == "true")
@ -761,74 +756,23 @@ def WriteFingerprintAssertion(script, target_info, source_info):
source_info.GetBuildProp("ro.build.thumbprint"))
def AddCompatibilityArchiveIfTrebleEnabled(target_zip, output_zip, target_info,
source_info=None):
"""Adds compatibility info into the output zip if it's Treble-enabled target.
def CheckVintfIfTrebleEnabled(target_files, target_info):
"""Checks compatibility info of the input target files.
Metadata used for on-device compatibility verification is retrieved from
target_zip then added to compatibility.zip which is added to the output_zip
archive.
Metadata used for compatibility verification is retrieved from target_zip.
Compatibility archive should only be included for devices that have enabled
Compatibility should only be checked for devices that have enabled
Treble support.
Args:
target_zip: Zip file containing the source files to be included for OTA.
output_zip: Zip file that will be sent for OTA.
target_files: Path to zip file containing the source files to be included
for OTA. Can also be the path to extracted directory.
target_info: The BuildInfo instance that holds the target build info.
source_info: The BuildInfo instance that holds the source build info, if
generating an incremental OTA; None otherwise.
"""
def AddCompatibilityArchive(framework_updated, device_updated):
"""Adds compatibility info based on update status of both sides of Treble
boundary.
Args:
framework_updated: If True, the system / product image will be updated
and therefore their metadata should be included.
device_updated: If True, the vendor / odm image will be updated and
therefore their metadata should be included.
"""
# Determine what metadata we need. Files are names relative to META/.
compatibility_files = []
device_metadata = ("vendor_manifest.xml", "vendor_matrix.xml")
framework_metadata = ("system_manifest.xml", "system_matrix.xml")
if device_updated:
compatibility_files += device_metadata
if framework_updated:
compatibility_files += framework_metadata
# Create new archive.
compatibility_archive = tempfile.NamedTemporaryFile()
compatibility_archive_zip = zipfile.ZipFile(
compatibility_archive, "w", compression=zipfile.ZIP_DEFLATED)
# Add metadata.
for file_name in compatibility_files:
target_file_name = "META/" + file_name
if target_file_name in target_zip.namelist():
data = target_zip.read(target_file_name)
common.ZipWriteStr(compatibility_archive_zip, file_name, data)
# Ensure files are written before we copy into output_zip.
compatibility_archive_zip.close()
# Only add the archive if we have any compatibility info.
if compatibility_archive_zip.namelist():
common.ZipWrite(output_zip, compatibility_archive.name,
arcname="compatibility.zip",
compress_type=zipfile.ZIP_STORED)
def FingerprintChanged(source_fp, target_fp):
if source_fp is None or target_fp is None:
return True
return source_fp != target_fp
# Will only proceed if the target has enabled the Treble support (as well as
# having a /vendor partition).
if not HasTrebleEnabled(target_zip, target_info):
if not HasTrebleEnabled(target_files, target_info):
return
# Skip adding the compatibility package as a workaround for b/114240221. The
@ -836,28 +780,8 @@ def AddCompatibilityArchiveIfTrebleEnabled(target_zip, output_zip, target_info,
if OPTIONS.skip_compatibility_check:
return
# Full OTA carries the info for system/vendor/product/odm
if source_info is None:
AddCompatibilityArchive(True, True)
return
source_fp = source_info.fingerprint
target_fp = target_info.fingerprint
system_updated = source_fp != target_fp
# other build fingerprints could be possibly blacklisted at build time. For
# such a case, we consider those images being changed.
vendor_updated = FingerprintChanged(source_info.vendor_fingerprint,
target_info.vendor_fingerprint)
product_updated = HasProductPartition(target_zip) and \
FingerprintChanged(source_info.product_fingerprint,
target_info.product_fingerprint)
odm_updated = HasOdmPartition(target_zip) and \
FingerprintChanged(source_info.odm_fingerprint,
target_info.odm_fingerprint)
AddCompatibilityArchive(system_updated or product_updated,
vendor_updated or odm_updated)
if not check_target_files_vintf.CheckVintf(target_files, target_info):
raise RuntimeError("VINTF compatibility check failed")
def GetBlockDifferences(target_zip, source_zip, target_info, source_info,
@ -1068,7 +992,7 @@ else if get_stage("%(bcb_dev)s") == "3/3" then
progress=progress_dict.get(block_diff.partition),
write_verify_script=OPTIONS.verify)
AddCompatibilityArchiveIfTrebleEnabled(input_zip, output_zip, target_info)
CheckVintfIfTrebleEnabled(OPTIONS.input_tmp, target_info)
boot_img = common.GetBootableImage(
"boot.img", "boot.img", OPTIONS.input_tmp, "BOOT")
@ -1643,8 +1567,7 @@ def WriteBlockIncrementalOTAPackage(target_zip, source_zip, output_file):
source_info=source_info,
device_specific=device_specific)
AddCompatibilityArchiveIfTrebleEnabled(
target_zip, output_zip, target_info, source_info)
CheckVintfIfTrebleEnabled(OPTIONS.target_tmp, target_info)
# Assertions (e.g. device properties check).
target_info.WriteDeviceAssertions(script, OPTIONS.oem_no_mount)
@ -2079,11 +2002,10 @@ def GenerateAbOtaPackage(target_file, output_file, source_file=None):
else:
logger.warning("Cannot find care map file in target_file package")
AddCompatibilityArchiveIfTrebleEnabled(
target_zip, output_zip, target_info, source_info)
common.ZipClose(target_zip)
CheckVintfIfTrebleEnabled(target_file, target_info)
# We haven't written the metadata entry yet, which will be handled in
# FinalizeMetadata().
common.ZipClose(output_zip)

View File

@ -0,0 +1,143 @@
#
# Copyright (C) 2019 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the 'License');
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an 'AS IS' BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import os.path
import common
import test_utils
from check_target_files_vintf import CheckVintf
# A skeleton target files directory structure. This is VINTF compatible.
SKELETON_TARGET_FILE_STRUCTURE = {
# Empty files
'PRODUCT/build.prop': '',
'PRODUCT/etc/build.prop': '',
'VENDOR/etc/build.prop': '',
'ODM/build.prop': '',
'ODM/etc/build.prop': '',
'RECOVERY/RAMDISK/etc/recovery.fstab': '',
'SYSTEM/build.prop': '',
'SYSTEM/etc/build.prop': '',
'SYSTEM_EXT/build.prop': '',
'SYSTEM_EXT/etc/build.prop': '',
# Non-empty files
'SYSTEM/compatibility_matrix.xml':"""
<compatibility-matrix version="1.0" type="framework">
<sepolicy>
<sepolicy-version>0.0</sepolicy-version>
<kernel-sepolicy-version>0</kernel-sepolicy-version>
</sepolicy>
</compatibility-matrix>""",
'SYSTEM/manifest.xml':
'<manifest version="1.0" type="framework" />',
'VENDOR/build.prop': 'ro.product.first_api_level=29\n',
'VENDOR/compatibility_matrix.xml':
'<compatibility-matrix version="1.0" type="device" />',
'VENDOR/manifest.xml':
'<manifest version="1.0" type="device"/>',
'META/misc_info.txt':
'recovery_api_version=3\nfstab_version=2\nvintf_enforce=true\n',
}
def write_string_to_file(content, path, mode='w'):
if not os.path.isdir(os.path.dirname(path)):
os.makedirs(os.path.dirname(path))
with open(path, mode=mode) as f:
f.write(content)
class CheckTargetFilesVintfTest(test_utils.ReleaseToolsTestCase):
def setUp(self):
self.testdata_dir = test_utils.get_testdata_dir()
def prepare_test_dir(self, test_delta_rel_path):
test_delta_dir = os.path.join(self.testdata_dir, test_delta_rel_path)
test_dir = common.MakeTempDir(prefix='check_target_files_vintf')
# Create a skeleton directory structure of target files
for rel_path, content in SKELETON_TARGET_FILE_STRUCTURE.items():
write_string_to_file(content, os.path.join(test_dir, rel_path))
# Overwrite with files from test_delta_rel_path
for root, _, files in os.walk(test_delta_dir):
rel_root = os.path.relpath(root, test_delta_dir)
for f in files:
output_file = os.path.join(test_dir, rel_root, f)
with open(os.path.join(root, f)) as inp:
write_string_to_file(inp.read(), output_file)
return test_dir
@test_utils.SkipIfExternalToolsUnavailable()
def test_CheckVintf_sanity(self):
msg = 'Sanity check with skeleton target files failed.'
test_dir = self.prepare_test_dir('does-not-exist')
self.assertTrue(CheckVintf(test_dir), msg=msg)
@test_utils.SkipIfExternalToolsUnavailable()
def test_CheckVintf_matrix_incompat(self):
msg = 'vintf/matrix_incompat should be incompatible because sepolicy ' \
'version fails to match'
test_dir = self.prepare_test_dir('vintf/matrix_incompat')
self.assertFalse(CheckVintf(test_dir), msg=msg)
@test_utils.SkipIfExternalToolsUnavailable()
def test_CheckVintf_kernel_compat(self):
msg = 'vintf/kernel with 4.14.1 kernel version should be compatible'
test_dir = self.prepare_test_dir('vintf/kernel')
write_string_to_file('', os.path.join(test_dir, 'META/kernel_configs.txt'))
write_string_to_file('4.14.1',
os.path.join(test_dir, 'META/kernel_version.txt'))
self.assertTrue(CheckVintf(test_dir), msg=msg)
@test_utils.SkipIfExternalToolsUnavailable()
def test_CheckVintf_kernel_incompat(self):
msg = 'vintf/kernel with 4.14.0 kernel version should be incompatible ' \
'because 4.14.1 kernel version is required'
test_dir = self.prepare_test_dir('vintf/kernel')
write_string_to_file('', os.path.join(test_dir, 'META/kernel_configs.txt'))
write_string_to_file('4.14.0',
os.path.join(test_dir, 'META/kernel_version.txt'))
self.assertFalse(CheckVintf(test_dir), msg=msg)
@test_utils.SkipIfExternalToolsUnavailable()
def test_CheckVintf_sku_compat(self):
msg = 'vintf/sku_compat should be compatible because ' \
'ODM/etc/vintf/manifest_sku.xml has the required HALs'
test_dir = self.prepare_test_dir('vintf/sku_compat')
write_string_to_file('vintf_odm_manifest_skus=sku',
os.path.join(test_dir, 'META/misc_info.txt'), mode='a')
self.assertTrue(CheckVintf(test_dir), msg=msg)
@test_utils.SkipIfExternalToolsUnavailable()
def test_CheckVintf_sku_incompat(self):
msg = 'vintf/sku_compat should be compatible because ' \
'ODM/etc/vintf/manifest_sku.xml does not have the required HALs'
test_dir = self.prepare_test_dir('vintf/sku_incompat')
write_string_to_file('vintf_odm_manifest_skus=sku',
os.path.join(test_dir, 'META/misc_info.txt'), mode='a')
self.assertFalse(CheckVintf(test_dir), msg=msg)
@test_utils.SkipIfExternalToolsUnavailable()
def test_CheckVintf_bad_xml(self):
test_dir = self.prepare_test_dir('does-not-exist')
write_string_to_file('not an XML',
os.path.join(test_dir, 'VENDOR/manifest.xml'))
# Should raise an error because a file has invalid format.
self.assertRaises(common.ExternalError, CheckVintf, test_dir)

View File

@ -0,0 +1,7 @@
<compatibility-matrix version="1.0" type="framework">
<kernel version="4.14.1" />
<sepolicy>
<sepolicy-version>0.0</sepolicy-version>
<kernel-sepolicy-version>0</kernel-sepolicy-version>
</sepolicy>
</compatibility-matrix>

View File

@ -0,0 +1,6 @@
<compatibility-matrix version="1.0" type="framework">
<sepolicy>
<sepolicy-version>1.0</sepolicy-version>
<kernel-sepolicy-version>0</kernel-sepolicy-version>
</sepolicy>
</compatibility-matrix>

View File

@ -0,0 +1,7 @@
<manifest version="1.0" type="device">
<hal format="hidl">
<name>foo</name>
<transport>hwbinder</transport>
<fqname>@1.0::IFoo/default</fqname>
</hal>
</manifest>

View File

@ -0,0 +1,14 @@
<compatibility-matrix version="1.0" type="framework">
<hal format="hidl" optional="false">
<name>foo</name>
<version>1.0</version>
<interface>
<name>IFoo</name>
<instance>default</instance>
</interface>
</hal>
<sepolicy>
<sepolicy-version>0.0</sepolicy-version>
<kernel-sepolicy-version>0</kernel-sepolicy-version>
</sepolicy>
</compatibility-matrix>

View File

@ -0,0 +1,7 @@
<manifest version="1.0" type="device">
<hal format="hidl">
<name>foo</name>
<transport>hwbinder</transport>
<fqname>@1.0::IFoo/default</fqname>
</hal>
</manifest>

View File

@ -0,0 +1,14 @@
<compatibility-matrix version="1.0" type="framework">
<hal format="hidl" optional="false">
<name>foo</name>
<version>1.1</version>
<interface>
<name>IFoo</name>
<instance>default</instance>
</interface>
</hal>
<sepolicy>
<sepolicy-version>0.0</sepolicy-version>
<kernel-sepolicy-version>0</kernel-sepolicy-version>
</sepolicy>
</compatibility-matrix>