Snap for 6258215 from da7716fdad56e66839a9248ec90dfbcd3fcb1649 to r-keystone-qcom-release

Change-Id: I3caededd5028a55ba23d3fc176f846adb104bd59
diff --git a/create/avd_spec.py b/create/avd_spec.py
index fed31a5..b34ad03 100644
--- a/create/avd_spec.py
+++ b/create/avd_spec.py
@@ -26,6 +26,7 @@
 import re
 import subprocess
 import tempfile
+import threading
 
 from acloud import errors
 from acloud.create import create_common
@@ -41,7 +42,8 @@
 
 # Default values for build target.
 _BRANCH_RE = re.compile(r"^Manifest branch: (?P<branch>.+)")
-_COMMAND_REPO_INFO = ["repo", "info"]
+_COMMAND_REPO_INFO = "repo info platform/tools/acloud"
+_REPO_TIMEOUT = 3
 _CF_ZIP_PATTERN = "*img*.zip"
 _DEFAULT_BUILD_BITNESS = "x86"
 _DEFAULT_BUILD_TYPE = "userdebug"
@@ -88,7 +90,7 @@
 
 
 # pylint: disable=too-many-public-methods
-class AVDSpec(object):
+class AVDSpec:
     """Class to store data on the type of AVD to create."""
 
     def __init__(self, args):
@@ -575,19 +577,31 @@
         Returns:
             branch: String, git branch name. e.g. "aosp-master"
         """
-        repo_output = ""
-        try:
-            repo_output = subprocess.check_output(_COMMAND_REPO_INFO)
-        except subprocess.CalledProcessError:
-            utils.PrintColorString(
-                "Unable to determine your repo branch, defaulting to %s"
-                % _DEFAULT_BRANCH, utils.TextColors.WARNING)
-        for line in repo_output.splitlines():
-            match = _BRANCH_RE.match(EscapeAnsi(line))
-            if match:
-                branch_prefix = _BRANCH_PREFIX.get(self._GetGitRemote(),
-                                                   _DEFAULT_BRANCH_PREFIX)
-                return branch_prefix + match.group("branch")
+        branch = None
+        # TODO(149460014): Migrate acloud to py3, then remove this
+        # workaround.
+        env = os.environ.copy()
+        env.pop("PYTHONPATH", None)
+        logger.info("Running command \"%s\"", _COMMAND_REPO_INFO)
+        process = subprocess.Popen(_COMMAND_REPO_INFO, shell=True, stdin=None,
+                                   stdout=subprocess.PIPE,
+                                   stderr=subprocess.STDOUT, env=env)
+        timer = threading.Timer(_REPO_TIMEOUT, process.kill)
+        timer.start()
+        stdout, _ = process.communicate()
+        if stdout:
+            for line in stdout.splitlines():
+                match = _BRANCH_RE.match(EscapeAnsi(line))
+                if match:
+                    branch_prefix = _BRANCH_PREFIX.get(self._GetGitRemote(),
+                                                       _DEFAULT_BRANCH_PREFIX)
+                    branch = branch_prefix + match.group("branch")
+        timer.cancel()
+        if branch:
+            return branch
+        utils.PrintColorString(
+            "Unable to determine your repo branch, defaulting to %s"
+            % _DEFAULT_BRANCH, utils.TextColors.WARNING)
         return _DEFAULT_BRANCH
 
     def _GetBuildTarget(self, args):
@@ -661,6 +675,14 @@
         return self._autoconnect is not False
 
     @property
+    def connect_adb(self):
+        """Auto-connect to adb.
+
+        Return: Boolean, whether autoconnect is enabled.
+        """
+        return self._autoconnect is not False
+
+    @property
     def connect_vnc(self):
         """Launch vnc.
 
@@ -746,6 +768,7 @@
         """Return the Cheeps host image name."""
         return self._stable_cheeps_host_image_name
 
+    # pylint: disable=invalid-name
     @property
     def stable_cheeps_host_image_project(self):
         """Return the project hosting the Cheeps host image."""
diff --git a/create/avd_spec_test.py b/create/avd_spec_test.py
index 0c323f5..22c1db5 100644
--- a/create/avd_spec_test.py
+++ b/create/avd_spec_test.py
@@ -15,6 +15,7 @@
 
 import glob
 import os
+import subprocess
 import unittest
 import mock
 
@@ -129,21 +130,32 @@
                          "/test_path_to_dir/avd-system.tar.gz")
 
     @mock.patch.object(avd_spec.AVDSpec, "_GetGitRemote")
-    @mock.patch("subprocess.check_output")
-    def testGetBranchFromRepo(self, mock_repo, mock_gitremote):
+    def testGetBranchFromRepo(self, mock_gitremote):
         """Test get branch name from repo info."""
         # Check aosp repo gets proper branch prefix.
+        fake_subprocess = mock.MagicMock()
+        fake_subprocess.stdout = mock.MagicMock()
+        fake_subprocess.stdout.readline = mock.MagicMock(return_value='')
+        fake_subprocess.poll = mock.MagicMock(return_value=0)
+        fake_subprocess.returncode = 0
+        return_value = "Manifest branch: master"
+        fake_subprocess.communicate = mock.MagicMock(return_value=(return_value, ''))
+        self.Patch(subprocess, "Popen", return_value=fake_subprocess)
+
         mock_gitremote.return_value = "aosp"
-        mock_repo.return_value = "Manifest branch: master"
         self.assertEqual(self.AvdSpec._GetBranchFromRepo(), "aosp-master")
 
         # Check default repo gets default branch prefix.
         mock_gitremote.return_value = ""
-        mock_repo.return_value = "Manifest branch: master"
+        return_value = "Manifest branch: master"
+        fake_subprocess.communicate = mock.MagicMock(return_value=(return_value, ''))
+        self.Patch(subprocess, "Popen", return_value=fake_subprocess)
         self.assertEqual(self.AvdSpec._GetBranchFromRepo(), "git_master")
 
         # Can't get branch from repo info, set it as default branch.
-        mock_repo.return_value = "Manifest branch:"
+        return_value = "Manifest branch:"
+        fake_subprocess.communicate = mock.MagicMock(return_value=(return_value, ''))
+        self.Patch(subprocess, "Popen", return_value=fake_subprocess)
         self.assertEqual(self.AvdSpec._GetBranchFromRepo(), "aosp-master")
 
     def testGetBuildBranch(self):
@@ -358,24 +370,28 @@
         self.args.autoconnect = False
         self.AvdSpec._ProcessMiscArgs(self.args)
         self.assertEqual(self.AvdSpec.autoconnect, False)
+        self.assertEqual(self.AvdSpec.connect_adb, False)
         self.assertEqual(self.AvdSpec.connect_vnc, False)
         self.assertEqual(self.AvdSpec.connect_webrtc, False)
 
         self.args.autoconnect = constants.INS_KEY_VNC
         self.AvdSpec._ProcessMiscArgs(self.args)
         self.assertEqual(self.AvdSpec.autoconnect, True)
+        self.assertEqual(self.AvdSpec.connect_adb, True)
         self.assertEqual(self.AvdSpec.connect_vnc, True)
         self.assertEqual(self.AvdSpec.connect_webrtc, False)
 
         self.args.autoconnect = constants.INS_KEY_ADB
         self.AvdSpec._ProcessMiscArgs(self.args)
         self.assertEqual(self.AvdSpec.autoconnect, True)
+        self.assertEqual(self.AvdSpec.connect_adb, True)
         self.assertEqual(self.AvdSpec.connect_vnc, False)
         self.assertEqual(self.AvdSpec.connect_webrtc, False)
 
         self.args.autoconnect = constants.INS_KEY_WEBRTC
         self.AvdSpec._ProcessMiscArgs(self.args)
         self.assertEqual(self.AvdSpec.autoconnect, True)
+        self.assertEqual(self.AvdSpec.connect_adb, True)
         self.assertEqual(self.AvdSpec.connect_vnc, False)
         self.assertEqual(self.AvdSpec.connect_webrtc, True)
 
