1# Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5import logging, re, commands
6from autotest_lib.client.bin import test, utils
7from autotest_lib.client.common_lib import error
8from autotest_lib.client.cros import power_status
9from autotest_lib.client.cros import power_utils
10
11class power_ARMSettings(test.test):
12    version = 1
13
14
15    def initialize(self):
16        self._usbpower = power_utils.USBPower()
17
18
19    def run_once(self):
20        if not self._check_cpu_type():
21            raise error.TestNAError('Unsupported CPU')
22
23        status = power_status.get_status()
24        if status.on_ac():
25            logging.info('AC Power is online')
26            self._on_ac = True
27        else:
28            logging.info('AC Power is offline')
29            self._on_ac = False
30
31        failures = ''
32
33        fail_count = self._verify_wifi_power_settings()
34        if fail_count:
35            failures += 'wifi_failures(%d) ' % fail_count
36
37        fail_count = self._verify_usb_power_settings()
38        if fail_count:
39            failures += 'usb_failures(%d) ' % fail_count
40
41        fail_count = self._verify_filesystem_power_settings()
42        if fail_count:
43            failures += 'filesystem_failures(%d) ' % fail_count
44
45
46        if failures:
47            raise error.TestFail(failures)
48
49
50    def _check_cpu_type(self):
51        cpuinfo = utils.read_file('/proc/cpuinfo')
52
53        # Look for ARM
54        match = re.search(r'ARMv[4-7]', cpuinfo)
55        if match:
56            return True
57
58        logging.info(cpuinfo)
59        return False
60
61
62    def _verify_wifi_power_settings(self):
63        if self._on_ac:
64            expected_state = 'off'
65        else:
66            expected_state = 'on'
67
68        iwconfig_out = utils.system_output('iwconfig', retain_output=True)
69        match = re.search(r'Power Management:(.*)', iwconfig_out)
70        if match and match.group(1) == expected_state:
71            return 0
72
73        logging.info(iwconfig_out)
74        return 1
75
76
77    def _verify_usb_power_settings(self):
78        errors = 0
79        self._usbpower.query_devices()
80        for dev in self._usbpower.devices:
81            # whitelist MUST autosuspend
82            autosuspend = dev.autosuspend()
83            logging.debug("USB %s:%s whitelisted:%s autosuspend:%s",
84                          dev.vid, dev.pid, dev.whitelisted, autosuspend)
85            if dev.whitelisted and not autosuspend:
86                logging.error("Whitelisted USB %s:%s "
87                              "has autosuspend disabled", dev.vid, dev.pid)
88                errors += 1
89            elif not dev.whitelisted:
90                # TODO(crbug.com/242228): Deprecate warnings once we can
91                # definitively identify preferred USB autosuspend settings
92                logging.warning("Non-Whitelisted USB %s:%s present.  "
93                                "Should it be whitelisted?", dev.vid, dev.pid)
94
95        return errors
96
97
98    def _verify_filesystem_power_settings(self):
99        mount_output = commands.getoutput('mount | fgrep commit=').split('\n')
100        if len(mount_output) == 0:
101            logging.debug('No file system entries with commit intervals found.')
102            return 1
103
104        errors = 0
105        # Parse for 'commit' param
106        for line in mount_output:
107            try:
108                commit = int(re.search(r'(commit=)([0-9]*)', line).group(2))
109            except:
110                logging.debug('Error reading commit value from \'%s\'', line)
111                errors += 1
112                continue
113
114
115            # Check for the correct commit interval.
116            if commit != 600:
117                logging.debug('File System: Incorrect commit interval %d', \
118                              commit)
119                errors += 1
120
121        return errors
122