def _CreateTraceConfigFile(self, config):
     assert not self._trace_config_file
     if self._platform_backend.GetOSName() == 'android':
         self._trace_config_file = os.path.join(
             _CHROME_TRACE_CONFIG_DIR_ANDROID,
             _CHROME_TRACE_CONFIG_FILE_NAME)
         self._platform_backend.device.WriteFile(
             self._trace_config_file,
             self._CreateTraceConfigFileString(config),
             as_root=True)
         # The config file has fixed path on Android. We need to ensure it is
         # always cleaned up.
         atexit_with_log.Register(self._RemoveTraceConfigFile)
     elif self._platform_backend.GetOSName() == 'chromeos':
         self._trace_config_file = os.path.join(
             _CHROME_TRACE_CONFIG_DIR_CROS, _CHROME_TRACE_CONFIG_FILE_NAME)
         cri = self._platform_backend.cri
         cri.PushContents(self._CreateTraceConfigFileString(config),
                          self._trace_config_file)
         cri.Chown(self._trace_config_file)
         # The config file has fixed path on CrOS. We need to ensure it is
         # always cleaned up.
         atexit_with_log.Register(self._RemoveTraceConfigFile)
     elif self._platform_backend.GetOSName() in _DESKTOP_OS_NAMES:
         self._trace_config_file = os.path.join(
             tempfile.mkdtemp(), _CHROME_TRACE_CONFIG_FILE_NAME)
         with open(self._trace_config_file, 'w') as f:
             trace_config_string = self._CreateTraceConfigFileString(config)
             logging.info('Trace config file string: %s',
                          trace_config_string)
             f.write(trace_config_string)
         os.chmod(self._trace_config_file,
                  os.stat(self._trace_config_file).st_mode | stat.S_IROTH)
     else:
         raise NotImplementedError
示例#2
0
    def StartServer(self):
        """Start Web Page Replay and verify that it started.

    Returns:
      A dictionary mapping the keys 'http', 'https', and (if used) 'dns'
      to the respective ports of the replay server.
    Raises:
      ReplayNotStartedError: if Replay start-up fails.
    """
        is_posix = sys.platform.startswith('linux') or sys.platform == 'darwin'
        logging.info('Starting Web-Page-Replay: %s', self._cmd_line)
        self._CreateTempLogFilePath()
        with open(self._temp_log_file_path, 'w') as log_fh:
            self.replay_process = subprocess.Popen(
                self._cmd_line,
                stdout=log_fh,
                stderr=subprocess.STDOUT,
                preexec_fn=(_ResetInterruptHandler if is_posix else None))
        try:
            py_utils.WaitFor(self._IsStarted, 30)
            logging.info('WPR ports: %s' % self._started_ports)
            atexit_with_log.Register(self.StopServer)
            return dict(self._started_ports)
        except Exception:
            self.StopServer()
            raise ReplayNotStartedError(
                'Web Page Replay failed to start. Log output:\n%s' %
                ''.join(self._LogLines()))
示例#3
0
  def _StartMsrServerIfNeeded(self):
    if self._msr_server_handle:
      return

    _InstallWinRing0()

    pipe_name = r"\\.\pipe\msr_server_pipe_{}".format(os.getpid())
    # Try to open a named pipe to receive a msr port number from server process.
    pipe = win32pipe.CreateNamedPipe(
        pipe_name,
        win32pipe.PIPE_ACCESS_INBOUND,
        win32pipe.PIPE_TYPE_MESSAGE | win32pipe.PIPE_WAIT,
        1, 32, 32, 300, None)
    parameters = (
        os.path.join(os.path.dirname(__file__), 'msr_server_win.py'),
        pipe_name,
    )
    self._msr_server_handle = self.LaunchApplication(
        sys.executable, parameters, elevate_privilege=True)
    if pipe != win32file.INVALID_HANDLE_VALUE:
      if win32pipe.ConnectNamedPipe(pipe, None) == 0:
        self._msr_server_port = int(win32file.ReadFile(pipe, 32)[1])
      win32api.CloseHandle(pipe)
    # Wait for server to start.
    try:
      socket.create_connection(('127.0.0.1', self._msr_server_port), 5).close()
    except socket.error:
      self.CloseMsrServer()
    atexit_with_log.Register(TerminateProcess, self._msr_server_handle)