diff --git a/create/local_image_local_instance.py b/create/local_image_local_instance.py
index d40dd5e..0ee5ee8 100644
--- a/create/local_image_local_instance.py
+++ b/create/local_image_local_instance.py
@@ -34,7 +34,6 @@
 [CUTTLEFISH_CONFIG_FILE] which is pointing to the runtime cuttlefish json.
 """
 
-import json
 import logging
 import os
 import shutil
@@ -44,7 +43,6 @@
 
 from acloud import errors
 from acloud.create import base_avd_create
-from acloud.delete import delete
 from acloud.internal import constants
 from acloud.internal.lib import utils
 from acloud.internal.lib.adb_tools import AdbTools
@@ -56,15 +54,13 @@
 logger = logging.getLogger(__name__)
 
 _CMD_LAUNCH_CVD_ARGS = (" -daemon -cpus %s -x_res %s -y_res %s -dpi %s "
-                        "-memory_mb %s -system_image_dir %s "
-                        "-instance_dir %s")
+                        "-memory_mb %s -run_adb_connector=%s "
+                        "-system_image_dir %s -instance_dir %s")
 _CMD_LAUNCH_CVD_DISK_ARGS = (" -blank_data_image_mb %s "
                              "-data_policy always_create")
 _CONFIRM_RELAUNCH = ("\nCuttlefish AVD[id:%d] is already running. \n"
                      "Enter 'y' to terminate current instance and launch a new "
                      "instance, enter anything else to exit out[y/N]: ")
-_ENV_CVD_HOME = "HOME"
-_ENV_CUTTLEFISH_INSTANCE = "CUTTLEFISH_INSTANCE"
 _LAUNCH_CVD_TIMEOUT_SECS = 120  # default timeout as 120 seconds
 _LAUNCH_CVD_TIMEOUT_ERROR = ("Cuttlefish AVD launch timeout, did not complete "
                              "within %d secs.")
@@ -102,13 +98,13 @@
                                        constants.CMD_LAUNCH_CVD)
         cmd = self.PrepareLaunchCVDCmd(launch_cvd_path,
                                        avd_spec.hw_property,
+                                       avd_spec.connect_adb,
                                        local_image_path,
                                        avd_spec.local_instance_id)
 
         result_report = report.Report(command="create")
         instance_name = instance.GetLocalInstanceName(
             avd_spec.local_instance_id)
-        local_ports = instance.GetLocalPortsbyInsId(avd_spec.local_instance_id)
         try:
             self.CheckLaunchCVD(
                 cmd, host_bins_path, avd_spec.local_instance_id, local_image_path,
@@ -116,18 +112,27 @@
         except errors.LaunchCVDFail as launch_error:
             result_report.SetStatus(report.Status.BOOT_FAIL)
             result_report.AddDeviceBootFailure(
-                instance_name, constants.LOCALHOST, local_ports.adb_port,
-                local_ports.vnc_port, str(launch_error))
+                instance_name, constants.LOCALHOST, None, None,
+                error=str(launch_error))
             return result_report
 
-        result_report.SetStatus(report.Status.SUCCESS)
-        result_report.AddDevice(instance_name, constants.LOCALHOST,
-                                local_ports.adb_port, local_ports.vnc_port)
-        # Launch vnc client if we're auto-connecting.
-        if avd_spec.connect_vnc:
-            utils.LaunchVNCFromReport(result_report, avd_spec, no_prompts)
-        if avd_spec.unlock_screen:
-            AdbTools(local_ports.adb_port).AutoUnlockScreen()
+        active_ins = list_instance.GetActiveCVD(avd_spec.local_instance_id)
+        if active_ins:
+            result_report.SetStatus(report.Status.SUCCESS)
+            result_report.AddDevice(instance_name, constants.LOCALHOST,
+                                    active_ins.adb_port, active_ins.vnc_port)
+            # Launch vnc client if we're auto-connecting.
+            if avd_spec.connect_vnc:
+                utils.LaunchVNCFromReport(result_report, avd_spec, no_prompts)
+            if avd_spec.unlock_screen:
+                AdbTools(active_ins.adb_port).AutoUnlockScreen()
+        else:
+            err_msg = "cvd_status return non-zero after launch_cvd"
+            logger.error(err_msg)
+            result_report.SetStatus(report.Status.BOOT_FAIL)
+            result_report.AddDeviceBootFailure(
+                instance_name, constants.LOCALHOST, None, None, error=err_msg)
+
         return result_report
 
     @staticmethod
@@ -166,8 +171,8 @@
                 self._FindCvdHostBinaries(avd_spec.local_tool_dirs))
 
     @staticmethod
-    def PrepareLaunchCVDCmd(launch_cvd_path, hw_property, system_image_dir,
-                            local_instance_id):
+    def PrepareLaunchCVDCmd(launch_cvd_path, hw_property, connect_adb,
+                            system_image_dir, local_instance_id):
         """Prepare launch_cvd command.
 
         Create the launch_cvd commands with all the required args and add
@@ -177,6 +182,7 @@
             launch_cvd_path: String of launch_cvd path.
             hw_property: dict object of hw property.
             system_image_dir: String of local images path.
+            connect_adb: Boolean flag that enables adb_connector.
             local_instance_id: Integer of instance id.
 
         Returns:
