CP cl/231269485

Bug: 123894473
Test: atest acloud_test --host
Change-Id: I6e22f3627ba4ed4bb8de8d830c776d63abba2a83
diff --git a/internal/lib/cvd_compute_client.py b/internal/lib/cvd_compute_client.py
index 920e807..8aab4be 100644
--- a/internal/lib/cvd_compute_client.py
+++ b/internal/lib/cvd_compute_client.py
@@ -62,7 +62,8 @@
                        build_target=None, branch=None, build_id=None,
                        kernel_branch=None, kernel_build_id=None,
                        blank_data_disk_size_gb=None, avd_spec=None,
-                       extra_scopes=None):
+                       extra_scopes=None, system_build_target=None,
+                       system_branch=None, system_build_id=None):
         """Create a cuttlefish instance given stable host image and build id.
 
         Args:
@@ -78,6 +79,10 @@
             blank_data_disk_size_gb: Size of the blank data disk in GB.
             avd_spec: An AVDSpec instance.
             extra_scopes: A list of extra scopes to be passed to the instance.
+            system_build_target: Target name for the system image,
+                           e.g. "cf_x86_phone-userdebug"
+            system_branch: A String, branch name for the system image.
+            system_build_id: A string, build id for the system image.
         """
         self._CheckMachineSize()
 
@@ -102,6 +107,11 @@
         if kernel_branch and kernel_build_id:
             metadata["cvd_01_fetch_kernel_bid"] = "{branch}/{build_id}".format(
                 branch=kernel_branch, build_id=kernel_build_id)
+        if system_build_target:
+            metadata["cvd_01_fetch_system_build_target"] = system_build_target
+        if system_branch and system_build_id:
+            metadata["cvd_01_fetch_system_bid"] = "{branch}/{build_id}".format(
+                branch=system_branch, build_id=system_build_id)
         metadata["cvd_01_launch"] = (self._launch_args
                                      if self._launch_args else "1")
 
diff --git a/public/acloud_main.py b/public/acloud_main.py
index 935e3f1..5e869a7 100644
--- a/public/acloud_main.py
+++ b/public/acloud_main.py
@@ -166,6 +166,28 @@
         " specifying kernel_build_id, the last green build in the branch will"
         " be used. If neither kernel_branch nor kernel_build_id are specified,"
         " the kernel that's bundled with the Android build would be used.")
+    create_cf_parser.add_argument(
+        "--system_branch",
+        type=str,
+        dest="system_branch",
+        help="Branch to consume the system image (system.img) from, will "
+        "default to what is defined by --branch. "
+        "That feature allows to (automatically) test various combinations "
+        "of vendor.img (CF, e.g.) and system images (GSI, e.g.). ",
+        required=False)
+    create_cf_parser.add_argument(
+        "--system_build_id",
+        type=str,
+        dest="system_build_id",
+        help="System image build id, e.g. 2145099, P2804227",
+        required=False)
+    create_cf_parser.add_argument(
+        "--system_build_target",
+        type=str,
+        dest="system_build_target",
+        help="System image build target, specify if different from "
+        "--build_target",
+        required=False)
 
     create_args.AddCommonCreateArgs(create_cf_parser)
     subparser_list.append(create_cf_parser)
@@ -374,6 +396,9 @@
             build_id=args.build_id,
             kernel_build_id=args.kernel_build_id,
             kernel_branch=args.kernel_branch,
+            system_branch=args.system_branch,
+            system_build_id=args.system_build_id,
+            system_build_target=args.system_build_target,
             num=args.num,
             serial_log_file=args.serial_log_file,
             logcat_file=args.logcat_file,
diff --git a/public/actions/common_operations.py b/public/actions/common_operations.py
index 5f3dcbb..77423e6 100644
--- a/public/actions/common_operations.py
+++ b/public/actions/common_operations.py
@@ -298,7 +298,8 @@
             for attr in ("branch", "build_target", "build_id", "kernel_branch",
                          "kernel_build_target", "kernel_build_id",
                          "emulator_branch", "emulator_build_target",
-                         "emulator_build_id"):
+                         "emulator_build_id", "system_branch",
+                         "system_build_id", "system_build_target"):
                 if getattr(device_factory, "_%s" % attr, None):
                     device_dict[attr] = getattr(device_factory, "_%s" % attr)
             if autoconnect:
