Esempio n. 1
0
    def postprocess_iteration(self):
        keyvals = self._stats.publish()

        # record the current and max backlight levels
        self._backlight = power_utils.Backlight()
        keyvals['level_backlight_max'] = self._backlight.get_max_level()
        keyvals['level_backlight_current'] = self._backlight.get_level()

        # record battery stats if not on AC
        if self.status.on_ac():
            keyvals['b_on_ac'] = 1
        else:
            keyvals['b_on_ac'] = 0
            keyvals['ah_charge_full'] = self.status.battery[0].charge_full
            keyvals['ah_charge_full_design'] = \
                                self.status.battery[0].charge_full_design
            keyvals['ah_charge_now'] = self.status.battery[0].charge_now
            keyvals['a_current_now'] = self.status.battery[0].current_now
            keyvals['wh_energy'] = self.status.battery[0].energy
            keyvals['w_energy_rate'] = self.status.battery[0].energy_rate
            keyvals['h_remaining_time'] = self.status.battery[0].remaining_time
            keyvals['v_voltage_min_design'] = \
                                self.status.battery[0].voltage_min_design
            keyvals['v_voltage_now'] = self.status.battery[0].voltage_now
            keyvals.update(self._plog.calc())

        keyvals.update(self._tlog.calc())
        keyvals.update(self._psr.get_keyvals())
        logging.debug("keyvals = %s", keyvals)

        self.write_perf_keyval(keyvals)
Esempio n. 2
0
    def test_power(self, local_path):
        """
        Runs the video power consumption test.

        @param local_path: the path to the video file.

        @return a dictionary that contains the test result.
        """

        self._backlight = power_utils.Backlight()
        self._backlight.set_default()

        self._service_stopper = service_stopper.ServiceStopper(
                service_stopper.ServiceStopper.POWER_DRAW_SERVICES)
        self._service_stopper.stop_services()

        self._power_status = power_status.get_status()
        # Verify that we are running on battery and the battery is sufficiently
        # charged.
        self._power_status.assert_battery_state(BATTERY_INITIAL_CHARGED_MIN)

        measurements = [power_status.SystemPower(
                self._power_status.battery_path)]

        def get_power(cr):
            power_logger = power_status.PowerLogger(measurements)
            power_logger.start()
            time.sleep(STABILIZATION_DURATION)
            start_time = time.time()
            time.sleep(MEASUREMENT_DURATION)
            power_logger.checkpoint('result', start_time)
            keyval = power_logger.calc()
            return keyval['result_' + measurements[0].domain + '_pwr']

        return self.test_playback(local_path, get_power)
Esempio n. 3
0
    def run_once(self, idle_time=120, sleep=10):
        with chrome.Chrome():
            self._backlight = power_utils.Backlight()
            self._backlight.set_default()

            t0 = time.time()
            self._start_time = t0
            self._psr = power_utils.DisplayPanelSelfRefresh(init_time=t0)
            self.status = power_status.get_status()
            self._stats = power_status.StatoMatic()

            measurements = []
            if not self.status.on_ac():
                measurements.append(
                    power_status.SystemPower(self.status.battery_path))
            if power_utils.has_rapl_support():
                measurements += power_rapl.create_rapl()
            self._plog = power_status.PowerLogger(measurements,
                                                  seconds_period=sleep)
            self._tlog = power_status.TempLogger([], seconds_period=sleep)
            self._plog.start()
            self._tlog.start()

            for _ in xrange(0, idle_time, sleep):
                time.sleep(sleep)
                self.status.refresh()
            self.status.refresh()
            self._plog.checkpoint('', self._start_time)
            self._tlog.checkpoint('', self._start_time)
            self._psr.refresh()
Esempio n. 4
0
 def initialize(self, **kwargs):
     """Set up local variables and ensure device is on AC power."""
     self._initialize_test_constants()
     self._power_status = power_status.get_status()
     if not self._power_status.on_ac():
         raise error.TestNAError('Test must be run with DUT on AC power.')
     self._backlight = power_utils.Backlight()
     super(policy_PowerManagementIdleSettings, self).initialize(**kwargs)