示例#4
0
    def StartServer(self):
        """Start Web Page Replay and verify that it started.

    Returns:
      A forwarders.PortSet(http, https, dns) tuple; with dns None if unused.
    Raises:
      ReplayNotStartedError: if Replay start-up fails.
    """
        is_posix = sys.platform.startswith('linux') or sys.platform == 'darwin'
        logging.info('Starting Web-Page-Replay: %s', self._cmd_line)
        self._CreateTempLogFilePath()
        with open(self._temp_log_file_path, 'w') as log_fh:
            self.replay_process = subprocess.Popen(
                self._cmd_line,
                stdout=log_fh,
                stderr=subprocess.STDOUT,
                preexec_fn=(_ResetInterruptHandler if is_posix else None))
        try:
            py_utils.WaitFor(self._IsStarted, 30)
            logging.info('WPR ports: %s' % self._started_ports)
            atexit_with_log.Register(self.StopServer)
            return forwarders.PortSet(
                self._started_ports['http'],
                self._started_ports['https'],
                self._started_ports.get('dns'),  # None if unused
            )
        except py_utils.TimeoutException:
            raise ReplayNotStartedError(
                'Web Page Replay failed to start. Log output:\n%s' %
                ''.join(self._LogLines()))
示例#5
0
 def StartServer(self, timeout=10):
     """Start TsProxy server and verify that it started.
 """
     cmd_line = [sys.executable, _TSPROXY_PATH]
     cmd_line.extend([
         '--port=0'
     ])  # Use port 0 so tsproxy picks a random available port.
     if self._host_ip:
         cmd_line.append('--desthost=%s' % self._host_ip)
     if self._http_port:
         cmd_line.append('--mapports=443:%s,*:%s' %
                         (self._https_port, self._http_port))
     logging.info('Tsproxy commandline: %r' % cmd_line)
     self._proc = subprocess.Popen(cmd_line,
                                   stdout=subprocess.PIPE,
                                   stdin=subprocess.PIPE,
                                   stderr=subprocess.PIPE,
                                   bufsize=1)
     atexit_with_log.Register(self.StopServer)
     try:
         py_utils.WaitFor(self._IsStarted, timeout)
         logging.info('TsProxy port: %s', self._port)
         self._is_running = True
     except py_utils.TimeoutException:
         err = self.StopServer()
         raise RuntimeError('Error starting tsproxy: %s' % err)
