Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / tools / telemetry / telemetry / core / platform / win_platform_backend.py
1 # Copyright (c) 2013 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
5 import collections
6 import ctypes
7 import platform
8 import re
9 import subprocess
10 import time
11 try:
12   import pywintypes  # pylint: disable=F0401
13   import win32api  # pylint: disable=F0401
14   import win32con  # pylint: disable=F0401
15   import win32process  # pylint: disable=F0401
16 except ImportError:
17   pywintypes = None
18   win32api = None
19   win32con = None
20   win32process = None
21
22 from telemetry import decorators
23 from telemetry.core import exceptions
24 from telemetry.core.platform import desktop_platform_backend
25 from telemetry.core.platform import platform_backend
26
27
28 class WinPlatformBackend(desktop_platform_backend.DesktopPlatformBackend):
29   # pylint: disable=W0613
30   def StartRawDisplayFrameRateMeasurement(self):
31     raise NotImplementedError()
32
33   def StopRawDisplayFrameRateMeasurement(self):
34     raise NotImplementedError()
35
36   def GetRawDisplayFrameRateMeasurements(self):
37     raise NotImplementedError()
38
39   def IsThermallyThrottled(self):
40     raise NotImplementedError()
41
42   def HasBeenThermallyThrottled(self):
43     raise NotImplementedError()
44
45   def GetSystemCommitCharge(self):
46     performance_info = self._GetPerformanceInfo()
47     return performance_info.CommitTotal * performance_info.PageSize / 1024
48
49   @decorators.Cache
50   def GetSystemTotalPhysicalMemory(self):
51     performance_info = self._GetPerformanceInfo()
52     return performance_info.PhysicalTotal * performance_info.PageSize / 1024
53
54   def GetCpuStats(self, pid):
55     cpu_info = self._GetWin32ProcessInfo(win32process.GetProcessTimes, pid)
56     # Convert 100 nanosecond units to seconds
57     cpu_time = (cpu_info['UserTime'] / 1e7 +
58                 cpu_info['KernelTime'] / 1e7)
59     return {'CpuProcessTime': cpu_time}
60
61   def GetCpuTimestamp(self):
62     """Return current timestamp in seconds."""
63     return {'TotalTime': time.time()}
64
65   def GetMemoryStats(self, pid):
66     memory_info = self._GetWin32ProcessInfo(
67         win32process.GetProcessMemoryInfo, pid)
68     return {'VM': memory_info['PagefileUsage'],
69             'VMPeak': memory_info['PeakPagefileUsage'],
70             'WorkingSetSize': memory_info['WorkingSetSize'],
71             'WorkingSetSizePeak': memory_info['PeakWorkingSetSize']}
72
73   def GetIOStats(self, pid):
74     io_stats = self._GetWin32ProcessInfo(win32process.GetProcessIoCounters, pid)
75     return {'ReadOperationCount': io_stats['ReadOperationCount'],
76             'WriteOperationCount': io_stats['WriteOperationCount'],
77             'ReadTransferCount': io_stats['ReadTransferCount'],
78             'WriteTransferCount': io_stats['WriteTransferCount']}
79
80   def KillProcess(self, pid, kill_process_tree=False):
81     # os.kill for Windows is Python 2.7.
82     cmd = ['taskkill', '/F', '/PID', str(pid)]
83     if kill_process_tree:
84       cmd.append('/T')
85     subprocess.Popen(cmd, stdout=subprocess.PIPE,
86                      stderr=subprocess.STDOUT).wait()
87
88   def GetSystemProcessInfo(self):
89     # [3:] To skip 2 blank lines and header.
90     lines = subprocess.Popen(
91         ['wmic', 'process', 'get',
92          'CommandLine,CreationDate,Name,ParentProcessId,ProcessId',
93          '/format:csv'],
94         stdout=subprocess.PIPE).communicate()[0].splitlines()[3:]
95     process_info = []
96     for line in lines:
97       if not line:
98         continue
99       parts = line.split(',')
100       pi = {}
101       pi['ProcessId'] = int(parts[-1])
102       pi['ParentProcessId'] = int(parts[-2])
103       pi['Name'] = parts[-3]
104       creation_date = None
105       if parts[-4]:
106         creation_date = float(re.split('[+-]', parts[-4])[0])
107       pi['CreationDate'] = creation_date
108       pi['CommandLine'] = ','.join(parts[1:-4])
109       process_info.append(pi)
110     return process_info
111
112   def GetChildPids(self, pid):
113     """Retunds a list of child pids of |pid|."""
114     ppid_map = collections.defaultdict(list)
115     creation_map = {}
116     for pi in self.GetSystemProcessInfo():
117       ppid_map[pi['ParentProcessId']].append(pi['ProcessId'])
118       if pi['CreationDate']:
119         creation_map[pi['ProcessId']] = pi['CreationDate']
120
121     def _InnerGetChildPids(pid):
122       if not pid or pid not in ppid_map:
123         return []
124       ret = [p for p in ppid_map[pid] if creation_map[p] >= creation_map[pid]]
125       for child in ret:
126         if child == pid:
127           continue
128         ret.extend(_InnerGetChildPids(child))
129       return ret
130
131     return _InnerGetChildPids(pid)
132
133   def GetCommandLine(self, pid):
134     for pi in self.GetSystemProcessInfo():
135       if pid == pi['ProcessId']:
136         return pi['CommandLine']
137     raise exceptions.ProcessGoneException()
138
139   def GetOSName(self):
140     return 'win'
141
142   @decorators.Cache
143   def GetOSVersionName(self):
144     os_version = platform.uname()[3]
145
146     if os_version.startswith('5.1.'):
147       return platform_backend.OSVersion('xp', 5.1)
148     if os_version.startswith('6.0.'):
149       return platform_backend.OSVersion('vista', 6.0)
150     if os_version.startswith('6.1.'):
151       return platform_backend.OSVersion('win7', 6.1)
152     if os_version.startswith('6.2.'):
153       return platform_backend.OSVersion('win8', 6.2)
154
155     raise NotImplementedError('Unknown win version %s.' % os_version)
156
157   def CanFlushIndividualFilesFromSystemCache(self):
158     return True
159
160   def GetFlushUtilityName(self):
161     return 'clear_system_cache.exe'
162
163   def _GetWin32ProcessInfo(self, func, pid):
164     mask = (win32con.PROCESS_QUERY_INFORMATION |
165             win32con.PROCESS_VM_READ)
166     handle = None
167     try:
168       handle = win32api.OpenProcess(mask, False, pid)
169       return func(handle)
170     except pywintypes.error, e:
171       errcode = e[0]
172       if errcode == 87:
173         raise exceptions.ProcessGoneException()
174       raise
175     finally:
176       if handle:
177         win32api.CloseHandle(handle)
178
179   def _GetPerformanceInfo(self):
180     class PerformanceInfo(ctypes.Structure):
181       """Struct for GetPerformanceInfo() call
182       http://msdn.microsoft.com/en-us/library/ms683210
183       """
184       _fields_ = [('size', ctypes.c_ulong),
185                   ('CommitTotal', ctypes.c_size_t),
186                   ('CommitLimit', ctypes.c_size_t),
187                   ('CommitPeak', ctypes.c_size_t),
188                   ('PhysicalTotal', ctypes.c_size_t),
189                   ('PhysicalAvailable', ctypes.c_size_t),
190                   ('SystemCache', ctypes.c_size_t),
191                   ('KernelTotal', ctypes.c_size_t),
192                   ('KernelPaged', ctypes.c_size_t),
193                   ('KernelNonpaged', ctypes.c_size_t),
194                   ('PageSize', ctypes.c_size_t),
195                   ('HandleCount', ctypes.c_ulong),
196                   ('ProcessCount', ctypes.c_ulong),
197                   ('ThreadCount', ctypes.c_ulong)]
198
199       def __init__(self):
200         self.size = ctypes.sizeof(self)
201         super(PerformanceInfo, self).__init__()
202
203     performance_info = PerformanceInfo()
204     ctypes.windll.psapi.GetPerformanceInfo(
205         ctypes.byref(performance_info), performance_info.size)
206     return performance_info