From 6513ab63d8c7019f8b7be7400ff50bda7b762962 Mon Sep 17 00:00:00 2001 From: Marc Leclair Date: Mon, 20 May 2024 17:55:04 -0400 Subject: [PATCH] added bettery testing scripts --- battery_test/adb_browsing.py | 87 +++++++++++ battery_test/adb_navigation.py | 80 ++++++++++ battery_test/auto-test-chrome.sh | 144 ++++++++++++++++++ battery_test/auto-test-firefox.sh | 218 +++++++++++++++++++++++++++ battery_test/battery_test.py | 196 ++++++++++++++++++++++++ battery_test/batterytest.sh | 52 +++++++ battery_test/cpu_use.sh | 44 ++++++ battery_test/process_battery_test.py | 161 ++++++++++++++++++++ battery_test/scroll.sh | 142 +++++++++++++++++ battery_test/test.mjs | 174 +++++++++++++++++++++ 10 files changed, 1298 insertions(+) create mode 100644 battery_test/adb_browsing.py create mode 100644 battery_test/adb_navigation.py create mode 100755 battery_test/auto-test-chrome.sh create mode 100755 battery_test/auto-test-firefox.sh create mode 100644 battery_test/battery_test.py create mode 100755 battery_test/batterytest.sh create mode 100755 battery_test/cpu_use.sh create mode 100644 battery_test/process_battery_test.py create mode 100755 battery_test/scroll.sh create mode 100644 battery_test/test.mjs diff --git a/battery_test/adb_browsing.py b/battery_test/adb_browsing.py new file mode 100644 index 0000000..81f1ac2 --- /dev/null +++ b/battery_test/adb_browsing.py @@ -0,0 +1,87 @@ +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 new file mode 100644 index 0000000..7af4746 --- /dev/null +++ b/battery_test/adb_navigation.py @@ -0,0 +1,80 @@ +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/auto-test-chrome.sh b/battery_test/auto-test-chrome.sh new file mode 100755 index 0000000..7c4310c --- /dev/null +++ b/battery_test/auto-test-chrome.sh @@ -0,0 +1,144 @@ +#!/bin/bash +PACKAGE="com.android.chrome" +ACTIVITY="com.google.android.apps.chrome.Main" +XML_FILE="window_dump.xml" + +# Test urls +URL_REDDIT="https://www.reddit.com/r/all" +URL_INSTAGRAM="https://www.instagram.com/" +URL_INSTAGRAM_EXPLORE="https://www.instagram.com/explore" +URL_FACEBOOK="https://www.facebook.com" +URL_TMZ="https://tmz.com" +URL_PEREZ="https://perezhilton.com" +URL_WIKI="https://wikipedia.org/wiki/Student%27s_t-test", +URL_SEARCH_FOX="https://searchfox.org/mozilla-central/source/toolkit/components/telemetry/Histograms.json", +URL_BUZZFEED="https://buzzfeed.com" +URL_CNN="https://cnn.com" + +# script start +adb shell am start -n "$PACKAGE/$ACTIVITY" +sleep 4 + +adb shell uiautomator dump +adb pull /sdcard/window_dump.xml +sleep 1 + +## Using awk to extract the bounds attribute for the specified resource ID +TOOLBAR_BOUNDS=$(xmllint --xpath "string(//node[@resource-id='com.android.chrome:id/search_box_text']/@bounds)" "$XML_FILE") +TABS_TRAY_BUTTON_BOUNDS=$(xmllint --xpath "string(//node[@resource-id='com.android.chrome:id/tab_switcher_button']/@bounds)" "$XML_FILE") +sleep 1 + +# Extract and calculate center coordinates in a single line +TOOLBAR_X_COORDINATE=$((($(echo "$TOOLBAR_BOUNDS" | awk -F'[][]' '{print $2}' | awk -F',' '{print $1}') + $(echo "$TOOLBAR_BOUNDS" | awk -F'[][]' '{print $4}' | awk -F',' '{print $1}')) / 2)) +TOOLBAR_Y_COORDINATE=$((($(echo "$TOOLBAR_BOUNDS" | awk -F'[][]' '{print $2}' | awk -F',' '{print $2}') + $(echo "$TOOLBAR_BOUNDS" | awk -F'[][]' '{print $4}' | awk -F',' '{print $2}')) / 2)) +TABS_TRAY_BUTTON_X_COORDINATE=$((($(echo "$TABS_TRAY_BUTTON_BOUNDS" | awk -F'[][]' '{print $2}' | awk -F',' '{print $1}') + $(echo "$TABS_TRAY_BUTTON_BOUNDS" | awk -F'[][]' '{print $4}' | awk -F',' '{print $1}')) / 2)) +TABS_TRAY_BUTTON_Y_COORDINATE=$((($(echo "$TABS_TRAY_BUTTON_BOUNDS" | awk -F'[][]' '{print $2}' | awk -F',' '{print $2}') + $(echo "$TABS_TRAY_BUTTON_BOUNDS" | awk -F'[][]' '{print $4}' | awk -F',' '{print $2}')) / 2)) + +# tap to open tabs tray +adb shell input tap $TABS_TRAY_BUTTON_X_COORDINATE $TABS_TRAY_BUTTON_Y_COORDINATE +sleep 2 + +# take ss +adb shell uiautomator dump +adb pull /sdcard/window_dump.xml + +ADD_TAB_BUTTON_BOUNDS=$(xmllint --xpath "string(//node[@resource-id='com.android.chrome:id/new_tab_view_button']/@bounds)" "$XML_FILE") +sleep 1 + +ADD_TAB_BUTTON_X_COORDINATE=$((($(echo "$ADD_TAB_BUTTON_BOUNDS" | awk -F'[][]' '{print $2}' | awk -F',' '{print $1}') + $(echo "$ADD_TAB_BUTTON_BOUNDS" | awk -F'[][]' '{print $4}' | awk -F',' '{print $1}')) / 2)) +ADD_TAB_BUTTON_Y_COORDINATE=$((($(echo "$ADD_TAB_BUTTON_BOUNDS" | awk -F'[][]' '{print $2}' | awk -F',' '{print $2}') + $(echo "$ADD_TAB_BUTTON_BOUNDS" | awk -F'[][]' '{print $4}' | awk -F',' '{print $2}')) / 2)) + +rm window_dump.xml +adb shell input keyevent KEYCODE_BACK +sleep 1 + +function tapToFocusToolbar() { + # tap on the url toolbar + adb shell input tap $TOOLBAR_X_COORDINATE $TOOLBAR_Y_COORDINATE + sleep 2 +} + +function inputTextToToolbar() { + # input url + adb shell input text $1 + sleep 2 +} + +function tapEnterAndWait5s() { + # press enter + adb shell input keyevent 66 + sleep 5 +} + +function tapEnterAndWait10s() { + # press enter + adb shell input keyevent 66 + sleep 10 +} + +function performScrollDown() { + # scroll down + adb shell input swipe 500 500 500 300 + adb shell input swipe 500 500 500 300 + adb shell input swipe 500 500 500 300 + sleep 2 +} + +function performScrollUp() { + # scroll up + adb shell input swipe 500 300 500 500 + adb shell input swipe 500 300 500 500 + adb shell input swipe 500 300 500 500 + sleep 2 +} + +function tapToOpenTabsTray() { + # tap to open tabs tray + adb shell input tap $TABS_TRAY_BUTTON_X_COORDINATE $TABS_TRAY_BUTTON_Y_COORDINATE + sleep 2 +} + +function tapToAddTab() { + # tap to open another tab + adb shell input tap $ADD_TAB_BUTTON_X_COORDINATE $ADD_TAB_BUTTON_Y_COORDINATE + sleep 3 +} + +function addTab() { + tapToOpenTabsTray + tapToAddTab +} + +function simple_browsing_single_site() { + tapToFocusToolbar + inputTextToToolbar $1 + tapEnterAndWait10s + performScrollDown + performScrollUp +} + +function simple_browsing_two_sites() { + tapToFocusToolbar + inputTextToToolbar $1 + tapEnterAndWait10s + performScrollDown + performScrollUp + tapToFocusToolbar + inputTextToToolbar $2 + tapEnterAndWait10s + performScrollDown + performScrollUp +} +# at this point our system is ready, the buttons' coordinates are generated + +# test starts after this line +simple_browsing_single_site $URL_BOOKING +addTab +simple_browsing_single_site $URL_MOZILLA +addTab +simple_browsing_single_site $URL_IMDB +addTab +simple_browsing_single_site $URL_WIKIPEDIA + +# uncomment this line if you want to stop the app +# adb shell am force-stop $PACKAGE diff --git a/battery_test/auto-test-firefox.sh b/battery_test/auto-test-firefox.sh new file mode 100755 index 0000000..477b123 --- /dev/null +++ b/battery_test/auto-test-firefox.sh @@ -0,0 +1,218 @@ +#!/bin/bash +PACKAGE="org.mozilla.firefox" +ACTIVITY="org.mozilla.fenix.HomeActivity" +XML_FILE="window_dump.xml" + +# Test urls +URL_REDDIT="https://www.reddit.com/r/all" +URL_INSTAGRAM="https://www.instagram.com/" +URL_INSTAGRAM_EXPLORE="https://www.instagram.com/explore" +URL_FACEBOOK="https://www.facebook.com" +URL_TMZ="https://tmz.com" +URL_PEREZ="https://perezhilton.com" +URL_WIKI="https://wikipedia.org/wiki/Student%27s_t-test", +URL_SEARCH_FOX="https://searchfox.org/mozilla-central/source/toolkit/components/telemetry/Histograms.json", +URL_BUZZFEED="https://buzzfeed.com" +URL_CNN="https://cnn.com" + + +# Set the total duration in seconds (30 minutes = 1800 seconds) +TOTAL_DURATION=900 +declare -i TOTAL_DURATION + +# Set the duration for each website in seconds (5 minutes = 300 seconds) +WEBSITE_DURATION=10 +declare -i WEBSITE_DURATION + +websites=("$URL_INSTAGRAM" ,"$URL_REDDIT", "$URL_INSTAGRAM_EXPLORE", "$URL_FACEBOK","$URL_TMZ", "$URL_PEREZ","$URL_WIKI", "$URL_SEARCH_FOX", "$URL_BUZZFEED","$URL_CNN" ) + +python3 battery_test.py firefox_text firefox_regular_browsing_adb 1800 \ + --start_method adb --serialID 192.168.2.132:5555 --components GPU CPU & +battery_test_pid=$! # Get the process ID (PID) +battery_test_pgid=$(ps -o pgid= -p $battery_test_pid) # Get the process group ID (PGID) + +trap 'echo "Cleaning up and exiting..."; kill -- -$battery_test_pgid; exit' SIGINT + +# script start +adb -s 192.168.2.132:5555 shell am start -n "$PACKAGE/$ACTIVITY" +sleep 4 + +adb -s 192.168.2.132:5555 shell uiautomator dump +adb -s 192.168.2.132:5555 pull /sdcard/window_dump.xml +sleep 1 + +TOOLBAR_BOUNDS=$(xmllint --xpath "string(//node[@resource-id='org.mozilla.firefox:id/toolbar']/@bounds)" "$XML_FILE") +TABS_TRAY_BUTTON_BOUNDS=$(xmllint --xpath "string(//node[@resource-id='org.mozilla.firefox:id/counter_box']/@bounds)" "$XML_FILE") +sleep 1 + +# Extract and calculate center coordinates in a single line +TOOLBAR_X_COORDINATE=$((($(echo "$TOOLBAR_BOUNDS" | awk -F'[][]' '{print $2}' | awk -F',' '{print $1}') + $(echo "$TOOLBAR_BOUNDS" | awk -F'[][]' '{print $4}' | awk -F',' '{print $1}')) / 2)) +TOOLBAR_Y_COORDINATE=$((($(echo "$TOOLBAR_BOUNDS" | awk -F'[][]' '{print $2}' | awk -F',' '{print $2}') + $(echo "$TOOLBAR_BOUNDS" | awk -F'[][]' '{print $4}' | awk -F',' '{print $2}')) / 2)) +TABS_TRAY_BUTTON_X_COORDINATE=$((($(echo "$TABS_TRAY_BUTTON_BOUNDS" | awk -F'[][]' '{print $2}' | awk -F',' '{print $1}') + $(echo "$TABS_TRAY_BUTTON_BOUNDS" | awk -F'[][]' '{print $4}' | awk -F',' '{print $1}')) / 2)) +TABS_TRAY_BUTTON_Y_COORDINATE=$((($(echo "$TABS_TRAY_BUTTON_BOUNDS" | awk -F'[][]' '{print $2}' | awk -F',' '{print $2}') + $(echo "$TABS_TRAY_BUTTON_BOUNDS" | awk -F'[][]' '{print $4}' | awk -F',' '{print $2}')) / 2)) + +# tap to open tabs tray +adb shell input tap $TABS_TRAY_BUTTON_X_COORDINATE $TABS_TRAY_BUTTON_Y_COORDINATE +sleep 2 + +# take ss +adb shell uiautomator dump +adb pull /sdcard/window_dump.xml + +ADD_TAB_BUTTON_BOUNDS=$(xmllint --xpath "string(//node[@content-desc='Add tab']/@bounds)" "$XML_FILE") +sleep 1 + +ADD_TAB_BUTTON_X_COORDINATE=$((($(echo "$ADD_TAB_BUTTON_BOUNDS" | awk -F'[][]' '{print $2}' | awk -F',' '{print $1}') + $(echo "$ADD_TAB_BUTTON_BOUNDS" | awk -F'[][]' '{print $4}' | awk -F',' '{print $1}')) / 2)) +ADD_TAB_BUTTON_Y_COORDINATE=$((($(echo "$ADD_TAB_BUTTON_BOUNDS" | awk -F'[][]' '{print $2}' | awk -F',' '{print $2}') + $(echo "$ADD_TAB_BUTTON_BOUNDS" | awk -F'[][]' '{print $4}' | awk -F',' '{print $2}')) / 2)) + +rm window_dump.xml +adb shell input keyevent KEYCODE_BACK +sleep 1 + + +function checkGoogleSignIn(){ + adb shell + +} + +function inputTextToToolbar() { + # Move the focus to the URL toolbar + adb -s 192.168.2.132:5555 shell input tap $TOOLBAR_X_COORDINATE $TOOLBAR_Y_COORDINATE + sleep 1 + + #key event to delete + adb -s 192.168.2.132:5555 shell input keyevent 67 + echo "erased" + sleep 1 + + # input url + adb -s 192.168.2.132:5555 shell input text $1 + sleep 1 + + adb -s 192.168.2.132:5555 shell input keyevent 67 +} + +function tapEnterAndWait5s() { + # press enter + adb -s 192.168.2.132:5555 shell input keyevent 66 + sleep 5 +} + +function tapEnterAndWait10s() { + # press enter + adb -s 192.168.2.132:5555 shell input keyevent 66 + sleep 10 +} + +function performScrollDown() { + # scroll down + adb -s 192.168.2.132:5555 shell input swipe 500 500 500 300 + adb -s 192.168.2.132:5555 shell input swipe 500 500 500 300 + adb -s 192.168.2.132:5555 shell input swipe 500 500 500 300 + sleep 2 +} + +function performScrollUp() { + # scroll up + adb -s 192.168.2.132:5555 shell input swipe 500 300 500 500 + adb -s 192.168.2.132:5555 shell input swipe 500 300 500 500 + adb -s 192.168.2.132:5555 shell input swipe 500 300 500 500 + sleep 2 +} + +function tapToOpenTabsTray() { + # tap to open tabs tray + adb -s 192.168.2.132:5555 shell input tap $TABS_TRAY_BUTTON_X_COORDINATE $TABS_TRAY_BUTTON_Y_COORDINATE + sleep 2 +} + +function tapToAddTab() { + # tap to open another tab + adb -s 192.168.2.132:5555 shell input tap $ADD_TAB_BUTTON_X_COORDINATE $ADD_TAB_BUTTON_Y_COORDINATE + sleep 3 +} + +function addTab() { + tapToOpenTabsTray + tapToAddTab +} + +function simple_browsing_single_site() { + echo "starting test for" + echo $1 + tapToFocusToolbar + inputTextToToolbar $1 + tapEnterAndWait10s + performScrollDown + performScrollUp +} + +function simple_browsing_two_sites() { + tapToFocusToolbar + inputTextToToolbar $1 + tapEnterAndWait10s + performScrollDown + performScrollUp + tapToFocusToolbar + inputTextToToolbar $2 + tapEnterAndWait10s + performScrollDown + performScrollUp +} +# at this point our system is ready, the buttons' coordinates are generated + +# Start of the loop +# Start of the loop +start_time=$(date +%s) +declare -i start_time +declare -i TOTAL_DURATION + +# Set the total duration in seconds (30 minutes = 1800 seconds) +TOTAL_DURATION=1800 + +start_time=$(date +%s) +declare -i start_time +declare -i TOTAL_DURATION + +# Set the total duration in seconds (30 minutes = 1800 seconds) +TOTAL_DURATION=1800 + +current_time=$(date +%s) +while [ $((current_time - start_time)) -lt $TOTAL_DURATION ]; do + + for url in "${websites[@]}"; do + tapToFocusToolbar + echo "Navigating to $url" + + inputTextToToolbar "$url" + tapEnterAndWait10s + sleep 2 + + # Start timer for the current website + website_start_time=$(date +%s) + + while [ $(( $(date +%s) - website_start_time )) -lt $WEBSITE_DURATION ]; do + performScrollDown + sleep 2 # Adjust the sleep for scrolling speed + done + + # Break out of the for loop if the total time is reached + if [[ $(date +%s) -ge $((start_time + TOTAL_DURATION)) ]]; then + echo "Total duration reached, breaking out of the loop" + break; + fi + + addTab # Add a new tab for the next website + done + current_time=$(date +%s) +done + + + + + + +# Cleanup and closing +adb -s 192.168.2.132:5555 shell am force-stop $PACKAGE +# Remove the window dump file +rm window_dump.xml diff --git a/battery_test/battery_test.py b/battery_test/battery_test.py new file mode 100644 index 0000000..38a8427 --- /dev/null +++ b/battery_test/battery_test.py @@ -0,0 +1,196 @@ +import subprocess +import time +import datetime +import os +import sys +import re +import argparse +import threading +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() + if output == '' and process.poll() is not None: + break + if output: + print(f"[{stream_name.upper()}] {output.strip()}") + sys.stdout.flush() + 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 = {} + for line in process_output.splitlines(): + parts = line.split() + if len(parts) >= 12: + 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(): + if pid in old_snapshot and (old_snapshot[pid][1] != data[1] or old_snapshot[pid][2] != data[2]): + 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+),") + types = {} + components_lower = [comp.lower() for comp in components] + for match in re.finditer(pattern, thermalservice_output): + comp_type, name = match.groups() + if comp_type.lower() in components_lower: + if comp_type not in types: + types[comp_type] = [] + types[comp_type].append(name) + return types + +def fetch_temperatures(component_names, serialID=None): + temperatures = {} + thermalservice_output = run_adb_command("dumpsys thermalservice", serialID) + hal_section = thermalservice_output.split("Current temperatures from HAL:")[1] + for comp_type, names in component_names.items(): + for name in names: + pattern_str = r"Temperature\{mValue=([\d\.]+),.*?mName=" + re.escape(name) + r"," + temp_pattern = re.compile(pattern_str, re.IGNORECASE) + temp_match = re.search(temp_pattern, hal_section) + if temp_match: + 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) + sys.exit(0) + + +def main(directory, filename, package, activity, duration, components, serialID, start_method): + last_snapshot = capture_processes(serialID) + output_path = os.path.join(directory, filename) + os.makedirs(directory, exist_ok=True) + logging_started = False + browsertime_process = None + + log_queue = queue.Queue() + + if start_method == "browsertime": + browsertime_cmd = ( + "browsertime " + "-b firefox --android " + 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;'" + ) + browsertime_process = start_browsertime_command(browsertime_cmd) + + threading.Thread(target=stream_output, args=(browsertime_process, 'stdout', log_queue)).start() + threading.Thread(target=stream_output, args=(browsertime_process, 'stderr', log_queue)).start() + + elif start_method == "manual": + start_app(package, activity, serialID) + logging_started = True + elif start_method == "adb": + logging_started = True + print("adb start do nothing") + components_names = get_component_names(components, serialID) + total_duration = round(int(duration) / 15) * 15 + num_iterations = total_duration // 15 + with open(output_path, 'w+') as file: + try: + file.write(f"Components {components} matched to these names {components_names}\n\n") + + iteration = 0 + while iteration < num_iterations: + try: + if log_queue.get_nowait(): + logging_started = True + except queue.Empty: + pass + if logging_started: + now = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') + battery_level, charge_counter = get_battery_status(serialID) + current_processes = capture_processes(serialID) + temperatures = fetch_temperatures(components_names, serialID) + file.write(f"[{(iteration + 1) * 15} seconds]\n") + + file.write("-Battery info:\n") + file.write(f" Battery level: {battery_level}\n") + file.write(f" Charge Counter: {charge_counter}\n") + print(f" Battery level: {battery_level}\n") + print(f" Charge Counter: {charge_counter}\n") + file.write("-Temperature of components:\n") + for comp, temp in temperatures.items(): + file.write(f" {comp} Temperature: {temp}°C\n") + changes = compare_and_log_changes(last_snapshot, current_processes) + if changes: + file.write("\n-Running processes:\n") + for change in changes: + file.write(f" {change}\n") + file.write("\n") + last_snapshot = current_processes + iteration += 1 + print(f'finished iteration {iteration} and spent {iteration * 15} seconds') + time.sleep(15) + + # Check if browsertime process has ended and stop logging if so + if browsertime_process and browsertime_process.poll() is not None: + logging_started = False + break + except KeyboardInterrupt: + print("Monitoring stopped.") + + 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.') + parser.add_argument('output_directory', type=str, help='Output directory path') + parser.add_argument('output_filename', type=str, help='Output filename') + + if "--start_method" in sys.argv and sys.argv[sys.argv.index("--start_method") + 1] == "manual": + parser.add_argument('package_name', type=str, help='Android package name (required for manual start)') + parser.add_argument('activity_name', type=str, help='Activity name (required for manual start)') + parser.add_argument('components', nargs='*', help='Optional list of components', default=[]) + else: + parser.add_argument('--package_name', type=str, help='Android package name (optional for browsertime)') + parser.add_argument('--activity_name', type=str, help='Activity name (optional for browsertime)') + parser.add_argument('--components', nargs='*', help='Optional list of components', default=[]) + + 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') + + 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) diff --git a/battery_test/batterytest.sh b/battery_test/batterytest.sh new file mode 100755 index 0000000..c294c58 --- /dev/null +++ b/battery_test/batterytest.sh @@ -0,0 +1,52 @@ +#!/bin/bash + +APP_PACKAGE='com.android.chrome' +MAIN_ACTIVITY='com.google.android.apps.chrome.Main' + +adb shell am start -n "$APP_PACKAGE/$MAIN_ACTIVITY" -a com.example.action.START_RECORDING + +sleep 5 + + +LAST_PROCESS_SNAPSHOT="last_processes.txt" +CURRENT_PROCESS_SNAPSHOT="current_processes.txt" + + +start_time=$(date +%s) +end_time=$((start_time + 1800)) + + +function get_battery_status() { + timestamp=$(date '+%Y-%m-%d %H:%M:%S.%3N') + echo "Timestamp: $timestamp" + echo "Battery level:" $(adb shell dumpsys battery | grep level | awk '{print $2}') + + current_charge=$(adb shell cat /sys/class/power_supply/battery/charge_counter) + echo "Timestamp: Charge Counter: $current_charge" +} + + +function capture_processes() { + adb shell top -b -n 1 | grep -E '^[0-9]' | awk '{print $1, $12, $9, $11}' > "$CURRENT_PROCESS_SNAPSHOT" +} + + +function compare_and_log_changes() { + if [ -f "$LAST_PROCESS_SNAPSHOT" ]; thenz + echo "Running tasks with changed times:" + awk 'NR==FNR {a[$1] = $4; next} ($1 in a) && (a[$1] != $4)' "$LAST_PROCESS_SNAPSHOT" "$CURRENT_PROCESS_SNAPSHOT" | \ + awk '{print " Name:", $2, "| CPU%:", $3, "| Time:", $4}' + fi + cp "$CURRENT_PROCESS_SNAPSHOT" "$LAST_PROCESS_SNAPSHOT" +} + + +capture_processes + + +while [ $(date +%s) -lt $end_time ]; do + get_battery_status + capture_processes + compare_and_log_changes + sleep 15 +done diff --git a/battery_test/cpu_use.sh b/battery_test/cpu_use.sh new file mode 100755 index 0000000..22e8e53 --- /dev/null +++ b/battery_test/cpu_use.sh @@ -0,0 +1,44 @@ +#!/bin/bash +PACKAGE="org.mozilla.firefox" +ACTIVITY="org.mozilla.fenix.HomeActivity" + + +MONITORING_DURATION=3600 + + +COLLECTION_INTERVAL=15 + + +LOG_FILE="firefox_background_usage.txt" + + +adb shell am start -n "$PACKAGE/$ACTIVITY" + +sleep 5 + + +adb shell input keyevent KEYCODE_HOME + + +start_time=$(date +%s) + +while [ $(( $(date +%s) - start_time )) -lt $MONITORING_DURATION ]; do + + adb shell dumpsys power | grep "Wake Locks" >> "$LOG_FILE" + + + echo "\n--- CPU Usage at $(date) ---" >> "$LOG_FILE" + adb shell top -n 1 | grep "$PACKAGE" >> "$LOG_FILE" + + + current_app=$(adb shell dumpsys activity activities | grep mResumedActivity) + if [[ $current_app == *"$ACTIVITY"* ]]; then + + adb shell input keyevent KEYCODE_HOME + fi + + sleep $COLLECTION_INTERVAL +done + + +adb shell am force-stop "$PACKAGE" diff --git a/battery_test/process_battery_test.py b/battery_test/process_battery_test.py new file mode 100644 index 0000000..08e7d39 --- /dev/null +++ b/battery_test/process_battery_test.py @@ -0,0 +1,161 @@ +import re +import csv +from collections import defaultdict + + +input_file_path = './chrome_test/chrome_battery_video_playback.txt' +output_file_path = './chrome_test/chrome_battery_video_playback_test.csv' +process_file_path = './chrome_test/chrome_battery_video_playback_test_process.csv' + +timestamp_regex = re.compile(r"\[(\d+) seconds\]") +battery_level_regex = re.compile(r"\s*Battery level:\s+(\d+)") +charge_counter_regex = re.compile(r"\s*Charge Counter:\s+(\d+)") +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'] + +data = [] +process_data = defaultdict(list) + +with open(input_file_path, 'r') as file: + current_entry = {} + for line in file: + + + timestamp_match = timestamp_regex.match(line) + if timestamp_match: + + if current_entry: + data.append(current_entry) + current_entry = {'Interval Time': int(timestamp_match.group(1))} + current_timestamp = int(timestamp_match.group(1)) + + battery_level_match = battery_level_regex.search(line) + if battery_level_match: + current_entry['Battery Level'] = int(battery_level_match.group(1)) + + charge_counter_match = charge_counter_regex.search(line) + if charge_counter_match: + current_entry['Charge Counter'] = int(charge_counter_match.group(1)) + + + if line.startswith("-Temperature of components:"): + temperatures = [] + + component_match = first_temperature_line_regex.match(line) + + if component_match: + 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: + temperatures.append(temp_line.strip()) + else: + break + + current_entry['Temperature of Components'] = "\n".join(temperatures) + + + + process_match = process_regex.match(line) + if process_match: + + process_name = process_match.group(1).strip() + 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) + + +for timestamp in process_data: + num_processes = len(process_data[timestamp]) + + for entry in data: + if entry['Interval Time'] == timestamp: + entry['Number of Processes'] = num_processes + break + else: + data.append({'Interval Time': timestamp, 'Number of Processes': num_processes}) + +total_charge_loss = data[0]['Charge Counter'] - data[-1]['Charge Counter'] + + +total_row = {'Interval Time': 'Total', + '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'] + writer = csv.DictWriter(csvfile, fieldnames=fieldnames) + writer.writeheader() + for entry in data: + writer.writerow(entry) + + data.append(total_row) + +aggregated_process_data = defaultdict(list) +for timestamp, processes in process_data.items(): + interval_start = (timestamp // 15) * 15 + aggregated_process_data[interval_start].extend(processes) + +with open(process_file_path, 'w', newline='') as csvfile: + fieldnames = ['Interval Time', 'Process Name', 'CPU%', 'Time'] + writer = csv.DictWriter(csvfile, fieldnames=fieldnames) + writer.writeheader() + + +for timestamp in process_data: + num_processes = len(process_data[timestamp]) + + for entry in data: + if entry['Interval Time'] == timestamp: + entry['Number of Processes'] = num_processes + break + 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) + writer.writeheader() + + current_interval = None + + for timestamp, processes in aggregated_process_data.items(): + for process in processes: + if any(keyword in process['Process Name'] for keyword in keywords): + if current_interval != timestamp: + current_interval = timestamp + writer.writerow({'Interval Time': timestamp, + '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']}) diff --git a/battery_test/scroll.sh b/battery_test/scroll.sh new file mode 100755 index 0000000..5e2389c --- /dev/null +++ b/battery_test/scroll.sh @@ -0,0 +1,142 @@ +#!/bin/bash +PACKAGE="com.android.chrome" +ACTIVITY="com.google.android.apps.chrome.Main" +XML_FILE="window_dump.xml" + +# Test urls +URL_ALL_RECIPE="https://www.allrecipes.com/" +URL_AMAZON="https://www.amazon.com/" +URL_BING="https://www.bing.com/" +URL_BING_SEARCH="https://www.bing.com/search?q=restaurants+in+exton+pa+19341" +URL_BOOKING="https://www.booking.com/" +URL_DAILY_MAIL="https://www.dailymail.co.uk/sciencetech/article-9749081/Experts-say-Hubble-repair-despite-NASA-insisting-multiple-options-fix.html" +URL_IMDB="https://m.imdb.com/" +URL_MICROSOFT="https://support.microsoft.com/en-us" +URL_STACKOVERFLOW="https://stackoverflow.com/" +URL_WIKIPEDIA="https://en.m.wikipedia.org/wiki/Main_Page" + +# script start +adb -s R5CTB1NTHSF shell am start -n "$PACKAGE/$ACTIVITY" +sleep 4 + +adb -s R5CTB1NTHSF shell uiautomator dump +adb -s R5CTB1NTHSF pull /sdcard/window_dump.xml +sleep 1 + +## Using awk to extract the bounds attribute for the specified resource ID +TOOLBAR_BOUNDS=$(xmllint --xpath "string(//node[@resource-id='com.android.chrome:id/search_box_text']/@bounds)" "$XML_FILE") +TABS_TRAY_BUTTON_BOUNDS=$(xmllint --xpath "string(//node[@resource-id='com.android.chrome:id/tab_switcher_button']/@bounds)" "$XML_FILE") +sleep 1 + +# Extract and calculate center coordinates in a single line +TOOLBAR_X_COORDINATE=$((($(echo "$TOOLBAR_BOUNDS" | awk -F'[][]' '{print $2}' | awk -F',' '{print $1}') + $(echo "$TOOLBAR_BOUNDS" | awk -F'[][]' '{print $4}' | awk -F',' '{print $1}')) / 2)) +TOOLBAR_Y_COORDINATE=$((($(echo "$TOOLBAR_BOUNDS" | awk -F'[][]' '{print $2}' | awk -F',' '{print $2}') + $(echo "$TOOLBAR_BOUNDS" | awk -F'[][]' '{print $4}' | awk -F',' '{print $2}')) / 2)) +TABS_TRAY_BUTTON_X_COORDINATE=$((($(echo "$TABS_TRAY_BUTTON_BOUNDS" | awk -F'[][]' '{print $2}' | awk -F',' '{print $1}') + $(echo "$TABS_TRAY_BUTTON_BOUNDS" | awk -F'[][]' '{print $4}' | awk -F',' '{print $1}')) / 2)) +TABS_TRAY_BUTTON_Y_COORDINATE=$((($(echo "$TABS_TRAY_BUTTON_BOUNDS" | awk -F'[][]' '{print $2}' | awk -F',' '{print $2}') + $(echo "$TABS_TRAY_BUTTON_BOUNDS" | awk -F'[][]' '{print $4}' | awk -F',' '{print $2}')) / 2)) + +# tap to open tabs tray +adb -s R5CTB1NTHSF shell input tap $TABS_TRAY_BUTTON_X_COORDINATE $TABS_TRAY_BUTTON_Y_COORDINATE +sleep 2 + +# take ss +adb -s R5CTB1NTHSF shell uiautomator dump +adb -s R5CTB1NTHSF pull /sdcard/window_dump.xml + +ADD_TAB_BUTTON_BOUNDS=$(xmllint --xpath "string(//node[@resource-id='com.android.chrome:id/new_tab_view_button']/@bounds)" "$XML_FILE") +sleep 1 + +ADD_TAB_BUTTON_X_COORDINATE=$((($(echo "$ADD_TAB_BUTTON_BOUNDS" | awk -F'[][]' '{print $2}' | awk -F',' '{print $1}') + $(echo "$ADD_TAB_BUTTON_BOUNDS" | awk -F'[][]' '{print $4}' | awk -F',' '{print $1}')) / 2)) +ADD_TAB_BUTTON_Y_COORDINATE=$((($(echo "$ADD_TAB_BUTTON_BOUNDS" | awk -F'[][]' '{print $2}' | awk -F',' '{print $2}') + $(echo "$ADD_TAB_BUTTON_BOUNDS" | awk -F'[][]' '{print $4}' | awk -F',' '{print $2}')) / 2)) + +rm window_dump.xml +adb -s R5CTB1NTHSF shell input keyevent KEYCODE_BACK +sleep 1 + +function tapToFocusToolbar() { + # tap on the url toolbar + adb -s R5CTB1NTHSF shell input tap $TOOLBAR_X_COORDINATE $TOOLBAR_Y_COORDINATE + sleep 2 +} + +function inputTextToToolbar() { + # input url + adb -s R5CTB1NTHSF shell input text $1 + sleep 2 +} + +function tapEnterAndWait5s() { + # press enter + adb -s R5CTB1NTHSF shell input keyevent 66 + sleep 5 +} + +function tapEnterAndWait10s() { + # press enter + adb -s R5CTB1NTHSF shell input keyevent 66 + sleep 10 +} + +function performScrollDown() { + # scroll down + adb -s R5CTB1NTHSF shell input swipe 500 1000 500 300 + sleep 3 +} + +function performScrollUp() { + # scroll up + adb -s R5CTB1NTHSF shell input swipe 500 300 500 1000 + sleep 3 +} + +function tapToOpenTabsTray() { + # tap to open tabs tray + adb -s R5CTB1NTHSF shell input tap $TABS_TRAY_BUTTON_X_COORDINATE $TABS_TRAY_BUTTON_Y_COORDINATE + sleep 2 +} + +function tapToAddTab() { + # tap to open another tab + adb -s R5CTB1NTHSF shell input tap $ADD_TAB_BUTTON_X_COORDINATE $ADD_TAB_BUTTON_Y_COORDINATE + sleep 3 +} + +function addTab() { + tapToOpenTabsTray + tapToAddTab +} + +function simple_browsing_single_site() { + tapToFocusToolbar + inputTextToToolbar $1 + tapEnterAndWait10s + performScrollDown + performScrollUp +} + +function simple_browsing_two_sites() { + tapToFocusToolbar + inputTextToToolbar $1 + tapEnterAndWait10s + performScrollDown + performScrollUp + tapToFocusToolbar + inputTextToToolbar $2 + tapEnterAndWait10s + performScrollDown + performScrollUp +} +# at this point our system is ready, the buttons' coordinates are generated + +# test starts after this line +simple_browsing_single_site $URL_AMAZON +addTab +simple_browsing_single_site $URL_BOOKING +addTab +simple_browsing_single_site $URL_DAILY_MAIL +addTab +simple_browsing_single_site $URL_IMDB +addTab +simple_browsing_single_site $URL_WIKIPEDIA + +# uncomment this line if you want to stop the app +adb -s R5CTB1NTHSF shell am force-stop $PACKAGE diff --git a/battery_test/test.mjs b/battery_test/test.mjs new file mode 100644 index 0000000..22a7fbf --- /dev/null +++ b/battery_test/test.mjs @@ -0,0 +1,174 @@ +var urls = [ + "https://facebook.com/", + "https://instagram.com/accounts/login/", + "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", +]; + +const MaxTime = 1800; // 30 minutes in seconds +const MinTimePerSite = 150; // 5 minutes in seconds +const MaxTimePerSite = 400; // 10 minutes in seconds + +const specialSites = { + "https://instagram.com/accounts/login/": 10, + "https://instagram.com/explore/": 400, + "https://facebook.com": 400, + "https://reddit.com/r/all": 400, + "https://amazon.ca/events/deals": 400, +}; + +let instagramLoggedIn = false; + +export default async function (context, commands) { + const delayTime = 500; + const scrollWaitTime = 7000; + const maxScrollAttempts = 10; + let startTime = Date.now(); + + for (let i = 0; i < urls.length; i++) { + let url = urls[i]; + let siteStartTime = Date.now(); + let allocatedTime = specialSites[url] || MinTimePerSite; + let minSiteTimeReached = false; + + console.log(`Navigating to ${url}.`); + + try { + await commands.switch.toNewTab(url); + console.log(`Switched to new tab for ${url}`); + await commands.wait.byTime(1000); // Wait for initial page load + console.log(`Waited on ${url}`); + + // Login to Facebook + if (url.includes("facebook.com")) { + console.log(`Logging into Facebook.`); + await commands.js.run(` + document.querySelector('[name="email"]').value = 'EMAIL'; + document.querySelector('[name="pass"]').value = 'PASSWORD'; + document.querySelector('[name="login"]').click(); + `); + await commands.wait.byTime(5000); + console.log(`Clicked login button on Facebook.`); + + await commands.js.run(` + const okButton = Array.from(document.querySelectorAll('button')) + .find(button => button.textContent.trim() === 'OK'); + if (okButton) { + okButton.click(); + } + `); + await commands.wait.byTime(5000); + console.log(`Clicked "OK" button after logging into Facebook.`); + } + + // Login to Instagram once + if (url.includes("instagram.com") && !instagramLoggedIn) { + // console.log(`Logging into Instagram.`); + + // // Check if "Switch accounts" button is present and click it + // const switchAccounts = await commands.js.run(` + // // Find the button with text containing "Continue as" + // var continueAsButton = Array.from(document.querySelectorAll('button')).find(button => button.textContent.includes("Continue as")); + + // // Click the button if found + // if (continueAsButton) { + // continueAsButton.click(); + // } else { + // console.log("Button not found"); + // } + // `); + await commands.addText.byXpath( + "EMAIL", + "//input[@aria-label='Phone number, username, or email']", + ); + await commands.addText.byXpath("PASSWORD", "//input[@type='password']"); + await commands.click.byXpathAndWait( + "//button[.//div[text()='Log in']]", + ); + await commands.wait.byTime(10000); // Wait for login to complete + instagramLoggedIn = true; + console.log(`Logged into Instagram.`); + } + + let lastScrollHeight = 0; + let newScrollHeight = 0; + + for (let attempt = 0; attempt < maxScrollAttempts; attempt++) { + if ( + (Date.now() - siteStartTime) / 1000 >= allocatedTime || + (Date.now() - startTime) / 1000 >= MaxTime + ) { + console.log(`Time limit reached for ${url}, moving to next site.`); + break; // Time limit reached, move to next site + } + + try { + console.log(`Scrolling attempt ${attempt + 1} on ${url}.`); + + lastScrollHeight = await commands.js.run( + "return document.body.scrollHeight", + ); + console.log(`Initial scroll height: ${lastScrollHeight}`); + + await commands.scroll.toBottom(delayTime); + console.log(`Scrolled to bottom on ${url}`); + await commands.wait.byTime(scrollWaitTime); // Wait to allow new content to load + console.log( + `Waited for ${scrollWaitTime / 1000} seconds after scrolling on ${url}`, + ); + + newScrollHeight = await commands.js.run( + "return document.body.scrollHeight", + ); + console.log(`New scroll height: ${newScrollHeight}`); + + if (newScrollHeight === lastScrollHeight) { + console.log( + `No more content to load on ${url}, checking minimum site time.`, + ); + if ((Date.now() - siteStartTime) / 1000 >= MinTimePerSite) { + minSiteTimeReached = true; + break; // Minimum site time reached, move to next site + } else { + console.log(`Minimum time not reached for ${url}, waiting...`); + await commands.wait.byTime( + (MinTimePerSite - (Date.now() - siteStartTime) / 1000) * 1000, + ); + minSiteTimeReached = true; + break; + } + } + } catch (scrollError) { + console.error(`Error during scrolling on ${url}:`, scrollError); + break; + } + } + + if (!minSiteTimeReached && !url.includes("instagam.com/accounts/login")) { + const remainingTime = + MinTimePerSite - (Date.now() - siteStartTime) / 1000; + if (remainingTime > 0) { + console.log( + `Waiting for ${remainingTime} seconds to reach minimum time for ${url}`, + ); + await commands.wait.byTime(remainingTime * 1000); + } + } + } catch (error) { + console.error(`Error while navigating or scrolling on ${url}:`, error); + } + + if ((Date.now() - startTime) / 1000 > MaxTime) { + console.log(`Total time limit reached. Stopping script.`); + break; + } + } + + console.log("Script finished"); +}