示例#6
0
  def StartServer(self, timeout=10, retries=None):
    """Start TsProxy server and verify that it started."""
    del retries # Handled by decorator.
    cmd_line = [sys.executable, _TSPROXY_PATH]
    # Use port 0 so tsproxy picks a random available port.
    cmd_line.extend(['--port=0'])
    if self._host_ip:
      cmd_line.append('--desthost=%s' % self._host_ip)
    if self._http_port:
      cmd_line.append(
          '--mapports=443:%s,*:%s' % (self._https_port, self._http_port))
      logging.info('Tsproxy commandline: %s', cmd_line)
    self._proc = subprocess.Popen(
        cmd_line, stdout=subprocess.PIPE, stdin=subprocess.PIPE,
        stderr=subprocess.PIPE, bufsize=1)
    self._non_blocking = False
    if fcntl:
      logging.info('fcntl is supported, trying to set '
                   'non blocking I/O for the ts_proxy process')
      fd = self._proc.stdout.fileno()
      fl = fcntl.fcntl(fd, fcntl.F_GETFL)
      fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK)
      self._non_blocking = True

    atexit_with_log.Register(self.StopServer)
    try:
      py_utils.WaitFor(self._IsStarted, timeout)
      logging.info('TsProxy port: %s', self._port)
      self._is_running = True
    except py_utils.TimeoutException:
      err = self.StopServer()
      if err:
        logging.error('Error stopping WPR server:\n%s', err)
      raise TsProxyServerError(
          'Error starting tsproxy: timed out after %s seconds' % timeout)
    def StartAgentTracing(self, config, timeout):
        """Start tracing on the BattOr.

    Args:
      config: A TracingConfig instance.
      timeout: number of seconds that this tracing agent should try to start
        tracing until timing out.

    Returns:
      True if the tracing agent started successfully.
    """
        if not config.enable_battor_trace:
            return False
        try:
            if self._battery:
                self._battery.SetCharging(False)
                atexit_with_log.Register(_ReenableChargingIfNeeded,
                                         self._battery)

            self._battor.StartShell()
            self._battor.StartTracing()
            return True
        except battor_error.BattOrError:
            if self._battery:
                self._battery.SetCharging(True)
            raise
    def StartServer(self):
        """Start Web Page Replay and verify that it started.

    Returns:
      A dictionary mapping the keys 'http', 'https', and (if used) 'dns'
      to the respective ports of the replay server.
    Raises:
      ReplayNotStartedError: if Replay start-up fails.
    """
        is_posix = sys.platform.startswith('linux') or sys.platform == 'darwin'
        logging.info('Starting Web-Page-Replay: %s', self._cmd_line)
        self._CreateTempLogFilePath()
        with open(self._temp_log_file_path, 'w') as log_fh:
            self.replay_process = subprocess.Popen(
                self._cmd_line,
                stdout=log_fh,
                stderr=subprocess.STDOUT,
                preexec_fn=(_ResetInterruptHandler if is_posix else None))
        try:
            # TODO(crbug.com/805418): consider changing this to wait with I/O timeout.
            # The 120s timeout is based on past failures (e.g: crbug.com/812639).
            py_utils.WaitFor(self._IsStarted, timeout=120)
            logging.info('WPR ports: %s' % self._started_ports)
            atexit_with_log.Register(self.StopServer)
            return dict(self._started_ports)
        except Exception:
            log_output = self.StopServer()
            raise ReplayNotStartedError(
                'Web Page Replay failed to start. Log output:\n%s' %
                log_output)
示例#9
0
 def __init__(self, device, local_port, remote_port):
     super(AndroidForwarder, self).__init__()
     self._device = device
     assert local_port, 'Local port must be given'
     forwarder.Forwarder.Map([(remote_port, local_port)], self._device)
     remote_port = forwarder.Forwarder.DevicePortForHostPort(local_port)
     self._StartedForwarding(local_port, remote_port)
     atexit_with_log.Register(self.Close)
示例#10
0
 def __init__(self, device, port_pair):
     super(AndroidForwarder, self).__init__(port_pair)
     self._device = device
     forwarder.Forwarder.Map(
         [(port_pair.remote_port, port_pair.local_port)], self._device)
     self._port_pair = (forwarders.PortPair(
         port_pair.local_port,
         forwarder.Forwarder.DevicePortForHostPort(port_pair.local_port)))
     atexit_with_log.Register(self.Close)
示例#11
0
    def __init__(self,
                 target_platform,
                 android_device=None,
                 battor_path=None,
                 battor_map_file=None,
                 battor_map=None,
                 serial_log_bucket=None,
                 autoflash=True):
        """Constructor.

    Args:
      target_platform: Platform BattOr is attached to.
      android_device: Serial number of Android device.
      battor_path: Path to BattOr device.
      battor_map_file: File giving map of [device serial: BattOr path]
      battor_map: Map of [device serial: BattOr path]
      serial_log_bucket: The cloud storage bucket to which BattOr agent serial
        logs are uploaded on failure.

    Attributes:
      _battor_path: Path to BattOr. Typically similar to /tty/USB0.
      _battor_agent_binary: Path to the BattOr agent binary used to communicate
        with the BattOr.
      _tracing: A bool saying if tracing has been started.
      _battor_shell: A subprocess running the battor_agent_binary
      _trace_results_path: Path to BattOr trace results file.
      _serial_log_bucket: Cloud storage bucket to which BattOr agent serial logs
        are uploaded on failure.
      _serial_log_file: Temp file for the BattOr agent serial log.
    """
        self._battor_path = self._GetBattOrPath(target_platform,
                                                android_device, battor_path,
                                                battor_map_file, battor_map)
        config = os.path.join(os.path.dirname(os.path.abspath(__file__)),
                              'battor_binary_dependencies.json')

        self._dm = dependency_manager.DependencyManager(
            [dependency_manager.BaseConfig(config)])
        self._battor_agent_binary = self._dm.FetchPath(
            'battor_agent_binary',
            '%s_%s' % (sys.platform, platform.machine()))

        self._autoflash = autoflash
        self._serial_log_bucket = serial_log_bucket
        self._tracing = False
        self._battor_shell = None
        self._trace_results_path = None
        self._start_tracing_time = None
        self._stop_tracing_time = None
        self._trace_results = None
        self._serial_log_file = None
        self._target_platform = target_platform
        self._git_hash = None

        atexit_with_log.Register(self.KillBattOrShell)
