xref: /aosp_15_r20/tools/acloud/create/local_image_local_instance.py (revision 800a58d989c669b8eb8a71d8df53b1ba3d411444)
1*800a58d9SAndroid Build Coastguard Worker#!/usr/bin/env python
2*800a58d9SAndroid Build Coastguard Worker#
3*800a58d9SAndroid Build Coastguard Worker# Copyright 2018 - The Android Open Source Project
4*800a58d9SAndroid Build Coastguard Worker#
5*800a58d9SAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License");
6*800a58d9SAndroid Build Coastguard Worker# you may not use this file except in compliance with the License.
7*800a58d9SAndroid Build Coastguard Worker# You may obtain a copy of the License at
8*800a58d9SAndroid Build Coastguard Worker#
9*800a58d9SAndroid Build Coastguard Worker#     http://www.apache.org/licenses/LICENSE-2.0
10*800a58d9SAndroid Build Coastguard Worker#
11*800a58d9SAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software
12*800a58d9SAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS,
13*800a58d9SAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*800a58d9SAndroid Build Coastguard Worker# See the License for the specific language governing permissions and
15*800a58d9SAndroid Build Coastguard Worker# limitations under the License.
16*800a58d9SAndroid Build Coastguard Workerr"""LocalImageLocalInstance class.
17*800a58d9SAndroid Build Coastguard Worker
18*800a58d9SAndroid Build Coastguard WorkerCreate class that is responsible for creating a local instance AVD with a
19*800a58d9SAndroid Build Coastguard Workerlocal image. For launching multiple local instances under the same user,
20*800a58d9SAndroid Build Coastguard WorkerThe cuttlefish tool requires 3 variables:
21*800a58d9SAndroid Build Coastguard Worker- ANDROID_HOST_OUT: To locate the launch_cvd tool.
22*800a58d9SAndroid Build Coastguard Worker- HOME: To specify the temporary folder of launch_cvd.
23*800a58d9SAndroid Build Coastguard Worker- CUTTLEFISH_INSTANCE: To specify the instance id.
24*800a58d9SAndroid Build Coastguard WorkerAcloud user must either set ANDROID_HOST_OUT or run acloud with --local-tool.
25*800a58d9SAndroid Build Coastguard WorkerThe user can optionally specify the folder by --local-instance-dir and the
26*800a58d9SAndroid Build Coastguard Workerinstance id by --local-instance.
27*800a58d9SAndroid Build Coastguard Worker
28*800a58d9SAndroid Build Coastguard WorkerThe adb port and vnc port of local instance will be decided according to
29*800a58d9SAndroid Build Coastguard Workerinstance id. The rule of adb port will be '6520 + [instance id] - 1' and the
30*800a58d9SAndroid Build Coastguard Workervnc port will be '6444 + [instance id] - 1'.
31*800a58d9SAndroid Build Coastguard Workere.g:
32*800a58d9SAndroid Build Coastguard WorkerIf instance id = 3 the adb port will be 6522 and vnc port will be 6446.
33*800a58d9SAndroid Build Coastguard Worker
34*800a58d9SAndroid Build Coastguard WorkerTo delete the local instance, we will call stop_cvd with the environment
35*800a58d9SAndroid Build Coastguard Workervariable [CUTTLEFISH_CONFIG_FILE] which is pointing to the runtime cuttlefish
36*800a58d9SAndroid Build Coastguard Workerjson.
37*800a58d9SAndroid Build Coastguard Worker
38*800a58d9SAndroid Build Coastguard WorkerTo run this program outside of a build environment, the following setup is
39*800a58d9SAndroid Build Coastguard Workerrequired.
40*800a58d9SAndroid Build Coastguard Worker- One of the local tool directories is a decompressed cvd host package,
41*800a58d9SAndroid Build Coastguard Worker  i.e., cvd-host_package.tar.gz.
42*800a58d9SAndroid Build Coastguard Worker- If the instance doesn't require mixed images, the local image directory
43*800a58d9SAndroid Build Coastguard Worker  should be an unzipped update package, i.e., <target>-img-<build>.zip,
44*800a58d9SAndroid Build Coastguard Worker  which contains a super image.
45*800a58d9SAndroid Build Coastguard Worker- If the instance requires mixing system image, the local image directory
46*800a58d9SAndroid Build Coastguard Worker  should be an unzipped target files package, i.e.,
47*800a58d9SAndroid Build Coastguard Worker  <target>-target_files-<build>.zip,
48*800a58d9SAndroid Build Coastguard Worker  which contains misc info and images not packed into a super image.
49*800a58d9SAndroid Build Coastguard Worker- If the instance requires mixing system image, one of the local tool
50*800a58d9SAndroid Build Coastguard Worker  directories should be an unzipped OTA tools package, i.e., otatools.zip.
51*800a58d9SAndroid Build Coastguard Worker"""
52*800a58d9SAndroid Build Coastguard Worker
53*800a58d9SAndroid Build Coastguard Workerimport collections
54*800a58d9SAndroid Build Coastguard Workerimport logging
55*800a58d9SAndroid Build Coastguard Workerimport os
56*800a58d9SAndroid Build Coastguard Workerimport re
57*800a58d9SAndroid Build Coastguard Workerimport shutil
58*800a58d9SAndroid Build Coastguard Workerimport subprocess
59*800a58d9SAndroid Build Coastguard Workerimport sys
60*800a58d9SAndroid Build Coastguard Worker
61*800a58d9SAndroid Build Coastguard Workerfrom acloud import errors
62*800a58d9SAndroid Build Coastguard Workerfrom acloud.create import base_avd_create
63*800a58d9SAndroid Build Coastguard Workerfrom acloud.create import create_common
64*800a58d9SAndroid Build Coastguard Workerfrom acloud.internal import constants
65*800a58d9SAndroid Build Coastguard Workerfrom acloud.internal.lib import cvd_utils
66*800a58d9SAndroid Build Coastguard Workerfrom acloud.internal.lib import ota_tools
67*800a58d9SAndroid Build Coastguard Workerfrom acloud.internal.lib import utils
68*800a58d9SAndroid Build Coastguard Workerfrom acloud.internal.lib.adb_tools import AdbTools
69*800a58d9SAndroid Build Coastguard Workerfrom acloud.list import list as list_instance
70*800a58d9SAndroid Build Coastguard Workerfrom acloud.list import instance
71*800a58d9SAndroid Build Coastguard Workerfrom acloud.public import report
72*800a58d9SAndroid Build Coastguard Workerfrom acloud.setup import mkcert
73*800a58d9SAndroid Build Coastguard Worker
74*800a58d9SAndroid Build Coastguard Worker
75*800a58d9SAndroid Build Coastguard Workerlogger = logging.getLogger(__name__)
76*800a58d9SAndroid Build Coastguard Worker
77*800a58d9SAndroid Build Coastguard Worker_SUPER_IMAGE_NAME = "super.img"
78*800a58d9SAndroid Build Coastguard Worker_MIXED_SUPER_IMAGE_NAME = "mixed_super.img"
79*800a58d9SAndroid Build Coastguard Worker_CMD_CVD_START = " start"
80*800a58d9SAndroid Build Coastguard Worker_CMD_CVD_VERSION = " version"
81*800a58d9SAndroid Build Coastguard Worker_CMD_LAUNCH_CVD_ARGS = (
82*800a58d9SAndroid Build Coastguard Worker    " -daemon -config=%s -system_image_dir %s -instance_dir %s "
83*800a58d9SAndroid Build Coastguard Worker    "-undefok=report_anonymous_usage_stats,config "
84*800a58d9SAndroid Build Coastguard Worker    "-report_anonymous_usage_stats=y")
85*800a58d9SAndroid Build Coastguard Worker_CMD_LAUNCH_CVD_HW_ARGS = " -cpus %s -x_res %s -y_res %s -dpi %s -memory_mb %s"
86*800a58d9SAndroid Build Coastguard Worker_CMD_LAUNCH_CVD_DISK_ARGS = (
87*800a58d9SAndroid Build Coastguard Worker    " -blank_data_image_mb %s -data_policy always_create")
88*800a58d9SAndroid Build Coastguard Worker_CMD_LAUNCH_CVD_WEBRTC_ARGS = " -start_webrtc=true"
89*800a58d9SAndroid Build Coastguard Worker_CMD_LAUNCH_CVD_VNC_ARG = " -start_vnc_server=true"
90*800a58d9SAndroid Build Coastguard Worker_CMD_LAUNCH_CVD_SUPER_IMAGE_ARG = " -super_image=%s"
91*800a58d9SAndroid Build Coastguard Worker_CMD_LAUNCH_CVD_BOOT_IMAGE_ARG = " -boot_image=%s"
92*800a58d9SAndroid Build Coastguard Worker_CMD_LAUNCH_CVD_VENDOR_BOOT_IMAGE_ARG = " -vendor_boot_image=%s"
93*800a58d9SAndroid Build Coastguard Worker_CMD_LAUNCH_CVD_KERNEL_IMAGE_ARG = " -kernel_path=%s"
94*800a58d9SAndroid Build Coastguard Worker_CMD_LAUNCH_CVD_INITRAMFS_IMAGE_ARG = " -initramfs_path=%s"
95*800a58d9SAndroid Build Coastguard Worker_CMD_LAUNCH_CVD_VBMETA_IMAGE_ARG = " -vbmeta_image=%s"
96*800a58d9SAndroid Build Coastguard Worker_CMD_LAUNCH_CVD_NO_ADB_ARG = " -run_adb_connector=false"
97*800a58d9SAndroid Build Coastguard Worker_CMD_LAUNCH_CVD_INSTANCE_NUMS_ARG = " -instance_nums=%s"
98*800a58d9SAndroid Build Coastguard Worker# Connect the OpenWrt device via console file.
99*800a58d9SAndroid Build Coastguard Worker_CMD_LAUNCH_CVD_CONSOLE_ARG = " -console=true"
100*800a58d9SAndroid Build Coastguard Worker_CMD_LAUNCH_CVD_WEBRTC_DEIVE_ID = " -webrtc_device_id=%s"
101*800a58d9SAndroid Build Coastguard Worker_CONFIG_RE = re.compile(r"^config=(?P<config>.+)")
102*800a58d9SAndroid Build Coastguard Worker_CONSOLE_NAME = "console"
103*800a58d9SAndroid Build Coastguard Worker# Files to store the output when launching cvds.
104*800a58d9SAndroid Build Coastguard Worker_STDOUT = "stdout"
105*800a58d9SAndroid Build Coastguard Worker_STDERR = "stderr"
106*800a58d9SAndroid Build Coastguard Worker_MAX_REPORTED_ERROR_LINES = 10
107*800a58d9SAndroid Build Coastguard Worker
108*800a58d9SAndroid Build Coastguard Worker# In accordance with the number of network interfaces in
109*800a58d9SAndroid Build Coastguard Worker# /etc/init.d/cuttlefish-common
110*800a58d9SAndroid Build Coastguard Worker_MAX_INSTANCE_ID = 10
111*800a58d9SAndroid Build Coastguard Worker
112*800a58d9SAndroid Build Coastguard Worker# TODO(b/213521240): To check why the delete function is not work and
113*800a58d9SAndroid Build Coastguard Worker# has to manually delete temp folder.
114*800a58d9SAndroid Build Coastguard Worker_INSTANCES_IN_USE_MSG = ("All instances are in use. Try resetting an instance "
115*800a58d9SAndroid Build Coastguard Worker                         "by specifying --local-instance and an id between 1 "
116*800a58d9SAndroid Build Coastguard Worker                         "and %d. Alternatively, to run 'acloud delete --all' "
117*800a58d9SAndroid Build Coastguard Worker                         % _MAX_INSTANCE_ID)
118*800a58d9SAndroid Build Coastguard Worker_CONFIRM_RELAUNCH = ("\nCuttlefish AVD[id:%d] is already running. \n"
119*800a58d9SAndroid Build Coastguard Worker                     "Enter 'y' to terminate current instance and launch a "
120*800a58d9SAndroid Build Coastguard Worker                     "new instance, enter anything else to exit out[y/N]: ")
121*800a58d9SAndroid Build Coastguard Worker
122*800a58d9SAndroid Build Coastguard Worker# The first two fields of this named tuple are image folder and CVD host
123*800a58d9SAndroid Build Coastguard Worker# package folder which are essential for local instances. The following fields
124*800a58d9SAndroid Build Coastguard Worker# are optional. They are set when the AVD spec requires to mix images.
125*800a58d9SAndroid Build Coastguard WorkerArtifactPaths = collections.namedtuple(
126*800a58d9SAndroid Build Coastguard Worker    "ArtifactPaths",
127*800a58d9SAndroid Build Coastguard Worker    ["image_dir", "host_bins", "host_artifacts", "misc_info", "ota_tools_dir",
128*800a58d9SAndroid Build Coastguard Worker     "system_image", "system_ext_image", "product_image",
129*800a58d9SAndroid Build Coastguard Worker     "boot_image", "vendor_boot_image", "kernel_image", "initramfs_image",
130*800a58d9SAndroid Build Coastguard Worker     "vendor_image", "vendor_dlkm_image", "odm_image", "odm_dlkm_image"])
131*800a58d9SAndroid Build Coastguard Worker
132*800a58d9SAndroid Build Coastguard Worker
133*800a58d9SAndroid Build Coastguard Workerclass LocalImageLocalInstance(base_avd_create.BaseAVDCreate):
134*800a58d9SAndroid Build Coastguard Worker    """Create class for a local image local instance AVD."""
135*800a58d9SAndroid Build Coastguard Worker
136*800a58d9SAndroid Build Coastguard Worker    @utils.TimeExecute(function_description="Total time: ",
137*800a58d9SAndroid Build Coastguard Worker                       print_before_call=False, print_status=False)
138*800a58d9SAndroid Build Coastguard Worker    def _CreateAVD(self, avd_spec, no_prompts):
139*800a58d9SAndroid Build Coastguard Worker        """Create the AVD.
140*800a58d9SAndroid Build Coastguard Worker
141*800a58d9SAndroid Build Coastguard Worker        Args:
142*800a58d9SAndroid Build Coastguard Worker            avd_spec: AVDSpec object that tells us what we're going to create.
143*800a58d9SAndroid Build Coastguard Worker            no_prompts: Boolean, True to skip all prompts.
144*800a58d9SAndroid Build Coastguard Worker
145*800a58d9SAndroid Build Coastguard Worker        Returns:
146*800a58d9SAndroid Build Coastguard Worker            A Report instance.
147*800a58d9SAndroid Build Coastguard Worker        """
148*800a58d9SAndroid Build Coastguard Worker        # Running instances on local is not supported on all OS.
149*800a58d9SAndroid Build Coastguard Worker        result_report = report.Report(command="create")
150*800a58d9SAndroid Build Coastguard Worker        if not utils.IsSupportedPlatform(print_warning=True):
151*800a58d9SAndroid Build Coastguard Worker            result_report.UpdateFailure(
152*800a58d9SAndroid Build Coastguard Worker                "The platform doesn't support to run acloud.")
153*800a58d9SAndroid Build Coastguard Worker            return result_report
154*800a58d9SAndroid Build Coastguard Worker        if not utils.IsSupportedKvm():
155*800a58d9SAndroid Build Coastguard Worker            result_report.UpdateFailure(
156*800a58d9SAndroid Build Coastguard Worker                "The environment doesn't support virtualization.")
157*800a58d9SAndroid Build Coastguard Worker            return result_report
158*800a58d9SAndroid Build Coastguard Worker
159*800a58d9SAndroid Build Coastguard Worker        artifact_paths = self.GetImageArtifactsPath(avd_spec)
160*800a58d9SAndroid Build Coastguard Worker
161*800a58d9SAndroid Build Coastguard Worker        try:
162*800a58d9SAndroid Build Coastguard Worker            ins_ids, ins_locks = self._SelectAndLockInstances(avd_spec)
163*800a58d9SAndroid Build Coastguard Worker        except errors.CreateError as e:
164*800a58d9SAndroid Build Coastguard Worker            result_report.UpdateFailure(str(e))
165*800a58d9SAndroid Build Coastguard Worker            return result_report
166*800a58d9SAndroid Build Coastguard Worker
167*800a58d9SAndroid Build Coastguard Worker        try:
168*800a58d9SAndroid Build Coastguard Worker            for ins_id, ins_lock in zip(ins_ids, ins_locks):
169*800a58d9SAndroid Build Coastguard Worker                if not self._CheckRunningCvd(ins_id, no_prompts):
170*800a58d9SAndroid Build Coastguard Worker                    # Mark as in-use so that it won't be auto-selected again.
171*800a58d9SAndroid Build Coastguard Worker                    ins_lock.SetInUse(True)
172*800a58d9SAndroid Build Coastguard Worker                    sys.exit(constants.EXIT_BY_USER)
173*800a58d9SAndroid Build Coastguard Worker
174*800a58d9SAndroid Build Coastguard Worker            result_report = self._CreateInstance(ins_ids, artifact_paths,
175*800a58d9SAndroid Build Coastguard Worker                                                 avd_spec, no_prompts)
176*800a58d9SAndroid Build Coastguard Worker            # Set the state to in-use if the instances start successfully.
177*800a58d9SAndroid Build Coastguard Worker            # Failing instances are not set to in-use so that the user can
178*800a58d9SAndroid Build Coastguard Worker            # restart them with the same IDs.
179*800a58d9SAndroid Build Coastguard Worker            if result_report.status == report.Status.SUCCESS:
180*800a58d9SAndroid Build Coastguard Worker                for ins_lock in ins_locks:
181*800a58d9SAndroid Build Coastguard Worker                    ins_lock.SetInUse(True)
182*800a58d9SAndroid Build Coastguard Worker            return result_report
183*800a58d9SAndroid Build Coastguard Worker        finally:
184*800a58d9SAndroid Build Coastguard Worker            for ins_lock in ins_locks:
185*800a58d9SAndroid Build Coastguard Worker                ins_lock.Unlock()
186*800a58d9SAndroid Build Coastguard Worker
187*800a58d9SAndroid Build Coastguard Worker    def _SelectAndLockInstances(self, avd_spec):
188*800a58d9SAndroid Build Coastguard Worker        """Select the ids and lock these instances.
189*800a58d9SAndroid Build Coastguard Worker
190*800a58d9SAndroid Build Coastguard Worker        Args:
191*800a58d9SAndroid Build Coastguard Worker            avd_spec: AVCSpec for the device.
192*800a58d9SAndroid Build Coastguard Worker
193*800a58d9SAndroid Build Coastguard Worker        Returns:
194*800a58d9SAndroid Build Coastguard Worker            The instance ids and the LocalInstanceLock that are locked.
195*800a58d9SAndroid Build Coastguard Worker        """
196*800a58d9SAndroid Build Coastguard Worker        main_id, main_lock = self._SelectAndLockInstance(avd_spec)
197*800a58d9SAndroid Build Coastguard Worker        ins_ids = [main_id]
198*800a58d9SAndroid Build Coastguard Worker        ins_locks = [main_lock]
199*800a58d9SAndroid Build Coastguard Worker        for _ in range(2, avd_spec.num_avds_per_instance + 1):
200*800a58d9SAndroid Build Coastguard Worker            ins_id, ins_lock = self._SelectOneFreeInstance()
201*800a58d9SAndroid Build Coastguard Worker            ins_ids.append(ins_id)
202*800a58d9SAndroid Build Coastguard Worker            ins_locks.append(ins_lock)
203*800a58d9SAndroid Build Coastguard Worker        logger.info("Selected instance ids: %s", ins_ids)
204*800a58d9SAndroid Build Coastguard Worker        return ins_ids, ins_locks
205*800a58d9SAndroid Build Coastguard Worker
206*800a58d9SAndroid Build Coastguard Worker    def _SelectAndLockInstance(self, avd_spec):
207*800a58d9SAndroid Build Coastguard Worker        """Select an id and lock the instance.
208*800a58d9SAndroid Build Coastguard Worker
209*800a58d9SAndroid Build Coastguard Worker        Args:
210*800a58d9SAndroid Build Coastguard Worker            avd_spec: AVDSpec for the device.
211*800a58d9SAndroid Build Coastguard Worker
212*800a58d9SAndroid Build Coastguard Worker        Returns:
213*800a58d9SAndroid Build Coastguard Worker            The instance id and the LocalInstanceLock that is locked by this
214*800a58d9SAndroid Build Coastguard Worker            process.
215*800a58d9SAndroid Build Coastguard Worker
216*800a58d9SAndroid Build Coastguard Worker        Raises:
217*800a58d9SAndroid Build Coastguard Worker            errors.CreateError if fails to select or lock the instance.
218*800a58d9SAndroid Build Coastguard Worker        """
219*800a58d9SAndroid Build Coastguard Worker        if avd_spec.local_instance_id:
220*800a58d9SAndroid Build Coastguard Worker            ins_id = avd_spec.local_instance_id
221*800a58d9SAndroid Build Coastguard Worker            ins_lock = instance.GetLocalInstanceLock(ins_id)
222*800a58d9SAndroid Build Coastguard Worker            if ins_lock.Lock():
223*800a58d9SAndroid Build Coastguard Worker                return ins_id, ins_lock
224*800a58d9SAndroid Build Coastguard Worker            raise errors.CreateError("Instance %d is locked by another "
225*800a58d9SAndroid Build Coastguard Worker                                     "process." % ins_id)
226*800a58d9SAndroid Build Coastguard Worker        return self._SelectOneFreeInstance()
227*800a58d9SAndroid Build Coastguard Worker
228*800a58d9SAndroid Build Coastguard Worker    @staticmethod
229*800a58d9SAndroid Build Coastguard Worker    def _SelectOneFreeInstance():
230*800a58d9SAndroid Build Coastguard Worker        """Select one free id and lock the instance.
231*800a58d9SAndroid Build Coastguard Worker
232*800a58d9SAndroid Build Coastguard Worker        Returns:
233*800a58d9SAndroid Build Coastguard Worker            The instance id and the LocalInstanceLock that is locked by this
234*800a58d9SAndroid Build Coastguard Worker            process.
235*800a58d9SAndroid Build Coastguard Worker
236*800a58d9SAndroid Build Coastguard Worker        Raises:
237*800a58d9SAndroid Build Coastguard Worker            errors.CreateError if fails to select or lock the instance.
238*800a58d9SAndroid Build Coastguard Worker        """
239*800a58d9SAndroid Build Coastguard Worker        for ins_id in range(1, _MAX_INSTANCE_ID + 1):
240*800a58d9SAndroid Build Coastguard Worker            ins_lock = instance.GetLocalInstanceLock(ins_id)
241*800a58d9SAndroid Build Coastguard Worker            if ins_lock.LockIfNotInUse(timeout_secs=0):
242*800a58d9SAndroid Build Coastguard Worker                return ins_id, ins_lock
243*800a58d9SAndroid Build Coastguard Worker        raise errors.CreateError(_INSTANCES_IN_USE_MSG)
244*800a58d9SAndroid Build Coastguard Worker
245*800a58d9SAndroid Build Coastguard Worker    # pylint: disable=too-many-locals,too-many-statements
246*800a58d9SAndroid Build Coastguard Worker    def _CreateInstance(self, instance_ids, artifact_paths, avd_spec,
247*800a58d9SAndroid Build Coastguard Worker                        no_prompts):
248*800a58d9SAndroid Build Coastguard Worker        """Create a CVD instance.
249*800a58d9SAndroid Build Coastguard Worker
250*800a58d9SAndroid Build Coastguard Worker        Args:
251*800a58d9SAndroid Build Coastguard Worker            instance_ids: List of integer of instance ids.
252*800a58d9SAndroid Build Coastguard Worker            artifact_paths: ArtifactPaths object.
253*800a58d9SAndroid Build Coastguard Worker            avd_spec: AVDSpec for the instance.
254*800a58d9SAndroid Build Coastguard Worker            no_prompts: Boolean, True to skip all prompts.
255*800a58d9SAndroid Build Coastguard Worker
256*800a58d9SAndroid Build Coastguard Worker        Returns:
257*800a58d9SAndroid Build Coastguard Worker            A Report instance.
258*800a58d9SAndroid Build Coastguard Worker        """
259*800a58d9SAndroid Build Coastguard Worker        local_instance_id = instance_ids[0]
260*800a58d9SAndroid Build Coastguard Worker        webrtc_port = self.GetWebrtcSigServerPort(local_instance_id)
261*800a58d9SAndroid Build Coastguard Worker        if avd_spec.connect_webrtc:
262*800a58d9SAndroid Build Coastguard Worker            utils.ReleasePort(webrtc_port)
263*800a58d9SAndroid Build Coastguard Worker
264*800a58d9SAndroid Build Coastguard Worker        cvd_home_dir = instance.GetLocalInstanceHomeDir(local_instance_id)
265*800a58d9SAndroid Build Coastguard Worker        create_common.PrepareLocalInstanceDir(cvd_home_dir, avd_spec)
266*800a58d9SAndroid Build Coastguard Worker        super_image_path = None
267*800a58d9SAndroid Build Coastguard Worker        vbmeta_image_path = None
268*800a58d9SAndroid Build Coastguard Worker        if artifact_paths.system_image or artifact_paths.vendor_image:
269*800a58d9SAndroid Build Coastguard Worker            super_image_path = os.path.join(cvd_home_dir,
270*800a58d9SAndroid Build Coastguard Worker                                            _MIXED_SUPER_IMAGE_NAME)
271*800a58d9SAndroid Build Coastguard Worker            ota = ota_tools.OtaTools(artifact_paths.ota_tools_dir)
272*800a58d9SAndroid Build Coastguard Worker            ota.MixSuperImage(
273*800a58d9SAndroid Build Coastguard Worker                super_image_path, artifact_paths.misc_info,
274*800a58d9SAndroid Build Coastguard Worker                artifact_paths.image_dir,
275*800a58d9SAndroid Build Coastguard Worker                system_image=artifact_paths.system_image,
276*800a58d9SAndroid Build Coastguard Worker                system_ext_image=artifact_paths.system_ext_image,
277*800a58d9SAndroid Build Coastguard Worker                product_image=artifact_paths.product_image,
278*800a58d9SAndroid Build Coastguard Worker                vendor_image=artifact_paths.vendor_image,
279*800a58d9SAndroid Build Coastguard Worker                vendor_dlkm_image=artifact_paths.vendor_dlkm_image,
280*800a58d9SAndroid Build Coastguard Worker                odm_image=artifact_paths.odm_image,
281*800a58d9SAndroid Build Coastguard Worker                odm_dlkm_image=artifact_paths.odm_dlkm_image)
282*800a58d9SAndroid Build Coastguard Worker            vbmeta_image_path = os.path.join(cvd_home_dir,
283*800a58d9SAndroid Build Coastguard Worker                                             "disabled_vbmeta.img")
284*800a58d9SAndroid Build Coastguard Worker            ota.MakeDisabledVbmetaImage(vbmeta_image_path)
285*800a58d9SAndroid Build Coastguard Worker        runtime_dir = instance.GetLocalInstanceRuntimeDir(local_instance_id)
286*800a58d9SAndroid Build Coastguard Worker        # TODO(b/168171781): cvd_status of list/delete via the symbolic.
287*800a58d9SAndroid Build Coastguard Worker        self.PrepareLocalCvdToolsLink(cvd_home_dir, artifact_paths.host_bins)
288*800a58d9SAndroid Build Coastguard Worker        if avd_spec.mkcert and avd_spec.connect_webrtc:
289*800a58d9SAndroid Build Coastguard Worker            self._TrustCertificatesForWebRTC(artifact_paths.host_artifacts)
290*800a58d9SAndroid Build Coastguard Worker        if not avd_spec.use_launch_cvd:
291*800a58d9SAndroid Build Coastguard Worker            self._LogCvdVersion(artifact_paths.host_bins)
292*800a58d9SAndroid Build Coastguard Worker
293*800a58d9SAndroid Build Coastguard Worker        hw_property = None
294*800a58d9SAndroid Build Coastguard Worker        if avd_spec.hw_customize:
295*800a58d9SAndroid Build Coastguard Worker            hw_property = avd_spec.hw_property
296*800a58d9SAndroid Build Coastguard Worker        config = self._GetConfigFromAndroidInfo(
297*800a58d9SAndroid Build Coastguard Worker            os.path.join(artifact_paths.image_dir,
298*800a58d9SAndroid Build Coastguard Worker                         constants.ANDROID_INFO_FILE))
299*800a58d9SAndroid Build Coastguard Worker        cmd = self.PrepareLaunchCVDCmd(hw_property,
300*800a58d9SAndroid Build Coastguard Worker                                       avd_spec.connect_adb,
301*800a58d9SAndroid Build Coastguard Worker                                       artifact_paths,
302*800a58d9SAndroid Build Coastguard Worker                                       runtime_dir,
303*800a58d9SAndroid Build Coastguard Worker                                       avd_spec.connect_webrtc,
304*800a58d9SAndroid Build Coastguard Worker                                       avd_spec.connect_vnc,
305*800a58d9SAndroid Build Coastguard Worker                                       super_image_path,
306*800a58d9SAndroid Build Coastguard Worker                                       avd_spec.launch_args,
307*800a58d9SAndroid Build Coastguard Worker                                       config or avd_spec.flavor,
308*800a58d9SAndroid Build Coastguard Worker                                       avd_spec.openwrt,
309*800a58d9SAndroid Build Coastguard Worker                                       avd_spec.use_launch_cvd,
310*800a58d9SAndroid Build Coastguard Worker                                       instance_ids,
311*800a58d9SAndroid Build Coastguard Worker                                       avd_spec.webrtc_device_id,
312*800a58d9SAndroid Build Coastguard Worker                                       vbmeta_image_path)
313*800a58d9SAndroid Build Coastguard Worker
314*800a58d9SAndroid Build Coastguard Worker        result_report = report.Report(command="create")
315*800a58d9SAndroid Build Coastguard Worker        instance_name = instance.GetLocalInstanceName(local_instance_id)
316*800a58d9SAndroid Build Coastguard Worker        try:
317*800a58d9SAndroid Build Coastguard Worker            self._LaunchCvd(cmd, local_instance_id, artifact_paths.host_bins,
318*800a58d9SAndroid Build Coastguard Worker                            artifact_paths.host_artifacts,
319*800a58d9SAndroid Build Coastguard Worker                            cvd_home_dir, (avd_spec.boot_timeout_secs or
320*800a58d9SAndroid Build Coastguard Worker                                           constants.DEFAULT_CF_BOOT_TIMEOUT))
321*800a58d9SAndroid Build Coastguard Worker            logs = cvd_utils.FindLocalLogs(runtime_dir, local_instance_id)
322*800a58d9SAndroid Build Coastguard Worker        except errors.LaunchCVDFail as launch_error:
323*800a58d9SAndroid Build Coastguard Worker            logs = cvd_utils.FindLocalLogs(runtime_dir, local_instance_id)
324*800a58d9SAndroid Build Coastguard Worker            err_msg = ("Cannot create cuttlefish instance: %s\n"
325*800a58d9SAndroid Build Coastguard Worker                       "For more detail: %s/launcher.log" %
326*800a58d9SAndroid Build Coastguard Worker                       (launch_error, runtime_dir))
327*800a58d9SAndroid Build Coastguard Worker            if constants.ERROR_MSG_WEBRTC_NOT_SUPPORT in str(launch_error):
328*800a58d9SAndroid Build Coastguard Worker                err_msg = (
329*800a58d9SAndroid Build Coastguard Worker                    "WEBRTC is not supported in current build. Please try VNC "
330*800a58d9SAndroid Build Coastguard Worker                    "such as '$acloud create --autoconnect vnc'")
331*800a58d9SAndroid Build Coastguard Worker            result_report.SetStatus(report.Status.BOOT_FAIL)
332*800a58d9SAndroid Build Coastguard Worker            result_report.SetErrorType(constants.ACLOUD_BOOT_UP_ERROR)
333*800a58d9SAndroid Build Coastguard Worker            result_report.AddDeviceBootFailure(
334*800a58d9SAndroid Build Coastguard Worker                instance_name, constants.LOCALHOST, None, None, error=err_msg,
335*800a58d9SAndroid Build Coastguard Worker                logs=logs)
336*800a58d9SAndroid Build Coastguard Worker            return result_report
337*800a58d9SAndroid Build Coastguard Worker
338*800a58d9SAndroid Build Coastguard Worker        active_ins = list_instance.GetActiveCVD(local_instance_id)
339*800a58d9SAndroid Build Coastguard Worker        if active_ins:
340*800a58d9SAndroid Build Coastguard Worker            update_data = None
341*800a58d9SAndroid Build Coastguard Worker            if avd_spec.openwrt:
342*800a58d9SAndroid Build Coastguard Worker                console_dir = os.path.dirname(
343*800a58d9SAndroid Build Coastguard Worker                    instance.GetLocalInstanceConfig(local_instance_id))
344*800a58d9SAndroid Build Coastguard Worker                console_path = os.path.join(console_dir, _CONSOLE_NAME)
345*800a58d9SAndroid Build Coastguard Worker                update_data = {"screen_command": f"screen {console_path}"}
346*800a58d9SAndroid Build Coastguard Worker            result_report.SetStatus(report.Status.SUCCESS)
347*800a58d9SAndroid Build Coastguard Worker            result_report.AddDevice(instance_name, constants.LOCALHOST,
348*800a58d9SAndroid Build Coastguard Worker                                    active_ins.adb_port, active_ins.vnc_port,
349*800a58d9SAndroid Build Coastguard Worker                                    webrtc_port, logs=logs,
350*800a58d9SAndroid Build Coastguard Worker                                    update_data=update_data)
351*800a58d9SAndroid Build Coastguard Worker            # Launch vnc client if we're auto-connecting.
352*800a58d9SAndroid Build Coastguard Worker            if avd_spec.connect_vnc:
353*800a58d9SAndroid Build Coastguard Worker                utils.LaunchVNCFromReport(result_report, avd_spec, no_prompts)
354*800a58d9SAndroid Build Coastguard Worker            if avd_spec.connect_webrtc:
355*800a58d9SAndroid Build Coastguard Worker                utils.LaunchBrowserFromReport(result_report)
356*800a58d9SAndroid Build Coastguard Worker            if avd_spec.unlock_screen:
357*800a58d9SAndroid Build Coastguard Worker                AdbTools(active_ins.adb_port).AutoUnlockScreen()
358*800a58d9SAndroid Build Coastguard Worker        else:
359*800a58d9SAndroid Build Coastguard Worker            err_msg = "cvd_status return non-zero after launch_cvd"
360*800a58d9SAndroid Build Coastguard Worker            logger.error(err_msg)
361*800a58d9SAndroid Build Coastguard Worker            result_report.SetStatus(report.Status.BOOT_FAIL)
362*800a58d9SAndroid Build Coastguard Worker            result_report.SetErrorType(constants.ACLOUD_BOOT_UP_ERROR)
363*800a58d9SAndroid Build Coastguard Worker            result_report.AddDeviceBootFailure(
364*800a58d9SAndroid Build Coastguard Worker                instance_name, constants.LOCALHOST, None, None, error=err_msg,
365*800a58d9SAndroid Build Coastguard Worker                logs=logs)
366*800a58d9SAndroid Build Coastguard Worker        return result_report
367*800a58d9SAndroid Build Coastguard Worker
368*800a58d9SAndroid Build Coastguard Worker    @staticmethod
369*800a58d9SAndroid Build Coastguard Worker    def GetWebrtcSigServerPort(instance_id):
370*800a58d9SAndroid Build Coastguard Worker        """Get the port of the signaling server.
371*800a58d9SAndroid Build Coastguard Worker
372*800a58d9SAndroid Build Coastguard Worker        Args:
373*800a58d9SAndroid Build Coastguard Worker            instance_id: Integer of instance id.
374*800a58d9SAndroid Build Coastguard Worker
375*800a58d9SAndroid Build Coastguard Worker        Returns:
376*800a58d9SAndroid Build Coastguard Worker            Integer of signaling server port.
377*800a58d9SAndroid Build Coastguard Worker        """
378*800a58d9SAndroid Build Coastguard Worker        return constants.WEBRTC_LOCAL_PORT + instance_id - 1
379*800a58d9SAndroid Build Coastguard Worker
380*800a58d9SAndroid Build Coastguard Worker    @staticmethod
381*800a58d9SAndroid Build Coastguard Worker    def _FindCvdHostBinaries(search_paths):
382*800a58d9SAndroid Build Coastguard Worker        """Return the directory that contains CVD host binaries."""
383*800a58d9SAndroid Build Coastguard Worker        for search_path in search_paths:
384*800a58d9SAndroid Build Coastguard Worker            if os.path.isfile(os.path.join(search_path, "bin",
385*800a58d9SAndroid Build Coastguard Worker                                           constants.CMD_LAUNCH_CVD)):
386*800a58d9SAndroid Build Coastguard Worker                return search_path
387*800a58d9SAndroid Build Coastguard Worker
388*800a58d9SAndroid Build Coastguard Worker        raise errors.GetCvdLocalHostPackageError(
389*800a58d9SAndroid Build Coastguard Worker            "CVD host binaries are not found. Please run `make hosttar`, or "
390*800a58d9SAndroid Build Coastguard Worker            "set --local-tool to an extracted CVD host package.")
391*800a58d9SAndroid Build Coastguard Worker
392*800a58d9SAndroid Build Coastguard Worker    @staticmethod
393*800a58d9SAndroid Build Coastguard Worker    def _FindCvdHostArtifactsPath(search_paths):
394*800a58d9SAndroid Build Coastguard Worker        """Return the directory that contains CVD host artifacts (in particular
395*800a58d9SAndroid Build Coastguard Worker           webrtc).
396*800a58d9SAndroid Build Coastguard Worker        """
397*800a58d9SAndroid Build Coastguard Worker        for search_path in search_paths:
398*800a58d9SAndroid Build Coastguard Worker            if os.path.isfile(os.path.join(search_path,
399*800a58d9SAndroid Build Coastguard Worker                                           "usr/share/webrtc/certs",
400*800a58d9SAndroid Build Coastguard Worker                                           "server.crt")):
401*800a58d9SAndroid Build Coastguard Worker                return search_path
402*800a58d9SAndroid Build Coastguard Worker
403*800a58d9SAndroid Build Coastguard Worker        raise errors.GetCvdLocalHostPackageError(
404*800a58d9SAndroid Build Coastguard Worker            "CVD host webrtc artifacts are not found. Please run "
405*800a58d9SAndroid Build Coastguard Worker            "`make hosttar`, or set --local-tool to an extracted CVD host "
406*800a58d9SAndroid Build Coastguard Worker            "package.")
407*800a58d9SAndroid Build Coastguard Worker
408*800a58d9SAndroid Build Coastguard Worker    @staticmethod
409*800a58d9SAndroid Build Coastguard Worker    def _VerifyExtractedImgZip(image_dir):
410*800a58d9SAndroid Build Coastguard Worker        """Verify that a path is build output dir or extracted img zip.
411*800a58d9SAndroid Build Coastguard Worker
412*800a58d9SAndroid Build Coastguard Worker        This method checks existence of super image. The file is in img zip
413*800a58d9SAndroid Build Coastguard Worker        but not in target files zip. A cuttlefish instance requires a super
414*800a58d9SAndroid Build Coastguard Worker        image if no system image or OTA tools are given.
415*800a58d9SAndroid Build Coastguard Worker
416*800a58d9SAndroid Build Coastguard Worker        Args:
417*800a58d9SAndroid Build Coastguard Worker            image_dir: The directory to be verified.
418*800a58d9SAndroid Build Coastguard Worker
419*800a58d9SAndroid Build Coastguard Worker        Raises:
420*800a58d9SAndroid Build Coastguard Worker            errors.GetLocalImageError if the directory does not contain the
421*800a58d9SAndroid Build Coastguard Worker            needed file.
422*800a58d9SAndroid Build Coastguard Worker        """
423*800a58d9SAndroid Build Coastguard Worker        if not os.path.isfile(os.path.join(image_dir, _SUPER_IMAGE_NAME)):
424*800a58d9SAndroid Build Coastguard Worker            raise errors.GetLocalImageError(
425*800a58d9SAndroid Build Coastguard Worker                f"Cannot find {_SUPER_IMAGE_NAME} in {image_dir}. The "
426*800a58d9SAndroid Build Coastguard Worker                f"directory is expected to be an extracted img zip or "
427*800a58d9SAndroid Build Coastguard Worker                f"{constants.ENV_ANDROID_PRODUCT_OUT}.")
428*800a58d9SAndroid Build Coastguard Worker
429*800a58d9SAndroid Build Coastguard Worker    @staticmethod
430*800a58d9SAndroid Build Coastguard Worker    def FindBootOrKernelImages(image_path):
431*800a58d9SAndroid Build Coastguard Worker        """Find boot, vendor_boot, kernel, and initramfs images in a path.
432*800a58d9SAndroid Build Coastguard Worker
433*800a58d9SAndroid Build Coastguard Worker        This method expects image_path to be:
434*800a58d9SAndroid Build Coastguard Worker        - An output directory of a kernel build. It contains a kernel image and
435*800a58d9SAndroid Build Coastguard Worker          initramfs.img.
436*800a58d9SAndroid Build Coastguard Worker        - A generic boot image or its parent directory. The image name is
437*800a58d9SAndroid Build Coastguard Worker          boot-*.img. The directory does not contain vendor_boot.img.
438*800a58d9SAndroid Build Coastguard Worker        - An output directory of a cuttlefish build. It contains boot.img and
439*800a58d9SAndroid Build Coastguard Worker          vendor_boot.img.
440*800a58d9SAndroid Build Coastguard Worker
441*800a58d9SAndroid Build Coastguard Worker        Args:
442*800a58d9SAndroid Build Coastguard Worker            image_path: A path to an image file or an image directory.
443*800a58d9SAndroid Build Coastguard Worker
444*800a58d9SAndroid Build Coastguard Worker        Returns:
445*800a58d9SAndroid Build Coastguard Worker            A tuple of strings, the paths to boot, vendor_boot, kernel, and
446*800a58d9SAndroid Build Coastguard Worker            initramfs images. Each value can be None.
447*800a58d9SAndroid Build Coastguard Worker
448*800a58d9SAndroid Build Coastguard Worker        Raises:
449*800a58d9SAndroid Build Coastguard Worker            errors.GetLocalImageError if image_path does not contain boot or
450*800a58d9SAndroid Build Coastguard Worker            kernel images.
451*800a58d9SAndroid Build Coastguard Worker        """
452*800a58d9SAndroid Build Coastguard Worker        kernel_image_path, initramfs_image_path = cvd_utils.FindKernelImages(
453*800a58d9SAndroid Build Coastguard Worker            image_path)
454*800a58d9SAndroid Build Coastguard Worker        if kernel_image_path and initramfs_image_path:
455*800a58d9SAndroid Build Coastguard Worker            return None, None, kernel_image_path, initramfs_image_path
456*800a58d9SAndroid Build Coastguard Worker
457*800a58d9SAndroid Build Coastguard Worker        boot_image_path, vendor_boot_image_path = cvd_utils.FindBootImages(
458*800a58d9SAndroid Build Coastguard Worker            image_path)
459*800a58d9SAndroid Build Coastguard Worker        if boot_image_path:
460*800a58d9SAndroid Build Coastguard Worker            return boot_image_path, vendor_boot_image_path, None, None
461*800a58d9SAndroid Build Coastguard Worker
462*800a58d9SAndroid Build Coastguard Worker        raise errors.GetLocalImageError(f"{image_path} is not a boot image or "
463*800a58d9SAndroid Build Coastguard Worker                                        f"a directory containing images.")
464*800a58d9SAndroid Build Coastguard Worker
465*800a58d9SAndroid Build Coastguard Worker    def GetImageArtifactsPath(self, avd_spec):
466*800a58d9SAndroid Build Coastguard Worker        """Get image artifacts path.
467*800a58d9SAndroid Build Coastguard Worker
468*800a58d9SAndroid Build Coastguard Worker        This method will check if launch_cvd is exist and return the tuple path
469*800a58d9SAndroid Build Coastguard Worker        (image path and host bins path) where they are located respectively.
470*800a58d9SAndroid Build Coastguard Worker        For remote image, RemoteImageLocalInstance will override this method
471*800a58d9SAndroid Build Coastguard Worker        and return the artifacts path which is extracted and downloaded from
472*800a58d9SAndroid Build Coastguard Worker        remote.
473*800a58d9SAndroid Build Coastguard Worker
474*800a58d9SAndroid Build Coastguard Worker        Args:
475*800a58d9SAndroid Build Coastguard Worker            avd_spec: AVDSpec object that tells us what we're going to create.
476*800a58d9SAndroid Build Coastguard Worker
477*800a58d9SAndroid Build Coastguard Worker        Returns:
478*800a58d9SAndroid Build Coastguard Worker            ArtifactPaths object consisting of image directory and host bins
479*800a58d9SAndroid Build Coastguard Worker            package.
480*800a58d9SAndroid Build Coastguard Worker
481*800a58d9SAndroid Build Coastguard Worker        Raises:
482*800a58d9SAndroid Build Coastguard Worker            errors.GetCvdLocalHostPackageError, errors.GetLocalImageError, or
483*800a58d9SAndroid Build Coastguard Worker            errors.CheckPathError if any artifact is not found.
484*800a58d9SAndroid Build Coastguard Worker        """
485*800a58d9SAndroid Build Coastguard Worker        image_dir = os.path.abspath(avd_spec.local_image_dir)
486*800a58d9SAndroid Build Coastguard Worker        tool_dirs = (avd_spec.local_tool_dirs +
487*800a58d9SAndroid Build Coastguard Worker                     create_common.GetNonEmptyEnvVars(
488*800a58d9SAndroid Build Coastguard Worker                         constants.ENV_ANDROID_SOONG_HOST_OUT,
489*800a58d9SAndroid Build Coastguard Worker                         constants.ENV_ANDROID_HOST_OUT))
490*800a58d9SAndroid Build Coastguard Worker        host_bins_path = self._FindCvdHostBinaries(tool_dirs)
491*800a58d9SAndroid Build Coastguard Worker        host_artifacts_path = self._FindCvdHostArtifactsPath(tool_dirs)
492*800a58d9SAndroid Build Coastguard Worker
493*800a58d9SAndroid Build Coastguard Worker        if avd_spec.local_system_image:
494*800a58d9SAndroid Build Coastguard Worker            misc_info_path = cvd_utils.FindMiscInfo(image_dir)
495*800a58d9SAndroid Build Coastguard Worker            image_dir = cvd_utils.FindImageDir(image_dir)
496*800a58d9SAndroid Build Coastguard Worker            ota_tools_dir = os.path.abspath(
497*800a58d9SAndroid Build Coastguard Worker                ota_tools.FindOtaToolsDir(tool_dirs))
498*800a58d9SAndroid Build Coastguard Worker            (
499*800a58d9SAndroid Build Coastguard Worker                system_image_path,
500*800a58d9SAndroid Build Coastguard Worker                system_ext_image_path,
501*800a58d9SAndroid Build Coastguard Worker                product_image_path,
502*800a58d9SAndroid Build Coastguard Worker            ) = create_common.FindSystemImages(avd_spec.local_system_image)
503*800a58d9SAndroid Build Coastguard Worker        else:
504*800a58d9SAndroid Build Coastguard Worker            self._VerifyExtractedImgZip(image_dir)
505*800a58d9SAndroid Build Coastguard Worker            misc_info_path = None
506*800a58d9SAndroid Build Coastguard Worker            ota_tools_dir = None
507*800a58d9SAndroid Build Coastguard Worker            system_image_path = None
508*800a58d9SAndroid Build Coastguard Worker            system_ext_image_path = None
509*800a58d9SAndroid Build Coastguard Worker            product_image_path = None
510*800a58d9SAndroid Build Coastguard Worker
511*800a58d9SAndroid Build Coastguard Worker        if avd_spec.local_kernel_image:
512*800a58d9SAndroid Build Coastguard Worker            (
513*800a58d9SAndroid Build Coastguard Worker                boot_image_path,
514*800a58d9SAndroid Build Coastguard Worker                vendor_boot_image_path,
515*800a58d9SAndroid Build Coastguard Worker                kernel_image_path,
516*800a58d9SAndroid Build Coastguard Worker                initramfs_image_path,
517*800a58d9SAndroid Build Coastguard Worker            ) = self.FindBootOrKernelImages(
518*800a58d9SAndroid Build Coastguard Worker                os.path.abspath(avd_spec.local_kernel_image))
519*800a58d9SAndroid Build Coastguard Worker        else:
520*800a58d9SAndroid Build Coastguard Worker            boot_image_path = None
521*800a58d9SAndroid Build Coastguard Worker            vendor_boot_image_path = None
522*800a58d9SAndroid Build Coastguard Worker            kernel_image_path = None
523*800a58d9SAndroid Build Coastguard Worker            initramfs_image_path = None
524*800a58d9SAndroid Build Coastguard Worker
525*800a58d9SAndroid Build Coastguard Worker        if avd_spec.local_vendor_boot_image:
526*800a58d9SAndroid Build Coastguard Worker            vendor_boot_image_path = create_common.FindVendorBootImage(
527*800a58d9SAndroid Build Coastguard Worker                avd_spec.local_vendor_boot_image)
528*800a58d9SAndroid Build Coastguard Worker
529*800a58d9SAndroid Build Coastguard Worker        if avd_spec.local_vendor_image:
530*800a58d9SAndroid Build Coastguard Worker            vendor_image_paths = cvd_utils.FindVendorImages(
531*800a58d9SAndroid Build Coastguard Worker                avd_spec.local_vendor_image)
532*800a58d9SAndroid Build Coastguard Worker            vendor_image_path = vendor_image_paths.vendor
533*800a58d9SAndroid Build Coastguard Worker            vendor_dlkm_image_path = vendor_image_paths.vendor_dlkm
534*800a58d9SAndroid Build Coastguard Worker            odm_image_path = vendor_image_paths.odm
535*800a58d9SAndroid Build Coastguard Worker            odm_dlkm_image_path = vendor_image_paths.odm_dlkm
536*800a58d9SAndroid Build Coastguard Worker        else:
537*800a58d9SAndroid Build Coastguard Worker            vendor_image_path = None
538*800a58d9SAndroid Build Coastguard Worker            vendor_dlkm_image_path = None
539*800a58d9SAndroid Build Coastguard Worker            odm_image_path = None
540*800a58d9SAndroid Build Coastguard Worker            odm_dlkm_image_path = None
541*800a58d9SAndroid Build Coastguard Worker
542*800a58d9SAndroid Build Coastguard Worker        return ArtifactPaths(image_dir, host_bins_path,
543*800a58d9SAndroid Build Coastguard Worker                             host_artifacts=host_artifacts_path,
544*800a58d9SAndroid Build Coastguard Worker                             misc_info=misc_info_path,
545*800a58d9SAndroid Build Coastguard Worker                             ota_tools_dir=ota_tools_dir,
546*800a58d9SAndroid Build Coastguard Worker                             system_image=system_image_path,
547*800a58d9SAndroid Build Coastguard Worker                             system_ext_image=system_ext_image_path,
548*800a58d9SAndroid Build Coastguard Worker                             product_image=product_image_path,
549*800a58d9SAndroid Build Coastguard Worker                             boot_image=boot_image_path,
550*800a58d9SAndroid Build Coastguard Worker                             vendor_boot_image=vendor_boot_image_path,
551*800a58d9SAndroid Build Coastguard Worker                             kernel_image=kernel_image_path,
552*800a58d9SAndroid Build Coastguard Worker                             initramfs_image=initramfs_image_path,
553*800a58d9SAndroid Build Coastguard Worker                             vendor_image=vendor_image_path,
554*800a58d9SAndroid Build Coastguard Worker                             vendor_dlkm_image=vendor_dlkm_image_path,
555*800a58d9SAndroid Build Coastguard Worker                             odm_image=odm_image_path,
556*800a58d9SAndroid Build Coastguard Worker                             odm_dlkm_image=odm_dlkm_image_path)
557*800a58d9SAndroid Build Coastguard Worker
558*800a58d9SAndroid Build Coastguard Worker    @staticmethod
559*800a58d9SAndroid Build Coastguard Worker    def _GetConfigFromAndroidInfo(android_info_path):
560*800a58d9SAndroid Build Coastguard Worker        """Get config value from android-info.txt.
561*800a58d9SAndroid Build Coastguard Worker
562*800a58d9SAndroid Build Coastguard Worker        The config in android-info.txt would like "config=phone".
563*800a58d9SAndroid Build Coastguard Worker
564*800a58d9SAndroid Build Coastguard Worker        Args:
565*800a58d9SAndroid Build Coastguard Worker            android_info_path: String of android-info.txt pah.
566*800a58d9SAndroid Build Coastguard Worker
567*800a58d9SAndroid Build Coastguard Worker        Returns:
568*800a58d9SAndroid Build Coastguard Worker            Strings of config value.
569*800a58d9SAndroid Build Coastguard Worker        """
570*800a58d9SAndroid Build Coastguard Worker        if os.path.exists(android_info_path):
571*800a58d9SAndroid Build Coastguard Worker            with open(android_info_path, "r") as android_info_file:
572*800a58d9SAndroid Build Coastguard Worker                android_info = android_info_file.read()
573*800a58d9SAndroid Build Coastguard Worker                logger.debug("Android info: %s", android_info)
574*800a58d9SAndroid Build Coastguard Worker                config_match = _CONFIG_RE.match(android_info)
575*800a58d9SAndroid Build Coastguard Worker                if config_match:
576*800a58d9SAndroid Build Coastguard Worker                    return config_match.group("config")
577*800a58d9SAndroid Build Coastguard Worker        return None
578*800a58d9SAndroid Build Coastguard Worker
579*800a58d9SAndroid Build Coastguard Worker    # pylint: disable=too-many-branches
580*800a58d9SAndroid Build Coastguard Worker    @staticmethod
581*800a58d9SAndroid Build Coastguard Worker    def PrepareLaunchCVDCmd(hw_property, connect_adb, artifact_paths,
582*800a58d9SAndroid Build Coastguard Worker                            runtime_dir, connect_webrtc, connect_vnc,
583*800a58d9SAndroid Build Coastguard Worker                            super_image_path, launch_args, config,
584*800a58d9SAndroid Build Coastguard Worker                            openwrt=False, use_launch_cvd=False,
585*800a58d9SAndroid Build Coastguard Worker                            instance_ids=None, webrtc_device_id=None,
586*800a58d9SAndroid Build Coastguard Worker                            vbmeta_image_path=None):
587*800a58d9SAndroid Build Coastguard Worker        """Prepare launch_cvd command.
588*800a58d9SAndroid Build Coastguard Worker
589*800a58d9SAndroid Build Coastguard Worker        Create the launch_cvd commands with all the required args and add
590*800a58d9SAndroid Build Coastguard Worker        in the user groups to it if necessary.
591*800a58d9SAndroid Build Coastguard Worker
592*800a58d9SAndroid Build Coastguard Worker        Args:
593*800a58d9SAndroid Build Coastguard Worker            hw_property: dict object of hw property.
594*800a58d9SAndroid Build Coastguard Worker            artifact_paths: ArtifactPaths object.
595*800a58d9SAndroid Build Coastguard Worker            connect_adb: Boolean flag that enables adb_connector.
596*800a58d9SAndroid Build Coastguard Worker            runtime_dir: String of runtime directory path.
597*800a58d9SAndroid Build Coastguard Worker            connect_webrtc: Boolean of connect_webrtc.
598*800a58d9SAndroid Build Coastguard Worker            connect_vnc: Boolean of connect_vnc.
599*800a58d9SAndroid Build Coastguard Worker            super_image_path: String of non-default super image path.
600*800a58d9SAndroid Build Coastguard Worker            launch_args: String of launch args.
601*800a58d9SAndroid Build Coastguard Worker            config: String of config name.
602*800a58d9SAndroid Build Coastguard Worker            openwrt: Boolean of enable OpenWrt devices.
603*800a58d9SAndroid Build Coastguard Worker            use_launch_cvd: Boolean of using launch_cvd for old build cases.
604*800a58d9SAndroid Build Coastguard Worker            instance_ids: List of integer of instance ids.
605*800a58d9SAndroid Build Coastguard Worker            webrtc_device_id: String of webrtc device id.
606*800a58d9SAndroid Build Coastguard Worker            vbmeta_image_path: String of vbmeta image path.
607*800a58d9SAndroid Build Coastguard Worker
608*800a58d9SAndroid Build Coastguard Worker        Returns:
609*800a58d9SAndroid Build Coastguard Worker            String, cvd start cmd.
610*800a58d9SAndroid Build Coastguard Worker        """
611*800a58d9SAndroid Build Coastguard Worker        bin_dir = os.path.join(artifact_paths.host_bins, "bin")
612*800a58d9SAndroid Build Coastguard Worker        cvd_path = os.path.join(bin_dir, constants.CMD_CVD)
613*800a58d9SAndroid Build Coastguard Worker        start_cvd_cmd = cvd_path + _CMD_CVD_START
614*800a58d9SAndroid Build Coastguard Worker        if use_launch_cvd or not os.path.isfile(cvd_path):
615*800a58d9SAndroid Build Coastguard Worker            start_cvd_cmd = os.path.join(bin_dir, constants.CMD_LAUNCH_CVD)
616*800a58d9SAndroid Build Coastguard Worker        launch_cvd_w_args = start_cvd_cmd + _CMD_LAUNCH_CVD_ARGS % (
617*800a58d9SAndroid Build Coastguard Worker            config, artifact_paths.image_dir, runtime_dir)
618*800a58d9SAndroid Build Coastguard Worker        if hw_property:
619*800a58d9SAndroid Build Coastguard Worker            launch_cvd_w_args = launch_cvd_w_args + _CMD_LAUNCH_CVD_HW_ARGS % (
620*800a58d9SAndroid Build Coastguard Worker                hw_property["cpu"], hw_property["x_res"], hw_property["y_res"],
621*800a58d9SAndroid Build Coastguard Worker                hw_property["dpi"], hw_property["memory"])
622*800a58d9SAndroid Build Coastguard Worker            if constants.HW_ALIAS_DISK in hw_property:
623*800a58d9SAndroid Build Coastguard Worker                launch_cvd_w_args = (launch_cvd_w_args +
624*800a58d9SAndroid Build Coastguard Worker                                     _CMD_LAUNCH_CVD_DISK_ARGS %
625*800a58d9SAndroid Build Coastguard Worker                                     hw_property[constants.HW_ALIAS_DISK])
626*800a58d9SAndroid Build Coastguard Worker
627*800a58d9SAndroid Build Coastguard Worker        if not connect_adb:
628*800a58d9SAndroid Build Coastguard Worker            launch_cvd_w_args = launch_cvd_w_args + _CMD_LAUNCH_CVD_NO_ADB_ARG
629*800a58d9SAndroid Build Coastguard Worker
630*800a58d9SAndroid Build Coastguard Worker        if connect_webrtc:
631*800a58d9SAndroid Build Coastguard Worker            launch_cvd_w_args = launch_cvd_w_args + _CMD_LAUNCH_CVD_WEBRTC_ARGS
632*800a58d9SAndroid Build Coastguard Worker
633*800a58d9SAndroid Build Coastguard Worker        if connect_vnc:
634*800a58d9SAndroid Build Coastguard Worker            launch_cvd_w_args = launch_cvd_w_args + _CMD_LAUNCH_CVD_VNC_ARG
635*800a58d9SAndroid Build Coastguard Worker
636*800a58d9SAndroid Build Coastguard Worker        if super_image_path:
637*800a58d9SAndroid Build Coastguard Worker            launch_cvd_w_args = (launch_cvd_w_args +
638*800a58d9SAndroid Build Coastguard Worker                                 _CMD_LAUNCH_CVD_SUPER_IMAGE_ARG %
639*800a58d9SAndroid Build Coastguard Worker                                 super_image_path)
640*800a58d9SAndroid Build Coastguard Worker
641*800a58d9SAndroid Build Coastguard Worker        if artifact_paths.boot_image:
642*800a58d9SAndroid Build Coastguard Worker            launch_cvd_w_args = (launch_cvd_w_args +
643*800a58d9SAndroid Build Coastguard Worker                                 _CMD_LAUNCH_CVD_BOOT_IMAGE_ARG %
644*800a58d9SAndroid Build Coastguard Worker                                 artifact_paths.boot_image)
645*800a58d9SAndroid Build Coastguard Worker
646*800a58d9SAndroid Build Coastguard Worker        if artifact_paths.vendor_boot_image:
647*800a58d9SAndroid Build Coastguard Worker            launch_cvd_w_args = (launch_cvd_w_args +
648*800a58d9SAndroid Build Coastguard Worker                                 _CMD_LAUNCH_CVD_VENDOR_BOOT_IMAGE_ARG %
649*800a58d9SAndroid Build Coastguard Worker                                 artifact_paths.vendor_boot_image)
650*800a58d9SAndroid Build Coastguard Worker
651*800a58d9SAndroid Build Coastguard Worker        if artifact_paths.kernel_image:
652*800a58d9SAndroid Build Coastguard Worker            launch_cvd_w_args = (launch_cvd_w_args +
653*800a58d9SAndroid Build Coastguard Worker                                 _CMD_LAUNCH_CVD_KERNEL_IMAGE_ARG %
654*800a58d9SAndroid Build Coastguard Worker                                 artifact_paths.kernel_image)
655*800a58d9SAndroid Build Coastguard Worker
656*800a58d9SAndroid Build Coastguard Worker        if artifact_paths.initramfs_image:
657*800a58d9SAndroid Build Coastguard Worker            launch_cvd_w_args = (launch_cvd_w_args +
658*800a58d9SAndroid Build Coastguard Worker                                 _CMD_LAUNCH_CVD_INITRAMFS_IMAGE_ARG %
659*800a58d9SAndroid Build Coastguard Worker                                 artifact_paths.initramfs_image)
660*800a58d9SAndroid Build Coastguard Worker
661*800a58d9SAndroid Build Coastguard Worker        if vbmeta_image_path:
662*800a58d9SAndroid Build Coastguard Worker            launch_cvd_w_args = (launch_cvd_w_args +
663*800a58d9SAndroid Build Coastguard Worker                                 _CMD_LAUNCH_CVD_VBMETA_IMAGE_ARG %
664*800a58d9SAndroid Build Coastguard Worker                                 vbmeta_image_path)
665*800a58d9SAndroid Build Coastguard Worker
666*800a58d9SAndroid Build Coastguard Worker        if openwrt:
667*800a58d9SAndroid Build Coastguard Worker            launch_cvd_w_args = launch_cvd_w_args + _CMD_LAUNCH_CVD_CONSOLE_ARG
668*800a58d9SAndroid Build Coastguard Worker
669*800a58d9SAndroid Build Coastguard Worker        if instance_ids and len(instance_ids) > 1:
670*800a58d9SAndroid Build Coastguard Worker            launch_cvd_w_args = (
671*800a58d9SAndroid Build Coastguard Worker                launch_cvd_w_args +
672*800a58d9SAndroid Build Coastguard Worker                _CMD_LAUNCH_CVD_INSTANCE_NUMS_ARG %
673*800a58d9SAndroid Build Coastguard Worker                ",".join(map(str, instance_ids)))
674*800a58d9SAndroid Build Coastguard Worker
675*800a58d9SAndroid Build Coastguard Worker        if webrtc_device_id:
676*800a58d9SAndroid Build Coastguard Worker            launch_cvd_w_args = (launch_cvd_w_args +
677*800a58d9SAndroid Build Coastguard Worker                                 _CMD_LAUNCH_CVD_WEBRTC_DEIVE_ID %
678*800a58d9SAndroid Build Coastguard Worker                                 webrtc_device_id)
679*800a58d9SAndroid Build Coastguard Worker
680*800a58d9SAndroid Build Coastguard Worker        if launch_args:
681*800a58d9SAndroid Build Coastguard Worker            launch_cvd_w_args = launch_cvd_w_args + " " + launch_args
682*800a58d9SAndroid Build Coastguard Worker
683*800a58d9SAndroid Build Coastguard Worker        launch_cmd = utils.AddUserGroupsToCmd(launch_cvd_w_args,
684*800a58d9SAndroid Build Coastguard Worker                                              constants.LIST_CF_USER_GROUPS)
685*800a58d9SAndroid Build Coastguard Worker        logger.debug("launch_cvd cmd:\n %s", launch_cmd)
686*800a58d9SAndroid Build Coastguard Worker        return launch_cmd
687*800a58d9SAndroid Build Coastguard Worker
688*800a58d9SAndroid Build Coastguard Worker    @staticmethod
689*800a58d9SAndroid Build Coastguard Worker    def PrepareLocalCvdToolsLink(cvd_home_dir, host_bins_path):
690*800a58d9SAndroid Build Coastguard Worker        """Create symbolic link for the cvd tools directory.
691*800a58d9SAndroid Build Coastguard Worker
692*800a58d9SAndroid Build Coastguard Worker        local instance's cvd tools could be generated in /out after local build
693*800a58d9SAndroid Build Coastguard Worker        or be generated in the download image folder. It creates a symbolic
694*800a58d9SAndroid Build Coastguard Worker        link then only check cvd_status using known link for both cases.
695*800a58d9SAndroid Build Coastguard Worker
696*800a58d9SAndroid Build Coastguard Worker        Args:
697*800a58d9SAndroid Build Coastguard Worker            cvd_home_dir: The parent directory of the link
698*800a58d9SAndroid Build Coastguard Worker            host_bins_path: String of host package directory.
699*800a58d9SAndroid Build Coastguard Worker
700*800a58d9SAndroid Build Coastguard Worker        Returns:
701*800a58d9SAndroid Build Coastguard Worker            String of cvd_tools link path
702*800a58d9SAndroid Build Coastguard Worker        """
703*800a58d9SAndroid Build Coastguard Worker        cvd_tools_link_path = os.path.join(cvd_home_dir,
704*800a58d9SAndroid Build Coastguard Worker                                           constants.CVD_TOOLS_LINK_NAME)
705*800a58d9SAndroid Build Coastguard Worker        if os.path.islink(cvd_tools_link_path):
706*800a58d9SAndroid Build Coastguard Worker            os.unlink(cvd_tools_link_path)
707*800a58d9SAndroid Build Coastguard Worker        os.symlink(host_bins_path, cvd_tools_link_path)
708*800a58d9SAndroid Build Coastguard Worker        return cvd_tools_link_path
709*800a58d9SAndroid Build Coastguard Worker
710*800a58d9SAndroid Build Coastguard Worker    @staticmethod
711*800a58d9SAndroid Build Coastguard Worker    def _TrustCertificatesForWebRTC(host_bins_path):
712*800a58d9SAndroid Build Coastguard Worker        """Copy the trusted certificates generated by openssl tool to the
713*800a58d9SAndroid Build Coastguard Worker        webrtc frontend certificate directory.
714*800a58d9SAndroid Build Coastguard Worker
715*800a58d9SAndroid Build Coastguard Worker        Args:
716*800a58d9SAndroid Build Coastguard Worker            host_bins_path: String of host package directory.
717*800a58d9SAndroid Build Coastguard Worker        """
718*800a58d9SAndroid Build Coastguard Worker        webrtc_certs_dir = os.path.join(host_bins_path,
719*800a58d9SAndroid Build Coastguard Worker                                        constants.WEBRTC_CERTS_PATH)
720*800a58d9SAndroid Build Coastguard Worker        if not os.path.isdir(webrtc_certs_dir):
721*800a58d9SAndroid Build Coastguard Worker            logger.debug("WebRTC frontend certificate path doesn't exist: %s",
722*800a58d9SAndroid Build Coastguard Worker                         webrtc_certs_dir)
723*800a58d9SAndroid Build Coastguard Worker            return
724*800a58d9SAndroid Build Coastguard Worker        local_cert_dir = os.path.join(os.path.expanduser("~"),
725*800a58d9SAndroid Build Coastguard Worker                                      constants.SSL_DIR)
726*800a58d9SAndroid Build Coastguard Worker        if mkcert.AllocateLocalHostCert():
727*800a58d9SAndroid Build Coastguard Worker            for cert_file_name in constants.WEBRTC_CERTS_FILES:
728*800a58d9SAndroid Build Coastguard Worker                shutil.copyfile(
729*800a58d9SAndroid Build Coastguard Worker                    os.path.join(local_cert_dir, cert_file_name),
730*800a58d9SAndroid Build Coastguard Worker                    os.path.join(webrtc_certs_dir, cert_file_name))
731*800a58d9SAndroid Build Coastguard Worker
732*800a58d9SAndroid Build Coastguard Worker    @staticmethod
733*800a58d9SAndroid Build Coastguard Worker    def _LogCvdVersion(host_bins_path):
734*800a58d9SAndroid Build Coastguard Worker        """Log the version of the cvd server.
735*800a58d9SAndroid Build Coastguard Worker
736*800a58d9SAndroid Build Coastguard Worker        Args:
737*800a58d9SAndroid Build Coastguard Worker            host_bins_path: String of host package directory.
738*800a58d9SAndroid Build Coastguard Worker        """
739*800a58d9SAndroid Build Coastguard Worker        cvd_path = os.path.join(host_bins_path, "bin", constants.CMD_CVD)
740*800a58d9SAndroid Build Coastguard Worker        if not os.path.isfile(cvd_path):
741*800a58d9SAndroid Build Coastguard Worker            logger.info("Skip logging cvd version as %s is not a file",
742*800a58d9SAndroid Build Coastguard Worker                        cvd_path)
743*800a58d9SAndroid Build Coastguard Worker            return
744*800a58d9SAndroid Build Coastguard Worker
745*800a58d9SAndroid Build Coastguard Worker        cmd = cvd_path + _CMD_CVD_VERSION
746*800a58d9SAndroid Build Coastguard Worker        try:
747*800a58d9SAndroid Build Coastguard Worker            proc = subprocess.run(cmd, shell=True, text=True,
748*800a58d9SAndroid Build Coastguard Worker                                  capture_output=True, timeout=5,
749*800a58d9SAndroid Build Coastguard Worker                                  check=False, cwd=host_bins_path)
750*800a58d9SAndroid Build Coastguard Worker            logger.info("`%s` returned %d; stdout:\n%s",
751*800a58d9SAndroid Build Coastguard Worker                        cmd, proc.returncode, proc.stdout)
752*800a58d9SAndroid Build Coastguard Worker            logger.info("`%s` stderr:\n%s", cmd, proc.stderr)
753*800a58d9SAndroid Build Coastguard Worker        except subprocess.SubprocessError as e:
754*800a58d9SAndroid Build Coastguard Worker            logger.error("`%s` failed: %s", cmd, e)
755*800a58d9SAndroid Build Coastguard Worker
756*800a58d9SAndroid Build Coastguard Worker    @staticmethod
757*800a58d9SAndroid Build Coastguard Worker    def _CheckRunningCvd(local_instance_id, no_prompts=False):
758*800a58d9SAndroid Build Coastguard Worker        """Check if launch_cvd with the same instance id is running.
759*800a58d9SAndroid Build Coastguard Worker
760*800a58d9SAndroid Build Coastguard Worker        Args:
761*800a58d9SAndroid Build Coastguard Worker            local_instance_id: Integer of instance id.
762*800a58d9SAndroid Build Coastguard Worker            no_prompts: Boolean, True to skip all prompts.
763*800a58d9SAndroid Build Coastguard Worker
764*800a58d9SAndroid Build Coastguard Worker        Returns:
765*800a58d9SAndroid Build Coastguard Worker            Whether the user wants to continue.
766*800a58d9SAndroid Build Coastguard Worker        """
767*800a58d9SAndroid Build Coastguard Worker        # Check if the instance with same id is running.
768*800a58d9SAndroid Build Coastguard Worker        existing_ins = list_instance.GetActiveCVD(local_instance_id)
769*800a58d9SAndroid Build Coastguard Worker        if existing_ins:
770*800a58d9SAndroid Build Coastguard Worker            if no_prompts or utils.GetUserAnswerYes(_CONFIRM_RELAUNCH %
771*800a58d9SAndroid Build Coastguard Worker                                                    local_instance_id):
772*800a58d9SAndroid Build Coastguard Worker                existing_ins.Delete()
773*800a58d9SAndroid Build Coastguard Worker            else:
774*800a58d9SAndroid Build Coastguard Worker                return False
775*800a58d9SAndroid Build Coastguard Worker        return True
776*800a58d9SAndroid Build Coastguard Worker
777*800a58d9SAndroid Build Coastguard Worker    @staticmethod
778*800a58d9SAndroid Build Coastguard Worker    def _StopCvd(local_instance_id, proc):
779*800a58d9SAndroid Build Coastguard Worker        """Call stop_cvd or kill a launch_cvd process.
780*800a58d9SAndroid Build Coastguard Worker
781*800a58d9SAndroid Build Coastguard Worker        Args:
782*800a58d9SAndroid Build Coastguard Worker            local_instance_id: Integer of instance id.
783*800a58d9SAndroid Build Coastguard Worker            proc: subprocess.Popen object, the launch_cvd process.
784*800a58d9SAndroid Build Coastguard Worker        """
785*800a58d9SAndroid Build Coastguard Worker        existing_ins = list_instance.GetActiveCVD(local_instance_id)
786*800a58d9SAndroid Build Coastguard Worker        if existing_ins:
787*800a58d9SAndroid Build Coastguard Worker            try:
788*800a58d9SAndroid Build Coastguard Worker                existing_ins.Delete()
789*800a58d9SAndroid Build Coastguard Worker                return
790*800a58d9SAndroid Build Coastguard Worker            except subprocess.CalledProcessError as e:
791*800a58d9SAndroid Build Coastguard Worker                logger.error("Cannot stop instance %d: %s",
792*800a58d9SAndroid Build Coastguard Worker                             local_instance_id, str(e))
793*800a58d9SAndroid Build Coastguard Worker        else:
794*800a58d9SAndroid Build Coastguard Worker            logger.error("Instance %d is not active.", local_instance_id)
795*800a58d9SAndroid Build Coastguard Worker        logger.info("Terminate launch_cvd process.")
796*800a58d9SAndroid Build Coastguard Worker        proc.terminate()
797*800a58d9SAndroid Build Coastguard Worker
798*800a58d9SAndroid Build Coastguard Worker    @utils.TimeExecute(function_description="Waiting for AVD(s) to boot up")
799*800a58d9SAndroid Build Coastguard Worker    def _LaunchCvd(self, cmd, local_instance_id, host_bins_path,
800*800a58d9SAndroid Build Coastguard Worker                   host_artifacts_path, cvd_home_dir, timeout):
801*800a58d9SAndroid Build Coastguard Worker        """Execute Launch CVD.
802*800a58d9SAndroid Build Coastguard Worker
803*800a58d9SAndroid Build Coastguard Worker        Kick off the launch_cvd command and log the output.
804*800a58d9SAndroid Build Coastguard Worker
805*800a58d9SAndroid Build Coastguard Worker        Args:
806*800a58d9SAndroid Build Coastguard Worker            cmd: String, launch_cvd command.
807*800a58d9SAndroid Build Coastguard Worker            local_instance_id: Integer of instance id.
808*800a58d9SAndroid Build Coastguard Worker            host_bins_path: String of host package directory containing
809*800a58d9SAndroid Build Coastguard Worker              binaries.
810*800a58d9SAndroid Build Coastguard Worker            host_artifacts_path: String of host package directory containing
811*800a58d9SAndroid Build Coastguard Worker              other artifacts.
812*800a58d9SAndroid Build Coastguard Worker            cvd_home_dir: String, the home directory for the instance.
813*800a58d9SAndroid Build Coastguard Worker            timeout: Integer, the number of seconds to wait for the AVD to
814*800a58d9SAndroid Build Coastguard Worker              boot up.
815*800a58d9SAndroid Build Coastguard Worker
816*800a58d9SAndroid Build Coastguard Worker        Raises:
817*800a58d9SAndroid Build Coastguard Worker            errors.LaunchCVDFail if launch_cvd times out or returns non-zero.
818*800a58d9SAndroid Build Coastguard Worker        """
819*800a58d9SAndroid Build Coastguard Worker        cvd_env = os.environ.copy()
820*800a58d9SAndroid Build Coastguard Worker        cvd_env[constants.ENV_ANDROID_SOONG_HOST_OUT] = host_artifacts_path
821*800a58d9SAndroid Build Coastguard Worker        # launch_cvd assumes host bins are in $ANDROID_HOST_OUT.
822*800a58d9SAndroid Build Coastguard Worker        cvd_env[constants.ENV_ANDROID_HOST_OUT] = host_bins_path
823*800a58d9SAndroid Build Coastguard Worker        cvd_env[constants.ENV_CVD_HOME] = cvd_home_dir
824*800a58d9SAndroid Build Coastguard Worker        cvd_env[constants.ENV_CUTTLEFISH_INSTANCE] = str(local_instance_id)
825*800a58d9SAndroid Build Coastguard Worker        cvd_env[constants.ENV_CUTTLEFISH_CONFIG_FILE] = (
826*800a58d9SAndroid Build Coastguard Worker            instance.GetLocalInstanceConfigPath(local_instance_id))
827*800a58d9SAndroid Build Coastguard Worker        cvd_env[constants.ENV_CVD_ACQUIRE_FILE_LOCK] = "false"
828*800a58d9SAndroid Build Coastguard Worker        cvd_env[constants.ENV_LAUNCHED_BY_ACLOUD] = "true"
829*800a58d9SAndroid Build Coastguard Worker        stdout_file = os.path.join(cvd_home_dir, _STDOUT)
830*800a58d9SAndroid Build Coastguard Worker        stderr_file = os.path.join(cvd_home_dir, _STDERR)
831*800a58d9SAndroid Build Coastguard Worker        # Check the result of launch_cvd command.
832*800a58d9SAndroid Build Coastguard Worker        # An exit code of 0 is equivalent to VIRTUAL_DEVICE_BOOT_COMPLETED
833*800a58d9SAndroid Build Coastguard Worker        with open(stdout_file, "w+") as f_stdout, open(stderr_file,
834*800a58d9SAndroid Build Coastguard Worker                                                       "w+") as f_stderr:
835*800a58d9SAndroid Build Coastguard Worker            try:
836*800a58d9SAndroid Build Coastguard Worker                proc = subprocess.Popen(
837*800a58d9SAndroid Build Coastguard Worker                    cmd, shell=True, env=cvd_env, stdout=f_stdout,
838*800a58d9SAndroid Build Coastguard Worker                    stderr=f_stderr, text=True, cwd=host_bins_path)
839*800a58d9SAndroid Build Coastguard Worker                proc.communicate(timeout=timeout)
840*800a58d9SAndroid Build Coastguard Worker                f_stdout.seek(0)
841*800a58d9SAndroid Build Coastguard Worker                f_stderr.seek(0)
842*800a58d9SAndroid Build Coastguard Worker                if proc.returncode == 0:
843*800a58d9SAndroid Build Coastguard Worker                    logger.info("launch_cvd stdout:\n%s", f_stdout.read())
844*800a58d9SAndroid Build Coastguard Worker                    logger.info("launch_cvd stderr:\n%s", f_stderr.read())
845*800a58d9SAndroid Build Coastguard Worker                    return
846*800a58d9SAndroid Build Coastguard Worker                error_msg = "launch_cvd returned %d." % proc.returncode
847*800a58d9SAndroid Build Coastguard Worker            except subprocess.TimeoutExpired:
848*800a58d9SAndroid Build Coastguard Worker                self._StopCvd(local_instance_id, proc)
849*800a58d9SAndroid Build Coastguard Worker                proc.communicate(timeout=5)
850*800a58d9SAndroid Build Coastguard Worker                error_msg = "Device did not boot within %d secs." % timeout
851*800a58d9SAndroid Build Coastguard Worker
852*800a58d9SAndroid Build Coastguard Worker            f_stdout.seek(0)
853*800a58d9SAndroid Build Coastguard Worker            f_stderr.seek(0)
854*800a58d9SAndroid Build Coastguard Worker            stderr = f_stderr.read()
855*800a58d9SAndroid Build Coastguard Worker            logger.error("launch_cvd stdout:\n%s", f_stdout.read())
856*800a58d9SAndroid Build Coastguard Worker            logger.error("launch_cvd stderr:\n%s", stderr)
857*800a58d9SAndroid Build Coastguard Worker            split_stderr = stderr.splitlines()[-_MAX_REPORTED_ERROR_LINES:]
858*800a58d9SAndroid Build Coastguard Worker            raise errors.LaunchCVDFail(
859*800a58d9SAndroid Build Coastguard Worker                "%s Stderr:\n%s" % (error_msg, "\n".join(split_stderr)))
860