1650be6d5f895abe5fd9fbca4cf242bdf92443c62Mike Truty# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
26a0746595cb21c52db2b4ef2e03ff1d73a75c1d0Sameer Nanda# Use of this source code is governed by a BSD-style license that can be
36a0746595cb21c52db2b4ef2e03ff1d73a75c1d0Sameer Nanda# found in the LICENSE file.
46a0746595cb21c52db2b4ef2e03ff1d73a75c1d0Sameer Nanda
5172ecb7f5a6bbda741799444237a9be4ee21518bEd Bakerimport collections, logging, numpy, os, tempfile, time
60ecaa5c74b6943368ba80cedca2259931f51426aDerek Basehorefrom autotest_lib.client.bin import utils, test
7bee23c2b0ca824c12c39e7a5a4cd4d2a313918b7Eric Lifrom autotest_lib.client.common_lib import error
8172ecb7f5a6bbda741799444237a9be4ee21518bEd Bakerfrom autotest_lib.client.common_lib import file_utils
90ecaa5c74b6943368ba80cedca2259931f51426aDerek Basehorefrom autotest_lib.client.common_lib.cros import chrome
10ccc390b2d0087b860cecd8086ea25a2326ffa144Derek Basehorefrom autotest_lib.client.common_lib.cros.network import xmlrpc_datatypes
11ccc390b2d0087b860cecd8086ea25a2326ffa144Derek Basehorefrom autotest_lib.client.common_lib.cros.network import xmlrpc_security_types
120ecaa5c74b6943368ba80cedca2259931f51426aDerek Basehorefrom autotest_lib.client.cros import backchannel, httpd
130d61ffb567a6d0e55c332b0ab1e05caf01000b77Eric Carusofrom autotest_lib.client.cros import memory_bandwidth_logger
14145cb75b5c33f590ddcb9421e8b3c3fbeae7117fTodd Brochfrom autotest_lib.client.cros import power_rapl, power_status, power_utils
15187240b15fe210be911c5dfc2a414d0780d9be7dTodd Brochfrom autotest_lib.client.cros import service_stopper
1605c4b5d1b1417c4e38f184416b0d0ede23cd4e0aTodd Brochfrom autotest_lib.client.cros.audio import audio_helper
171f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wileyfrom autotest_lib.client.cros.networking import wifi_proxy
189450ad9bc6e5537d93f31bd53f161067fb13a1d5Dale Curtis
199d4bcb6d907ad23d947f65d3c764c8ee3848e7d3Sameer Nandaparams_dict = {
209d4bcb6d907ad23d947f65d3c764c8ee3848e7d3Sameer Nanda    'test_time_ms': '_mseconds',
219d4bcb6d907ad23d947f65d3c764c8ee3848e7d3Sameer Nanda    'should_scroll': '_should_scroll',
229d4bcb6d907ad23d947f65d3c764c8ee3848e7d3Sameer Nanda    'should_scroll_up': '_should_scroll_up',
239d4bcb6d907ad23d947f65d3c764c8ee3848e7d3Sameer Nanda    'scroll_loop': '_scroll_loop',
249d4bcb6d907ad23d947f65d3c764c8ee3848e7d3Sameer Nanda    'scroll_interval_ms': '_scroll_interval_ms',
259d4bcb6d907ad23d947f65d3c764c8ee3848e7d3Sameer Nanda    'scroll_by_pixels': '_scroll_by_pixels',
267868162435adf9082b022a5ba6e00614c7c66381Simon Que    'tasks': '_tasks',
279d4bcb6d907ad23d947f65d3c764c8ee3848e7d3Sameer Nanda}
289d4bcb6d907ad23d947f65d3c764c8ee3848e7d3Sameer Nanda
296a0746595cb21c52db2b4ef2e03ff1d73a75c1d0Sameer Nanda
300ecaa5c74b6943368ba80cedca2259931f51426aDerek Basehoreclass power_LoadTest(test.test):
31145cb75b5c33f590ddcb9421e8b3c3fbeae7117fTodd Broch    """test class"""
3206548eee3dafcf0fc9ee0dcd15eb607b901ad2c1Benson Leung    version = 2
335cfd7fab4966bf402c4073a41707c31b26cb8c5fAchuith Bhandarkar    _username = 'powerloadtest@gmail.com'
34172ecb7f5a6bbda741799444237a9be4ee21518bEd Baker    _pltp_url = 'https://sites.google.com/a/chromium.org/dev/chromium-os' \
35172ecb7f5a6bbda741799444237a9be4ee21518bEd Baker                '/testing/power-testing/pltp/pltp'
3650fb54165e35caebc1bd90d409fcba0fe0b01658Sameer Nanda
37e7c4cab13a8576a4f9de41b2dc1fb8c45c97424cEric Li
385cfd7fab4966bf402c4073a41707c31b26cb8c5fAchuith Bhandarkar    def initialize(self, percent_initial_charge_min=None,
394f99e9a29b81d14cc94eb711cdb4adb5e66872abSameer Nanda                 check_network=True, loop_time=3600, loop_count=1,
404f99e9a29b81d14cc94eb711cdb4adb5e66872abSameer Nanda                 should_scroll='true', should_scroll_up='true',
414f99e9a29b81d14cc94eb711cdb4adb5e66872abSameer Nanda                 scroll_loop='false', scroll_interval_ms='10000',
4221978453eaa14e284560915268cf9cb1b4604a48Todd Broch                 scroll_by_pixels='600', test_low_batt_p=3,
4359405505bdf7284425645edc162436fd89fb6d51Derek Basehore                 verbose=True, force_wifi=False, wifi_ap='', wifi_sec='none',
44fd456804cb8f90f43589f440e0a12c3a7fc7c9d4Derek Basehore                 wifi_pw='', wifi_timeout=60, tasks='', kblight_percent=10,
453932cc39076c41847e4b8201abb225528b4b815eTodd Broch                 volume_level=10, mic_gain=10, low_batt_margin_p=2,
460d61ffb567a6d0e55c332b0ab1e05caf01000b77Eric Caruso                 ac_ok=False, log_mem_bandwidth=False):
479d4bcb6d907ad23d947f65d3c764c8ee3848e7d3Sameer Nanda        """
489d4bcb6d907ad23d947f65d3c764c8ee3848e7d3Sameer Nanda        percent_initial_charge_min: min battery charge at start of test
499d4bcb6d907ad23d947f65d3c764c8ee3848e7d3Sameer Nanda        check_network: check that Ethernet interface is not running
50417da5be901b3e68131017e1a631bdd84835b1d2Sameer Nanda        loop_time: length of time to run the test for in each loop
51a5b3a27862f43e060f9823dd60fa0be18a348862Derek Basehore        loop_count: number of times to loop the test for
529d4bcb6d907ad23d947f65d3c764c8ee3848e7d3Sameer Nanda        should_scroll: should the extension scroll pages
539d4bcb6d907ad23d947f65d3c764c8ee3848e7d3Sameer Nanda        should_scroll_up: should scroll in up direction
549d4bcb6d907ad23d947f65d3c764c8ee3848e7d3Sameer Nanda        scroll_loop: continue scrolling indefinitely
559d4bcb6d907ad23d947f65d3c764c8ee3848e7d3Sameer Nanda        scroll_interval_ms: how often to scoll
569d4bcb6d907ad23d947f65d3c764c8ee3848e7d3Sameer Nanda        scroll_by_pixels: number of pixels to scroll each time
57a5b3a27862f43e060f9823dd60fa0be18a348862Derek Basehore        test_low_batt_p: percent battery at which test should stop
58a5b3a27862f43e060f9823dd60fa0be18a348862Derek Basehore        verbose: add more logging information
59a5b3a27862f43e060f9823dd60fa0be18a348862Derek Basehore        force_wifi: should we force to test to run on wifi
60a5b3a27862f43e060f9823dd60fa0be18a348862Derek Basehore        wifi_ap: the name (ssid) of the wifi access point
61a5b3a27862f43e060f9823dd60fa0be18a348862Derek Basehore        wifi_sec: the type of security for the wifi ap
62a5b3a27862f43e060f9823dd60fa0be18a348862Derek Basehore        wifi_pw: password for the wifi ap
63d7a0f395cd6a36c4f86a88e2bce3b6a6319fbdc8Derek Basehore        wifi_timeout: The timeout for wifi configuration
642f156e8967fab4b4ffe38cd727aaeabf5e4080f6Todd Broch        kblight_percent: percent brightness of keyboard backlight
6505c4b5d1b1417c4e38f184416b0d0ede23cd4e0aTodd Broch        volume_level: percent audio volume level
6605c4b5d1b1417c4e38f184416b0d0ede23cd4e0aTodd Broch        mic_gain: percent audio microphone gain level
67145cb75b5c33f590ddcb9421e8b3c3fbeae7117fTodd Broch        low_batt_margin_p: percent low battery margin to be added to
68145cb75b5c33f590ddcb9421e8b3c3fbeae7117fTodd Broch            sys_low_batt_p to guarantee test completes prior to powerd shutdown
693932cc39076c41847e4b8201abb225528b4b815eTodd Broch        ac_ok: boolean to allow running on AC
700d61ffb567a6d0e55c332b0ab1e05caf01000b77Eric Caruso        log_mem_bandwidth: boolean to log memory bandwidth during the test
719d4bcb6d907ad23d947f65d3c764c8ee3848e7d3Sameer Nanda        """
72af5de98643110a67a9f5c323dd56be3eb1e35448Todd Broch        self._backlight = None
736597273abc070f752cd1d57a88556b5f98d96934Derek Basehore        self._services = None
7441acbf89080501db1b554c6919e1e0b3593585ffDerek Basehore        self._browser = None
75417da5be901b3e68131017e1a631bdd84835b1d2Sameer Nanda        self._loop_time = loop_time
76417da5be901b3e68131017e1a631bdd84835b1d2Sameer Nanda        self._loop_count = loop_count
77417da5be901b3e68131017e1a631bdd84835b1d2Sameer Nanda        self._mseconds = self._loop_time * 1000
789d4bcb6d907ad23d947f65d3c764c8ee3848e7d3Sameer Nanda        self._verbose = verbose
7921978453eaa14e284560915268cf9cb1b4604a48Todd Broch
8021978453eaa14e284560915268cf9cb1b4604a48Todd Broch        self._sys_low_batt_p = 0.
8121978453eaa14e284560915268cf9cb1b4604a48Todd Broch        self._sys_low_batt_s = 0.
8221978453eaa14e284560915268cf9cb1b4604a48Todd Broch        self._test_low_batt_p = test_low_batt_p
839d4bcb6d907ad23d947f65d3c764c8ee3848e7d3Sameer Nanda        self._should_scroll = should_scroll
849d4bcb6d907ad23d947f65d3c764c8ee3848e7d3Sameer Nanda        self._should_scroll_up = should_scroll_up
859d4bcb6d907ad23d947f65d3c764c8ee3848e7d3Sameer Nanda        self._scroll_loop = scroll_loop
869d4bcb6d907ad23d947f65d3c764c8ee3848e7d3Sameer Nanda        self._scroll_interval_ms = scroll_interval_ms
879d4bcb6d907ad23d947f65d3c764c8ee3848e7d3Sameer Nanda        self._scroll_by_pixels = scroll_by_pixels
88417da5be901b3e68131017e1a631bdd84835b1d2Sameer Nanda        self._tmp_keyvals = {}
89bee23c2b0ca824c12c39e7a5a4cd4d2a313918b7Eric Li        self._power_status = power_status.get_status()
903932cc39076c41847e4b8201abb225528b4b815eTodd Broch        self._tmp_keyvals['b_on_ac'] = self._power_status.on_ac()
9159405505bdf7284425645edc162436fd89fb6d51Derek Basehore        self._force_wifi = force_wifi
92b7edff18c59e1caedc32f972551ec68b3620eea5Dale Curtis        self._testServer = None
93fd456804cb8f90f43589f440e0a12c3a7fc7c9d4Derek Basehore        self._tasks = tasks.replace(' ','')
94b312dcf7a07ffdfe5a9625bbb1b5b08e81158b39Jason Glasgow        self._backchannel = None
95f10a3198906c17a539c830e1263e6efb0a3db7b2Derek Basehore        self._shill_proxy = None
962f156e8967fab4b4ffe38cd727aaeabf5e4080f6Todd Broch        self._kblight_percent = kblight_percent
9705c4b5d1b1417c4e38f184416b0d0ede23cd4e0aTodd Broch        self._volume_level = volume_level
9805c4b5d1b1417c4e38f184416b0d0ede23cd4e0aTodd Broch        self._mic_gain = mic_gain
993932cc39076c41847e4b8201abb225528b4b815eTodd Broch        self._ac_ok = ac_ok
1000d61ffb567a6d0e55c332b0ab1e05caf01000b77Eric Caruso        self._log_mem_bandwidth = log_mem_bandwidth
10121978453eaa14e284560915268cf9cb1b4604a48Todd Broch        self._wait_time = 60
10221978453eaa14e284560915268cf9cb1b4604a48Todd Broch        self._stats = collections.defaultdict(list)
1039d4bcb6d907ad23d947f65d3c764c8ee3848e7d3Sameer Nanda
104172ecb7f5a6bbda741799444237a9be4ee21518bEd Baker        with tempfile.NamedTemporaryFile() as pltp:
105172ecb7f5a6bbda741799444237a9be4ee21518bEd Baker            file_utils.download_file(self._pltp_url, pltp.name)
106172ecb7f5a6bbda741799444237a9be4ee21518bEd Baker            self._password = pltp.read().rstrip()
10799c242a22b990e59cac306efa392a2f0f3215bc4Derek Basehore
1083932cc39076c41847e4b8201abb225528b4b815eTodd Broch        if not ac_ok:
1093932cc39076c41847e4b8201abb225528b4b815eTodd Broch            self._power_status.assert_battery_state(percent_initial_charge_min)
11059405505bdf7284425645edc162436fd89fb6d51Derek Basehore        # If force wifi enabled, convert eth0 to backchannel and connect to the
11159405505bdf7284425645edc162436fd89fb6d51Derek Basehore        # specified WiFi AP.
11259405505bdf7284425645edc162436fd89fb6d51Derek Basehore        if self._force_wifi:
113ccc390b2d0087b860cecd8086ea25a2326ffa144Derek Basehore            sec_config = None
114ccc390b2d0087b860cecd8086ea25a2326ffa144Derek Basehore            # TODO(dbasehore): Fix this when we get a better way of figuring out
115ccc390b2d0087b860cecd8086ea25a2326ffa144Derek Basehore            # the wifi security configuration.
116ccc390b2d0087b860cecd8086ea25a2326ffa144Derek Basehore            if wifi_sec == 'rsn' or wifi_sec == 'wpa':
117ccc390b2d0087b860cecd8086ea25a2326ffa144Derek Basehore                sec_config = xmlrpc_security_types.WPAConfig(
118ccc390b2d0087b860cecd8086ea25a2326ffa144Derek Basehore                        psk=wifi_pw,
119ccc390b2d0087b860cecd8086ea25a2326ffa144Derek Basehore                        wpa_mode=xmlrpc_security_types.WPAConfig.MODE_PURE_WPA2,
120ccc390b2d0087b860cecd8086ea25a2326ffa144Derek Basehore                        wpa2_ciphers=
121ccc390b2d0087b860cecd8086ea25a2326ffa144Derek Basehore                                [xmlrpc_security_types.WPAConfig.CIPHER_CCMP])
122ccc390b2d0087b860cecd8086ea25a2326ffa144Derek Basehore            wifi_config = xmlrpc_datatypes.AssociationParameters(
123d7a0f395cd6a36c4f86a88e2bce3b6a6319fbdc8Derek Basehore                    ssid=wifi_ap, security_config=sec_config,
124d7a0f395cd6a36c4f86a88e2bce3b6a6319fbdc8Derek Basehore                    configuration_timeout=wifi_timeout)
1259450ad9bc6e5537d93f31bd53f161067fb13a1d5Dale Curtis            # If backchannel is already running, don't run it again.
126b312dcf7a07ffdfe5a9625bbb1b5b08e81158b39Jason Glasgow            self._backchannel = backchannel.Backchannel()
127b312dcf7a07ffdfe5a9625bbb1b5b08e81158b39Jason Glasgow            if not self._backchannel.setup():
1289450ad9bc6e5537d93f31bd53f161067fb13a1d5Dale Curtis                raise error.TestError('Could not setup Backchannel network.')
1299450ad9bc6e5537d93f31bd53f161067fb13a1d5Dale Curtis
130f10a3198906c17a539c830e1263e6efb0a3db7b2Derek Basehore            self._shill_proxy = wifi_proxy.WifiProxy()
131f10a3198906c17a539c830e1263e6efb0a3db7b2Derek Basehore            self._shill_proxy.remove_all_wifi_entries()
132d996e409a3debba138a3ed9523d6a2cad49b210aTodd Broch            for i in xrange(1,4):
133f10a3198906c17a539c830e1263e6efb0a3db7b2Derek Basehore                raw_output = self._shill_proxy.connect_to_wifi_network(
134ccc390b2d0087b860cecd8086ea25a2326ffa144Derek Basehore                        wifi_config.ssid,
135ccc390b2d0087b860cecd8086ea25a2326ffa144Derek Basehore                        wifi_config.security,
136ccc390b2d0087b860cecd8086ea25a2326ffa144Derek Basehore                        wifi_config.security_parameters,
137ccc390b2d0087b860cecd8086ea25a2326ffa144Derek Basehore                        wifi_config.save_credentials,
138ccc390b2d0087b860cecd8086ea25a2326ffa144Derek Basehore                        station_type=wifi_config.station_type,
139ccc390b2d0087b860cecd8086ea25a2326ffa144Derek Basehore                        hidden_network=wifi_config.is_hidden,
140ccc390b2d0087b860cecd8086ea25a2326ffa144Derek Basehore                        discovery_timeout_seconds=
141ccc390b2d0087b860cecd8086ea25a2326ffa144Derek Basehore                                wifi_config.discovery_timeout,
142ccc390b2d0087b860cecd8086ea25a2326ffa144Derek Basehore                        association_timeout_seconds=
143ccc390b2d0087b860cecd8086ea25a2326ffa144Derek Basehore                                wifi_config.association_timeout,
144ccc390b2d0087b860cecd8086ea25a2326ffa144Derek Basehore                        configuration_timeout_seconds=
145d996e409a3debba138a3ed9523d6a2cad49b210aTodd Broch                                wifi_config.configuration_timeout * i)
146ccc390b2d0087b860cecd8086ea25a2326ffa144Derek Basehore                result = xmlrpc_datatypes.AssociationResult. \
147ccc390b2d0087b860cecd8086ea25a2326ffa144Derek Basehore                        from_dbus_proxy_output(raw_output)
148ccc390b2d0087b860cecd8086ea25a2326ffa144Derek Basehore                if result.success:
149ccc390b2d0087b860cecd8086ea25a2326ffa144Derek Basehore                    break
150d996e409a3debba138a3ed9523d6a2cad49b210aTodd Broch                logging.warn('wifi connect: disc:%d assoc:%d config:%d fail:%s',
151d996e409a3debba138a3ed9523d6a2cad49b210aTodd Broch                             result.discovery_time, result.association_time,
152d996e409a3debba138a3ed9523d6a2cad49b210aTodd Broch                             result.configuration_time, result.failure_reason)
153ccc390b2d0087b860cecd8086ea25a2326ffa144Derek Basehore            else:
1549450ad9bc6e5537d93f31bd53f161067fb13a1d5Dale Curtis                raise error.TestError('Could not connect to WiFi network.')
155ccc390b2d0087b860cecd8086ea25a2326ffa144Derek Basehore
156278b5370c7d022768e0ab319ce7f439a877e4443Simon Que        else:
157278b5370c7d022768e0ab319ce7f439a877e4443Simon Que            # Find all wired ethernet interfaces.
158278b5370c7d022768e0ab319ce7f439a877e4443Simon Que            # TODO: combine this with code in network_DisableInterface, in a
159278b5370c7d022768e0ab319ce7f439a877e4443Simon Que            # common library somewhere.
160278b5370c7d022768e0ab319ce7f439a877e4443Simon Que            ifaces = [ nic.strip() for nic in os.listdir('/sys/class/net/')
161278b5370c7d022768e0ab319ce7f439a877e4443Simon Que                if ((not os.path.exists('/sys/class/net/' + nic + '/phy80211'))
162278b5370c7d022768e0ab319ce7f439a877e4443Simon Que                    and nic.find('eth') != -1) ]
163278b5370c7d022768e0ab319ce7f439a877e4443Simon Que            logging.debug(str(ifaces))
164278b5370c7d022768e0ab319ce7f439a877e4443Simon Que            for iface in ifaces:
1651bc91d6b5e86fe30b2c1b6bb74262c57c1ec7e35Christopher Grant                if check_network and self._is_network_iface_running(iface):
166ee79b397f23b6fd21a668b24264ce4c331d4d129Todd Broch                    raise error.TestError('Ethernet interface is active. ' +
167ee79b397f23b6fd21a668b24264ce4c331d4d129Todd Broch                                          'Please remove Ethernet cable')
1689d4bcb6d907ad23d947f65d3c764c8ee3848e7d3Sameer Nanda
169d075074b8fc70d829912864f819345407295f35dSameer Nanda        # record the max backlight level
170af5de98643110a67a9f5c323dd56be3eb1e35448Todd Broch        self._backlight = power_utils.Backlight()
171af5de98643110a67a9f5c323dd56be3eb1e35448Todd Broch        self._tmp_keyvals['level_backlight_max'] = \
172af5de98643110a67a9f5c323dd56be3eb1e35448Todd Broch            self._backlight.get_max_level()
1736a0746595cb21c52db2b4ef2e03ff1d73a75c1d0Sameer Nanda
174d16f1daab3a354b637065b99dbc31809ce5674ddAlex Miller        self._services = service_stopper.ServiceStopper(
175d16f1daab3a354b637065b99dbc31809ce5674ddAlex Miller            service_stopper.ServiceStopper.POWER_DRAW_SERVICES)
176d16f1daab3a354b637065b99dbc31809ce5674ddAlex Miller        self._services.stop_services()
177d16f1daab3a354b637065b99dbc31809ce5674ddAlex Miller
1789d4bcb6d907ad23d947f65d3c764c8ee3848e7d3Sameer Nanda        # fix up file perms for the power test extension so that chrome
1799d4bcb6d907ad23d947f65d3c764c8ee3848e7d3Sameer Nanda        # can access it
180ce1407b29b32f8f8fb1121251e28f0861ecac6a8Sameer Nanda        os.system('chmod -R 755 %s' % self.bindir)
1819d4bcb6d907ad23d947f65d3c764c8ee3848e7d3Sameer Nanda
1826a0746595cb21c52db2b4ef2e03ff1d73a75c1d0Sameer Nanda        # setup a HTTP Server to listen for status updates from the power
1836a0746595cb21c52db2b4ef2e03ff1d73a75c1d0Sameer Nanda        # test extension
184c4d8f4aab4e434fcb1a9fb33931768ffebfb8f1cEric Li        self._testServer = httpd.HTTPListener(8001, docroot=self.bindir)
1856a0746595cb21c52db2b4ef2e03ff1d73a75c1d0Sameer Nanda        self._testServer.run()
1866a0746595cb21c52db2b4ef2e03ff1d73a75c1d0Sameer Nanda
18787aced24632053d9df0a42842307abf165f60ad1Sameer Nanda        # initialize various interesting power related stats
18869324998af43b8992df694370a8536bad2da2f9cTodd Broch        self._statomatic = power_status.StatoMatic()
189417da5be901b3e68131017e1a631bdd84835b1d2Sameer Nanda
1904ae320f5b4afd9c047dfa446d76722100c03665bJulius Werner        self._power_status.refresh()
19121978453eaa14e284560915268cf9cb1b4604a48Todd Broch        (self._sys_low_batt_p, self._sys_low_batt_s) = \
19221978453eaa14e284560915268cf9cb1b4604a48Todd Broch            self._get_sys_low_batt_values()
193145cb75b5c33f590ddcb9421e8b3c3fbeae7117fTodd Broch        min_low_batt_p = min(self._sys_low_batt_p + low_batt_margin_p, 100)
194145cb75b5c33f590ddcb9421e8b3c3fbeae7117fTodd Broch        if self._sys_low_batt_p and (min_low_batt_p > self._test_low_batt_p):
19504be2bd5e4666a5c253e9c30ab20555e04286032Ilja H. Friedel            logging.warning("test low battery threshold is below system " +
19621978453eaa14e284560915268cf9cb1b4604a48Todd Broch                         "low battery requirement.  Setting to %f",
197145cb75b5c33f590ddcb9421e8b3c3fbeae7117fTodd Broch                         min_low_batt_p)
198145cb75b5c33f590ddcb9421e8b3c3fbeae7117fTodd Broch            self._test_low_batt_p = min_low_batt_p
1994ae320f5b4afd9c047dfa446d76722100c03665bJulius Werner
2009d4bcb6d907ad23d947f65d3c764c8ee3848e7d3Sameer Nanda        self._ah_charge_start = self._power_status.battery[0].charge_now
2019d4bcb6d907ad23d947f65d3c764c8ee3848e7d3Sameer Nanda        self._wh_energy_start = self._power_status.battery[0].energy
2029d4bcb6d907ad23d947f65d3c764c8ee3848e7d3Sameer Nanda
20306548eee3dafcf0fc9ee0dcd15eb607b901ad2c1Benson Leung    def run_once(self):
204417da5be901b3e68131017e1a631bdd84835b1d2Sameer Nanda        t0 = time.time()
205417da5be901b3e68131017e1a631bdd84835b1d2Sameer Nanda
206edfd5ba0e55670be04143d919b7d559b56a9bf35Eric Caruso        # record the PSR counter
207edfd5ba0e55670be04143d919b7d559b56a9bf35Eric Caruso        psr_t0 = self._get_psr_counter()
208edfd5ba0e55670be04143d919b7d559b56a9bf35Eric Caruso
2092f156e8967fab4b4ffe38cd727aaeabf5e4080f6Todd Broch        try:
2102f156e8967fab4b4ffe38cd727aaeabf5e4080f6Todd Broch            kblight = power_utils.KbdBacklight()
2112f156e8967fab4b4ffe38cd727aaeabf5e4080f6Todd Broch            kblight.set(self._kblight_percent)
2122f156e8967fab4b4ffe38cd727aaeabf5e4080f6Todd Broch            self._tmp_keyvals['percent_kbd_backlight'] = kblight.get()
2132f156e8967fab4b4ffe38cd727aaeabf5e4080f6Todd Broch        except power_utils.KbdBacklightException as e:
2142f156e8967fab4b4ffe38cd727aaeabf5e4080f6Todd Broch            logging.info("Assuming no keyboard backlight due to :: %s", str(e))
2152f156e8967fab4b4ffe38cd727aaeabf5e4080f6Todd Broch            kblight = None
2162f156e8967fab4b4ffe38cd727aaeabf5e4080f6Todd Broch
2172ea62250aa5ee9d9960c9f65a9501da6fd53ca8aTodd Broch        measurements = \
2182ea62250aa5ee9d9960c9f65a9501da6fd53ca8aTodd Broch            [power_status.SystemPower(self._power_status.battery_path)]
2192ea62250aa5ee9d9960c9f65a9501da6fd53ca8aTodd Broch        if power_utils.has_rapl_support():
2202ea62250aa5ee9d9960c9f65a9501da6fd53ca8aTodd Broch            measurements += power_rapl.create_rapl()
2212ea62250aa5ee9d9960c9f65a9501da6fd53ca8aTodd Broch        self._plog = power_status.PowerLogger(measurements, seconds_period=20)
222be3c3e70c41e5e28a88dad5b7062dd9baf6af091Todd Broch        self._tlog = power_status.TempLogger([], seconds_period=20)
2232ea62250aa5ee9d9960c9f65a9501da6fd53ca8aTodd Broch        self._plog.start()
224be3c3e70c41e5e28a88dad5b7062dd9baf6af091Todd Broch        self._tlog.start()
2250d61ffb567a6d0e55c332b0ab1e05caf01000b77Eric Caruso        if self._log_mem_bandwidth:
2260d61ffb567a6d0e55c332b0ab1e05caf01000b77Eric Caruso            self._mlog = memory_bandwidth_logger.MemoryBandwidthLogger(
2270d61ffb567a6d0e55c332b0ab1e05caf01000b77Eric Caruso                raw=False, seconds_period=2)
2280d61ffb567a6d0e55c332b0ab1e05caf01000b77Eric Caruso            self._mlog.start()
2292ea62250aa5ee9d9960c9f65a9501da6fd53ca8aTodd Broch
2300ecaa5c74b6943368ba80cedca2259931f51426aDerek Basehore        ext_path = os.path.join(os.path.dirname(__file__), 'extension')
23141acbf89080501db1b554c6919e1e0b3593585ffDerek Basehore        self._browser = chrome.Chrome(extension_paths=[ext_path],
2325cfd7fab4966bf402c4073a41707c31b26cb8c5fAchuith Bhandarkar                                gaia_login=True,
2335cfd7fab4966bf402c4073a41707c31b26cb8c5fAchuith Bhandarkar                                username=self._username,
2345cfd7fab4966bf402c4073a41707c31b26cb8c5fAchuith Bhandarkar                                password=self._password)
23541acbf89080501db1b554c6919e1e0b3593585ffDerek Basehore        extension = self._browser.get_extension(ext_path)
236fd456804cb8f90f43589f440e0a12c3a7fc7c9d4Derek Basehore        for k in params_dict:
237fd456804cb8f90f43589f440e0a12c3a7fc7c9d4Derek Basehore            if getattr(self, params_dict[k]) is not '':
238fd456804cb8f90f43589f440e0a12c3a7fc7c9d4Derek Basehore                extension.ExecuteJavaScript('var %s = %s;' %
239fd456804cb8f90f43589f440e0a12c3a7fc7c9d4Derek Basehore                                            (k, getattr(self, params_dict[k])))
2400ecaa5c74b6943368ba80cedca2259931f51426aDerek Basehore
241deac9bc81f75261120c42458da2c26e08987117fDerek Basehore        # This opens a trap start page to capture tabs opened for first login.
242deac9bc81f75261120c42458da2c26e08987117fDerek Basehore        # It will be closed when startTest is run.
243deac9bc81f75261120c42458da2c26e08987117fDerek Basehore        extension.ExecuteJavaScript('chrome.windows.create(null, null);')
244deac9bc81f75261120c42458da2c26e08987117fDerek Basehore
245417da5be901b3e68131017e1a631bdd84835b1d2Sameer Nanda        for i in range(self._loop_count):
2462ea62250aa5ee9d9960c9f65a9501da6fd53ca8aTodd Broch            start_time = time.time()
247664bad8943c04684b1181e53dc0e58d598733c55Derek Basehore            extension.ExecuteJavaScript('startTest();')
248fd4caad0dadc545b7458c16c2340fecfbfd1fe40Todd Broch            # the power test extension will report its status here
249fd4caad0dadc545b7458c16c2340fecfbfd1fe40Todd Broch            latch = self._testServer.add_wait_url('/status')
250d075074b8fc70d829912864f819345407295f35dSameer Nanda
251d075074b8fc70d829912864f819345407295f35dSameer Nanda            # reset backlight level since powerd might've modified it
252d075074b8fc70d829912864f819345407295f35dSameer Nanda            # based on ambient light
253d075074b8fc70d829912864f819345407295f35dSameer Nanda            self._set_backlight_level()
254698956153242dfb51ebdaadef4317749c7fc4be0Todd Broch            self._set_lightbar_level()
2552f156e8967fab4b4ffe38cd727aaeabf5e4080f6Todd Broch            if kblight:
2562f156e8967fab4b4ffe38cd727aaeabf5e4080f6Todd Broch                kblight.set(self._kblight_percent)
25730561af7cc67403c50ba09f5a14258e1c34e3006Hsin-Yu Chao            audio_helper.set_volume_levels(self._volume_level,
25830561af7cc67403c50ba09f5a14258e1c34e3006Hsin-Yu Chao                                           self._mic_gain)
259d075074b8fc70d829912864f819345407295f35dSameer Nanda
260417da5be901b3e68131017e1a631bdd84835b1d2Sameer Nanda            low_battery = self._do_wait(self._verbose, self._loop_time,
26106548eee3dafcf0fc9ee0dcd15eb607b901ad2c1Benson Leung                                        latch)
262417da5be901b3e68131017e1a631bdd84835b1d2Sameer Nanda
2632ea62250aa5ee9d9960c9f65a9501da6fd53ca8aTodd Broch            self._plog.checkpoint('loop%d' % (i), start_time)
264be3c3e70c41e5e28a88dad5b7062dd9baf6af091Todd Broch            self._tlog.checkpoint('loop%d' % (i), start_time)
265417da5be901b3e68131017e1a631bdd84835b1d2Sameer Nanda            if self._verbose:
266145cb75b5c33f590ddcb9421e8b3c3fbeae7117fTodd Broch                logging.debug('loop %d completed', i)
267417da5be901b3e68131017e1a631bdd84835b1d2Sameer Nanda
268417da5be901b3e68131017e1a631bdd84835b1d2Sameer Nanda            if low_battery:
269417da5be901b3e68131017e1a631bdd84835b1d2Sameer Nanda                logging.info('Exiting due to low battery')
270417da5be901b3e68131017e1a631bdd84835b1d2Sameer Nanda                break
2716a0746595cb21c52db2b4ef2e03ff1d73a75c1d0Sameer Nanda
272417da5be901b3e68131017e1a631bdd84835b1d2Sameer Nanda        t1 = time.time()
27321978453eaa14e284560915268cf9cb1b4604a48Todd Broch        self._tmp_keyvals['minutes_battery_life_tested'] = (t1 - t0) / 60
274edfd5ba0e55670be04143d919b7d559b56a9bf35Eric Caruso        if psr_t0:
275edfd5ba0e55670be04143d919b7d559b56a9bf35Eric Caruso            self._tmp_keyvals['psr_residency'] = \
276edfd5ba0e55670be04143d919b7d559b56a9bf35Eric Caruso                (self._get_psr_counter() - psr_t0) / (10 * (t1 - t0))
2776a0746595cb21c52db2b4ef2e03ff1d73a75c1d0Sameer Nanda
2786a0746595cb21c52db2b4ef2e03ff1d73a75c1d0Sameer Nanda
2796a0746595cb21c52db2b4ef2e03ff1d73a75c1d0Sameer Nanda    def postprocess_iteration(self):
28021978453eaa14e284560915268cf9cb1b4604a48Todd Broch        def _log_stats(prefix, stats):
28121978453eaa14e284560915268cf9cb1b4604a48Todd Broch            if not len(stats):
28221978453eaa14e284560915268cf9cb1b4604a48Todd Broch                return
28321978453eaa14e284560915268cf9cb1b4604a48Todd Broch            np = numpy.array(stats)
28421978453eaa14e284560915268cf9cb1b4604a48Todd Broch            logging.debug("%s samples: %d", prefix, len(np))
28521978453eaa14e284560915268cf9cb1b4604a48Todd Broch            logging.debug("%s mean:    %.2f", prefix, np.mean())
28621978453eaa14e284560915268cf9cb1b4604a48Todd Broch            logging.debug("%s stdev:   %.2f", prefix, np.std())
28721978453eaa14e284560915268cf9cb1b4604a48Todd Broch            logging.debug("%s max:     %.2f", prefix, np.max())
28821978453eaa14e284560915268cf9cb1b4604a48Todd Broch            logging.debug("%s min:     %.2f", prefix, np.min())
28921978453eaa14e284560915268cf9cb1b4604a48Todd Broch
29021978453eaa14e284560915268cf9cb1b4604a48Todd Broch
29121978453eaa14e284560915268cf9cb1b4604a48Todd Broch        def _log_per_loop_stats():
29221978453eaa14e284560915268cf9cb1b4604a48Todd Broch            samples_per_loop = self._loop_time / self._wait_time + 1
29321978453eaa14e284560915268cf9cb1b4604a48Todd Broch            for kname in self._stats:
29421978453eaa14e284560915268cf9cb1b4604a48Todd Broch                start_idx = 0
29521978453eaa14e284560915268cf9cb1b4604a48Todd Broch                loop = 1
29621978453eaa14e284560915268cf9cb1b4604a48Todd Broch                for end_idx in xrange(samples_per_loop, len(self._stats[kname]),
29721978453eaa14e284560915268cf9cb1b4604a48Todd Broch                                      samples_per_loop):
29821978453eaa14e284560915268cf9cb1b4604a48Todd Broch                    _log_stats("%s loop %d" % (kname, loop),
29921978453eaa14e284560915268cf9cb1b4604a48Todd Broch                               self._stats[kname][start_idx:end_idx])
30021978453eaa14e284560915268cf9cb1b4604a48Todd Broch                    loop += 1
30121978453eaa14e284560915268cf9cb1b4604a48Todd Broch                    start_idx = end_idx
30221978453eaa14e284560915268cf9cb1b4604a48Todd Broch
30321978453eaa14e284560915268cf9cb1b4604a48Todd Broch
30421978453eaa14e284560915268cf9cb1b4604a48Todd Broch        def _log_all_stats():
30521978453eaa14e284560915268cf9cb1b4604a48Todd Broch            for kname in self._stats:
30621978453eaa14e284560915268cf9cb1b4604a48Todd Broch                _log_stats(kname, self._stats[kname])
30721978453eaa14e284560915268cf9cb1b4604a48Todd Broch
30821978453eaa14e284560915268cf9cb1b4604a48Todd Broch
3092ea62250aa5ee9d9960c9f65a9501da6fd53ca8aTodd Broch        keyvals = self._plog.calc()
310be3c3e70c41e5e28a88dad5b7062dd9baf6af091Todd Broch        keyvals.update(self._tlog.calc())
31169324998af43b8992df694370a8536bad2da2f9cTodd Broch        keyvals.update(self._statomatic.publish())
31221978453eaa14e284560915268cf9cb1b4604a48Todd Broch
3130d61ffb567a6d0e55c332b0ab1e05caf01000b77Eric Caruso        if self._log_mem_bandwidth:
3140d61ffb567a6d0e55c332b0ab1e05caf01000b77Eric Caruso            self._mlog.stop()
3150d61ffb567a6d0e55c332b0ab1e05caf01000b77Eric Caruso            self._mlog.join()
3160d61ffb567a6d0e55c332b0ab1e05caf01000b77Eric Caruso
31721978453eaa14e284560915268cf9cb1b4604a48Todd Broch        _log_all_stats()
31821978453eaa14e284560915268cf9cb1b4604a48Todd Broch        _log_per_loop_stats()
319c4133d233aa092c4cb9d6e399baaad4eaa16d187Julius Werner
32087aced24632053d9df0a42842307abf165f60ad1Sameer Nanda        # record battery stats
32150fb54165e35caebc1bd90d409fcba0fe0b01658Sameer Nanda        keyvals['a_current_now'] = self._power_status.battery[0].current_now
3229d4bcb6d907ad23d947f65d3c764c8ee3848e7d3Sameer Nanda        keyvals['ah_charge_full'] = self._power_status.battery[0].charge_full
3236a0746595cb21c52db2b4ef2e03ff1d73a75c1d0Sameer Nanda        keyvals['ah_charge_full_design'] = \
3249d4bcb6d907ad23d947f65d3c764c8ee3848e7d3Sameer Nanda                             self._power_status.battery[0].charge_full_design
3259d4bcb6d907ad23d947f65d3c764c8ee3848e7d3Sameer Nanda        keyvals['ah_charge_start'] = self._ah_charge_start
3269d4bcb6d907ad23d947f65d3c764c8ee3848e7d3Sameer Nanda        keyvals['ah_charge_now'] = self._power_status.battery[0].charge_now
32750fb54165e35caebc1bd90d409fcba0fe0b01658Sameer Nanda        keyvals['ah_charge_used'] = keyvals['ah_charge_start'] - \
32850fb54165e35caebc1bd90d409fcba0fe0b01658Sameer Nanda                                    keyvals['ah_charge_now']
3299d4bcb6d907ad23d947f65d3c764c8ee3848e7d3Sameer Nanda        keyvals['wh_energy_start'] = self._wh_energy_start
3309d4bcb6d907ad23d947f65d3c764c8ee3848e7d3Sameer Nanda        keyvals['wh_energy_now'] = self._power_status.battery[0].energy
33150fb54165e35caebc1bd90d409fcba0fe0b01658Sameer Nanda        keyvals['wh_energy_used'] = keyvals['wh_energy_start'] - \
33250fb54165e35caebc1bd90d409fcba0fe0b01658Sameer Nanda                                    keyvals['wh_energy_now']
3336a0746595cb21c52db2b4ef2e03ff1d73a75c1d0Sameer Nanda        keyvals['v_voltage_min_design'] = \
3349d4bcb6d907ad23d947f65d3c764c8ee3848e7d3Sameer Nanda                             self._power_status.battery[0].voltage_min_design
33521978453eaa14e284560915268cf9cb1b4604a48Todd Broch        keyvals['wh_energy_full_design'] = \
33621978453eaa14e284560915268cf9cb1b4604a48Todd Broch                             self._power_status.battery[0].energy_full_design
3379d4bcb6d907ad23d947f65d3c764c8ee3848e7d3Sameer Nanda        keyvals['v_voltage_now'] = self._power_status.battery[0].voltage_now
3389d4bcb6d907ad23d947f65d3c764c8ee3848e7d3Sameer Nanda
339417da5be901b3e68131017e1a631bdd84835b1d2Sameer Nanda        keyvals.update(self._tmp_keyvals)
340417da5be901b3e68131017e1a631bdd84835b1d2Sameer Nanda
34121978453eaa14e284560915268cf9cb1b4604a48Todd Broch        keyvals['percent_sys_low_battery'] = self._sys_low_batt_p
34221978453eaa14e284560915268cf9cb1b4604a48Todd Broch        keyvals['seconds_sys_low_battery'] = self._sys_low_batt_s
34321978453eaa14e284560915268cf9cb1b4604a48Todd Broch        voltage_np = numpy.array(self._stats['v_voltage_now'])
34421978453eaa14e284560915268cf9cb1b4604a48Todd Broch        voltage_mean = voltage_np.mean()
34521978453eaa14e284560915268cf9cb1b4604a48Todd Broch        keyvals['v_voltage_mean'] = voltage_mean
3463932cc39076c41847e4b8201abb225528b4b815eTodd Broch
3472633eef2994f6d798f2c22000c006063bee1ae85Eric Caruso        keyvals['wh_energy_powerlogger'] = \
3482633eef2994f6d798f2c22000c006063bee1ae85Eric Caruso                             self._energy_use_from_powerlogger(keyvals)
3492633eef2994f6d798f2c22000c006063bee1ae85Eric Caruso
3503932cc39076c41847e4b8201abb225528b4b815eTodd Broch        if keyvals['ah_charge_used'] > 0:
35161b032031e418fece0430cf13bd84fff239ac603Eric Caruso            # For full runs, we should use charge to scale for battery life,
35261b032031e418fece0430cf13bd84fff239ac603Eric Caruso            # since the voltage swing is accounted for.
35361b032031e418fece0430cf13bd84fff239ac603Eric Caruso            # For short runs, energy will be a better estimate.
35461b032031e418fece0430cf13bd84fff239ac603Eric Caruso            if self._loop_count > 1:
35561b032031e418fece0430cf13bd84fff239ac603Eric Caruso                estimated_reps = (keyvals['ah_charge_full_design'] /
35661b032031e418fece0430cf13bd84fff239ac603Eric Caruso                                  keyvals['ah_charge_used'])
35761b032031e418fece0430cf13bd84fff239ac603Eric Caruso            else:
35861b032031e418fece0430cf13bd84fff239ac603Eric Caruso                estimated_reps = (keyvals['wh_energy_full_design'] /
35961b032031e418fece0430cf13bd84fff239ac603Eric Caruso                                  keyvals['wh_energy_powerlogger'])
36061b032031e418fece0430cf13bd84fff239ac603Eric Caruso
36161b032031e418fece0430cf13bd84fff239ac603Eric Caruso            bat_life_scale =  estimated_reps * \
3623932cc39076c41847e4b8201abb225528b4b815eTodd Broch                              ((100 - keyvals['percent_sys_low_battery']) / 100)
3633932cc39076c41847e4b8201abb225528b4b815eTodd Broch
3643932cc39076c41847e4b8201abb225528b4b815eTodd Broch            keyvals['minutes_battery_life'] = bat_life_scale * \
3653932cc39076c41847e4b8201abb225528b4b815eTodd Broch                keyvals['minutes_battery_life_tested']
3663932cc39076c41847e4b8201abb225528b4b815eTodd Broch            # In the case where sys_low_batt_s is non-zero subtract those
3673932cc39076c41847e4b8201abb225528b4b815eTodd Broch            # minutes from the final extrapolation.
3683932cc39076c41847e4b8201abb225528b4b815eTodd Broch            if self._sys_low_batt_s:
3693932cc39076c41847e4b8201abb225528b4b815eTodd Broch                keyvals['minutes_battery_life'] -= self._sys_low_batt_s / 60
3703932cc39076c41847e4b8201abb225528b4b815eTodd Broch
3713932cc39076c41847e4b8201abb225528b4b815eTodd Broch            keyvals['a_current_rate'] = keyvals['ah_charge_used'] * 60 / \
3723932cc39076c41847e4b8201abb225528b4b815eTodd Broch                                        keyvals['minutes_battery_life_tested']
3733932cc39076c41847e4b8201abb225528b4b815eTodd Broch            keyvals['w_energy_rate'] = keyvals['wh_energy_used'] * 60 / \
3743932cc39076c41847e4b8201abb225528b4b815eTodd Broch                                       keyvals['minutes_battery_life_tested']
37519b22d991c000510e91aca1b7bce6c57b9a63a15Todd Broch            self.output_perf_value(description='minutes_battery_life',
37619b22d991c000510e91aca1b7bce6c57b9a63a15Todd Broch                                   value=keyvals['minutes_battery_life'],
37719b22d991c000510e91aca1b7bce6c57b9a63a15Todd Broch                                   units='minutes')
3783932cc39076c41847e4b8201abb225528b4b815eTodd Broch
3796a0746595cb21c52db2b4ef2e03ff1d73a75c1d0Sameer Nanda        self.write_perf_keyval(keyvals)
3802ea62250aa5ee9d9960c9f65a9501da6fd53ca8aTodd Broch        self._plog.save_results(self.resultsdir)
381be3c3e70c41e5e28a88dad5b7062dd9baf6af091Todd Broch        self._tlog.save_results(self.resultsdir)
3829d4bcb6d907ad23d947f65d3c764c8ee3848e7d3Sameer Nanda
3839d4bcb6d907ad23d947f65d3c764c8ee3848e7d3Sameer Nanda
3849d4bcb6d907ad23d947f65d3c764c8ee3848e7d3Sameer Nanda    def cleanup(self):
385af5de98643110a67a9f5c323dd56be3eb1e35448Todd Broch        if self._backlight:
386af5de98643110a67a9f5c323dd56be3eb1e35448Todd Broch            self._backlight.restore()
387187240b15fe210be911c5dfc2a414d0780d9be7dTodd Broch        if self._services:
388187240b15fe210be911c5dfc2a414d0780d9be7dTodd Broch            self._services.restore_services()
389187240b15fe210be911c5dfc2a414d0780d9be7dTodd Broch
390b5056ea955d1997ce7d28441656f6134b30a1a07Dale Curtis        # cleanup backchannel interface
391f10a3198906c17a539c830e1263e6efb0a3db7b2Derek Basehore        # Prevent wifi congestion in test lab by forcing machines to forget the
392f10a3198906c17a539c830e1263e6efb0a3db7b2Derek Basehore        # wifi AP we connected to at the start of the test.
393f10a3198906c17a539c830e1263e6efb0a3db7b2Derek Basehore        if self._shill_proxy:
394f10a3198906c17a539c830e1263e6efb0a3db7b2Derek Basehore            self._shill_proxy.remove_all_wifi_entries()
395b312dcf7a07ffdfe5a9625bbb1b5b08e81158b39Jason Glasgow        if self._backchannel:
396b312dcf7a07ffdfe5a9625bbb1b5b08e81158b39Jason Glasgow            self._backchannel.teardown()
39741acbf89080501db1b554c6919e1e0b3593585ffDerek Basehore        if self._browser:
39841acbf89080501db1b554c6919e1e0b3593585ffDerek Basehore            self._browser.close()
399b7edff18c59e1caedc32f972551ec68b3620eea5Dale Curtis        if self._testServer:
400b7edff18c59e1caedc32f972551ec68b3620eea5Dale Curtis            self._testServer.stop()
4019d4bcb6d907ad23d947f65d3c764c8ee3848e7d3Sameer Nanda
4029d4bcb6d907ad23d947f65d3c764c8ee3848e7d3Sameer Nanda
4032e56d3461849c3066023f0f6e9e9060523d72d30Mike Truty    def _do_wait(self, verbose, seconds, latch):
4049d4bcb6d907ad23d947f65d3c764c8ee3848e7d3Sameer Nanda        latched = False
405417da5be901b3e68131017e1a631bdd84835b1d2Sameer Nanda        low_battery = False
40621978453eaa14e284560915268cf9cb1b4604a48Todd Broch        total_time = seconds + self._wait_time
4072e56d3461849c3066023f0f6e9e9060523d72d30Mike Truty        elapsed_time = 0
4089d4bcb6d907ad23d947f65d3c764c8ee3848e7d3Sameer Nanda
4092e56d3461849c3066023f0f6e9e9060523d72d30Mike Truty        while elapsed_time < total_time:
41021978453eaa14e284560915268cf9cb1b4604a48Todd Broch            time.sleep(self._wait_time)
41121978453eaa14e284560915268cf9cb1b4604a48Todd Broch            elapsed_time += self._wait_time
4129d4bcb6d907ad23d947f65d3c764c8ee3848e7d3Sameer Nanda
4139d4bcb6d907ad23d947f65d3c764c8ee3848e7d3Sameer Nanda            self._power_status.refresh()
41421978453eaa14e284560915268cf9cb1b4604a48Todd Broch            charge_now = self._power_status.battery[0].charge_now
41521978453eaa14e284560915268cf9cb1b4604a48Todd Broch            energy_rate = self._power_status.battery[0].energy_rate
41621978453eaa14e284560915268cf9cb1b4604a48Todd Broch            voltage_now = self._power_status.battery[0].voltage_now
41721978453eaa14e284560915268cf9cb1b4604a48Todd Broch            self._stats['w_energy_rate'].append(energy_rate)
41821978453eaa14e284560915268cf9cb1b4604a48Todd Broch            self._stats['v_voltage_now'].append(voltage_now)
419417da5be901b3e68131017e1a631bdd84835b1d2Sameer Nanda            if verbose:
42021978453eaa14e284560915268cf9cb1b4604a48Todd Broch                logging.debug('ah_charge_now %f', charge_now)
42121978453eaa14e284560915268cf9cb1b4604a48Todd Broch                logging.debug('w_energy_rate %f', energy_rate)
42221978453eaa14e284560915268cf9cb1b4604a48Todd Broch                logging.debug('v_voltage_now %f', voltage_now)
423417da5be901b3e68131017e1a631bdd84835b1d2Sameer Nanda
424cfa1ddf94edc7ac518a178415ec4a7c9a61a9dd6Todd Broch            low_battery = (self._power_status.percent_current_charge() <
42521978453eaa14e284560915268cf9cb1b4604a48Todd Broch                           self._test_low_batt_p)
426417da5be901b3e68131017e1a631bdd84835b1d2Sameer Nanda
427417da5be901b3e68131017e1a631bdd84835b1d2Sameer Nanda            latched = latch.is_set()
428417da5be901b3e68131017e1a631bdd84835b1d2Sameer Nanda
429417da5be901b3e68131017e1a631bdd84835b1d2Sameer Nanda            if latched or low_battery:
4309d4bcb6d907ad23d947f65d3c764c8ee3848e7d3Sameer Nanda                break
4319d4bcb6d907ad23d947f65d3c764c8ee3848e7d3Sameer Nanda
432417da5be901b3e68131017e1a631bdd84835b1d2Sameer Nanda        if latched:
433417da5be901b3e68131017e1a631bdd84835b1d2Sameer Nanda            # record chrome power extension stats
434417da5be901b3e68131017e1a631bdd84835b1d2Sameer Nanda            form_data = self._testServer.get_form_entries()
435417da5be901b3e68131017e1a631bdd84835b1d2Sameer Nanda            logging.debug(form_data)
436417da5be901b3e68131017e1a631bdd84835b1d2Sameer Nanda            for e in form_data:
437417da5be901b3e68131017e1a631bdd84835b1d2Sameer Nanda                key = 'ext_' + e
438417da5be901b3e68131017e1a631bdd84835b1d2Sameer Nanda                if key in self._tmp_keyvals:
439a8d49fffc08e05a5cccaa5821c84bd4ca86768a8Todd Broch                    self._tmp_keyvals[key] += "_%s" % form_data[e]
440417da5be901b3e68131017e1a631bdd84835b1d2Sameer Nanda                else:
441417da5be901b3e68131017e1a631bdd84835b1d2Sameer Nanda                    self._tmp_keyvals[key] = form_data[e]
442417da5be901b3e68131017e1a631bdd84835b1d2Sameer Nanda        else:
4439d4bcb6d907ad23d947f65d3c764c8ee3848e7d3Sameer Nanda            logging.debug("Didn't get status back from power extension")
4449d4bcb6d907ad23d947f65d3c764c8ee3848e7d3Sameer Nanda
445417da5be901b3e68131017e1a631bdd84835b1d2Sameer Nanda        return low_battery
446d075074b8fc70d829912864f819345407295f35dSameer Nanda
447d075074b8fc70d829912864f819345407295f35dSameer Nanda
448d075074b8fc70d829912864f819345407295f35dSameer Nanda    def _set_backlight_level(self):
449af5de98643110a67a9f5c323dd56be3eb1e35448Todd Broch        self._backlight.set_default()
450d075074b8fc70d829912864f819345407295f35dSameer Nanda        # record brightness level
451af5de98643110a67a9f5c323dd56be3eb1e35448Todd Broch        self._tmp_keyvals['level_backlight_current'] = \
452af5de98643110a67a9f5c323dd56be3eb1e35448Todd Broch            self._backlight.get_level()
453698956153242dfb51ebdaadef4317749c7fc4be0Todd Broch
454698956153242dfb51ebdaadef4317749c7fc4be0Todd Broch
455698956153242dfb51ebdaadef4317749c7fc4be0Todd Broch    def _set_lightbar_level(self, level='off'):
456698956153242dfb51ebdaadef4317749c7fc4be0Todd Broch        """Set lightbar level.
457698956153242dfb51ebdaadef4317749c7fc4be0Todd Broch
458698956153242dfb51ebdaadef4317749c7fc4be0Todd Broch        Args:
459698956153242dfb51ebdaadef4317749c7fc4be0Todd Broch          level: string value to set lightbar to.  See ectool for more details.
460698956153242dfb51ebdaadef4317749c7fc4be0Todd Broch        """
461698956153242dfb51ebdaadef4317749c7fc4be0Todd Broch        rv = utils.system('which ectool', ignore_status=True)
462698956153242dfb51ebdaadef4317749c7fc4be0Todd Broch        if rv:
463698956153242dfb51ebdaadef4317749c7fc4be0Todd Broch            return
464698956153242dfb51ebdaadef4317749c7fc4be0Todd Broch        rv = utils.system('ectool lightbar %s' % level, ignore_status=True)
465698956153242dfb51ebdaadef4317749c7fc4be0Todd Broch        if rv:
466698956153242dfb51ebdaadef4317749c7fc4be0Todd Broch            logging.info('Assuming no lightbar due to non-zero exit status')
467698956153242dfb51ebdaadef4317749c7fc4be0Todd Broch        else:
468698956153242dfb51ebdaadef4317749c7fc4be0Todd Broch            logging.info('Setting lightbar to %s', level)
469698956153242dfb51ebdaadef4317749c7fc4be0Todd Broch            self._tmp_keyvals['level_lightbar_current'] = level
47021978453eaa14e284560915268cf9cb1b4604a48Todd Broch
47121978453eaa14e284560915268cf9cb1b4604a48Todd Broch
47221978453eaa14e284560915268cf9cb1b4604a48Todd Broch    def _get_sys_low_batt_values(self):
47321978453eaa14e284560915268cf9cb1b4604a48Todd Broch        """Determine the low battery values for device and return.
47421978453eaa14e284560915268cf9cb1b4604a48Todd Broch
47521978453eaa14e284560915268cf9cb1b4604a48Todd Broch        2012/11/01: power manager (powerd.cc) parses parameters in filesystem
47621978453eaa14e284560915268cf9cb1b4604a48Todd Broch          and outputs a log message like:
47721978453eaa14e284560915268cf9cb1b4604a48Todd Broch
47821978453eaa14e284560915268cf9cb1b4604a48Todd Broch           [1101/173837:INFO:powerd.cc(258)] Using low battery time threshold
47921978453eaa14e284560915268cf9cb1b4604a48Todd Broch                     of 0 secs and using low battery percent threshold of 3.5
48021978453eaa14e284560915268cf9cb1b4604a48Todd Broch
48121978453eaa14e284560915268cf9cb1b4604a48Todd Broch           It currently checks to make sure that only one of these values is
48221978453eaa14e284560915268cf9cb1b4604a48Todd Broch           defined.
48321978453eaa14e284560915268cf9cb1b4604a48Todd Broch
48421978453eaa14e284560915268cf9cb1b4604a48Todd Broch        Returns:
48521978453eaa14e284560915268cf9cb1b4604a48Todd Broch          Tuple of (percent, seconds)
48621978453eaa14e284560915268cf9cb1b4604a48Todd Broch            percent: float of low battery percentage
48721978453eaa14e284560915268cf9cb1b4604a48Todd Broch            seconds: float of low battery seconds
48821978453eaa14e284560915268cf9cb1b4604a48Todd Broch
48921978453eaa14e284560915268cf9cb1b4604a48Todd Broch        """
49021978453eaa14e284560915268cf9cb1b4604a48Todd Broch        split_re = 'threshold of'
49121978453eaa14e284560915268cf9cb1b4604a48Todd Broch
49221978453eaa14e284560915268cf9cb1b4604a48Todd Broch        powerd_log = '/var/log/power_manager/powerd.LATEST'
49321978453eaa14e284560915268cf9cb1b4604a48Todd Broch        cmd = 'grep "low battery time" %s' % powerd_log
49421978453eaa14e284560915268cf9cb1b4604a48Todd Broch        line = utils.system_output(cmd)
49521978453eaa14e284560915268cf9cb1b4604a48Todd Broch        secs = float(line.split(split_re)[1].split()[0])
49621978453eaa14e284560915268cf9cb1b4604a48Todd Broch        percent = float(line.split(split_re)[2].split()[0])
49721978453eaa14e284560915268cf9cb1b4604a48Todd Broch        if secs and percent:
49821978453eaa14e284560915268cf9cb1b4604a48Todd Broch            raise error.TestError("Low battery percent and seconds " +
49921978453eaa14e284560915268cf9cb1b4604a48Todd Broch                                  "are non-zero.")
50021978453eaa14e284560915268cf9cb1b4604a48Todd Broch        return (percent, secs)
501edfd5ba0e55670be04143d919b7d559b56a9bf35Eric Caruso
5021bc91d6b5e86fe30b2c1b6bb74262c57c1ec7e35Christopher Grant
503edfd5ba0e55670be04143d919b7d559b56a9bf35Eric Caruso    def _get_psr_counter(self):
504edfd5ba0e55670be04143d919b7d559b56a9bf35Eric Caruso        """Get the current value of the system PSR counter.
505edfd5ba0e55670be04143d919b7d559b56a9bf35Eric Caruso        This counts the number of milliseconds the system has resided in PSR.
506edfd5ba0e55670be04143d919b7d559b56a9bf35Eric Caruso
507edfd5ba0e55670be04143d919b7d559b56a9bf35Eric Caruso        Returns:
508edfd5ba0e55670be04143d919b7d559b56a9bf35Eric Caruso          count: amount of time PSR has been active since boot in ms, or
509edfd5ba0e55670be04143d919b7d559b56a9bf35Eric Caruso              None if the performance counter can't be read
510edfd5ba0e55670be04143d919b7d559b56a9bf35Eric Caruso
511edfd5ba0e55670be04143d919b7d559b56a9bf35Eric Caruso        """
512edfd5ba0e55670be04143d919b7d559b56a9bf35Eric Caruso        psr_status_file = '/sys/kernel/debug/dri/0/i915_edp_psr_status'
513c2e7bbbdc18d080e2eabd90fa158404961556087Eric Caruso        try:
514c2e7bbbdc18d080e2eabd90fa158404961556087Eric Caruso            count = utils.get_field(utils.read_file(psr_status_file),
515c2e7bbbdc18d080e2eabd90fa158404961556087Eric Caruso                                    0,
516c2e7bbbdc18d080e2eabd90fa158404961556087Eric Caruso                                    linestart='Performance_Counter:')
517c2e7bbbdc18d080e2eabd90fa158404961556087Eric Caruso        except IOError:
518c2e7bbbdc18d080e2eabd90fa158404961556087Eric Caruso            logging.info("Can't find or read PSR status file")
519c2e7bbbdc18d080e2eabd90fa158404961556087Eric Caruso            return None
520c2e7bbbdc18d080e2eabd90fa158404961556087Eric Caruso
521edfd5ba0e55670be04143d919b7d559b56a9bf35Eric Caruso        logging.debug("PSR performance counter: %s", count)
522edfd5ba0e55670be04143d919b7d559b56a9bf35Eric Caruso        return int(count) if count else None
5231bc91d6b5e86fe30b2c1b6bb74262c57c1ec7e35Christopher Grant
5241bc91d6b5e86fe30b2c1b6bb74262c57c1ec7e35Christopher Grant
5251bc91d6b5e86fe30b2c1b6bb74262c57c1ec7e35Christopher Grant    def _is_network_iface_running(self, name):
5261bc91d6b5e86fe30b2c1b6bb74262c57c1ec7e35Christopher Grant        """
5271bc91d6b5e86fe30b2c1b6bb74262c57c1ec7e35Christopher Grant        Checks to see if the interface is running.
5281bc91d6b5e86fe30b2c1b6bb74262c57c1ec7e35Christopher Grant
5291bc91d6b5e86fe30b2c1b6bb74262c57c1ec7e35Christopher Grant        Args:
5301bc91d6b5e86fe30b2c1b6bb74262c57c1ec7e35Christopher Grant          name: name of the interface to check.
5311bc91d6b5e86fe30b2c1b6bb74262c57c1ec7e35Christopher Grant
5321bc91d6b5e86fe30b2c1b6bb74262c57c1ec7e35Christopher Grant        Returns:
5331bc91d6b5e86fe30b2c1b6bb74262c57c1ec7e35Christopher Grant          True if the interface is running.
5341bc91d6b5e86fe30b2c1b6bb74262c57c1ec7e35Christopher Grant
5351bc91d6b5e86fe30b2c1b6bb74262c57c1ec7e35Christopher Grant        """
5361bc91d6b5e86fe30b2c1b6bb74262c57c1ec7e35Christopher Grant        try:
5371bc91d6b5e86fe30b2c1b6bb74262c57c1ec7e35Christopher Grant            # TODO: Switch to 'ip' (crbug.com/410601).
5381bc91d6b5e86fe30b2c1b6bb74262c57c1ec7e35Christopher Grant            out = utils.system_output('ifconfig %s' % name)
5391bc91d6b5e86fe30b2c1b6bb74262c57c1ec7e35Christopher Grant        except error.CmdError, e:
5401bc91d6b5e86fe30b2c1b6bb74262c57c1ec7e35Christopher Grant            logging.info(e)
5411bc91d6b5e86fe30b2c1b6bb74262c57c1ec7e35Christopher Grant            return False
5421bc91d6b5e86fe30b2c1b6bb74262c57c1ec7e35Christopher Grant
5431bc91d6b5e86fe30b2c1b6bb74262c57c1ec7e35Christopher Grant        return out.find('RUNNING') >= 0
5442633eef2994f6d798f2c22000c006063bee1ae85Eric Caruso
5452633eef2994f6d798f2c22000c006063bee1ae85Eric Caruso
5462633eef2994f6d798f2c22000c006063bee1ae85Eric Caruso    def _energy_use_from_powerlogger(self, keyval):
5472633eef2994f6d798f2c22000c006063bee1ae85Eric Caruso        """
5482633eef2994f6d798f2c22000c006063bee1ae85Eric Caruso        Calculates the energy use, in Wh, used over the course of the run as
5492633eef2994f6d798f2c22000c006063bee1ae85Eric Caruso        reported by the PowerLogger.
5502633eef2994f6d798f2c22000c006063bee1ae85Eric Caruso
5512633eef2994f6d798f2c22000c006063bee1ae85Eric Caruso        Args:
5522633eef2994f6d798f2c22000c006063bee1ae85Eric Caruso          keyval: the dictionary of keyvals containing PowerLogger output
5532633eef2994f6d798f2c22000c006063bee1ae85Eric Caruso
5542633eef2994f6d798f2c22000c006063bee1ae85Eric Caruso        Returns:
5552633eef2994f6d798f2c22000c006063bee1ae85Eric Caruso          energy_wh: total energy used over the course of this run
5562633eef2994f6d798f2c22000c006063bee1ae85Eric Caruso
5572633eef2994f6d798f2c22000c006063bee1ae85Eric Caruso        """
5582633eef2994f6d798f2c22000c006063bee1ae85Eric Caruso        energy_wh = 0
5592633eef2994f6d798f2c22000c006063bee1ae85Eric Caruso        loop = 0
5602633eef2994f6d798f2c22000c006063bee1ae85Eric Caruso        while True:
5612633eef2994f6d798f2c22000c006063bee1ae85Eric Caruso            duration_key = 'loop%d_system_duration' % loop
5622633eef2994f6d798f2c22000c006063bee1ae85Eric Caruso            avg_power_key = 'loop%d_system_pwr' % loop
5632633eef2994f6d798f2c22000c006063bee1ae85Eric Caruso            if duration_key not in keyval or avg_power_key not in keyval:
5642633eef2994f6d798f2c22000c006063bee1ae85Eric Caruso                break
5652633eef2994f6d798f2c22000c006063bee1ae85Eric Caruso            energy_wh += keyval[duration_key] * keyval[avg_power_key] / 3600
5662633eef2994f6d798f2c22000c006063bee1ae85Eric Caruso            loop += 1
5672633eef2994f6d798f2c22000c006063bee1ae85Eric Caruso        return energy_wh
568