def __init__(self, devconstants): super(GPS, self).__init__(Hardware.GPS, devconstants) self._uid_states = {} self._sleep_time = round(1000 * devconstants.GPS_SLEEP_TIME) self._update_time = 0 self._hook_method = 0 self._statekeeper = None self._status = None self._setup_gps_hook() self._uidstates_lock = threading.Lock() self._statekeeper_lock = threading.Lock() self._gpsstatus_lock = threading.Lock() # Track physical state self._statekeeper = GPSState(self._hook_method, self._sleep_time) # We need a GPS listener so that we can get the satellite count. Also # if anything goes wrong with the libgps hook, we revert to using this self._listener = GPSListener(self.__on_gps_status_changed) self._listener.start() # Use notification service to gather UID information if it's available callbacks = { NotificationProxy.ON_START_WAKELOCK: self.__on_start_wakelock, NotificationProxy.ON_STOP_WAKELOCK: self.__on_stop_wakelock, NotificationProxy.ON_START_GPS: self.__on_start_gps, NotificationProxy.ON_STOP_GPS: self.__on_start_gps, } if NotificationProxy.is_available(): self._event_server = NotificationProxy(callbacks) self._event_server.add_hook()
class Sensors(DeviceMonitor): SENSORS = SensorsAccess.get_sensors().keys() def __init__(self, devconstants=None): super(Sensors, self).__init__(Hardware.SENSORS, devconstants) self._state = SensorState() self._uid_states = {} self._sensorslock = threading.Lock() callbacks = { NotificationProxy.ON_START_SENSOR: self.__on_start_sensor, NotificationProxy.ON_STOP_SENSOR: self.__on_stop_sensor } self.has_uid_information = True if NotificationProxy.is_available(): self._event_server = NotificationProxy(callbacks) self._event_server.add_hook() def _on_exit(self): if NotificationProxy.is_available(): self._event_server.remove_hook() super(Sensors, self)._on_exit() def calc_iteration(self, iter_num): """ Return power usage of each application using sensors after one iteration. """ result = IterationData() sensor_usage = SensorUsage() with self._sensorslock: sensor_usage.on_times = self._state.get_times() result.set_sys_usage(sensor_usage) for uid, state in self._uid_states.iteritems(): usage = SensorUsage() usage.on_times = state.get_times() result.set_uid_usage(uid, usage) if state.started_sensors == 0: del (self._uid_states[uid]) return result def __on_start_sensor(self, uid, sensor): with self._sensorslock: self._state.start_sensor(sensor) uid_state = self._uid_states.setdefault(uid, SensorState()) uid_state.start_sensor(sensor) def __on_stop_sensor(self, uid, sensor): with self._sensorslock: self._state.stop_sensor(sensor) uid_state = self._uid_states.setdefault(uid, SensorState()) uid_state.stop_sensor(sensor)
def _on_exit(self): self._listener.stop() if NotificationProxy.is_available(): self._event_server.remove_hook() super(GPS, self)._on_exit()
def __init__(self, devconstants=None): super(Sensors, self).__init__(Hardware.SENSORS, devconstants) self._state = SensorState() self._uid_states = {} self._sensorslock = threading.Lock() callbacks = { NotificationProxy.ON_START_SENSOR: self.__on_start_sensor, NotificationProxy.ON_STOP_SENSOR: self.__on_stop_sensor } self.has_uid_information = True if NotificationProxy.is_available(): self._event_server = NotificationProxy(callbacks) self._event_server.add_hook()
def __init__(self, devconstants=None): super(Audio, self).__init__(Hardware.AUDIO, devconstants) self._uid_states = {} self._uid_usage = None self._uidstate_lock = threading.Lock() self._sys_uid = None callbacks = { NotificationProxy.ON_SYSTEM_MEDIA_CALL: self.__on_system_media_call, NotificationProxy.ON_START_MEDIA: self.__on_start_media, NotificationProxy.ON_STOP_MEDIA: self.__on_stop_media, } self.has_uid_information = NotificationProxy.is_available() if self.has_uid_information: self._event_server = NotificationProxy(callbacks) self._event_server.add_hook()
def _setup_gps_hook(self): """ Setup method for collecting GPS state information. """ # We can always use the status listener hook and perhaps the # notification hook if we are running eclaire or higher and the # notification hook is installed. We can only do this on eclaire or # higher because it wasn't until eclaire that they fixed a bug # where they didn't maintain a wakelock while the GPS engine was on self._hook_method = self.HOOK_GPS_STATUS_LISTENER try: # >= 5: eclair or higher if ((NotificationProxy.is_available() and int(Build.VERSION.SDK_INT) >= 5)): self._hook_method |= self.HOOK_NOTIFICATIONS except ValueError: pass # If we don't have a way of getting the off<->sleep transitions via # notifications, let's just use a timer and simulate the state of # the GPS instead if self._hook_method & self.HOOK_NOTIFICATIONS == self.NO_HOOKS: self._hook_method |= self.HOOK_TIMER
def has_uid_information(self): return NotificationProxy.is_available()
class GPS(DeviceMonitor): # Constants from android.location.GpsStatus GPS_EVENT_STARTED = 1 GPS_EVENT_STOPPED = 2 GPS_EVENT_FIRST_FIX = 3 GPS_EVENT_SATELLITE_STATUS = 4 # Local constants GPS_STATUS_SESSION_BEGIN = 1 GPS_STATUS_SESSION_END = 2 GPS_STATUS_ENGINE_ON = 3 GPS_STATUS_ENGINE_OFF = 4 NO_HOOKS = 0 HOOK_GPS_STATUS_LISTENER = 1 HOOK_NOTIFICATIONS = 2 HOOK_TIMER = 4 POWER_STATE_OFF = 0 POWER_STATE_SLEEP = 1 POWER_STATE_ON = 2 NPOWER_STATES = 3 def __init__(self, devconstants): super(GPS, self).__init__(Hardware.GPS, devconstants) self._uid_states = {} self._sleep_time = round(1000 * devconstants.GPS_SLEEP_TIME) self._update_time = 0 self._hook_method = 0 self._statekeeper = None self._status = None self._setup_gps_hook() self._uidstates_lock = threading.Lock() self._statekeeper_lock = threading.Lock() self._gpsstatus_lock = threading.Lock() # Track physical state self._statekeeper = GPSState(self._hook_method, self._sleep_time) # We need a GPS listener so that we can get the satellite count. Also # if anything goes wrong with the libgps hook, we revert to using this self._listener = GPSListener(self.__on_gps_status_changed) self._listener.start() # Use notification service to gather UID information if it's available callbacks = { NotificationProxy.ON_START_WAKELOCK: self.__on_start_wakelock, NotificationProxy.ON_STOP_WAKELOCK: self.__on_stop_wakelock, NotificationProxy.ON_START_GPS: self.__on_start_gps, NotificationProxy.ON_STOP_GPS: self.__on_start_gps, } if NotificationProxy.is_available(): self._event_server = NotificationProxy(callbacks) self._event_server.add_hook() def _on_exit(self): self._listener.stop() if NotificationProxy.is_available(): self._event_server.remove_hook() super(GPS, self)._on_exit() @property def has_uid_information(self): return NotificationProxy.is_available() def _setup_gps_hook(self): """ Setup method for collecting GPS state information. """ # We can always use the status listener hook and perhaps the # notification hook if we are running eclaire or higher and the # notification hook is installed. We can only do this on eclaire or # higher because it wasn't until eclaire that they fixed a bug # where they didn't maintain a wakelock while the GPS engine was on self._hook_method = self.HOOK_GPS_STATUS_LISTENER try: # >= 5: eclair or higher if ((NotificationProxy.is_available() and int(Build.VERSION.SDK_INT) >= 5)): self._hook_method |= self.HOOK_NOTIFICATIONS except ValueError: pass # If we don't have a way of getting the off<->sleep transitions via # notifications, let's just use a timer and simulate the state of # the GPS instead if self._hook_method & self.HOOK_NOTIFICATIONS == self.NO_HOOKS: self._hook_method |= self.HOOK_TIMER def __on_start_wakelock(self, uid, name, lock_type): """ Callback method for GPS status monitor. """ if (uid == SystemInfo.AID_SYSTEM) and (name == "GpsLocationProvider"): self._statekeeper.update_event(self.GPS_STATUS_ENGINE_ON, self.HOOK_NOTIFICATIONS) def __on_stop_wakelock(self, uid, name, lock_type): """ Callback method for GPS status monitor. """ if (uid == SystemInfo.AID_SYSTEM) and (name == "GpsLocationProvider"): self._statekeeper.update_event(self.GPS_STATUS_ENGINE_OFF, self.HOOK_NOTIFICATIONS) def __on_start_gps(self, uid): """ Callback method for GPS status monitor. """ self.update_uid_event(uid, self.GPS_STATUS_SESSION_BEGIN, self.HOOK_NOTIFICATIONS) def __on_stop_gps(self, uid): """ Callback method for GPS status monitor. """ self.update_uid_event(uid, self.GPS_STATUS_SESSION_END, self.HOOK_NOTIFICATIONS) def __on_gps_status_changed(self, event): """ Callback method for GPS status monitor. """ if event == self.GPS_EVENT_STARTED: self._statekeeper.update_event(self.GPS_STATUS_SESSION_BEGIN, self.HOOK_GPS_STATUS_LISTENER) elif event == self.GPS_EVENT_STOPPED: self._statekeeper.update_event(self.GPS_STATUS_SESSION_END, self.HOOK_GPS_STATUS_LISTENER) with self._gpsstatus_lock: self._status = self._listener.gps_status def update_uid_event(self, uid, event, hook_source): """ Update GPS state machine for given UID """ with self._uidstates_lock: state = self._uid_states.get(uid, None) if not state: state = GPSState(self.HOOK_NOTIFICATIONS | self.HOOK_TIMER, self._sleep_time, self._update_time) self._uid_states[uid] = state state.update_event(event, hook_source) def calc_iteration(self, iter_num): """ Return power usage of each application using GPS after one iteration. """ result = IterationData() # Get the power data for the physical GPS device with self._statekeeper_lock: state_times = self._statekeeper.state_times pwr_state = self._statekeeper.pwr_state self._statekeeper.reset_times() # Get the number of satellite that were available in the last update num_satellites = 0 with self._gpsstatus_lock: if pwr_state == self.POWER_STATE_ON and self._status is not None: num_satellites = len(self._status.getSatellites()) result.set_sys_usage(GPSUsage(state_times, num_satellites)) # Get usage data for each UID we have information on if self.has_uid_information: with self._uidstates_lock: self._update_time = (self._start_time + self._iter_interval * iter_num) for uid, state in self._uid_states.iteritems(): state_times = state.get_state_times() pwr_state = state.get_power_state() state.reset_times() # There is a guarantee that num_satellites will be zero # if GPS is off (see above) result.set_uid_usage(uid, GPSUsage(state_times, num_satellites)) # Remove state information for UIDs no longer using the GPS if pwr_state == self.POWER_STATE_OFF: del (self._uid_states[uid]) return result
class Audio(DeviceMonitor): AudioProxy = AudioAccess() def __init__(self, devconstants=None): super(Audio, self).__init__(Hardware.AUDIO, devconstants) self._uid_states = {} self._uid_usage = None self._uidstate_lock = threading.Lock() self._sys_uid = None callbacks = { NotificationProxy.ON_SYSTEM_MEDIA_CALL: self.__on_system_media_call, NotificationProxy.ON_START_MEDIA: self.__on_start_media, NotificationProxy.ON_STOP_MEDIA: self.__on_stop_media, } self.has_uid_information = NotificationProxy.is_available() if self.has_uid_information: self._event_server = NotificationProxy(callbacks) self._event_server.add_hook() def _on_exit(self): if self.has_uid_information: self._event_server.remove_hook() super(Audio, self)._on_exit() def __on_system_media_call(self, uid): self._sys_uid = uid def __on_start_media(self, uid, id_): uid_usage = MediaUsage(uid, id_) if (uid == SystemInfo.AID_SYSTEM) and (self._sys_uid is not None): uid_usage.proxy_uid = self._sys_uid self._sys_uid = None else: uid_usage.proxy_uid = uid with self._uidstate_lock: # Act like a treeset. Just insert, but don't update self._uid_states.setdefault(uid, uid_usage) def __on_stop_media(self, uid, id_): with self._uidstate_lock: del (self._uid_states[uid]) def calc_iteration(self, iter_num): """ Return power usage of each application using audio after one iteration. """ result = IterationData() audio_on = (self._uid_usage is not None and len(self._uid_states) != 0 ) or (self.AudioProxy.is_music_active()) result.set_sys_usage(AudioUsage(audio_on)) if self._uid_usage is not None: with self._uidstate_lock: uid = -1 for usage in self._uid_usage.values(): if usage.uid != uid: result.set_uid_usage(usage.proxy_uid, AudioUsage(True)) uid = usage.uid return result
def _on_exit(self): if NotificationProxy.is_available(): self._event_server.remove_hook() super(Sensors, self)._on_exit()
class Audio(DeviceMonitor): AudioProxy = AudioAccess() def __init__(self, devconstants=None): super(Audio, self).__init__(Hardware.AUDIO, devconstants) self._uid_states = {} self._uid_usage = None self._uidstate_lock = threading.Lock() self._sys_uid = None callbacks = { NotificationProxy.ON_SYSTEM_MEDIA_CALL: self.__on_system_media_call, NotificationProxy.ON_START_MEDIA: self.__on_start_media, NotificationProxy.ON_STOP_MEDIA: self.__on_stop_media, } self.has_uid_information = NotificationProxy.is_available() if self.has_uid_information: self._event_server = NotificationProxy(callbacks) self._event_server.add_hook() def _on_exit(self): if self.has_uid_information: self._event_server.remove_hook() super(Audio, self)._on_exit() def __on_system_media_call(self, uid): self._sys_uid = uid def __on_start_media(self, uid, id_): uid_usage = MediaUsage(uid, id_) if (uid == SystemInfo.AID_SYSTEM) and (self._sys_uid is not None): uid_usage.proxy_uid = self._sys_uid self._sys_uid = None else: uid_usage.proxy_uid = uid with self._uidstate_lock: # Act like a treeset. Just insert, but don't update self._uid_states.setdefault(uid, uid_usage) def __on_stop_media(self, uid, id_): with self._uidstate_lock: del (self._uid_states[uid]) def calc_iteration(self, iter_num): """ Return power usage of each application using audio after one iteration. """ result = IterationData() audio_on = (self._uid_usage is not None and len(self._uid_states) != 0) or (self.AudioProxy.is_music_active()) result.set_sys_usage(AudioUsage(audio_on)) if self._uid_usage is not None: with self._uidstate_lock: uid = -1 for usage in self._uid_usage.values(): if usage.uid != uid: result.set_uid_usage(usage.proxy_uid, AudioUsage(True)) uid = usage.uid return result