예제 #1
0
    def cleanup(self):
        """Autotest cleanup function

        It is run by common_lib/test.py.
        """
        if self._backlight:
            self._backlight.restore()
        if self._service_stopper:
            self._service_stopper.restore_services()
        if self._original_governors:
            utils.restore_scaling_governor_states(self._original_governors)
        if self._use_ec:
            power_utils.charge_control_by_ectool(is_charge=True)
        super(video_JDAPerf, self).cleanup()
예제 #2
0
    def cleanup(self):
        if self._force_discharge:
            power_utils.charge_control_by_ectool(True)
        if self._backlight:
            self._backlight.restore()
        if self._services:
            self._services.restore_services()
        self._detachable_handler.restore()

        # cleanup backchannel interface
        # Prevent wifi congestion in test lab by forcing machines to forget the
        # wifi AP we connected to at the start of the test.
        if self._shill_proxy:
            self._shill_proxy.remove_all_wifi_entries()
        if self._backchannel:
            self._backchannel.teardown()
        if self._browser:
            self._browser.close()
        if self._testServer:
            self._testServer.stop()
예제 #3
0
    def test_power(self):
        """
        Runs the video power consumption test.

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

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

        self._power_status = power_status.get_status()

        self._use_ec = True
        if not power_utils.charge_control_by_ectool(is_charge=False):
            logging.warning('Can\'t stop charging')
            return {}

        if not self._power_status.battery:
            raise error.TestFail('No valid battery')

        # Verify that the battery is sufficiently charged.
        percent_initial_charge = self._power_status.percent_current_charge()
        if percent_initial_charge < BATTERY_INITIAL_CHARGED_MIN:
            logging.warning(
                'Initial charge (%f) less than min (%f)',
                (percent_initial_charge, BATTERY_INITIAL_CHARGED_MIN))
            return {}

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

        def get_power():
            power_logger = power_status.PowerLogger(measurements)
            power_logger.start()
            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_avg']

        return self.test_decode(get_power)
    def run_once(self,
                 test_hours=None,
                 sample_hours=None,
                 max_milliwatts_standby=500,
                 ac_ok=False,
                 force_discharge=False,
                 suspend_state='',
                 bypass_check=False):
        """Put DUT to suspend state for |sample_hours| and measure power."""
        if not power_utils.has_battery():
            raise error.TestNAError(
                'Skipping test because DUT has no battery.')

        if test_hours < sample_hours:
            raise error.TestFail('Test hours must be greater than sample '
                                 'hours.')

        # If we're measuring < 6min of standby then the S0 time is not
        # negligible. Note, reasonable rule of thumb is S0 idle is ~10-20 times
        # standby power.
        if sample_hours < self._min_sample_hours and not bypass_check:
            raise error.TestFail('Must standby more than %.2f hours.' % \
                                 sample_hours)

        power_stats = power_status.get_status()

        if not ac_ok and power_stats.on_ac():
            raise error.TestError('On AC, please unplug power supply.')

        if force_discharge:
            if not power_stats.on_ac():
                raise error.TestError('Not on AC, please plug in power supply '
                                      'to attempt force discharge.')
            if not power_utils.charge_control_by_ectool(False):
                raise error.TestError('Unable to force discharge.')

            self._force_discharge_enabled = True

        charge_start = power_stats.battery[0].charge_now
        voltage_start = power_stats.battery[0].voltage_now

        max_hours = ((charge_start * voltage_start) /
                     (max_milliwatts_standby / 1000.))
        if max_hours < test_hours:
            raise error.TestFail('Battery not charged adequately for test.')

        suspender = power_suspend.Suspender(self.resultsdir,
                                            suspend_state=suspend_state)

        elapsed_hours = 0

        results = {}
        loop = 0
        start_ts = time.time()

        while elapsed_hours < test_hours:
            charge_before = power_stats.battery[0].charge_now
            before_suspend_secs = rtc.get_seconds()
            suspender.suspend(duration=sample_hours * 3600)
            after_suspend_secs = rtc.get_seconds()

            power_stats.refresh()
            if power_stats.percent_current_charge() < self._percent_min_charge:
                logging.warning('Battery = %.2f%%.  Too low to continue.')
                break

            # check that the RTC slept the correct amount of time as there could
            # potentially be another wake source that would spoil the test.
            actual_hours = (after_suspend_secs - before_suspend_secs) / 3600.0
            percent_diff = math.fabs((actual_hours - sample_hours) /
                                     ((actual_hours + sample_hours) / 2) * 100)
            if percent_diff > 2 and not bypass_check:
                err = 'Requested standby time and actual varied by %.2f%%.' \
                    % percent_diff
                raise error.TestFail(err)

            # Check resulting charge consumption
            charge_used = charge_before - power_stats.battery[0].charge_now
            elapsed_hours += actual_hours
            logging.debug(
                'loop%d done: loop hours %.3f, elapsed hours %.3f '
                'charge used: %.3f', loop, actual_hours, elapsed_hours,
                charge_used)
            loop += 1

        end_ts = time.time()
        offset = (end_ts - start_ts - elapsed_hours * 3600) / 2.
        offset += suspender.get_suspend_delay()
        start_ts += offset
        end_ts -= offset
        power_telemetry_utils.start_measurement(start_ts)
        power_telemetry_utils.end_measurement(end_ts)
        self._checkpoint_logger.checkpoint(self.tagged_testname, start_ts,
                                           end_ts)
        charge_end = power_stats.battery[0].charge_now
        total_charge_used = charge_start - charge_end
        if total_charge_used <= 0 and not bypass_check:
            raise error.TestError('Charge used is suspect.')

        voltage_end = power_stats.battery[0].voltage_now
        standby_hours = power_stats.battery[0].charge_full_design / \
                        total_charge_used * elapsed_hours
        energy_used = (voltage_start + voltage_end) / 2 * \
                      total_charge_used

        results['ah_charge_start'] = charge_start
        results['ah_charge_now'] = charge_end
        results['ah_charge_used'] = total_charge_used
        results['force_discharge'] = self._force_discharge_enabled
        results['hours_standby_time'] = standby_hours
        results['hours_standby_time_tested'] = elapsed_hours
        results['v_voltage_start'] = voltage_start
        results['v_voltage_now'] = voltage_end
        results['w_energy_rate'] = energy_used / elapsed_hours
        results['wh_energy_used'] = energy_used

        self.write_perf_keyval(results)
        pdash = power_dashboard.SimplePowerLoggerDashboard(
            end_ts - start_ts,
            results['w_energy_rate'],
            self.tagged_testname,
            start_ts,
            self.resultsdir,
            note=self._pdash_note)
        pdash.upload()
        self._checkpoint_logger.save_checkpoint_data(self.resultsdir)

        self.output_perf_value(description='hours_standby_time',
                               value=results['hours_standby_time'],
                               units='hours',
                               higher_is_better=True)
        self.output_perf_value(description='w_energy_rate',
                               value=results['w_energy_rate'],
                               units='watts',
                               higher_is_better=False)

        # need to sleep for some time to allow network connection to return
        time.sleep(10)
 def cleanup(self):
     """Clean up force discharge."""
     if self._force_discharge_enabled:
         power_utils.charge_control_by_ectool(True)
예제 #6
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=None,
                 force_discharge=False, pdash_note=''):
        """
        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: whether real GAIA login should be attempted.  If 'None'
            (default) then boolean is determined from URL.
        force_discharge: boolean of whether to tell ec to discharge battery even
            when the charger is plugged in.
        pdash_note: note of the current run to send to power dashboard.
        """
        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._force_discharge = force_discharge
        self._pdash_note = pdash_note

        if not power_utils.has_battery():
            if ac_ok and (power_utils.has_powercap_support() or
                          power_utils.has_rapl_support()):
                logging.info("Device has no battery but has powercap data.")
            else:
                rsp = "Skipping test for device without battery and powercap."
                raise error.TestNAError(rsp)
        self._power_status = power_status.get_status()
        self._tmp_keyvals['b_on_ac'] = self._power_status.on_ac()

        self._gaia_login = gaia_login
        if gaia_login is None:
            self._gaia_login = power_load_util.use_gaia_login()

        self._username = power_load_util.get_username()
        self._password = power_load_util.get_password()

        if not ac_ok:
            self._power_status.assert_battery_state(percent_initial_charge_min)

        if force_discharge:
            if not power_utils.charge_control_by_ectool(False):
                raise error.TestError('Could not run battery force discharge.')

        # 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.
            ifaces = [ iface for iface in interface.get_interfaces()
                if (not iface.is_wifi_device() and
                    iface.name.startswith('eth')) ]
            logging.debug(str([iface.name for iface in ifaces]))
            for iface in ifaces:
                if check_network and iface.is_lower_up:
                    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()

        self._detachable_handler = power_utils.BaseActivitySimulator()

        # 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()
        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'))

        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

        if self._power_status.battery:
            self._ah_charge_start = self._power_status.battery[0].charge_now
            self._wh_energy_start = self._power_status.battery[0].energy