示例#12
0
 def _CreateTraceConfigFile(self, config):
     assert not self._trace_config_file
     os_name = self._platform_backend.GetOSName()
     if os_name == 'android':
         self._trace_config_file = os.path.join(
             _CHROME_TRACE_CONFIG_DIR_ANDROID,
             _CHROME_TRACE_CONFIG_FILE_NAME)
         self._platform_backend.device.WriteFile(
             self._trace_config_file,
             self._CreateTraceConfigFileString(config),
             as_root=True)
         # The config file has fixed path on Android. We need to ensure it is
         # always cleaned up.
         atexit_with_log.Register(self._RemoveTraceConfigFile)
     elif os_name == 'chromeos':
         self._trace_config_file = os.path.join(
             _CHROME_TRACE_CONFIG_DIR_CROS, _CHROME_TRACE_CONFIG_FILE_NAME)
         cri = self._platform_backend.cri
         # Before push the config file to DUT, first make sure the DUT is not
         # write-protected, and remount the root here to avoid losing the config
         # file.
         cri.MakeRootReadWriteIfNecessary()
         cri.PushContents(self._CreateTraceConfigFileString(config),
                          self._trace_config_file)
         cri.Chown(self._trace_config_file)
         # The config file has fixed path on CrOS. We need to ensure it is
         # always cleaned up.
         atexit_with_log.Register(self._RemoveTraceConfigFile)
     elif os_name in _DESKTOP_OS_NAMES:
         self._trace_config_file = os.path.join(
             tempfile.mkdtemp(), _CHROME_TRACE_CONFIG_FILE_NAME)
         with open(self._trace_config_file, 'w') as f:
             trace_config_string = self._CreateTraceConfigFileString(config)
             logging.info('Trace config file string: %s',
                          trace_config_string)
             f.write(trace_config_string)
         os.chmod(self._trace_config_file,
                  os.stat(self._trace_config_file).st_mode | stat.S_IROTH)
     else:
         raise NotImplementedError('Tracing not supported on: %s' % os_name)
示例#13
0
    def CollectAgentTraceData(self, trace_data_builder):
        if not self._is_tracing_controllable:
            return
        assert not trace_event.trace_is_enabled(
        ), 'Stop tracing before collection.'
        with open(self._trace_log, 'r') as fp:
            data = ast.literal_eval(fp.read() + ']')
        trace_data_builder.AddTraceFor(
            trace_data_module.TELEMETRY_PART,
            {
                "traceEvents": data,
                "metadata": {
                    # TODO(charliea): For right now, we use "TELEMETRY" as the clock
                    # domain to guarantee that Telemetry is given its own clock
                    # domain. Telemetry isn't really a clock domain, though: it's a
                    # system that USES a clock domain like LINUX_CLOCK_MONOTONIC or
                    # WIN_QPC. However, there's a chance that a Telemetry controller
                    # running on Linux (using LINUX_CLOCK_MONOTONIC) is interacting
                    # with an Android phone (also using LINUX_CLOCK_MONOTONIC, but
                    # on a different machine). The current logic collapses clock
                    # domains based solely on the clock domain string, but we really
                    # should to collapse based on some (device ID, clock domain ID)
                    # tuple. Giving Telemetry its own clock domain is a work-around
                    # for this.
                    "clock-domain":
                    "TELEMETRY",
                    "telemetry": (self._telemetry_info.AsDict()
                                  if self._telemetry_info else {}),
                }
            })
        try:
            os.remove(self._trace_log)
            self._trace_log = None
        except OSError:
            logging.exception(
                'Error when deleting %s, will try again at exit.',
                self._trace_log)

            def DeleteAtExit(path):
                os.remove(path)

            atexit_with_log.Register(DeleteAtExit, self._trace_log)
        self._trace_log = None
