@@ -0,0 +1,6 @@
#!/bin/sh

if [ "$2" = "up" ]; then
export PATH=$PATH:/usr/sbin
olpc-connectivity &
fi
@@ -0,0 +1,2 @@
#!/bin/bash
/usr/bin/olpc-appstats &
@@ -0,0 +1,248 @@
#!/usr/bin/env python

import gtk
import wnck
import gio
import gobject

import logging
from logging.handlers import RotatingFileHandler
import time
import os


DCON_SLEEP_PATH = '/sys/devices/platform/dcon/sleep'
LOG_MAX_SIZE = 1048576

_logger = None


def _read_file(path):
if os.access(path, os.R_OK) == 0:
return None

fd = open(path, 'r')
value = fd.read()
fd.close()
if value:
value = value.strip('\n')
return value
else:
return None

def setup():
global _logger

logging_filename = None
session_type = _read_file('/home/olpc/.olpc-active-desktop')
if session_type == 'gnome':
logging_filename = os.path.join(os.path.expanduser("~"),
".olpc-gnome-stats")
else:
logging_filename = os.path.join(os.path.expanduser("~"),
".olpc-sugar-stats")

_logger = logging.Logger('appstats', level=logging.INFO)

log_handler = RotatingFileHandler(
logging_filename, maxBytes=LOG_MAX_SIZE, backupCount=0)
log_handler.setFormatter(logging.Formatter('%(message)s'))

_logger.addHandler(log_handler)


class SuspendMonitor(gobject.GObject):
__gsignals__ = {
'suspend': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])),
'resume': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])),
}

def __init__(self):
gobject.GObject.__init__(self)

self._is_suspended = False

self._monitor = gio.File(DCON_SLEEP_PATH)\
.monitor_file(gio.FILE_MONITOR_NONE, None)

self._monitor.connect('changed', self._file_changed_cb)

def _file_changed_cb(self, monitor, one_file, other_file, event):
if event != gio.FILE_MONITOR_EVENT_CHANGED:
return

with open(DCON_SLEEP_PATH) as _file:
is_suspended = bool(int(_file.read()))

if is_suspended == self._is_suspended:
return
self._is_suspended = is_suspended

if self._is_suspended:
self.emit('suspend')
else:
self.emit('resume')


class SessionLogResume():
def __init__(self, monitor):
monitor.connect('suspend', self._suspend_cb)
monitor.connect('resume', self._resume_cb)

def _suspend_cb(self, event):
self._log("SUSPEND")

def _resume_cb(self, event):
self._log("RESUME")

def _log(self, label):
with open("/home/olpc/.olpc-launch-stats", "a") as log_file:
log_file.write("{0} {1}".format(int(time.time()), label) + '\n')


class X11Sniffer(object):
def __init__(self, monitor):
self._screen = wnck.screen_get_default()
self._applications = {}
self._current_app = None
self._start_time = 0
monitor.connect('suspend', self._suspend_cb)
monitor.connect('resume', self._resume_cb)

def start(self):
self._screen.connect('window-opened', self._window_opened_cb)
self._screen.connect('window-closed', self._window_closed_cb)
self._screen.connect('active-window-changed',
self._active_window_changed_cb)

def stop(self):
self._screen.disconnect_by_func(self._window_opened_cb)
self._screen.disconnect_by_func(self._window_closed_cb)
self._screen.disconnect_by_func(self._active_window_changed_cb)

def update(self, stat_type, application=None):
current_time = time.time()
if application is None:
_logger.info("%f %s" % (current_time, stat_type))
else:
_logger.info("%f %s %r" % (current_time, stat_type, application))

def _suspend_cb(self, event):
if self._current_app is not None:
self.update("DEACTIVATE")

def _resume_cb(self, event):
if self._current_app is not None:
self.update("ACTIVATE", self._current_app)

def _window_opened_cb(self, screen, window):
if window.get_window_type() == wnck.WINDOW_DESKTOP:
return

if window.get_window_type() != wnck.WINDOW_NORMAL or \
_get_x11_property(window, '_SUGAR_WINDOW_TYPE') == 'launcher':
return

app = window.get_application()
application = self._applications.get(app)
if application is None:
application = _Application(window, app)
self._applications[app] = application

def _window_closed_cb(self, screen, window):
if window.get_window_type() == wnck.WINDOW_DESKTOP:
return

if window.get_window_type() != wnck.WINDOW_NORMAL or \
_get_x11_property(window, '_SUGAR_WINDOW_TYPE') == 'launcher':
return

wnck_app = None
cur_application = None
xid = window.get_xid()
for app, application in self._applications.items():
if xid == application.window_xid:
wnck_app = app
cur_application = application
break

if cur_application is not None:
if not wnck_app.get_windows():
del self._applications[wnck_app]

def _active_window_changed_cb(self, screen, previous_window=None):
window = screen.get_active_window()
if window is None:
return

