OLD | NEW |
---|---|
(Empty) | |
1 #!/usr/bin/env python | |
2 # | |
3 # Copyright 2016 Google Inc. | |
4 # | |
5 # Use of this source code is governed by a BSD-style license that can be | |
6 # found in the LICENSE file. | |
7 | |
8 | |
9 import android_devices | |
10 import copy | |
rmistry
2016/02/18 15:29:21
unused
borenet
2016/02/18 15:40:56
Done.
| |
11 import default_flavor | |
12 import os | |
13 | |
14 | |
15 """Android flavor utils, used for building for and running tests on Android.""" | |
16 | |
17 | |
18 class _ADBWrapper(object): | |
19 """Wrapper for ADB.""" | |
20 def __init__(self, path_to_adb, serial, android_flavor): | |
21 self._adb = path_to_adb | |
22 self._serial = serial | |
23 self._wait_count = 0 | |
24 self._android_flavor = android_flavor | |
25 | |
26 def wait_for_device(self): | |
27 """Run 'adb wait-for-device'.""" | |
28 self._wait_count += 1 | |
29 cmd = [ | |
30 os.path.join(self._android_flavor.android_bin, 'adb_wait_for_device'), | |
31 '-s', self._serial, | |
32 ] | |
33 self._android_flavor._bot_info.run( | |
34 cmd, env=self._android_flavor._default_env) | |
35 | |
36 def maybe_wait_for_device(self): | |
37 """Run 'adb wait-for-device' if it hasn't already been run.""" | |
38 if self._wait_count == 0: | |
39 self.wait_for_device() | |
40 | |
41 def __call__(self, *args, **kwargs): | |
42 self.maybe_wait_for_device() | |
43 return self._android_flavor._bot_info.run(self._adb + args, **kwargs) | |
44 | |
45 | |
46 class AndroidFlavorUtils(default_flavor.DefaultFlavorUtils): | |
47 def __init__(self, skia_api): | |
48 super(AndroidFlavorUtils, self).__init__(skia_api) | |
49 self.device = self._bot_info.spec['device_cfg'] | |
50 slave_info = android_devices.SLAVE_INFO.get( | |
51 self._bot_info.slave_name, | |
52 android_devices.SLAVE_INFO['default']) | |
53 self.serial = slave_info.serial | |
54 self.android_bin = os.path.join( | |
55 self._bot_info.skia_dir, 'platform_tools', 'android', 'bin') | |
56 self._android_sdk_root = slave_info.android_sdk_root | |
57 self._adb = _ADBWrapper( | |
58 os.path.join(self._android_sdk_root, 'platform-tools', 'adb'), | |
59 self.serial, | |
60 self) | |
61 self._has_root = slave_info.has_root | |
62 self._default_env = {'ANDROID_SDK_ROOT': self._android_sdk_root, | |
63 'ANDROID_HOME': self._android_sdk_root, | |
64 'SKIA_ANDROID_VERBOSE_SETUP': '1'} | |
65 | |
66 def step(self, name, cmd, env=None, **kwargs): | |
67 self._adb.maybe_wait_for_device() | |
68 args = [self.android_bin.join('android_run_skia'), | |
69 '--verbose', | |
70 '--logcat', | |
71 '-d', self.device, | |
72 '-s', self.serial, | |
73 '-t', self._bot_info.configuration, | |
74 ] | |
75 env = dict(env or {}) | |
76 env.update(self._default_env) | |
77 | |
78 return self._bot_info.run(self._bot_info.m.step, name=name, cmd=args + cmd, | |
79 env=env, **kwargs) | |
80 | |
81 def compile(self, target): | |
82 """Build the given target.""" | |
83 env = dict(self._default_env) | |
84 ccache = self._bot_info.ccache | |
85 if ccache: | |
86 env['ANDROID_MAKE_CCACHE'] = ccache | |
87 | |
88 cmd = [os.path.join(self.android_bin, 'android_ninja'), target, | |
89 '-d', self.device] | |
90 if 'Clang' in self._bot_info.name: | |
91 cmd.append('--clang') | |
92 self._bot_info.run(cmd, env=env) | |
93 | |
94 def device_path_join(self, *args): | |
95 """Like os.path.join(), but for paths on a connected Android device.""" | |
96 return '/'.join(args) | |
97 | |
98 def device_path_exists(self, path): | |
99 """Like os.path.exists(), but for paths on a connected device.""" | |
100 exists_str = 'FILE_EXISTS' | |
101 return exists_str in self._adb( | |
102 name='exists %s' % self._bot_info.m.path.basename(path), | |
103 serial=self.serial, | |
104 cmd=['shell', 'if', '[', '-e', path, '];', | |
105 'then', 'echo', exists_str + ';', 'fi'], | |
106 stdout=self._bot_info.m.raw_io.output(), | |
107 infra_step=True | |
108 ).stdout | |
109 | |
110 def _remove_device_dir(self, path): | |
111 """Remove the directory on the device.""" | |
112 self._adb(name='rmdir %s' % self._bot_info.m.path.basename(path), | |
113 serial=self.serial, | |
114 cmd=['shell', 'rm', '-r', path], | |
115 infra_step=True) | |
116 # Sometimes the removal fails silently. Verify that it worked. | |
117 if self.device_path_exists(path): | |
118 raise Exception('Failed to remove %s!' % path) # pragma: no cover | |
119 | |
120 def _create_device_dir(self, path): | |
121 """Create the directory on the device.""" | |
122 self._adb(name='mkdir %s' % self._bot_info.m.path.basename(path), | |
123 serial=self.serial, | |
124 cmd=['shell', 'mkdir', '-p', path], | |
125 infra_step=True) | |
126 | |
127 def copy_directory_contents_to_device(self, host_dir, device_dir): | |
128 """Like shutil.copytree(), but for copying to a connected device.""" | |
129 self._bot_info.run( | |
130 self._bot_info.m.step, | |
131 name='push %s' % self._bot_info.m.path.basename(host_dir), | |
132 cmd=[self.android_bin.join('adb_push_if_needed'), '--verbose', | |
133 '-s', self.serial, host_dir, device_dir], | |
134 env=self._default_env, | |
135 infra_step=True) | |
136 | |
137 def copy_directory_contents_to_host(self, device_dir, host_dir): | |
138 """Like shutil.copytree(), but for copying from a connected device.""" | |
139 self._bot_info.run( | |
140 self._bot_info.m.step, | |
141 name='pull %s' % self._bot_info.m.path.basename(device_dir), | |
142 cmd=[self.android_bin.join('adb_pull_if_needed'), '--verbose', | |
143 '-s', self.serial, device_dir, host_dir], | |
144 env=self._default_env, | |
145 infra_step=True) | |
146 | |
147 def copy_file_to_device(self, host_path, device_path): | |
148 """Like shutil.copyfile, but for copying to a connected device.""" | |
149 self._adb(name='push %s' % self._bot_info.m.path.basename(host_path), | |
150 serial=self.serial, | |
151 cmd=['push', host_path, device_path], | |
152 infra_step=True) | |
153 | |
154 def create_clean_device_dir(self, path): | |
155 """Like shutil.rmtree() + os.makedirs(), but on a connected device.""" | |
156 self._remove_device_dir(path) | |
157 self._create_device_dir(path) | |
158 | |
159 def install(self): | |
160 """Run device-specific installation steps.""" | |
161 if self._has_root: | |
162 self._adb(name='adb root', | |
163 serial=self.serial, | |
164 cmd=['root'], | |
165 infra_step=True) | |
166 # Wait for the device to reconnect. | |
167 self._bot_info.run( | |
168 self._bot_info.m.step, | |
169 name='wait', | |
170 cmd=['sleep', '10'], | |
171 infra_step=True) | |
172 self._adb.wait_for_device() | |
173 | |
174 # TODO(borenet): Set CPU scaling mode to 'performance'. | |
175 self._bot_info.run(self._bot_info.m.step, | |
176 name='kill skia', | |
177 cmd=[self.android_bin.join('android_kill_skia'), | |
178 '--verbose', '-s', self.serial], | |
179 env=self._default_env, | |
180 infra_step=True) | |
181 if self._has_root: | |
182 self._adb(name='stop shell', | |
183 serial=self.serial, | |
184 cmd=['shell', 'stop'], | |
185 infra_step=True) | |
186 | |
187 # Print out battery stats. | |
188 self._adb(name='starting battery stats', | |
189 serial=self.serial, | |
190 cmd=['shell', 'dumpsys', 'batteryproperties'], | |
191 infra_step=True) | |
192 | |
193 def cleanup_steps(self): | |
194 """Run any device-specific cleanup steps.""" | |
195 self._adb(name='final battery stats', | |
196 serial=self.serial, | |
197 cmd=['shell', 'dumpsys', 'batteryproperties'], | |
198 infra_step=True) | |
199 self._adb(name='reboot', | |
200 serial=self.serial, | |
201 cmd=['reboot'], | |
202 infra_step=True) | |
203 self._bot_info.run( | |
204 self._bot_info.m.step, | |
205 name='wait for reboot', | |
206 cmd=['sleep', '10'], | |
207 infra_step=True) | |
208 self._adb.wait_for_device() | |
209 | |
210 def read_file_on_device(self, path, *args, **kwargs): | |
211 """Read the given file.""" | |
212 return self._adb(name='read %s' % self._bot_info.m.path.basename(path), | |
213 serial=self.serial, | |
214 cmd=['shell', 'cat', path], | |
215 stdout=self._bot_info.m.raw_io.output(), | |
216 infra_step=True).stdout.rstrip() | |
217 | |
218 def remove_file_on_device(self, path, *args, **kwargs): | |
219 """Delete the given file.""" | |
220 return self._adb(name='rm %s' % self._bot_info.m.path.basename(path), | |
221 serial=self.serial, | |
222 cmd=['shell', 'rm', '-f', path], | |
223 infra_step=True, | |
224 *args, | |
225 **kwargs) | |
226 | |
227 def get_device_dirs(self): | |
228 """ Set the directories which will be used by the build steps.""" | |
229 device_scratch_dir = self._adb( | |
230 name='get EXTERNAL_STORAGE dir', | |
231 serial=self.serial, | |
232 cmd=['shell', 'echo', '$EXTERNAL_STORAGE'], | |
233 ) | |
234 prefix = self.device_path_join(device_scratch_dir, 'skiabot', 'skia_') | |
235 return default_flavor.DeviceDirs( | |
236 dm_dir=prefix + 'dm', | |
237 perf_data_dir=prefix + 'perf', | |
238 resource_dir=prefix + 'resources', | |
239 images_dir=prefix + 'images', | |
240 skp_dir=prefix + 'skp/skps', | |
241 tmp_dir=prefix + 'tmp_dir') | |
242 | |
OLD | NEW |