Home | History | Annotate | Download | only in cros
      1 # Copyright 2015 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 
      5 import logging
      6 import threading
      7 
      8 import dbus
      9 import dbus.mainloop.glib
     10 import gobject
     11 
     12 from autotest_lib.client.cros import upstart
     13 
     14 class DarkResumeListener(object):
     15     """Server which listens for dark resume-related DBus signals to count how
     16     many dark resumes we have seen since instantiation."""
     17 
     18     SIGNAL_NAME = 'DarkSuspendImminent'
     19 
     20 
     21     def __init__(self):
     22         dbus.mainloop.glib.threads_init()
     23         gobject.threads_init()
     24 
     25         dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
     26         self._bus = dbus.SystemBus()
     27         self._count = 0
     28         self._stop_resuspend = False
     29 
     30         self._bus.add_signal_receiver(handler_function=self._saw_dark_resume,
     31                                       signal_name=self.SIGNAL_NAME)
     32 
     33         def loop_runner():
     34             """Handles DBus events on the system bus using the mainloop."""
     35             # If we just call run on this loop, the listener will hang and the test
     36             # will never finish. Instead, we process events as they come in. This
     37             # thread is set to daemon below, which means that the program will exit
     38             # when the main thread exits.
     39             loop = gobject.MainLoop()
     40             context = loop.get_context()
     41             while True:
     42                 context.iteration(True)
     43         thread = threading.Thread(None, loop_runner)
     44         thread.daemon = True
     45         thread.start()
     46         logging.debug('Dark resume listener started')
     47 
     48 
     49     @property
     50     def count(self):
     51         """Number of DarkSuspendImminent events this listener has seen since its
     52         creation."""
     53         return self._count
     54 
     55 
     56     def _saw_dark_resume(self, unused):
     57         self._count += 1
     58         if self._stop_resuspend:
     59             # Restart powerd to stop re-suspend.
     60             upstart.restart_job('powerd')
     61 
     62 
     63     def stop_resuspend(self, should_stop):
     64         """
     65         Whether to stop suspend after seeing a dark resume.
     66 
     67         @param should_stop: Whether to stop system from re-suspending.
     68         """
     69         self._stop_resuspend = should_stop
     70 
     71