@@ -185,7 +191,8 @@
         instance_dir = instance.GetLocalInstanceRuntimeDir(local_instance_id)
         launch_cvd_w_args = launch_cvd_path + _CMD_LAUNCH_CVD_ARGS % (
             hw_property["cpu"], hw_property["x_res"], hw_property["y_res"],
-            hw_property["dpi"], hw_property["memory"], system_image_dir,
+            hw_property["dpi"], hw_property["memory"],
+            ("true" if connect_adb else "false"), system_image_dir,
             instance_dir)
         if constants.HW_ALIAS_DISK in hw_property:
             launch_cvd_w_args = (launch_cvd_w_args + _CMD_LAUNCH_CVD_DISK_ARGS %
@@ -218,10 +225,11 @@
         # different dir (e.g. downloaded image).
         os.environ[constants.ENV_ANDROID_HOST_OUT] = host_bins_path
         # Check if the instance with same id is running.
-        if self.IsLocalCVDRunning(local_instance_id):
+        existing_ins = list_instance.GetActiveCVD(local_instance_id)
+        if existing_ins:
             if no_prompts or utils.GetUserAnswerYes(_CONFIRM_RELAUNCH %
                                                     local_instance_id):
-                self._StopCvd(host_bins_path, local_instance_id)
+                existing_ins.Delete()
             else:
                 sys.exit(constants.EXIT_BY_USER)
         else:
@@ -239,36 +247,6 @@
         self._LaunchCvd(cmd, local_instance_id, timeout=timeout_secs)
 
     @staticmethod
-    def _StopCvd(host_bins_path, local_instance_id):
-        """Execute stop_cvd to stop cuttlefish instance.
-
-        Args:
-            host_bins_path: String of host package directory.
-            local_instance_id: Integer of instance id.
-        """
-        stop_cvd_cmd = os.path.join(host_bins_path,
-                                    "bin",
-                                    constants.CMD_STOP_CVD)
-        with open(os.devnull, "w") as dev_null:
-            cvd_env = os.environ.copy()
-            cvd_env[constants.ENV_CUTTLEFISH_CONFIG_FILE] = os.path.join(
-                instance.GetLocalInstanceRuntimeDir(local_instance_id),
-                constants.CUTTLEFISH_CONFIG_FILE)
-            subprocess.check_call(
-                utils.AddUserGroupsToCmd(
-                    stop_cvd_cmd, constants.LIST_CF_USER_GROUPS),
-                stderr=dev_null, stdout=dev_null, shell=True, env=cvd_env)
-
-        # Delete ssvnc viewer
-        local_ports = instance.GetLocalPortsbyInsId(local_instance_id)
-        delete.CleanupSSVncviewer(local_ports.vnc_port)
-        # Disconnect adb device
-        adb_cmd = AdbTools(local_ports.adb_port)
-        # When relaunch a local instance, we need to pass in retry=True to make
-        # sure adb device is completely gone since it will use the same adb port
-        adb_cmd.DisconnectAdb(retry=True)
-
-    @staticmethod
     @utils.TimeExecute(function_description="Waiting for AVD(s) to boot up")
     def _LaunchCvd(cmd, local_instance_id, timeout=None):
         """Execute Launch CVD.
@@ -291,8 +269,8 @@
         os.makedirs(cvd_runtime_dir)
 
         cvd_env = os.environ.copy()
-        cvd_env[_ENV_CVD_HOME] = cvd_home_dir
-        cvd_env[_ENV_CUTTLEFISH_INSTANCE] = str(local_instance_id)
+        cvd_env[constants.ENV_CVD_HOME] = cvd_home_dir
+        cvd_env[constants.ENV_CUTTLEFISH_INSTANCE] = str(local_instance_id)
         # Check the result of launch_cvd command.
         # An exit code of 0 is equivalent to VIRTUAL_DEVICE_BOOT_COMPLETED
         process = subprocess.Popen(cmd, shell=True, stderr=subprocess.STDOUT,
@@ -318,19 +296,6 @@
             utils.TextColors.WARNING)
 
     @staticmethod
-    def IsLocalCVDRunning(local_instance_id):
-        """Check if the AVD with specific instance id is running
-
-        Args:
-            local_instance_id: Integer of instance id.
-
-        Return:
-            Boolean, True if AVD is running.
-        """
-        local_ports = instance.GetLocalPortsbyInsId(local_instance_id)
-        return AdbTools(local_ports.adb_port).IsAdbConnected()
-
-    @staticmethod
     def IsLocalImageOccupied(local_image_dir):
         """Check if the given image path is being used by a running CVD process.
 
@@ -340,15 +305,12 @@
         Return:
             Integer of instance id which using the same image path.
         """
-        local_cvd_ids = list_instance.GetActiveCVDIds()
-        for cvd_id in local_cvd_ids:
-            cvd_config_path = os.path.join(instance.GetLocalInstanceRuntimeDir(
-                cvd_id), constants.CUTTLEFISH_CONFIG_FILE)
-            if not os.path.isfile(cvd_config_path):
-                continue
-            with open(cvd_config_path, "r") as config_file:
-                json_array = json.load(config_file)
-                for disk_path in json_array[_VIRTUAL_DISK_PATHS]:
+        # TODO(149602560): Remove occupied image checking after after cf disk
+        # overlay is stable
+        for cf_runtime_config_path in instance.GetAllLocalInstanceConfigs():
+            ins = instance.LocalInstance(cf_runtime_config_path)
+            if ins.CvdStatus():
+                for disk_path in ins.virtual_disk_paths:
                     if local_image_dir in disk_path:
-                        return cvd_id
+                        return ins.instance_id
         return None
diff --git a/create/local_image_local_instance_test.py b/create/local_image_local_instance_test.py
index eaa43a5..d1a0acc 100644
--- a/create/local_image_local_instance_test.py
+++ b/create/local_image_local_instance_test.py
@@ -24,6 +24,7 @@
 from acloud import errors
 from acloud.create import local_image_local_instance
 from acloud.list import instance
+from acloud.list import list as list_instance
 from acloud.internal import constants
 from acloud.internal.lib import driver_test_lib
 from acloud.internal.lib import utils
@@ -34,12 +35,12 @@
 
     LAUNCH_CVD_CMD_WITH_DISK = """sg group1 <<EOF
 sg group2
-launch_cvd -daemon -cpus fake -x_res fake -y_res fake -dpi fake -memory_mb fake -system_image_dir fake_image_dir -instance_dir fake_cvd_dir -blank_data_image_mb fake -data_policy always_create
+launch_cvd -daemon -cpus fake -x_res fake -y_res fake -dpi fake -memory_mb fake -run_adb_connector=true -system_image_dir fake_image_dir -instance_dir fake_cvd_dir -blank_data_image_mb fake -data_policy always_create
 EOF"""
 
     LAUNCH_CVD_CMD_NO_DISK = """sg group1 <<EOF
 sg group2
-launch_cvd -daemon -cpus fake -x_res fake -y_res fake -dpi fake -memory_mb fake -system_image_dir fake_image_dir -instance_dir fake_cvd_dir
+launch_cvd -daemon -cpus fake -x_res fake -y_res fake -dpi fake -memory_mb fake -run_adb_connector=true -system_image_dir fake_image_dir -instance_dir fake_cvd_dir
 EOF"""
 
     _EXPECTED_DEVICES_IN_REPORT = [
@@ -51,6 +52,13 @@
         }
     ]
 
+    _EXPECTED_DEVICES_IN_FAILED_REPORT = [
+        {
+            "instance_name": "local-instance-1",
+            "ip": "127.0.0.1"
+        }
+    ]
+
     def setUp(self):
         """Initialize new LocalImageLocalInstance."""
         super(LocalImageLocalInstanceTest, self).setUp()
@@ -58,7 +66,6 @@
 
     # pylint: disable=protected-access
     @mock.patch("acloud.create.local_image_local_instance.utils")
-    @mock.patch("acloud.create.local_image_local_instance.instance")
     @mock.patch.object(local_image_local_instance.LocalImageLocalInstance,
                        "PrepareLaunchCVDCmd")
     @mock.patch.object(local_image_local_instance.LocalImageLocalInstance,
@@ -66,17 +73,23 @@
     @mock.patch.object(local_image_local_instance.LocalImageLocalInstance,
                        "CheckLaunchCVD")
     def testCreateAVD(self, mock_check_launch_cvd, mock_get_image,
-                      _mock_prepare, mock_instance, mock_utils):
+                      _mock_prepare, mock_utils):
         """Test the report returned by _CreateAVD."""
         mock_utils.IsSupportedPlatform.return_value = True
-
-        mock_instance.GetLocalInstanceName.return_value = "local-instance-1"
-        mock_instance.GetLocalPortsbyInsId.return_value = mock.Mock(
-            adb_port=6520, vnc_port=6444)
-
         mock_get_image.return_value = ("/image/path", "/host/bin/path")
+        mock_avd_spec = mock.Mock(connect_adb=False, unlock_screen=False)
+        self.Patch(instance, "GetLocalInstanceName",
+                   return_value="local-instance-1")
+        local_ins = mock.MagicMock(
+            adb_port=6520,
+            vnc_port=6444
+        )
+        local_ins.CvdStatus.return_value = True
+        self.Patch(instance, "LocalInstance",
+                   return_value=local_ins)
+        self.Patch(list_instance, "GetActiveCVD",
+                   return_value=local_ins)
 
-        mock_avd_spec = mock.Mock(autoconnect=False, unlock_screen=False)
         # Success
         report = self.local_image_local_instance._CreateAVD(
             mock_avd_spec, no_prompts=True)
@@ -90,7 +103,7 @@
             mock_avd_spec, no_prompts=True)
 
         self.assertEqual(report.data.get("devices_failing_boot"),
-                         self._EXPECTED_DEVICES_IN_REPORT)
+                         self._EXPECTED_DEVICES_IN_FAILED_REPORT)
         self.assertEqual(report.errors, ["timeout"])
 
     # pylint: disable=protected-access
@@ -132,7 +145,7 @@
         constants.LIST_CF_USER_GROUPS = ["group1", "group2"]
 
         launch_cmd = self.local_image_local_instance.PrepareLaunchCVDCmd(
-            constants.CMD_LAUNCH_CVD, hw_property, "fake_image_dir",
+            constants.CMD_LAUNCH_CVD, hw_property, True, "fake_image_dir",
             "fake_cvd_dir")
         self.assertEqual(launch_cmd, self.LAUNCH_CVD_CMD_WITH_DISK)
 
@@ -140,15 +153,14 @@
         hw_property = {"cpu": "fake", "x_res": "fake", "y_res": "fake",
                        "dpi":"fake", "memory": "fake"}
         launch_cmd = self.local_image_local_instance.PrepareLaunchCVDCmd(
-            constants.CMD_LAUNCH_CVD, hw_property, "fake_image_dir",
+            constants.CMD_LAUNCH_CVD, hw_property, True, "fake_image_dir",
             "fake_cvd_dir")
         self.assertEqual(launch_cmd, self.LAUNCH_CVD_CMD_NO_DISK)
 
     @mock.patch.object(local_image_local_instance.LocalImageLocalInstance,
                        "_LaunchCvd")
     @mock.patch.object(utils, "GetUserAnswerYes")
-    @mock.patch.object(local_image_local_instance.LocalImageLocalInstance,
-                       "IsLocalCVDRunning")
+    @mock.patch.object(list_instance, "GetActiveCVD")
     @mock.patch.object(local_image_local_instance.LocalImageLocalInstance,
                        "IsLocalImageOccupied")
     def testCheckLaunchCVD(self, mock_image_occupied, mock_cvd_running,
@@ -195,8 +207,8 @@
         local_instance_id = 3
         launch_cvd_cmd = "launch_cvd"
         cvd_env = {}
-        cvd_env[local_image_local_instance._ENV_CVD_HOME] = "fake_home"
-        cvd_env[local_image_local_instance._ENV_CUTTLEFISH_INSTANCE] = str(
+        cvd_env[constants.ENV_CVD_HOME] = "fake_home"
+        cvd_env[constants.ENV_CUTTLEFISH_INSTANCE] = str(
             local_instance_id)
         process = mock.MagicMock()
         process.wait.return_value = True
diff --git a/delete/delete.py b/delete/delete.py
index 86b0a42..02ee484 100644
--- a/delete/delete.py
+++ b/delete/delete.py
@@ -20,7 +20,6 @@
 from __future__ import print_function
 
 import logging
-import os
 import re
 import subprocess
 
@@ -42,53 +41,9 @@
 _COMMAND_GET_PROCESS_ID = ["pgrep", "run_cvd"]
 _COMMAND_GET_PROCESS_COMMAND = ["ps", "-o", "command", "-p"]
 _RE_RUN_CVD = re.compile(r"^(?P<run_cvd>.+run_cvd)")
-_SSVNC_VIEWER_PATTERN = "vnc://127.0.0.1:%(vnc_port)d"
 _LOCAL_INSTANCE_PREFIX = "local-"
 
 
-def _GetStopCvd():
-    """Get stop_cvd path.
-
-    "stop_cvd" and "run_cvd" are in the same folder(host package folder).
-    Try to get directory of "run_cvd" by "ps -o command -p <pid>." command.
-    For example: "/tmp/bin/run_cvd"
-
-    Returns:
-        String of stop_cvd file path.
-
-    Raises:
-        errors.NoExecuteCmd: Can't find stop_cvd.
-    """
-    process_id = subprocess.check_output(_COMMAND_GET_PROCESS_ID)
-    process_info = subprocess.check_output(
-        _COMMAND_GET_PROCESS_COMMAND + process_id.splitlines())
-    for process in process_info.splitlines():
-        match = _RE_RUN_CVD.match(process)
-        if match:
-            run_cvd_path = match.group("run_cvd")
-            stop_cvd_cmd = os.path.join(os.path.dirname(run_cvd_path),
-                                        constants.CMD_STOP_CVD)
-            if os.path.exists(stop_cvd_cmd):
-                logger.debug("stop_cvd command: %s", stop_cvd_cmd)
-                return stop_cvd_cmd
-
-    default_stop_cvd = utils.FindExecutable(constants.CMD_STOP_CVD)
-    if default_stop_cvd:
-        return default_stop_cvd
-
-    raise errors.NoExecuteCmd("Cannot find stop_cvd binary.")
-
-
-def CleanupSSVncviewer(vnc_port):
-    """Cleanup the old disconnected ssvnc viewer.
-
-    Args:
-        vnc_port: Integer, port number of vnc.
-    """
-    ssvnc_viewer_pattern = _SSVNC_VIEWER_PATTERN % {"vnc_port":vnc_port}
-    utils.CleanupProcess(ssvnc_viewer_pattern)
-
-
 def DeleteInstances(cfg, instances_to_delete):
     """Delete instances according to instances_to_delete.
 
@@ -118,8 +73,8 @@
         else:
             remote_instance_list.append(instance.name)
         # Delete ssvnc viewer
-        if instance.forwarding_vnc_port:
-            CleanupSSVncviewer(instance.forwarding_vnc_port)
+        if instance.vnc_port:
+            utils.CleanupSSVncviewer(instance.vnc_port)
 
     if remote_instance_list:
         # TODO(119283708): We should move DeleteAndroidVirtualDevices into
@@ -171,7 +126,7 @@
 def DeleteLocalCuttlefishInstance(instance, delete_report):
     """Delete a local cuttlefish instance.
 
-    Delete local instance with stop_cvd command and write delete instance
+    Delete local instance and write delete instance
     information to report.
 
     Args:
@@ -182,21 +137,12 @@
         delete_report.
     """
     try:
-        with open(os.devnull, "w") as dev_null:
-            cvd_env = os.environ.copy()
-            if instance.instance_dir:
-                cvd_env[constants.ENV_CUTTLEFISH_CONFIG_FILE] = os.path.join(
-                    instance.instance_dir, constants.CUTTLEFISH_CONFIG_FILE)
-            subprocess.check_call(
-                utils.AddUserGroupsToCmd(_GetStopCvd(),
-                                         constants.LIST_CF_USER_GROUPS),
-                stderr=dev_null, stdout=dev_null, shell=True, env=cvd_env)
-            delete_report.SetStatus(report.Status.SUCCESS)
-            device_driver.AddDeletionResultToReport(
-                delete_report, [instance.name], failed=[],
-                error_msgs=[],
-                resource_name="instance")
-            CleanupSSVncviewer(instance.vnc_port)
+        instance.Delete()
+        delete_report.SetStatus(report.Status.SUCCESS)
+        device_driver.AddDeletionResultToReport(
+            delete_report, [instance.name], failed=[],
+            error_msgs=[],
+            resource_name="instance")
     except subprocess.CalledProcessError as e:
         delete_report.AddError(str(e))
         delete_report.SetStatus(report.Status.FAIL)
diff --git a/delete/delete_test.py b/delete/delete_test.py
index 49cef1c..829ab7b 100644
--- a/delete/delete_test.py
+++ b/delete/delete_test.py
@@ -14,12 +14,10 @@
 """Tests for delete."""
 
 import unittest
-import subprocess
 import mock
 
 from acloud.delete import delete
 from acloud.internal.lib import driver_test_lib
-from acloud.internal.lib import utils
 from acloud.list import list as list_instances
 from acloud.public import report
 
@@ -28,20 +26,8 @@
 class DeleteTest(driver_test_lib.BaseDriverTest):
     """Test delete functions."""
 
-    # pylint: disable=protected-access
-    @mock.patch("os.path.exists", return_value=True)
-    @mock.patch("subprocess.check_output")
-    def testGetStopcvd(self, mock_subprocess, mock_path_exist):
-        """Test _GetStopCvd."""
-        mock_subprocess.side_effect = ["fake_id",
-                                       "/tmp/bin/run_cvd"]
-        expected_value = "/tmp/bin/stop_cvd"
-        self.assertEqual(expected_value, delete._GetStopCvd())
-
-    @mock.patch.object(delete, "_GetStopCvd", return_value="")
     @mock.patch("subprocess.check_call")
-    def testDeleteLocalCuttlefishInstance(self, mock_subprocess,
-                                          mock_get_stopcvd):
+    def testDeleteLocalCuttlefishInstance(self, mock_subprocess):
         """Test DeleteLocalCuttlefishInstance."""
         mock_subprocess.return_value = True
         instance_object = mock.MagicMock()
@@ -108,21 +94,6 @@
         self.assertTrue(len(delete_report.errors) > 0)
         self.assertEqual(delete_report.status, "FAIL")
 
-    # pylint: disable=protected-access, no-member
-    def testCleanupSSVncviwer(self):
-        """test cleanup ssvnc viewer."""
-        fake_vnc_port = 9999
-        fake_ss_vncviewer_pattern = delete._SSVNC_VIEWER_PATTERN % {
-            "vnc_port": fake_vnc_port}
-        self.Patch(utils, "IsCommandRunning", return_value=True)
-        self.Patch(subprocess, "check_call", return_value=True)
-        delete.CleanupSSVncviewer(fake_vnc_port)
-        subprocess.check_call.assert_called_with(["pkill", "-9", "-f", fake_ss_vncviewer_pattern])
-
-        subprocess.check_call.call_count = 0
-        self.Patch(utils, "IsCommandRunning", return_value=False)
-        subprocess.check_call.assert_not_called()
-
     @mock.patch.object(delete, "DeleteInstances", return_value="")
     @mock.patch.object(delete, "DeleteRemoteInstances", return_value="")
     def testDeleteInstanceByNames(self, mock_delete_remote_ins,
diff --git a/internal/constants.py b/internal/constants.py
index fb95d44..c530244 100755
--- a/internal/constants.py
+++ b/internal/constants.py
@@ -150,6 +150,8 @@
 INS_STATUS_RUNNING = "RUNNING"
 LOCAL_INS_NAME = "local-instance"
 ENV_CUTTLEFISH_CONFIG_FILE = "CUTTLEFISH_CONFIG_FILE"
+ENV_CUTTLEFISH_INSTANCE = "CUTTLEFISH_INSTANCE"
+ENV_CVD_HOME = "HOME"
 CUTTLEFISH_CONFIG_FILE = "cuttlefish_config.json"
 
 TEMP_ARTIFACTS_FOLDER = "acloud_image_artifacts"
diff --git a/internal/lib/cvd_runtime_config.py b/internal/lib/cvd_runtime_config.py
index f15af2e..fd5bba6 100644
--- a/internal/lib/cvd_runtime_config.py
+++ b/internal/lib/cvd_runtime_config.py
@@ -75,16 +75,16 @@
     "memory_mb" : 4096,
     "cpus" : 2,
     "dpi" : 320,
-    "virtual_disk_paths" :
-        [
-            "/path-to-image"
-        ],
     "instances" :
         {
             "1" :
             {
                 "adb_ip_and_port" : "127.0.0.1:6520",
                 "instance_dir" : "/path-to-instance-dir",
+                "virtual_disk_paths" :
+                [
+                    "/path-to-image"
+                ],
             }
         }
     }
@@ -101,8 +101,6 @@
         adb_connector = self._config_dict.get(_CFG_KEY_ADB_CONNECTOR_BINARY)
         self._cvd_tools_path = (os.path.dirname(adb_connector)
                                 if adb_connector else None)
-        self._virtual_disk_paths = self._config_dict.get(
-            _CFG_KEY_VIRTUAL_DISK_PATHS)
 
         # Below properties will be collected inside of instance id node if there
         # are more than one instance.
@@ -110,6 +108,8 @@
         self._vnc_port = self._config_dict.get(_CFG_KEY_VNC_PORT)
         self._adb_port = self._config_dict.get(_CFG_KEY_ADB_PORT)
         self._adb_ip_port = self._config_dict.get(_CFG_KEY_ADB_IP_PORT)
+        self._virtual_disk_paths = self._config_dict.get(
+            _CFG_KEY_VIRTUAL_DISK_PATHS)
         if not self._instance_dir:
             ins_cfg = self._config_dict.get(_CFG_KEY_INSTANCES)
             ins_dict = ins_cfg.get(self._instance_id)
@@ -121,6 +121,7 @@
             self._vnc_port = ins_dict.get(_CFG_KEY_VNC_PORT)
             self._adb_port = ins_dict.get(_CFG_KEY_ADB_PORT)
             self._adb_ip_port = ins_dict.get(_CFG_KEY_ADB_IP_PORT)
+            self._virtual_disk_paths = ins_dict.get(_CFG_KEY_VIRTUAL_DISK_PATHS)
 
     @staticmethod
     def _GetCuttlefishRuntimeConfig(runtime_cf_config_path):
diff --git a/internal/lib/utils.py b/internal/lib/utils.py
index e6790d3..a60c6c3 100755
--- a/internal/lib/utils.py
+++ b/internal/lib/utils.py
@@ -100,6 +100,7 @@
 # dict of supported system and their distributions.
 _SUPPORTED_SYSTEMS_AND_DISTS = {"Linux": ["Ubuntu", "Debian"]}
 _DEFAULT_TIMEOUT_ERR = "Function did not complete within %d secs."
+_SSVNC_VIEWER_PATTERN = "vnc://127.0.0.1:%(vnc_port)d"
 
 
 class TempDir(object):
@@ -917,14 +918,22 @@
     Args:
         report: Report object, that stores and generates report.
     """
+    PrintColorString("(This is an experimental project for webrtc, and since "
+                     "the certificate is self-signed, Chrome will mark it as "
+                     "an insecure website. keep going.)",
+                     TextColors.WARNING)
+
     for device in report.data.get("devices", []):
         if device.get("ip"):
-            PrintColorString("(This is an experimental project for webrtc, and "
-                             "since the certificate is self-signed, Chrome will "
-                             "mark it as an insecure website. keep going.)",
-                             TextColors.WARNING)
-            webbrowser.open_new_tab("%s%s:%s" % (
-                _WEBRTC_URL, device.get("ip"), _WEBRTC_PORT))
+            webrtc_link = "%s%s:%s" % (_WEBRTC_URL, device.get("ip"),
+                                       _WEBRTC_PORT)
+            if os.environ.get(_ENV_DISPLAY, None):
+                webbrowser.open_new_tab(webrtc_link)
+            else:
+                PrintColorString("Remote terminal can't support launch webbrowser.",
+                                 TextColors.FAIL)
+                PrintColorString("Open %s to remotely control AVD on the "
+                                 "browser." % webrtc_link)
         else:
             PrintColorString("Auto-launch devices webrtc in browser failed!",
                              TextColors.FAIL)
@@ -1251,3 +1260,13 @@
     """
     return (namedtuple_object.__dict__.items() if six.PY2
             else namedtuple_object._asdict().items())
+
+
+def CleanupSSVncviewer(vnc_port):
+    """Cleanup the old disconnected ssvnc viewer.
+
+    Args:
+        vnc_port: Integer, port number of vnc.
+    """
+    ssvnc_viewer_pattern = _SSVNC_VIEWER_PATTERN % {"vnc_port":vnc_port}
+    CleanupProcess(ssvnc_viewer_pattern)
diff --git a/internal/lib/utils_test.py b/internal/lib/utils_test.py
index 480b4d2..169a36d 100644
--- a/internal/lib/utils_test.py
+++ b/internal/lib/utils_test.py
@@ -411,6 +411,22 @@
         first_call_args = utils._ExecuteCommand.call_args_list[0][0]
         self.assertEqual(first_call_args[1], args_list)
 
+    # pylint: disable=protected-access, no-member
+    def testCleanupSSVncviwer(self):
+        """test cleanup ssvnc viewer."""
+        fake_vnc_port = 9999
+        fake_ss_vncviewer_pattern = utils._SSVNC_VIEWER_PATTERN % {
+            "vnc_port": fake_vnc_port}
+        self.Patch(utils, "IsCommandRunning", return_value=True)
+        self.Patch(subprocess, "check_call", return_value=True)
+        utils.CleanupSSVncviewer(fake_vnc_port)
+        subprocess.check_call.assert_called_with(["pkill", "-9", "-f", fake_ss_vncviewer_pattern])
+
+        subprocess.check_call.call_count = 0
+        self.Patch(utils, "IsCommandRunning", return_value=False)
+        utils.CleanupSSVncviewer(fake_vnc_port)
+        subprocess.check_call.assert_not_called()
+
 
 if __name__ == "__main__":
     unittest.main()
diff --git a/list/instance.py b/list/instance.py
index 8f91245..fb98960 100644
--- a/list/instance.py
+++ b/list/instance.py
@@ -48,6 +48,7 @@
 
 _ACLOUD_CVD_TEMP = os.path.join(tempfile.gettempdir(), "acloud_cvd_temp")
 _CVD_RUNTIME_FOLDER_NAME = "cuttlefish_runtime"
+_CVD_STATUS_BIN = "cvd_status"
 _MSG_UNABLE_TO_CALCULATE = "Unable to calculate"
 _RE_GROUP_ADB = "local_adb_port"
 _RE_GROUP_VNC = "local_vnc_port"
@@ -63,10 +64,21 @@
 _LOCAL_ZONE = "local"
 _FULL_NAME_STRING = ("device serial: %(device_serial)s (%(instance_name)s) "
                      "elapsed time: %(elapsed_time)s")
+_INDENT = " " * 3
 LocalPorts = collections.namedtuple("LocalPorts", [constants.VNC_PORT,
                                                    constants.ADB_PORT])
 
 
+def GetDefaultCuttlefishConfig():
+    """Get the path of default cuttlefish instance config.
+
+    Return:
+        String, path of cf runtime config.
+    """
+    return os.path.join(os.path.expanduser("~"), _CVD_RUNTIME_FOLDER_NAME,
+                        constants.CUTTLEFISH_CONFIG_FILE)
+
+
 def GetLocalInstanceName(local_instance_id):
     """Get local cuttlefish instance name by instance id.
 
@@ -79,8 +91,48 @@
     return "%s-%d" % (constants.LOCAL_INS_NAME, local_instance_id)
 
 
+def GetLocalInstanceConfig(local_instance_id):
+    """Get the path of instance config.
+
+    Args:
+        local_instance_id: Integer of instance id.
+
+    Return:
+        String, path of cf runtime config.
+    """
+    cfg_path = os.path.join(GetLocalInstanceRuntimeDir(local_instance_id),
+                            constants.CUTTLEFISH_CONFIG_FILE)
+    if os.path.isfile(cfg_path):
+        return cfg_path
+    return None
+
+
+def GetAllLocalInstanceConfigs():
+    """Get the list of instance config.
+
+    Return:
+        List of instance config path.
+    """
+    cfg_list = []
+    # Check if any instance config is under home folder.
+    cfg_path = GetDefaultCuttlefishConfig()
+    if os.path.isfile(cfg_path):
+        cfg_list.append(cfg_path)
+
+    # Check if any instance config is under acloud cvd temp folder.
+    if os.path.exists(_ACLOUD_CVD_TEMP):
+        for ins_name in os.listdir(_ACLOUD_CVD_TEMP):
+            cfg_path = os.path.join(_ACLOUD_CVD_TEMP,
+                                    ins_name,
+                                    _CVD_RUNTIME_FOLDER_NAME,
+                                    constants.CUTTLEFISH_CONFIG_FILE)
+            if os.path.isfile(cfg_path):
+                cfg_list.append(cfg_path)
+    return cfg_list
+
+
 def GetLocalInstanceHomeDir(local_instance_id):
-    """Get local instance home dir accroding to instance id.
+    """Get local instance home dir according to instance id.
 
     Args:
         local_instance_id: Integer of instance id.
@@ -105,34 +157,6 @@
                         _CVD_RUNTIME_FOLDER_NAME)
 
 
-def GetCuttlefishRuntimeConfig(local_instance_id):
-    """Get and parse cuttlefish_config.json.
-
-    Args:
-        local_instance_id: Integer of instance id.
-
-    Returns:
-        A CvdRuntimeConfig instance.
-    """
-    runtime_cf_config_path = os.path.join(GetLocalInstanceRuntimeDir(
-        local_instance_id), constants.CUTTLEFISH_CONFIG_FILE)
-    return cvd_runtime_config.CvdRuntimeConfig(runtime_cf_config_path)
-
-
-def GetLocalPortsbyInsId(local_instance_id):
-    """Get vnc and adb port by local instance id.
-
-    Args:
-        local_instance_id: local_instance_id: Integer of instance id.
-
-    Returns:
-        NamedTuple of (vnc_port, adb_port) used by local instance, both are
-        integers.
-    """
-    return LocalPorts(vnc_port=constants.CF_VNC_PORT + local_instance_id - 1,
-                      adb_port=constants.CF_ADB_PORT + local_instance_id - 1)
-
-
 def _GetCurrentLocalTime():
     """Return a datetime object for current time in local time zone."""
     return datetime.datetime.now(dateutil.tz.tzlocal())
@@ -193,31 +217,30 @@
 
     def Summary(self):
         """Let's make it easy to see what this class is holding."""
-        indent = " " * 3
         representation = []
         representation.append(" name: %s" % self._name)
-        representation.append("%s IP: %s" % (indent, self._ip))
-        representation.append("%s create time: %s" % (indent, self._createtime))
-        representation.append("%s elapse time: %s" % (indent, self._elapsed_time))
-        representation.append("%s status: %s" % (indent, self._status))
-        representation.append("%s avd type: %s" % (indent, self._avd_type))
-        representation.append("%s display: %s" % (indent, self._display))
-        representation.append("%s vnc: 127.0.0.1:%s" % (indent, self._vnc_port))
-        representation.append("%s zone: %s" % (indent, self._zone))
+        representation.append("%s IP: %s" % (_INDENT, self._ip))
+        representation.append("%s create time: %s" % (_INDENT, self._createtime))
+        representation.append("%s elapse time: %s" % (_INDENT, self._elapsed_time))
+        representation.append("%s status: %s" % (_INDENT, self._status))
+        representation.append("%s avd type: %s" % (_INDENT, self._avd_type))
+        representation.append("%s display: %s" % (_INDENT, self._display))
+        representation.append("%s vnc: 127.0.0.1:%s" % (_INDENT, self._vnc_port))
+        representation.append("%s zone: %s" % (_INDENT, self._zone))
 
-        if self._adb_port:
+        if self._adb_port and self._device_information:
             representation.append("%s adb serial: 127.0.0.1:%s" %
-                                  (indent, self._adb_port))
+                                  (_INDENT, self._adb_port))
             representation.append("%s product: %s" % (
-                indent, self._device_information["product"]))
+                _INDENT, self._device_information["product"]))
             representation.append("%s model: %s" % (
-                indent, self._device_information["model"]))
+                _INDENT, self._device_information["model"]))
             representation.append("%s device: %s" % (
-                indent, self._device_information["device"]))
+                _INDENT, self._device_information["device"]))
             representation.append("%s transport_id: %s" % (
-                indent, self._device_information["transport_id"]))
+                _INDENT, self._device_information["transport_id"]))
         else:
