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