1# Lint as: python2, python3
2# Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6import logging
7
8from autotest_lib.client.common_lib import error
9from autotest_lib.server import autotest, test
10
11
12# TODO(b/163372205): Some models before unibuild have ambient light sensors
13# only on certain skus. However, has_ambient_light_sensor powerd pref has to
14# be set for all skus. For these models, skip checking the existence of ambient
15# light sensors against has_ambient_light_sensor powerd pref.
16IGNORE_ALS_PREF_MODELS = ['caroline']
17
18class power_BrightnessResetAfterReboot(test.test):
19    """Verifies that the panel brightness level resets after device reboots.
20    """
21    version = 2
22
23    def run_once(self, host, client_autotest):
24        """This test verifies that the panel brightness level resets after
25           device reboots.
26        """
27        if host.has_internal_display() is None:
28            raise error.TestNAError('Device has no internal display.')
29        autotest_client = autotest.Autotest(host)
30        host.reboot()
31        autotest_client.run_test(client_autotest,
32                                 exit_without_logout=True)
33
34        cmd = 'check_powerd_config --ambient_light_sensor'
35        num_als_pref = int(host.run_output(cmd, ignore_status=True))
36
37        cmd = 'backlight_tool --get_ambient_light_lux'
38        result = host.run(cmd, ignore_status=True)
39        als_exists = not result.exit_status # 0 is cmd success.
40
41        if num_als_pref and not als_exists:
42            model = host.get_platform()
43            msg = ('Powerd pref indicates %d ambient light sensor(s) but device '
44                   'is unable to find it (them).' % num_als_pref)
45            if model in IGNORE_ALS_PREF_MODELS:
46                logging.info('%s However, skip this check for model: %s.',
47                             msg, model)
48            else:
49                raise error.TestFail(msg)
50
51        initial_lux = -1
52        if als_exists:
53            initial_lux = int(result.stdout.rstrip())
54            lux_domain = [initial_lux / 2, initial_lux * 2]
55            brightness_range = \
56                    [get_backlight(host, lux) for lux in lux_domain]
57        else:
58            brightness_range = [10.0, 90.0]
59
60        initial_brightness = get_backlight(host)
61        if (initial_brightness < brightness_range[0] or
62                initial_brightness > brightness_range[1]):
63            raise error.TestFail('Default brightness level is out of scope '
64                                 '(%d%% - %d%%): %f' % (brightness_range[0],
65                                                        brightness_range[1],
66                                                        initial_brightness))
67
68        brightness_min = 0.0
69        if (not set_backlight(host, brightness_min) or
70                get_backlight(host) != brightness_min):
71            raise error.TestFail('Unable to change the brightness to minimum '
72                                 '(%f%%) level.' % brightness_min)
73
74        brightness_max = 100.0
75        if (not set_backlight(host, brightness_max) or
76                get_backlight(host) != brightness_max):
77            raise error.TestFail('Unable to change the brightness to maximum '
78                                 '(%f%%) level.' % brightness_max)
79
80        host.reboot()
81        autotest_client.run_test(client_autotest,
82                                 exit_without_logout=True)
83        brightness_after_reboot = get_backlight(host)
84        if not als_exists and initial_brightness == brightness_after_reboot:
85            return
86        # If there is an ambient light sensor, allow a small change in internal
87        # display brightness, in case that the ambient light changes slightly.
88        if als_exists:
89            cushion = 0.2
90            lux_domain_after_reboot = [(1.0 - cushion) * initial_lux,
91                                       (1.0 + cushion) * initial_lux]
92            brightness_range_after_reboot = [get_backlight(host, lux) for lux
93                                             in lux_domain_after_reboot]
94            if (brightness_range_after_reboot[0] <=
95                    brightness_after_reboot <=
96                    brightness_range_after_reboot[1]):
97                return
98
99        raise error.TestFail('Unable to reset internal display brightness back '
100                             'to default after reboot.\n'
101                             'Previous boot default brightness: %f\n'
102                             'Current boot default brightness: %f' %
103                             (initial_brightness, brightness_after_reboot))
104
105
106def set_backlight(host, percentage):
107    """Executes backlight_tool to set internal display backlight.
108       @param host: host object representing the DUT.
109       @param percentage: linear percentage to set internal display
110                          backlight to.
111    """
112    cmd = 'backlight_tool --set_brightness_percent=%f' % percentage
113    try:
114        exit_status = host.run(cmd).exit_status
115    except error.CmdError:
116        raise error.TestFail(cmd)
117    return not exit_status # 0 is cmd success.
118
119def get_backlight(host, lux=-1):
120    """Executes backlight_tool to get internal display backlight.
121       @param host: host object representing the DUT.
122    """
123    cmd = 'backlight_tool --get_brightness_percent'
124    if lux >= 0:
125        cmd = '%s --lux=%d' % (cmd, lux)
126    try:
127        result = host.run_output(cmd)
128    except error.CmdError:
129        raise error.TestFail(cmd)
130    return float(result)
131