Esempio n. 5
0
    def run_once(self, run_time_sec=60):
        """
        @param run_time_sec: time to run the test
        """
        if run_time_sec < 30:
            raise error.TestError('Must run for at least 30 seconds')

        with chrome.Chrome(init_network_controller=True) as cr:
            # Start powerd if not started.  Set timeouts for quick idle events.
            run_time_ms = run_time_sec * 1000
            # At the time of writing this test, the video detector gets a status
            # update from Chrome every ten seconds.
            dim_ms = 10000
            off_ms = max(3600000, run_time_ms * 10)
            prefs = {
                'has_ambient_light_sensor': 0,
                'ignore_external_policy': 1,
                'plugged_dim_ms': dim_ms,
                'plugged_off_ms': off_ms,
                'unplugged_dim_ms': dim_ms,
                'unplugged_off_ms': off_ms,
            }
            self._pref_change = power_utils.PowerPrefChanger(prefs)

            keyvals = {}

            # Start with max brightness, so we can easily detect dimming.
            power_utils.BacklightController().set_brightness_to_max()
            backlight = power_utils.Backlight()
            initial_brightness = \
                base_utils.wait_for_value(backlight.get_max_level)

            # Open a tab to play video.
            cr.browser.platform.SetHTTPServerDirectories(self.bindir)
            tab = cr.browser.tabs[0]
            tab.Navigate(
                cr.browser.platform.http_server.UrlOf(
                    os.path.join(self.bindir, 'fade.html')))
            tab.WaitForDocumentReadyStateToBeComplete()

            # Sleep until the runtime is up.
            time.sleep(run_time_sec)

            # Stop powerd to avoid dimming when the video stops.
            utils.system_output('stop powerd')

            final_brightness = backlight.get_level()

            # Check that the backlight stayed the same.
            if initial_brightness != final_brightness:
                raise error.TestFail(
                    ('Backlight level changed from %d to %d when it should ' + \
                     'have stayed the same.') %
                    (initial_brightness, final_brightness))

            keyvals['initial_brightness'] = initial_brightness
            keyvals['final_brightness'] = final_brightness
            self.write_perf_keyval(keyvals)
    def run_once(self):
        # optionally test keyboard backlight
        kblight = None
        kblight_errs = 0
        try:
            kblight = power_utils.KbdBacklight()
        except power_utils.KbdBacklightException as e:
            logging.info("Assuming no keyboard backlight due to %s", str(e))

        if kblight:
            init_percent = kblight.get_percent()
            try:
                for i in xrange(100, -1, -1):
                    kblight.set_percent(i)
                    result = int(kblight.get_percent())
                    if i != result:
                        logging.error('keyboard backlight set %d != %d get', i,
                                      result)
                        kblight_errs += 1
            finally:
                kblight.set_percent(init_percent)

        if kblight_errs:
            raise error.TestFail("%d errors testing keyboard backlight." % \
                                 kblight_errs)

        self._backlight = power_utils.Backlight()
        backlight_errs = 0
        backlight_max = self._backlight.get_max_level()
        for i in xrange(backlight_max + 1):
            self._backlight.set_level(i)
            result = self._backlight.get_level()
            if i != result:
                # The kernel Documentation/ABI/stable/sysfs-class-backlight
                # states that the requested brightness may not be the
                # actual_brightness.
                # Although not specified in the docs, let's allow the difference
                # between requested brightness and actual_brightness percent be
                # within a tolerance of 1 of each other.
                actual_percent = self._backlight.get_percent()
                expected_percent = float(i) / float(backlight_max) * 100.0
                diff_percent = abs(actual_percent - expected_percent)
                log_level_func = logging.warn
                if diff_percent > 1:
                    backlight_errs += 1
                    log_level_func = logging.error
                    log_level_func(
                        'backlight expected vs. actual exceeds error'
                        'tolerance')
                log_level_func('backlight set %d != %d get', i, result)
                log_level_func('backlight percent difference is %f%%',
                               diff_percent)

        if backlight_errs:
            raise error.TestFail("%d errors testing backlight." % \
                                 backlight_errs)
    def __enter__(self):
        self._backlight = power_utils.Backlight()
        self._backlight.set_default()

        self._service_stopper = service_stopper.ServiceStopper(
                service_stopper.ServiceStopper.POWER_DRAW_SERVICES)
        self._service_stopper.stop_services()

        status = power_status.get_status()

        # Verify that we are running on battery and the battery is sufficiently
        # charged.
        status.assert_battery_state(BATTERY_INITIAL_CHARGED_MIN)
        self._system_power = power_status.SystemPower(status.battery_path)
        self._power_logger = power_status.PowerLogger([self._system_power])
        return self
    def run_power_test(self, browser, test_url, ac_ok):
        """Runs the webgl power consumption test and reports the perf results.

        @param browser: The Browser object to run the test with.
        @param test_url: The URL to the aquarium test site.
        @param ac_ok: Boolean on whether its ok to have AC power supplied.
        """

        self._backlight = power_utils.Backlight()
        self._backlight.set_default()

        self._service_stopper = service_stopper.ServiceStopper(
            service_stopper.ServiceStopper.POWER_DRAW_SERVICES)
        self._service_stopper.stop_services()

        if not ac_ok:
            self._power_status = power_status.get_status()
            # Verify that we are running on battery and the battery is
            # sufficiently charged.
            self._power_status.assert_battery_state(
                BATTERY_INITIAL_CHARGED_MIN)

            measurements = [
                power_status.SystemPower(self._power_status.battery_path)
            ]

        def get_power():
            power_logger = power_status.PowerLogger(measurements)
            power_logger.start()
            time.sleep(STABILIZATION_DURATION)
            start_time = time.time()
            time.sleep(MEASUREMENT_DURATION)
            power_logger.checkpoint('result', start_time)
            keyval = power_logger.calc()
            logging.info('Power output %s', keyval)
            return keyval['result_' + measurements[0].domain + '_pwr']

        self.run_fish_test(browser, test_url, 1000, perf_log=False)
        if not ac_ok:
            energy_rate = get_power()
            # This is a power specific test so we are not capturing
            # avg_fps and avg_render_time in this test.
            self.perf_keyval[POWER_DESCRIPTION] = energy_rate
            self.output_perf_value(description=POWER_DESCRIPTION,
                                   value=energy_rate,
                                   units='W',
                                   higher_is_better=False)
    def run_power_test(self, audio_type):
        """
        Captures power usage and reports it to the perf dashboard.

        @param audio_type: audio format label to attach with perf keyval.
        """

        self._backlight = power_utils.Backlight()
        self._backlight.set_default()

        self._service_stopper = service_stopper.ServiceStopper(
            service_stopper.ServiceStopper.POWER_DRAW_SERVICES)
        self._service_stopper.stop_services()

        self._power_status = power_status.get_status()
        # Verify that we are running on battery and the battery is sufficiently
        # charged.
        self._power_status.assert_battery_state(BATTERY_INITIAL_CHARGED_MIN)

        measurements = [
            power_status.SystemPower(self._power_status.battery_path)
        ]

        def get_power():
            power_logger = power_status.PowerLogger(measurements)
            power_logger.start()
            time.sleep(STABILIZATION_DURATION)
            start_time = time.time()
            time.sleep(MEASUREMENT_DURATION)
            power_logger.checkpoint('result', start_time)
            keyval = power_logger.calc()
            logging.info('Power output %s', keyval)
            return keyval['result_' + measurements[0].domain + '_pwr']

        energy_rate = get_power()
        perf_keyval = {}
        perf_keyval[POWER_DESCRIPTION + audio_type] = energy_rate
        self.output_perf_value(description=POWER_DESCRIPTION + audio_type,
                               value=energy_rate,
                               units='W',
                               higher_is_better=False)
        self.write_perf_keyval(perf_keyval)
