xref: /aosp_15_r20/external/autotest/client/cros/service_stopper.py (revision 9c5db1993ded3edbeafc8092d69fe5de2ee02df7)
1*9c5db199SXin Li# Copyright (c) 2013 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 Li"""
6*9c5db199SXin LiProvides utility class for stopping and restarting services
7*9c5db199SXin Li
8*9c5db199SXin LiWhen using this class, one likely wishes to do the following:
9*9c5db199SXin Li
10*9c5db199SXin Li    def initialize(self):
11*9c5db199SXin Li        self._services = service_stopper.ServiceStopper(['service'])
12*9c5db199SXin Li        self._services.stop_services()
13*9c5db199SXin Li
14*9c5db199SXin Li
15*9c5db199SXin Li    def cleanup(self):
16*9c5db199SXin Li        self._services.start_services()
17*9c5db199SXin Li
18*9c5db199SXin LiAs this ensures that the services will be off before the test code runs, and
19*9c5db199SXin Lithe test framework will ensure that the services are restarted through any
20*9c5db199SXin Licode path out of the test.
21*9c5db199SXin Li"""
22*9c5db199SXin Li
23*9c5db199SXin Liimport logging
24*9c5db199SXin Liimport os
25*9c5db199SXin Li
26*9c5db199SXin Lifrom autotest_lib.client.bin import utils
27*9c5db199SXin Lifrom autotest_lib.client.cros import upstart
28*9c5db199SXin Li
29*9c5db199SXin Li
30*9c5db199SXin Liclass ServiceStopper(object):
31*9c5db199SXin Li    """Class to manage CrOS services.
32*9c5db199SXin Li    Public attributes:
33*9c5db199SXin Li      services_to_stop: list of services that should be stopped
34*9c5db199SXin Li
35*9c5db199SXin Li   Public constants:
36*9c5db199SXin Li      POWER_DRAW_SERVICES: list of services that influence power test in
37*9c5db199SXin Li    unpredictable/undesirable manners.
38*9c5db199SXin Li
39*9c5db199SXin Li    Public methods:
40*9c5db199SXin Li      stop_sevices: stop running system services.
41*9c5db199SXin Li      restore_services: restore services that were previously stopped.
42*9c5db199SXin Li
43*9c5db199SXin Li    Private attributes:
44*9c5db199SXin Li      _services_stopped: list of services that were successfully stopped
45*9c5db199SXin Li    """
46*9c5db199SXin Li
47*9c5db199SXin Li    POWER_DRAW_SERVICES = ['fwupd', 'powerd', 'update-engine', 'vnc']
48*9c5db199SXin Li
49*9c5db199SXin Li    # List of thermal throttling services that should be disabled.
50*9c5db199SXin Li    # - temp_metrics for link.
51*9c5db199SXin Li    # - thermal for daisy, snow, pit etc.
52*9c5db199SXin Li    # - dptf for intel >= baytrail
53*9c5db199SXin Li    # TODO(ihf): cpu_quiet on nyan isn't a service. We still need to disable it
54*9c5db199SXin Li    #            on nyan. See crbug.com/357457.
55*9c5db199SXin Li    THERMAL_SERVICES = ['dptf', 'temp_metrics', 'thermal']
56*9c5db199SXin Li
57*9c5db199SXin Li    def __init__(self, services_to_stop=[]):
58*9c5db199SXin Li        """Initialize instance of class.
59*9c5db199SXin Li
60*9c5db199SXin Li        By Default sets an empty list of services.
61*9c5db199SXin Li        """
62*9c5db199SXin Li        self.services_to_stop = services_to_stop
63*9c5db199SXin Li        self._services_stopped = []
64*9c5db199SXin Li
65*9c5db199SXin Li
66*9c5db199SXin Li    def stop_services(self):
67*9c5db199SXin Li        """Turn off managed services."""
68*9c5db199SXin Li
69*9c5db199SXin Li        for service in self.services_to_stop:
70*9c5db199SXin Li            if not upstart.has_service(service):
71*9c5db199SXin Li                continue
72*9c5db199SXin Li            if not upstart.is_running(service):
73*9c5db199SXin Li                continue
74*9c5db199SXin Li            upstart.stop_job(service)
75*9c5db199SXin Li            self._services_stopped.append(service)
76*9c5db199SXin Li
77*9c5db199SXin Li
78*9c5db199SXin Li    def restore_services(self):
79*9c5db199SXin Li        """Restore services that were stopped."""
80*9c5db199SXin Li        for service in reversed(self._services_stopped):
81*9c5db199SXin Li            upstart.restart_job(service)
82*9c5db199SXin Li        self._services_stopped = []
83*9c5db199SXin Li
84*9c5db199SXin Li
85*9c5db199SXin Li    def __enter__(self):
86*9c5db199SXin Li        self.stop_services()
87*9c5db199SXin Li        return self
88*9c5db199SXin Li
89*9c5db199SXin Li
90*9c5db199SXin Li    def __exit__(self, exnval, exntype, exnstack):
91*9c5db199SXin Li        self.restore_services()
92*9c5db199SXin Li
93*9c5db199SXin Li
94*9c5db199SXin Li    def close(self):
95*9c5db199SXin Li        """Equivalent to restore_services."""
96*9c5db199SXin Li        self.restore_services()
97*9c5db199SXin Li
98*9c5db199SXin Li
99*9c5db199SXin Li    def _dptf_fixup_pl1(self):
100*9c5db199SXin Li        """For intel devices that don't set their PL1 override in coreboot's
101*9c5db199SXin Li        devicetree.cb (See 'register "tdp_pl1_override') stopping DPTF will
102*9c5db199SXin Li        change the PL1 limit to the platform default.  For eve (KBL-Y) that
103*9c5db199SXin Li        would be 4.5W.  To workaround this until FW can be fixed we should
104*9c5db199SXin Li        instead query what the PL1 limit is for the proc_thermal driver and
105*9c5db199SXin Li        write it to the PL1 constraint.
106*9c5db199SXin Li
107*9c5db199SXin Li        TODO(b/144020442)
108*9c5db199SXin Li        """
109*9c5db199SXin Li        pl1_max_path = \
110*9c5db199SXin Li        '/sys/devices/pci0000:00/0000:00:04.0/power_limits/power_limit_0_max_uw'
111*9c5db199SXin Li        pl1_constraint_path = \
112*9c5db199SXin Li        '/sys/class/powercap/intel-rapl:0/constraint_0_power_limit_uw'
113*9c5db199SXin Li        if not os.path.exists(pl1_max_path):
114*9c5db199SXin Li            return
115*9c5db199SXin Li
116*9c5db199SXin Li        pl1 = int(utils.read_one_line(pl1_max_path))
117*9c5db199SXin Li        logging.debug('PL1 set to %d uw', pl1)
118*9c5db199SXin Li        utils.system('echo %d > %s' % (pl1, pl1_constraint_path))
119*9c5db199SXin Li
120*9c5db199SXin Li
121*9c5db199SXin Lidef get_thermal_service_stopper():
122*9c5db199SXin Li    """Convenience method to retrieve thermal service stopper."""
123*9c5db199SXin Li    return ServiceStopper(services_to_stop=ServiceStopper.THERMAL_SERVICES)
124