This file is indexed.

/usr/lib/python2.7/dist-packages/framework/resource.py is in fso-frameworkd 0.10.1-3.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
# -*- coding: UTF-8 -*-
"""
freesmartphone.org Framework Daemon

(C) 2008 Guillaume 'Charlie' Chereau <charlie@openmoko.org>
(C) 2008-2009 Michael 'Mickey' Lauer <mlauer@vanille-media.de>
(C) 2008 Jan 'Shoragan' Lübbe <jluebbe@lasnet.de>
(C) 2008 Openmoko, Inc.
GPLv2 or later

Package: framework
Module: resource
"""

MODULE_NAME = "frameworkd.resource"
__version__ = "0.5.3"

from framework.config import config
from framework.patterns import decorator, asyncworker, dbuscache
from framework.helpers import exceptionlogger

import gobject
import dbus.service
from dbus import validate_interface_name, Signature, validate_member_name

import Queue

import logging
logger = logging.getLogger( MODULE_NAME )

#----------------------------------------------------------------------------#
@decorator.decorator
def checkedmethod(f, *args, **kw):
    """
    This decorator wraps an asynchronous dbus method to checks the resource status and returning
    org.freesmartphone.Resource.ResourceNotEnabled if the resource is not enabled.
    """
    #print "calling %s with args %s, %s" % (f.func_name, args, kw)
    self = args[0]
    dbus_error = args[-1]
    if self._resourceStatus == "enabled":
        return f(*args, **kw)
    else:
        dbus_error( ResourceNotEnabled( "Resource %s is not enabled, current status is '%s'" % ( self.__class__.__name__, self._resourceStatus ) ) )

#----------------------------------------------------------------------------#
@decorator.decorator
def checkedsyncmethod(f, *args, **kw):
    """
    This decorator wraps a synchronous dbus method to checks the resource status and returning
    org.freesmartphone.Resource.ResourceNotEnabled if the resource is not enabled.
    """
    #print "calling %s with args %s, %s" % (f.func_name, args, kw)
    self = args[0]
    if self._resourceStatus == "enabled":
        return f(*args, **kw)
    else:
        raise ResourceNotEnabled( "Resource %s is not enabled, current status is '%s'" % ( self.__class__.__name__, self._resourceStatus ) )

#----------------------------------------------------------------------------#
@decorator.decorator
def queuedsignal(f, *args, **kw):
    """
    This decorator wraps a dbus signal and sends it only if the resource is enabled.
    Otherwise, it enqueues the signal.
    """
    #print "calling %s with args %s, %s" % (f.func_name, args, kw)
    self = args[0]
    if self._resourceStatus == "enabled":
        return f(*args, **kw)
    else:
        self._delayedSignalQueue.put( ( f, args ) ) # push for later

#----------------------------------------------------------------------------#
@decorator.decorator
def checkedsignal(f, *args, **kw):
    """
    This decorator wraps a dbus signal and sends it only if the resource is enabled.
    Otherwise, it drops the signal.
    """
    #print "calling %s with args %s, %s" % (f.func_name, args, kw)
    self = args[0]
    if self._resourceStatus == "enabled":
        return f(*args, **kw)
    else:
        logger.info( "Dropping signal %s, since resource %s is not enabled. Current status is '%s'" % ( f.__name__, self.__class__.__name__, self._resourceStatus ) )

#----------------------------------------------------------------------------#
class ResourceNotEnabled( dbus.DBusException ):
#----------------------------------------------------------------------------#
    _dbus_error_name = "org.freesmartphone.Resource.NotEnabled"

#----------------------------------------------------------------------------#
class ResourceError( dbus.DBusException ):
#----------------------------------------------------------------------------#
    _dbus_error_name = "org.freesmartphone.Resource.Error"

