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 tmp_dir = android_data_dir,
40 texttraces_dir = android_data_dir +
'text_blob_traces')
45 'GalaxyS20',
'MotoG4',
'NVIDIA_Shield',
46 'P30',
'Pixel4',
'Pixel4XL',
'Pixel5',
'TecnoSpark3Pro',
'JioNext']
70 'Nexus5x': range(0, 4),
72 'Pixel2XL': range(0, 4),
82 def _wait_for_device(self, title, attempt):
83 self.
m.
run(self.
m.step,
84 'adb kill-server after failure of \'%s\' (attempt %d)' % (
87 infra_step=
True, timeout=30, abort_on_failure=
False,
88 fail_build_on_failure=
False)
89 self.
m.
run(self.
m.step,
90 'wait for device after failure of \'%s\' (attempt %d)' % (
92 cmd=[self.
ADB_BINARY,
'wait-for-device'], infra_step=
True,
93 timeout=180, abort_on_failure=
False,
94 fail_build_on_failure=
False)
95 self.
m.
run(self.
m.step,
96 'adb devices -l after failure of \'%s\' (attempt %d)' % (
99 infra_step=
True, timeout=30, abort_on_failure=
False,
100 fail_build_on_failure=
False)
101 self.
m.
run(self.
m.step,
102 'adb reboot device after failure of \'%s\' (attempt %d)' % (
105 infra_step=
True, timeout=30, abort_on_failure=
False,
106 fail_build_on_failure=
False)
107 self.
m.
run(self.
m.step,
108 'wait for device after failure of \'%s\' (attempt %d)' % (
114 'while [[ -z $(getprop sys.boot_completed) ]]; do sleep 1; done',
116 timeout=180, abort_on_failure=
False,
117 fail_build_on_failure=
False)
118 device = self.
m.vars.builder_cfg.get(
'model')
121 self.
m.
run(self.
m.step,
126 timeout=180, abort_on_failure=
False,
127 fail_build_on_failure=
False)
129 def _adb(self, title, *cmd, **kwargs):
131 if 'infra_step' not in kwargs:
132 kwargs[
'infra_step'] =
True
136 attempts = kwargs.pop(
'attempts', 3)
141 with self.
m.context(cwd=self.
m.path.start_dir.join(
'skia')):
143 return self.
m.run.with_retry(self.
m.step, title, attempts,
145 between_attempts_fn=wait_for_device,
148 def _scale_for_dm(self):
149 device = self.
m.vars.builder_cfg.get(
'model')
151 self.
m.vars.internal_hardware_label):
163 if 0
not in scale_up:
167 if device ==
'AndroidOne':
169 elif device
in [
'Pixel3a',
'Pixel4',
'Pixel4a',
'Wembley',
'Pixel6',
'Pixel7']:
176 def _scale_for_nanobench(self):
177 device = self.
m.vars.builder_cfg.get(
'model')
179 self.
m.vars.internal_hardware_label):
184 if device
in [
'Pixel6',
'Pixel7']:
200 self.
m.run.with_retry(self.
m.step,
201 "Lock GPU to %d (and other perf tweaks)" % gpu_freq,
203 cmd=[
'python3', script, self.
ADB_BINARY, gpu_freq],
207 def _set_governor(self, cpu, gov):
210 self.
m.run.with_retry(self.
m.step,
211 "Set CPU %d's governor to %s" % (cpu, gov),
213 cmd=[
'python3', script, self.
ADB_BINARY, cpu, gov],
218 def _set_cpu_online(self, cpu, value):
219 """Set /sys/devices/system/cpu/cpu{N}/online to value (0 or 1)."""
229 self.
m.run.with_retry(self.
m.step,
230 '%s CPU %d' % (msg, cpu),
232 cmd=[
'python3', script, self.
ADB_BINARY, cpu, value],
234 between_attempts_fn=wait_for_device,
238 def _scale_cpu(self, cpu, target_percent):
245 self.
m.run.with_retry(self.
m.step,
246 'Scale CPU %d to %f' % (cpu, target_percent),
248 cmd=[
'python3', script, self.
ADB_BINARY, str(target_percent), cpu],
250 between_attempts_fn=wait_for_device,
254 def _asan_setup_path(self):
255 return self.
m.vars.workdir.join(
256 'android_ndk_linux',
'toolchains',
'llvm',
'prebuilt',
'linux-x86_64',
257 'lib',
'clang',
'17',
'bin',
'asan_device_setup')
263 if self.
m.vars.builder_cfg.get(
'model')
in [
'GalaxyS20',
'GalaxyS9']:
267 '/vendor/lib64/egl/libGLES_mali.so',
269 if 'ASAN' in self.
m.vars.extra_tokens:
273 self.
m.step,
'Setting up device to run ASAN',
277 abort_on_failure=
True)
290 self.
m.
run(self.
m.step,
293 infra_step=
True, timeout=30, abort_on_failure=
False,
294 fail_build_on_failure=
False)
295 self.
m.
run(self.
m.step,
296 'wait for device after rebooting',
301 'while [[ -z $(getprop sys.boot_completed) ]]; do sleep 1; done',
303 timeout=180, abort_on_failure=
False,
304 fail_build_on_failure=
False)
306 if 'ASAN' in self.
m.vars.extra_tokens:
309 self.
m.
run(self.
m.step,
310 'wait for device before uninstalling ASAN',
311 cmd=[self.
ADB_BINARY,
'wait-for-device',
'shell',
314 'while [[ -z $(getprop sys.boot_completed) ]]; do sleep 1; done',
316 timeout=180, abort_on_failure=
False,
317 fail_build_on_failure=
False)
318 self.
m.
run(self.
m.step,
'uninstall ASAN',
320 infra_step=
True, timeout=300,
321 abort_on_failure=
False, fail_build_on_failure=
False)
325 self.
m.
run(self.
m.step,
'dump log',
329 abort_on_failure=
False)
337 if (self.
m.run.failed_steps
and
338 isinstance(self.
m.run.failed_steps[0], recipe_api.InfraFailure)):
339 bot_id = self.
m.vars.swarming_bot_id
340 self.
m.file.write_text(
'Quarantining Bot',
341 '/home/chrome-bot/%s.force_quarantine' % bot_id,
348 sh =
'%s.sh' % cmd[0]
349 self.
m.run.writefile(self.
m.vars.tmp_dir.join(sh),
350 'set -x; LD_LIBRARY_PATH=%s %s%s; echo $? >%src' % (
354 self.
_adb(
'push %s' % sh,
357 self.
_adb(
'clear log',
'logcat',
'-c')
359 self.
m.
step(
'%s' % cmd[0],
363 self.
_adb(
'push %s %s' % (host, device),
'push', host, device)
366 contents = self.
m.file.glob_paths(
'ls %s/*' % host,
368 test_data=[
'foo.png',
'bar.jpg'])
369 args = contents + [device]
370 self.
_adb(
'push %s/* %s' % (host, device),
'push', *args)
375 with self.
m.step.nest(
'adb pull'):
376 tmp = self.
m.path.mkdtemp(
'adb_pull')
377 self.
_adb(
'pull %s' % device,
'pull', device, tmp)
378 paths = self.
m.file.glob_paths(
381 self.
m.path.basename(device) + self.
m.path.sep +
'*',
382 test_data=[
'%d.png' % i
for i
in (1, 2)])
384 self.
m.file.copy(
'copy %s' % self.
m.path.basename(p), p, host)
389 'abort_on_failure':
False,
390 'fail_build_on_failure':
False,
392 rv = self.
_adb(
'check if %s exists' % path,
393 'shell',
'test',
'-f', path, **testKwargs)
397 rv = self.
_adb(
'read %s' % path,
398 'shell',
'cat', path, stdout=self.
m.raw_io.output(),
400 return rv.stdout.decode(
'utf-8').rstrip()
if rv
and rv.stdout
else None
404 self.
m.run.with_retry(self.
m.step,
'rm %s' % path, 3,
405 cmd=[
'python3', script, self.
ADB_BINARY, path],
410 self.
_adb(
'mkdir %s' % path,
'shell',
'mkdir',
'-p', path)
static SkString resource(SkPDFResourceType type, int index)
def _set_cpu_online(self, cpu, value)
def read_file_on_device(self, path, **kwargs)
def copy_file_to_device(self, host, device)
def step(self, name, cmd)
def copy_directory_contents_to_device(self, host, device)
def _wait_for_device(self, title, attempt)
def __init__(self, m, app_name)
def copy_directory_contents_to_host(self, device, host)
def create_clean_device_dir(self, path)
def _asan_setup_path(self)
def remove_file_on_device(self, path)
def _scale_for_nanobench(self)
def _adb(self, title, *cmd, **kwargs)
def _set_governor(self, cpu, gov)
def _scale_cpu(self, cpu, target_percent)
def remove_file_on_device(self, path)
const myers::Point & get(const myers::Segment &)
SI auto map(std::index_sequence< I... >, Fn &&fn, const Args &... args) -> skvx::Vec< sizeof...(I), decltype(fn(args[0]...))>