Esempio n. 10
0
    def test_power(self, local_path):
        """
        Runs the video power consumption test.

        @param local_path: the path to the video file.

        @return a dictionary that contains the test result.
        """

        self._backlight = power_utils.Backlight()
        self._backlight.set_default()

        self._service_stopper = service_stopper.ServiceStopper(
                service_stopper.ServiceStopper.POWER_DRAW_SERVICES)
        self._service_stopper.stop_services()

        self._power_status = power_status.get_status()
        # We expect the DUT is powered by battery now. But this is not always
        # true due to other bugs. Disable this test temporarily as workaround.
        # TODO(kcwu): remove this workaround after AC control is stable
        #             crbug.com/723968
        if self._power_status.on_ac():
            logging.warning('Still powered by AC. Skip this test')
            return {}
        # Verify that the battery is sufficiently charged.
        self._power_status.assert_battery_state(BATTERY_INITIAL_CHARGED_MIN)

        measurements = [power_status.SystemPower(
                self._power_status.battery_path)]

        def get_power(cr):
            power_logger = power_status.PowerLogger(measurements)
            power_logger.start()
            time.sleep(STABILIZATION_DURATION)
            start_time = time.time()
            time.sleep(MEASUREMENT_DURATION)
            power_logger.checkpoint('result', start_time)
            keyval = power_logger.calc()
            return keyval['result_' + measurements[0].domain + '_pwr']

        return self.test_playback(local_path, get_power)
    def run_once(self, delay=60, seconds=10, tries=20):
        self._backlight = power_utils.Backlight()

        # disable screen blanking. Stopping screen-locker isn't
        # synchronous :(. Add a sleep for now, till powerd comes around
        # and fixes all this for us.
        # TODO(davidjames): Power manager should support this feature directly
        time.sleep(5)
        graphics_utils.screen_disable_blanking()

        status = power_status.get_status()
        status.assert_battery_state(5)

        max_brightness = self._backlight.get_max_level()
        if max_brightness < 4:
            raise error.TestFail('Must have at least 5 backlight levels')
        sysfs_max = self._get_highest_sysfs_max_brightness()
        if max_brightness != sysfs_max:
            raise error.TestFail(('Max brightness %d is not the highest ' +
                                  'possible |max_brightness|, which is %d') %
                                 (max_brightness, sysfs_max))
        keyvals = {}
        rates = []

        levels = [0, 50, 100]
        for i in levels:
            self._backlight.set_percent(i)
            time.sleep(delay)
            this_rate = []
            for _ in range(tries):
                time.sleep(seconds)
                status.refresh()
                this_rate.append(status.battery[0].energy_rate)
            rate = min(this_rate)
            keyvals['w_bl_%d_rate' % i] = rate
            rates.append(rate)
        self.write_perf_keyval(keyvals)
        for i in range(1, len(levels)):
            if rates[i] <= rates[i - 1]:
                raise error.TestFail('Turning up the backlight ' \
                                     'should increase energy consumption')
