1# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5import json, re, time
6
7from autotest_lib.client.common_lib import error
8from autotest_lib.server import hosts
9from autotest_lib.server import test
10
11
12_TIME_TO_SUSPEND = 10
13_EXTRA_DELAY = 10
14
15
16class power_BatteryStateOnResume(test.test):
17    """
18    Test to verify the battery charge state of the DUT on resume after the AC
19    charger gets unplugged and plugged in its suspend state.
20
21    If DUT is connected to RPM(default) - No need to pass any command line args.
22    If DUT is connected to USB powerstrip(via servo), Need to pass cmdlineargs
23    as --args=power_control="servoj10".
24    If DUT is not connected to servo and RPM. i.e to handle manually, Need to
25    pass cmdlineargs as --args=power_control="manual".
26    """
27    version = 1
28
29    def initialize(self, host, client_ip, cmdline_args):
30        self._client = hosts.create_host(client_ip)
31        self.ensure_battery_present()
32
33        args = {}
34        for arg in cmdline_args:
35            match = re.search("^(\w+)=(.+)", arg)
36            if match:
37                args[match.group(1)] = match.group(2)
38        self.power_control = args.get('power_control', host.POWER_CONTROL_RPM)
39        if self.power_control not in host.POWER_CONTROL_VALID_ARGS:
40            raise error.TestError('Valid values for --args=power_control '
41                                  'are %s. But you entered wrong argument '
42                                  'as "%s".'
43                                   % (host.POWER_CONTROL_VALID_ARGS,
44                                   self.power_control))
45
46
47    def run_once(self, host):
48        if not self.loggedin(host):
49            raise error.TestError("Not logged in!")
50        self.unplug_ac_on_suspend(host)
51        self.test_discharge_state(host)
52        self.plug_ac_on_suspend(host)
53        self.test_charge_state(host)
54
55
56    def unplug_ac_on_suspend(self, host):
57        """Unplugs AC when device in Suspend state."""
58        host.servo.lid_close()
59        time.sleep(_TIME_TO_SUSPEND + _EXTRA_DELAY)
60        host.power_off(self.power_control)
61        host.servo.lid_open()
62        time.sleep(_EXTRA_DELAY)
63
64
65    def plug_ac_on_suspend(self, host):
66        """Plugs AC when device in Suspend state."""
67        host.servo.lid_close()
68        time.sleep(_TIME_TO_SUSPEND + _EXTRA_DELAY)
69        host.power_on(self.power_control)
70        host.servo.lid_open()
71        time.sleep(_EXTRA_DELAY)
72
73
74    def ensure_battery_present(self):
75        """Ensure we have battery exists in DUT."""
76        result = self._client.run('power_supply_info | egrep present')
77        if 'yes' not in result.stdout:
78            raise error.TestError('Find no batteries')
79
80
81    def loggedin(self, host):
82        """
83        Checks if the host has a logged in user.
84
85        @return True if a user is logged in on the device.
86        """
87        try:
88            cmd_out = host.run('cryptohome --action=status').stdout.strip()
89        except:
90            return False
91        status = json.loads(cmd_out)
92        return any((mount['mounted'] for mount in status['mounts']))
93
94
95    def test_charge_state(self, host):
96        """Tests whether battery is in 'Charging/Charged' state."""
97        bat_state = self.get_bat_status(host)
98        if not (bat_state == 'Charging' or bat_state == 'Fully charged'):
99            raise error.TestFail('Not Charging.  BAT state is %s.' % bat_state)
100
101
102    def test_discharge_state(self, host):
103        """Tests whether battery is in 'Discharging' state."""
104        bat_state = self.get_bat_status(host)
105        if not bat_state == 'Discharging':
106            raise error.TestFail(
107                'Not Discharging.  BAT state is %s.' % bat_state)
108
109
110    def get_bat_status(self, host):
111        """Returns the battery state per the 'power_supply_info' tool.
112
113        @return battery power 'state' value. (i.e, Charging/Discharging ..)
114        """
115        bat_state_info = host.run(
116            'power_supply_info | egrep state').stdout.strip()
117        split_list = bat_state_info.split(":")
118        return split_list[-1].strip()
119