From 62b60fa1e1f9c9c58d012f1c8654a705d5e250cf Mon Sep 17 00:00:00 2001 From: Gonzalo Odiard Date: Fri, 27 Dec 2013 12:00:22 -0300 Subject: [PATCH] Inhibit suspend while a activity is shared In some network environments, suspend/reume can make loose messages and break collaboration. This patch inhibit suspend when collaboration start. The implementation can be used by activities or Sugar to inhibit suspend/resume when needed. More information in http://dev.laptop.org/ticket/10363 Signed-off-by: Gonzalo Odiard --- src/sugar3/Makefile.am | 1 + src/sugar3/activity/activity.py | 10 ++++ src/sugar3/power.py | 85 +++++++++++++++++++++++++++++++++ 3 files changed, 96 insertions(+) create mode 100644 src/sugar3/power.py diff --git a/src/sugar3/Makefile.am b/src/sugar3/Makefile.am index c81947b0..4742093b 100644 --- a/src/sugar3/Makefile.am +++ b/src/sugar3/Makefile.am @@ -14,6 +14,7 @@ sugar_PYTHON = \ logger.py \ mime.py \ network.py \ + power.py \ profile.py \ util.py diff --git a/src/sugar3/activity/activity.py b/src/sugar3/activity/activity.py index ead54f63..bc938b88 100644 --- a/src/sugar3/activity/activity.py +++ b/src/sugar3/activity/activity.py @@ -74,6 +74,7 @@ from telepathy.constants import CONNECTION_HANDLE_TYPE_CONTACT from telepathy.constants import CONNECTION_HANDLE_TYPE_ROOM from sugar3 import util +from sugar3 import power from sugar3.presence import presenceservice from sugar3.activity.activityservice import ActivityService from sugar3.graphics import style @@ -809,6 +810,10 @@ class Activity(Window, Gtk.Container): logging.debug('Failed to join activity: %s' % err) return + power_manager = power.get_power_manager() + if power_manager.suspend_breaks_collaboration(): + power_manager.inhibit_suspend() + self.reveal() self.emit('joined') self.__privacy_changed_cb(self.shared_activity, None) @@ -837,6 +842,10 @@ class Activity(Window, Gtk.Container): activity.props.name = self._jobject.metadata['title'] + power_manager = power.get_power_manager() + if power_manager.suspend_breaks_collaboration(): + power_manager.inhibit_suspend() + self.shared_activity = activity self.shared_activity.connect('notify::private', self.__privacy_changed_cb) @@ -953,6 +962,7 @@ class Activity(Window, Gtk.Container): dbus.service.Object.remove_from_connection(self._bus) self._session.unregister(self) + power.get_power_manager().shutdown() def close(self, skip_save=False): """Request that the activity be stopped and saved to the Journal diff --git a/src/sugar3/power.py b/src/sugar3/power.py new file mode 100644 index 00000000..b5d03628 --- /dev/null +++ b/src/sugar3/power.py @@ -0,0 +1,85 @@ +# Copyright (C) 2014, Sugarlabs +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. + +import os +import logging + +_POWERD_INHIBIT_DIR = '/var/run/powerd-inhibit-suspend' + +_power_manager = None + + +def get_power_manager(): + global _power_manager + if _power_manager is None: + _power_manager = PowerManager() + return _power_manager + + +class PowerManager(): + """ control of powerd idle suspend, + reference counted, + does nothing if powerd is not present + """ + + def __init__(self): + self._suspend_inhibit_counter = 0 + + def __del__(self): + self._remove_flag_file() + + def suspend_breaks_collaboration(self): + return True + + def inhibit_suspend(self): + if not os.path.exists(_POWERD_INHIBIT_DIR): + return + + if self._suspend_inhibit_counter == 0: + path = os.path.join(_POWERD_INHIBIT_DIR, str(os.getpid())) + try: + with open(path, 'w') as flag_file: + flag_file.write('') + except IOError: + logging.error("Inhibit Suspend: Could not create file %s", + path) + + self._suspend_inhibit_counter += 1 + + def restore_suspend(self): + self._suspend_inhibit_counter -= 1 + if self._suspend_inhibit_counter > 0: + return + self._remove_flag_file() + + def is_suspend_inhibited(self): + return self._suspend_inhibit_counter > 0 + + def shutdown(self): + """ + This method clean the flag file if exists, + is already called when the activity is closed. + """ + self._remove_flag_file() + + def _remove_flag_file(self): + path = os.path.join(_POWERD_INHIBIT_DIR, str(os.getpid())) + try: + os.unlink(path) + except IOError: + logging.error("Inhibit Suspend: Could not delete file %s", path) + self._suspend_inhibit_counter = 0