if window.get_window_type() != wnck.WINDOW_DIALOG:
while window.get_transient() is not None:
window = window.get_transient()

app = window.get_application()
application = self._applications.get(app)

def deactivate():
return (self._current_app is not None and
(application is None or
application.app_name == 'nautilus'))

if deactivate():
self._current_app = None
self.update("DEACTIVATE")

if application is not None:
if application.window_xid is None:
application.window_xid = window.get_xid()

if application.app_name == 'nautilus':
return

if application != self._current_app:
self._current_app = application
self.update("ACTIVATE", application)


class _Application(object):
def __init__(self, window, app):
self.app = app
self.app_name = self._get_app_name(window, app)
self.window_xid = None

def _get_app_name(self, window, app):
activity_id = _get_x11_property(window, '_SUGAR_ACTIVITY_ID')
if activity_id:
bundle_id = _get_x11_property(window, '_SUGAR_BUNDLE_ID')
return bundle_id
else:
return app.get_name()

def __repr__(self):
return "{0} {1}".format(self.window_xid, self.app_name)


def _get_x11_property(window, prop):
gdk_window = gtk.gdk.window_foreign_new(window.get_xid())

# There is a chance to get X error
gtk.gdk.error_trap_push()
prop_info = gdk_window.property_get(prop, 'STRING')
gtk.gdk.error_trap_pop()

if prop_info is None:
return None
else:
return prop_info[2]


def main():
setup()
monitor = SuspendMonitor()
session_log_resume = SessionLogResume(monitor)
sniffer = X11Sniffer(monitor)
sniffer.start()

gtk.main()

if __name__ == '__main__':
main()
@@ -160,7 +160,10 @@ cat /proc/uptime >$HOME/.boot_time
if [ "$desktop" = "sugar" ]
then
## Sugar

printf '%(%s)T START_SUGAR\n' -1 >> $HOME/.olpc-launch-stats

printf '%(%s)T START_SUGAR\n' -1 >> $HOME/.olpc-sugar-stats

## If .rfkill_block_wifi exists, ensure it is blocked
## (we may have unblocked it for gnome) #10532
[ -e $HOME/.rfkill_block_wifi ] && /sbin/rfkill block wifi
@@ -169,6 +172,10 @@ then
cchmod 0755 $HOME/Activities
else
## Non-Sugar Desktop
printf '%(%s)T START_GNOME\n' -1 >> $HOME/.olpc-launch-stats

printf '%(%s)T START_GNOME\n' -1 >> $HOME/.olpc-gnome-stats


## GNOME should be able to switch on wifi #10532
if [ -e $HOME/.rfkill_block_wifi ]; then
@@ -201,4 +208,4 @@ else
string:display.dcon_freeze int32:0 &
fi

exec $desktop
exec $desktop
@@ -0,0 +1,67 @@
#!/usr/bin/env python
#
# Copyright (C) 2009 One Laptop per Child
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA


import sys
import os
import os.path
import subprocess
import gettext
import time

from gi.repository import Gtk

_ = lambda msg: gettext.dgettext('olpc-switch-desktop', msg)

def do_switch():
with open("/home/olpc/.olpc-launch-stats", "a") as log_file:
log_file.write("{0} END".format(int(time.time())) + '\n')
try:
fd = open(os.path.join(os.environ['HOME'], ".olpc-active-desktop"), "w")
fd.write("sugar")
fd.close()
except Exception, e:
print "Error:", e
dlg = Gtk.MessageDialog(None, 0, Gtk.MessageType.ERROR,
Gtk.ButtonsType.OK, _("Could not switch desktop: an internal "
"error has occurred."))
dlg.run()
dlg.destroy()
return
subprocess.call(['dbus-send','--session','--dest=org.gnome.SessionManager',
'/org/gnome/SessionManager','org.gnome.SessionManager.Logout',
'uint32:1'])

def main():
dlg = Gtk.MessageDialog(None, 0, Gtk.MessageType.INFO,
Gtk.ButtonsType.OK_CANCEL, _("Click OK to switch to the Sugar "
"learning environment.\nAll active applications will be closed."))
dlg.set_title(_("Switch desktop"))
dlg.set_property("skip-taskbar-hint", False)

icon_theme = Gtk.IconTheme.get_default()
pixbuf = icon_theme.load_icon("olpc-switch-to-sugar", 48, 0)
dlg.set_icon(pixbuf)

resp = dlg.run()
dlg.destroy()
if resp == Gtk.ResponseType.OK:
do_switch()

if __name__ == "__main__":
main()
@@ -0,0 +1,11 @@
[Unit]
Description=Log date and time before shutdown for statistics
Before=systemd-poweroff.service systemd-reboot.service systemd-halt.service
DefaultDependencies=no

[Service]
ExecStart=/usr/sbin/olpc-log-shutdown
Type=oneshot

[Install]
WantedBy=poweroff.target halt.target reboot.target