| OLD | NEW |
| 1 # Copyright 2013 The Chromium Authors. All rights reserved. | 1 # Copyright 2013 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 import Queue | 5 import Queue |
| 6 import datetime | 6 import datetime |
| 7 import logging | 7 import logging |
| 8 import re | 8 import re |
| 9 import threading | 9 import threading |
| 10 from pylib import android_commands |
| 11 from pylib.device import device_utils |
| 10 | 12 |
| 11 | 13 |
| 12 # Log marker containing SurfaceTexture timestamps. | 14 # Log marker containing SurfaceTexture timestamps. |
| 13 _SURFACE_TEXTURE_TIMESTAMPS_MESSAGE = 'SurfaceTexture update timestamps' | 15 _SURFACE_TEXTURE_TIMESTAMPS_MESSAGE = 'SurfaceTexture update timestamps' |
| 14 _SURFACE_TEXTURE_TIMESTAMP_RE = '\d+' | 16 _SURFACE_TEXTURE_TIMESTAMP_RE = '\d+' |
| 15 | 17 |
| 16 _MIN_NORMALIZED_FRAME_LENGTH = 0.5 | 18 _MIN_NORMALIZED_FRAME_LENGTH = 0.5 |
| 17 | 19 |
| 18 | 20 |
| 19 class SurfaceStatsCollector(object): | 21 class SurfaceStatsCollector(object): |
| 20 """Collects surface stats for a SurfaceView from the output of SurfaceFlinger. | 22 """Collects surface stats for a SurfaceView from the output of SurfaceFlinger. |
| 21 | 23 |
| 22 Args: | 24 Args: |
| 23 adb: the adb connection to use. | 25 device: A DeviceUtils instance. |
| 24 """ | 26 """ |
| 25 class Result(object): | 27 class Result(object): |
| 26 def __init__(self, name, value, unit): | 28 def __init__(self, name, value, unit): |
| 27 self.name = name | 29 self.name = name |
| 28 self.value = value | 30 self.value = value |
| 29 self.unit = unit | 31 self.unit = unit |
| 30 | 32 |
| 31 def __init__(self, adb): | 33 def __init__(self, device): |
| 32 self._adb = adb | 34 # TODO(jbudorick) Remove once telemetry gets switched over. |
| 35 if isinstance(device, android_commands.AndroidCommands): |
| 36 device = device_utils.DeviceUtils(device) |
| 37 self._device = device |
| 33 self._collector_thread = None | 38 self._collector_thread = None |
| 34 self._use_legacy_method = False | 39 self._use_legacy_method = False |
| 35 self._surface_before = None | 40 self._surface_before = None |
| 36 self._get_data_event = None | 41 self._get_data_event = None |
| 37 self._data_queue = None | 42 self._data_queue = None |
| 38 self._stop_event = None | 43 self._stop_event = None |
| 39 self._results = [] | 44 self._results = [] |
| 40 self._warn_about_empty_data = True | 45 self._warn_about_empty_data = True |
| 41 | 46 |
| 42 def DisableWarningAboutEmptyData(self): | 47 def DisableWarningAboutEmptyData(self): |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 203 | 208 |
| 204 def _ClearSurfaceFlingerLatencyData(self): | 209 def _ClearSurfaceFlingerLatencyData(self): |
| 205 """Clears the SurfaceFlinger latency data. | 210 """Clears the SurfaceFlinger latency data. |
| 206 | 211 |
| 207 Returns: | 212 Returns: |
| 208 True if SurfaceFlinger latency is supported by the device, otherwise | 213 True if SurfaceFlinger latency is supported by the device, otherwise |
| 209 False. | 214 False. |
| 210 """ | 215 """ |
| 211 # The command returns nothing if it is supported, otherwise returns many | 216 # The command returns nothing if it is supported, otherwise returns many |
| 212 # lines of result just like 'dumpsys SurfaceFlinger'. | 217 # lines of result just like 'dumpsys SurfaceFlinger'. |
| 213 results = self._adb.RunShellCommand( | 218 results = self._device.old_interface.RunShellCommand( |
| 214 'dumpsys SurfaceFlinger --latency-clear SurfaceView') | 219 'dumpsys SurfaceFlinger --latency-clear SurfaceView') |
| 215 return not len(results) | 220 return not len(results) |
| 216 | 221 |
| 217 def _GetSurfaceFlingerFrameData(self): | 222 def _GetSurfaceFlingerFrameData(self): |
| 218 """Returns collected SurfaceFlinger frame timing data. | 223 """Returns collected SurfaceFlinger frame timing data. |
| 219 | 224 |
| 220 Returns: | 225 Returns: |
| 221 A tuple containing: | 226 A tuple containing: |
| 222 - The display's nominal refresh period in seconds. | 227 - The display's nominal refresh period in seconds. |
| 223 - A list of timestamps signifying frame presentation times in seconds. | 228 - A list of timestamps signifying frame presentation times in seconds. |
| (...skipping 22 matching lines...) Expand all Loading... |
| 246 # | 251 # |
| 247 # ceil((C - A) / refresh-period) | 252 # ceil((C - A) / refresh-period) |
| 248 # | 253 # |
| 249 # (each time the number above changes, we have a "jank"). | 254 # (each time the number above changes, we have a "jank"). |
| 250 # If this happens a lot during an animation, the animation appears | 255 # If this happens a lot during an animation, the animation appears |
| 251 # janky, even if it runs at 60 fps in average. | 256 # janky, even if it runs at 60 fps in average. |
| 252 # | 257 # |
| 253 # We use the special "SurfaceView" window name because the statistics for | 258 # We use the special "SurfaceView" window name because the statistics for |
| 254 # the activity's main window are not updated when the main web content is | 259 # the activity's main window are not updated when the main web content is |
| 255 # composited into a SurfaceView. | 260 # composited into a SurfaceView. |
| 256 results = self._adb.RunShellCommand( | 261 results = self._device.old_interface.RunShellCommand( |
| 257 'dumpsys SurfaceFlinger --latency SurfaceView', | 262 'dumpsys SurfaceFlinger --latency SurfaceView', |
| 258 log_result=logging.getLogger().isEnabledFor(logging.DEBUG)) | 263 log_result=logging.getLogger().isEnabledFor(logging.DEBUG)) |
| 259 if not len(results): | 264 if not len(results): |
| 260 return (None, None) | 265 return (None, None) |
| 261 | 266 |
| 262 timestamps = [] | 267 timestamps = [] |
| 263 nanoseconds_per_second = 1e9 | 268 nanoseconds_per_second = 1e9 |
| 264 refresh_period = long(results[0]) / nanoseconds_per_second | 269 refresh_period = long(results[0]) / nanoseconds_per_second |
| 265 | 270 |
| 266 # If a fence associated with a frame is still pending when we query the | 271 # If a fence associated with a frame is still pending when we query the |
| (...skipping 17 matching lines...) Expand all Loading... |
| 284 def _GetSurfaceStatsLegacy(self): | 289 def _GetSurfaceStatsLegacy(self): |
| 285 """Legacy method (before JellyBean), returns the current Surface index | 290 """Legacy method (before JellyBean), returns the current Surface index |
| 286 and timestamp. | 291 and timestamp. |
| 287 | 292 |
| 288 Calculate FPS by measuring the difference of Surface index returned by | 293 Calculate FPS by measuring the difference of Surface index returned by |
| 289 SurfaceFlinger in a period of time. | 294 SurfaceFlinger in a period of time. |
| 290 | 295 |
| 291 Returns: | 296 Returns: |
| 292 Dict of {page_flip_count (or 0 if there was an error), timestamp}. | 297 Dict of {page_flip_count (or 0 if there was an error), timestamp}. |
| 293 """ | 298 """ |
| 294 results = self._adb.RunShellCommand('service call SurfaceFlinger 1013') | 299 results = self._device.old_interface.RunShellCommand( |
| 300 'service call SurfaceFlinger 1013') |
| 295 assert len(results) == 1 | 301 assert len(results) == 1 |
| 296 match = re.search('^Result: Parcel\((\w+)', results[0]) | 302 match = re.search('^Result: Parcel\((\w+)', results[0]) |
| 297 cur_surface = 0 | 303 cur_surface = 0 |
| 298 if match: | 304 if match: |
| 299 try: | 305 try: |
| 300 cur_surface = int(match.group(1), 16) | 306 cur_surface = int(match.group(1), 16) |
| 301 except Exception: | 307 except Exception: |
| 302 logging.error('Failed to parse current surface from ' + match.group(1)) | 308 logging.error('Failed to parse current surface from ' + match.group(1)) |
| 303 else: | 309 else: |
| 304 logging.warning('Failed to call SurfaceFlinger surface ' + results[0]) | 310 logging.warning('Failed to call SurfaceFlinger surface ' + results[0]) |
| 305 return { | 311 return { |
| 306 'page_flip_count': cur_surface, | 312 'page_flip_count': cur_surface, |
| 307 'timestamp': datetime.datetime.now(), | 313 'timestamp': datetime.datetime.now(), |
| 308 } | 314 } |
| OLD | NEW |