-            representation.append("%s adb serial: disconnected" % indent)
+            representation.append("%s adb serial: disconnected" % _INDENT)
 
         return "\n".join(representation)
 
@@ -247,16 +270,6 @@
         return self._display
 
     @property
-    def forwarding_adb_port(self):
-        """Return the adb port."""
-        return self._adb_port
-
-    @property
-    def forwarding_vnc_port(self):
-        """Return the vnc port."""
-        return self._vnc_port
-
-    @property
     def ssh_tunnel_is_connected(self):
         """Return the connect status."""
         return self._ssh_tunnel_is_connected
@@ -299,25 +312,28 @@
 
 class LocalInstance(Instance):
     """Class to store data of local cuttlefish instance."""
-
-    def __init__(self, local_instance_id, cf_runtime_cfg):
+    def __init__(self, cf_config_path):
         """Initialize a localInstance object.
 
         Args:
-            local_instance_id: Integer of instance id.
-            cf_runtime_cfg: A CvdRuntimeConfig instance.
+            cf_config_path: String, path to the cf runtime config.
         """
-        display = _DISPLAY_STRING % {"x_res": cf_runtime_cfg.x_res,
-                                     "y_res": cf_runtime_cfg.y_res,
-                                     "dpi": cf_runtime_cfg.dpi}
+        self._cf_runtime_cfg = cvd_runtime_config.CvdRuntimeConfig(cf_config_path)
+        self._instance_dir = self._cf_runtime_cfg.instance_dir
+        self._virtual_disk_paths = self._cf_runtime_cfg.virtual_disk_paths
+        self._local_instance_id = int(self._cf_runtime_cfg.instance_id)
+
+        display = _DISPLAY_STRING % {"x_res": self._cf_runtime_cfg.x_res,
+                                     "y_res": self._cf_runtime_cfg.y_res,
+                                     "dpi": self._cf_runtime_cfg.dpi}
         # TODO(143063678), there's no createtime info in
         # cuttlefish_config.json so far.
