class TestIterationData(object): def setUp(self): self.data = IterationData() self.data.uid_usage[2] = UsageData(10) def test_add(self): idata = IterationData() idata.uid_usage[2] = UsageData(10) idata.uid_usage[3] = UsageData(15) idata = self.data.add(idata) self.assertEqual(self.data.uid_usage.keys(), [2]) self.assertEqual(self.data.uid_usage.values(), [UsageData(20)]) self.assertEqual(idata.uid_usage.keys(), [2, 3]) self.assertEqual(idata.uid_usage.values(), [UsageData(20), UsageData(15)]) def test_add_uid_usage(self): self.data.add_uid_usage(10, UsageData(15)) self.assertEqual(self.data.uid_usage[10].usage, 15) def test_set_usage(self): self.data.set_usage(10) self.assertEqual(self.uid_usage[SystemInfo.AID_ALL], 10)
def test_add(self): idata = IterationData() idata.uid_usage[2] = UsageData(10) idata.uid_usage[3] = UsageData(15) idata = self.data.add(idata) self.assertEqual(self.data.uid_usage.keys(), [2]) self.assertEqual(self.data.uid_usage.values(), [UsageData(20)]) self.assertEqual(idata.uid_usage.keys(), [2, 3]) self.assertEqual(idata.uid_usage.values(), [UsageData(20), UsageData(15)])
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 calc_iteration(self, iter_num): """ Return power usage of each application using display after one iteration. """ result = IterationData() brightness = Screen.get_display_brightness() if 0 <= brightness <= 255: self.logger.warn("Could not retrieve brightness information") return result with self._screenlock: screen = self.screen_on usage = LCDUsage(brightness, screen) result.set_sys_usage(usage) if screen: uid = ForegroundDetector.get_foreground_uid() result.set_uid_usage(uid, usage) return result
def calc_iteration(self, iter_num): """ Return power usage of each application using display after one iteration. """ result = IterationData() brightness = Screen.get_display_brightness() if 0 <= brightness <= 255: self.logger.warn("Could not retrieve brightness information") return result with self._screenlock: screen = self.screen_on px_pwr = 0.0 # TODO: Substitute with C-based getScreenPixPower native function if screen and self._fb_file is not None: try: with open(self._fb_file) as fp: for x in self._fb_samples: fp.seek(x * 4) # Read 32-bit integer from file px = struct.unpack('i', fp.read(4))[0] blue = px >> 8 & 0xFF green = px >> 16 & 0xFF red = px >> 24 & 0xFF # Calculate the power usage of this pixel as if it were # at full brightness. Linearly scale by brightness to # get true power usage. To calculate whole screen power # usage, compute average of sampled region and multiply # by number of pixels sum_colors = red + green + blue px_pwr += (self.RED_PWR * (red*red) + self.GREEN_PWR * (green*green) + self.BLUE_PWR * (blue*blue) - self.MODULATION_PWR * (sum_colors * sum_colors)) except IOError as (errno, strerr): self.logger.warn("Can't read framebuffer {0}".format(strerr)) px_pwr = 0.0 if px_pwr > 0.0: px_pwr *= self.width * self.height / self.NSAMPLES
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 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 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
def calc_iteration(self, iter_num): """ Return power usage of each application using WiFi after one iteration. """ result = IterationData() state = self._wifi.get_state() if ((state != WifiAccess.WIFI_STATE_ENABLED) or (state != WifiAccess.WIFI_STATE_DISABLING)): # Allow the real interface state keeper to reset its state so that # the next update it knows it's coming back from an off state. We # also need to clear all UID information self._state.interface_off() self._uid_states.clear() self._speed = None result.set_sys_usage(WifiUsage()) return result tx_pkts = int(self._sysfs.tx_packets) rx_pkts = int(self._sysfs.rx_packets) tx_bytes = int(self._sysfs.tx_bytes) rx_bytes = int(self._sysfs.rx_bytes) if ((tx_pkts == -1) or (rx_pkts == -1) or (tx_bytes == -1) or (rx_bytes == -1)): self.logger.warn("Failed to read packet and byte counts from WiFi") return result # Update the link speed every 15 seconds as pulling the WifiInfo # structure from WifiManager is a little expensive. This isn't really # something that is likely to change frequently anyway if (iter_num % 15 == 0) or not self._speed: self._speed = self._wifi.get_speed() if self._state.is_initialized(): result.set_sys_usage(WifiUsage(True, self._state.delta_pkts, self._state.delta_tx_bytes, self._state.delta_rx_bytes, self._state.tx_rate, self._speed, self._state.pwr_state)) self._state.update(tx_pkts, rx_pkts, tx_bytes, rx_bytes) uids = SystemInfo.get_uids() if uids is not None: for uid in uids: if uid < 0: continue uid_state = self._uid_states.get(uid, None) if not uid_state: uid_state = WifiState(self._constants.WIFI_HIGHLOW_PKTBOUND, self._constants.WIFI_LOWHIGH_PKTBOUND) self._uid_states[uid] = uid_state if not uid_state.is_stale(): # Use heuristic to not poll for UIDs that haven't had much # activity recently continue # These read operations are the expensive part of polling with open(self.UID_TX_BYTE_MASK.format(uid)) as fp: tx_bytes = int(fp.read().strip()) with open(self.UID_RX_BYTE_MASK.format(uid)) as fp: rx_bytes = int(fp.read().strip()) if (rx_bytes == -1) or (tx_bytes == -1): self.logger.warn("Failed to read UID Tx/Rx byte counts") elif uid_state.is_initialized(): # We only have info on bytes received but what we really # want is the number of packets received so we will # estimate it delta_tx_bytes = tx_bytes - self._state.tx_bytes delta_rx_bytes = rx_bytes - self._state.rx_bytes tx_pkts = int(round(delta_tx_bytes / self._state.avg_tx_pkt_size)) rx_pkts = int(round(delta_rx_bytes / self._state.avg_rx_pkt_size)) if (delta_tx_bytes > 0) and (tx_pkts == 0): tx_pkts = 1 if (delta_rx_bytes > 0) and (rx_pkts == 0): rx_pkts = 1 active = ((tx_bytes != uid_state.tx_bytes) or (rx_bytes != uid_state.rx_bytes)) uid_state.update((self._state.tx_pkts + tx_pkts), (self._state.rx_pkts + rx_pkts), tx_bytes, rx_bytes) if active: usage = WifiUsage(True, uid_state.delta_pkts, uid_state.delta_tx_bytes, uid_state.delta_rx_bytes, uid_state.tx_rate, self._speed, uid_state.pwr_state) result.set_uid_usage(uid, usage) else: uid_state.update(0, 0, tx_bytes, rx_bytes) return result
def calc_iteration(self, iter_num): """ Return power usage of each application using CPU core after one iteration. """ result = IterationData() freq = self._read_cpu_freq() if freq == 0: self.logger.warn("Failed to read CPU frequency") return result times = SystemInfo.get_usr_sys_total_times(self.num) if len(times) == 0: self.logger.warn("Failed to read CPU times") return result usr_time = times[SystemInfo.INDEX_USR_TIME] sys_time = times[SystemInfo.INDEX_SYS_TIME] total_time = times[SystemInfo.INDEX_TOTAL_TIME] init = self._state.is_initialized() self._state.update(usr_time, sys_time, total_time, iter_num) # Power draw is based on usage time along with CPU frequency if init: result.set_sys_usage( CPUUsage(self._state.get_usr_perc(), self._state.get_sys_perc(), freq)) # Distribute CPU power draw during iteration among running processes. # CPU usage is returned by Linux using process ID. # A UID can have many processes and our final result should be based on # UID (app), therefore we need to account for all processes referring # to the same UID self._uid_states.clear() pids = SystemInfo.get_running_pids() if pids is not None: for i, pid in enumerate(pids): if pid < 0: break pid_state = self._pid_states.get(pid, None) # New process that hasn't been registered yet by our monitor if not pid_state: uid = SystemInfo.get_uid_for_pid(pid) if uid >= 0: self._pid_states[pid] = CPUState(uid) else: # Assume process no longer exists continue if pid_state.is_stale(iter_num): # Nothing much is going on with this PID recently. We'll # just assume that it's not using any of the CPU for this # iteration pid_state.skip_update(iter_num, total_time) else: times = SystemInfo.get_pid_usr_sys_times(pid) if len(times) > 0: usr_time = times[SystemInfo.INDEX_USR_TIME] sys_time = times[SystemInfo.INDEX_SYS_TIME] # Update slice of time used by this process based on # global iteration time pid_state.update(usr_time, sys_time, total_time, iter_num) if not init: continue uid_state = self._uid_states.get(pid_state.uid, None) # Register new UID if it doesn't exist. Else absorb power data # from its respective process if uid_state is not None: self._uid_states[pid_state.uid] = pid_state else: uid_state.absorb(pid_state) # Remove processes that are no longer active self._pid_states = { k: v for k, v in self._pid_states.iteritems() if self._pid_states[k].is_alive(iter_num) } # Collect the summed UID information for k, v in self._uid_states.iteritems(): uid_usage = self._get_cpu_usage(uid_state.get_usr_perc(), uid_state.get_sys_perc(), freq) result.set_uid_usage(uid, uid_usage) return result
def calc_iteration(self, iter_num): total = IterationData() # TODO: Rewrite below using FP for cpu in self.cpus: total.add(cpu.calc_iteration(iter_num)) return total
def calc_iteration(self, iter_num): """ Return power usage of each application using 3G interface during one iteration.""" result = IterationData() net_type = self._telephony.get_network_type() # Seems like TelephonyManager.NETWORK_TYPE_HSDPA = 8 # TODO: Actually get models for the different network types if ((net_type != TelephonyAccess.NETWORK_TYPE_UMTS) and (net_type != TelephonyAccess.NETWORK_TYPE_HSDPA)): net_type = TelephonyAccess.NETWORK_TYPE_UMTS net_state = self._telephony.get_state() if ((net_state != TelephonyAccess.DATA_CONNECTED) or (net_type != TelephonyAccess.NETWORK_TYPE_UMTS and net_type != TelephonyAccess.NETWORK_TYPE_HSDPA)): # We need to allow the real interface state to reset itself so that # the next update it knows it's coming back from an off state. We # also need to clear all UID information self._state.interface_off() self._uid_states.clear() result.set_sys_usage(ThreeGUsage()) return result tx_pkts = int(self._sysfs.tx_packets) rx_pkts = int(self._sysfs.rx_packets) tx_bytes = int(self._sysfs.tx_bytes) rx_bytes = int(self._sysfs.rx_bytes) if (tx_bytes == -1) or (rx_bytes == -1): self.logger.warn("Failed to read UID Tx/Rx byte counts") return result self._state.update(tx_pkts, rx_pkts, tx_bytes, rx_bytes) if self._state.is_initialized(): result.set_sys_usage(ThreeGUsage(True, self._state.delta_pkts, self._state.tx_bytes, self._state.rx_bytes, self._state.pwr_state, self._provider)) uids = SystemInfo.get_uids() if uids is not None: for uid in uids: if uid < 0: continue uid_state = self._uid_states.setdefault(uid, ThreeGState()) if uid_state.is_stale(): # Use heuristic to not poll for UIDs that haven't had much # activity recently continue # Read operations are the expensive part of polling with open(self.UID_TX_BYTE_MASK.format(uid)) as fp: tx_bytes = int(fp.read().strip()) with open(self.UID_RX_BYTE_MASK.format(uid)) as fp: rx_bytes = int(fp.read().strip()) if (rx_bytes == -1) or (tx_bytes == -1): self.logger.warn("Failed to read UID Tx/Rx byte counts") elif uid_state.is_initialized(): uid_state.update(0, 0, tx_bytes, rx_bytes) if ((uid_state.tx_bytes + uid_state.rx_bytes != 0) or (uid_state.pwr_state != self.POWER_STATE_IDLE)): usage = ThreeGUsage(True, uid_state.delta_pkts, uid_state.tx_bytes, uid_state.rx_bytes, uid_state.pwr_state, self._provider) result.set_uid_usage(uid, usage) else: uid_state.update(0, 0, tx_bytes, rx_bytes) return result
def setUp(self): self.data = IterationData() self.data.uid_usage[2] = UsageData(10)
def calc_iteration(self, iter_num): """ Return power usage of each application using 3G interface during one iteration.""" result = IterationData() net_type = self._telephony.get_network_type() # Seems like TelephonyManager.NETWORK_TYPE_HSDPA = 8 # TODO: Actually get models for the different network types if ((net_type != TelephonyAccess.NETWORK_TYPE_UMTS) and (net_type != TelephonyAccess.NETWORK_TYPE_HSDPA)): net_type = TelephonyAccess.NETWORK_TYPE_UMTS net_state = self._telephony.get_state() if ((net_state != TelephonyAccess.DATA_CONNECTED) or (net_type != TelephonyAccess.NETWORK_TYPE_UMTS and net_type != TelephonyAccess.NETWORK_TYPE_HSDPA)): # We need to allow the real interface state to reset itself so that # the next update it knows it's coming back from an off state. We # also need to clear all UID information self._state.interface_off() self._uid_states.clear() result.set_sys_usage(ThreeGUsage()) return result tx_pkts = int(self._sysfs.tx_packets) rx_pkts = int(self._sysfs.rx_packets) tx_bytes = int(self._sysfs.tx_bytes) rx_bytes = int(self._sysfs.rx_bytes) if (tx_bytes == -1) or (rx_bytes == -1): self.logger.warn("Failed to read UID Tx/Rx byte counts") return result self._state.update(tx_pkts, rx_pkts, tx_bytes, rx_bytes) if self._state.is_initialized(): result.set_sys_usage( ThreeGUsage(True, self._state.delta_pkts, self._state.tx_bytes, self._state.rx_bytes, self._state.pwr_state, self._provider)) uids = SystemInfo.get_uids() if uids is not None: for uid in uids: if uid < 0: continue uid_state = self._uid_states.setdefault(uid, ThreeGState()) if uid_state.is_stale(): # Use heuristic to not poll for UIDs that haven't had much # activity recently continue # Read operations are the expensive part of polling with open(self.UID_TX_BYTE_MASK.format(uid)) as fp: tx_bytes = int(fp.read().strip()) with open(self.UID_RX_BYTE_MASK.format(uid)) as fp: rx_bytes = int(fp.read().strip()) if (rx_bytes == -1) or (tx_bytes == -1): self.logger.warn("Failed to read UID Tx/Rx byte counts") elif uid_state.is_initialized(): uid_state.update(0, 0, tx_bytes, rx_bytes) if ((uid_state.tx_bytes + uid_state.rx_bytes != 0) or (uid_state.pwr_state != self.POWER_STATE_IDLE)): usage = ThreeGUsage(True, uid_state.delta_pkts, uid_state.tx_bytes, uid_state.rx_bytes, uid_state.pwr_state, self._provider) result.set_uid_usage(uid, usage) else: uid_state.update(0, 0, tx_bytes, rx_bytes) return result
def calc_iteration(self, iter_num): """ Return power usage of each application using CPU core after one iteration. """ result = IterationData() freq = self._read_cpu_freq() if freq == 0: self.logger.warn("Failed to read CPU frequency") return result times = SystemInfo.get_usr_sys_total_times(self.num) if len(times) == 0: self.logger.warn("Failed to read CPU times") return result usr_time = times[SystemInfo.INDEX_USR_TIME] sys_time = times[SystemInfo.INDEX_SYS_TIME] total_time = times[SystemInfo.INDEX_TOTAL_TIME] init = self._state.is_initialized() self._state.update(usr_time, sys_time, total_time, iter_num) # Power draw is based on usage time along with CPU frequency if init: result.set_sys_usage(CPUUsage(self._state.get_usr_perc(), self._state.get_sys_perc(), freq)) # Distribute CPU power draw during iteration among running processes. # CPU usage is returned by Linux using process ID. # A UID can have many processes and our final result should be based on # UID (app), therefore we need to account for all processes referring # to the same UID self._uid_states.clear() pids = SystemInfo.get_running_pids() if pids is not None: for i, pid in enumerate(pids): if pid < 0: break pid_state = self._pid_states.get(pid, None) # New process that hasn't been registered yet by our monitor if not pid_state: uid = SystemInfo.get_uid_for_pid(pid) if uid >= 0: self._pid_states[pid] = CPUState(uid) else: # Assume process no longer exists continue if pid_state.is_stale(iter_num): # Nothing much is going on with this PID recently. We'll # just assume that it's not using any of the CPU for this # iteration pid_state.skip_update(iter_num, total_time) else: times = SystemInfo.get_pid_usr_sys_times(pid) if len(times) > 0: usr_time = times[SystemInfo.INDEX_USR_TIME] sys_time = times[SystemInfo.INDEX_SYS_TIME] # Update slice of time used by this process based on # global iteration time pid_state.update(usr_time, sys_time, total_time, iter_num) if not init: continue uid_state = self._uid_states.get(pid_state.uid, None) # Register new UID if it doesn't exist. Else absorb power data # from its respective process if uid_state is not None: self._uid_states[pid_state.uid] = pid_state else: uid_state.absorb(pid_state) # Remove processes that are no longer active self._pid_states = {k: v for k, v in self._pid_states.iteritems() if self._pid_states[k].is_alive(iter_num)} # Collect the summed UID information for k, v in self._uid_states.iteritems(): uid_usage = self._get_cpu_usage(uid_state.get_usr_perc(), uid_state.get_sys_perc(), freq) result.set_uid_usage(uid, uid_usage) return result
def calc_iteration(self, iter_num): """ Return power usage of each application using WiFi after one iteration. """ result = IterationData() state = self._wifi.get_state() if ((state != WifiAccess.WIFI_STATE_ENABLED) or (state != WifiAccess.WIFI_STATE_DISABLING)): # Allow the real interface state keeper to reset its state so that # the next update it knows it's coming back from an off state. We # also need to clear all UID information self._state.interface_off() self._uid_states.clear() self._speed = None result.set_sys_usage(WifiUsage()) return result tx_pkts = int(self._sysfs.tx_packets) rx_pkts = int(self._sysfs.rx_packets) tx_bytes = int(self._sysfs.tx_bytes) rx_bytes = int(self._sysfs.rx_bytes) if ((tx_pkts == -1) or (rx_pkts == -1) or (tx_bytes == -1) or (rx_bytes == -1)): self.logger.warn("Failed to read packet and byte counts from WiFi") return result # Update the link speed every 15 seconds as pulling the WifiInfo # structure from WifiManager is a little expensive. This isn't really # something that is likely to change frequently anyway if (iter_num % 15 == 0) or not self._speed: self._speed = self._wifi.get_speed() if self._state.is_initialized(): result.set_sys_usage( WifiUsage(True, self._state.delta_pkts, self._state.delta_tx_bytes, self._state.delta_rx_bytes, self._state.tx_rate, self._speed, self._state.pwr_state)) self._state.update(tx_pkts, rx_pkts, tx_bytes, rx_bytes) uids = SystemInfo.get_uids() if uids is not None: for uid in uids: if uid < 0: continue uid_state = self._uid_states.get(uid, None) if not uid_state: uid_state = WifiState( self._constants.WIFI_HIGHLOW_PKTBOUND, self._constants.WIFI_LOWHIGH_PKTBOUND) self._uid_states[uid] = uid_state if not uid_state.is_stale(): # Use heuristic to not poll for UIDs that haven't had much # activity recently continue # These read operations are the expensive part of polling with open(self.UID_TX_BYTE_MASK.format(uid)) as fp: tx_bytes = int(fp.read().strip()) with open(self.UID_RX_BYTE_MASK.format(uid)) as fp: rx_bytes = int(fp.read().strip()) if (rx_bytes == -1) or (tx_bytes == -1): self.logger.warn("Failed to read UID Tx/Rx byte counts") elif uid_state.is_initialized(): # We only have info on bytes received but what we really # want is the number of packets received so we will # estimate it delta_tx_bytes = tx_bytes - self._state.tx_bytes delta_rx_bytes = rx_bytes - self._state.rx_bytes tx_pkts = int( round(delta_tx_bytes / self._state.avg_tx_pkt_size)) rx_pkts = int( round(delta_rx_bytes / self._state.avg_rx_pkt_size)) if (delta_tx_bytes > 0) and (tx_pkts == 0): tx_pkts = 1 if (delta_rx_bytes > 0) and (rx_pkts == 0): rx_pkts = 1 active = ((tx_bytes != uid_state.tx_bytes) or (rx_bytes != uid_state.rx_bytes)) uid_state.update((self._state.tx_pkts + tx_pkts), (self._state.rx_pkts + rx_pkts), tx_bytes, rx_bytes) if active: usage = WifiUsage(True, uid_state.delta_pkts, uid_state.delta_tx_bytes, uid_state.delta_rx_bytes, uid_state.tx_rate, self._speed, uid_state.pwr_state) result.set_uid_usage(uid, usage) else: uid_state.update(0, 0, tx_bytes, rx_bytes) return result