diff --git a/public/actions/common_operations_test.py b/public/actions/common_operations_test.py
index 030a958..8f6e93e 100644
--- a/public/actions/common_operations_test.py
+++ b/public/actions/common_operations_test.py
@@ -53,6 +53,9 @@
         self.device_factory._kernel_branch = None
         self.device_factory._kernel_build_id = None
         self.device_factory._kernel_build_target = None
+        self.device_factory._system_branch = None
+        self.device_factory._system_build_id = None
+        self.device_factory._system_build_target = None
         self.device_factory._emulator_branch = None
         self.device_factory._emulator_build_id = None
         self.device_factory._emulator_build_target = None
diff --git a/public/actions/create_cuttlefish_action.py b/public/actions/create_cuttlefish_action.py
index 65ce954..c8cc860 100644
--- a/public/actions/create_cuttlefish_action.py
+++ b/public/actions/create_cuttlefish_action.py
@@ -52,7 +52,8 @@
                  "/home/vsoc-01/cuttlefish_runtime/cuttlefish_config.json"]
 
     def __init__(self, cfg, build_target, build_id, kernel_build_id=None,
-                 avd_spec=None, kernel_branch=None):
+                 avd_spec=None, kernel_branch=None, system_branch=None,
+                 system_build_id=None, system_build_target=None):
 
         self.credentials = auth.CreateCredentials(cfg)
 
@@ -68,6 +69,9 @@
         self._blank_data_disk_size_gb = cfg.extra_data_disk_size_gb
         self._avd_spec = avd_spec
         self._kernel_branch = kernel_branch
+        self._system_branch = system_branch
+        self._system_build_id = system_build_id
+        self._system_build_target = system_build_target or build_target
         self._kernel_build_target = cfg.kernel_build_target
         self._extra_scopes = cfg.extra_scopes
 
@@ -91,6 +95,18 @@
         else:
             self._kernel_build_target = None
 
