OLD | NEW |
1 # Copyright (C) 2012 Google Inc. All rights reserved. | 1 # Copyright (C) 2012 Google Inc. All rights reserved. |
2 # | 2 # |
3 # Redistribution and use in source and binary forms, with or without | 3 # Redistribution and use in source and binary forms, with or without |
4 # modification, are permitted provided that the following conditions are | 4 # modification, are permitted provided that the following conditions are |
5 # met: | 5 # met: |
6 # | 6 # |
7 # * Redistributions of source code must retain the above copyright | 7 # * Redistributions of source code must retain the above copyright |
8 # notice, this list of conditions and the following disclaimer. | 8 # notice, this list of conditions and the following disclaimer. |
9 # * Redistributions in binary form must reproduce the above | 9 # * Redistributions in binary form must reproduce the above |
10 # copyright notice, this list of conditions and the following disclaimer | 10 # copyright notice, this list of conditions and the following disclaimer |
(...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
295 command_version = path_version | 295 command_version = path_version |
296 | 296 |
297 assert command_path, 'Unable to locate the "adb" command. Are you using
an Android checkout of Chromium?' | 297 assert command_path, 'Unable to locate the "adb" command. Are you using
an Android checkout of Chromium?' |
298 | 298 |
299 AndroidCommands._adb_command_path = command_path | 299 AndroidCommands._adb_command_path = command_path |
300 return command_path | 300 return command_path |
301 | 301 |
302 # Local private methods. | 302 # Local private methods. |
303 | 303 |
304 def _log_error(self, message): | 304 def _log_error(self, message): |
305 _log.error('[%s] %s' % (self._device_serial, message)) | 305 _log.error('[%s] %s', self._device_serial, message) |
306 | 306 |
307 def _log_info(self, message): | 307 def _log_info(self, message): |
308 _log.info('[%s] %s' % (self._device_serial, message)) | 308 _log.info('[%s] %s', self._device_serial, message) |
309 | 309 |
310 def _log_debug(self, message): | 310 def _log_debug(self, message): |
311 if self._debug_logging: | 311 if self._debug_logging: |
312 _log.debug('[%s] %s' % (self._device_serial, message)) | 312 _log.debug('[%s] %s', self._device_serial, message) |
313 | 313 |
314 @staticmethod | 314 @staticmethod |
315 def _determine_adb_version(adb_command_path, executive, debug_logging): | 315 def _determine_adb_version(adb_command_path, executive, debug_logging): |
316 re_version = re.compile('^.*version ([\d\.]+)') | 316 re_version = re.compile('^.*version ([\d\.]+)') |
317 try: | 317 try: |
318 output = executive.run_command([adb_command_path, 'version'], error_
handler=executive.ignore_error, | 318 output = executive.run_command([adb_command_path, 'version'], error_
handler=executive.ignore_error, |
319 debug_logging=debug_logging) | 319 debug_logging=debug_logging) |
320 except OSError: | 320 except OSError: |
321 return None | 321 return None |
322 | 322 |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
360 | 360 |
361 result = executive.run_command([AndroidCommands.adb_command_path(executi
ve, debug_logging=self._debug_logging), 'devices'], | 361 result = executive.run_command([AndroidCommands.adb_command_path(executi
ve, debug_logging=self._debug_logging), 'devices'], |
362 error_handler=executive.ignore_error, deb
ug_logging=self._debug_logging) | 362 error_handler=executive.ignore_error, deb
ug_logging=self._debug_logging) |
363 devices = re_device.findall(result) | 363 devices = re_device.findall(result) |
364 if not devices: | 364 if not devices: |
365 return [] | 365 return [] |
366 | 366 |
367 for device_serial in sorted(devices): | 367 for device_serial in sorted(devices): |
368 commands = AndroidCommands(executive, device_serial, self._debug_log
ging) | 368 commands = AndroidCommands(executive, device_serial, self._debug_log
ging) |
369 if self._battery_level_for_device(commands) < AndroidDevices.MINIMUM
_BATTERY_PERCENTAGE: | 369 if self._battery_level_for_device(commands) < AndroidDevices.MINIMUM
_BATTERY_PERCENTAGE: |
370 _log.warning('Device with serial "%s" skipped because it has les
s than %d percent battery.' | 370 _log.warning('Device with serial "%s" skipped because it has les
s than %d percent battery.', |
371 % (commands.get_serial(), AndroidDevices.MINIMUM_BA
TTERY_PERCENTAGE)) | 371 commands.get_serial(), AndroidDevices.MINIMUM_BATTE
RY_PERCENTAGE) |
372 continue | 372 continue |
373 | 373 |
374 if not self._is_device_screen_on(commands): | 374 if not self._is_device_screen_on(commands): |
375 _log.warning('Device with serial "%s" skipped because the screen
must be on.' % commands.get_serial()) | 375 _log.warning('Device with serial "%s" skipped because the screen
must be on.', commands.get_serial()) |
376 continue | 376 continue |
377 | 377 |
378 self._usable_devices.append(commands) | 378 self._usable_devices.append(commands) |
379 | 379 |
380 return self._usable_devices | 380 return self._usable_devices |
381 | 381 |
382 def get_device(self, executive, device_index): | 382 def get_device(self, executive, device_index): |
383 devices = self.usable_devices(executive) | 383 devices = self.usable_devices(executive) |
384 if device_index >= len(devices): | 384 if device_index >= len(devices): |
385 raise AssertionError('Device index exceeds number of usable devices.
') | 385 raise AssertionError('Device index exceeds number of usable devices.
') |
386 | 386 |
387 return devices[device_index] | 387 return devices[device_index] |
388 | 388 |
389 def is_device_prepared(self, device_serial): | 389 def is_device_prepared(self, device_serial): |
390 return device_serial in self._prepared_devices | 390 return device_serial in self._prepared_devices |
391 | 391 |
392 def set_device_prepared(self, device_serial): | 392 def set_device_prepared(self, device_serial): |
393 self._prepared_devices.append(device_serial) | 393 self._prepared_devices.append(device_serial) |
394 | 394 |
395 # Private methods | 395 # Private methods |
396 def _battery_level_for_device(self, commands): | 396 def _battery_level_for_device(self, commands): |
397 battery_status = commands.run(['shell', 'dumpsys', 'battery']) | 397 battery_status = commands.run(['shell', 'dumpsys', 'battery']) |
398 if 'Error' in battery_status or "Can't find service: battery" in battery
_status: | 398 if 'Error' in battery_status or "Can't find service: battery" in battery
_status: |
399 _log.warning('Unable to read the battery level from device with seri
al "%s".' % commands.get_serial()) | 399 _log.warning('Unable to read the battery level from device with seri
al "%s".', commands.get_serial()) |
400 return 0 | 400 return 0 |
401 | 401 |
402 return int(re.findall('level: (\d+)', battery_status)[0]) | 402 return int(re.findall('level: (\d+)', battery_status)[0]) |
403 | 403 |
404 def _is_device_screen_on(self, commands): | 404 def _is_device_screen_on(self, commands): |
405 power_status = commands.run(['shell', 'dumpsys', 'power']) | 405 power_status = commands.run(['shell', 'dumpsys', 'power']) |
406 return 'mScreenOn=true' in power_status or 'mScreenOn=SCREEN_ON_BIT' in
power_status or 'Display Power: state=ON' in power_status | 406 return 'mScreenOn=true' in power_status or 'mScreenOn=SCREEN_ON_BIT' in
power_status or 'Display Power: state=ON' in power_status |
407 | 407 |
408 | 408 |
409 class AndroidPort(base.Port): | 409 class AndroidPort(base.Port): |
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
552 callback("[%s] %s" % (serial, msg)) | 552 callback("[%s] %s" % (serial, msg)) |
553 finally: | 553 finally: |
554 lock.release() | 554 lock.release() |
555 | 555 |
556 log_safely("preparing device", throttled=False) | 556 log_safely("preparing device", throttled=False) |
557 try: | 557 try: |
558 d._setup_test(log_safely) | 558 d._setup_test(log_safely) |
559 log_safely("device prepared", throttled=False) | 559 log_safely("device prepared", throttled=False) |
560 except (ScriptError, driver.DeviceFailure) as e: | 560 except (ScriptError, driver.DeviceFailure) as e: |
561 lock.acquire() | 561 lock.acquire() |
562 _log.warning("[%s] failed to prepare_device: %s" % (serial, str(
e))) | 562 _log.warning("[%s] failed to prepare_device: %s", serial, str(e)
) |
563 lock.release() | 563 lock.release() |
564 except KeyboardInterrupt: | 564 except KeyboardInterrupt: |
565 if pool: | 565 if pool: |
566 pool.terminate() | 566 pool.terminate() |
567 | 567 |
568 # FIXME: It would be nice if we knew how many workers we needed. | 568 # FIXME: It would be nice if we knew how many workers we needed. |
569 num_workers = self.default_child_processes() | 569 num_workers = self.default_child_processes() |
570 num_child_processes = int(self.get_option('child_processes')) | 570 num_child_processes = int(self.get_option('child_processes')) |
571 if num_child_processes: | 571 if num_child_processes: |
572 num_workers = min(num_workers, num_child_processes) | 572 num_workers = min(num_workers, num_child_processes) |
(...skipping 28 matching lines...) Expand all Loading... |
601 | 601 |
602 def check_sys_deps(self, needs_http): | 602 def check_sys_deps(self, needs_http): |
603 for (font_dirs, font_file, package) in HOST_FONT_FILES: | 603 for (font_dirs, font_file, package) in HOST_FONT_FILES: |
604 exists = False | 604 exists = False |
605 for font_dir in font_dirs: | 605 for font_dir in font_dirs: |
606 font_path = font_dir + font_file | 606 font_path = font_dir + font_file |
607 if self._check_file_exists(font_path, '', more_logging=False): | 607 if self._check_file_exists(font_path, '', more_logging=False): |
608 exists = True | 608 exists = True |
609 break | 609 break |
610 if not exists: | 610 if not exists: |
611 _log.error('You are missing %s under %s. Try installing %s. See
build instructions.' % | 611 _log.error('You are missing %s under %s. Try installing %s. See
build instructions.', |
612 (font_file, font_dirs, package)) | 612 font_file, font_dirs, package) |
613 return test_run_results.SYS_DEPS_EXIT_STATUS | 613 return test_run_results.SYS_DEPS_EXIT_STATUS |
614 return test_run_results.OK_EXIT_STATUS | 614 return test_run_results.OK_EXIT_STATUS |
615 | 615 |
616 def requires_http_server(self): | 616 def requires_http_server(self): |
617 """Chromium Android runs tests on devices, and uses the HTTP server to | 617 """Chromium Android runs tests on devices, and uses the HTTP server to |
618 serve the actual layout tests to the test driver.""" | 618 serve the actual layout tests to the test driver.""" |
619 return True | 619 return True |
620 | 620 |
621 def start_http_server(self, additional_dirs, number_of_drivers): | 621 def start_http_server(self, additional_dirs, number_of_drivers): |
622 additional_dirs[PERF_TEST_PATH_PREFIX] = self.perf_tests_dir() | 622 additional_dirs[PERF_TEST_PATH_PREFIX] = self.perf_tests_dir() |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
691 def __init__(self, host, executable_path, output_dir, android_commands, symf
s_path, kallsyms_path, identifier=None): | 691 def __init__(self, host, executable_path, output_dir, android_commands, symf
s_path, kallsyms_path, identifier=None): |
692 super(AndroidPerf, self).__init__(host, executable_path, output_dir, "da
ta", identifier) | 692 super(AndroidPerf, self).__init__(host, executable_path, output_dir, "da
ta", identifier) |
693 self._android_commands = android_commands | 693 self._android_commands = android_commands |
694 self._perf_process = None | 694 self._perf_process = None |
695 self._symfs_path = symfs_path | 695 self._symfs_path = symfs_path |
696 self._kallsyms_path = kallsyms_path | 696 self._kallsyms_path = kallsyms_path |
697 | 697 |
698 def check_configuration(self): | 698 def check_configuration(self): |
699 # Check that perf is installed | 699 # Check that perf is installed |
700 if not self._android_commands.file_exists('/system/bin/perf'): | 700 if not self._android_commands.file_exists('/system/bin/perf'): |
701 _log.error("Cannot find /system/bin/perf on device %s" % self._andro
id_commands.get_serial()) | 701 _log.error("Cannot find /system/bin/perf on device %s", self._androi
d_commands.get_serial()) |
702 return False | 702 return False |
703 | 703 |
704 # Check that the device is a userdebug build (or at least has the necess
ary libraries). | 704 # Check that the device is a userdebug build (or at least has the necess
ary libraries). |
705 if self._android_commands.run(['shell', 'getprop', 'ro.build.type']).str
ip() != 'userdebug': | 705 if self._android_commands.run(['shell', 'getprop', 'ro.build.type']).str
ip() != 'userdebug': |
706 _log.error("Device %s is not flashed with a userdebug build of Andro
id" % self._android_commands.get_serial()) | 706 _log.error("Device %s is not flashed with a userdebug build of Andro
id", self._android_commands.get_serial()) |
707 return False | 707 return False |
708 | 708 |
709 # FIXME: Check that the binary actually is perf-able (has stackframe poi
nters)? | 709 # FIXME: Check that the binary actually is perf-able (has stackframe poi
nters)? |
710 # objdump -s a function and make sure it modifies the fp? | 710 # objdump -s a function and make sure it modifies the fp? |
711 # Instruct users to rebuild after export GYP_DEFINES="profiling=1 $GYP_D
EFINES" | 711 # Instruct users to rebuild after export GYP_DEFINES="profiling=1 $GYP_D
EFINES" |
712 return True | 712 return True |
713 | 713 |
714 def print_setup_instructions(self): | 714 def print_setup_instructions(self): |
715 _log.error(""" | 715 _log.error(""" |
716 perf on android requires a 'userdebug' build of Android, see: | 716 perf on android requires a 'userdebug' build of Android, see: |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
759 self._cached_perf_host_path = self._find_perfhost_binary() | 759 self._cached_perf_host_path = self._find_perfhost_binary() |
760 return self._cached_perf_host_path | 760 return self._cached_perf_host_path |
761 | 761 |
762 def _first_ten_lines_of_profile(self, perf_output): | 762 def _first_ten_lines_of_profile(self, perf_output): |
763 match = re.search("^#[^\n]*\n((?: [^\n]*\n){1,10})", perf_output, re.MUL
TILINE) | 763 match = re.search("^#[^\n]*\n((?: [^\n]*\n){1,10})", perf_output, re.MUL
TILINE) |
764 return match.group(1) if match else None | 764 return match.group(1) if match else None |
765 | 765 |
766 def profile_after_exit(self): | 766 def profile_after_exit(self): |
767 perf_exitcode = self._perf_process.wait() | 767 perf_exitcode = self._perf_process.wait() |
768 if perf_exitcode != 0: | 768 if perf_exitcode != 0: |
769 _log.debug("Perf failed (exit code: %i), can't process results." % p
erf_exitcode) | 769 _log.debug("Perf failed (exit code: %i), can't process results.", pe
rf_exitcode) |
770 return | 770 return |
771 | 771 |
772 self._android_commands.pull('/data/perf.data', self._output_path) | 772 self._android_commands.pull('/data/perf.data', self._output_path) |
773 | 773 |
774 perfhost_path = self._perfhost_path() | 774 perfhost_path = self._perfhost_path() |
775 perfhost_report_command = [ | 775 perfhost_report_command = [ |
776 'report', | 776 'report', |
777 '--input', self._output_path, | 777 '--input', self._output_path, |
778 '--symfs', self._symfs_path, | 778 '--symfs', self._symfs_path, |
779 '--kallsyms', self._kallsyms_path, | 779 '--kallsyms', self._kallsyms_path, |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
848 | 848 |
849 def _update_kallsyms_cache(self, output_dir): | 849 def _update_kallsyms_cache(self, output_dir): |
850 kallsyms_name = "%s-kallsyms" % self._android_commands.get_serial() | 850 kallsyms_name = "%s-kallsyms" % self._android_commands.get_serial() |
851 kallsyms_cache_path = self._port.host.filesystem.join(output_dir, kallsy
ms_name) | 851 kallsyms_cache_path = self._port.host.filesystem.join(output_dir, kallsy
ms_name) |
852 | 852 |
853 self._android_commands.restart_as_root() | 853 self._android_commands.restart_as_root() |
854 | 854 |
855 saved_kptr_restrict = self._android_commands.run(['shell', 'cat', KPTR_R
ESTRICT_PATH]).strip() | 855 saved_kptr_restrict = self._android_commands.run(['shell', 'cat', KPTR_R
ESTRICT_PATH]).strip() |
856 self._android_commands.run(['shell', 'echo', '0', '>', KPTR_RESTRICT_PAT
H]) | 856 self._android_commands.run(['shell', 'echo', '0', '>', KPTR_RESTRICT_PAT
H]) |
857 | 857 |
858 _log.debug("Updating kallsyms file (%s) from device" % kallsyms_cache_pa
th) | 858 _log.debug("Updating kallsyms file (%s) from device", kallsyms_cache_pat
h) |
859 self._android_commands.pull("/proc/kallsyms", kallsyms_cache_path) | 859 self._android_commands.pull("/proc/kallsyms", kallsyms_cache_path) |
860 | 860 |
861 self._android_commands.run(['shell', 'echo', saved_kptr_restrict, '>', K
PTR_RESTRICT_PATH]) | 861 self._android_commands.run(['shell', 'echo', saved_kptr_restrict, '>', K
PTR_RESTRICT_PATH]) |
862 | 862 |
863 return kallsyms_cache_path | 863 return kallsyms_cache_path |
864 | 864 |
865 def _find_or_create_symfs(self): | 865 def _find_or_create_symfs(self): |
866 env = self._port.host.environ.copy() | 866 env = self._port.host.environ.copy() |
867 fs = self._port.host.filesystem | 867 fs = self._port.host.filesystem |
868 | 868 |
869 if 'ANDROID_SYMFS' in env: | 869 if 'ANDROID_SYMFS' in env: |
870 symfs_path = env['ANDROID_SYMFS'] | 870 symfs_path = env['ANDROID_SYMFS'] |
871 else: | 871 else: |
872 symfs_path = fs.join(self._port.results_directory(), 'symfs') | 872 symfs_path = fs.join(self._port.results_directory(), 'symfs') |
873 _log.debug("ANDROID_SYMFS not set, using %s" % symfs_path) | 873 _log.debug("ANDROID_SYMFS not set, using %s", symfs_path) |
874 | 874 |
875 # find the installed path, and the path of the symboled built library | 875 # find the installed path, and the path of the symboled built library |
876 # FIXME: We should get the install path from the device! | 876 # FIXME: We should get the install path from the device! |
877 symfs_library_path = fs.join(symfs_path, "data/app-lib/%s-1/%s" % | 877 symfs_library_path = fs.join(symfs_path, "data/app-lib/%s-1/%s" % |
878 (self._driver_details.package_name(), self.
_driver_details.library_name())) | 878 (self._driver_details.package_name(), self.
_driver_details.library_name())) |
879 built_library_path = self._port._build_path('lib', self._driver_details.
library_name()) | 879 built_library_path = self._port._build_path('lib', self._driver_details.
library_name()) |
880 assert fs.exists(built_library_path) | 880 assert fs.exists(built_library_path) |
881 | 881 |
882 # FIXME: Ideally we'd check the sha1's first and make a soft-link instea
d | 882 # FIXME: Ideally we'd check the sha1's first and make a soft-link instea
d |
883 # of copying (since we probably never care about windows). | 883 # of copying (since we probably never care about windows). |
884 _log.debug("Updating symfs library (%s) from built copy (%s)" % (symfs_l
ibrary_path, built_library_path)) | 884 _log.debug("Updating symfs library (%s) from built copy (%s)", symfs_lib
rary_path, built_library_path) |
885 fs.maybe_make_directory(fs.dirname(symfs_library_path)) | 885 fs.maybe_make_directory(fs.dirname(symfs_library_path)) |
886 fs.copyfile(built_library_path, symfs_library_path) | 886 fs.copyfile(built_library_path, symfs_library_path) |
887 | 887 |
888 return symfs_path | 888 return symfs_path |
889 | 889 |
890 def _setup_md5sum_and_push_data_if_needed(self, log_callback): | 890 def _setup_md5sum_and_push_data_if_needed(self, log_callback): |
891 self._md5sum_path = self._port.path_to_md5sum() | 891 self._md5sum_path = self._port.path_to_md5sum() |
892 if not self._android_commands.file_exists(MD5SUM_DEVICE_PATH): | 892 if not self._android_commands.file_exists(MD5SUM_DEVICE_PATH): |
893 if not self._android_commands.push(self._md5sum_path, MD5SUM_DEVICE_
PATH): | 893 if not self._android_commands.push(self._md5sum_path, MD5SUM_DEVICE_
PATH): |
894 self._abort('Could not push md5sum to device') | 894 self._abort('Could not push md5sum to device') |
(...skipping 24 matching lines...) Expand all Loading... |
919 self._android_commands.mkdir(self._driver_details.device_directory(), ch
mod='777') | 919 self._android_commands.mkdir(self._driver_details.device_directory(), ch
mod='777') |
920 self._android_commands.mkdir(self._driver_details.device_fifo_directory(
), chmod='777') | 920 self._android_commands.mkdir(self._driver_details.device_fifo_directory(
), chmod='777') |
921 | 921 |
922 # Make sure that the disk cache on the device resets to a clean state. | 922 # Make sure that the disk cache on the device resets to a clean state. |
923 self._android_commands.run(['shell', 'rm', '-r', self._driver_details.de
vice_cache_directory()]) | 923 self._android_commands.run(['shell', 'rm', '-r', self._driver_details.de
vice_cache_directory()]) |
924 | 924 |
925 # Mark this device as having been set up. | 925 # Mark this device as having been set up. |
926 self._android_devices.set_device_prepared(self._android_commands.get_ser
ial()) | 926 self._android_devices.set_device_prepared(self._android_commands.get_ser
ial()) |
927 | 927 |
928 def _log_error(self, message): | 928 def _log_error(self, message): |
929 _log.error('[%s] %s' % (self._android_commands.get_serial(), message)) | 929 _log.error('[%s] %s', self._android_commands.get_serial(), message) |
930 | 930 |
931 def _log_warning(self, message): | 931 def _log_warning(self, message): |
932 _log.warning('[%s] %s' % (self._android_commands.get_serial(), message)) | 932 _log.warning('[%s] %s', self._android_commands.get_serial(), message) |
933 | 933 |
934 def _log_debug(self, message): | 934 def _log_debug(self, message): |
935 if self._debug_logging: | 935 if self._debug_logging: |
936 _log.debug('[%s] %s' % (self._android_commands.get_serial(), message
)) | 936 _log.debug('[%s] %s', self._android_commands.get_serial(), message) |
937 | 937 |
938 def _abort(self, message): | 938 def _abort(self, message): |
939 self._device_failed = True | 939 self._device_failed = True |
940 raise driver.DeviceFailure('[%s] %s' % (self._android_commands.get_seria
l(), message)) | 940 raise driver.DeviceFailure('[%s] %s' % (self._android_commands.get_seria
l(), message)) |
941 | 941 |
942 @staticmethod | 942 @staticmethod |
943 def _extract_hashes_from_md5sum_output(md5sum_output): | 943 def _extract_hashes_from_md5sum_output(md5sum_output): |
944 assert md5sum_output | 944 assert md5sum_output |
945 return [line.split(' ')[0] for line in md5sum_output] | 945 return [line.split(' ')[0] for line in md5sum_output] |
946 | 946 |
(...skipping 360 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1307 return command | 1307 return command |
1308 | 1308 |
1309 def _read_prompt(self, deadline): | 1309 def _read_prompt(self, deadline): |
1310 last_char = '' | 1310 last_char = '' |
1311 while True: | 1311 while True: |
1312 current_char = self._server_process.read_stdout(deadline, 1) | 1312 current_char = self._server_process.read_stdout(deadline, 1) |
1313 if current_char == ' ': | 1313 if current_char == ' ': |
1314 if last_char in ('#', '$'): | 1314 if last_char in ('#', '$'): |
1315 return | 1315 return |
1316 last_char = current_char | 1316 last_char = current_char |
OLD | NEW |