Esempio n. 12
0
    def run_once(self, resume_percent=70):
        results = {}
        backlight = power_utils.Backlight()

        results['initial_brightness'] = backlight.get_level()
        max_level = backlight.get_max_level()
        resume_level = int(round(max_level * resume_percent / 100))

        # If the current brightness is the same as the requested brightness,
        # request 100 - |resume_brightness| instead.
        if resume_level == results['initial_brightness']:
            resume_level = max_level - resume_level
        backlight.set_resume_level(resume_level)

        sys_power.kernel_suspend(seconds=5)

        final_level = backlight.get_level()
        if final_level != resume_level:
            raise error.TestFail(
                ('Brightness level after resume did not match requested ' + \
                 'brightness: %d vs %d') % (final_level, resume_level))

        results['resume_brightness'] = resume_level
        self.write_perf_keyval(results)
Esempio n. 13
0
    def run_once(self):
        # Require that this test be run on battery with at least 5% charge
        status = power_status.get_status()
        status.assert_battery_state(5)

        prefs = {
            'has_ambient_light_sensor': 0,
            'ignore_external_policy': 1,
            'plugged_dim_ms': 7200000,
            'plugged_off_ms': 9000000,
            'plugged_suspend_ms': 18000000,
            'unplugged_dim_ms': 7200000,
            'unplugged_off_ms': 9000000,
            'unplugged_suspend_ms': 18000000
        }
        self._pref_change = power_utils.PowerPrefChanger(prefs)

        keyvals = {}
        num_errors = 0

        # These are the expected ratios of energy rate between max, min, and off
        # (zero) brightness levels.  e.g. when changing from max to min, the
        # energy rate must become <= (max_energy_rate * max_to_min_factor).
        max_to_min_factor = \
            1.0 - self._energy_rate_change_threshold_percent / 100.0
        min_to_off_factor = \
            1.0 - self._energy_rate_change_threshold_percent / 100.0
        off_to_max_factor = 1.0 / (max_to_min_factor * min_to_off_factor)

        # Determine the number of outputs that are on.
        starting_num_outputs_on = get_num_outputs_on()
        if starting_num_outputs_on == 0:
            raise error.TestFail('At least one display output must be on.')
        keyvals['starting_num_outputs_on'] = starting_num_outputs_on

        self._backlight = power_utils.Backlight()
        keyvals['max_brightness'] = self._backlight.get_max_level()
        if keyvals['max_brightness'] <= self._min_num_steps:
            raise error.TestFail('Must have at least %d backlight levels' %
                                 (self._min_num_steps + 1))

        keyvals['initial_brightness'] = self._backlight.get_level()

        self._wait_for_stable_energy_rate()
        keyvals['initial_power_w'] = self._get_current_energy_rate()

        self._backlight_controller = power_utils.BacklightController()
        self._backlight_controller.set_brightness_to_max()

        current_brightness = \
            utils.wait_for_value(self._backlight.get_level,
                                 max_threshold=keyvals['max_brightness'])
        if current_brightness != keyvals['max_brightness']:
            num_errors += 1
            logging.error(('Failed to increase brightness to max, ' + \
                           'brightness is %d.') % current_brightness)
        else:
            self._wait_for_stable_energy_rate()
            keyvals['max_brightness_power_w'] = self._get_current_energy_rate()

        # Set brightness to minimum without going to zero.
        # Note that we don't know what the minimum brightness is, so just set
        # min_threshold=0 to use the timeout to wait for the brightness to
        # settle.
        self._backlight_controller.set_brightness_to_min()
        current_brightness = utils.wait_for_value(
            self._backlight.get_level,
            min_threshold=(keyvals['max_brightness'] / 2 - 1))
        if current_brightness >= keyvals['max_brightness'] / 2 or \
           current_brightness == 0:
            num_errors += 1
            logging.error('Brightness is not at minimum non-zero level: %d' %
                          current_brightness)
        else:
            self._wait_for_stable_energy_rate()
            keyvals['min_brightness_power_w'] = self._get_current_energy_rate()

        # Turn off the screen by decreasing brightness one more time with
        # allow_off=True.
        self._backlight_controller.decrease_brightness(True)
        current_brightness = utils.wait_for_value(self._backlight.get_level,
                                                  min_threshold=0)
        if current_brightness != 0:
            num_errors += 1
            logging.error('Brightness is %d, expecting 0.' %
                          current_brightness)

        # Wait for screen to turn off.
        num_outputs_on = utils.wait_for_value(
            get_num_outputs_on, min_threshold=(starting_num_outputs_on - 1))
        keyvals['outputs_on_after_screen_off'] = num_outputs_on
        if num_outputs_on >= starting_num_outputs_on:
            num_errors += 1
            logging.error('At least one display must have been turned off. ' + \
                          'Number of displays on: %s' % num_outputs_on)
        else:
            self._wait_for_stable_energy_rate()
            keyvals['screen_off_power_w'] = self._get_current_energy_rate()

        # Set brightness to max.
        self._backlight_controller.set_brightness_to_max()
        current_brightness = utils.wait_for_value(
            self._backlight.get_level, max_threshold=keyvals['max_brightness'])
        if current_brightness != keyvals['max_brightness']:
            num_errors += 1
            logging.error(('Failed to increase brightness to max, ' + \
                           'brightness is %d.') % current_brightness)

        # Verify that the same number of outputs are on as before.
        num_outputs_on = get_num_outputs_on()
        keyvals['outputs_on_at_end'] = num_outputs_on
        if num_outputs_on != starting_num_outputs_on:
            num_errors += 1
            logging.error(('Number of displays turned on should be same as ' + \
                           'at start.  Number of displays on: %s') %
                          num_outputs_on)

        self._wait_for_stable_energy_rate()
        keyvals['final_power_w'] = self._get_current_energy_rate()

        # Energy rate must have changed significantly between transitions.
        if 'max_brightness_power_w' in keyvals and \
           'min_brightness_power_w' in keyvals and \
           keyvals['min_brightness_power_w'] >= \
               keyvals['max_brightness_power_w'] * max_to_min_factor:
            num_errors += 1
            logging.error('Power draw did not decrease enough when ' + \
                          'brightness was decreased from max to min.')

        if 'screen_off_power_w' in keyvals and \
           'min_brightness_power_w' in keyvals and \
           keyvals['screen_off_power_w'] >= \
               keyvals['min_brightness_power_w'] * min_to_off_factor:
            num_errors += 1
            logging.error('Power draw did not decrease enough when screen ' + \
                          'was turned off.')

        if num_outputs_on == starting_num_outputs_on and \
           'screen_off_power_w' in keyvals and \
           keyvals['final_power_w'] <= \
               keyvals['screen_off_power_w'] * off_to_max_factor:
            num_errors += 1
            logging.error('Power draw did not increase enough after ' + \
                          'turning screen on.')

        self.write_perf_keyval(keyvals)

        if num_errors > 0:
            raise error.TestFail('Test failed with %d errors' % num_errors)
    def run_once(self, short=False, test_groups=None, reps=1):
        # Some sub-tests have duration specified directly, _base_secs * reps
        # is used in this case. Others complete whenever the underlying task
        # completes, those are manually tuned to be roughly around
        # reps * 30 seconds. Don't change _base_secs unless you also
        # change the manual tuning in sub-tests
        self._base_secs = 30
        self._repeats = reps
        self._duration_secs = self._base_secs * reps

        # Lists of default tests to run
        UI_TESTS = ['backlight', 'download', 'webpages', 'video', 'v8']
        NONUI_TESTS = ['backchannel', 'sound', 'lowlevel']
        DEFAULT_TESTS = UI_TESTS + NONUI_TESTS
        DEFAULT_SHORT_TESTS = ['download', 'webpages', 'video']

        self.short = short
        if test_groups is None:
            if self.short:
                test_groups = DEFAULT_SHORT_TESTS
            else:
                test_groups = DEFAULT_TESTS
        logging.info('Test groups to run: %s', ', '.join(test_groups))

        self._backlight = power_utils.Backlight()
        self._backlight.set_default()

        measurements = \
            [power_status.SystemPower(self._power_status.battery_path)]
        if power_utils.has_rapl_support():
            measurements += power_rapl.create_rapl()
        self._plog = power_status.PowerLogger(measurements)
        self._plog.start()

        # Log in.
        with chrome.Chrome() as cr:
            self._browser = cr.browser
            graphics_utils.screen_disable_energy_saving()
            # Most of the tests will be running in this tab.
            self._tab = cr.browser.tabs[0]

            # Verify that we have a functioning browser and local web server.
            self._tab.Activate()
            self._web_echo("Sanity_test")
            self._tab.WaitForDocumentReadyStateToBeComplete()

            # Video test must have the data from download test
            if ('video' in test_groups):
                iv = test_groups.index('video')
                if 'download' not in test_groups[:iv]:
                    msg = '"download" test must run before "video".'
                    raise error.TestError(msg)

            # Run all the test groups
            self._run_test_groups(test_groups)

        # Wrap up
        keyvals = self._plog.calc()
        keyvals.update(self._tmp_keyvals)

        # Calculate expected battery life time with ChromeVer power draw
        idle_name = 'ChromeVer_system_pwr'
        if idle_name in keyvals:
            hours_life = self.energy_full_design / keyvals[idle_name]
            keyvals['hours_battery_ChromeVer'] = hours_life

        # Calculate a weighted power draw and battery life time. The weights
        # are intended to represent "typical" usage. Some video, some Flash ...
        # and most of the time idle.
        # see http://www.chromium.org/chromium-os/testing/power-testing
        weights = {
            'vid400p_h264_system_pwr': 0.1,
            # TODO(chromium:309403) re-enable BallsFlex once Flash in
            # test-lab understood and re-distribute back to 60/20/10/10.
            # 'BallsFlex_system_pwr':0.1,
            'BallsDHTML_system_pwr': 0.3,
        }
        weights[idle_name] = 1 - sum(weights.values())

        if set(weights).issubset(set(keyvals)):
            p = sum(w * keyvals[k] for (k, w) in weights.items())
            keyvals['w_Weighted_system_pwr'] = p
            keyvals['hours_battery_Weighted'] = self.energy_full_design / p

        self.write_perf_keyval(keyvals)
        self._plog.save_results(self.resultsdir)
