Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 # Copyright 2014 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 import logging | |
| 5 import os | |
| 6 import re | |
| 7 import subprocess | |
| 8 import sys | |
| 9 | |
| 10 from telemetry.core import android_app | |
| 11 from telemetry.core import exceptions | |
| 12 from telemetry.core import platform | |
| 13 from telemetry.core import util | |
| 14 from telemetry.core import wpr_modes | |
| 15 from telemetry.core.backends import adb_commands | |
| 16 from telemetry.core.backends import android_app_backend | |
| 17 from telemetry.core.platform import android_device | |
| 18 from telemetry.user_story import shared_user_story_state | |
| 19 from telemetry.web_perf import timeline_based_measurement | |
| 20 | |
| 21 try: | |
| 22 import psutil # pylint: disable=import-error | |
| 23 except ImportError: | |
| 24 psutil = None | |
| 25 | |
| 26 | |
| 27 class SharedAppState(shared_user_story_state.SharedUserStoryState): | |
| 28 def __init__(self, test, finder_options, user_story_set): | |
| 29 super(SharedAppState, self).__init__(test, finder_options, user_story_set) | |
| 30 # SharedAppState only supports TimelineBasedMeasurement (TBM). | |
| 31 # TODO(slamm): This SharedAppState does not yet interact with TBM yet | |
| 32 # because TBM still has browser based logic. | |
| 33 assert isinstance(test, timeline_based_measurement.TimelineBasedMeasurement) | |
| 34 self._finder_options = finder_options | |
| 35 self._android_app = None | |
| 36 self._current_user_story = None | |
| 37 self._platform = GetPlatform(finder_options) | |
| 38 assert self._platform, 'Unable to create android platform.' | |
| 39 | |
| 40 @property | |
| 41 def platform(self): | |
| 42 return self._platform | |
| 43 | |
| 44 @property | |
| 45 def _platform_backend(self): | |
|
nednguyen
2014/12/05 20:15:22
This is a hack. If there is no plan to fix this in
slamm
2014/12/06 00:40:00
Done.
slamm
2014/12/06 00:40:00
Done.
| |
| 46 return self._platform._platform_backend | |
| 47 | |
| 48 def _PrepareWpr(self, network_controller, archive_path, | |
| 49 make_javascript_deterministic=True): | |
| 50 browser_options = self._finder_options.browser_options | |
| 51 if self._finder_options.use_live_sites: | |
| 52 browser_options.wpr_mode = wpr_modes.WPR_OFF | |
| 53 elif browser_options.wpr_mode != wpr_modes.WPR_RECORD: | |
| 54 browser_options.wpr_mode = ( | |
| 55 wpr_modes.WPR_REPLAY | |
| 56 if archive_path and os.path.isfile(archive_path) | |
| 57 else wpr_modes.WPR_OFF) | |
| 58 | |
| 59 # Replay's life-cycle is tied to the browser. Start and Stop are handled by | |
| 60 # platform_backend.DidCreateBrowser and platform_backend.WillCloseBrowser, | |
| 61 # respectively. | |
| 62 # TODO(slamm): Update life-cycle comment with https://crbug.com/424777 fix. | |
| 63 wpr_mode = browser_options.wpr_mode | |
| 64 network_controller.SetReplayArgs( | |
| 65 archive_path, wpr_mode, browser_options.netsim, | |
| 66 browser_options.extra_wpr_args, make_javascript_deterministic) | |
| 67 | |
| 68 def WillRunUserStory(self, user_story): | |
| 69 assert not self._android_app | |
| 70 self._current_user_story = user_story | |
| 71 #self._PrepareWpr(self.platform.network_controller, user_story.archive_path) | |
| 72 | |
| 73 # TODO(chrishenry): Should this be moved to | |
| 74 # SharedAndroidAppState.DidRunUserStory? | |
| 75 self._platform_backend.DismissCrashDialogIfNeeded() | |
| 76 | |
| 77 start_intent = user_story.start_intent | |
| 78 platform_backend = self.platform._platform_backend # pylint: disable=W0212 | |
| 79 app_backend = android_app_backend.AndroidAppBackend( | |
| 80 platform_backend, start_intent) | |
| 81 self._android_app = android_app.AndroidApp(app_backend, platform_backend) | |
| 82 | |
| 83 def RunUserStory(self, results): | |
| 84 # CHEAT HAXX0R!! | |
| 85 self._current_user_story.Run() | |
| 86 | |
| 87 def DidRunUserStory(self, results): | |
| 88 if self._android_app: | |
| 89 self._android_app.Close() | |
| 90 self._android_app = None | |
| 91 | |
| 92 def GetTestExpectationAndSkipValue(self, expectations): | |
| 93 # TODO(chrishenry): Implement this properly. | |
| 94 return 'pass', None | |
| 95 | |
| 96 def TearDownState(self, results): | |
| 97 pass | |
| 98 | |
| 99 | |
| 100 def GetPlatform(finder_options): | |
| 101 """Finds all the desktop browsers available on this machine.""" | |
| 102 if not CanFindDevices(): | |
| 103 logging.info('No adb command found. ' + | |
| 104 'Will not try searching for Android browsers.') | |
| 105 return None | |
| 106 | |
| 107 if finder_options.android_device: | |
| 108 devices = [android_device.AndroidDevice( | |
| 109 finder_options.android_device, | |
| 110 enable_performance_mode=not finder_options.no_performance_mode)] | |
| 111 else: | |
| 112 devices = android_device.AndroidDevice.GetAllConnectedDevices() | |
| 113 | |
| 114 if len(devices) == 0: | |
| 115 logging.info('No android devices found.') | |
| 116 return None | |
| 117 elif len(devices) > 1: | |
| 118 logging.warn( | |
| 119 'Multiple devices attached. Please specify one of the following:\n' + | |
| 120 '\n'.join([' --device=%s' % d.device_id for d in devices])) | |
| 121 return None | |
| 122 | |
| 123 try: | |
| 124 android_platform = platform.GetPlatformForDevice(devices[0]) | |
| 125 except exceptions.PlatformError: | |
| 126 return None | |
| 127 | |
| 128 # Host side workaround for crbug.com/268450 (adb instability). | |
| 129 # The adb server has a race which is mitigated by binding to a single core. | |
| 130 if psutil: | |
| 131 for proc in psutil.process_iter(): | |
| 132 try: | |
| 133 if 'adb' in proc.name: | |
| 134 if 'cpu_affinity' in dir(proc): | |
| 135 proc.cpu_affinity([0]) # New versions of psutil. | |
| 136 elif 'set_cpu_affinity' in dir(proc): | |
| 137 proc.set_cpu_affinity([0]) # Older versions. | |
| 138 else: | |
| 139 logging.warn( | |
| 140 'Cannot set CPU affinity due to stale psutil version: %s', | |
| 141 '.'.join(str(x) for x in psutil.version_info)) | |
| 142 except (psutil.NoSuchProcess, psutil.AccessDenied): | |
| 143 logging.warn('Failed to set adb process CPU affinity') | |
| 144 | |
| 145 return android_platform | |
| 146 | |
| 147 | |
| 148 def CanFindDevices(): | |
| 149 if not adb_commands.IsAndroidSupported(): | |
| 150 logging.info('Android build commands unavailable on this machine. Have ' | |
| 151 'you installed Android build dependencies?') | |
| 152 return False | |
| 153 | |
| 154 try: | |
| 155 with open(os.devnull, 'w') as devnull: | |
| 156 proc = subprocess.Popen( | |
| 157 ['adb', 'devices'], | |
| 158 stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=devnull) | |
| 159 stdout, _ = proc.communicate() | |
| 160 if re.search(re.escape('????????????\tno permissions'), stdout) != None: | |
| 161 logging.warn('adb devices reported a permissions error. Consider ' | |
| 162 'restarting adb as root:') | |
| 163 logging.warn(' adb kill-server') | |
| 164 logging.warn(' sudo `which adb` devices\n\n') | |
| 165 return True | |
| 166 except OSError: | |
| 167 platform_tools_path = os.path.join(util.GetChromiumSrcDir(), | |
| 168 'third_party', 'android_tools', 'sdk', 'platform-tools') | |
| 169 if (sys.platform.startswith('linux') and | |
| 170 os.path.exists(os.path.join(platform_tools_path, 'adb'))): | |
| 171 os.environ['PATH'] = os.pathsep.join([platform_tools_path, | |
| 172 os.environ['PATH']]) | |
| 173 return True | |
| 174 return False | |
| OLD | NEW |