blob: b3fb5c51fdfac9016c69383e991f695782b087c9 [file] [log] [blame]
# Copyright 2016 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import logging
from battor import battor_error
from battor import battor_wrapper
from py_utils import cloud_storage
from devil.android import battery_utils
from py_trace_event import trace_time
from telemetry.internal.platform import tracing_agent
from telemetry.internal.util import atexit_with_log
from telemetry.timeline import trace_data
def _ReenableChargingIfNeeded(battery):
if not battery.GetCharging():
battery.SetCharging(True)
logging.info('Charging status checked at exit.')
class BattOrTracingAgent(tracing_agent.TracingAgent):
"""A tracing agent for getting power data from a BattOr device.
BattOrTracingAgent allows Telemetry to issue high-level tracing commands
(StartTracing, StopTracing, RecordClockSyncMarker) to BattOrs, which are
high-frequency power monitors used for battery testing.
"""
def __init__(self, platform_backend):
super(BattOrTracingAgent, self).__init__(platform_backend)
self._platform_backend = platform_backend
android_device = (
platform_backend.device if platform_backend.GetOSName() == 'android'
else None)
self._battery = (
battery_utils.BatteryUtils(platform_backend.device)
if platform_backend.GetOSName() == 'android' else None)
self._battor = battor_wrapper.BattorWrapper(
platform_backend.GetOSName(), android_device=android_device,
serial_log_bucket=cloud_storage.TELEMETRY_OUTPUT)
@classmethod
def IsSupported(cls, platform_backend):
"""Returns True if BattOr tracing is available."""
if platform_backend.GetOSName() == 'android':
# TODO(rnephew): When we pass BattOr device map into Telemetry, change
# this to reflect that.
return battor_wrapper.IsBattOrConnected(
'android', android_device=platform_backend.device)
return battor_wrapper.IsBattOrConnected(platform_backend.GetOSName())
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 StopAgentTracing(self):
"""Stops tracing on the BattOr."""
try:
self._battor.StopTracing()
finally:
if self._battery:
self._battery.SetCharging(True)
def SupportsExplicitClockSync(self):
return self._battor.SupportsExplicitClockSync()
def RecordClockSyncMarker(self, sync_id,
record_controller_clock_sync_marker_callback):
"""Records a clock sync marker in the BattOr trace.
Args:
sync_id: Unique id for sync event.
record_controller_clock_sync_marker_callback: Function that takes a sync
ID and a timestamp as arguments. This function typically will record the
tracing controller clock sync marker.
"""
timestamp = trace_time.Now()
try:
self._battor.RecordClockSyncMarker(sync_id)
except battor_error.BattorError:
logging.critical(
'Error while clock syncing with BattOr. Killing BattOr shell.')
self._battor.KillBattOrShell()
raise
record_controller_clock_sync_marker_callback(sync_id, timestamp)
def CollectAgentTraceData(self, trace_data_builder, timeout=None):
data = self._battor.CollectTraceData(timeout=timeout)
trace_data_builder.SetTraceFor(trace_data.BATTOR_TRACE_PART, data)