Initial support for running monkey in run_on_as_app.py
Change-Id: Ia6946ebeb60c0ea5c8c605a33a3ab21390492c93
diff --git a/tools/run_on_as_app.py b/tools/run_on_as_app.py
index b56f96d..a272b79 100755
--- a/tools/run_on_as_app.py
+++ b/tools/run_on_as_app.py
@@ -8,6 +8,7 @@
import optparse
import subprocess
import sys
+import time
import utils
import zipfile
@@ -27,39 +28,49 @@
# 'flavor': ... (default no flavor)
# },
'AnExplorer': {
+ 'app_id': 'dev.dworks.apps.anexplorer.pro',
'git_repo': 'https://github.com/1hakr/AnExplorer',
'flavor': 'googleMobilePro',
'signed-apk-name': 'AnExplorer-googleMobileProRelease-4.0.3.apk',
},
'AntennaPod': {
+ 'app_id': 'de.danoeh.antennapod',
'git_repo': 'https://github.com/AntennaPod/AntennaPod.git',
'flavor': 'play',
},
'apps-android-wikipedia': {
+ 'app_id': 'org.wikipedia',
'git_repo': 'https://github.com/wikimedia/apps-android-wikipedia',
'flavor': 'prod',
'signed-apk-name': 'app-prod-universal-release.apk'
},
'friendlyeats-android': {
+ 'app_id': 'com.google.firebase.example.fireeats',
'git_repo': 'https://github.com/firebase/friendlyeats-android.git'
},
'KISS': {
+ 'app_id': 'fr.neamar.kiss',
'git_repo': 'https://github.com/Neamar/KISS',
},
'materialistic': {
+ 'app_id': 'io.github.hidroh.materialistic',
'git_repo': 'https://github.com/hidroh/materialistic',
},
'Minimal-Todo': {
+ 'app_id': 'com.avjindersinghsekhon.minimaltodo',
'git_repo': 'https://github.com/avjinder/Minimal-Todo',
},
'NewPipe': {
+ 'app_id': 'org.schabi.newpipe',
'git_repo': 'https://github.com/TeamNewPipe/NewPipe',
},
'Simple-Calendar': {
+ 'app_id': 'com.simplemobiletools.calendar.pro',
'git_repo': 'https://github.com/SimpleMobileTools/Simple-Calendar',
'signed-apk-name': 'calendar-release.apk'
},
'tachiyomi': {
+ 'app_id': 'eu.kanade.tachiyomi',
'git_repo': 'https://github.com/sgjesse/tachiyomi.git',
'flavor': 'standard',
},
@@ -79,6 +90,9 @@
android_build_tools = os.path.join(
android_home, 'build-tools', android_build_tools_version)
+# TODO(christofferqa): Do not rely on 'emulator-5554' name
+emulator_id = 'emulator-5554'
+
def ComputeSizeOfDexFilesInApk(apk):
dex_size = 0
z = zipfile.ZipFile(apk, 'r')
@@ -110,6 +124,30 @@
os.remove(apk_dest)
os.rename(apk, apk_dest)
+def InstallApkOnEmulator(apk_dest):
+ subprocess.check_call(
+ ['adb', '-s', emulator_id, 'install', '-r', '-d', apk_dest])
+
+def WaitForEmulator():
+ stdout = subprocess.check_output(['adb', 'devices'])
+ if '{}\tdevice'.format(emulator_id) in stdout:
+ return
+
+ print('Emulator \'{}\' not connected; waiting for connection'.format(
+ emulator_id))
+
+ time_waited = 0
+ while True:
+ time.sleep(10)
+ time_waited += 10
+ stdout = subprocess.check_output(['adb', 'devices'])
+ if '{}\tdevice'.format(emulator_id) not in stdout:
+ print('... still waiting for connection')
+ if time_waited >= 5 * 60:
+ raise Exception('No emulator connected for 5 minutes')
+ else:
+ return
+
def BuildAppWithSelectedShrinkers(app, config, options):
git_repo = config['git_repo']
@@ -128,23 +166,37 @@
else:
as_utils.remove_r8_dependency(checkout_dir)
- dex_size_per_shrinker = {}
+ result_per_shrinker = {}
with utils.ChangedWorkingDirectory(checkout_dir):
for shrinker in SHRINKERS:
if options.shrinker is not None and shrinker != options.shrinker:
continue
- apk_dest = BuildAppWithShrinker(
- app, config, shrinker, checkout_dir, options)
+ apk_dest = None
+ result = {}
+ try:
+ apk_dest = BuildAppWithShrinker(
+ app, config, shrinker, checkout_dir, options)
+ dex_size = ComputeSizeOfDexFilesInApk(apk_dest)
+ result['apk_dest'] = apk_dest,
+ result['build_status'] = 'success'
+ result['dex_size'] = dex_size
+ except:
+ warn('Failed to build {} with {}'.format(app, shrinker))
+ result['build_status'] = 'failed'
- dex_size = ComputeSizeOfDexFilesInApk(apk_dest)
- dex_size_per_shrinker[shrinker] = dex_size
+ if options.monkey:
+ if result.get('build_status') == 'success':
+ result['monkey_status'] = 'success' if RunMonkey(
+ app, config, apk_dest) else 'failed'
+
+ result_per_shrinker[shrinker] = result
if IsTrackedByGit('gradle.properties'):
GitCheckout('gradle.properties')
- return dex_size_per_shrinker
+ return result_per_shrinker
def BuildAppWithShrinker(app, config, shrinker, checkout_dir, options):
print('Building {} with {}'.format(app, shrinker))
@@ -219,26 +271,52 @@
return apk_dest
-def LogResults(dex_size_per_shrinker_per_app):
- for app, dex_size_per_shrinker in dex_size_per_shrinker_per_app.iteritems():
+def RunMonkey(app, config, apk_dest):
+ WaitForEmulator()
+ InstallApkOnEmulator(apk_dest)
+
+ app_id = config.get('app_id')
+ number_of_events_to_generate = 50
+
+ stdout = subprocess.check_output(['adb', 'shell', 'monkey', '-p', app_id,
+ str(number_of_events_to_generate)])
+ return 'Events injected: {}'.format(number_of_events_to_generate) in stdout
+
+def LogResults(result_per_shrinker_per_app, options):
+ for app, result_per_shrinker in result_per_shrinker_per_app.iteritems():
print(app + ':')
- baseline = dex_size_per_shrinker.get('proguard', -1)
- for shrinker, dex_size in dex_size_per_shrinker.iteritems():
- if dex_size != baseline and baseline >= 0:
- if dex_size < baseline:
- success(' {}: {} ({})'.format(
- shrinker, dex_size, dex_size - baseline))
- elif dex_size > baseline:
- warn(' {}: {} ({})'.format(
- shrinker, dex_size, dex_size - baseline))
+ baseline = result_per_shrinker.get('proguard', {}).get('dex_size', -1)
+ for shrinker, result in result_per_shrinker.iteritems():
+ build_status = result.get('build_status')
+ if build_status != 'success':
+ warn(' {}: {}'.format(shrinker, build_status))
else:
- print(' {}: {}'.format(shrinker, dex_size))
+ print(' {}:'.format(shrinker))
+ dex_size = result.get('dex_size')
+ if dex_size != baseline and baseline >= 0:
+ if dex_size < baseline:
+ success(' dex size: {} ({})'.format(
+ dex_size, dex_size - baseline))
+ elif dex_size > baseline:
+ warn(' dex size: {} ({})'.format(dex_size, dex_size - baseline))
+ else:
+ print(' dex size: {}'.format(dex_size))
+ if options.monkey:
+ monkey_status = result.get('monkey_status')
+ if monkey_status != 'success':
+ warn(' monkey: {}'.format(monkey_status))
+ else:
+ success(' monkey: {}'.format(monkey_status))
def ParseOptions(argv):
result = optparse.OptionParser()
result.add_option('--app',
help='What app to run on',
choices=APPS.keys())
+ result.add_option('--monkey',
+ help='Whether to install and run app(s) with monkey',
+ default=False,
+ action='store_true')
result.add_option('--sign_apks',
help='Whether the APKs should be signed',
default=False,
@@ -247,9 +325,9 @@
help='The shrinker to use (by default, all are run)',
choices=SHRINKERS)
result.add_option('--use_tot',
- help='Whether to use the ToT version of R8',
- default=False,
- action='store_true')
+ help='Whether to disable the use of the ToT version of R8',
+ default=True,
+ action='store_false')
return result.parse_args(argv)
def main(argv):
@@ -257,18 +335,18 @@
assert not options.use_tot or os.path.isfile(utils.R8_JAR), (
'Cannot build from ToT without r8.jar')
- dex_size_per_shrinker_per_app = {}
+ result_per_shrinker_per_app = {}
if options.app:
- dex_size_per_shrinker_per_app[options.app] = BuildAppWithSelectedShrinkers(
+ result_per_shrinker_per_app[options.app] = BuildAppWithSelectedShrinkers(
options.app, APPS.get(options.app), options)
else:
for app, config in APPS.iteritems():
if not config.get('skip', False):
- dex_size_per_shrinker_per_app[app] = BuildAppWithSelectedShrinkers(
+ result_per_shrinker_per_app[app] = BuildAppWithSelectedShrinkers(
app, config, options)
- LogResults(dex_size_per_shrinker_per_app)
+ LogResults(result_per_shrinker_per_app, options)
def success(message):
CGREEN = '\033[32m'