-        name = GetLocalInstanceName(local_instance_id)
+        name = GetLocalInstanceName(self._local_instance_id)
         fullname = (_FULL_NAME_STRING %
-                    {"device_serial": "127.0.0.1:%d" % cf_runtime_cfg.adb_port,
+                    {"device_serial": "127.0.0.1:%s" % self._cf_runtime_cfg.adb_port,
                      "instance_name": name,
                      "elapsed_time": None})
-        adb_device = AdbTools(cf_runtime_cfg.adb_port)
+        adb_device = AdbTools(self._cf_runtime_cfg.adb_port)
         device_information = None
         if adb_device.IsAdbConnected():
             device_information = adb_device.device_information
@@ -325,19 +341,102 @@
         super(LocalInstance, self).__init__(
             name=name, fullname=fullname, display=display, ip="127.0.0.1",
             status=constants.INS_STATUS_RUNNING,
-            adb_port=cf_runtime_cfg.adb_port, vnc_port=cf_runtime_cfg.vnc_port,
+            adb_port=self._cf_runtime_cfg.adb_port,
+            vnc_port=self._cf_runtime_cfg.vnc_port,
             createtime=None, elapsed_time=None, avd_type=constants.TYPE_CF,
             is_local=True, device_information=device_information,
             zone=_LOCAL_ZONE)
 
-        # LocalInstance class properties
-        self._instance_dir = cf_runtime_cfg.instance_dir
+    def Summary(self):
+        """Return the string that this class is holding."""
+        instance_home = "%s instance home: %s" % (_INDENT, self._instance_dir)
+        return "%s\n%s" % (super(LocalInstance, self).Summary(), instance_home)
+
+    def CvdStatus(self):
+        """check if local instance is active.
+
+        Execute cvd_status cmd to check if it exit without error.
+
+        Returns
+            True if instance is active.
+        """
+        cvd_env = os.environ.copy()
+        cvd_env[constants.ENV_CUTTLEFISH_CONFIG_FILE] = self._cf_runtime_cfg.config_path
+        cvd_env[constants.ENV_CVD_HOME] = GetLocalInstanceHomeDir(self._local_instance_id)
+        cvd_env[constants.ENV_CUTTLEFISH_INSTANCE] = str(self._local_instance_id)
+        try:
+            cvd_status_cmd = os.path.join(self._cf_runtime_cfg.cvd_tools_path,
+                                          _CVD_STATUS_BIN)
+            logger.debug("Running cmd[%s] to check cvd status.", cvd_status_cmd)
+            process = subprocess.Popen(cvd_status_cmd,
+                                       stdin=None,
+                                       stdout=subprocess.PIPE,
+                                       stderr=subprocess.STDOUT,
+                                       env=cvd_env)
+            stdout, _ = process.communicate()
+            if process.returncode != 0:
+                if stdout:
+                    logger.debug("Local instance[%s] is not active: %s",
+                                 self.name, stdout.strip())
+                return False
+            return True
+        except subprocess.CalledProcessError as cpe:
+            logger.error("Failed to run cvd_status: %s", cpe.output)
+            return False
+
+    def Delete(self):
+        """Execute stop_cvd to stop local cuttlefish instance.
+
+        - We should get the same host tool used to launch cvd to delete instance
+        , So get stop_cvd bin from the cvd runtime config.
+        - Add CUTTLEFISH_CONFIG_FILE env variable to tell stop_cvd which cvd
+        need to be deleted.
+        - Stop adb since local instance use the fixed adb port and could be
+         reused again soon.
+        """
+        stop_cvd_cmd = os.path.join(self.cf_runtime_cfg.cvd_tools_path,
+                                    constants.CMD_STOP_CVD)
+        logger.debug("Running cmd[%s] to delete local cvd", stop_cvd_cmd)
+        with open(os.devnull, "w") as dev_null:
+            cvd_env = os.environ.copy()
+            if self.instance_dir:
+                cvd_env[constants.ENV_CUTTLEFISH_CONFIG_FILE] = self._cf_runtime_cfg.config_path
+                cvd_env[constants.ENV_CVD_HOME] = GetLocalInstanceHomeDir(
+                    self._local_instance_id)
+                cvd_env[constants.ENV_CUTTLEFISH_INSTANCE] = str(self._local_instance_id)
+            else:
+                logger.error("instance_dir is null!! instance[%d] might not be"
+                             " deleted", self._local_instance_id)
+            subprocess.check_call(
+                utils.AddUserGroupsToCmd(stop_cvd_cmd,
+                                         constants.LIST_CF_USER_GROUPS),
+                stderr=dev_null, stdout=dev_null, shell=True, env=cvd_env)
+
+        adb_cmd = AdbTools(self.adb_port)
+        # When relaunch a local instance, we need to pass in retry=True to make
+        # sure adb device is completely gone since it will use the same adb port
+        adb_cmd.DisconnectAdb(retry=True)
 
     @property
     def instance_dir(self):
         """Return _instance_dir."""
         return self._instance_dir
 
+    @property
+    def instance_id(self):
+        """Return _local_instance_id."""
+        return self._local_instance_id
+
+    @property
+    def virtual_disk_paths(self):
+        """Return virtual_disk_paths"""
+        return self._virtual_disk_paths
+
+    @property
+    def cf_runtime_cfg(self):
+        """Return _cf_runtime_cfg"""
+        return self._cf_runtime_cfg
+
 
 class LocalGoldfishInstance(Instance):
     """Class to store data of local goldfish instance."""
diff --git a/list/instance_test.py b/list/instance_test.py
index 9832c80..a2c7922 100644
--- a/list/instance_test.py
+++ b/list/instance_test.py
@@ -27,6 +27,7 @@
 import dateutil.tz
 
 from acloud.internal import constants
+from acloud.internal.lib import cvd_runtime_config
 from acloud.internal.lib import driver_test_lib
 from acloud.internal.lib.adb_tools import AdbTools
 from acloud.list import instance
@@ -62,15 +63,18 @@
         """"Test get local instance info from launch_cvd process."""
         self.Patch(subprocess, "check_output", return_value=self.PS_LAUNCH_CVD)
         cf_config = mock.MagicMock(
+            instance_id=2,
             x_res=1080,
             y_res=1920,
             dpi=480,
             instance_dir="fake_instance_dir",
             adb_port=6521,
-            vnc_port=6445
+            vnc_port=6445,
+            adb_ip_port="127.0.0.1:6521",
         )
-
-        local_instance = instance.LocalInstance(2, cf_config)
+        self.Patch(cvd_runtime_config, "CvdRuntimeConfig",
+                   return_value=cf_config)
+        local_instance = instance.LocalInstance(cf_config)
 
         self.assertEqual(constants.LOCAL_INS_NAME + "-2", local_instance.name)
         self.assertEqual(True, local_instance.islocal)
@@ -80,8 +84,8 @@
                                  constants.LOCAL_INS_NAME + "-2",
                                  "None"))
         self.assertEqual(expected_full_name, local_instance.fullname)