#----------------------------------------------------------------------------#
class Resource( dbus.service.Object, asyncworker.SynchronizedAsyncWorker ):
#----------------------------------------------------------------------------#
    """
    Base class for all the resources

    The Resource class is used for anything that need to know about who is
    using a given resource. The OUsaged subsystem manage all the resources and keep
    track of how many clients are using them. When a resource is no longer used,
    its Disable method will be called by ousaged. The resource object can then do
    whatever is needed. When a resource is disabled and a client need to use it,
    ousaged will call its Enable method.

    A resource also needs to be able to prepare for a system suspend, or resume
    OUsaged will call the Suspend and Resume methods of the resource before a
    system suspend and after a system wakeup.

    To define a new resource, a subsystem needs to subclass this class,
    and call the register method once after initialisation.
    """
    DBUS_INTERFACE = 'org.freesmartphone.Resource'

    sync_resources_with_lifecycle = config.getValue( "ousaged", "sync_resources_with_lifecycle", "always" )

    commandInProgress = { \
        "enable":   "enabling",
        "disable":  "disabling",
        "suspend":  "suspending",
        "resume":   "resuming",
        }

    commandDone = { \
        "enable":   "enabled",
        "disable":  "disabled",
        "suspend":  "suspended",
        "resume":   "enabled",
        }

    def __init__( self, bus, name ):
        """
        Register the object as a new resource in ousaged

        bus: dbus session bus
        name: the name of the resource that will be used by the clients
        """
        # HACK HACK HACK: We do _not_ initialize the dbus service object here,
        # (in order to prevent initializing it twice), but rather rely on someone
        # else doing this for us.
        if not isinstance( self, dbus.service.Object ):
            raise RuntimeError( "Resource only allowed as mixin w/ dbus.service.Object" )
        self._resourceBus = bus
        self._resourceName = name
        self._resourceStatus = "unknown"
        self._delayedSignalQueue = Queue.Queue()

        asyncworker.SynchronizedAsyncWorker.__init__( self )

        # We need to call the ousaged.Register method, but we can't do it
        # immediatly for the ousaged object may not be present yet.
        # We use gobject.idle_add method to make the call only at the next
        # mainloop iteration
        def on_idle( self=self ):
            logger.debug( "Trying to register resource %s", self._resourceName )

            try:
                usaged = self._resourceBus.get_object( "org.freesmartphone.ousaged", "/org/freesmartphone/Usage" )
                usageiface = dbus.Interface( usaged, "org.freesmartphone.Usage" )
            except dbus.exceptions.DBusException:
                logger.warning( "Can't register resource %s since ousaged is not present. Enabling device", name )
                gobject.idle_add( self.Enable, lambda: False, lambda dummy: False )
            else:
                def on_reply( self=self ):
                    logger.debug( "%s is now a registered resource", self._resourceName )

                def on_error( err, self=self ):
                    logger.error( "%s can't be registered (%s). Enabling", self._resourceName, err )
                    gobject.idle_add( self.Enable, lambda: False, lambda dummy: False )


                #usageiface = dbuscache.dbusInterfaceForObjectWithInterface(
                    #"org.freesmartphone.ousaged",
                    #"/org/freesmartphone/Usage",
                    #"org.freesmartphone.Usage" )

                #usageiface.RegisterResource( self._resourceName, self, reply_handler=on_reply, error_handler=on_error )
                usageiface.RegisterResource( self._resourceName, self, reply_handler=on_reply, error_handler=on_error )

            return False # mainloop: don't call me again

        gobject.idle_add( on_idle )

    @exceptionlogger
    def onProcessElement( self, element ):
        command, ok_callback, err_callback = element
        logger.debug( "processing command '%s' for resource '%s' (present status=%s)", command, self, self._resourceStatus )

        stateNow = self._resourceStatus
        if stateNow == "disabled" and command != "enable":
            ok_callback()
        else:

            def ok( self=self, command=command, dbus_ok=ok_callback ):
                self._updateResourceStatus( self.commandDone[command] )
                logger.debug( "(ok) done processing command '%s' for resource '%s' (new status=%s); triggering next command", command, self, self._resourceStatus )
                self.trigger()
                dbus_ok()

            def err( error, self=self, command=command, dbus_err=err_callback ):
                logger.debug( "(error) done processing command '%s' for resource '%s' (new status=%s); triggering next command", command, self, self._resourceStatus )
                self.trigger()
                dbus_err( error )

            self._updateResourceStatus( self.commandInProgress[command] )
            if command == "enable":
                self._enable( ok, err )
            elif command == "disable":
                self._disable( ok, err )
            elif command == "suspend":
                self._suspend( ok, err )
            elif command == "resume":
                self._resume( ok, err )
            else:
                logger.warning( "unknown resource command '%s' ignored.", command )
                self.trigger()

    def shutdown( self ):
        """
        Called by the subsystem during system shutdown.
        """

        if self.sync_resources_with_lifecycle in ( "always", "shutdown" ) and \
           self._resourceStatus in ( "enabled" , "enabling", "unknown" ):
            # no error handling, either it works or not
            #self._disable( lambda: None, lambda Foo: None )
            self.Disable( lambda: None, lambda Foo: None )

    def _updateResourceStatus( self, nextStatus ):
        logger.info( "setting resource status for %s from %s to %s" % ( self._resourceName, self._resourceStatus, nextStatus ) )
        self._resourceStatus = nextStatus
        # send all queued signals, if any
        if self._resourceStatus == "enabled":
            logger.debug( "resource now enabled. checking signal queue" )
            while not self._delayedSignalQueue.empty():
                f, args = self._delayedSignalQueue.get()
                logger.debug( "sending delayed signal %s( %s )", f, args )
                f(*args)

    # The DBus methods update the resource status and call the python implementation
    @dbus.service.method( DBUS_INTERFACE, "", "", async_callbacks=( "dbus_ok", "dbus_error" ) )
    def Enable( self, dbus_ok, dbus_error ):
        self.enqueue( "enable", dbus_ok, dbus_error )

    @dbus.service.method( DBUS_INTERFACE, "", "", async_callbacks=( "dbus_ok", "dbus_error" ) )
    def Disable( self, dbus_ok, dbus_error ):
        self.enqueue( "disable", dbus_ok, dbus_error )

    @dbus.service.method( DBUS_INTERFACE, "", "", async_callbacks=( "dbus_ok", "dbus_error" ) )
    def Suspend( self, dbus_ok, dbus_error ):
        self.enqueue( "suspend", dbus_ok, dbus_error )

    @dbus.service.method( DBUS_INTERFACE, "", "", async_callbacks=( "dbus_ok", "dbus_error" ) )
    def Resume( self, dbus_ok, dbus_error ):
        self.enqueue( "resume", dbus_ok, dbus_error )

    # Subclass of Service should reimplement these methods
    def _enable( self, on_ok, on_error ):
        logger.warning( "FIXME: Override Resource._enable for resource %s", self._resourceName )
        on_ok()

    def _disable( self, on_ok, on_error ):
        logger.warning( "FIXME: Override Resource._disable for resource %s", self._resourceName )
        on_ok()

    def _suspend( self, on_ok, on_error ):
        logger.warning( "FIXME: Override Resource._suspend for resource %s", self._resourceName )
        on_ok()

    def _resume( self, on_ok, on_error ):
        logger.warning( "FIXME: Override Resource._resume for resource %s", self._resourceName )
        on_ok()