OLD | NEW |
1 # Copyright (c) 2015 The Chromium Authors. All rights reserved. | 1 # Copyright (c) 2015 The Chromium Authors. All rights reserved. |
2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 """Utility library for running a startup profile on an Android device. | 5 """Utility library for running a startup profile on an Android device. |
6 | 6 |
7 Sets up a device for cygprofile, disables sandboxing permissions, and sets up | 7 Sets up a device for cygprofile, disables sandboxing permissions, and sets up |
8 support for web page replay, device forwarding, and fake certificate authority | 8 support for web page replay, device forwarding, and fake certificate authority |
9 to make runs repeatable. | 9 to make runs repeatable. |
10 """ | 10 """ |
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
211 def RunCygprofileTests(self): | 211 def RunCygprofileTests(self): |
212 """Run the cygprofile unit tests suite on the device. | 212 """Run the cygprofile unit tests suite on the device. |
213 | 213 |
214 Args: | 214 Args: |
215 path_to_tests: The location on the host machine with the compiled | 215 path_to_tests: The location on the host machine with the compiled |
216 cygprofile test binary. | 216 cygprofile test binary. |
217 Returns: | 217 Returns: |
218 The exit code for the tests. | 218 The exit code for the tests. |
219 """ | 219 """ |
220 device_path = '/data/local/tmp/cygprofile_unittests' | 220 device_path = '/data/local/tmp/cygprofile_unittests' |
221 self._device.old_interface.PushIfNeeded( | 221 self._device.PushChangedFiles([(self._cygprofile_tests, device_path)]) |
222 self._cygprofile_tests, device_path) | 222 try: |
223 (exit_code, _) = ( | 223 self._device.RunShellCommand(device_path, check_return=True) |
224 self._device.old_interface.GetShellCommandStatusAndOutput( | 224 except device_errors.CommandFailedError: |
225 command=device_path, log_result=True)) | 225 # TODO(jbudorick): Let the exception propagate up once clients can |
226 return exit_code | 226 # handle it. |
| 227 logging.exception('Failure while running cygprofile_unittests:') |
| 228 return 1 |
| 229 return 0 |
227 | 230 |
228 def CollectProfile(self, apk, package_info): | 231 def CollectProfile(self, apk, package_info): |
229 """Run a profile and collect the log files. | 232 """Run a profile and collect the log files. |
230 | 233 |
231 Args: | 234 Args: |
232 apk: The location of the chrome apk to profile. | 235 apk: The location of the chrome apk to profile. |
233 package_info: A PackageInfo structure describing the chrome apk, | 236 package_info: A PackageInfo structure describing the chrome apk, |
234 as from pylib/constants. | 237 as from pylib/constants. |
235 Returns: | 238 Returns: |
236 A list of cygprofile data files. | 239 A list of cygprofile data files. |
237 Raises: | 240 Raises: |
238 NoCyglogDataError: No data was found on the device. | 241 NoCyglogDataError: No data was found on the device. |
239 """ | 242 """ |
240 self._Install(apk, package_info) | 243 self._Install(apk) |
241 | |
242 try: | 244 try: |
243 changer = self._SetChromeFlags(package_info) | 245 changer = self._SetChromeFlags(package_info) |
244 self._SetUpDeviceFolders() | 246 self._SetUpDeviceFolders() |
245 # Start up chrome once with a blank page, just to get the one-off | 247 # Start up chrome once with a blank page, just to get the one-off |
246 # activities out of the way such as apk resource extraction and profile | 248 # activities out of the way such as apk resource extraction and profile |
247 # creation. | 249 # creation. |
248 self._StartChrome(package_info, 'about:blank') | 250 self._StartChrome(package_info, 'about:blank') |
249 time.sleep(15) | 251 time.sleep(15) |
250 self._KillChrome(package_info) | 252 self._KillChrome(package_info) |
251 self._SetUpDeviceFolders() | 253 self._SetUpDeviceFolders() |
252 with WprManager(self._WPR_ARCHIVE, self._device, | 254 with WprManager(self._WPR_ARCHIVE, self._device, |
253 package_info.cmdline_file): | 255 package_info.cmdline_file): |
254 self._StartChrome(package_info, self._TEST_URL) | 256 self._StartChrome(package_info, self._TEST_URL) |
255 time.sleep(90) | 257 time.sleep(90) |
256 self._KillChrome(package_info) | 258 self._KillChrome(package_info) |
257 finally: | 259 finally: |
258 self._RestoreChromeFlags(changer) | 260 self._RestoreChromeFlags(changer) |
259 | 261 |
260 data = self._PullCyglogData() | 262 data = self._PullCyglogData() |
261 self._DeleteDeviceData() | 263 self._DeleteDeviceData() |
262 return data | 264 return data |
263 | 265 |
264 def Cleanup(self): | 266 def Cleanup(self): |
265 """Delete all local and device files left over from profiling. """ | 267 """Delete all local and device files left over from profiling. """ |
266 self._DeleteDeviceData() | 268 self._DeleteDeviceData() |
267 self._DeleteHostData() | 269 self._DeleteHostData() |
268 | 270 |
269 def _Install(self, apk, package_info): | 271 def _Install(self, apk): |
270 """Installs Chrome.apk on the device. | 272 """Installs Chrome.apk on the device. |
271 Args: | 273 Args: |
272 apk: The location of the chrome apk to profile. | 274 apk: The location of the chrome apk to profile. |
273 package_info: A PackageInfo structure describing the chrome apk, | 275 package_info: A PackageInfo structure describing the chrome apk, |
274 as from pylib/constants. | 276 as from pylib/constants. |
275 """ | 277 """ |
276 print 'Installing apk...' | 278 print 'Installing apk...' |
277 self._device.old_interface.ManagedInstall(apk, package_info.package) | 279 self._device.Install(apk) |
278 | 280 |
279 def _SetUpDevice(self): | 281 def _SetUpDevice(self): |
280 """When profiling, files are output to the disk by every process. This | 282 """When profiling, files are output to the disk by every process. This |
281 means running without sandboxing enabled. | 283 means running without sandboxing enabled. |
282 """ | 284 """ |
283 # We need to have adb root in order to pull cyglog data | 285 # We need to have adb root in order to pull cyglog data |
284 try: | 286 try: |
285 print 'Enabling root...' | 287 print 'Enabling root...' |
286 self._device.EnableRoot() | 288 self._device.EnableRoot() |
287 # SELinux need to be in permissive mode, otherwise the process cannot | 289 # SELinux need to be in permissive mode, otherwise the process cannot |
288 # write the log files. | 290 # write the log files. |
289 print 'Putting SELinux in permissive mode...' | 291 print 'Putting SELinux in permissive mode...' |
290 self._device.old_interface.RunShellCommand('setenforce 0') | 292 self._device.RunShellCommand(['setenforce' '0'], check_return=True) |
291 except device_errors.CommandFailedError as e: | 293 except device_errors.CommandFailedError as e: |
292 # TODO(jbudorick) Handle this exception appropriately once interface | 294 # TODO(jbudorick) Handle this exception appropriately once interface |
293 # conversions are finished. | 295 # conversions are finished. |
294 logging.error(str(e)) | 296 logging.error(str(e)) |
295 | 297 |
296 def _SetChromeFlags(self, package_info): | 298 def _SetChromeFlags(self, package_info): |
297 print 'Setting Chrome flags...' | 299 print 'Setting Chrome flags...' |
298 changer = flag_changer.FlagChanger( | 300 changer = flag_changer.FlagChanger( |
299 self._device, package_info.cmdline_file) | 301 self._device, package_info.cmdline_file) |
300 changer.AddFlags(['--no-sandbox', '--disable-fre']) | 302 changer.AddFlags(['--no-sandbox', '--disable-fre']) |
301 return changer | 303 return changer |
302 | 304 |
303 def _RestoreChromeFlags(self, changer): | 305 def _RestoreChromeFlags(self, changer): |
304 print 'Restoring Chrome flags...' | 306 print 'Restoring Chrome flags...' |
305 if changer: | 307 if changer: |
306 changer.Restore() | 308 changer.Restore() |
307 | 309 |
308 def _SetUpDeviceFolders(self): | 310 def _SetUpDeviceFolders(self): |
309 """Creates folders on the device to store cyglog data. """ | 311 """Creates folders on the device to store cyglog data. """ |
310 print 'Setting up device folders...' | 312 print 'Setting up device folders...' |
311 self._DeleteDeviceData() | 313 self._DeleteDeviceData() |
312 self._device.old_interface.RunShellCommand( | 314 self._device.RunShellCommand( |
313 'mkdir -p %s' % self._DEVICE_CYGLOG_DIR) | 315 ['mkdir', '-p', str(self._DEVICE_CYGLOG_DIR)], |
| 316 check_return=True) |
314 | 317 |
315 def _DeleteDeviceData(self): | 318 def _DeleteDeviceData(self): |
316 """Clears out cyglog storage locations on the device. """ | 319 """Clears out cyglog storage locations on the device. """ |
317 self._device.old_interface.RunShellCommand( | 320 self._device.RunShellCommand( |
318 'rm -rf %s' % self._DEVICE_CYGLOG_DIR) | 321 ['rm', '-rf', str(self._DEVICE_CYGLOG_DIR)], |
| 322 check_return=True) |
319 | 323 |
320 def _StartChrome(self, package_info, url): | 324 def _StartChrome(self, package_info, url): |
321 print 'Launching chrome...' | 325 print 'Launching chrome...' |
322 self._device.StartActivity( | 326 self._device.StartActivity( |
323 intent.Intent(package=package_info.package, | 327 intent.Intent(package=package_info.package, |
324 activity=package_info.activity, | 328 activity=package_info.activity, |
325 data=url, | 329 data=url, |
326 extras={'create_new_tab' : True}), | 330 extras={'create_new_tab' : True}), |
327 blocking=True, force_stop=True) | 331 blocking=True, force_stop=True) |
328 | 332 |
(...skipping 11 matching lines...) Expand all Loading... |
340 def _PullCyglogData(self): | 344 def _PullCyglogData(self): |
341 """Pull the cyglog data off of the device. | 345 """Pull the cyglog data off of the device. |
342 | 346 |
343 Returns: | 347 Returns: |
344 A list of cyglog data files which were pulled. | 348 A list of cyglog data files which were pulled. |
345 Raises: | 349 Raises: |
346 NoCyglogDataError: No data was found on the device. | 350 NoCyglogDataError: No data was found on the device. |
347 """ | 351 """ |
348 print 'Pulling cyglog data...' | 352 print 'Pulling cyglog data...' |
349 self._SetUpHostFolders() | 353 self._SetUpHostFolders() |
350 self._device.old_interface.Adb().Pull( | 354 self._device.PullFile( |
351 self._DEVICE_CYGLOG_DIR, self._host_cyglog_dir) | 355 self._DEVICE_CYGLOG_DIR, self._host_cyglog_dir) |
352 files = os.listdir(self._host_cyglog_dir) | 356 files = os.listdir(self._host_cyglog_dir) |
353 | 357 |
354 if len(files) == 0: | 358 if len(files) == 0: |
355 raise NoCyglogDataError('No cyglog data was collected') | 359 raise NoCyglogDataError('No cyglog data was collected') |
356 | 360 |
357 return [os.path.join(self._host_cyglog_dir, x) for x in files] | 361 return [os.path.join(self._host_cyglog_dir, x) for x in files] |
OLD | NEW |