-        self.assertEqual(6521, local_instance.forwarding_adb_port)
-        self.assertEqual(6445, local_instance.forwarding_vnc_port)
+        self.assertEqual(6521, local_instance.adb_port)
+        self.assertEqual(6445, local_instance.vnc_port)
 
     @mock.patch("acloud.list.instance.tempfile")
     @mock.patch("acloud.list.instance.AdbTools")
@@ -214,8 +218,8 @@
         # test ssh_tunnel_is_connected will be true if ssh tunnel connection is found
         instance_info = instance.RemoteInstance(self.GCE_INSTANCE)
         self.assertTrue(instance_info.ssh_tunnel_is_connected)
-        self.assertEqual(instance_info.forwarding_adb_port, fake_adb)
-        self.assertEqual(instance_info.forwarding_vnc_port, fake_vnc)
+        self.assertEqual(instance_info.adb_port, fake_adb)
+        self.assertEqual(instance_info.vnc_port, fake_vnc)
         self.assertEqual("1.1.1.1", instance_info.ip)
         self.assertEqual("fake_status", instance_info.status)
         self.assertEqual("fake_type", instance_info.avd_type)
diff --git a/list/list.py b/list/list.py
index 6afaf0a..febd6f3 100644
--- a/list/list.py
+++ b/list/list.py
@@ -20,8 +20,7 @@
 from __future__ import print_function
 import getpass
 import logging
-import re
-import subprocess
+import os
 
 from acloud import errors
 from acloud.internal import constants
@@ -35,28 +34,6 @@
 logger = logging.getLogger(__name__)
 
 _COMMAND_PS_LAUNCH_CVD = ["ps", "-wweo", "lstart,cmd"]
-_RE_LOCAL_CVD_PORT = re.compile(r"^127\.0\.0\.1:65(?P<cvd_port_suffix>\d{2})\s+")
-
-
-def GetActiveCVDIds():
-    """Get active local cvd ids from adb devices.
-
-    The adb port of local instance will be decided according to instance id.
-    The rule of adb port will be '6520 + [instance id] - 1'. So we grep last
-    two digits of port and calculate the instance id.
-
-    Return:
-        List of cvd id.
-    """
-    local_cvd_ids = []
-    adb_cmd = [constants.ADB_BIN, "devices"]
-    device_info = subprocess.check_output(adb_cmd)
-    for device in device_info.splitlines():
-        match = _RE_LOCAL_CVD_PORT.match(device)
-        if match:
-            cvd_serial = match.group("cvd_port_suffix")
-            local_cvd_ids.append(int(cvd_serial) - 19)
-    return local_cvd_ids
 
 
 def _ProcessInstances(instance_list):
