Path: blob/master/AndroidRunner/Plugins/monsoon/Monsoon.py
907 views
import csv1import os2import os.path as op3import time4from collections import OrderedDict56from AndroidRunner import util7from AndroidRunner.Plugins.Profiler import Profiler8from AndroidRunner.Plugins.monsoon.script.power_device import power_meter910class Monsoon(Profiler):11def __init__(self, config, paths):12super(Monsoon, self).__init__(config, paths)13self.output_dir = ''14self.paths = paths15self.profile = False16self.data_points = ["energy_joules", "duration_ms", "error_flag"]1718def dependencies(self):19return []2021def load(self, device):22return2324def start_profiling(self, device, **kwargs):25"""Start the profiling process"""2627# Quickly let the mobile device sleep and wake up so a run can take up to 30 minutes.28device.shell("input keyevent KEYCODE_SLEEP")29device.shell("input keyevent KEYCODE_WAKEUP")30time.sleep(5)31self.profile = True32power_meter.start()3334def stop_profiling(self, device, **kwargs):35"""Stop the profiling process"""36self.results = power_meter.stop()37self.profile = False3839# Quickly let the mobile device sleep and wake up so the device is awake for 30 minutes.40# This solves the issue of certain commands sent to the device blocking the execution of the program.41device.shell("input keyevent KEYCODE_SLEEP")42device.shell("input keyevent KEYCODE_WAKEUP")43time.sleep(5)4445def collect_results(self, device):46"""Collect the data and clean up extra files on the device, save data in location set by 'set_output' """47filename = 'monsoon_{}.csv'.format(time.strftime('%Y.%m.%d_%H%M%S'))48with open(op.join(self.output_dir, filename), 'w+') as f:49writer = csv.writer(f)50writer.writerow(self.data_points)51#Seconds to milliseconds52writer.writerow([self.results[0], round(self.results[1]*1000), self.results[2]])5354def unload(self, device):55return5657def set_output(self, output_dir):58"""Set the output directory before the start_profiling is called"""59self.output_dir = output_dir6061def aggregate_subject(self):62"""Aggregate the data at the end of a subject, collect data and save data to location set by 'set output' """63with open(op.join(self.output_dir, 'aggregated.csv'), 'w+') as output:64writer = csv.writer(output)65writer.writerow(self.data_points)6667# Loop over files containing the measurements for each run in ascending order (oldest run first, newest run last).68for output_file in sorted(os.listdir(self.output_dir), reverse=False):69if output_file.startswith("monsoon_"):70res = open(op.join(self.output_dir, output_file)).readlines()[1]71res = res.rstrip()72res = res.split(",")73writer.writerow([res[0],res[1],res[2]])7475def aggregate_end(self, data_dir, output_file):76"""Aggregate the data at the end of the experiment.77Data located in file structure inside data_dir. Save aggregated data to output_file78"""79rows = self.aggregate_final(data_dir)80util.write_to_file(output_file, rows)8182def aggregate_final(self, data_dir):83"""Compiles subject aggregation files"""84rows = []85for device in util.list_subdir(data_dir):86row = OrderedDict({'device': device})87device_dir = os.path.join(data_dir, device)88for subject in util.list_subdir(device_dir):89row.update({'subject': subject})90subject_dir = os.path.join(device_dir, subject)91if os.path.isdir(os.path.join(subject_dir, 'monsoon')):92temp_row = row.copy()93row.update(self.get_aggregated_runs_subject(94os.path.join(subject_dir, 'monsoon')))95self.add_rows(row, temp_row, rows, subject_dir)9697else:98for browser in util.list_subdir(subject_dir):99row.update({'browser': browser})100browser_dir = os.path.join(subject_dir, browser)101if os.path.isdir(os.path.join(browser_dir, 'monsoon')):102temp_row = row.copy()103row.update(self.get_aggregated_runs_subject(104os.path.join(browser_dir, 'monsoon')))105self.add_rows(row, temp_row, rows, browser_dir)106return rows107108@staticmethod109def get_aggregated_runs_subject(logs_dir):110"""Finds the aggregated file for a subject and returns the rows of that file. The data returned is a key-value pair where the value is a list"""111for aggregated_file in [f for f in os.listdir(logs_dir) if os.path.isfile(os.path.join(logs_dir, f))]:112if aggregated_file == "aggregated.csv":113with open(os.path.join(logs_dir, aggregated_file), 'r') as aggregated:114reader = csv.DictReader(aggregated)115row_dict = OrderedDict()116for row in reader:117for f in reader.fieldnames:118if f in row_dict.keys():119temp = row_dict[f]120temp.append(row[f])121row_dict.update({f: temp})122else:123row_dict.update({f: [row[f]]})124return OrderedDict(row_dict)125126def add_rows(self, row, temp_row, rows, dir):127"""Retrieves the list values in the key-value pairs from get_aggregated_runs_subject and creates n rows for list of size n"""128repetition_count = len(os.listdir(os.path.join(dir, 'monsoon'))) - 1129for i in range(repetition_count):130temp_row.update({self.data_points[0]: row[self.data_points[0]][i], self.data_points[1]: row[self.data_points[1]][i], self.data_points[2]: row[self.data_points[2]][i]})131rows.append(temp_row.copy())132return rows133134135