示例#14
0
def EnableListingStrayProcessesUponExitHook():
    def _ListAllSubprocesses():
        try:
            import psutil
        except ImportError:
            logging.warning(
                'psutil is not installed on the system. Not listing possible '
                'leaked processes. To install psutil, see: '
                'https://pypi.python.org/pypi/psutil')
            return
        telemetry_pid = os.getpid()
        parent = psutil.Process(telemetry_pid)
        if hasattr(parent, 'children'):
            children = parent.children(recursive=True)
        else:  # Some old version of psutil use get_children instead children.
            children = parent.get_children()
        if children:
            leak_processes_info = []
            for p in children:
                if inspect.ismethod(p.name):
                    name = p.name()
                else:  # Process.name is a property in old versions of psutil.
                    name = p.name
                process_info = '%s (%s)' % (name, p.pid)
                try:
                    if inspect.ismethod(p.cmdline):
                        cmdline = p.cmdline()
                    else:
                        cmdline = p.cmdline
                    process_info += ' - %s' % cmdline
                except Exception as e:  # pylint: disable=broad-except
                    logging.warning(str(e))
                leak_processes_info.append(process_info)
            logging.warning('Telemetry leaks these processes: %s',
                            ', '.join(leak_processes_info))

    atexit_with_log.Register(_ListAllSubprocesses)
    def StartServer(self, timeout=10):
        """Start TsProxy server and verify that it started.
    """
        cmd_line = [sys.executable, _TSPROXY_PATH]
        cmd_line.extend([
            '--port=0'
        ])  # Use port 0 so tsproxy picks a random available port.
        if self._host_ip:
            cmd_line.append('--desthost=%s' % self._host_ip)
        if self._http_port:
            cmd_line.append('--mapports=443:%s,*:%s' %
                            (self._https_port, self._http_port))
        logging.info('Tsproxy commandline: %r' % cmd_line)
        self._proc = subprocess.Popen(cmd_line,
                                      stdout=subprocess.PIPE,
                                      stdin=subprocess.PIPE,
                                      stderr=subprocess.PIPE,
                                      bufsize=1)
        self._non_blocking = False
        if fcntl:
            logging.info('fcntl is supported, try setting '
                         'non blocking I/O for the ts_proxy process')
            fd = self._proc.stdout.fileno()
            fl = fcntl.fcntl(fd, fcntl.F_GETFL)
            fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK)
            self._non_blocking = True

        atexit_with_log.Register(self.StopServer)
        try:
            py_utils.WaitFor(self._IsStarted, timeout)
            logging.info('TsProxy port: %s', self._port)
            self._is_running = True
        except py_utils.TimeoutException:
            # TODO(nedn): remove this debug log once crbug.com/766877 is resolved
            ps_util.ListAllSubprocesses()
            err = self.StopServer()
            raise RuntimeError('Error starting tsproxy: %s' % err)
示例#16
0
 def __init__(self, power_monitors, battery):
     super(AndroidPowerMonitorController, self).__init__()
     self._candidate_power_monitors = power_monitors
     self._active_monitors = []
     self._battery = battery
     atexit_with_log.Register(_ReenableChargingIfNeeded, self._battery)
示例#17
0
def EnableListingStrayProcessesUponExitHook():
    atexit_with_log.Register(ListAllSubprocesses)