aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHsin-Yi Chen <hsinyichen@google.com>2022-04-13 10:41:58 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2022-04-13 10:41:58 +0000
commit1ce4850f6b6cce08671f6e6a45b3baa82784460a (patch)
treee47c3e3e7542720fe7623a6d7fd5a563870c8c77
parentf5d75f9e4b602833370b75628d8f00db8fadd2c3 (diff)
parenta589f388b20252416abfcc6dec1896bd6a334834 (diff)
downloadacloud-1ce4850f6b6cce08671f6e6a45b3baa82784460a.tar.gz
Merge "Support local cuttlefish instances with mixed vendor_boot.img" am: eb3c30ec2f am: a589f388b2
Original change: https://android-review.googlesource.com/c/platform/tools/acloud/+/2059349 Change-Id: Ie8a36233798aa7183862054de7adfc1b8814a6ee Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
-rw-r--r--create/create_common.py6
-rw-r--r--create/create_common_test.py5
-rw-r--r--create/local_image_local_instance.py56
-rw-r--r--create/local_image_local_instance_test.py93
-rw-r--r--create/remote_image_local_instance.py3
-rw-r--r--internal/lib/cvd_utils.py34
-rw-r--r--internal/lib/cvd_utils_test.py2
7 files changed, 120 insertions, 79 deletions
diff --git a/create/create_common.py b/create/create_common.py
index 1d1a5212..a5694d7b 100644
--- a/create/create_common.py
+++ b/create/create_common.py
@@ -146,7 +146,7 @@ def GetCvdHostPackage(package_path=None):
'\n'.join(dirs_to_check))
-def FindLocalImage(path, default_name_pattern):
+def FindLocalImage(path, default_name_pattern, raise_error=True):
"""Find an image file in the given path.
Args:
@@ -165,7 +165,9 @@ def FindLocalImage(path, default_name_pattern):
names = [name for name in os.listdir(path) if
re.fullmatch(default_name_pattern, name)]
if not names:
- raise errors.GetLocalImageError("No image in %s." % path)
+ if raise_error:
+ raise errors.GetLocalImageError("No image in %s." % path)
+ return None
if len(names) != 1:
raise errors.GetLocalImageError("More than one image in %s: %s" %
(path, " ".join(names)))
diff --git a/create/create_common_test.py b/create/create_common_test.py
index 0caa97a9..14503e6a 100644
--- a/create/create_common_test.py
+++ b/create/create_common_test.py
@@ -152,11 +152,14 @@ class CreateCommonTest(driver_test_lib.BaseDriverTest):
self.assertEqual("/dir/name",
create_common.FindLocalImage("/dir/", "name"))
+
+ self.assertIsNone(create_common.FindLocalImage("/dir", "not_exist",
+ raise_error=False))
with self.assertRaises(errors.GetLocalImageError):
create_common.FindLocalImage("/dir", "not_exist")
with self.assertRaises(errors.GetLocalImageError):
- create_common.FindLocalImage("/dir", "name.?")
+ create_common.FindLocalImage("/dir", "name.?", raise_error=False)
@mock.patch.object(utils, "Decompress")
def testDownloadRemoteArtifact(self, mock_decompress):
diff --git a/create/local_image_local_instance.py b/create/local_image_local_instance.py
index c4c585fb..c5913fb4 100644
--- a/create/local_image_local_instance.py
+++ b/create/local_image_local_instance.py
@@ -62,6 +62,7 @@ from acloud import errors
from acloud.create import base_avd_create
from acloud.create import create_common
from acloud.internal import constants
+from acloud.internal.lib import cvd_utils
from acloud.internal.lib import ota_tools
from acloud.internal.lib import utils
from acloud.internal.lib.adb_tools import AdbTools
@@ -73,13 +74,6 @@ from acloud.setup import mkcert
logger = logging.getLogger(__name__)
-# The boot image name pattern corresponds to the use cases:
-# - In a cuttlefish build environment, ANDROID_PRODUCT_OUT conatins boot.img
-# and boot-debug.img. The former is the default boot image. The latter is not
-# useful for cuttlefish.
-# - In an officially released GKI (Generic Kernel Image) package, the image
-# name is boot-<kernel version>.img.
-_BOOT_IMAGE_NAME_PATTERN = r"boot(-[\d.]+)?\.img"
_SYSTEM_IMAGE_NAME_PATTERN = r"system\.img"
_MISC_INFO_FILE_NAME = "misc_info.txt"
_TARGET_FILES_IMAGES_DIR_NAME = "IMAGES"
@@ -97,6 +91,7 @@ _CMD_LAUNCH_CVD_WEBRTC_ARGS = " -start_webrtc=true"
_CMD_LAUNCH_CVD_VNC_ARG = " -start_vnc_server=true"
_CMD_LAUNCH_CVD_SUPER_IMAGE_ARG = " -super_image=%s"
_CMD_LAUNCH_CVD_BOOT_IMAGE_ARG = " -boot_image=%s"
+_CMD_LAUNCH_CVD_VENDOR_BOOT_IMAGE_ARG = " -vendor_boot_image=%s"
_CMD_LAUNCH_CVD_NO_ADB_ARG = " -run_adb_connector=false"
# Connect the OpenWrt device via console file.
_CMD_LAUNCH_CVD_CONSOLE_ARG = " -console=true"
@@ -127,7 +122,7 @@ _CONFIRM_RELAUNCH = ("\nCuttlefish AVD[id:%d] is already running. \n"
ArtifactPaths = collections.namedtuple(
"ArtifactPaths",
["image_dir", "host_bins", "host_artifacts", "misc_info", "ota_tools_dir",
- "system_image", "boot_image"])
+ "system_image", "boot_image", "vendor_boot_image"])
class LocalImageLocalInstance(base_avd_create.BaseAVDCreate):
@@ -236,8 +231,6 @@ class LocalImageLocalInstance(base_avd_create.BaseAVDCreate):
runtime_dir = instance.GetLocalInstanceRuntimeDir(local_instance_id)
# TODO(b/168171781): cvd_status of list/delete via the symbolic.
self.PrepareLocalCvdToolsLink(cvd_home_dir, artifact_paths.host_bins)
- cvd_path = os.path.join(artifact_paths.host_bins, "bin",
- constants.CMD_CVD)
if avd_spec.mkcert and avd_spec.connect_webrtc:
self._TrustCertificatesForWebRTC(artifact_paths.host_artifacts)
@@ -246,15 +239,13 @@ class LocalImageLocalInstance(base_avd_create.BaseAVDCreate):
hw_property = avd_spec.hw_property
config = self._GetConfigFromAndroidInfo(
os.path.join(artifact_paths.image_dir, constants.ANDROID_INFO_FILE))
- cmd = self.PrepareLaunchCVDCmd(cvd_path,
- hw_property,
+ cmd = self.PrepareLaunchCVDCmd(hw_property,
avd_spec.connect_adb,
- artifact_paths.image_dir,
+ artifact_paths,
runtime_dir,
avd_spec.connect_webrtc,
avd_spec.connect_vnc,
super_image_path,
- artifact_paths.boot_image,
avd_spec.launch_args,
config or avd_spec.flavor,
avd_spec.openwrt,
@@ -436,17 +427,19 @@ class LocalImageLocalInstance(base_avd_create.BaseAVDCreate):
system_image_path = None
if avd_spec.local_kernel_image:
- boot_image_path = create_common.FindLocalImage(
- avd_spec.local_kernel_image, _BOOT_IMAGE_NAME_PATTERN)
+ boot_image_path, vendor_boot_image_path = cvd_utils.FindBootImages(
+ avd_spec.local_kernel_image)
else:
boot_image_path = None
+ vendor_boot_image_path = None
return ArtifactPaths(image_dir, host_bins_path,
host_artifacts=host_artifacts_path,
misc_info=misc_info_path,
ota_tools_dir=ota_tools_dir,
system_image=system_image_path,
- boot_image=boot_image_path)
+ boot_image=boot_image_path,
+ vendor_boot_image=vendor_boot_image_path)
@staticmethod
def _MixSuperImage(output_dir, artifact_paths):
@@ -490,26 +483,23 @@ class LocalImageLocalInstance(base_avd_create.BaseAVDCreate):
return None
@staticmethod
- def PrepareLaunchCVDCmd(cvd_path, hw_property, connect_adb,
- image_dir, runtime_dir, connect_webrtc,
- connect_vnc, super_image_path, boot_image_path,
- launch_args, config, openwrt=False,
- use_launch_cvd=False):
+ def PrepareLaunchCVDCmd(hw_property, connect_adb, artifact_paths,
+ runtime_dir, connect_webrtc, connect_vnc,
+ super_image_path, launch_args, config,
+ openwrt=False, use_launch_cvd=False):
"""Prepare launch_cvd command.
Create the launch_cvd commands with all the required args and add
in the user groups to it if necessary.
Args:
- cvd_path: String of cvd path.
hw_property: dict object of hw property.
- image_dir: String of local images path.
+ artifact_paths: ArtifactPaths object.
connect_adb: Boolean flag that enables adb_connector.
runtime_dir: String of runtime directory path.
connect_webrtc: Boolean of connect_webrtc.
connect_vnc: Boolean of connect_vnc.
super_image_path: String of non-default super image path.
- boot_image_path: String of non-default boot image path.
launch_args: String of launch args.
config: String of config name.
openwrt: Boolean of enable OpenWrt devices.
@@ -518,12 +508,13 @@ class LocalImageLocalInstance(base_avd_create.BaseAVDCreate):
Returns:
String, cvd start cmd.
"""
- start_cvd_cmd = cvd_path + _CMD_CVD_START
+ bin_dir = os.path.join(artifact_paths.host_bins, "bin")
+ start_cvd_cmd = (os.path.join(bin_dir, constants.CMD_CVD) +
+ _CMD_CVD_START)
if use_launch_cvd:
- bin_dir = os.path.dirname(cvd_path)
start_cvd_cmd = os.path.join(bin_dir, constants.CMD_LAUNCH_CVD)
launch_cvd_w_args = start_cvd_cmd + _CMD_LAUNCH_CVD_ARGS % (
- config, image_dir, runtime_dir)
+ config, artifact_paths.image_dir, runtime_dir)
if hw_property:
launch_cvd_w_args = launch_cvd_w_args + _CMD_LAUNCH_CVD_HW_ARGS % (
hw_property["cpu"], hw_property["x_res"], hw_property["y_res"],
@@ -546,10 +537,15 @@ class LocalImageLocalInstance(base_avd_create.BaseAVDCreate):
_CMD_LAUNCH_CVD_SUPER_IMAGE_ARG %
super_image_path)
- if boot_image_path:
+ if artifact_paths.boot_image:
launch_cvd_w_args = (launch_cvd_w_args +
_CMD_LAUNCH_CVD_BOOT_IMAGE_ARG %
- boot_image_path)
+ artifact_paths.boot_image)
+
+ if artifact_paths.vendor_boot_image:
+ launch_cvd_w_args = (launch_cvd_w_args +
+ _CMD_LAUNCH_CVD_VENDOR_BOOT_IMAGE_ARG %
+ artifact_paths.vendor_boot_image)
if openwrt:
launch_cvd_w_args = launch_cvd_w_args + _CMD_LAUNCH_CVD_CONSOLE_ARG
diff --git a/create/local_image_local_instance_test.py b/create/local_image_local_instance_test.py
index 16f5d7fa..7baf9711 100644
--- a/create/local_image_local_instance_test.py
+++ b/create/local_image_local_instance_test.py
@@ -37,37 +37,37 @@ class LocalImageLocalInstanceTest(driver_test_lib.BaseDriverTest):
LAUNCH_CVD_CMD_WITH_DISK = """sg group1 <<EOF
sg group2
-cvd start -daemon -config=phone -system_image_dir fake_image_dir -instance_dir fake_cvd_dir -undefok=report_anonymous_usage_stats,config -report_anonymous_usage_stats=y -cpus fake -x_res fake -y_res fake -dpi fake -memory_mb fake -blank_data_image_mb fake -data_policy always_create -start_vnc_server=true
+bin/cvd start -daemon -config=phone -system_image_dir fake_image_dir -instance_dir fake_cvd_dir -undefok=report_anonymous_usage_stats,config -report_anonymous_usage_stats=y -cpus fake -x_res fake -y_res fake -dpi fake -memory_mb fake -blank_data_image_mb fake -data_policy always_create -start_vnc_server=true
EOF"""
LAUNCH_CVD_CMD_NO_DISK = """sg group1 <<EOF
sg group2
-cvd start -daemon -config=phone -system_image_dir fake_image_dir -instance_dir fake_cvd_dir -undefok=report_anonymous_usage_stats,config -report_anonymous_usage_stats=y -cpus fake -x_res fake -y_res fake -dpi fake -memory_mb fake -start_vnc_server=true
+bin/cvd start -daemon -config=phone -system_image_dir fake_image_dir -instance_dir fake_cvd_dir -undefok=report_anonymous_usage_stats,config -report_anonymous_usage_stats=y -cpus fake -x_res fake -y_res fake -dpi fake -memory_mb fake -start_vnc_server=true
EOF"""
LAUNCH_CVD_CMD_NO_DISK_WITH_GPU = """sg group1 <<EOF
sg group2
-cvd start -daemon -config=phone -system_image_dir fake_image_dir -instance_dir fake_cvd_dir -undefok=report_anonymous_usage_stats,config -report_anonymous_usage_stats=y -cpus fake -x_res fake -y_res fake -dpi fake -memory_mb fake -start_vnc_server=true
+bin/cvd start -daemon -config=phone -system_image_dir fake_image_dir -instance_dir fake_cvd_dir -undefok=report_anonymous_usage_stats,config -report_anonymous_usage_stats=y -cpus fake -x_res fake -y_res fake -dpi fake -memory_mb fake -start_vnc_server=true
EOF"""
LAUNCH_CVD_CMD_WITH_WEBRTC = """sg group1 <<EOF
sg group2
-cvd start -daemon -config=auto -system_image_dir fake_image_dir -instance_dir fake_cvd_dir -undefok=report_anonymous_usage_stats,config -report_anonymous_usage_stats=y -start_webrtc=true
+bin/cvd start -daemon -config=auto -system_image_dir fake_image_dir -instance_dir fake_cvd_dir -undefok=report_anonymous_usage_stats,config -report_anonymous_usage_stats=y -start_webrtc=true
EOF"""
LAUNCH_CVD_CMD_WITH_MIXED_IMAGES = """sg group1 <<EOF
sg group2
-cvd start -daemon -config=phone -system_image_dir fake_image_dir -instance_dir fake_cvd_dir -undefok=report_anonymous_usage_stats,config -report_anonymous_usage_stats=y -start_vnc_server=true -super_image=fake_super_image -boot_image=fake_boot_image
+bin/cvd start -daemon -config=phone -system_image_dir fake_image_dir -instance_dir fake_cvd_dir -undefok=report_anonymous_usage_stats,config -report_anonymous_usage_stats=y -start_vnc_server=true -super_image=fake_super_image -boot_image=fake_boot_image -vendor_boot_image=fake_vendor_boot_image
EOF"""
LAUNCH_CVD_CMD_WITH_ARGS = """sg group1 <<EOF
sg group2
-cvd start -daemon -config=phone -system_image_dir fake_image_dir -instance_dir fake_cvd_dir -undefok=report_anonymous_usage_stats,config -report_anonymous_usage_stats=y -start_vnc_server=true -setupwizard_mode=REQUIRED
+bin/cvd start -daemon -config=phone -system_image_dir fake_image_dir -instance_dir fake_cvd_dir -undefok=report_anonymous_usage_stats,config -report_anonymous_usage_stats=y -start_vnc_server=true -setupwizard_mode=REQUIRED
EOF"""
LAUNCH_CVD_CMD_WITH_OPENWRT = """sg group1 <<EOF
sg group2
-launch_cvd -daemon -config=phone -system_image_dir fake_image_dir -instance_dir fake_cvd_dir -undefok=report_anonymous_usage_stats,config -report_anonymous_usage_stats=y -start_vnc_server=true -console=true
+bin/launch_cvd -daemon -config=phone -system_image_dir fake_image_dir -instance_dir fake_cvd_dir -undefok=report_anonymous_usage_stats,config -report_anonymous_usage_stats=y -start_vnc_server=true -console=true
EOF"""
_EXPECTED_DEVICES_IN_REPORT = [
@@ -118,7 +118,8 @@ EOF"""
"""Test _CreateAVD."""
mock_utils.IsSupportedPlatform.return_value = True
mock_get_image.return_value = local_image_local_instance.ArtifactPaths(
- "/image/path", "/host/bin/path", "host/usr/path", None, None, None, None)
+ "/image/path", "/host/bin/path", "host/usr/path",
+ None, None, None, None, None)
mock_check_running_cvd.return_value = True
mock_avd_spec = mock.Mock()
mock_lock = mock.Mock()
@@ -199,7 +200,8 @@ EOF"""
"/instances/cvd/config")
artifact_paths = local_image_local_instance.ArtifactPaths(
"/image/path", "/host/bin/path", "/host/usr/path", "/misc/info/path",
- "/ota/tools/dir", "/system/image/path", "/boot/image/path")
+ "/ota/tools/dir", "/system/image/path", "/boot/image/path",
+ "/vendor_boot/image/path")
mock_ota_tools_object = mock.Mock()
mock_ota_tools.OtaTools.return_value = mock_ota_tools_object
mock_avd_spec = mock.Mock(
@@ -288,24 +290,29 @@ EOF"""
mock_avd_spec)
mock_ota_tools.FindOtaToolsDir.assert_not_called()
- self.assertEqual(paths, (image_dir, cvd_dir, cvd_dir, None, None, None, None))
+ self.assertEqual(paths, (image_dir, cvd_dir, cvd_dir,
+ None, None, None, None, None))
@mock.patch("acloud.create.local_image_local_instance.ota_tools")
- def testGetImageFromBuildEnvironment(self, mock_ota_tools):
+ @mock.patch("acloud.create.local_image_local_instance.cvd_utils")
+ def testGetImageFromBuildEnvironment(self, mock_cvd_utils, mock_ota_tools):
"""Test GetImageArtifactsPath with files in build environment."""
+ boot_image_path = "/mock/boot.img"
+ vendor_boot_image_path = "/mock/vendor_boot.img"
+ mock_cvd_utils.FindBootImages.return_value = (boot_image_path,
+ vendor_boot_image_path)
+
with tempfile.TemporaryDirectory() as temp_dir:
image_dir = os.path.join(temp_dir, "image")
cvd_dir = os.path.join(temp_dir, "cvd-host_package")
mock_ota_tools.FindOtaToolsDir.return_value = cvd_dir
extra_image_dir = os.path.join(temp_dir, "extra_image")
system_image_path = os.path.join(extra_image_dir, "system.img")
- boot_image_path = os.path.join(extra_image_dir, "boot.img")
misc_info_path = os.path.join(image_dir, "misc_info.txt")
self._CreateEmptyFile(os.path.join(image_dir, "vbmeta.img"))
self._CreateEmptyFile(os.path.join(cvd_dir, "bin", "launch_cvd"))
self._CreateEmptyFile(os.path.join(cvd_dir, "usr/share/webrtc/certs", "server.crt"))
self._CreateEmptyFile(system_image_path)
- self._CreateEmptyFile(boot_image_path)
self._CreateEmptyFile(os.path.join(extra_image_dir,
"boot-debug.img"))
self._CreateEmptyFile(misc_info_path)
@@ -325,29 +332,33 @@ EOF"""
mock_avd_spec)
mock_ota_tools.FindOtaToolsDir.assert_called_with([cvd_dir, "/cvd"])
+ mock_cvd_utils.FindBootImages.asssert_called_with(extra_image_dir)
self.assertEqual(paths,
(image_dir, cvd_dir, cvd_dir, misc_info_path, cvd_dir,
- system_image_path, boot_image_path))
+ system_image_path, boot_image_path,
+ vendor_boot_image_path))
@mock.patch("acloud.create.local_image_local_instance.ota_tools")
- def testGetImageFromTargetFiles(self, mock_ota_tools):
+ @mock.patch("acloud.create.local_image_local_instance.cvd_utils")
+ def testGetImageFromTargetFiles(self, mock_cvd_utils, mock_ota_tools):
"""Test GetImageArtifactsPath with extracted target files."""
ota_tools_dir = "/mock_ota_tools"
mock_ota_tools.FindOtaToolsDir.return_value = ota_tools_dir
+ boot_image_path = "/mock/boot.img"
+ mock_cvd_utils.FindBootImages.return_value = (boot_image_path, None)
with tempfile.TemporaryDirectory() as temp_dir:
image_dir = os.path.join(temp_dir, "image")
cvd_dir = os.path.join(temp_dir, "cvd-host_package")
system_image_path = os.path.join(temp_dir, "system", "test.img")
misc_info_path = os.path.join(image_dir, "META", "misc_info.txt")
- boot_image_path = os.path.join(temp_dir, "boot", "test.img")
+
self._CreateEmptyFile(os.path.join(image_dir, "IMAGES",
"vbmeta.img"))
self._CreateEmptyFile(os.path.join(cvd_dir, "bin", "launch_cvd"))
self._CreateEmptyFile(os.path.join(cvd_dir, "usr/share/webrtc/certs", "server.crt"))
self._CreateEmptyFile(system_image_path)
self._CreateEmptyFile(misc_info_path)
- self._CreateEmptyFile(boot_image_path)
mock_avd_spec = mock.Mock(
local_image_dir=image_dir,
@@ -363,10 +374,11 @@ EOF"""
mock_ota_tools.FindOtaToolsDir.assert_called_with(
[ota_tools_dir, cvd_dir])
+ mock_cvd_utils.FindBootImages.assert_called_with(boot_image_path)
self.assertEqual(paths,
(os.path.join(image_dir, "IMAGES"), cvd_dir, cvd_dir,
misc_info_path, ota_tools_dir, system_image_path,
- boot_image_path))
+ boot_image_path, None))
@mock.patch.object(utils, "CheckUserInGroups")
def testPrepareLaunchCVDCmd(self, mock_usergroups):
@@ -375,50 +387,61 @@ EOF"""
hw_property = {"cpu": "fake", "x_res": "fake", "y_res": "fake",
"dpi":"fake", "memory": "fake", "disk": "fake"}
constants.LIST_CF_USER_GROUPS = ["group1", "group2"]
+ mock_artifact_paths = mock.Mock(
+ spec=[],
+ image_dir="fake_image_dir",
+ host_bins="",
+ host_artifacts="host_artifacts",
+ misc_info=None,
+ ota_tools_dir=None,
+ system_image=None,
+ boot_image=None,
+ vendor_boot_image=None)
launch_cmd = self.local_image_local_instance.PrepareLaunchCVDCmd(
- constants.CMD_CVD, hw_property, True, "fake_image_dir",
- "fake_cvd_dir", False, True, None, None, None, "phone")
+ hw_property, True, mock_artifact_paths, "fake_cvd_dir", False,
+ True, None, None, "phone")
self.assertEqual(launch_cmd, self.LAUNCH_CVD_CMD_WITH_DISK)
# "disk" doesn't exist in hw_property.
hw_property = {"cpu": "fake", "x_res": "fake", "y_res": "fake",
"dpi": "fake", "memory": "fake"}
launch_cmd = self.local_image_local_instance.PrepareLaunchCVDCmd(
- constants.CMD_CVD, hw_property, True, "fake_image_dir",
- "fake_cvd_dir", False, True, None, None, None, "phone")
+ hw_property, True, mock_artifact_paths, "fake_cvd_dir", False,
+ True, None, None, "phone")
self.assertEqual(launch_cmd, self.LAUNCH_CVD_CMD_NO_DISK)
# "gpu" is enabled with "default"
launch_cmd = self.local_image_local_instance.PrepareLaunchCVDCmd(
- constants.CMD_CVD, hw_property, True, "fake_image_dir",
- "fake_cvd_dir", False, True, None, None, None, "phone")
+ hw_property, True, mock_artifact_paths, "fake_cvd_dir", False,
+ True, None, None, "phone")
self.assertEqual(launch_cmd, self.LAUNCH_CVD_CMD_NO_DISK_WITH_GPU)
# Following test with hw_property is None.
launch_cmd = self.local_image_local_instance.PrepareLaunchCVDCmd(
- constants.CMD_CVD, None, True, "fake_image_dir",
- "fake_cvd_dir", True, False, None, None, None, "auto")
+ None, True, mock_artifact_paths, "fake_cvd_dir", True, False,
+ None, None, "auto")
self.assertEqual(launch_cmd, self.LAUNCH_CVD_CMD_WITH_WEBRTC)
+ mock_artifact_paths.boot_image = "fake_boot_image"
+ mock_artifact_paths.vendor_boot_image = "fake_vendor_boot_image"
launch_cmd = self.local_image_local_instance.PrepareLaunchCVDCmd(
- constants.CMD_CVD, None, True, "fake_image_dir",
- "fake_cvd_dir", False, True, "fake_super_image", "fake_boot_image",
- None, "phone")
+ None, True, mock_artifact_paths, "fake_cvd_dir", False, True,
+ "fake_super_image", None, "phone")
self.assertEqual(launch_cmd, self.LAUNCH_CVD_CMD_WITH_MIXED_IMAGES)
+ mock_artifact_paths.boot_image = None
+ mock_artifact_paths.vendor_boot_image = None
# Add args into launch command with "-setupwizard_mode=REQUIRED"
launch_cmd = self.local_image_local_instance.PrepareLaunchCVDCmd(
- constants.CMD_CVD, None, True, "fake_image_dir",
- "fake_cvd_dir", False, True, None, None,
- "-setupwizard_mode=REQUIRED", "phone")
+ None, True, mock_artifact_paths, "fake_cvd_dir", False, True,
+ None, "-setupwizard_mode=REQUIRED", "phone")
self.assertEqual(launch_cmd, self.LAUNCH_CVD_CMD_WITH_ARGS)
# Test with "openwrt" and "use_launch_cvd" are enabled.
launch_cmd = self.local_image_local_instance.PrepareLaunchCVDCmd(
- constants.CMD_LAUNCH_CVD, None, True, "fake_image_dir",
- "fake_cvd_dir", False, True, None, None, None,
- "phone", openwrt=True, use_launch_cvd=True)
+ None, True, mock_artifact_paths, "fake_cvd_dir", False, True,
+ None, None, "phone", openwrt=True, use_launch_cvd=True)
self.assertEqual(launch_cmd, self.LAUNCH_CVD_CMD_WITH_OPENWRT)
@mock.patch.object(utils, "GetUserAnswerYes")
diff --git a/create/remote_image_local_instance.py b/create/remote_image_local_instance.py
index acde2cb6..d0d0958f 100644
--- a/create/remote_image_local_instance.py
+++ b/create/remote_image_local_instance.py
@@ -247,4 +247,5 @@ class RemoteImageLocalInstance(local_image_local_instance.LocalImageLocalInstanc
misc_info=misc_info_path,
ota_tools_dir=ota_tools_dir,
system_image=system_image_path,
- boot_image=None)
+ boot_image=None,
+ vendor_boot_image=None)
diff --git a/internal/lib/cvd_utils.py b/internal/lib/cvd_utils.py
index 42cbe8a8..20534efe 100644
--- a/internal/lib/cvd_utils.py
+++ b/internal/lib/cvd_utils.py
@@ -20,6 +20,7 @@ import os
import posixpath as remote_path
from acloud import errors
+from acloud.create import create_common
from acloud.internal import constants
from acloud.internal.lib import ssh
from acloud.internal.lib import utils
@@ -31,11 +32,17 @@ logger = logging.getLogger(__name__)
# bootloader and kernel are files required to launch AVD.
_ARTIFACT_FILES = ["*.img", "bootloader", "kernel"]
_REMOTE_IMAGE_DIR = "acloud_cf"
-_BOOT_IMAGE_NAME = "boot.img"
+# The boot image name pattern corresponds to the use cases:
+# - In a cuttlefish build environment, ANDROID_PRODUCT_OUT conatins boot.img
+# and boot-debug.img. The former is the default boot image. The latter is not
+# useful for cuttlefish.
+# - In an officially released GKI (Generic Kernel Image) package, the image
+# name is boot-<kernel version>.img.
+_BOOT_IMAGE_NAME_PATTERN = r"boot(-[\d.]+)?\.img"
_VENDOR_BOOT_IMAGE_NAME = "vendor_boot.img"
_KERNEL_IMAGE_NAMES = ("kernel", "bzImage", "Image")
_INITRAMFS_IMAGE_NAME = "initramfs.img"
-_REMOTE_BOOT_IMAGE_PATH = remote_path.join(_REMOTE_IMAGE_DIR, _BOOT_IMAGE_NAME)
+_REMOTE_BOOT_IMAGE_PATH = remote_path.join(_REMOTE_IMAGE_DIR, "boot.img")
_REMOTE_VENDOR_BOOT_IMAGE_PATH = remote_path.join(
_REMOTE_IMAGE_DIR, _VENDOR_BOOT_IMAGE_NAME)
_REMOTE_KERNEL_IMAGE_PATH = remote_path.join(
@@ -139,7 +146,7 @@ def _IsBootImage(image_path):
return image_file.read(8) == _ANDROID_BOOT_IMAGE_MAGIC
-def _FindBootImages(search_path):
+def FindBootImages(search_path):
"""Find boot and vendor_boot images in a path.
Args:
@@ -148,13 +155,22 @@ def _FindBootImages(search_path):
Returns:
The boot image path and the vendor_boot image path. Each value can be
None if the path doesn't exist.
+
+ Raises:
+ errors.GetLocalImageError if search_path contains more than one boot
+ image or the file format is not correct.
"""
- if _IsBootImage(search_path):
- return search_path, None
+ boot_image_path = create_common.FindLocalImage(
+ search_path, _BOOT_IMAGE_NAME_PATTERN, raise_error=False)
+ if boot_image_path and not _IsBootImage(boot_image_path):
+ raise errors.GetLocalImageError(
+ f"{boot_image_path} is not a boot image.")
+
+ vendor_boot_image_path = os.path.join(search_path, _VENDOR_BOOT_IMAGE_NAME)
+ if not os.path.isfile(vendor_boot_image_path):
+ vendor_boot_image_path = None
- paths = [os.path.join(search_path, name) for name in
- (_BOOT_IMAGE_NAME, _VENDOR_BOOT_IMAGE_NAME)]
- return [(path if os.path.isfile(path) else None) for path in paths]
+ return boot_image_path, vendor_boot_image_path
def _FindKernelImages(search_path):
@@ -196,7 +212,7 @@ def _UploadKernelImages(ssh_obj, search_path):
# Assume that the caller cleaned up the remote home directory.
ssh_obj.Run("mkdir -p " + _REMOTE_IMAGE_DIR)
- boot_image_path, vendor_boot_image_path = _FindBootImages(search_path)
+ boot_image_path, vendor_boot_image_path = FindBootImages(search_path)
if boot_image_path:
ssh_obj.ScpPushFile(boot_image_path, _REMOTE_BOOT_IMAGE_PATH)
launch_cvd_args = ["-boot_image", _REMOTE_BOOT_IMAGE_PATH]
diff --git a/internal/lib/cvd_utils_test.py b/internal/lib/cvd_utils_test.py
index 14e79934..ab0e82ac 100644
--- a/internal/lib/cvd_utils_test.py
+++ b/internal/lib/cvd_utils_test.py
@@ -81,7 +81,7 @@ class CvdUtilsTest(unittest.TestCase):
mock_ssh.Run.assert_called_with(expected_ssh_cmd)
def testUploadBootImages(self):
- """Test UploadExtraImages with boot images."""
+ """Test FindBootImages and UploadExtraImages."""
mock_ssh = mock.Mock()
with tempfile.TemporaryDirectory(prefix="cvd_utils") as image_dir:
boot_image_path = os.path.join(image_dir, "boot.img")