diff --git a/battery_test/adb_browsing.py b/battery_test/adb_browsing.py deleted file mode 100644 index 81f1ac2..0000000 --- a/battery_test/adb_browsing.py +++ /dev/null @@ -1,87 +0,0 @@ -import subprocess -import time - -PACKAGE = "com.android.chrome" -ACTIVITY = "com.google.android.apps.chrome.Main" -XML_FILE = "window_dump.xml" - -# Test URLs -URLS = [ - "https://facebook.com/", - "https://instagram.com", - "https://instagram.com/explore/", - "https://buzzfeed.com", - "https://cnn.com", - "https://tmz.com", - "https://perezhilton.com", - "https://wikipedia.org/wiki/Student%27s_t-test", - "https://searchfox.org/mozilla-central/source/toolkit/components/telemetry/Histograms.json", -] - -def run_cmd(cmd): - return subprocess.run(cmd, shell=True, capture_output=True, text=True) - -def extract_bounds(xml_file, resource_id): - cmd = f"xmllint --xpath \"string(//node[@resource-id='{resource_id}']/@bounds)\" {xml_file}" - result = run_cmd(cmd) - bounds = result.stdout.strip() - if not bounds: - raise ValueError(f"Could not find bounds for resource-id {resource_id}") - - try: - left, top = map(int, bounds.split('][')[0][1:].split(',')) - right, bottom = map(int, bounds.split('][')[1][:-1].split(',')) - except ValueError: - raise ValueError(f"Failed to parse bounds '{bounds}' for resource-id {resource_id}") - - x = (left + right) // 2 - y = (top + bottom) // 2 - return x, y - - -def tap(x, y): - run_cmd(f"adb -s R5CTB1NTHSF shellinput tap {x} {y}") - time.sleep(2) - -def input_text(text): - for character in text: - run_cmd(f"adb -s R5CTB1NTHSF shellinput text '{character}'") - time.sleep(2) - -def scroll_down(): - run_cmd("adb -s R5CTB1NTHSF shellinput swipe 500 1500 500 300 500") - time.sleep(3) - -def scroll_up(): - run_cmd("adb -s R5CTB1NTHSF shellinput swipe 500 300 500 1500 500") - time.sleep(3) - -def start_browser(url): - run_cmd(f"adb -s R5CTB1NTHSF shellam start -n {PACKAGE}/{ACTIVITY} -d {url}") - time.sleep(4) - -def close_browser(): - run_cmd(f"adb -s R5CTB1NTHSF shellam force-stop {PACKAGE}") - -def setup(): - run_cmd("adb -s R5CTB1NTHSF shelluiautomator dump /sdcard/window_dump.xml") - run_cmd("adb -s R5CTB1NTHSF pull /sdcard/window_dump.xml") - -def browse_url(url): - start_browser(url) - setup() - toolbar_x, toolbar_y = extract_bounds(XML_FILE, 'com.android.chrome:id/search_box_text') - tap(toolbar_x, toolbar_y) - input_text(url) - run_cmd("adb -s R5CTB1NTHSF shellinput keyevent 66") # KEYCODE_ENTER - time.sleep(10) - scroll_down() - scroll_up() - -def main(): - for url in URLS: - browse_url(url) - close_browser() - -if __name__ == "__main__": - main() diff --git a/battery_test/adb_navigation.py b/battery_test/adb_navigation.py deleted file mode 100644 index 7af4746..0000000 --- a/battery_test/adb_navigation.py +++ /dev/null @@ -1,80 +0,0 @@ -import subprocess -import time - -PACKAGE = "com.android.chrome" -ACTIVITY = "com.google.android.apps.chrome.Main" -XML_FILE = "window_dump.xml" - -# Test URLs -URLS = [ - "https://www.allrecipes.com/", - "https://www.amazon.com/", - "https://www.bing.com/search?q=restaurants+in+exton+pa+19341", - "https://www.booking.com/", - "https://www.dailymail.co.uk/sciencetech/article-9749081/Experts-say-Hubble-repair-despite-NASA-insisting-multiple-options-fix.html", - "https://m.imdb.com/", - "https://support.microsoft.com/en-us", - "https://stackoverflow.com/", - "https://en.m.wikipedia.org/wiki/Main_Page" -] - -def run_cmd(cmd): - return subprocess.run(cmd, shell=True, capture_output=True, text=True) - -def extract_bounds(xml_file, resource_id): - cmd = f"xmllint --xpath \"string(//node[@resource-id='{resource_id}']/@bounds)\" {xml_file}" - result = run_cmd(cmd) - bounds = result.stdout.strip() - # Parse the bounds "left,top][right,bottom" to get coordinates - left, top = map(int, bounds.split('][')[0][1:].split(',')) - right, bottom = map(int, bounds.split('][')[1][:-1].split(',')) - x = (left + right) // 2 - y = (top + bottom) // 2 - return x, y - -def tap(x, y): - run_cmd(f"adb -s R5CTB1NTHSF shellinput tap {x} {y}") - time.sleep(2) - -def input_text(text): - for character in text: - run_cmd(f"adb -s R5CTB1NTHSF shellinput text '{character}'") - time.sleep(2) - -def scroll_down(): - run_cmd("adb -s R5CTB1NTHSF shellinput swipe 500 1500 500 300 500") - time.sleep(3) - -def scroll_up(): - run_cmd("adb -s R5CTB1NTHSF shellinput swipe 500 300 500 1500 500") - time.sleep(3) - -def start_browser(url): - run_cmd(f"adb -s R5CTB1NTHSF shellam start -n {PACKAGE}/{ACTIVITY} -d {url}") - time.sleep(4) - -def close_browser(): - run_cmd(f"adb -s R5CTB1NTHSF shellam force-stop {PACKAGE}") - -def setup(): - run_cmd("adb -s R5CTB1NTHSF shelluiautomator dump /sdcard/window_dump.xml") - run_cmd("adb -s R5CTB1NTHSF pull /sdcard/window_dump.xml") - -def browse_url(url): - start_browser(url) - setup() - toolbar_x, toolbar_y = extract_bounds(XML_FILE, 'com.android.chrome:id/search_box_text') - tap(toolbar_x, toolbar_y) - input_text(url) - run_cmd("adb -s R5CTB1NTHSF shellinput keyevent 66") # KEYCODE_ENTER - time.sleep(10) - scroll_down() - scroll_up() - -def main(): - for url in URLS: - browse_url(url) - close_browser() - -if __name__ == "__main__": - main() diff --git a/battery_test/battery_test.py b/battery_test/battery_test.py index 38a8427..b8cca34 100644 --- a/battery_test/battery_test.py +++ b/battery_test/battery_test.py @@ -9,20 +9,24 @@ import queue import signal + def run_adb_command(command, serialID=None): if serialID is None: print(command) return subprocess.check_output(["adb", "shell"] + command.split(), text=True) return subprocess.check_output(["adb", "-s", serialID, "shell"] + command.split(), text=True) + def start_app(package, activity, serialID=None): run_adb_command(f"am start -n {package}/{activity}", serialID) + def start_browsertime_command(command): print("Running command:", command) process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True, text=True) return process + def stream_output(process, stream_name, log_queue): while True: output = getattr(process, stream_name).readline() @@ -34,12 +38,14 @@ def stream_output(process, stream_name, log_queue): if stream_name == 'stdout' and "Starting: Intent" in output: log_queue.put(True) + def get_battery_status(serialID=None): battery_info = run_adb_command("dumpsys battery", serialID) battery_level = re.search(r"level: (\d+)", battery_info).group(1) current_charge = run_adb_command("cat /sys/class/power_supply/battery/charge_counter", serialID) return battery_level, current_charge + def capture_processes(serialID=None): process_output = run_adb_command("top -b -n 1 | grep -E '^[0-9]'", serialID) processes = {} @@ -49,6 +55,7 @@ def capture_processes(serialID=None): processes[parts[0]] = (parts[11], parts[8], parts[10]) return processes + def compare_and_log_changes(old_snapshot, new_snapshot): changes = [] for pid, data in new_snapshot.items(): @@ -56,6 +63,7 @@ def compare_and_log_changes(old_snapshot, new_snapshot): changes.append(f"Name: {data[0]} | CPU%: {data[1]} | Time: {data[2]}") return changes + def get_component_names(components, serialID=None): thermalservice_output = run_adb_command("dumpsys thermalservice", serialID) pattern = re.compile(r"\{\.type = (\w+), \.name = (\w+),") @@ -69,6 +77,7 @@ def get_component_names(components, serialID=None): types[comp_type].append(name) return types + def fetch_temperatures(component_names, serialID=None): temperatures = {} thermalservice_output = run_adb_command("dumpsys thermalservice", serialID) @@ -82,6 +91,7 @@ def fetch_temperatures(component_names, serialID=None): temperatures[name] = float(temp_match.group(1)) return temperatures + def signal_handler(sig, frame): print('SIGINT received. Exiting...') # Perform any necessary cleanup actions here (e.g., close files, save data) @@ -101,15 +111,14 @@ def main(directory, filename, package, activity, duration, components, serialID, browsertime_cmd = ( "browsertime " "-b firefox --android " - f"--firefox.geckodriverPath {os.path.expanduser('~/Repositories/mozilla-unified/target/debug/geckodriver')} " + f"--firefox.geckodriverPath {os.path.expanduser('~/Repositories/mozilla-unified/target/debug/geckodriver')}" "--firefox.android.package org.mozilla.firefox " "--firefox.android.activity org.mozilla.fenix.IntentReceiverActivity " "--firefox.geckodriverArgs=\"--android-storage\" " "--firefox.geckodriverArgs=\"sdcard\" " "test.mjs " "-n 1 --maxLoadTime 60000 -vvv " - "--pageCompleteCheck 'return true;'" - ) + "--pageCompleteCheck 'return true;'") browsertime_process = start_browsertime_command(browsertime_cmd) threading.Thread(target=stream_output, args=(browsertime_process, 'stdout', log_queue)).start() @@ -171,6 +180,7 @@ def main(directory, filename, package, activity, duration, components, serialID, if browsertime_process is not None: browsertime_process.kill() + if __name__ == "__main__": signal.signal(signal.SIGINT, signal_handler) parser = argparse.ArgumentParser(description='Process some integers.') @@ -188,9 +198,17 @@ def main(directory, filename, package, activity, duration, components, serialID, parser.add_argument('duration_seconds', type=int, help='Duration in seconds') parser.add_argument('--serialID', type=str, help='Optional serial ID', default=None) - parser.add_argument('--start_method', type=str, choices=['browsertime', 'manual','adb'], default='browsertime', help='Method to start the app') + parser.add_argument( + '--start_method', + type=str, + choices=[ + 'browsertime', + 'manual', + 'adb'], + default='browsertime', + help='Method to start the app') args = parser.parse_args() main(args.output_directory, args.output_filename, args.package_name, args.activity_name, - args.duration_seconds, args.components, args.serialID, args.start_method) + args.duration_seconds, args.components, args.serialID, args.start_method) diff --git a/battery_test/process_battery_test.py b/battery_test/process_battery_test.py index 08e7d39..370c0fe 100644 --- a/battery_test/process_battery_test.py +++ b/battery_test/process_battery_test.py @@ -13,7 +13,7 @@ first_temperature_line_regex = re.compile(r"-\s*Temperature of components:\s*(\w+ Temperature:\s+[\d.]+°C)") temperature_regex = re.compile(r"\s*(\w+) Temperature:\s+([\d.]+)°C") process_regex = re.compile(r"\s*Name:\s+(.*?)\s+\|\s+CPU%:\s+([\d.]+)\s+\|\s+Time:\s+([\d:\.]+)") -keywords = ['firefox','google', 'chrome'] +keywords = ['firefox', 'google', 'chrome'] data = [] process_data = defaultdict(list) @@ -22,7 +22,6 @@ current_entry = {} for line in file: - timestamp_match = timestamp_regex.match(line) if timestamp_match: @@ -39,7 +38,6 @@ if charge_counter_match: current_entry['Charge Counter'] = int(charge_counter_match.group(1)) - if line.startswith("-Temperature of components:"): temperatures = [] @@ -49,8 +47,6 @@ first_component = component_match.group(1) temperatures.append(first_component.strip()) - - for temp_line in file: temperature_match = temperature_regex.match(temp_line) if temperature_match: @@ -60,8 +56,6 @@ current_entry['Temperature of Components'] = "\n".join(temperatures) - - process_match = process_regex.match(line) if process_match: @@ -69,16 +63,12 @@ process_cpu = process_match.group(2).strip() process_time = process_match.group(3).strip() - - process_data[current_timestamp].append({ "Process Name": process_name, "CPU%": process_cpu, "Time": process_time }) # A - - if current_entry: data.append(current_entry) @@ -97,17 +87,22 @@ total_row = {'Interval Time': 'Total', - 'Battery Level': None, - 'Charge Counter': total_charge_loss, - 'Temperature of Components': None, - 'Number of Processes': None} + 'Battery Level': None, + 'Charge Counter': total_charge_loss, + 'Temperature of Components': None, + 'Number of Processes': None} data.append(total_row) with open(output_file_path, 'w', newline='') as csvfile: - fieldnames = ['Interval Time', 'Battery Level', 'Charge Counter', 'Temperature of Components', 'Number of Processes'] + fieldnames = [ + 'Interval Time', + 'Battery Level', + 'Charge Counter', + 'Temperature of Components', + 'Number of Processes'] writer = csv.DictWriter(csvfile, fieldnames=fieldnames) writer.writeheader() for entry in data: @@ -136,8 +131,6 @@ else: data.append({'Interval Time': timestamp, 'Number of Processes': num_processes}) - - with open(process_file_path, 'w', newline='') as csvfile: fieldnames = ['Interval Time', 'Process Name', 'CPU%', 'Time'] writer = csv.DictWriter(csvfile, fieldnames=fieldnames) @@ -151,11 +144,11 @@ if current_interval != timestamp: current_interval = timestamp writer.writerow({'Interval Time': timestamp, - 'Process Name': process['Process Name'], - 'CPU%': process['CPU%'], - 'Time': process['Time']}) + 'Process Name': process['Process Name'], + 'CPU%': process['CPU%'], + 'Time': process['Time']}) else: writer.writerow({'Interval Time': '', - 'Process Name': process['Process Name'], - 'CPU%': process['CPU%'], - 'Time': process['Time']}) + 'Process Name': process['Process Name'], + 'CPU%': process['CPU%'], + 'Time': process['Time']})