blob: c4b7c3de993861f34ee8206dc4868151f9376432 [file] [log] [blame]
# Copyright 2020 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 time
from autotest_lib.client.common_lib import error
from autotest_lib.server.cros.faft.firmware_test import FirmwareTest
class firmware_ECChargingState(FirmwareTest):
"""
Type-C servo-v4 based EC charging state test.
"""
version = 1
# The delay to wait for the AC state to update.
AC_STATE_UPDATE_DELAY = 3
# We wait for up to 3 hrs for the battery to report fully charged.
FULL_CHARGE_TIMEOUT = 60 * 60 * 3
# The period to check battery state while charging.
CHECK_BATT_STATE_WAIT = 60
def initialize(self, host, cmdline_args):
super(firmware_ECChargingState, self).initialize(host, cmdline_args)
if not self.check_ec_capability(['battery', 'charging']):
raise error.TestNAError("Nothing needs to be tested on this DUT")
if self.servo.get_servo_version() != 'servo_v4_with_ccd_cr50':
raise error.TestNAError("This test can only be run with servo-v4 "
"+ CCD. If you don't have a Type-C servo-v4, please run "
"the test manually.")
if host.is_ac_connected() != True:
raise error.TestFail("This test must be run with AC power.")
self.switcher.setup_mode('normal')
self.ec.send_command("chan save")
self.ec.send_command("chan 0")
def cleanup(self):
try:
self.ec.send_command("chan restore")
except Exception as e:
logging.error("Caught exception: %s", str(e))
super(firmware_ECChargingState, self).cleanup()
def check_ac_state(self):
"""Check if AC is plugged."""
ac_state = int(self.ec.send_command_get_output("chgstate",
["ac\s*=\s*(0|1)\s*"])[0][1])
if ac_state == 1:
return 'on'
elif ac_state == 0:
return 'off'
else:
return 'unknown'
def get_battery_level(self):
"""Get battery charge percentage."""
batt_level = int(self.ec.send_command_get_output("battery",
["Charge:\s+(\d+)\s+"])[0][1])
return batt_level
def run_once(self, host):
"""Execute the main body of the test."""
if host.is_ac_connected() != True:
raise error.TestFail("This test must be run with AC power.")
logging.info("Suspend, unplug AC, and then wake up the device.")
self.suspend()
self.switcher.wait_for_client_offline()
# Call set_servo_v4_role_to_snk() instead of directly setting
# servo_v4 role to snk, so servo_v4_role can be recovered to
# default src in cleanup().
self.set_servo_v4_role_to_snk()
time.sleep(self.AC_STATE_UPDATE_DELAY)
# Verify servo v4 is sinking power.
if self.check_ac_state() != 'off':
raise error.TestFail("Fail to unplug AC.")
self.servo.power_normal_press()
self.switcher.wait_for_client()
batt_state = host.get_battery_state()
if batt_state != 'Discharging':
raise error.TestFail("Wrong battery state. Expected: "
"Discharging, got: %s." % batt_state)
logging.info("Suspend, plug AC, and then wake up the device.")
self.suspend()
self.switcher.wait_for_client_offline()
self.servo.set_servo_v4_role('src')
time.sleep(self.AC_STATE_UPDATE_DELAY)
# Verify servo v4 is sourcing power.
if self.check_ac_state() != 'on':
raise error.TestFail("Fail to plug AC.")
self.servo.power_normal_press()
self.switcher.wait_for_client()
batt_state = host.get_battery_state()
if batt_state != 'Charging' and batt_state != 'Fully charged':
raise error.TestFail("Wrong battery state. Expected: "
"Charging/Fully charged, got: %s." % batt_state)
logging.info("Keep charging until the battery reports fully charged.")
deadline = time.time() + self.FULL_CHARGE_TIMEOUT
while time.time() < deadline:
batt_state = host.get_battery_state()
if batt_state == 'Fully charged':
logging.info("The battery reports fully charged.")
return
elif batt_state == 'Charging':
logging.info("Wait for the battery to be fully charged. "
"The current battery level is %d%%.",
self.get_battery_level())
else:
raise error.TestFail("The battery state is %s. "
"Is AC unplugged?", batt_state)
time.sleep(self.CHECK_BATT_STATE_WAIT)
raise error.TestFail("The battery does not report fully charged "
"before timeout is reached. The final battery level is %d%%.",
self.get_battery_level())