blob: ee4e6e1592aa7fcc3100c07d7d7b125f053b259d [file] [log] [blame] [edit]
# Copyright 2016 The Chromium OS 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
import os
import factory_common # pylint: disable=unused-import
from cros.factory.device import device_utils
from cros.factory.goofy.plugins import periodic_plugin
from cros.factory.utils import log_utils
from cros.factory.utils import type_utils
class BatteryMonitor(periodic_plugin.PeriodicPlugin):
# Sync disks when battery level is higher than this value.
# Otherwise, power loss during disk sync operation may incur even worse
# outcome.
MIN_BATTERY_LEVEL_FOR_DISK_SYNC = 1.0
def __init__(self, goofy, period_secs, critical_low_battery_pct=None,
warning_low_battery_pct=False):
super(BatteryMonitor, self).__init__(goofy, period_secs)
self._critical_low_battery_pct = critical_low_battery_pct
self._warning_low_battery_pct = warning_low_battery_pct
self._dut = device_utils.CreateDUTInterface()
self._last_log_message = None
self._warn = log_utils.NoisyLogger(logging.warn)
self._except = log_utils.NoisyLogger(logging.exception)
@type_utils.Overrides
def RunTask(self):
self._CheckBattery()
def _CheckBattery(self):
"""Checks the current battery status.
Logs current battery charging level and status to log. If the battery level
is lower below warning_low_battery_pct, send warning event to server.
If the battery level is lower below critical_low_battery_pct, flush disks.
"""
message = ''
log_level = logging.INFO
try:
power = self._dut.power
if not power.CheckBatteryPresent():
message = 'Battery is not present'
else:
ac_present = power.CheckACPresent()
charge_pct = power.GetChargePct(get_float=True)
message = ('Current battery level %.1f%%, AC charger is %s' %
(charge_pct, 'connected' if ac_present else 'disconnected'))
if charge_pct > self._critical_low_battery_pct:
critical_low_battery = False
else:
critical_low_battery = True
# Only sync disks when battery level is still above minimum
# value. This can be used for offline analysis when shopfloor cannot
# be connected.
if charge_pct > self.MIN_BATTERY_LEVEL_FOR_DISK_SYNC:
self._warn.Log('disk syncing for critical low battery situation')
os.system('sync')
else:
self._warn.Log(
'disk syncing is cancelled because battery level is lower '
'than %.1f', self.MIN_BATTERY_LEVEL_FOR_DISK_SYNC)
# Notify factory server
if (critical_low_battery or
(not ac_present and charge_pct <= self._warning_low_battery_pct)):
log_level = logging.WARNING
self.goofy.event_log.Log('low_battery',
battery_level=charge_pct,
charger_connected=ac_present,
critical=critical_low_battery)
self.goofy.log_watcher.KickWatchThread()
system_log_manager = self.goofy.plugin_controller.GetPluginInstance(
'system_log_manager')
if system_log_manager:
system_log_manager.KickToSync()
except Exception:
self._except.Log('Unable to check battery or notify factory server')
finally:
if message and message != self._last_log_message:
logging.log(log_level, message)
self._last_log_message = message