#!/usr/bin/env bash # # Prepares the device for the macrobenchmark module, and takes it back afterwards. # # ./tools/benchmark-fixture.sh # create the folder, grant storage access # ./tools/benchmark-fixture.sh --remove # delete the folder again # # Why this is a script rather than setup inside the benchmark: UiAutomation's executeShellCommand # runs with the *test app's* uid, not the shell's, so it cannot write to /sdcard and cannot grant # itself an app-op. The first version of the benchmark tried exactly that and failed with a # RuntimeException from UiAutomationConnection, leaving no fixture and a hang. Through adb the same # commands run as the shell user, which has the rights this needs. # # The folder is at the root of shared storage under a name that sorts before everything else, so the # benchmark finds its row without scrolling. set -euo pipefail package=de.softwareapp_hb.filemanager directory=/sdcard/AABenchmark count=1000 # The size is a knob because the interesting question is how the browser scales: 1 000 files is what the # benchmark uses by default, and 5 000 or 20 000 is the same run with a bigger folder: # # ./tools/benchmark-fixture.sh --count 20000 # # Creating is idempotent: a folder that already holds at least `--count` files is left alone, because # building twenty thousand files through a phone's storage layer takes about half an hour and the fixture # is worth keeping between runs. `--fresh` rebuilds it anyway. if [ "${1:-}" = "--count" ]; then count=${2:?"--count needs a number"} case "$count" in ''|*[!0-9]*) echo "benchmark-fixture: --count needs a number, not '$count'" >&2; exit 2 ;; esac shift 2 fi fresh=0 if [ "${1:-}" = "--fresh" ]; then fresh=1 shift fi case "${1:-create}" in --remove) adb shell "rm -rf $directory" echo "benchmark-fixture: removed $directory" ;; create) existing=$(adb shell "ls $directory 2>/dev/null | wc -l" | tr -d '\r ') if [ "$fresh" -eq 0 ] && [ "${existing:-0}" -ge "$count" ]; then echo "benchmark-fixture: reusing $directory ($existing files, $count asked for)" else # One shell loop with builtin redirection: no fork per file, so a thousand files take a # moment rather than a minute. adb shell "rm -rf $directory; mkdir -p $directory; \ i=0; while [ \$i -lt $count ]; do : > $directory/file-\$i.txt; i=\$((i+1)); done" echo "benchmark-fixture: $count files in $directory" fi # The benchmark build is not the debug build, so it starts with no storage grant; granting it # here is what lets the run be unattended. No `--uid`: that flag takes a uid, not a package # name, and passing a package there grants nothing while still reporting that something was # set — which is exactly the kind of half-truth that costs an afternoon. Re-granted even when the # fixture is reused, because a reinstall of the app clears its app-ops. adb shell "appops set $package MANAGE_EXTERNAL_STORAGE allow" echo "benchmark-fixture: storage granted to $package" ;; *) echo "usage: $0 [--remove]" >&2 exit 2 ;; esac