6from recipe_engine
import recipe_api
7from recipe_engine
import recipe_test_api
13"""Android flavor, used for running code on Android."""
18 super(AndroidFlavor, self).
__init__(m, app_name)
22 if 'skia' not in self.
m.vars.swarming_bot_id:
23 self.
ADB_BINARY =
'/opt/infra-android/tools/adb'
25 'chrome_infrastructure_adbkey')
28 android_data_dir =
'/sdcard/revenge_of_the_skiabot/'
30 bin_dir =
'/data/local/tmp/',
31 dm_dir = android_data_dir +
'dm_out',
32 perf_data_dir = android_data_dir +
'perf',
33 resource_dir = android_data_dir +
'resources',
34 fonts_dir =
'NOT_SUPPORTED',
35 images_dir = android_data_dir +
'images',
36 lotties_dir = android_data_dir +
'lotties',
37 skp_dir = android_data_dir +
'skps',
38 svg_dir = android_data_dir +
'svgs',
39 mskp_dir = android_data_dir +
'mskp',
40 tmp_dir = android_data_dir,
41 texttraces_dir = android_data_dir +
'text_blob_traces')
46 'GalaxyS20',
'MotoG4',
'NVIDIA_Shield',
47 'P30',
'Pixel4',
'Pixel4XL',
'Pixel5',
'TecnoSpark3Pro',
'JioNext']
71 'Nexus5x': range(0, 4),
73 'Pixel2XL': range(0, 4),
84 self.
m.
run(self.
m.step,
85 'adb kill-server after failure of \'%s\' (attempt %d)' % (
88 infra_step=
True, timeout=30, abort_on_failure=
False,
89 fail_build_on_failure=
False)
90 self.
m.
run(self.
m.step,
91 'wait for device after failure of \'%s\' (attempt %d)' % (
93 cmd=[self.
ADB_BINARY,
'wait-for-device'], infra_step=
True,
94 timeout=180, abort_on_failure=
False,
95 fail_build_on_failure=
False)
96 self.
m.
run(self.
m.step,
97 'adb devices -l after failure of \'%s\' (attempt %d)' % (
100 infra_step=
True, timeout=30, abort_on_failure=
False,
101 fail_build_on_failure=
False)
102 self.
m.
run(self.
m.step,
103 'adb reboot device after failure of \'%s\' (attempt %d)' % (
106 infra_step=
True, timeout=30, abort_on_failure=
False,
107 fail_build_on_failure=
False)
108 self.
m.
run(self.
m.step,
109 'wait for device after failure of \'%s\' (attempt %d)' % (
115 'while [[ -z $(getprop sys.boot_completed) ]]; do sleep 1; done',
117 timeout=180, abort_on_failure=
False,
118 fail_build_on_failure=
False)
119 device = self.
m.vars.builder_cfg.get(
'model')
122 self.
m.
run(self.
m.step,
127 timeout=180, abort_on_failure=
False,
128 fail_build_on_failure=
False)
130 def _adb(self, title, *cmd, **kwargs):
132 if 'infra_step' not in kwargs:
133 kwargs[
'infra_step'] =
True
137 attempts = kwargs.pop(
'attempts', 3)
139 def wait_for_device(attempt):
142 with self.
m.context(cwd=self.
m.path[
'start_dir'].join(
'skia')):
144 return self.
m.run.with_retry(self.
m.step, title, attempts,
146 between_attempts_fn=wait_for_device,
150 device = self.
m.vars.builder_cfg.get(
'model')
152 self.
m.vars.internal_hardware_label):
164 if 0
not in scale_up:
168 if device ==
'AndroidOne':
170 elif device
in [
'Pixel3a',
'Pixel4',
'Pixel4a',
'Wembley',
'Pixel6',
'Pixel7']:
178 device = self.
m.vars.builder_cfg.get(
'model')
180 self.
m.vars.internal_hardware_label):
185 if device
in [
'Pixel6',
'Pixel7']:
200 script = self.
module.resource(
'set_gpu_scaling.py')
201 self.
m.run.with_retry(self.
m.step,
202 "Lock GPU to %d (and other perf tweaks)" % gpu_freq,
204 cmd=[
'python3', script, self.
ADB_BINARY, gpu_freq],
210 script = self.
module.resource(
'set_cpu_scaling_governor.py')
211 self.
m.run.with_retry(self.
m.step,
212 "Set CPU %d's governor to %s" % (cpu, gov),
214 cmd=[
'python3', script, self.
ADB_BINARY, cpu, gov],
220 """Set /sys/devices/system/cpu/cpu{N}/online to value (0 or 1)."""
226 def wait_for_device(attempt):
229 script = self.
module.resource(
'set_cpu_online.py')
230 self.
m.run.with_retry(self.
m.step,
231 '%s CPU %d' % (msg, cpu),
233 cmd=[
'python3', script, self.
ADB_BINARY, cpu, value],
235 between_attempts_fn=wait_for_device,
242 def wait_for_device(attempt):
245 script = self.
module.resource(
'scale_cpu.py')
246 self.
m.run.with_retry(self.
m.step,
247 'Scale CPU %d to %f' % (cpu, target_percent),
249 cmd=[
'python3', script, self.
ADB_BINARY, str(target_percent), cpu],
251 between_attempts_fn=wait_for_device,
256 return self.
m.vars.workdir.join(
257 'android_ndk_linux',
'toolchains',
'llvm',
'prebuilt',
'linux-x86_64',
258 'lib',
'clang',
'17',
'bin',
'asan_device_setup')
264 if self.
m.vars.builder_cfg.get(
'model')
in [
'GalaxyS20',
'GalaxyS9']:
268 '/vendor/lib64/egl/libGLES_mali.so',
270 if 'ASAN' in self.
m.vars.extra_tokens:
272 script = self.
module.resource(
'setup_device_for_asan.py')
274 self.
m.step,
'Setting up device to run ASAN',
278 abort_on_failure=
True)
291 self.
m.
run(self.
m.step,
294 infra_step=
True, timeout=30, abort_on_failure=
False,
295 fail_build_on_failure=
False)
296 self.
m.
run(self.
m.step,
297 'wait for device after rebooting',
302 'while [[ -z $(getprop sys.boot_completed) ]]; do sleep 1; done',
304 timeout=180, abort_on_failure=
False,
305 fail_build_on_failure=
False)
307 if 'ASAN' in self.
m.vars.extra_tokens:
310 self.
m.
run(self.
m.step,
311 'wait for device before uninstalling ASAN',
312 cmd=[self.
ADB_BINARY,
'wait-for-device',
'shell',
315 'while [[ -z $(getprop sys.boot_completed) ]]; do sleep 1; done',
317 timeout=180, abort_on_failure=
False,
318 fail_build_on_failure=
False)
319 self.
m.
run(self.
m.step,
'uninstall ASAN',
321 infra_step=
True, timeout=300,
322 abort_on_failure=
False, fail_build_on_failure=
False)
325 script = self.
module.resource(
'dump_adb_log.py')
326 self.
m.
run(self.
m.step,
'dump log',
330 abort_on_failure=
False)
338 if (self.
m.run.failed_steps
and
339 isinstance(self.
m.run.failed_steps[0], recipe_api.InfraFailure)):
340 bot_id = self.
m.vars.swarming_bot_id
341 self.
m.file.write_text(
'Quarantining Bot',
342 '/home/chrome-bot/%s.force_quarantine' % bot_id,
349 sh =
'%s.sh' % cmd[0]
350 self.
m.run.writefile(self.
m.vars.tmp_dir.join(sh),
351 'set -x; LD_LIBRARY_PATH=%s %s%s; echo $? >%src' % (
355 self.
_adb(
'push %s' % sh,
358 self.
_adb(
'clear log',
'logcat',
'-c')
359 script = self.
module.resource(
'run_sh.py')
360 self.
m.
step(
'%s' % cmd[0],
364 self.
_adb(
'push %s %s' % (host, device),
'push', host, device)
367 contents = self.
m.file.glob_paths(
'ls %s/*' % host,
369 test_data=[
'foo.png',
'bar.jpg'])
370 args = contents + [device]
371 self.
_adb(
'push %s/* %s' % (host, device),
'push', *args)
376 with self.
m.step.nest(
'adb pull'):
377 tmp = self.
m.path.mkdtemp(
'adb_pull')
378 self.
_adb(
'pull %s' % device,
'pull', device, tmp)
379 paths = self.
m.file.glob_paths(
382 self.
m.path.basename(device) + self.
m.path.sep +
'*',
383 test_data=[
'%d.png' % i
for i
in (1, 2)])
385 self.
m.file.copy(
'copy %s' % self.
m.path.basename(p), p, host)
390 'abort_on_failure':
False,
391 'fail_build_on_failure':
False,
393 rv = self.
_adb(
'check if %s exists' % path,
394 'shell',
'test',
'-f', path, **testKwargs)
398 rv = self.
_adb(
'read %s' % path,
399 'shell',
'cat', path, stdout=self.
m.raw_io.output(),
401 return rv.stdout.decode(
'utf-8').rstrip()
if rv
and rv.stdout
else None
404 script = self.
module.resource(
'remove_file_on_device.py')
405 self.
m.run.with_retry(self.
m.step,
'rm %s' % path, 3,
406 cmd=[
'python3', script, self.
ADB_BINARY, path],
411 self.
_adb(
'mkdir %s' % path,
'shell',
'mkdir',
'-p', path)
_wait_for_device(self, title, attempt)
read_file_on_device(self, path, **kwargs)
_set_governor(self, cpu, gov)
copy_file_to_device(self, host, device)
_adb(self, title, *cmd, **kwargs)
__init__(self, m, app_name)
create_clean_device_dir(self, path)
remove_file_on_device(self, path)
_scale_cpu(self, cpu, target_percent)
_scale_for_nanobench(self)
copy_directory_contents_to_device(self, host, device)
copy_directory_contents_to_host(self, device, host)
_set_cpu_online(self, cpu, value)
remove_file_on_device(self, path)