+        if system_branch:
+            # If no system_build_id is given or system_build_id is latest,
+            # use the last green build id in the given system_branch
+            if not system_build_id or system_build_id == self.LATEST:
+                self._system_build_id = self._build_client.GetLKGB(
+                    self._system_build_target, system_branch)
+        elif system_build_id:
+            self._system_branch = self._build_client.GetBranch(
+                self._system_build_target, system_build_id)
+        else:
+            self._system_build_target = None
+
     def CreateInstance(self):
         """Creates singe configured cuttlefish device.
 
@@ -123,7 +139,10 @@
             kernel_build_id=self._kernel_build_id,
             blank_data_disk_size_gb=self._blank_data_disk_size_gb,
             avd_spec=self._avd_spec,
-            extra_scopes=self._extra_scopes)
+            extra_scopes=self._extra_scopes,
+            system_build_target=self._system_build_target,
+            system_branch=self._system_branch,
+            system_build_id=self._system_build_id)
 
         return instance
 
@@ -134,6 +153,9 @@
                   build_id=None,
                   kernel_build_id=None,
                   kernel_branch=None,
+                  system_branch=None,
+                  system_build_id=None,
+                  system_build_target=None,
                   num=1,
                   serial_log_file=None,
                   logcat_file=None,
@@ -148,6 +170,9 @@
         build_id: String, Build id, e.g. "2263051", "P2804227"
         kernel_build_id: String, Kernel build id.
         kernel_branch: String, Kernel branch name.
+        system_branch: Branch name to consume the system.img from, a string.
+        system_build_id: System branch build id, a string.
+        system_build_target: System image build target, a string.
         num: Integer, Number of devices to create.
         serial_log_file: String, A path to a tar file where serial output should
                          be saved to.
@@ -172,15 +197,27 @@
         logcat_file = avd_spec.logcat_file
         client_adb_port = avd_spec.client_adb_port
     logger.info(
-        "Creating a cuttlefish device in project %s, build_target: %s, "
-        "build_id: %s, num: %s, serial_log_file: %s, logcat_file: %s, "
-        "autoconnect: %s, report_internal_ip: %s", cfg.project, build_target,
-        build_id, num, serial_log_file, logcat_file, autoconnect,
-        report_internal_ip)
-    device_factory = CuttlefishDeviceFactory(cfg, build_target, build_id,
-                                             avd_spec=avd_spec,
-                                             kernel_build_id=kernel_build_id,
-                                             kernel_branch=kernel_branch)
+        "Creating a cuttlefish device in project %s, "
+        "build_target: %s, "
+        "build_id: %s, "
+        "kernel_build_id: %s, "
+        "kernel_branch: %s, "
+        "system_branch: %s, "
+        "system_build_id: %s, "
+        "system_build_target: %s, "
+        "num: %s, "
+        "serial_log_file: %s, "
+        "logcat_file: %s, "
+        "autoconnect: %s, "
+        "report_internal_ip: %s", cfg.project, build_target,
+        build_id, kernel_build_id, kernel_branch, system_branch,
+        system_build_id, system_build_target, num, serial_log_file,
+        logcat_file, autoconnect, report_internal_ip)
+    device_factory = CuttlefishDeviceFactory(
+        cfg, build_target, build_id, avd_spec=avd_spec,
+        kernel_build_id=kernel_build_id, kernel_branch=kernel_branch,
+        system_branch=system_branch, system_build_id=system_build_id,
+        system_build_target=system_build_target)
     return common_operations.CreateDevices("create_cf", cfg, device_factory,
                                            num, constants.TYPE_CF,
                                            report_internal_ip, autoconnect,
diff --git a/public/actions/create_cuttlefish_action_test.py b/public/actions/create_cuttlefish_action_test.py
index 1e61412..4b57de2 100644
--- a/public/actions/create_cuttlefish_action_test.py
+++ b/public/actions/create_cuttlefish_action_test.py
@@ -44,6 +44,9 @@
     KERNEL_BUILD_ID = "54321"
     KERNEL_BUILD_TARGET = "kernel"
     BRANCH = "fake-branch"
+    SYSTEM_BRANCH = "fake-system-branch"
+    SYSTEM_BUILD_ID = "23456"
+    SYSTEM_BUILD_TARGET = "fake-system-build-target"
     STABLE_HOST_IMAGE_NAME = "fake-stable-host-image-name"
     STABLE_HOST_IMAGE_PROJECT = "fake-stable-host-image-project"
     EXTRA_DATA_DISK_GB = 4
@@ -100,14 +103,18 @@
 
         # Mock build client method
         self.build_client.GetBranch.side_effect = [self.BRANCH,
-                                                   self.KERNEL_BRANCH]
+                                                   self.KERNEL_BRANCH,
+                                                   self.SYSTEM_BRANCH]
 
         # Setup avd_spec as None to use cfg to create devices
         none_avd_spec = None
 
         # Call CreateDevices
         report = create_cuttlefish_action.CreateDevices(
-            none_avd_spec, cfg, self.BUILD_TARGET, self.BUILD_ID, self.KERNEL_BUILD_ID)
+            none_avd_spec, cfg, self.BUILD_TARGET, self.BUILD_ID,
+            self.KERNEL_BUILD_ID, system_build_target=self.SYSTEM_BUILD_TARGET,
+            system_branch=self.SYSTEM_BRANCH,
+            system_build_id=self.SYSTEM_BUILD_ID)
 
         # Verify
         self.compute_client.CreateInstance.assert_called_with(
@@ -119,6 +126,9 @@
             build_id=self.BUILD_ID,
             kernel_branch=self.KERNEL_BRANCH,
             kernel_build_id=self.KERNEL_BUILD_ID,
+            system_branch=self.SYSTEM_BRANCH,
+            system_build_id=self.SYSTEM_BUILD_ID,
+            system_build_target=self.SYSTEM_BUILD_TARGET,
             blank_data_disk_size_gb=self.EXTRA_DATA_DISK_GB,
             avd_spec=none_avd_spec,
             extra_scopes=self.EXTRA_SCOPES)
@@ -132,6 +142,9 @@
                     "kernel_branch": self.KERNEL_BRANCH,
                     "kernel_build_id": self.KERNEL_BUILD_ID,
                     "kernel_build_target": self.KERNEL_BUILD_TARGET,
+                    "system_branch": self.SYSTEM_BRANCH,
+                    "system_build_id": self.SYSTEM_BUILD_ID,
+                    "system_build_target": self.SYSTEM_BUILD_TARGET,
                     "instance_name": self.INSTANCE,
                     "ip": self.IP.external,
                 },