Allow ota_from_target_file to work entirely on directories

When building android, build system will first zip target_file directory
into a .zip file, and then invoke ota_from_target_files. We
ota_from_target_files can work directly on top of directories, we can
parallelize OTA generation and target_file zipping, making builds
faster.

Bug: 227848550
Bug: 277028723
Test: th
Change-Id: Id72bd7cca708af0e1bae2db754f39b27777cd601
This commit is contained in:
Kelvin Zhang
2023-04-17 16:38:08 -07:00
parent 67ca3c05c7
commit 9dbe2ce40f
3 changed files with 79 additions and 32 deletions

View File

@@ -22,7 +22,8 @@ import zipfile
import ota_metadata_pb2
import common
from common import (ZipDelete, ZipClose, OPTIONS, MakeTempFile,
import fnmatch
from common import (ZipDelete, DoesInputFileContain, ReadBytesFromInputFile, OPTIONS, MakeTempFile,
ZipWriteStr, BuildInfo, LoadDictionaryFromFile,
SignFile, PARTITIONS_WITH_BUILD_PROP, PartitionBuildProps,
GetRamdiskFormat, ParseUpdateEngineConfig)
@@ -44,7 +45,8 @@ OPTIONS.boot_variable_file = None
METADATA_NAME = 'META-INF/com/android/metadata'
METADATA_PROTO_NAME = 'META-INF/com/android/metadata.pb'
UNZIP_PATTERN = ['IMAGES/*', 'META/*', 'OTA/*', 'RADIO/*']
UNZIP_PATTERN = ['IMAGES/*', 'META/*', 'OTA/*',
'RADIO/*', '*/build.prop', '*/default.prop', '*/build.default', "*/etc/vintf/*"]
SECURITY_PATCH_LEVEL_PROP_NAME = "ro.build.version.security_patch"
@@ -626,12 +628,10 @@ def ConstructOtaApexInfo(target_zip, source_file=None):
"""If applicable, add the source version to the apex info."""
def _ReadApexInfo(input_zip):
if "META/apex_info.pb" not in input_zip.namelist():
if not DoesInputFileContain(input_zip, "META/apex_info.pb"):
logger.warning("target_file doesn't contain apex_info.pb %s", input_zip)
return None
with input_zip.open("META/apex_info.pb", "r") as zfp:
return zfp.read()
return ReadBytesFromInputFile(input_zip, "META/apex_info.pb")
target_apex_string = _ReadApexInfo(target_zip)
# Return early if the target apex info doesn't exist or is empty.
@@ -727,7 +727,7 @@ def ExtractTargetFiles(path: str):
logger.info("target files %s is already extracted", path)
return path
extracted_dir = common.MakeTempDir("target_files")
common.UnzipToDir(path, extracted_dir, UNZIP_PATTERN)
common.UnzipToDir(path, extracted_dir, UNZIP_PATTERN + [""])
return extracted_dir
@@ -1040,3 +1040,27 @@ class AbOtaPropertyFiles(StreamingPropertyFiles):
assert metadata_total <= payload_size
return (payload_offset, metadata_total)
def Fnmatch(filename, pattersn):
return any([fnmatch.fnmatch(filename, pat) for pat in pattersn])
def CopyTargetFilesDir(input_dir):
output_dir = common.MakeTempDir("target_files")
shutil.copytree(os.path.join(input_dir, "IMAGES"), os.path.join(
output_dir, "IMAGES"), dirs_exist_ok=True)
shutil.copytree(os.path.join(input_dir, "META"), os.path.join(
output_dir, "META"), dirs_exist_ok=True)
for (dirpath, _, filenames) in os.walk(input_dir):
for filename in filenames:
path = os.path.join(dirpath, filename)
relative_path = path.removeprefix(input_dir).removeprefix("/")
if not Fnmatch(relative_path, UNZIP_PATTERN):
continue
if filename.endswith(".prop") or filename == "prop.default" or "/etc/vintf/" in relative_path:
target_path = os.path.join(
output_dir, relative_path)
os.makedirs(os.path.dirname(target_path), exist_ok=True)
shutil.copy(path, target_path)
return output_dir