• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright (c) 2010 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 logging, time
6from autotest_lib.client.bin import test
7from autotest_lib.client.common_lib import error
8from autotest_lib.client.cros import service_stopper
9from autotest_lib.client.cros.power import power_status, power_utils
10
11class power_BatteryCharge(test.test):
12    """class power_BatteryCharge."""
13    version = 1
14
15    def initialize(self):
16        if not power_utils.has_battery():
17            raise error.TestNAError('DUT has no battery. Test Skipped')
18
19        self.status = power_status.get_status()
20
21        if not self.status.on_ac():
22            raise error.TestNAError(
23                  'This test needs to be run with the AC power online')
24
25        self._services = service_stopper.ServiceStopper(
26            service_stopper.ServiceStopper.POWER_DRAW_SERVICES + ['ui'])
27        self._services.stop_services()
28
29
30    def run_once(self, max_run_time=180, percent_charge_to_add=1,
31                 percent_initial_charge_max=None,
32                 percent_target_charge=None,
33                 use_design_charge_capacity=True):
34
35        """
36        max_run_time: maximum time the test will run for
37        percent_charge_to_add: percentage of the charge capacity charge to
38                  add. The target charge will be capped at the charge capacity.
39        percent_initial_charge_max: maxium allowed initial charge.
40        use_design_charge_capacity: If set, use charge_full_design rather than
41                  charge_full for calculations. charge_full represents
42                  wear-state of battery, vs charge_full_design representing
43                  ideal design state.
44        """
45
46        time_to_sleep = 60
47
48        self._backlight = power_utils.Backlight()
49        self._backlight.set_percent(0)
50
51        self.remaining_time = self.max_run_time = max_run_time
52
53        self.charge_full_design = self.status.battery[0].charge_full_design
54        self.charge_full = self.status.battery[0].charge_full
55        if use_design_charge_capacity:
56            self.charge_capacity = self.charge_full_design
57        else:
58            self.charge_capacity = self.charge_full
59
60        if self.charge_capacity == 0:
61            raise error.TestError('Failed to determine charge capacity')
62
63        self.initial_charge = self.status.battery[0].charge_now
64        percent_initial_charge = self.initial_charge * 100 / \
65                                 self.charge_capacity
66        if percent_initial_charge_max and percent_initial_charge > \
67                                          percent_initial_charge_max:
68            raise error.TestError('Initial charge (%f) higher than max (%f)'
69                      % (percent_initial_charge, percent_initial_charge_max))
70
71        current_charge = self.initial_charge
72        if percent_target_charge is None:
73            charge_to_add = self.charge_capacity * \
74                            float(percent_charge_to_add) / 100
75            target_charge = current_charge + charge_to_add
76        else:
77            target_charge = self.charge_capacity * \
78                            float(percent_target_charge) / 100
79
80        # trim target_charge if it exceeds charge capacity
81        if target_charge > self.charge_capacity:
82            target_charge = self.charge_capacity
83
84        logging.info('max_run_time: %d', self.max_run_time)
85        logging.info('initial_charge: %f', self.initial_charge)
86        logging.info('target_charge: %f', target_charge)
87
88        while self.remaining_time and current_charge < target_charge:
89            if time_to_sleep > self.remaining_time:
90                time_to_sleep = self.remaining_time
91            self.remaining_time -= time_to_sleep
92
93            time.sleep(time_to_sleep)
94
95            self.status.refresh()
96            if not self.status.on_ac():
97                raise error.TestError(
98                      'This test needs to be run with the AC power online')
99
100            new_charge = self.status.battery[0].charge_now
101            logging.info('time_to_sleep: %d', time_to_sleep)
102            logging.info('charge_added: %f', (new_charge - current_charge))
103
104            current_charge = new_charge
105            logging.info('current_charge: %f', current_charge)
106
107            if self.status.battery[0].status == 'Full':
108                logging.info('Battery full, aborting!')
109                break
110
111
112    def postprocess_iteration(self):
113        keyvals = {}
114        keyvals['ah_charge_full'] = self.charge_full
115        keyvals['ah_charge_full_design'] = self.charge_full_design
116        keyvals['ah_charge_capacity'] = self.charge_capacity
117        keyvals['ah_initial_charge'] = self.initial_charge
118        keyvals['ah_final_charge'] = self.status.battery[0].charge_now
119        keyvals['s_time_taken'] = self.max_run_time - self.remaining_time
120        keyvals['percent_initial_charge'] = self.initial_charge * 100 / \
121                                            keyvals['ah_charge_capacity']
122        keyvals['percent_final_charge'] = keyvals['ah_final_charge'] * 100 / \
123                                          keyvals['ah_charge_capacity']
124
125        percent_charge_added = keyvals['percent_final_charge'] - \
126            keyvals['percent_initial_charge']
127        # Conditionally write charge current keyval only when the amount of
128        # charge added is > 50% to remove samples when test is run but battery
129        # is already mostly full.  Otherwise current will be ~0 and not
130        # meaningful.
131        if percent_charge_added > 50:
132            hrs_charging = keyvals['s_time_taken'] / 3600.
133            keyvals['a_avg50_charge_current'] = \
134                (keyvals['ah_final_charge'] - self.initial_charge) / \
135                hrs_charging
136
137        self.write_perf_keyval(keyvals)
138
139
140    def cleanup(self):
141        if hasattr(self, '_services') and self._services:
142            self._services.restore_services()
143        if hasattr(self, '_backlight') and self._backlight:
144            self._backlight.restore()
145