@@ -144,19 +121,39 @@
     Returns:
         instance_list: List of local instances.
     """
-    local_cvd_ids = GetActiveCVDIds()
     local_instance_list = []
-    for cvd_id in local_cvd_ids:
-        try:
-            cf_runtime_cfg = instance.GetCuttlefishRuntimeConfig(cvd_id)
-            local_instance_list.append(
-                instance.LocalInstance(cvd_id, cf_runtime_cfg))
-        except errors.ConfigError:
-            logger.error("Instance[id:%d] dir not found!", cvd_id)
-
+    for cf_runtime_config_path in instance.GetAllLocalInstanceConfigs():
+        ins = instance.LocalInstance(cf_runtime_config_path)
+        if ins.CvdStatus():
+            local_instance_list.append(ins)
+        else:
+            logger.info("cvd runtime config found but instance is not active:%s"
+                        , cf_runtime_config_path)
     return local_instance_list
 
 
+def GetActiveCVD(local_instance_id):
+    """Check if the local AVD with specific instance id is running
+
+    Args:
+        local_instance_id: Integer of instance id.
+
+    Return:
+        LocalInstance object.
+    """
+    cfg_path = instance.GetLocalInstanceConfig(local_instance_id)
+    if cfg_path:
+        ins = instance.LocalInstance(cfg_path)
+        if ins.CvdStatus():
+            return ins
+    cfg_path = instance.GetDefaultCuttlefishConfig()
+    if local_instance_id == 1 and os.path.isfile(cfg_path):
+        ins = instance.LocalInstance(cfg_path)
+        if ins.CvdStatus():
+            return ins
+    return None
+
+
 def GetLocalInstances():
     """Look for local cuttleifsh and goldfish instances.
 
@@ -308,7 +305,7 @@
     """
     all_instance_info = []
     for instance_object in instances:
-        if instance_object.forwarding_adb_port == adb_port:
+        if instance_object.adb_port == adb_port:
             return [instance_object]
         all_instance_info.append(instance_object.fullname)
 
diff --git a/list/list_test.py b/list/list_test.py
index 12f7ce4..a4b466c 100644
--- a/list/list_test.py
+++ b/list/list_test.py
@@ -12,12 +12,13 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 """Tests for list."""
-import subprocess
+
 import unittest
 
 import mock
 
 from acloud import errors
+from acloud.internal.lib import cvd_runtime_config
 from acloud.internal.lib import driver_test_lib
 from acloud.internal.lib import utils
 from acloud.list import list as list_instance
@@ -91,7 +92,7 @@
     def testFilterInstancesByAdbPort(self):
         """test FilterInstancesByAdbPort."""
         alive_instance1 = InstanceObject("alive_instance1")
-        alive_instance1.forwarding_adb_port = 1111
+        alive_instance1.adb_port = 1111
         alive_instance1.fullname = "device serial: 127.0.0.1:1111 alive_instance1"
         expected_instance = [alive_instance1]
         # Test to find instance by adb port number.
@@ -105,17 +106,24 @@
     # pylint: disable=protected-access
     def testGetLocalCuttlefishInstances(self):
         """test _GetLocalCuttlefishInstances."""
-        cf_config = mock.MagicMock()
-
         # Test getting two instance case
-        self.Patch(list_instance, "GetActiveCVDIds", return_value=[1, 2])
-        self.Patch(instance, "GetCuttlefishRuntimeConfig", return_value=cf_config)
+        self.Patch(instance, "GetAllLocalInstanceConfigs",
+                   return_value=["fake_path1", "fake_path2"])
         self.Patch(instance, "GetLocalInstanceRuntimeDir")
-        self.Patch(instance, "LocalInstance")
+
+        local_ins = mock.MagicMock()
+        local_ins.CvdStatus.return_value = True
+        self.Patch(instance, "LocalInstance", return_value=local_ins)
 
         ins_list = list_instance._GetLocalCuttlefishInstances()
         self.assertEqual(2, len(ins_list))
 
+        local_ins = mock.MagicMock()
+        local_ins.CvdStatus.return_value = False
+        self.Patch(instance, "LocalInstance", return_value=local_ins)
+        ins_list = list_instance._GetLocalCuttlefishInstances()
+        self.assertEqual(0, len(ins_list))
+
     # pylint: disable=no-member
     def testPrintInstancesDetails(self):
         """test PrintInstancesDetails."""
@@ -125,10 +133,13 @@
             x_res=728,
             y_res=728,
             dpi=240,
-            instance_dir="fake_dir"
+            instance_dir="fake_dir",
+            adb_ip_port="127.0.0.1:6520"
         )
+        self.Patch(cvd_runtime_config, "CvdRuntimeConfig",
+                   return_value=cf_config)
 
-        ins = instance.LocalInstance(1, cf_config)
+        ins = instance.LocalInstance("fake_cf_path")
         list_instance.PrintInstancesDetails([ins], verbose=True)
         instance.Instance.Summary.assert_called_once()
 
@@ -141,15 +152,6 @@
         list_instance.PrintInstancesDetails([], verbose=True)
         instance.Instance.Summary.assert_not_called()
 
-    # pylint: disable=no-member
-    def testGetActiveCVDIds(self):
-        """test GetActiveCVDIds."""
-        # Test getting two local devices
-        adb_output = "127.0.0.1:6520  device\n127.0.0.1:6521  device"
-        expected_result = [1, 2]
-        self.Patch(subprocess, "check_output", return_value=adb_output)
-        self.assertEqual(list_instance.GetActiveCVDIds(), expected_result)
-
 
 if __name__ == "__main__":
     unittest.main()
diff --git a/public/report.py b/public/report.py
index 5f5a07a..dd95c4e 100755
--- a/public/report.py
+++ b/public/report.py
@@ -150,7 +150,7 @@
                 "requested to update to a status with lower severity %s, ignored.",
                 self.status, status)
 
-    def AddDevice(self, instance_name, ip_address, adb_port, vnc_port=None,
+    def AddDevice(self, instance_name, ip_address, adb_port, vnc_port,
                   key="devices"):
         """Add a record of a device.
 
