xref: /aosp_15_r20/external/skia/infra/bots/recipe_modules/flavor/api.py (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1# Copyright 2016 The Chromium Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5
6# pylint: disable=W0201
7
8
9from recipe_engine import recipe_api
10
11from . import android
12from . import chromebook
13from . import default
14from . import ios
15from . import valgrind
16
17
18"""Abstractions for running code on various platforms.
19
20The methods in this module define how certain high-level functions should work.
21Each flavor should correspond to a subclass of DefaultFlavor which may override
22any of these functions as appropriate for that flavor.
23
24For example, the AndroidFlavor will override the functions for copying files
25between the host and Android device, as well as the 'step' function, so that
26commands may be run through ADB.
27"""
28
29
30VERSION_FILE_LOTTIE = 'LOTTIE_VERSION'
31VERSION_FILE_SK_IMAGE = 'SK_IMAGE_VERSION'
32VERSION_FILE_SKP = 'SKP_VERSION'
33VERSION_FILE_SVG = 'SVG_VERSION'
34VERSION_FILE_TEXTTRACES = 'TEXTTRACES_VERSION'
35
36VERSION_NONE = -1
37
38def is_android(vars_api):
39  return ('Android' in vars_api.extra_tokens or
40          'Android' in vars_api.builder_cfg.get('os', ''))
41
42def is_chromebook(vars_api):
43  return ('Chromebook' in vars_api.extra_tokens or
44          'ChromeOS' in vars_api.builder_cfg.get('os', ''))
45
46def is_ios(vars_api):
47  return ('iOS' in vars_api.extra_tokens or
48          'iOS' == vars_api.builder_cfg.get('os', ''))
49
50def is_valgrind(vars_api):
51  return 'Valgrind' in vars_api.extra_tokens
52
53
54class SkiaFlavorApi(recipe_api.RecipeApi):
55  def get_flavor(self, vars_api, app_name):
56    """Return a flavor utils object specific to the given builder."""
57    if is_chromebook(vars_api):
58      return chromebook.ChromebookFlavor(self, app_name)
59    if is_android(vars_api):
60      return android.AndroidFlavor(self, app_name)
61    elif is_ios(vars_api):
62      return ios.iOSFlavor(self, app_name)
63    elif is_valgrind(vars_api):
64      return valgrind.ValgrindFlavor(self, app_name)
65    else:
66      return default.DefaultFlavor(self, app_name)
67
68  def setup(self, app_name):
69    self._f = self.get_flavor(self.m.vars, app_name)
70    self.device_dirs = self._f.device_dirs
71    self.host_dirs = self._f.host_dirs
72    self._skia_dir = self.m.path.start_dir.joinpath('skia')
73
74  def step(self, name, cmd, **kwargs):
75    return self._f.step(name, cmd, **kwargs)
76
77  def device_path_join(self, *args):
78    return self._f.device_path_join(*args)
79
80  def copy_directory_contents_to_device(self, host_dir, device_dir):
81    return self._f.copy_directory_contents_to_device(host_dir, device_dir)
82
83  def copy_directory_contents_to_host(self, device_dir, host_dir):
84    return self._f.copy_directory_contents_to_host(device_dir, host_dir)
85
86  def copy_file_to_device(self, host_path, device_path):
87    return self._f.copy_file_to_device(host_path, device_path)
88
89  def create_clean_host_dir(self, path):
90    return self._f.create_clean_host_dir(path)
91
92  def create_clean_device_dir(self, path):
93    return self._f.create_clean_device_dir(path)
94
95  def read_file_on_device(self, path, **kwargs):
96    return self._f.read_file_on_device(path, **kwargs)
97
98  def remove_file_on_device(self, path):
99    return self._f.remove_file_on_device(path)
100
101  def install(self, skps=False, images=False, lotties=False, svgs=False,
102              resources=False, texttraces=False):
103    self._f.install()
104
105    if texttraces:
106      self._copy_texttraces()
107    # TODO(borenet): Only copy files which have changed.
108    if resources:
109      self.copy_directory_contents_to_device(
110          self.m.path.start_dir.joinpath('skia', 'resources'),
111          self.device_dirs.resource_dir)
112
113    if skps:
114      self._copy_skps()
115    if images:
116      self._copy_images()
117    if lotties:
118      self._copy_lotties()
119    if svgs:
120      self._copy_svgs()
121
122  def cleanup_steps(self):
123    return self._f.cleanup_steps()
124
125  def _copy_dir(self, host_version, version_file, tmp_dir,
126                host_path, device_path):
127    actual_version_file = self.m.path.join(tmp_dir, version_file)
128    # Copy to device.
129    device_version_file = self.device_path_join(
130        self.device_dirs.tmp_dir, version_file)
131    if str(actual_version_file) != str(device_version_file):
132      device_version = self.read_file_on_device(device_version_file,
133                                                abort_on_failure=False,
134                                                fail_build_on_failure=False)
135      if not device_version:
136        device_version = VERSION_NONE
137      if device_version != host_version:
138        self.remove_file_on_device(device_version_file)
139        self.create_clean_device_dir(device_path)
140        self.copy_directory_contents_to_device(
141            host_path, device_path)
142
143        # Copy the new version file.
144        self.copy_file_to_device(actual_version_file, device_version_file)
145
146  def _copy_images(self):
147    """Copy test images if needed."""
148    version = self.m.run.asset_version('skimage', self._skia_dir)
149    self.m.run.writefile(
150        self.m.path.join(self.m.vars.tmp_dir, VERSION_FILE_SK_IMAGE),
151        version)
152    self._copy_dir(
153        version,
154        VERSION_FILE_SK_IMAGE,
155        self.m.vars.tmp_dir,
156        self.host_dirs.images_dir,
157        self.device_dirs.images_dir)
158    return version
159
160  def _copy_lotties(self):
161    """Copy test lotties if needed."""
162    version = self.m.run.asset_version('lottie-samples', self._skia_dir)
163    self.m.run.writefile(
164        self.m.path.join(self.m.vars.tmp_dir, VERSION_FILE_LOTTIE),
165        version)
166    self._copy_dir(
167        version,
168        VERSION_FILE_LOTTIE,
169        self.m.vars.tmp_dir,
170        self.host_dirs.lotties_dir,
171        self.device_dirs.lotties_dir)
172    return version
173
174  def _copy_skps(self):
175    """Copy the SKPs if needed."""
176    version = self.m.run.asset_version('skp', self._skia_dir)
177    self.m.run.writefile(
178        self.m.path.join(self.m.vars.tmp_dir, VERSION_FILE_SKP),
179        version)
180    self._copy_dir(
181        version,
182        VERSION_FILE_SKP,
183        self.m.vars.tmp_dir,
184        self.host_dirs.skp_dir,
185        self.device_dirs.skp_dir)
186    return version
187
188  def _copy_svgs(self):
189    """Copy the SVGs if needed."""
190    version = self.m.run.asset_version('svg', self._skia_dir)
191    self.m.run.writefile(
192        self.m.path.join(self.m.vars.tmp_dir, VERSION_FILE_SVG),
193        version)
194    self._copy_dir(
195        version,
196        VERSION_FILE_SVG,
197        self.m.vars.tmp_dir,
198        self.host_dirs.svg_dir,
199        self.device_dirs.svg_dir)
200    return version
201
202  def _copy_texttraces(self):
203    """Copy the text traces if needed."""
204    version = self.m.run.asset_version('text_blob_traces', self._skia_dir)
205    self.m.run.writefile(
206        self.m.path.join(self.m.vars.tmp_dir, VERSION_FILE_TEXTTRACES),
207        version)
208    self._copy_dir(
209        version,
210        VERSION_FILE_TEXTTRACES,
211        self.m.vars.tmp_dir,
212        self.host_dirs.texttraces_dir,
213        self.device_dirs.texttraces_dir)
214    return version
215