|
|
|
|
@ -10,15 +10,27 @@
|
|
|
|
|
|
|
|
|
|
package org.appspot.apprtc;
|
|
|
|
|
|
|
|
|
|
import android.content.Context;
|
|
|
|
|
import android.content.Intent;
|
|
|
|
|
import android.content.IntentFilter;
|
|
|
|
|
import android.os.BatteryManager;
|
|
|
|
|
import android.os.Environment;
|
|
|
|
|
import android.os.SystemClock;
|
|
|
|
|
import android.util.Log;
|
|
|
|
|
|
|
|
|
|
import java.io.BufferedReader;
|
|
|
|
|
import java.io.File;
|
|
|
|
|
import java.io.FileNotFoundException;
|
|
|
|
|
import java.io.FileOutputStream;
|
|
|
|
|
import java.io.FileReader;
|
|
|
|
|
import java.io.IOException;
|
|
|
|
|
import java.util.InputMismatchException;
|
|
|
|
|
import java.text.SimpleDateFormat;
|
|
|
|
|
import java.util.Calendar;
|
|
|
|
|
import java.util.Date;
|
|
|
|
|
import java.util.Scanner;
|
|
|
|
|
|
|
|
|
|
import org.appspot.apprtc.util.LooperExecutor;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Simple CPU monitor. The caller creates a CpuMonitor object which can then
|
|
|
|
|
* be used via sampleCpuUtilization() to collect the percentual use of the
|
|
|
|
|
@ -62,29 +74,142 @@ import java.util.Scanner;
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
class CpuMonitor {
|
|
|
|
|
private static final int SAMPLE_SAVE_NUMBER = 10; // Assumed to be >= 3.
|
|
|
|
|
private int[] percentVec = new int[SAMPLE_SAVE_NUMBER];
|
|
|
|
|
private int sum3 = 0;
|
|
|
|
|
private int sum10 = 0;
|
|
|
|
|
private static final String TAG = "CpuMonitor";
|
|
|
|
|
private long[] cpuFreq;
|
|
|
|
|
private static final String DUMP_FILE = "cpu_log.txt";
|
|
|
|
|
private static final int CPU_STAT_SAMPLE_PERIOD = 2000;
|
|
|
|
|
private static final int CPU_STAT_LOG_PERIOD = 6000;
|
|
|
|
|
|
|
|
|
|
private final Context appContext;
|
|
|
|
|
private LooperExecutor executor;
|
|
|
|
|
private long lastStatLogTimeMs;
|
|
|
|
|
private int iterations;
|
|
|
|
|
private double currentUserCpuUsage;
|
|
|
|
|
private double currentSystemCpuUsage;
|
|
|
|
|
private double currentTotalCpuUsage;
|
|
|
|
|
private double currentFrequencyScale = -1;
|
|
|
|
|
private double sumUserCpuUsage;
|
|
|
|
|
private double sumSystemCpuUsage;
|
|
|
|
|
private double sumFrequencyScale;
|
|
|
|
|
private double sumTotalCpuUsage;
|
|
|
|
|
private long[] cpuFreqMax;
|
|
|
|
|
private int cpusPresent;
|
|
|
|
|
private double lastPercentFreq = -1;
|
|
|
|
|
private int cpuCurrent;
|
|
|
|
|
private int cpuAvg3;
|
|
|
|
|
private int cpuAvgAll;
|
|
|
|
|
private int actualCpusPresent;
|
|
|
|
|
private boolean initialized = false;
|
|
|
|
|
private String[] maxPath;
|
|
|
|
|
private String[] curPath;
|
|
|
|
|
ProcStat lastProcStat;
|
|
|
|
|
private double[] curFreqScales;
|
|
|
|
|
private ProcStat lastProcStat;
|
|
|
|
|
|
|
|
|
|
private static boolean dumpEnabled = false;
|
|
|
|
|
private static FileOutputStream fileWriter;
|
|
|
|
|
|
|
|
|
|
private class ProcStat {
|
|
|
|
|
final long runTime;
|
|
|
|
|
final long userTime;
|
|
|
|
|
final long systemTime;
|
|
|
|
|
final long idleTime;
|
|
|
|
|
|
|
|
|
|
ProcStat(long aRunTime, long aIdleTime) {
|
|
|
|
|
runTime = aRunTime;
|
|
|
|
|
idleTime = aIdleTime;
|
|
|
|
|
ProcStat(long userTime, long systemTime, long idleTime) {
|
|
|
|
|
this.userTime = userTime;
|
|
|
|
|
this.systemTime = systemTime;
|
|
|
|
|
this.idleTime = idleTime;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public CpuMonitor(Context context) {
|
|
|
|
|
Log.d(TAG, "CpuMonitor ctor.");
|
|
|
|
|
appContext = context.getApplicationContext();
|
|
|
|
|
lastStatLogTimeMs = 0;
|
|
|
|
|
|
|
|
|
|
executor = new LooperExecutor();
|
|
|
|
|
executor.requestStart();
|
|
|
|
|
scheduleCpuUtilizationTask();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void release() {
|
|
|
|
|
if (executor != null) {
|
|
|
|
|
Log.d(TAG, "release");
|
|
|
|
|
executor.cancelScheduledTasks();
|
|
|
|
|
executor.requestStop();
|
|
|
|
|
executor = null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void pause() {
|
|
|
|
|
if (executor != null) {
|
|
|
|
|
Log.d(TAG, "pause");
|
|
|
|
|
executor.cancelScheduledTasks();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void resume() {
|
|
|
|
|
if (executor != null) {
|
|
|
|
|
Log.d(TAG, "resume");
|
|
|
|
|
resetStat();
|
|
|
|
|
scheduleCpuUtilizationTask();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public synchronized int getCpuUsageCurrent() {
|
|
|
|
|
return doubleToPercent(currentTotalCpuUsage);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public synchronized int getCpuUsageAverage() {
|
|
|
|
|
return sumDoubleToPercent(sumTotalCpuUsage, iterations);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public synchronized int getCpuFrequencyScaleCurrent() {
|
|
|
|
|
return doubleToPercent(currentFrequencyScale);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void scheduleCpuUtilizationTask() {
|
|
|
|
|
executor.scheduleAtFixedRate(new Runnable() {
|
|
|
|
|
@Override
|
|
|
|
|
public void run() {
|
|
|
|
|
logCpuUtilization();
|
|
|
|
|
}
|
|
|
|
|
}, CPU_STAT_SAMPLE_PERIOD);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void checkDump(String statString) {
|
|
|
|
|
if (!dumpEnabled) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (fileWriter == null) {
|
|
|
|
|
Log.d(TAG, "Start log dump");
|
|
|
|
|
String fileName = Environment.getExternalStorageDirectory().getAbsolutePath()
|
|
|
|
|
+ File.separator + DUMP_FILE;
|
|
|
|
|
try {
|
|
|
|
|
fileWriter = new FileOutputStream(fileName, false /* append */);
|
|
|
|
|
} catch (FileNotFoundException e) {
|
|
|
|
|
Log.e(TAG, "Can not open file.", e);
|
|
|
|
|
dumpEnabled = false;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Date date = Calendar.getInstance().getTime();
|
|
|
|
|
SimpleDateFormat df = new SimpleDateFormat("MM-dd HH:mm:ss.SSS");
|
|
|
|
|
String msg = df.format(date) + " " + TAG + ":" + statString + "\n";
|
|
|
|
|
try {
|
|
|
|
|
fileWriter.write(msg.getBytes());
|
|
|
|
|
} catch (IOException e) {
|
|
|
|
|
Log.e(TAG, "Can not write to file.", e);
|
|
|
|
|
dumpEnabled = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void logCpuUtilization() {
|
|
|
|
|
boolean logStatistics = false;
|
|
|
|
|
if (SystemClock.elapsedRealtime() - lastStatLogTimeMs >= CPU_STAT_LOG_PERIOD) {
|
|
|
|
|
lastStatLogTimeMs = SystemClock.elapsedRealtime();
|
|
|
|
|
logStatistics = true;
|
|
|
|
|
}
|
|
|
|
|
boolean cpuMonitorAvailable = sampleCpuUtilization();
|
|
|
|
|
if (logStatistics && cpuMonitorAvailable) {
|
|
|
|
|
String statString = getStatString();
|
|
|
|
|
checkDump(statString);
|
|
|
|
|
Log.d(TAG, statString);
|
|
|
|
|
resetStat();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -92,8 +217,8 @@ class CpuMonitor {
|
|
|
|
|
try {
|
|
|
|
|
FileReader fin = new FileReader("/sys/devices/system/cpu/present");
|
|
|
|
|
try {
|
|
|
|
|
BufferedReader rdr = new BufferedReader(fin);
|
|
|
|
|
Scanner scanner = new Scanner(rdr).useDelimiter("[-\n]");
|
|
|
|
|
BufferedReader reader = new BufferedReader(fin);
|
|
|
|
|
Scanner scanner = new Scanner(reader).useDelimiter("[-\n]");
|
|
|
|
|
scanner.nextInt(); // Skip leading number 0.
|
|
|
|
|
cpusPresent = 1 + scanner.nextInt();
|
|
|
|
|
scanner.close();
|
|
|
|
|
@ -108,20 +233,45 @@ class CpuMonitor {
|
|
|
|
|
Log.e(TAG, "Error closing file");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cpuFreq = new long [cpusPresent];
|
|
|
|
|
maxPath = new String [cpusPresent];
|
|
|
|
|
curPath = new String [cpusPresent];
|
|
|
|
|
cpuFreqMax = new long[cpusPresent];
|
|
|
|
|
maxPath = new String[cpusPresent];
|
|
|
|
|
curPath = new String[cpusPresent];
|
|
|
|
|
curFreqScales = new double[cpusPresent];
|
|
|
|
|
for (int i = 0; i < cpusPresent; i++) {
|
|
|
|
|
cpuFreq[i] = 0; // Frequency "not yet determined".
|
|
|
|
|
cpuFreqMax[i] = 0; // Frequency "not yet determined".
|
|
|
|
|
curFreqScales[i] = 0;
|
|
|
|
|
maxPath[i] = "/sys/devices/system/cpu/cpu" + i + "/cpufreq/cpuinfo_max_freq";
|
|
|
|
|
curPath[i] = "/sys/devices/system/cpu/cpu" + i + "/cpufreq/scaling_cur_freq";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
lastProcStat = new ProcStat(0, 0);
|
|
|
|
|
lastProcStat = new ProcStat(0, 0, 0);
|
|
|
|
|
resetStat();
|
|
|
|
|
|
|
|
|
|
initialized = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private synchronized void resetStat() {
|
|
|
|
|
sumUserCpuUsage = 0;
|
|
|
|
|
sumSystemCpuUsage = 0;
|
|
|
|
|
sumFrequencyScale = 0;
|
|
|
|
|
sumTotalCpuUsage = 0;
|
|
|
|
|
iterations = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private int getBatteryLevel() {
|
|
|
|
|
// Use sticky broadcast with null receiver to read battery level once only.
|
|
|
|
|
Intent intent = appContext.registerReceiver(
|
|
|
|
|
null /* receiver */, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
|
|
|
|
|
|
|
|
|
|
int batteryLevel = 0;
|
|
|
|
|
int batteryScale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, 100);
|
|
|
|
|
if (batteryScale > 0) {
|
|
|
|
|
batteryLevel = (int) (
|
|
|
|
|
100f * intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0) / batteryScale);
|
|
|
|
|
}
|
|
|
|
|
return batteryLevel;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Re-measure CPU use. Call this method at an interval of around 1/s.
|
|
|
|
|
* This method returns true on success. The fields
|
|
|
|
|
@ -130,36 +280,48 @@ class CpuMonitor {
|
|
|
|
|
* cpuAvg3: The average CPU over the last 3 calls.
|
|
|
|
|
* cpuAvgAll: The average CPU over the last SAMPLE_SAVE_NUMBER calls.
|
|
|
|
|
*/
|
|
|
|
|
public boolean sampleCpuUtilization() {
|
|
|
|
|
private synchronized boolean sampleCpuUtilization() {
|
|
|
|
|
long lastSeenMaxFreq = 0;
|
|
|
|
|
long cpufreqCurSum = 0;
|
|
|
|
|
long cpufreqMaxSum = 0;
|
|
|
|
|
long cpuFreqCurSum = 0;
|
|
|
|
|
long cpuFreqMaxSum = 0;
|
|
|
|
|
|
|
|
|
|
if (!initialized) {
|
|
|
|
|
init();
|
|
|
|
|
}
|
|
|
|
|
if (cpusPresent == 0) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
actualCpusPresent = 0;
|
|
|
|
|
for (int i = 0; i < cpusPresent; i++) {
|
|
|
|
|
/*
|
|
|
|
|
* For each CPU, attempt to first read its max frequency, then its
|
|
|
|
|
* current frequency. Once as the max frequency for a CPU is found,
|
|
|
|
|
* save it in cpuFreq[].
|
|
|
|
|
* save it in cpuFreqMax[].
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
if (cpuFreq[i] == 0) {
|
|
|
|
|
curFreqScales[i] = 0;
|
|
|
|
|
if (cpuFreqMax[i] == 0) {
|
|
|
|
|
// We have never found this CPU's max frequency. Attempt to read it.
|
|
|
|
|
long cpufreqMax = readFreqFromFile(maxPath[i]);
|
|
|
|
|
if (cpufreqMax > 0) {
|
|
|
|
|
lastSeenMaxFreq = cpufreqMax;
|
|
|
|
|
cpuFreq[i] = cpufreqMax;
|
|
|
|
|
cpuFreqMax[i] = cpufreqMax;
|
|
|
|
|
maxPath[i] = null; // Kill path to free its memory.
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
lastSeenMaxFreq = cpuFreq[i]; // A valid, previously read value.
|
|
|
|
|
lastSeenMaxFreq = cpuFreqMax[i]; // A valid, previously read value.
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
long cpufreqCur = readFreqFromFile(curPath[i]);
|
|
|
|
|
cpufreqCurSum += cpufreqCur;
|
|
|
|
|
long cpuFreqCur = readFreqFromFile(curPath[i]);
|
|
|
|
|
if (cpuFreqCur == 0 && lastSeenMaxFreq == 0) {
|
|
|
|
|
// No current frequency information for this CPU core - ignore it.
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if (cpuFreqCur > 0) {
|
|
|
|
|
actualCpusPresent++;
|
|
|
|
|
}
|
|
|
|
|
cpuFreqCurSum += cpuFreqCur;
|
|
|
|
|
|
|
|
|
|
/* Here, lastSeenMaxFreq might come from
|
|
|
|
|
* 1. cpuFreq[i], or
|
|
|
|
|
@ -167,11 +329,14 @@ class CpuMonitor {
|
|
|
|
|
* 3. a newly read value, or
|
|
|
|
|
* 4. hypothetically from the pre-loop dummy.
|
|
|
|
|
*/
|
|
|
|
|
cpufreqMaxSum += lastSeenMaxFreq;
|
|
|
|
|
cpuFreqMaxSum += lastSeenMaxFreq;
|
|
|
|
|
if (lastSeenMaxFreq > 0) {
|
|
|
|
|
curFreqScales[i] = (double) cpuFreqCur / lastSeenMaxFreq;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (cpufreqMaxSum == 0) {
|
|
|
|
|
Log.e(TAG, "Could not read max frequency for any CPU");
|
|
|
|
|
if (cpuFreqCurSum == 0 || cpuFreqMaxSum == 0) {
|
|
|
|
|
Log.e(TAG, "Could not read max or current frequency for any CPU");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -182,58 +347,85 @@ class CpuMonitor {
|
|
|
|
|
* incorrect only if the frequencies have peeked or dropped in between the
|
|
|
|
|
* invocations.
|
|
|
|
|
*/
|
|
|
|
|
double newPercentFreq = 100.0 * cpufreqCurSum / cpufreqMaxSum;
|
|
|
|
|
double percentFreq;
|
|
|
|
|
if (lastPercentFreq > 0) {
|
|
|
|
|
percentFreq = (lastPercentFreq + newPercentFreq) * 0.5;
|
|
|
|
|
double newFrequencyScale = (double) cpuFreqCurSum / cpuFreqMaxSum;
|
|
|
|
|
double frequencyScale;
|
|
|
|
|
if (currentFrequencyScale > 0) {
|
|
|
|
|
frequencyScale = (currentFrequencyScale + newFrequencyScale) * 0.5;
|
|
|
|
|
} else {
|
|
|
|
|
percentFreq = newPercentFreq;
|
|
|
|
|
frequencyScale = newFrequencyScale;
|
|
|
|
|
}
|
|
|
|
|
lastPercentFreq = newPercentFreq;
|
|
|
|
|
|
|
|
|
|
ProcStat procStat = readIdleAndRunTime();
|
|
|
|
|
ProcStat procStat = readProcStat();
|
|
|
|
|
if (procStat == null) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
long diffRunTime = procStat.runTime - lastProcStat.runTime;
|
|
|
|
|
long diffUserTime = procStat.userTime - lastProcStat.userTime;
|
|
|
|
|
long diffSystemTime = procStat.systemTime - lastProcStat.systemTime;
|
|
|
|
|
long diffIdleTime = procStat.idleTime - lastProcStat.idleTime;
|
|
|
|
|
long allTime = diffUserTime + diffSystemTime + diffIdleTime;
|
|
|
|
|
|
|
|
|
|
if (frequencyScale == 0 || allTime == 0) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Update statistics.
|
|
|
|
|
currentFrequencyScale = frequencyScale;
|
|
|
|
|
sumFrequencyScale += frequencyScale;
|
|
|
|
|
|
|
|
|
|
currentUserCpuUsage = (double) diffUserTime / allTime;
|
|
|
|
|
sumUserCpuUsage += currentUserCpuUsage;
|
|
|
|
|
|
|
|
|
|
currentSystemCpuUsage = (double) diffSystemTime / allTime;
|
|
|
|
|
sumSystemCpuUsage += currentSystemCpuUsage;
|
|
|
|
|
|
|
|
|
|
currentTotalCpuUsage = (currentUserCpuUsage + currentSystemCpuUsage) * currentFrequencyScale;
|
|
|
|
|
sumTotalCpuUsage += currentTotalCpuUsage;
|
|
|
|
|
|
|
|
|
|
iterations++;
|
|
|
|
|
// Save new measurements for next round's deltas.
|
|
|
|
|
lastProcStat = procStat;
|
|
|
|
|
|
|
|
|
|
long allTime = diffRunTime + diffIdleTime;
|
|
|
|
|
int percent = allTime == 0 ? 0 : (int) Math.round(percentFreq * diffRunTime / allTime);
|
|
|
|
|
percent = Math.max(0, Math.min(percent, 100));
|
|
|
|
|
|
|
|
|
|
// Subtract old relevant measurement, add newest.
|
|
|
|
|
sum3 += percent - percentVec[2];
|
|
|
|
|
// Subtract oldest measurement, add newest.
|
|
|
|
|
sum10 += percent - percentVec[SAMPLE_SAVE_NUMBER - 1];
|
|
|
|
|
|
|
|
|
|
// Rotate saved percent values, save new measurement in vacated spot.
|
|
|
|
|
for (int i = SAMPLE_SAVE_NUMBER - 1; i > 0; i--) {
|
|
|
|
|
percentVec[i] = percentVec[i - 1];
|
|
|
|
|
}
|
|
|
|
|
percentVec[0] = percent;
|
|
|
|
|
|
|
|
|
|
cpuCurrent = percent;
|
|
|
|
|
cpuAvg3 = sum3 / 3;
|
|
|
|
|
cpuAvgAll = sum10 / SAMPLE_SAVE_NUMBER;
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public int getCpuCurrent() {
|
|
|
|
|
return cpuCurrent;
|
|
|
|
|
private int doubleToPercent(double d) {
|
|
|
|
|
return (int) (d * 100 + 0.5);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public int getCpuAvg3() {
|
|
|
|
|
return cpuAvg3;
|
|
|
|
|
private int sumDoubleToPercent(double d, int iterations) {
|
|
|
|
|
if (iterations > 0) {
|
|
|
|
|
return (int) (d * 100.0 / (double) iterations + 0.5);
|
|
|
|
|
} else {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public int getCpuAvgAll() {
|
|
|
|
|
return cpuAvgAll;
|
|
|
|
|
private String getStatString() {
|
|
|
|
|
StringBuilder stat = new StringBuilder();
|
|
|
|
|
stat.append("CPU User: ")
|
|
|
|
|
.append(doubleToPercent(currentUserCpuUsage)).append("/")
|
|
|
|
|
.append(sumDoubleToPercent(sumUserCpuUsage, iterations)).append(" (")
|
|
|
|
|
.append(doubleToPercent(currentUserCpuUsage * currentFrequencyScale)).append(")")
|
|
|
|
|
.append(". System: ")
|
|
|
|
|
.append(doubleToPercent(currentSystemCpuUsage)).append("/")
|
|
|
|
|
.append(sumDoubleToPercent(sumSystemCpuUsage, iterations)).append(" (")
|
|
|
|
|
.append(doubleToPercent(currentSystemCpuUsage * currentFrequencyScale)).append(")")
|
|
|
|
|
.append(". CPU freq %: ")
|
|
|
|
|
.append(doubleToPercent(currentFrequencyScale)).append("/")
|
|
|
|
|
.append(sumDoubleToPercent(sumFrequencyScale, iterations))
|
|
|
|
|
.append(". Total CPU usage: ")
|
|
|
|
|
.append(doubleToPercent(currentTotalCpuUsage)).append("/")
|
|
|
|
|
.append(sumDoubleToPercent(sumTotalCpuUsage, iterations))
|
|
|
|
|
.append(". Cores: ")
|
|
|
|
|
.append(actualCpusPresent);
|
|
|
|
|
stat.append("( ");
|
|
|
|
|
for (int i = 0; i < cpusPresent; i++) {
|
|
|
|
|
stat.append(doubleToPercent(curFreqScales[i])).append(" ");
|
|
|
|
|
}
|
|
|
|
|
stat.append("). Battery %: ")
|
|
|
|
|
.append(getBatteryLevel());
|
|
|
|
|
return stat.toString();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@ -266,8 +458,9 @@ class CpuMonitor {
|
|
|
|
|
* Read the current utilization of all CPUs using the cumulative first line
|
|
|
|
|
* of /proc/stat.
|
|
|
|
|
*/
|
|
|
|
|
private ProcStat readIdleAndRunTime() {
|
|
|
|
|
long runTime = 0;
|
|
|
|
|
private ProcStat readProcStat() {
|
|
|
|
|
long userTime = 0;
|
|
|
|
|
long systemTime = 0;
|
|
|
|
|
long idleTime = 0;
|
|
|
|
|
try {
|
|
|
|
|
FileReader fin = new FileReader("/proc/stat");
|
|
|
|
|
@ -275,11 +468,13 @@ class CpuMonitor {
|
|
|
|
|
BufferedReader rdr = new BufferedReader(fin);
|
|
|
|
|
Scanner scanner = new Scanner(rdr);
|
|
|
|
|
scanner.next();
|
|
|
|
|
long user = scanner.nextLong();
|
|
|
|
|
userTime = scanner.nextLong();
|
|
|
|
|
long nice = scanner.nextLong();
|
|
|
|
|
long sys = scanner.nextLong();
|
|
|
|
|
runTime = user + nice + sys;
|
|
|
|
|
userTime += nice;
|
|
|
|
|
systemTime = scanner.nextLong();
|
|
|
|
|
idleTime = scanner.nextLong();
|
|
|
|
|
long ioWaitTime = scanner.nextLong();
|
|
|
|
|
userTime += ioWaitTime;
|
|
|
|
|
scanner.close();
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
Log.e(TAG, "Problems parsing /proc/stat");
|
|
|
|
|
@ -294,6 +489,6 @@ class CpuMonitor {
|
|
|
|
|
Log.e(TAG, "Problems reading /proc/stat");
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
return new ProcStat(runTime, idleTime);
|
|
|
|
|
return new ProcStat(userTime, systemTime, idleTime);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|