Add --local-system_dlkm-image
system_dlkm has been a new requirement since Android 13. Generally it is
built from the kernel branches and in different formats. Cuttlefish
requires the flattened ext4 image. system_dlkm image has to be mixed
with cuttlefish images into a super image. The user has to provide OTA
tools and cuttlefish target_files zip as parameters to acloud.
Bug: 298075407
Test: acloud-dev create -vv --host 192.168.9.2 \
--host-user vsoc-01 --host-ssh-private-key-path ~/id_rsa \
--local-system_dlkm-image ~/system_dlkm.flatten.ext4.img \
--local-boot-image ~/boot.img \
--local-image ~/target_files.zip \
--cvd-host-package ~/cvd-host_package.tar.gz \
--local-tool ~/otatools
Change-Id: I17b9d7a1318f3357a4384d939a25d6ecf2e734b5
diff --git a/create/avd_spec.py b/create/avd_spec.py
index 386d96a..7f53ec8 100644
--- a/create/avd_spec.py
+++ b/create/avd_spec.py
@@ -123,6 +123,7 @@
self._local_instance_dir = None
self._local_kernel_image = None
self._local_system_image = None
+ self._local_system_dlkm_image = None
self._local_vendor_image = None
self._local_tool_dirs = None
self._image_download_dir = None
@@ -259,6 +260,10 @@
self._local_system_image = self._GetLocalImagePath(
args.local_system_image)
+ if args.local_system_dlkm_image is not None:
+ self._local_system_dlkm_image = self._GetLocalImagePath(
+ args.local_system_dlkm_image)
+
if args.local_vendor_image is not None:
self._local_vendor_image = self._GetLocalImagePath(
args.local_vendor_image)
@@ -837,6 +842,11 @@
return self._local_system_image
@property
+ def local_system_dlkm_image(self):
+ """Return local system_dlkm image path."""
+ return self._local_system_dlkm_image
+
+ @property
def local_vendor_image(self):
"""Return local vendor image path."""
return self._local_vendor_image
diff --git a/create/avd_spec_test.py b/create/avd_spec_test.py
index 5f20e40..1b3e34c 100644
--- a/create/avd_spec_test.py
+++ b/create/avd_spec_test.py
@@ -121,22 +121,27 @@
# Specified --local-*-image with dirs.
self.args.local_kernel_image = expected_image_dir
self.args.local_system_image = expected_image_dir
+ self.args.local_system_dlkm_image = expected_image_dir
self.args.local_vendor_image = expected_image_dir
self.AvdSpec._ProcessImageArgs(self.args)
self.assertEqual(self.AvdSpec.local_kernel_image, expected_image_dir)
self.assertEqual(self.AvdSpec.local_system_image, expected_image_dir)
+ self.assertEqual(self.AvdSpec.local_system_dlkm_image, expected_image_dir)
self.assertEqual(self.AvdSpec.local_vendor_image, expected_image_dir)
# Specified --local-*-image with files.
self.args.local_kernel_image = expected_image_file
self.args.local_system_image = expected_image_file
+ self.args.local_system_dlkm_image = expected_image_file
self.AvdSpec._ProcessImageArgs(self.args)
self.assertEqual(self.AvdSpec.local_kernel_image, expected_image_file)
self.assertEqual(self.AvdSpec.local_system_image, expected_image_file)
+ self.assertEqual(self.AvdSpec.local_system_dlkm_image, expected_image_file)
# Specified --local-*-image without args.
self.args.local_kernel_image = constants.FIND_IN_BUILD_ENV
self.args.local_system_image = constants.FIND_IN_BUILD_ENV
+ self.args.local_system_dlkm_image = constants.FIND_IN_BUILD_ENV
self.args.local_vendor_image = constants.FIND_IN_BUILD_ENV
with mock.patch("acloud.create.avd_spec.utils."
"GetBuildEnvironmentVariable",
@@ -144,6 +149,7 @@
self.AvdSpec._ProcessImageArgs(self.args)
self.assertEqual(self.AvdSpec.local_kernel_image, expected_image_dir)
self.assertEqual(self.AvdSpec.local_system_image, expected_image_dir)
+ self.assertEqual(self.AvdSpec.local_system_dlkm_image, expected_image_dir)
self.assertEqual(self.AvdSpec.local_vendor_image, expected_image_dir)
def testProcessAutoconnect(self):
diff --git a/create/create_args.py b/create/create_args.py
index ba6e2a8..6ad1e96 100644
--- a/create/create_args.py
+++ b/create/create_args.py
@@ -591,6 +591,16 @@
"e.g., --local-system-image, --local-system-image /path/to/dir, or "
"--local-system-image /path/to/img")
create_parser.add_argument(
+ "--local-system_dlkm-image",
+ const=constants.FIND_IN_BUILD_ENV,
+ type=str,
+ dest="local_system_dlkm_image",
+ nargs="?",
+ required=False,
+ help="`cuttlefish only` Use the locally built system_dlkm image for "
+ "the AVD. Look for the image in $ANDROID_PRODUCT_OUT if no args value "
+ "is provided.")
+ create_parser.add_argument(
"--local-vendor-image",
const=constants.FIND_IN_BUILD_ENV,
type=str,
diff --git a/internal/lib/cvd_utils.py b/internal/lib/cvd_utils.py
index fe42685..7b71896 100644
--- a/internal/lib/cvd_utils.py
+++ b/internal/lib/cvd_utils.py
@@ -38,13 +38,10 @@
# Local build artifacts to be uploaded.
_ARTIFACT_FILES = ["*.img", "bootloader", "kernel"]
-# 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_DLKM_IMAGE_NAMES = (
+ "system_dlkm.flatten.ext4.img", # GKI artifact
+ "system_dlkm.img", # cuttlefish artifact
+)
_VENDOR_BOOT_IMAGE_NAME = "vendor_boot.img"
_KERNEL_IMAGE_NAMES = ("kernel", "bzImage", "Image")
_INITRAMFS_IMAGE_NAME = "initramfs.img"
@@ -362,6 +359,32 @@
f"{search_path} is not a boot image or a directory containing images.")
+def _FindSystemDlkmImage(search_path):
+ """Find system_dlkm image in a path.
+
+ Args:
+ search_path: A path to an image file or an image directory.
+
+ Returns:
+ The system_dlkm image path.
+
+ Raises:
+ errors.GetLocalImageError if search_path does not contain a
+ system_dlkm image.
+ """
+ if os.path.isfile(search_path):
+ return search_path
+
+ for name in _SYSTEM_DLKM_IMAGE_NAMES:
+ path = os.path.join(search_path, name)
+ if os.path.isfile(path):
+ return path
+
+ raise errors.GetLocalImageError(
+ f"{search_path} is not a system_dlkm image or a directory containing "
+ "images.")
+
+
def _MixSuperImage(super_image_path, avd_spec, target_files_dir, ota):
"""Mix super image from device images and extra images.
@@ -378,6 +401,7 @@
system_image_path = None
system_ext_image_path = None
product_image_path = None
+ system_dlkm_image_path = None
vendor_image_path = None
vendor_dlkm_image_path = None
odm_image_path = None
@@ -390,6 +414,10 @@
product_image_path,
) = create_common.FindSystemImages(avd_spec.local_system_image)
+ if avd_spec.local_system_dlkm_image:
+ system_dlkm_image_path = _FindSystemDlkmImage(
+ avd_spec.local_system_dlkm_image)
+
if avd_spec.local_vendor_image:
(
vendor_image_path,
@@ -402,6 +430,7 @@
system_image=system_image_path,
system_ext_image=system_ext_image_path,
product_image=product_image_path,
+ system_dlkm_image=system_dlkm_image_path,
vendor_image=vendor_image_path,
vendor_dlkm_image=vendor_dlkm_image_path,
odm_image=odm_image_path,
@@ -428,7 +457,8 @@
def AreTargetFilesRequired(avd_spec):
"""Return whether UploadExtraImages requires target_files_dir."""
- return bool(avd_spec.local_system_image or avd_spec.local_vendor_image)
+ return bool(avd_spec.local_system_image or avd_spec.local_vendor_image or
+ avd_spec.local_system_dlkm_image)
def UploadExtraImages(ssh_obj, remote_dir, avd_spec, target_files_dir):
@@ -461,7 +491,8 @@
if AreTargetFilesRequired(avd_spec):
if not target_files_dir:
raise ValueError("target_files_dir is required when avd_spec has "
- "local system image or local vendor image.")
+ "local system image, local system_dlkm image, or "
+ "local vendor image.")
ota = ota_tools.FindOtaTools(
avd_spec.local_tool_dirs + create_common.GetNonEmptyEnvVars(
constants.ENV_ANDROID_SOONG_HOST_OUT,
diff --git a/internal/lib/cvd_utils_test.py b/internal/lib/cvd_utils_test.py
index dccfd47..505f144 100644
--- a/internal/lib/cvd_utils_test.py
+++ b/internal/lib/cvd_utils_test.py
@@ -161,6 +161,7 @@
mock_avd_spec = mock.Mock(local_kernel_image="boot.img",
local_system_image=None,
+ local_system_dlkm_image=None,
local_vendor_image=None)
args = cvd_utils.UploadExtraImages(mock_ssh, "dir", mock_avd_spec,
None)
@@ -192,6 +193,7 @@
mock_avd_spec = mock.Mock(local_kernel_image=kernel_image_path,
local_system_image=None,
+ local_system_dlkm_image=None,
local_vendor_image=None)
with self.assertRaises(errors.GetLocalImageError):
cvd_utils.UploadExtraImages(mock_ssh, "dir", mock_avd_spec,
@@ -222,14 +224,15 @@
extra_image_dir = os.path.join(temp_dir, "extra")
mock_avd_spec = mock.Mock(local_kernel_image=None,
local_system_image=extra_image_dir,
+ local_system_dlkm_image=extra_image_dir,
local_vendor_image=extra_image_dir,
local_tool_dirs=[])
self.CreateFile(
os.path.join(target_files_dir, "IMAGES", "boot.img"))
self.CreateFile(
os.path.join(target_files_dir, "META", "misc_info.txt"))
- for image_name in ["system.img", "vendor.img", "vendor_dlkm.img",
- "odm.img", "odm_dlkm.img"]:
+ for image_name in ["system.img", "system_dlkm.img", "vendor.img",
+ "vendor_dlkm.img", "odm.img", "odm_dlkm.img"]:
self.CreateFile(os.path.join(extra_image_dir, image_name))
args = cvd_utils.UploadExtraImages(mock_ssh, "dir", mock_avd_spec,
target_files_dir)
@@ -246,7 +249,16 @@
self.assertEqual(1, len(upload_args))
self.assertIn(" super.img", upload_args[0])
self.assertIn("dir/acloud_image", upload_args[0])
- mock_ota_tools_object.MixSuperImage.assert_called_once()
+ mock_ota_tools_object.MixSuperImage.assert_called_once_with(
+ mock.ANY, mock.ANY, os.path.join(target_files_dir, "IMAGES"),
+ system_image=os.path.join(extra_image_dir, "system.img"),
+ system_ext_image=None,
+ product_image=None,
+ system_dlkm_image=os.path.join(extra_image_dir, "system_dlkm.img"),
+ vendor_image=os.path.join(extra_image_dir, "vendor.img"),
+ vendor_dlkm_image=os.path.join(extra_image_dir, "vendor_dlkm.img"),
+ odm_image=os.path.join(extra_image_dir, "odm.img"),
+ odm_dlkm_image=os.path.join(extra_image_dir, "odm_dlkm.img"))
# vbmeta image
mock_ota_tools_object.MakeDisabledVbmetaImage.assert_called_once()
mock_ssh.ScpPushFile.assert_called_once_with(
diff --git a/internal/lib/ota_tools.py b/internal/lib/ota_tools.py
index 8863623..5048770 100644
--- a/internal/lib/ota_tools.py
+++ b/internal/lib/ota_tools.py
@@ -301,9 +301,9 @@
def MixSuperImage(self, super_image, misc_info, image_dir,
system_image=None, system_ext_image=None,
- product_image=None, vendor_image=None,
- vendor_dlkm_image=None, odm_image=None,
- odm_dlkm_image=None):
+ product_image=None, system_dlkm_image=None,
+ vendor_image=None, vendor_dlkm_image=None,
+ odm_image=None, odm_dlkm_image=None):
"""Create mixed super image from device images and given partition
images.
@@ -314,6 +314,7 @@
system_image: Path to the system image.
system_ext_image: Path to the system_ext image.
product_image: Path to the product image.
+ system_dlkm_image: Path to the system_dlkm image.
vendor_image: Path to the vendor image.
vendor_dlkm_image: Path to the vendor_dlkm image.
odm_image: Path to the odm image.
@@ -326,6 +327,7 @@
system=system_image,
system_ext=system_ext_image,
product=product_image,
+ system_dlkm=system_dlkm_image,
vendor=vendor_image,
vendor_dlkm=vendor_dlkm_image,
odm=odm_image,