Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2)

Side by Side Diff: telemetry/telemetry/internal/platform/win_platform_backend.py

Issue 3016583002: Remove Windows MSR power monitoring code (Closed)
Patch Set: Created 3 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « telemetry/telemetry/internal/platform/power_monitor/msr_power_monitor_unittest.py ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 from py_utils import atexit_with_log
6 import collections 5 import collections
7 import contextlib 6 import contextlib
8 import ctypes 7 import ctypes
9 import logging 8 import logging
10 import os
11 import platform 9 import platform
12 import re 10 import re
13 import socket
14 import struct
15 import subprocess 11 import subprocess
16 import sys 12 import sys
17 import time 13 import time
18 import zipfile
19
20 from py_utils import cloud_storage # pylint: disable=import-error
21 14
22 from telemetry.core import exceptions 15 from telemetry.core import exceptions
23 from telemetry.core import os_version as os_version_module 16 from telemetry.core import os_version as os_version_module
24 from telemetry import decorators 17 from telemetry import decorators
25 from telemetry.internal.platform import desktop_platform_backend 18 from telemetry.internal.platform import desktop_platform_backend
26 from telemetry.internal.platform.power_monitor import msr_power_monitor
27 from telemetry.internal.util import path
28 19
29 try: 20 try:
30 import pywintypes # pylint: disable=import-error 21 import pywintypes # pylint: disable=import-error
31 import win32api # pylint: disable=import-error 22 import win32api # pylint: disable=import-error
32 from win32com.shell import shell # pylint: disable=no-name-in-module 23 from win32com.shell import shell # pylint: disable=no-name-in-module
33 from win32com.shell import shellcon # pylint: disable=no-name-in-module 24 from win32com.shell import shellcon # pylint: disable=no-name-in-module
34 import win32con # pylint: disable=import-error 25 import win32con # pylint: disable=import-error
35 import win32file # pylint: disable=import-error
36 import win32gui # pylint: disable=import-error 26 import win32gui # pylint: disable=import-error
37 import win32pipe # pylint: disable=import-error
38 import win32process # pylint: disable=import-error 27 import win32process # pylint: disable=import-error
39 import winerror # pylint: disable=import-error 28 import winerror # pylint: disable=import-error
40 try: 29 try:
41 import winreg # pylint: disable=import-error 30 import winreg # pylint: disable=import-error
42 except ImportError: 31 except ImportError:
43 import _winreg as winreg # pylint: disable=import-error 32 import _winreg as winreg # pylint: disable=import-error
44 import win32security # pylint: disable=import-error 33 import win32security # pylint: disable=import-error
45 except ImportError: 34 except ImportError:
46 pywintypes = None 35 pywintypes = None
47 shell = None 36 shell = None
48 shellcon = None 37 shellcon = None
49 win32api = None 38 win32api = None
50 win32con = None 39 win32con = None
51 win32file = None 40 win32file = None
52 win32gui = None 41 win32gui = None
53 win32pipe = None 42 win32pipe = None
54 win32process = None 43 win32process = None
55 win32security = None 44 win32security = None
56 winerror = None 45 winerror = None
57 winreg = None 46 winreg = None
58 47
59 48
60 def _InstallWinRing0():
61 """WinRing0 is used for reading MSRs."""
62 executable_dir = os.path.dirname(sys.executable)
63
64 python_is_64_bit = sys.maxsize > 2 ** 32
65 dll_file_name = 'WinRing0x64.dll' if python_is_64_bit else 'WinRing0.dll'
66 dll_path = os.path.join(executable_dir, dll_file_name)
67
68 os_is_64_bit = platform.machine().endswith('64')
69 driver_file_name = 'WinRing0x64.sys' if os_is_64_bit else 'WinRing0.sys'
70 driver_path = os.path.join(executable_dir, driver_file_name)
71
72 # Check for WinRing0 and download if needed.
73 if not (os.path.exists(dll_path) and os.path.exists(driver_path)):
74 win_binary_dir = os.path.join(
75 path.GetTelemetryDir(), 'bin', 'win', 'AMD64')
76 zip_path = os.path.join(win_binary_dir, 'winring0.zip')
77 cloud_storage.GetIfChanged(zip_path, bucket=cloud_storage.PUBLIC_BUCKET)
78 try:
79 with zipfile.ZipFile(zip_path, 'r') as zip_file:
80 error_message = (
81 'Failed to extract %s into %s. If python claims that '
82 'the zip file is locked, this may be a lie. The problem may be '
83 'that python does not have write permissions to the destination '
84 'directory.'
85 )
86 # Install DLL.
87 if not os.path.exists(dll_path):
88 try:
89 zip_file.extract(dll_file_name, executable_dir)
90 except:
91 logging.error(error_message % (dll_file_name, executable_dir))
92 raise
93
94 # Install kernel driver.
95 if not os.path.exists(driver_path):
96 try:
97 zip_file.extract(driver_file_name, executable_dir)
98 except:
99 logging.error(error_message % (driver_file_name, executable_dir))
100 raise
101 finally:
102 os.remove(zip_path)
103
104
105 def TerminateProcess(process_handle):
106 if not process_handle:
107 return
108 if win32process.GetExitCodeProcess(process_handle) == win32con.STILL_ACTIVE:
109 win32process.TerminateProcess(process_handle, 0)
110 process_handle.close()
111
112
113 class WinPlatformBackend(desktop_platform_backend.DesktopPlatformBackend): 49 class WinPlatformBackend(desktop_platform_backend.DesktopPlatformBackend):
114 def __init__(self): 50 def __init__(self):
115 super(WinPlatformBackend, self).__init__() 51 super(WinPlatformBackend, self).__init__()
116 self._msr_server_handle = None
117 self._msr_server_port = None
118 self._power_monitor = msr_power_monitor.MsrPowerMonitorWin(self)
119 52
120 @classmethod 53 @classmethod
121 def IsPlatformBackendForHost(cls): 54 def IsPlatformBackendForHost(cls):
122 return sys.platform == 'win32' 55 return sys.platform == 'win32'
123 56
124 def __del__(self):
125 self.close()
126
127 def close(self):
128 self.CloseMsrServer()
129
130 def CloseMsrServer(self):
131 if not self._msr_server_handle:
132 return
133
134 TerminateProcess(self._msr_server_handle)
135 self._msr_server_handle = None
136 self._msr_server_port = None
137
138 def IsThermallyThrottled(self): 57 def IsThermallyThrottled(self):
139 raise NotImplementedError() 58 raise NotImplementedError()
140 59
141 def HasBeenThermallyThrottled(self): 60 def HasBeenThermallyThrottled(self):
142 raise NotImplementedError() 61 raise NotImplementedError()
143 62
144 def GetSystemCommitCharge(self): 63 def GetSystemCommitCharge(self):
145 performance_info = self._GetPerformanceInfo() 64 performance_info = self._GetPerformanceInfo()
146 return performance_info.CommitTotal * performance_info.PageSize / 1024 65 return performance_info.CommitTotal * performance_info.PageSize / 1024
147 66
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after
352 if proc_info['hInstApp'] <= 32: 271 if proc_info['hInstApp'] <= 32:
353 raise Exception('Unable to launch %s' % application) 272 raise Exception('Unable to launch %s' % application)
354 return proc_info['hProcess'] 273 return proc_info['hProcess']
355 else: 274 else:
356 handle, _, _, _ = win32process.CreateProcess( 275 handle, _, _, _ = win32process.CreateProcess(
357 None, application + ' ' + parameters, None, None, False, 276 None, application + ' ' + parameters, None, None, False,
358 win32process.CREATE_NO_WINDOW, None, None, win32process.STARTUPINFO()) 277 win32process.CREATE_NO_WINDOW, None, None, win32process.STARTUPINFO())
359 return handle 278 return handle
360 279
361 def CanMonitorPower(self): 280 def CanMonitorPower(self):
362 # TODO(charliea): This is a stopgap until all desktop power monitoring code
363 # can be removed. (crbug.com/763263)
364 return False 281 return False
365 282
366 def CanMeasurePerApplicationPower(self): 283 def CanMeasurePerApplicationPower(self):
367 return self._power_monitor.CanMeasurePerApplicationPower() 284 return False
368
369 def StartMonitoringPower(self, browser):
370 self._power_monitor.StartMonitoringPower(browser)
371
372 def StopMonitoringPower(self):
373 return self._power_monitor.StopMonitoringPower()
374
375 def _StartMsrServerIfNeeded(self):
376 if self._msr_server_handle:
377 return
378
379 _InstallWinRing0()
380
381 pipe_name = r"\\.\pipe\msr_server_pipe_{}".format(os.getpid())
382 # Try to open a named pipe to receive a msr port number from server process.
383 pipe = win32pipe.CreateNamedPipe(
384 pipe_name,
385 win32pipe.PIPE_ACCESS_INBOUND,
386 win32pipe.PIPE_TYPE_MESSAGE | win32pipe.PIPE_WAIT,
387 1, 32, 32, 300, None)
388 parameters = (
389 os.path.join(os.path.dirname(__file__), 'msr_server_win.py'),
390 pipe_name,
391 )
392 self._msr_server_handle = self.LaunchApplication(
393 sys.executable, parameters, elevate_privilege=True)
394 if pipe != win32file.INVALID_HANDLE_VALUE:
395 if win32pipe.ConnectNamedPipe(pipe, None) == 0:
396 self._msr_server_port = int(win32file.ReadFile(pipe, 32)[1])
397 win32api.CloseHandle(pipe)
398 # Wait for server to start.
399 try:
400 socket.create_connection(('127.0.0.1', self._msr_server_port), 5).close()
401 except socket.error:
402 self.CloseMsrServer()
403 atexit_with_log.Register(TerminateProcess, self._msr_server_handle)
404
405 def ReadMsr(self, msr_number, start=0, length=64):
406 self._StartMsrServerIfNeeded()
407 if not self._msr_server_handle:
408 raise OSError('Unable to start MSR server.')
409
410 sock = socket.create_connection(('127.0.0.1', self._msr_server_port), 5)
411 try:
412 sock.sendall(struct.pack('I', msr_number))
413 response = sock.recv(8)
414 finally:
415 sock.close()
416 return struct.unpack('Q', response)[0] >> start & ((1 << length) - 1)
417 285
418 def IsCooperativeShutdownSupported(self): 286 def IsCooperativeShutdownSupported(self):
419 return True 287 return True
420 288
421 def CooperativelyShutdown(self, proc, app_name): 289 def CooperativelyShutdown(self, proc, app_name):
422 pid = proc.pid 290 pid = proc.pid
423 291
424 # http://timgolden.me.uk/python/win32_how_do_i/ 292 # http://timgolden.me.uk/python/win32_how_do_i/
425 # find-the-window-for-my-subprocess.html 293 # find-the-window-for-my-subprocess.html
426 # 294 #
(...skipping 22 matching lines...) Expand all
449 return True 317 return True
450 hwnds = [] 318 hwnds = []
451 win32gui.EnumWindows(find_chrome_windows, hwnds) 319 win32gui.EnumWindows(find_chrome_windows, hwnds)
452 if hwnds: 320 if hwnds:
453 for hwnd in hwnds: 321 for hwnd in hwnds:
454 win32gui.SendMessage(hwnd, win32con.WM_CLOSE, 0, 0) 322 win32gui.SendMessage(hwnd, win32con.WM_CLOSE, 0, 0)
455 return True 323 return True
456 else: 324 else:
457 logging.info('Did not find any windows owned by target process') 325 logging.info('Did not find any windows owned by target process')
458 return False 326 return False
OLDNEW
« no previous file with comments | « telemetry/telemetry/internal/platform/power_monitor/msr_power_monitor_unittest.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698