def update_event(self, event, hook_source): """ When a hook source gets an event, it should report it to this function. The only exception is HOOK_TIME which is handled within this class itself. """ # TODO: Access should be locked if (self._hook_mask & hook_source) == GPS.NO_HOOKS: # We are not using this hook source, ignore. return self._update_times() prev_state = self.pwr_state if event == GPS.GPS_STATUS_SESSION_BEGIN: self.pwr_state = GPS.POWER_STATE_ON elif event == GPS.GPS_STATUS_SESSION_END: if self.pwr_state == GPS.POWER_STATE_ON: self.pwr_state = GPS.POWER_STATE_SLEEP elif event == GPS.GPS_STATUS_ENGINE_ON: if self.pwr_state == GPS.POWER_STATE_OFF: self.pwr_state = GPS.POWER_STATE_SLEEP elif event == GPS.GPS_STATUS_ENGINE_OFF: self.pwr_state = GPS.POWER_STATE_OFF else: self.logger.error("Unknown GPS event capture: {0}".format(event)) if self.pwr_state != prev_state: if ((prev_state == GPS.POWER_STATE_ON) and (self.pwr_state == GPS.POWER_STATE_SLEEP)): self._off_time = SystemClock.elapsedRealtime() + \ self._sleep_time else: # Any other state transition should reset the off timer self._off_time = None
def start_sensor(self, name): if (name in self._on) and (self._on[name] == 0): self._on_times[name] -= SystemClock.elapsedRealtime() -\ self._timestamp self.started_sensors += 1 # WARNING: May break when name is invalid self._on[name] += 1
def stop_sensor(self, name): if name in self._on: if self._on[name] == 0: return if self._on[name] - 1 == 0: self._on_times[name] += (SystemClock.elapsedRealtime() - self._timestamp) self.started_sensors -= 1 self._on[name] -= 1
def __init__(self): self._total = 0 self._start_time = SystemClock.elapsedRealtime() self._counters = { self.COUNTER_MINUTE: _BucketCounter(), self.COUNTER_HOUR: _BucketCounter(), self.COUNTER_DAY: _BucketCounter(), self.COUNTER_TOTAL: _BucketCounter(), }
def _prepare(self, iter_interval=1): """ Called once at the beginning of the daemon loop. """ self._start_time = SystemClock.elapsedRealtime() self._iter_interval = iter_interval # Every second # Iteration-data buffers for cycling during data collection self._data1 = None self._data2 = None self._iter1 = -1 self._iter2 = -1
def is_stale(self): """ Heuristic to avoid excessive polling on UIDs. We shouldn't update state on every iteration as it takes too much time """ if not self.is_initialized(): return True # TODO: check if 10000 is the correct number (should be 10s?) # Reduce this number if we want more frequent WiFi checks return ((SystemClock.elapsedRealtime() - self._update_time) > min( 10000, self.inactive_time))
def is_stale(self): """ Heuristic to avoid excessive polling on UIDs. We shouldn't update state on every iteration as it takes too much time """ if not self.is_initialized(): return True # TODO: check if 10000 is the correct number (should be 10s?) # Reduce this number if we want more frequent WiFi checks return ((SystemClock.elapsedRealtime() - self._update_time) > min(10000, self.inactive_time))
def is_stale(self): """ Heuristic to avoid excessive polling on UIDs. We shouldn't update state on every iteration as it takes too much time None -> Boolean """ if self.pwr_state != ThreeG.POWER_STATE_IDLE: return True # TODO: check if 10000 us the correct number (Why 10s?) # Reduce this number if we want more frequent 3G checks return ((SystemClock.elapsedRealtime() - self._update_time) > min(10000, self._inactive_time))
def get(self, type_): assert (Counter.COUNTER_MINUTE <= type_ <= Counter.COUNTER_TOTAL) if type_ == Counter.COUNTER_TOTAL: return self._total now = SystemClock.elapsedRealtime() - self._start_time timestamp = (now * _BucketCounter.BUCKET_NUM / Counter.COUNTER_DURATIONS[type_]) progress = ((now * _BucketCounter.BUCKET_NUM % Counter.COUNTER_DURATIONS[type_]) / Counter.COUNTER_DURATIONS[type_]) return self._counters[type_].get(timestamp, progress)
def is_stale(self): """ Heuristic to avoid excessive polling on UIDs. We shouldn't update state on every iteration as it takes too much time None -> Boolean """ if self.pwr_state != ThreeG.POWER_STATE_IDLE: return True # TODO: check if 10000 us the correct number (Why 10s?) # Reduce this number if we want more frequent 3G checks return ((SystemClock.elapsedRealtime() - self._update_time) > min( 10000, self._inactive_time))
def update(self, tx_pkts, rx_pkts, tx_bytes, rx_bytes): now = SystemClock.elapsedRealtime() if (self._update_time is not None) and (now > self._update_time): delta_time = now - self._update_time self.delta_pkts = tx_pkts + rx_pkts - self.tx_pkts - self.rx_pkts self.delta_tx_bytes = tx_bytes - self.tx_bytes self.delta_rx_bytes = rx_bytes - self.rx_bytes inactive = (self.delta_tx_bytes == 0) and (self.delta_rx_bytes == 0) if inactive: self._inactive_time += delta_time else: self._inactive_time = 0 # TODO: Make this always work time_mult = 1 if PowerEstimator.ITERATION_INTERVAL % 1000 != 0: # Cannot handle 1-sec iteration intervals pass else: time_mult = 1000 // PowerEstimator.ITERATION_INTERVAL if self.pwr_state == ThreeG.POWER_STATE_IDLE and not inactive: self.pwr_state = ThreeG.POWER_STATE_FACH elif self.pwr_state == ThreeG.POWER_STATE_FACH: if inactive: self._pwr_state_time += 1 if (self._pwr_state_time >= (self._fach_idle_time * time_mult)): self._pwr_state_time = 0 self.pwr_state = ThreeG.POWER_STATE_IDLE else: self._pwr_state_time = 0 if (self.delta_tx_bytes > 0) or (self.delta_rx_bytes > 0): self.pwr_state = ThreeG.POWER_STATE_DCH elif self.pwr_state == ThreeG.POWER_STATE_DCH: if inactive: self._pwr_state_time += 1 if self._pwr_state_time >= self._dch_fach_time * time_mult: self._pwr_state_time = 0 self.pwr_state = ThreeG.POWER_STATE_FACH else: self._pwr_state_time = 0 self._update_time = now self.tx_pkts = tx_pkts self.rx_pkts = rx_pkts self.tx_bytes = tx_bytes self.rx_bytes = rx_bytes
def update(self, tx_pkts, rx_pkts, tx_bytes, rx_bytes): now = SystemClock.elapsedRealtime() if (self._update_time is not None) and (now > self._update_time): delta_time = now - self._update_time self.delta_pkts = tx_pkts + rx_pkts - self.tx_pkts - self.rx_pkts self.delta_tx_bytes = tx_bytes - self.tx_bytes self.delta_rx_bytes = rx_bytes - self.rx_bytes inactive = (self.delta_tx_bytes == 0) and (self.delta_rx_bytes == 0) if inactive: self._inactive_time += delta_time else: self._inactive_time = 0 # TODO: Make this always work time_mult = 1 if PowerEstimator.ITERATION_INTERVAL % 1000 != 0: # Cannot handle 1-sec iteration intervals pass else: time_mult = 1000 // PowerEstimator.ITERATION_INTERVAL if self.pwr_state == ThreeG.POWER_STATE_IDLE and not inactive: self.pwr_state = ThreeG.POWER_STATE_FACH elif self.pwr_state == ThreeG.POWER_STATE_FACH: if inactive: self._pwr_state_time += 1 if (self._pwr_state_time >= (self._fach_idle_time * time_mult)): self._pwr_state_time = 0 self.pwr_state = ThreeG.POWER_STATE_IDLE else: self._pwr_state_time = 0 if (self.delta_tx_bytes > 0) or (self.delta_rx_bytes > 0): self.pwr_state = ThreeG.POWER_STATE_DCH elif self.pwr_state == ThreeG.POWER_STATE_DCH: if inactive: self._pwr_state_time += 1 if self._pwr_state_time >= self._dch_fach_time * time_mult: self._pwr_state_time = 0 self.pwr_state = ThreeG.POWER_STATE_FACH else: self._pwr_state_time = 0 self._update_time = now self.tx_pkts = tx_pkts self.rx_pkts = rx_pkts self.tx_bytes = tx_bytes self.rx_bytes = rx_bytes
def _update_times(self): now = SystemClock.elapsedRealtime() # Check if GPS has gone to sleep state due to timer if ((self._hook_mask & GPS.HOOK_TIMER != GPS.NO_HOOKS) and (self._off_time is not None) and (self._off_time < now)): self._state_times[self.pwr_state] += (self._off_time - self._update_time) / 1000 self.pwr_state = GPS.POWER_STATE_OFF self._off_time = None # Update the amount of time that we've been in the current state self._state_times[self.pwr_state] += ((now - self._update_time) / 1000) self._update_time = now
def get_times(self): now = SystemClock.elapsedRealtime() div = now - self._timestamp if div <= 0: div = 1 times = {} for k, v in self._on_times.iteritems(): factor = now - self._timestamp if self._on.get(k, 0) > 0 else 0 times[k] = (v + factor) / div self._on_times[k] = 0 self._timestamp = now return times
def __init__(self, hook_mask, sleep_time=None, update_time=None): # The union of whatever valid hook sources. See HOOK_ constants self._hook_mask = hook_mask # The time GPS hardware should turn off. Only used if HOOK_TIMER is in # hook_mask. Not useful if HOOK_TIMER is not set self._off_time = None # Time GPS remains in sleep state after session has ended # (seconds) self._sleep_time = sleep_time if not update_time: self._update_time = SystemClock.elapsedRealtime() else: self._update_time = update_time self._state_times = [] self.pwr_state = GPS.POWER_STATE_OFF
def _run(self): """ Runs the daemon loop that collects data for this monitor.""" # Hands off to client class to actually calculate the information we # want for this monitor iter_num = 0 self._prepare() while not self.is_stopped(): data = self.calc_iteration(iter_num) if data is not None: with self._data_lock: if self._iter1 < self._iter2: self._iter1 = iter_num self._data1 = data else: self._iter2 = iter_num self._data2 = data if not self.is_stopped(): break now = SystemClock.elapsedRealtime() # Compute the next iteration that we can make the start of prev_iter = iter_num iter_num = max((iter_num + 1), 1 + (now - self._start_time) / self._iter_interval) if prev_iter + 1 != iter_num: self.logger.warn("Had to skip iteration {0} to " "{1}".format(prev_iter, iter_num)) # Sleep until next iteration completes time.sleep(self._start_time + iter_num * self._iter_interval - now) self._on_exit()
def update(self, tx_pkts, rx_pkts, tx_bytes, rx_bytes): now = SystemClock.elapsedRealtime() if (self._update_time is not None) and (now > self._update_time): delta_time = now - self._update_time # 1024 * 7.8125 = 131.072 self.tx_rate = (tx_bytes - self.tx_bytes) / 131.072 / delta_time self.delta_pkts = rx_pkts + tx_pkts - self.rx_pkts - self.tx_pkts self.delta_tx_bytes = tx_bytes - self.tx_bytes self.delta_rx_bytes = rx_bytes - self.rx_bytes if tx_pkts != self.tx_pkts: self.avg_tx_pkt_size = ((0.9 * self.avg_tx_pkt_size) + (0.1 * (tx_bytes - self.tx_bytes) / (tx_pkts - self.tx_pkts))) if rx_pkts != self.rx_pkts: self.avg_rx_pkt_size = ((0.9 * self.avg_rx_pkt_size) + (0.1 * (rx_bytes - self.rx_bytes) / ( rx_pkts - self.rx_pkts))) if (rx_bytes != self.rx_bytes) or (tx_bytes != self.tx_bytes): self.inactive_time = 0 else: self.inactive_time += now - self._update_time if self.delta_pkts < self._highlow_pktbound: self.pwr_state = Wifi.POWER_STATE_LOW elif self.delta_pkts > self._lowhigh_pktbound: self.pwr_state = Wifi.POWER_STATE_HIGH self._update_time = now self.tx_pkts = tx_pkts self.rx_pkts = rx_pkts self.tx_bytes = tx_bytes self.rx_bytes = rx_bytes
def update(self, tx_pkts, rx_pkts, tx_bytes, rx_bytes): now = SystemClock.elapsedRealtime() if (self._update_time is not None) and (now > self._update_time): delta_time = now - self._update_time # 1024 * 7.8125 = 131.072 self.tx_rate = (tx_bytes - self.tx_bytes) / 131.072 / delta_time self.delta_pkts = rx_pkts + tx_pkts - self.rx_pkts - self.tx_pkts self.delta_tx_bytes = tx_bytes - self.tx_bytes self.delta_rx_bytes = rx_bytes - self.rx_bytes if tx_pkts != self.tx_pkts: self.avg_tx_pkt_size = ((0.9 * self.avg_tx_pkt_size) + (0.1 * (tx_bytes - self.tx_bytes) / (tx_pkts - self.tx_pkts))) if rx_pkts != self.rx_pkts: self.avg_rx_pkt_size = ((0.9 * self.avg_rx_pkt_size) + (0.1 * (rx_bytes - self.rx_bytes) / (rx_pkts - self.rx_pkts))) if (rx_bytes != self.rx_bytes) or (tx_bytes != self.tx_bytes): self.inactive_time = 0 else: self.inactive_time += now - self._update_time if self.delta_pkts < self._highlow_pktbound: self.pwr_state = Wifi.POWER_STATE_LOW elif self.delta_pkts > self._lowhigh_pktbound: self.pwr_state = Wifi.POWER_STATE_HIGH self._update_time = now self.tx_pkts = tx_pkts self.rx_pkts = rx_pkts self.tx_bytes = tx_bytes self.rx_bytes = rx_bytes
def _run(self): """Loop that keeps updating the power profile""" start_time = SystemClock.elapsedRealtime() for hw in self._phone.hardware.values(): hw.init(start_time, self.ITERATION_INTERVAL) hw.start() self._running.set() iter_num = 0 while self.is_running(): now = SystemClock.elapsedRealtime() # Compute the next iteration that we can make the ending of. We # wait for the end of the iteration so that the monitors have a # chance to collect data iter_num = max(iter_num, (now - start_time) // self.ITERATION_INTERVAL) # sleep until the next iteration completes time.sleep(start_time + iter_num * self.ITERATION_INTERVAL - now) # Check if service was interrupted while sleeping if not self.is_running(): break total_power = 0 hw_data = {} if iter_num % (30 * 60) == 0: self._log_sys_settings() if iter_num % 60 == 0: self._log_battery() for name, hw in self._phone.hardware.iteritems(): data = hw.get_data(iter_num) if data is None: continue hw_data[name] = data for uid, usage in data.uid_usage.iteritems(): power = self._phone.power_function[name](usage) usage.power = power self._pwr_history[name].add(uid, iter_num, power) if uid == SystemInfo.AID_ALL: total_power += power # Update list of running apps with self._appslock: self._running_apps.setdefault(uid, SystemInfo.get_uid_name( uid)) if name == "OLED" and usage.pix_pwr >= 0: self._oled_pwr_history.add_power(uid, iter_num, 1000 * data.pix_pwr) self._log_uid_power(self, uid, name, power) # Only log app names for the first time if iter_num == 0: self._log_app_names() self._log_power(total_power, hw_data) self._update_avg_power() # Wait for all hardware monitors to finish for hw in self._phone.hardware.values(): hw.stop() hw.join()
def interface_off(self): self._update_time = SystemClock.elapsedRealtime() self.pwr_state = ThreeG.POWER_STATE_IDLE
def __init__(self): self._on = dict.fromkeys(Sensors.SENSORS, 0) self._on_times = dict.fromkeys(Sensors.SENSORS, 0) self._timestamp = SystemClock.elapsedRealtime() self.started_sensors = 0
def add(self, value): self._total += value now = SystemClock.elapsedRealtime() - self._start_time for type_, counter in self._counters.iteritems(): counter.add(value, now * _BucketCounter.BUCKET_NUM / Counter.COUNTER_DURATIONS[type_])
def interface_off(self): self._update_time = SystemClock.elapsedRealtime() self.pwr_state = ThreeG.POWER_STATE_IDLE