tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

ffx_emulator.py (4107B)


      1 # Copyright 2023 The Chromium Authors
      2 # Use of this source code is governed by a BSD-style license that can be
      3 # found in the LICENSE file.
      4 """Provide helpers for running Fuchsia's `ffx emu`."""
      5 
      6 import argparse
      7 import logging
      8 import os
      9 import random
     10 
     11 from contextlib import AbstractContextManager
     12 
     13 import monitors
     14 
     15 from common import run_ffx_command, IMAGES_ROOT, INTERNAL_IMAGES_ROOT, \
     16                   DIR_SRC_ROOT
     17 from compatible_utils import get_host_arch
     18 
     19 
     20 class FfxEmulator(AbstractContextManager):
     21    """A helper for managing emulators."""
     22    # pylint: disable=too-many-branches
     23    def __init__(self, args: argparse.Namespace) -> None:
     24        if args.product:
     25            self._product = args.product
     26        else:
     27            if get_host_arch() == 'x64':
     28                self._product = 'terminal.x64'
     29            else:
     30                self._product = 'terminal.qemu-arm64'
     31 
     32        self._enable_graphics = args.enable_graphics
     33        self._logs_dir = args.logs_dir
     34        self._with_network = args.with_network
     35        if args.everlasting:
     36            # Do not change the name, it will break the logic.
     37            # ffx has a prefix-matching logic, so 'fuchsia-emulator' is not
     38            # usable to avoid breaking local development workflow. I.e.
     39            # developers can create an everlasting emulator and an ephemeral one
     40            # without interfering each other.
     41            self._node_name = 'fuchsia-everlasting-emulator'
     42            assert self._everlasting()
     43        else:
     44            self._node_name = 'fuchsia-emulator-' + str(random.randint(
     45                1, 9999))
     46        self._device_spec = args.device_spec
     47 
     48    def _everlasting(self) -> bool:
     49        return self._node_name == 'fuchsia-everlasting-emulator'
     50 
     51    def __enter__(self) -> str:
     52        """Start the emulator.
     53 
     54        Returns:
     55            The node name of the emulator.
     56        """
     57        logging.info('Starting emulator %s', self._node_name)
     58        prod, board = self._product.split('.', 1)
     59        image_dir = os.path.join(IMAGES_ROOT, prod, board)
     60        if not os.path.isdir(image_dir):
     61            image_dir = os.path.join(INTERNAL_IMAGES_ROOT, prod, board)
     62        emu_command = ['emu', 'start', image_dir, '--name', self._node_name]
     63        configs = ['emu.start.timeout=300']
     64        if not self._enable_graphics:
     65            emu_command.append('-H')
     66        if self._logs_dir:
     67            emu_command.extend(
     68                ('-l', os.path.join(self._logs_dir, 'emulator_log')))
     69        if self._with_network:
     70            emu_command.extend(['--net', 'tap'])
     71        else:
     72            emu_command.extend(['--net', 'user'])
     73        if self._everlasting():
     74            emu_command.extend(['--reuse-with-check'])
     75        if self._device_spec:
     76            emu_command.extend(['--device', self._device_spec])
     77 
     78        # fuchsia-sdk does not carry arm64 qemu binaries, so use overrides to
     79        # allow it using the qemu-arm64 being downloaded separately.
     80        if get_host_arch() == 'arm64':
     81            configs.append(
     82                'sdk.overrides.qemu_internal=' +
     83                os.path.join(DIR_SRC_ROOT, 'third_party', 'qemu-linux-arm64',
     84                             'bin', 'qemu-system-aarch64'))
     85 
     86        # Always use qemu for arm64 images, no matter it runs on arm64 hosts or
     87        # x64 hosts with simulation.
     88        if self._product.endswith('arm64'):
     89            emu_command.extend(['--engine', 'qemu'])
     90 
     91        with monitors.time_consumption('emulator', 'startup_time'):
     92            run_ffx_command(cmd=emu_command, timeout=310, configs=configs)
     93 
     94        return self._node_name
     95 
     96    def __exit__(self, exc_type, exc_value, traceback) -> bool:
     97        """Shutdown the emulator."""
     98 
     99        logging.info('Stopping the emulator %s', self._node_name)
    100        cmd = ['emu', 'stop', self._node_name]
    101        if self._everlasting():
    102            cmd.extend(['--persist'])
    103        # The emulator might have shut down unexpectedly, so this command
    104        # might fail.
    105        run_ffx_command(cmd=cmd, check=False)
    106        # Do not suppress exceptions.
    107        return False