xref: /aosp_15_r20/external/autotest/server/cros/dark_resume_utils.py (revision 9c5db1993ded3edbeafc8092d69fe5de2ee02df7)
1# Copyright 2014 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
6
7from autotest_lib.client.cros import constants
8from autotest_lib.server import autotest
9
10POWER_DIR = '/var/lib/power_manager'
11TMP_POWER_DIR = '/tmp/power_manager'
12POWER_DEFAULTS = '/usr/share/power_manager/board_specific'
13
14RESUME_CTRL_RETRIES = 3
15RESUME_GRACE_PERIOD = 10
16XMLRPC_BRINGUP_TIMEOUT_SECONDS = 60
17DARK_SUSPEND_MAX_DELAY_TIMEOUT_MILLISECONDS = 60000
18
19
20class DarkResumeUtils(object):
21    """Class containing common functionality for tests which exercise dark
22    resume pathways. We set up powerd to allow dark resume and also configure
23    the suspended devices so that the backchannel can stay up. We can also
24    check for the number of dark resumes that have happened in a particular
25    suspend request.
26    """
27
28
29    def __init__(self, host, duration=0):
30        """Set up powerd preferences so we will properly go into dark resume,
31        and still be able to communicate with the DUT.
32
33        @param host: the DUT to set up dark resume for
34
35        """
36        self._host = host
37        logging.info('Setting up dark resume preferences')
38
39        # Make temporary directory, which will be used to hold
40        # temporary preferences. We want to avoid writing into
41        # /var/lib so we don't have to save any state.
42        logging.debug('Creating temporary powerd prefs at %s', TMP_POWER_DIR)
43        host.run('mkdir -p %s' % TMP_POWER_DIR)
44
45        logging.debug('Enabling dark resume')
46        host.run('echo 0 > %s/disable_dark_resume' % TMP_POWER_DIR)
47        logging.debug('setting max dark suspend delay timeout to %d msecs',
48                  DARK_SUSPEND_MAX_DELAY_TIMEOUT_MILLISECONDS)
49        host.run('echo %d > %s/max_dark_suspend_delay_timeout_ms' %
50                 (DARK_SUSPEND_MAX_DELAY_TIMEOUT_MILLISECONDS, TMP_POWER_DIR))
51
52        # bind the tmp directory to the power preference directory
53        host.run('mount --bind %s %s' % (TMP_POWER_DIR, POWER_DIR))
54
55        logging.debug('Restarting powerd with new settings')
56        host.run('stop powerd; start powerd')
57
58        logging.debug('Starting XMLRPC session to watch for dark resumes')
59        self._client_proxy = self._get_xmlrpc_proxy()
60
61
62    def teardown(self):
63        """Clean up changes made by DarkResumeUtils."""
64
65        logging.info('Tearing down dark resume preferences')
66
67        logging.debug('Cleaning up temporary powerd bind mounts')
68        self._host.run('umount %s' % POWER_DIR)
69
70        logging.debug('Restarting powerd to revert to old settings')
71        self._host.run('stop powerd; start powerd')
72
73
74    def suspend(self, suspend_secs):
75        """ Suspends the device for |suspend_secs| without blocking for resume.
76
77        @param suspend_secs : Sleep for seconds. Sets a RTC alarm to wake the
78                              system.
79        """
80        logging.info('Suspending DUT (in background)...')
81        self._client_proxy.suspend_bg(suspend_secs)
82
83
84    def stop_resuspend_on_dark_resume(self, stop_resuspend=True):
85        """
86        If |stop_resuspend| is True, stops re-suspend on seeing a dark resume.
87        """
88        self._client_proxy.set_stop_resuspend(stop_resuspend)
89
90
91    def count_dark_resumes(self):
92        """Return the number of dark resumes since the beginning of the test.
93
94        This method will raise an error if the DUT is not reachable.
95
96        @return the number of dark resumes counted by this DarkResumeUtils
97
98        """
99        return self._client_proxy.get_dark_resume_count()
100
101
102
103    def host_has_lid(self):
104        """Returns True if the DUT has a lid."""
105        return self._client_proxy.has_lid()
106
107
108    def _get_xmlrpc_proxy(self):
109        """Get a dark resume XMLRPC proxy for the host this DarkResumeUtils is
110        attached to.
111
112        The returned object has no particular type.  Instead, when you call
113        a method on the object, it marshalls the objects passed as arguments
114        and uses them to make RPCs on the remote server.  Thus, you should
115        read dark_resume_xmlrpc_server.py to find out what methods are supported.
116
117        @return proxy object for remote XMLRPC server.
118
119        """
120        # Make sure the client library is on the device so that the proxy
121        # code is there when we try to call it.
122        client_at = autotest.Autotest(self._host)
123        client_at.install()
124        # Start up the XMLRPC proxy on the client
125        proxy = self._host.rpc_server_tracker.xmlrpc_connect(
126                constants.DARK_RESUME_XMLRPC_SERVER_COMMAND,
127                constants.DARK_RESUME_XMLRPC_SERVER_PORT,
128                command_name=
129                    constants.DARK_RESUME_XMLRPC_SERVER_CLEANUP_PATTERN,
130                ready_test_name=
131                    constants.DARK_RESUME_XMLRPC_SERVER_READY_METHOD,
132                timeout_seconds=XMLRPC_BRINGUP_TIMEOUT_SECONDS)
133        return proxy
134