@@ -161,9 +161,13 @@
             vnc_port: An integer.
             key: A string, the data entry where the record is added.
         """
-        device = {constants.INSTANCE_NAME: instance_name,
-                  constants.IP: "%s:%d" % (ip_address, adb_port),
-                  constants.ADB_PORT: adb_port}
+        device = {constants.INSTANCE_NAME: instance_name}
+        if adb_port:
+            device[constants.ADB_PORT] = adb_port
+            device[constants.IP] = "%s:%d" % (ip_address, adb_port)
+        else:
+            device[constants.IP] = ip_address
+
         if vnc_port:
             device[constants.VNC_PORT] = vnc_port
         self.AddData(key=key, value=device)
diff --git a/public/report_test.py b/public/report_test.py
index 772c987..d3987c8 100644
--- a/public/report_test.py
+++ b/public/report_test.py
@@ -63,12 +63,13 @@
     def testAddDevice(self):
         """test AddDevice."""
         test_report = report.Report("create")
-        test_report.AddDevice("instance_1", "127.0.0.1", 6520)
+        test_report.AddDevice("instance_1", "127.0.0.1", 6520, 6444)
         expected = {
             "devices": [{
                 "instance_name": "instance_1",
                 "ip": "127.0.0.1:6520",
-                "adb_port": 6520
+                "adb_port": 6520,
+                "vnc_port": 6444
             }]
         }
         self.assertEqual(test_report.data, expected)
diff --git a/reconnect/reconnect.py b/reconnect/reconnect.py
index 1be9567..d354b4e 100644
--- a/reconnect/reconnect.py
+++ b/reconnect/reconnect.py
@@ -22,7 +22,6 @@
 import re
 
 from acloud import errors
-from acloud.delete import delete
 from acloud.internal import constants
 from acloud.internal.lib import auth
 from acloud.internal.lib import android_compute_client
@@ -51,7 +50,7 @@
     vnc_started_pattern = _VNC_STARTED_PATTERN % {"vnc_port": vnc_port}
     if not utils.IsCommandRunning(vnc_started_pattern):
         #clean old disconnect ssvnc viewer.
-        delete.CleanupSSVncviewer(vnc_port)
+        utils.CleanupSSVncviewer(vnc_port)
 
         match = _RE_DISPLAY.match(display)
         if match:
@@ -110,9 +109,9 @@
                                     "unknown avd type: %s" %
                                     (instance.name, instance.avd_type))
 
-    adb_cmd = AdbTools(instance.forwarding_adb_port)
-    vnc_port = instance.forwarding_vnc_port
-    adb_port = instance.forwarding_adb_port
+    adb_cmd = AdbTools(instance.adb_port)
+    vnc_port = instance.vnc_port
+    adb_port = instance.adb_port
     # ssh tunnel is up but device is disconnected on adb
     if instance.ssh_tunnel_is_connected and not adb_cmd.IsAdbConnectionAlive():
         adb_cmd.DisconnectAdb()
diff --git a/reconnect/reconnect_test.py b/reconnect/reconnect_test.py
index 493067b..70ea801 100644
--- a/reconnect/reconnect_test.py
+++ b/reconnect/reconnect_test.py
@@ -42,7 +42,7 @@
         instance_object = mock.MagicMock()
         instance_object.ip = "1.1.1.1"
         instance_object.islocal = False
-        instance_object.forwarding_adb_port = "8686"
+        instance_object.adb_port = "8686"
         instance_object.avd_type = "cuttlefish"
         self.Patch(subprocess, "check_call", return_value=True)
         self.Patch(utils, "LaunchVncClient")
@@ -52,7 +52,7 @@
         self.Patch(utils, "IsCommandRunning", return_value=False)
 
         #test ssh tunnel not connected, remote instance.
-        instance_object.forwarding_vnc_port = 6666
+        instance_object.vnc_port = 6666
         instance_object.display = ""
         utils.AutoConnect.call_count = 0
         reconnect.ReconnectInstance(ssh_private_key_path, instance_object, fake_report)
@@ -69,7 +69,7 @@
         instance_object.ssh_tunnel_is_connected = False
         instance_object.display = ""
         utils.AutoConnect.call_count = 0
-        instance_object.forwarding_vnc_port = 5555
+        instance_object.vnc_port = 5555
         extra_args_ssh_tunnel = None
         self.Patch(utils, "AutoConnect",
                    return_value=ForwardedPorts(vnc_port=11111, adb_port=22222))
@@ -100,7 +100,7 @@
         #test reconnect local instance.
         instance_object.islocal = True
         instance_object.display = ""
-        instance_object.forwarding_vnc_port = 5555
+        instance_object.vnc_port = 5555
         instance_object.ssh_tunnel_is_connected = False
         utils.AutoConnect.call_count = 0
         reconnect.ReconnectInstance(ssh_private_key_path,
@@ -115,8 +115,8 @@
         fake_report = mock.MagicMock()
         instance_object = mock.MagicMock()
         instance_object.ip = "1.1.1.1"
-        instance_object.forwarding_vnc_port = 9999
-        instance_object.forwarding_adb_port = "9999"
+        instance_object.vnc_port = 9999
+        instance_object.adb_port = "9999"
         instance_object.islocal = False
         instance_object.ssh_tunnel_is_connected = False
         self.Patch(utils, "AutoConnect")
diff --git a/setup/host_setup_runner.py b/setup/host_setup_runner.py
index a334c2c..9a668e5 100644
--- a/setup/host_setup_runner.py
+++ b/setup/host_setup_runner.py
@@ -23,7 +23,10 @@
 
 import getpass
 import logging
+import os
+import shutil
 import sys
+import tempfile
 
 from acloud.internal import constants
 from acloud.internal.lib import utils
@@ -33,17 +36,20 @@
 
 logger = logging.getLogger(__name__)
 
-# Install cuttlefish-common will probably not work now.
-# TODO: update this to pull from the proper repo.
-_AVD_REQUIRED_PKGS = ["cuttlefish-common",
-                      # TODO(b/117613492): This is all qemu related, take this
-                      # out once they are added back in as deps for
-                      # cuttlefish-common.
-                      "qemu-kvm", "qemu-system-common", "qemu-system-x86",
-                      "qemu-utils", "libvirt-clients", "libvirt-daemon-system"]
+# Packages "devscripts" and "equivs" are required for "mk-build-deps".
+_AVD_REQUIRED_PKGS = [
+    "devscripts", "equivs", "libvirt-clients", "libvirt-daemon-system"]
 _BASE_REQUIRED_PKGS = ["ssvnc", "lzop"]
+_CUTTLEFISH_COMMOM_PKG = "cuttlefish-common"
+_CF_COMMOM_FOLDER = "cf-common"
 _LIST_OF_MODULES = ["kvm_intel", "kvm"]
 _UPDATE_APT_GET_CMD = "sudo apt-get update"
+_INSTALL_CUTTLEFISH_COMMOM_CMD = [
+    "git clone https://github.com/google/android-cuttlefish.git {git_folder}",
+    "cd {git_folder}",
+    "yes | sudo mk-build-deps -i -r -B",
+    "dpkg-buildpackage -uc -us",
+    "sudo apt-get install -y -f ../cuttlefish-common_*_amd64.deb"]
 
 
 class BasePkgInstaller(base_task_runner.BaseTaskRunner):
@@ -109,6 +115,47 @@
     PACKAGES = _BASE_REQUIRED_PKGS
 
 
+class CuttlefishCommonPkgInstaller(base_task_runner.BaseTaskRunner):
+    """Subtask base runner class for installing cuttlefish-common."""
+
+    WELCOME_MESSAGE_TITLE = "Install cuttlefish-common packages on the host"
+    WELCOME_MESSAGE = ("This step will walk you through the cuttlefish-common "
+                       "packages installation for your host.")
+
+    def ShouldRun(self):
+        """Check if cuttlefish-common package is installed.
+
+        Returns:
+            Boolean, True if cuttlefish-common is not installed.
+        """
+        if not utils.IsSupportedPlatform():
+            return False
+
+        # Any required package is not installed or not up-to-date will need to
+        # run installation task.
+        if not setup_common.PackageInstalled(_CUTTLEFISH_COMMOM_PKG):
+            return True
+        return False
+
+    def _Run(self):
+        """Install cuttlefilsh-common packages."""
+        cf_common_path = os.path.join(tempfile.mkdtemp(), _CF_COMMOM_FOLDER)
+        logger.debug("cuttlefish-common path: %s", cf_common_path)
+        cmd = "\n".join(sub_cmd.format(git_folder=cf_common_path)
+                        for sub_cmd in _INSTALL_CUTTLEFISH_COMMOM_CMD)
+
+        if not utils.GetUserAnswerYes("\nStart to install cuttlefish-common :\n%s"
+                                      "\nPress 'y' to continue or anything "
+                                      "else to do it myself and run acloud "
+                                      "again[y/N]: " % cmd):
+            sys.exit(constants.EXIT_BY_USER)
+        try:
+            setup_common.CheckCmdOutput(cmd, shell=True)
+        finally:
+            shutil.rmtree(os.path.dirname(cf_common_path))
+        logger.info("Cuttlefish-common package installed now.")
+
+
 class CuttlefishHostSetup(base_task_runner.BaseTaskRunner):
     """Subtask class that setup host for cuttlefish."""
 
diff --git a/setup/host_setup_runner_test.py b/setup/host_setup_runner_test.py
index b424db5..111540e 100644
--- a/setup/host_setup_runner_test.py
+++ b/setup/host_setup_runner_test.py
@@ -13,13 +13,17 @@
 # limitations under the License.
 """Tests for host_setup_runner."""
 import platform
+import shutil
+import tempfile
 import unittest
+import mock
 
 from acloud.internal.lib import driver_test_lib
 from acloud.internal.lib import utils
 from acloud.setup import setup_common
-from acloud.setup.host_setup_runner import CuttlefishHostSetup
 from acloud.setup.host_setup_runner import AvdPkgInstaller
+from acloud.setup.host_setup_runner import CuttlefishCommonPkgInstaller
+from acloud.setup.host_setup_runner import CuttlefishHostSetup
 
 
 class CuttlefishHostSetupTest(driver_test_lib.BaseDriverTest):
@@ -85,9 +89,36 @@
     def testShouldNotRun(self):
         """Test ShoudRun should raise error in non-linux os."""
         self.Patch(platform, "system", return_value="Mac")
-
         self.assertFalse(self.AvdPkgInstaller.ShouldRun())
 
 
+class CuttlefishCommonPkgInstallerTest(driver_test_lib.BaseDriverTest):
+    """Test CuttlefishCommonPkgInstallerTest."""
+
+    # pylint: disable=invalid-name
+    def setUp(self):
+        """Set up the test."""
+        super(CuttlefishCommonPkgInstallerTest, self).setUp()
+        self.CuttlefishCommonPkgInstaller = CuttlefishCommonPkgInstaller()
+
+    def testShouldRun(self):
+        """Test ShoudRun."""
+        self.Patch(platform, "system", return_value="Linux")
+        self.Patch(setup_common, "PackageInstalled", return_value=False)
+        self.assertTrue(self.CuttlefishCommonPkgInstaller.ShouldRun())
+
+    @mock.patch.object(shutil, "rmtree")
+    @mock.patch.object(setup_common, "CheckCmdOutput")
+    def testRun(self, mock_cmd, mock_rmtree):
+        """Test Run."""
+        fake_tmp_folder = "/tmp/cf-common"
+        self.Patch(tempfile, "mkdtemp", return_value=fake_tmp_folder)
+        self.Patch(utils, "GetUserAnswerYes", return_value="y")
+        self.Patch(CuttlefishCommonPkgInstaller, "ShouldRun", return_value=True)
+        self.CuttlefishCommonPkgInstaller.Run()
+        self.assertEqual(mock_cmd.call_count, 1)
+        mock_rmtree.assert_called_once_with(fake_tmp_folder)
+
+
 if __name__ == "__main__":
     unittest.main()
diff --git a/setup/setup.py b/setup/setup.py
index 36b6ffd..39513dc 100644
--- a/setup/setup.py
+++ b/setup/setup.py
@@ -48,6 +48,7 @@
     # 2.Init all subtasks in queue and traverse them.
     host_base_runner = host_setup_runner.HostBasePkgInstaller()
     host_avd_runner = host_setup_runner.AvdPkgInstaller()
+    host_cf_common_runner = host_setup_runner.CuttlefishCommonPkgInstaller()
     host_env_runner = host_setup_runner.CuttlefishHostSetup()
     gcp_runner = gcp_setup_runner.GcpTaskRunner(args.config_file)
     task_queue = []
@@ -55,6 +56,7 @@
     if args.host:
         task_queue.append(host_base_runner)
         task_queue.append(host_avd_runner)
+        task_queue.append(host_cf_common_runner)
         task_queue.append(host_env_runner)
     # We should do these setup tasks if specified or if no args were used.
     if args.host_base or (not args.host and not args.gcp_init):