| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2015 The WebRTC Project Authors. All rights reserved. | 2 * Copyright 2015 The WebRTC Project Authors. All rights reserved. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
| 5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
| 6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
| 7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
| 8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
| 9 */ | 9 */ |
| 10 | 10 |
| 11 package org.appspot.apprtc; | 11 package org.appspot.apprtc; |
| 12 | 12 |
| 13 import android.content.Context; | 13 import android.content.Context; |
| 14 import android.content.Intent; | 14 import android.content.Intent; |
| 15 import android.content.IntentFilter; | 15 import android.content.IntentFilter; |
| 16 import android.os.BatteryManager; | 16 import android.os.BatteryManager; |
| 17 import android.os.Environment; | |
| 18 import android.os.SystemClock; | 17 import android.os.SystemClock; |
| 19 import android.util.Log; | 18 import android.util.Log; |
| 20 | 19 |
| 21 import java.io.BufferedReader; | 20 import java.io.BufferedReader; |
| 22 import java.io.File; | |
| 23 import java.io.FileNotFoundException; | 21 import java.io.FileNotFoundException; |
| 24 import java.io.FileOutputStream; | |
| 25 import java.io.FileReader; | 22 import java.io.FileReader; |
| 26 import java.io.IOException; | 23 import java.io.IOException; |
| 27 import java.text.SimpleDateFormat; | 24 import java.util.Arrays; |
| 28 import java.util.Calendar; | |
| 29 import java.util.Date; | |
| 30 import java.util.Scanner; | 25 import java.util.Scanner; |
| 31 | 26 |
| 32 import org.appspot.apprtc.util.LooperExecutor; | 27 import org.appspot.apprtc.util.LooperExecutor; |
| 33 | 28 |
| 34 /** | 29 /** |
| 35 * Simple CPU monitor. The caller creates a CpuMonitor object which can then | 30 * Simple CPU monitor. The caller creates a CpuMonitor object which can then |
| 36 * be used via sampleCpuUtilization() to collect the percentual use of the | 31 * be used via sampleCpuUtilization() to collect the percentual use of the |
| 37 * cumulative CPU capacity for all CPUs running at their nominal frequency. 3 | 32 * cumulative CPU capacity for all CPUs running at their nominal frequency. 3 |
| 38 * values are generated: (1) getCpuCurrent() returns the use since the last | 33 * values are generated: (1) getCpuCurrent() returns the use since the last |
| 39 * sampleCpuUtilization(), (2) getCpuAvg3() returns the use since 3 prior | 34 * sampleCpuUtilization(), (2) getCpuAvg3() returns the use since 3 prior |
| (...skipping 28 matching lines...) Expand all Loading... |
| 68 * | 63 * |
| 69 * <p>Known problems: | 64 * <p>Known problems: |
| 70 * 1. Nexus 7 devices running Kitkat have a kernel which often output an | 65 * 1. Nexus 7 devices running Kitkat have a kernel which often output an |
| 71 * incorrect 'idle' field in /proc/stat. The value is close to twice the | 66 * incorrect 'idle' field in /proc/stat. The value is close to twice the |
| 72 * correct value, and then returns to back to correct reading. Both when | 67 * correct value, and then returns to back to correct reading. Both when |
| 73 * jumping up and back down we might create faulty CPU load readings. | 68 * jumping up and back down we might create faulty CPU load readings. |
| 74 */ | 69 */ |
| 75 | 70 |
| 76 class CpuMonitor { | 71 class CpuMonitor { |
| 77 private static final String TAG = "CpuMonitor"; | 72 private static final String TAG = "CpuMonitor"; |
| 78 private static final String DUMP_FILE = "cpu_log.txt"; | 73 private static final int MOVING_AVERAGE_SAMPLES = 10; |
| 79 private static final int CPU_STAT_SAMPLE_PERIOD = 2000; | 74 |
| 80 private static final int CPU_STAT_LOG_PERIOD = 6000; | 75 private static final int CPU_STAT_SAMPLE_PERIOD_MS = 1000; |
| 76 private static final int CPU_STAT_LOG_PERIOD_MS = 5000; |
| 81 | 77 |
| 82 private final Context appContext; | 78 private final Context appContext; |
| 79 // User CPU usage at current frequency. |
| 80 private final MovingAverage userCpuUsage; |
| 81 // System CPU usage at current frequency. |
| 82 private final MovingAverage systemCpuUsage; |
| 83 // Total CPU usage relative to maximum frequency. |
| 84 private final MovingAverage totalCpuUsage; |
| 85 // CPU frequency in percentage from maximum. |
| 86 private final MovingAverage frequencyScale; |
| 87 |
| 83 private LooperExecutor executor; | 88 private LooperExecutor executor; |
| 84 private long lastStatLogTimeMs; | 89 private long lastStatLogTimeMs; |
| 85 private int iterations; | |
| 86 private double currentUserCpuUsage; | |
| 87 private double currentSystemCpuUsage; | |
| 88 private double currentTotalCpuUsage; | |
| 89 private double currentFrequencyScale = -1; | |
| 90 private double sumUserCpuUsage; | |
| 91 private double sumSystemCpuUsage; | |
| 92 private double sumFrequencyScale; | |
| 93 private double sumTotalCpuUsage; | |
| 94 private long[] cpuFreqMax; | 90 private long[] cpuFreqMax; |
| 95 private int cpusPresent; | 91 private int cpusPresent; |
| 96 private int actualCpusPresent; | 92 private int actualCpusPresent; |
| 97 private boolean initialized = false; | 93 private boolean initialized; |
| 94 private boolean cpuOveruse; |
| 98 private String[] maxPath; | 95 private String[] maxPath; |
| 99 private String[] curPath; | 96 private String[] curPath; |
| 100 private double[] curFreqScales; | 97 private double[] curFreqScales; |
| 101 private ProcStat lastProcStat; | 98 private ProcStat lastProcStat; |
| 102 | 99 |
| 103 private static boolean dumpEnabled = false; | 100 private static class ProcStat { |
| 104 private static FileOutputStream fileWriter; | |
| 105 | |
| 106 private class ProcStat { | |
| 107 final long userTime; | 101 final long userTime; |
| 108 final long systemTime; | 102 final long systemTime; |
| 109 final long idleTime; | 103 final long idleTime; |
| 110 | 104 |
| 111 ProcStat(long userTime, long systemTime, long idleTime) { | 105 ProcStat(long userTime, long systemTime, long idleTime) { |
| 112 this.userTime = userTime; | 106 this.userTime = userTime; |
| 113 this.systemTime = systemTime; | 107 this.systemTime = systemTime; |
| 114 this.idleTime = idleTime; | 108 this.idleTime = idleTime; |
| 115 } | 109 } |
| 116 } | 110 } |
| 117 | 111 |
| 112 private static class MovingAverage { |
| 113 private final int size; |
| 114 private double sum; |
| 115 private double currentValue; |
| 116 private double circBuffer[]; |
| 117 private int circBufferIndex; |
| 118 |
| 119 public MovingAverage(int size) { |
| 120 if (size <= 0) { |
| 121 throw new AssertionError("Size value in MovingAverage ctor should be pos
itive."); |
| 122 } |
| 123 this.size = size; |
| 124 circBuffer = new double[size]; |
| 125 } |
| 126 |
| 127 public void reset() { |
| 128 Arrays.fill(circBuffer, 0); |
| 129 circBufferIndex = 0; |
| 130 sum = 0; |
| 131 currentValue = 0; |
| 132 } |
| 133 |
| 134 public void addValue(double value) { |
| 135 sum -= circBuffer[circBufferIndex]; |
| 136 circBuffer[circBufferIndex++] = value; |
| 137 currentValue = value; |
| 138 sum += value; |
| 139 if (circBufferIndex >= size) { |
| 140 circBufferIndex = 0; |
| 141 } |
| 142 } |
| 143 |
| 144 public double getCurrent() { |
| 145 return currentValue; |
| 146 } |
| 147 |
| 148 public double getAverage() { |
| 149 return sum / (double) size; |
| 150 } |
| 151 } |
| 152 |
| 118 public CpuMonitor(Context context) { | 153 public CpuMonitor(Context context) { |
| 119 Log.d(TAG, "CpuMonitor ctor."); | 154 Log.d(TAG, "CpuMonitor ctor."); |
| 120 appContext = context.getApplicationContext(); | 155 appContext = context.getApplicationContext(); |
| 121 lastStatLogTimeMs = 0; | 156 userCpuUsage = new MovingAverage(MOVING_AVERAGE_SAMPLES); |
| 157 systemCpuUsage = new MovingAverage(MOVING_AVERAGE_SAMPLES); |
| 158 totalCpuUsage = new MovingAverage(MOVING_AVERAGE_SAMPLES); |
| 159 frequencyScale = new MovingAverage(MOVING_AVERAGE_SAMPLES); |
| 160 lastStatLogTimeMs = SystemClock.elapsedRealtime(); |
| 122 | 161 |
| 123 executor = new LooperExecutor(); | 162 executor = new LooperExecutor(); |
| 124 executor.requestStart(); | 163 executor.requestStart(); |
| 125 scheduleCpuUtilizationTask(); | 164 scheduleCpuUtilizationTask(); |
| 126 } | 165 } |
| 127 | 166 |
| 128 public void release() { | 167 public void release() { |
| 129 if (executor != null) { | 168 if (executor != null) { |
| 130 Log.d(TAG, "release"); | 169 Log.d(TAG, "release"); |
| 131 executor.cancelScheduledTasks(); | 170 executor.cancelScheduledTasks(); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 142 } | 181 } |
| 143 | 182 |
| 144 public void resume() { | 183 public void resume() { |
| 145 if (executor != null) { | 184 if (executor != null) { |
| 146 Log.d(TAG, "resume"); | 185 Log.d(TAG, "resume"); |
| 147 resetStat(); | 186 resetStat(); |
| 148 scheduleCpuUtilizationTask(); | 187 scheduleCpuUtilizationTask(); |
| 149 } | 188 } |
| 150 } | 189 } |
| 151 | 190 |
| 191 public synchronized void reset() { |
| 192 if (executor != null) { |
| 193 Log.d(TAG, "reset"); |
| 194 resetStat(); |
| 195 cpuOveruse = false; |
| 196 } |
| 197 } |
| 198 |
| 152 public synchronized int getCpuUsageCurrent() { | 199 public synchronized int getCpuUsageCurrent() { |
| 153 return doubleToPercent(currentTotalCpuUsage); | 200 return doubleToPercent(userCpuUsage.getCurrent() + systemCpuUsage.getCurrent
()); |
| 154 } | 201 } |
| 155 | 202 |
| 156 public synchronized int getCpuUsageAverage() { | 203 public synchronized int getCpuUsageAverage() { |
| 157 return sumDoubleToPercent(sumTotalCpuUsage, iterations); | 204 return doubleToPercent(userCpuUsage.getAverage() + systemCpuUsage.getAverage
()); |
| 158 } | 205 } |
| 159 | 206 |
| 160 public synchronized int getCpuFrequencyScaleCurrent() { | 207 public synchronized int getFrequencyScaleAverage() { |
| 161 return doubleToPercent(currentFrequencyScale); | 208 return doubleToPercent(frequencyScale.getAverage()); |
| 162 } | 209 } |
| 163 | 210 |
| 164 private void scheduleCpuUtilizationTask() { | 211 private void scheduleCpuUtilizationTask() { |
| 165 executor.scheduleAtFixedRate(new Runnable() { | 212 executor.scheduleAtFixedRate(new Runnable() { |
| 166 @Override | 213 @Override |
| 167 public void run() { | 214 public void run() { |
| 168 logCpuUtilization(); | 215 cpuUtilizationTask(); |
| 169 } | 216 } |
| 170 }, CPU_STAT_SAMPLE_PERIOD); | 217 }, CPU_STAT_SAMPLE_PERIOD_MS); |
| 171 } | 218 } |
| 172 | 219 |
| 173 private void checkDump(String statString) { | 220 private void cpuUtilizationTask() { |
| 174 if (!dumpEnabled) { | 221 boolean cpuMonitorAvailable = sampleCpuUtilization(); |
| 175 return; | 222 if (cpuMonitorAvailable |
| 176 } | 223 && SystemClock.elapsedRealtime() - lastStatLogTimeMs >= CPU_STAT_LOG_PER
IOD_MS) { |
| 177 if (fileWriter == null) { | 224 lastStatLogTimeMs = SystemClock.elapsedRealtime(); |
| 178 Log.d(TAG, "Start log dump"); | 225 String statString = getStatString(); |
| 179 String fileName = Environment.getExternalStorageDirectory().getAbsolutePat
h() | 226 Log.d(TAG, statString); |
| 180 + File.separator + DUMP_FILE; | |
| 181 try { | |
| 182 fileWriter = new FileOutputStream(fileName, false /* append */); | |
| 183 } catch (FileNotFoundException e) { | |
| 184 Log.e(TAG, "Can not open file.", e); | |
| 185 dumpEnabled = false; | |
| 186 return; | |
| 187 } | |
| 188 } | |
| 189 | |
| 190 Date date = Calendar.getInstance().getTime(); | |
| 191 SimpleDateFormat df = new SimpleDateFormat("MM-dd HH:mm:ss.SSS"); | |
| 192 String msg = df.format(date) + " " + TAG + ":" + statString + "\n"; | |
| 193 try { | |
| 194 fileWriter.write(msg.getBytes()); | |
| 195 } catch (IOException e) { | |
| 196 Log.e(TAG, "Can not write to file.", e); | |
| 197 dumpEnabled = false; | |
| 198 } | 227 } |
| 199 } | 228 } |
| 200 | 229 |
| 201 private void logCpuUtilization() { | |
| 202 boolean logStatistics = false; | |
| 203 if (SystemClock.elapsedRealtime() - lastStatLogTimeMs >= CPU_STAT_LOG_PERIOD
) { | |
| 204 lastStatLogTimeMs = SystemClock.elapsedRealtime(); | |
| 205 logStatistics = true; | |
| 206 } | |
| 207 boolean cpuMonitorAvailable = sampleCpuUtilization(); | |
| 208 if (logStatistics && cpuMonitorAvailable) { | |
| 209 String statString = getStatString(); | |
| 210 checkDump(statString); | |
| 211 Log.d(TAG, statString); | |
| 212 resetStat(); | |
| 213 } | |
| 214 } | |
| 215 | |
| 216 private void init() { | 230 private void init() { |
| 217 try { | 231 try { |
| 218 FileReader fin = new FileReader("/sys/devices/system/cpu/present"); | 232 FileReader fin = new FileReader("/sys/devices/system/cpu/present"); |
| 219 try { | 233 try { |
| 220 BufferedReader reader = new BufferedReader(fin); | 234 BufferedReader reader = new BufferedReader(fin); |
| 221 Scanner scanner = new Scanner(reader).useDelimiter("[-\n]"); | 235 Scanner scanner = new Scanner(reader).useDelimiter("[-\n]"); |
| 222 scanner.nextInt(); // Skip leading number 0. | 236 scanner.nextInt(); // Skip leading number 0. |
| 223 cpusPresent = 1 + scanner.nextInt(); | 237 cpusPresent = 1 + scanner.nextInt(); |
| 224 scanner.close(); | 238 scanner.close(); |
| 225 } catch (Exception e) { | 239 } catch (Exception e) { |
| (...skipping 18 matching lines...) Expand all Loading... |
| 244 curPath[i] = "/sys/devices/system/cpu/cpu" + i + "/cpufreq/scaling_cur_fre
q"; | 258 curPath[i] = "/sys/devices/system/cpu/cpu" + i + "/cpufreq/scaling_cur_fre
q"; |
| 245 } | 259 } |
| 246 | 260 |
| 247 lastProcStat = new ProcStat(0, 0, 0); | 261 lastProcStat = new ProcStat(0, 0, 0); |
| 248 resetStat(); | 262 resetStat(); |
| 249 | 263 |
| 250 initialized = true; | 264 initialized = true; |
| 251 } | 265 } |
| 252 | 266 |
| 253 private synchronized void resetStat() { | 267 private synchronized void resetStat() { |
| 254 sumUserCpuUsage = 0; | 268 userCpuUsage.reset(); |
| 255 sumSystemCpuUsage = 0; | 269 systemCpuUsage.reset(); |
| 256 sumFrequencyScale = 0; | 270 totalCpuUsage.reset(); |
| 257 sumTotalCpuUsage = 0; | 271 frequencyScale.reset(); |
| 258 iterations = 0; | 272 lastStatLogTimeMs = SystemClock.elapsedRealtime(); |
| 259 } | 273 } |
| 260 | 274 |
| 261 private int getBatteryLevel() { | 275 private int getBatteryLevel() { |
| 262 // Use sticky broadcast with null receiver to read battery level once only. | 276 // Use sticky broadcast with null receiver to read battery level once only. |
| 263 Intent intent = appContext.registerReceiver( | 277 Intent intent = appContext.registerReceiver( |
| 264 null /* receiver */, new IntentFilter(Intent.ACTION_BATTERY_CHANGED)); | 278 null /* receiver */, new IntentFilter(Intent.ACTION_BATTERY_CHANGED)); |
| 265 | 279 |
| 266 int batteryLevel = 0; | 280 int batteryLevel = 0; |
| 267 int batteryScale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, 100); | 281 int batteryScale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, 100); |
| 268 if (batteryScale > 0) { | 282 if (batteryScale > 0) { |
| (...skipping 29 matching lines...) Expand all Loading... |
| 298 * For each CPU, attempt to first read its max frequency, then its | 312 * For each CPU, attempt to first read its max frequency, then its |
| 299 * current frequency. Once as the max frequency for a CPU is found, | 313 * current frequency. Once as the max frequency for a CPU is found, |
| 300 * save it in cpuFreqMax[]. | 314 * save it in cpuFreqMax[]. |
| 301 */ | 315 */ |
| 302 | 316 |
| 303 curFreqScales[i] = 0; | 317 curFreqScales[i] = 0; |
| 304 if (cpuFreqMax[i] == 0) { | 318 if (cpuFreqMax[i] == 0) { |
| 305 // We have never found this CPU's max frequency. Attempt to read it. | 319 // We have never found this CPU's max frequency. Attempt to read it. |
| 306 long cpufreqMax = readFreqFromFile(maxPath[i]); | 320 long cpufreqMax = readFreqFromFile(maxPath[i]); |
| 307 if (cpufreqMax > 0) { | 321 if (cpufreqMax > 0) { |
| 322 Log.d(TAG, "Core " + i + ". Max frequency: " + cpufreqMax); |
| 308 lastSeenMaxFreq = cpufreqMax; | 323 lastSeenMaxFreq = cpufreqMax; |
| 309 cpuFreqMax[i] = cpufreqMax; | 324 cpuFreqMax[i] = cpufreqMax; |
| 310 maxPath[i] = null; // Kill path to free its memory. | 325 maxPath[i] = null; // Kill path to free its memory. |
| 311 } | 326 } |
| 312 } else { | 327 } else { |
| 313 lastSeenMaxFreq = cpuFreqMax[i]; // A valid, previously read value. | 328 lastSeenMaxFreq = cpuFreqMax[i]; // A valid, previously read value. |
| 314 } | 329 } |
| 315 | 330 |
| 316 long cpuFreqCur = readFreqFromFile(curPath[i]); | 331 long cpuFreqCur = readFreqFromFile(curPath[i]); |
| 317 if (cpuFreqCur == 0 && lastSeenMaxFreq == 0) { | 332 if (cpuFreqCur == 0 && lastSeenMaxFreq == 0) { |
| (...skipping 22 matching lines...) Expand all Loading... |
| 340 return false; | 355 return false; |
| 341 } | 356 } |
| 342 | 357 |
| 343 /* | 358 /* |
| 344 * Since the cycle counts are for the period between the last invocation | 359 * Since the cycle counts are for the period between the last invocation |
| 345 * and this present one, we average the percentual CPU frequencies between | 360 * and this present one, we average the percentual CPU frequencies between |
| 346 * now and the beginning of the measurement period. This is significantly | 361 * now and the beginning of the measurement period. This is significantly |
| 347 * incorrect only if the frequencies have peeked or dropped in between the | 362 * incorrect only if the frequencies have peeked or dropped in between the |
| 348 * invocations. | 363 * invocations. |
| 349 */ | 364 */ |
| 350 double newFrequencyScale = (double) cpuFreqCurSum / cpuFreqMaxSum; | 365 double currentFrequencyScale = cpuFreqCurSum / (double) cpuFreqMaxSum; |
| 351 double frequencyScale; | 366 if (frequencyScale.getCurrent() > 0) { |
| 352 if (currentFrequencyScale > 0) { | 367 currentFrequencyScale = (frequencyScale.getCurrent() + currentFrequencySca
le) * 0.5; |
| 353 frequencyScale = (currentFrequencyScale + newFrequencyScale) * 0.5; | |
| 354 } else { | |
| 355 frequencyScale = newFrequencyScale; | |
| 356 } | 368 } |
| 357 | 369 |
| 358 ProcStat procStat = readProcStat(); | 370 ProcStat procStat = readProcStat(); |
| 359 if (procStat == null) { | 371 if (procStat == null) { |
| 360 return false; | 372 return false; |
| 361 } | 373 } |
| 362 | 374 |
| 363 long diffUserTime = procStat.userTime - lastProcStat.userTime; | 375 long diffUserTime = procStat.userTime - lastProcStat.userTime; |
| 364 long diffSystemTime = procStat.systemTime - lastProcStat.systemTime; | 376 long diffSystemTime = procStat.systemTime - lastProcStat.systemTime; |
| 365 long diffIdleTime = procStat.idleTime - lastProcStat.idleTime; | 377 long diffIdleTime = procStat.idleTime - lastProcStat.idleTime; |
| 366 long allTime = diffUserTime + diffSystemTime + diffIdleTime; | 378 long allTime = diffUserTime + diffSystemTime + diffIdleTime; |
| 367 | 379 |
| 368 if (frequencyScale == 0 || allTime == 0) { | 380 if (currentFrequencyScale == 0 || allTime == 0) { |
| 369 return false; | 381 return false; |
| 370 } | 382 } |
| 371 | 383 |
| 372 // Update statistics. | 384 // Update statistics. |
| 373 currentFrequencyScale = frequencyScale; | 385 frequencyScale.addValue(currentFrequencyScale); |
| 374 sumFrequencyScale += frequencyScale; | |
| 375 | 386 |
| 376 currentUserCpuUsage = (double) diffUserTime / allTime; | 387 double currentUserCpuUsage = diffUserTime / (double) allTime; |
| 377 sumUserCpuUsage += currentUserCpuUsage; | 388 userCpuUsage.addValue(currentUserCpuUsage); |
| 378 | 389 |
| 379 currentSystemCpuUsage = (double) diffSystemTime / allTime; | 390 double currentSystemCpuUsage = diffSystemTime / (double) allTime; |
| 380 sumSystemCpuUsage += currentSystemCpuUsage; | 391 systemCpuUsage.addValue(currentSystemCpuUsage); |
| 381 | 392 |
| 382 currentTotalCpuUsage = (currentUserCpuUsage + currentSystemCpuUsage) * curre
ntFrequencyScale; | 393 double currentTotalCpuUsage = |
| 383 sumTotalCpuUsage += currentTotalCpuUsage; | 394 (currentUserCpuUsage + currentSystemCpuUsage) * currentFrequencyScale; |
| 395 totalCpuUsage.addValue(currentTotalCpuUsage); |
| 384 | 396 |
| 385 iterations++; | |
| 386 // Save new measurements for next round's deltas. | 397 // Save new measurements for next round's deltas. |
| 387 lastProcStat = procStat; | 398 lastProcStat = procStat; |
| 388 | 399 |
| 389 return true; | 400 return true; |
| 390 } | 401 } |
| 391 | 402 |
| 392 private int doubleToPercent(double d) { | 403 private int doubleToPercent(double d) { |
| 393 return (int) (d * 100 + 0.5); | 404 return (int) (d * 100 + 0.5); |
| 394 } | 405 } |
| 395 | 406 |
| 396 private int sumDoubleToPercent(double d, int iterations) { | 407 private synchronized String getStatString() { |
| 397 if (iterations > 0) { | |
| 398 return (int) (d * 100.0 / (double) iterations + 0.5); | |
| 399 } else { | |
| 400 return 0; | |
| 401 } | |
| 402 } | |
| 403 | |
| 404 private String getStatString() { | |
| 405 StringBuilder stat = new StringBuilder(); | 408 StringBuilder stat = new StringBuilder(); |
| 406 stat.append("CPU User: ") | 409 stat.append("CPU User: ") |
| 407 .append(doubleToPercent(currentUserCpuUsage)).append("/") | 410 .append(doubleToPercent(userCpuUsage.getCurrent())).append("/") |
| 408 .append(sumDoubleToPercent(sumUserCpuUsage, iterations)).append(" (") | 411 .append(doubleToPercent(userCpuUsage.getAverage())) |
| 409 .append(doubleToPercent(currentUserCpuUsage * currentFrequencyScale)).ap
pend(")") | |
| 410 .append(". System: ") | 412 .append(". System: ") |
| 411 .append(doubleToPercent(currentSystemCpuUsage)).append("/") | 413 .append(doubleToPercent(systemCpuUsage.getCurrent())).append("/") |
| 412 .append(sumDoubleToPercent(sumSystemCpuUsage, iterations)).append(" (") | 414 .append(doubleToPercent(systemCpuUsage.getAverage())) |
| 413 .append(doubleToPercent(currentSystemCpuUsage * currentFrequencyScale)).
append(")") | 415 .append(". Freq: ") |
| 414 .append(". CPU freq %: ") | 416 .append(doubleToPercent(frequencyScale.getCurrent())).append("/") |
| 415 .append(doubleToPercent(currentFrequencyScale)).append("/") | 417 .append(doubleToPercent(frequencyScale.getAverage())) |
| 416 .append(sumDoubleToPercent(sumFrequencyScale, iterations)) | 418 .append(". Total usage: ") |
| 417 .append(". Total CPU usage: ") | 419 .append(doubleToPercent(totalCpuUsage.getCurrent())).append("/") |
| 418 .append(doubleToPercent(currentTotalCpuUsage)).append("/") | 420 .append(doubleToPercent(totalCpuUsage.getAverage())) |
| 419 .append(sumDoubleToPercent(sumTotalCpuUsage, iterations)) | |
| 420 .append(". Cores: ") | 421 .append(". Cores: ") |
| 421 .append(actualCpusPresent); | 422 .append(actualCpusPresent); |
| 422 stat.append("( "); | 423 stat.append("( "); |
| 423 for (int i = 0; i < cpusPresent; i++) { | 424 for (int i = 0; i < cpusPresent; i++) { |
| 424 stat.append(doubleToPercent(curFreqScales[i])).append(" "); | 425 stat.append(doubleToPercent(curFreqScales[i])).append(" "); |
| 425 } | 426 } |
| 426 stat.append("). Battery %: ") | 427 stat.append("). Battery: ").append(getBatteryLevel()); |
| 427 .append(getBatteryLevel()); | 428 if (cpuOveruse) { |
| 429 stat.append(". Overuse."); |
| 430 } |
| 428 return stat.toString(); | 431 return stat.toString(); |
| 429 } | 432 } |
| 430 | 433 |
| 431 /** | 434 /** |
| 432 * Read a single integer value from the named file. Return the read value | 435 * Read a single integer value from the named file. Return the read value |
| 433 * or if an error occurs return 0. | 436 * or if an error occurs return 0. |
| 434 */ | 437 */ |
| 435 private long readFreqFromFile(String fileName) { | 438 private long readFreqFromFile(String fileName) { |
| 436 long number = 0; | 439 long number = 0; |
| 437 try { | 440 try { |
| (...skipping 23 matching lines...) Expand all Loading... |
| 461 private ProcStat readProcStat() { | 464 private ProcStat readProcStat() { |
| 462 long userTime = 0; | 465 long userTime = 0; |
| 463 long systemTime = 0; | 466 long systemTime = 0; |
| 464 long idleTime = 0; | 467 long idleTime = 0; |
| 465 try { | 468 try { |
| 466 FileReader fin = new FileReader("/proc/stat"); | 469 FileReader fin = new FileReader("/proc/stat"); |
| 467 try { | 470 try { |
| 468 BufferedReader rdr = new BufferedReader(fin); | 471 BufferedReader rdr = new BufferedReader(fin); |
| 469 Scanner scanner = new Scanner(rdr); | 472 Scanner scanner = new Scanner(rdr); |
| 470 scanner.next(); | 473 scanner.next(); |
| 471 userTime = scanner.nextLong(); | 474 userTime = scanner.nextLong(); // user |
| 472 long nice = scanner.nextLong(); | 475 long nice = scanner.nextLong(); // nice |
| 473 userTime += nice; | 476 userTime += nice; |
| 474 systemTime = scanner.nextLong(); | 477 systemTime = scanner.nextLong(); // system |
| 475 idleTime = scanner.nextLong(); | 478 idleTime = scanner.nextLong(); // idle |
| 476 long ioWaitTime = scanner.nextLong(); | 479 long ioWaitTime = scanner.nextLong(); // iowait |
| 477 userTime += ioWaitTime; | 480 userTime += ioWaitTime; |
| 481 long irqTime = scanner.nextLong() + scanner.nextLong(); // irq + softirq |
| 482 systemTime += irqTime; |
| 478 scanner.close(); | 483 scanner.close(); |
| 479 } catch (Exception e) { | 484 } catch (Exception e) { |
| 480 Log.e(TAG, "Problems parsing /proc/stat"); | 485 Log.e(TAG, "Problems parsing /proc/stat"); |
| 481 return null; | 486 return null; |
| 482 } finally { | 487 } finally { |
| 483 fin.close(); | 488 fin.close(); |
| 484 } | 489 } |
| 485 } catch (FileNotFoundException e) { | 490 } catch (FileNotFoundException e) { |
| 486 Log.e(TAG, "Cannot open /proc/stat for reading"); | 491 Log.e(TAG, "Cannot open /proc/stat for reading"); |
| 487 return null; | 492 return null; |
| 488 } catch (IOException e) { | 493 } catch (IOException e) { |
| 489 Log.e(TAG, "Problems reading /proc/stat"); | 494 Log.e(TAG, "Problems reading /proc/stat"); |
| 490 return null; | 495 return null; |
| 491 } | 496 } |
| 492 return new ProcStat(userTime, systemTime, idleTime); | 497 return new ProcStat(userTime, systemTime, idleTime); |
| 493 } | 498 } |
| 494 } | 499 } |
| OLD | NEW |