Esempio n. 15
0
    def initialize(self,
                   percent_initial_charge_min=None,
                   check_network=True,
                   loop_time=3600,
                   loop_count=1,
                   should_scroll='true',
                   should_scroll_up='true',
                   scroll_loop='false',
                   scroll_interval_ms='10000',
                   scroll_by_pixels='600',
                   test_low_batt_p=3,
                   verbose=True,
                   force_wifi=False,
                   wifi_ap='',
                   wifi_sec='none',
                   wifi_pw='',
                   wifi_timeout=60,
                   tasks='',
                   volume_level=10,
                   mic_gain=10,
                   low_batt_margin_p=2,
                   ac_ok=False,
                   log_mem_bandwidth=False,
                   gaia_login=True):
        """
        percent_initial_charge_min: min battery charge at start of test
        check_network: check that Ethernet interface is not running
        loop_time: length of time to run the test for in each loop
        loop_count: number of times to loop the test for
        should_scroll: should the extension scroll pages
        should_scroll_up: should scroll in up direction
        scroll_loop: continue scrolling indefinitely
        scroll_interval_ms: how often to scoll
        scroll_by_pixels: number of pixels to scroll each time
        test_low_batt_p: percent battery at which test should stop
        verbose: add more logging information
        force_wifi: should we force to test to run on wifi
        wifi_ap: the name (ssid) of the wifi access point
        wifi_sec: the type of security for the wifi ap
        wifi_pw: password for the wifi ap
        wifi_timeout: The timeout for wifi configuration
        volume_level: percent audio volume level
        mic_gain: percent audio microphone gain level
        low_batt_margin_p: percent low battery margin to be added to
            sys_low_batt_p to guarantee test completes prior to powerd shutdown
        ac_ok: boolean to allow running on AC
        log_mem_bandwidth: boolean to log memory bandwidth during the test
        gaia_login: boolean of whether real GAIA login should be attempted.
        """
        self._backlight = None
        self._services = None
        self._browser = None
        self._loop_time = loop_time
        self._loop_count = loop_count
        self._mseconds = self._loop_time * 1000
        self._verbose = verbose

        self._sys_low_batt_p = 0.
        self._sys_low_batt_s = 0.
        self._test_low_batt_p = test_low_batt_p
        self._should_scroll = should_scroll
        self._should_scroll_up = should_scroll_up
        self._scroll_loop = scroll_loop
        self._scroll_interval_ms = scroll_interval_ms
        self._scroll_by_pixels = scroll_by_pixels
        self._tmp_keyvals = {}
        self._power_status = None
        self._force_wifi = force_wifi
        self._testServer = None
        self._tasks = tasks.replace(' ', '')
        self._backchannel = None
        self._shill_proxy = None
        self._volume_level = volume_level
        self._mic_gain = mic_gain
        self._ac_ok = ac_ok
        self._log_mem_bandwidth = log_mem_bandwidth
        self._wait_time = 60
        self._stats = collections.defaultdict(list)
        self._gaia_login = gaia_login

        if not power_utils.has_battery():
            rsp = "Device designed without battery. Skipping test."
            raise error.TestNAError(rsp)
        self._power_status = power_status.get_status()
        self._tmp_keyvals['b_on_ac'] = self._power_status.on_ac()

        with tempfile.NamedTemporaryFile() as pltp:
            file_utils.download_file(self._pltp_url, pltp.name)
            self._password = pltp.read().rstrip()

        if not ac_ok:
            self._power_status.assert_battery_state(percent_initial_charge_min)
        # If force wifi enabled, convert eth0 to backchannel and connect to the
        # specified WiFi AP.
        if self._force_wifi:
            sec_config = None
            # TODO(dbasehore): Fix this when we get a better way of figuring out
            # the wifi security configuration.
            if wifi_sec == 'rsn' or wifi_sec == 'wpa':
                sec_config = xmlrpc_security_types.WPAConfig(
                    psk=wifi_pw,
                    wpa_mode=xmlrpc_security_types.WPAConfig.MODE_PURE_WPA2,
                    wpa2_ciphers=[xmlrpc_security_types.WPAConfig.CIPHER_CCMP])
            wifi_config = xmlrpc_datatypes.AssociationParameters(
                ssid=wifi_ap,
                security_config=sec_config,
                configuration_timeout=wifi_timeout)
            # If backchannel is already running, don't run it again.
            self._backchannel = backchannel.Backchannel()
            if not self._backchannel.setup():
                raise error.TestError('Could not setup Backchannel network.')

            self._shill_proxy = wifi_proxy.WifiProxy()
            self._shill_proxy.remove_all_wifi_entries()
            for i in xrange(1, 4):
                raw_output = self._shill_proxy.connect_to_wifi_network(
                    wifi_config.ssid,
                    wifi_config.security,
                    wifi_config.security_parameters,
                    wifi_config.save_credentials,
                    station_type=wifi_config.station_type,
                    hidden_network=wifi_config.is_hidden,
                    discovery_timeout_seconds=wifi_config.discovery_timeout,
                    association_timeout_seconds=wifi_config.
                    association_timeout,
                    configuration_timeout_seconds=wifi_config.
                    configuration_timeout * i)
                result = xmlrpc_datatypes.AssociationResult. \
                        from_dbus_proxy_output(raw_output)
                if result.success:
                    break
                logging.warn(
                    'wifi connect: disc:%d assoc:%d config:%d fail:%s',
                    result.discovery_time, result.association_time,
                    result.configuration_time, result.failure_reason)
            else:
                raise error.TestError('Could not connect to WiFi network.')

        else:
            # Find all wired ethernet interfaces.
            # TODO: combine this with code in network_DisableInterface, in a
            # common library somewhere.
            ifaces = [
                nic.strip() for nic in os.listdir('/sys/class/net/')
                if ((not os.path.exists('/sys/class/net/' + nic + '/phy80211'))
                    and nic.find('eth') != -1)
            ]
            logging.debug(str(ifaces))
            for iface in ifaces:
                if check_network and self._is_network_iface_running(iface):
                    raise error.TestError('Ethernet interface is active. ' +
                                          'Please remove Ethernet cable')

        # record the max backlight level
        self._backlight = power_utils.Backlight()
        self._tmp_keyvals['level_backlight_max'] = \
            self._backlight.get_max_level()

        self._services = service_stopper.ServiceStopper(
            service_stopper.ServiceStopper.POWER_DRAW_SERVICES)
        self._services.stop_services()

        # fix up file perms for the power test extension so that chrome
        # can access it
        os.system('chmod -R 755 %s' % self.bindir)

        # setup a HTTP Server to listen for status updates from the power
        # test extension
        self._testServer = httpd.HTTPListener(8001, docroot=self.bindir)
        self._testServer.run()

        # initialize various interesting power related stats
        self._statomatic = power_status.StatoMatic()

        self._power_status.refresh()
        help_output = utils.system_output('check_powerd_config --help')
        if 'low_battery_shutdown' in help_output:
            logging.info('Have low_battery_shutdown option')
            self._sys_low_batt_p = float(
                utils.system_output(
                    'check_powerd_config --low_battery_shutdown_percent'))
            self._sys_low_batt_s = int(
                utils.system_output(
                    'check_powerd_config --low_battery_shutdown_time'))
        else:
            # TODO(dchan) Once M57 in stable, remove this option and function.
            logging.info('No low_battery_shutdown option')
            (self._sys_low_batt_p, self._sys_low_batt_s) = \
                self._get_sys_low_batt_values_from_log()

        if self._sys_low_batt_p and self._sys_low_batt_s:
            raise error.TestError(
                "Low battery percent and seconds are non-zero.")

        min_low_batt_p = min(self._sys_low_batt_p + low_batt_margin_p, 100)
        if self._sys_low_batt_p and (min_low_batt_p > self._test_low_batt_p):
            logging.warning(
                "test low battery threshold is below system " +
                "low battery requirement.  Setting to %f", min_low_batt_p)
            self._test_low_batt_p = min_low_batt_p

        self._ah_charge_start = self._power_status.battery[0].charge_now
        self._wh_energy_start = self._power_status.battery[0].energy
    def run_once(self, max_run_time=180, percent_charge_to_add=1,
                 percent_initial_charge_max=None,
                 percent_target_charge=None,
                 use_design_charge_capacity=True):

        """
        max_run_time: maximum time the test will run for
        percent_charge_to_add: percentage of the charge capacity charge to
                  add. The target charge will be capped at the charge capacity.
        percent_initial_charge_max: maxium allowed initial charge.
        use_design_charge_capacity: If set, use charge_full_design rather than
                  charge_full for calculations. charge_full represents
                  wear-state of battery, vs charge_full_design representing
                  ideal design state.
        """

        time_to_sleep = 60

        self._backlight = power_utils.Backlight()
        self._backlight.set_percent(0)

        self.remaining_time = self.max_run_time = max_run_time

        self.charge_full_design = self.status.battery[0].charge_full_design
        self.charge_full = self.status.battery[0].charge_full
        if use_design_charge_capacity:
            self.charge_capacity = self.charge_full_design
        else:
            self.charge_capacity = self.charge_full

        if self.charge_capacity == 0:
            raise error.TestError('Failed to determine charge capacity')

        self.initial_charge = self.status.battery[0].charge_now
        percent_initial_charge = self.initial_charge * 100 / \
                                 self.charge_capacity
        if percent_initial_charge_max and percent_initial_charge > \
                                          percent_initial_charge_max:
            raise error.TestError('Initial charge (%f) higher than max (%f)'
                      % (percent_initial_charge, percent_initial_charge_max))

        current_charge = self.initial_charge
        if percent_target_charge is None:
            charge_to_add = self.charge_capacity * \
                            float(percent_charge_to_add) / 100
            target_charge = current_charge + charge_to_add
        else:
            target_charge = self.charge_capacity * \
                            float(percent_target_charge) / 100

        # trim target_charge if it exceeds charge capacity
        if target_charge > self.charge_capacity:
            target_charge = self.charge_capacity

        logging.info('max_run_time: %d', self.max_run_time)
        logging.info('initial_charge: %f', self.initial_charge)
        logging.info('target_charge: %f', target_charge)

        while self.remaining_time and current_charge < target_charge:
            if time_to_sleep > self.remaining_time:
                time_to_sleep = self.remaining_time
            self.remaining_time -= time_to_sleep

            time.sleep(time_to_sleep)

            self.status.refresh()
            if not self.status.on_ac():
                raise error.TestError(
                      'This test needs to be run with the AC power online')

            new_charge = self.status.battery[0].charge_now
            logging.info('time_to_sleep: %d', time_to_sleep)
            logging.info('charge_added: %f', (new_charge - current_charge))

            current_charge = new_charge
            logging.info('current_charge: %f', current_charge)

            if self.status.battery[0].status == 'Full':
                logging.info('Battery full, aborting!')
                break