Merge "Read current CPU frequencies and populate CpuInfo."
This commit is contained in:
committed by
Android (Google) Code Review
commit
f92396c580
@@ -20,6 +20,7 @@ import android.annotation.IntDef;
|
||||
import android.annotation.Nullable;
|
||||
import android.system.Os;
|
||||
import android.system.OsConstants;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.SparseArray;
|
||||
import android.util.SparseIntArray;
|
||||
|
||||
@@ -46,8 +47,12 @@ public final class CpuInfoReader {
|
||||
private static final String CPUFREQ_DIR_PATH = "/sys/devices/system/cpu/cpufreq";
|
||||
private static final String POLICY_DIR_PREFIX = "policy";
|
||||
private static final String RELATED_CPUS_FILE = "related_cpus";
|
||||
private static final String AFFECTED_CPUS_FILE = "affected_cpus";
|
||||
private static final String CUR_CPUFREQ_FILE = "cpuinfo_cur_freq";
|
||||
private static final String MAX_CPUFREQ_FILE = "cpuinfo_max_freq";
|
||||
private static final String CUR_SCALING_FREQ_FILE = "scaling_cur_freq";
|
||||
private static final String MAX_SCALING_FREQ_FILE = "scaling_max_freq";
|
||||
private static final String TIME_IN_STATE_FILE = "stats/time_in_state";
|
||||
private static final String CPUSET_DIR_PATH = "/dev/cpuset";
|
||||
private static final String CPUSET_TOP_APP_DIR = "top-app";
|
||||
private static final String CPUSET_BACKGROUND_DIR = "background";
|
||||
@@ -60,6 +65,8 @@ public final class CpuInfoReader {
|
||||
+ "(?<irqClockTicks>[0-9]+)\\s(?<softirqClockTicks>[0-9]+)\\s"
|
||||
+ "(?<stealClockTicks>[0-9]+)\\s(?<guestClockTicks>[0-9]+)\\s"
|
||||
+ "(?<guestNiceClockTicks>[0-9]+)");
|
||||
private static final Pattern TIME_IN_STATE_PATTERN =
|
||||
Pattern.compile("(?<freqKHz>[0-9]+)\\s(?<time>[0-9]+)");
|
||||
private static final long MILLIS_PER_JIFFY = 1000L / Os.sysconf(OsConstants._SC_CLK_TCK);
|
||||
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@@ -70,14 +77,16 @@ public final class CpuInfoReader {
|
||||
private @interface CpusetCategory{}
|
||||
|
||||
private final File mCpusetDir;
|
||||
private final File mCpuFreqDir;
|
||||
private final File mProcStatFile;
|
||||
private final SparseIntArray mCpusetCategoriesByCpus = new SparseIntArray();
|
||||
private final SparseArray<Long> mMaxCpuFrequenciesByCpus = new SparseArray<>();
|
||||
private final ArrayMap<String, ArrayMap<Long, Long>> mTimeInStateByPolicy = new ArrayMap<>();
|
||||
|
||||
private File mCpuFreqDir;
|
||||
private File mProcStatFile;
|
||||
private File[] mCpuFreqPolicyDirs;
|
||||
private SparseArray<CpuUsageStats> mCumulativeCpuUsageStats = new SparseArray<>();
|
||||
private boolean mIsEnabled;
|
||||
private boolean mHasTimeInStateFile;
|
||||
|
||||
public CpuInfoReader() {
|
||||
this(new File(CPUSET_DIR_PATH), new File(CPUFREQ_DIR_PATH), new File(PROC_STAT_FILE_PATH));
|
||||
@@ -115,6 +124,11 @@ public final class CpuInfoReader {
|
||||
mCpuFreqDir.getAbsolutePath());
|
||||
return false;
|
||||
}
|
||||
|
||||
// The Kernel must be configured to generate the `time_in_state` file. If the Kernel is not
|
||||
// configured to generate this file, this file won't be available for the entire system
|
||||
// uptime. Thus, check for the presence of this file only during init.
|
||||
mHasTimeInStateFile = new File(mCpuFreqPolicyDirs[0], TIME_IN_STATE_FILE).exists();
|
||||
mIsEnabled = true;
|
||||
return true;
|
||||
}
|
||||
@@ -129,8 +143,44 @@ public final class CpuInfoReader {
|
||||
Slogf.e(TAG, "Failed to read latest CPU usage stats");
|
||||
return Collections.emptyList();
|
||||
}
|
||||
// TODO(b/217422127): Read current CPU frequencies and populate the CpuInfo.
|
||||
return Collections.emptyList();
|
||||
SparseArray<Long> cpuFrequenciesByCpus = readCurrentCpuFrequencies();
|
||||
List<CpuInfo> cpuInfos = new ArrayList<>();
|
||||
for (int i = 0; i < cpuFrequenciesByCpus.size(); i++) {
|
||||
int cpu = cpuFrequenciesByCpus.keyAt(i);
|
||||
long curFrequency = cpuFrequenciesByCpus.valueAt(i);
|
||||
if (!mMaxCpuFrequenciesByCpus.contains(cpu) || !latestCpuUsageStats.contains(cpu)) {
|
||||
Slogf.w(TAG, "Missing max CPU frequency or CPU usage stats for CPU core %d", cpu);
|
||||
continue;
|
||||
}
|
||||
int cpuCategories = mCpusetCategoriesByCpus.get(cpu, -1);
|
||||
if (cpuCategories < 0) {
|
||||
Slogf.w(TAG, "Missing cpuset information for CPU core %d", cpu);
|
||||
continue;
|
||||
}
|
||||
cpuInfos.add(new CpuInfo(cpu, cpuCategories, curFrequency,
|
||||
mMaxCpuFrequenciesByCpus.get(cpu), latestCpuUsageStats.get(cpu)));
|
||||
}
|
||||
return cpuInfos;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void setCpuFreqDir(File cpuFreqDir) {
|
||||
File[] cpuFreqPolicyDirs = cpuFreqDir.listFiles(
|
||||
file -> file.isDirectory() && file.getName().startsWith(POLICY_DIR_PREFIX));
|
||||
if (mCpuFreqPolicyDirs == null || mCpuFreqPolicyDirs.length == 0) {
|
||||
Slogf.w(TAG, "Failed to set CPU frequency directory. Missing policy directories at %s",
|
||||
mCpuFreqDir.getAbsolutePath());
|
||||
return;
|
||||
}
|
||||
mCpuFreqDir = cpuFreqDir;
|
||||
mCpuFreqPolicyDirs = cpuFreqPolicyDirs;
|
||||
Slogf.i(TAG, "Set CPU frequency directory to %s", cpuFreqDir.getAbsolutePath());
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void setProcStatFile(File procStatFile) {
|
||||
mProcStatFile = procStatFile;
|
||||
Slogf.i(TAG, "Set proc stat file to %s", procStatFile.getAbsolutePath());
|
||||
}
|
||||
|
||||
private void readCpusetCategories() {
|
||||
@@ -192,6 +242,77 @@ public final class CpuInfoReader {
|
||||
: readCpuFreqKHz(new File(policyDir, MAX_SCALING_FREQ_FILE));
|
||||
}
|
||||
|
||||
private SparseArray<Long> readCurrentCpuFrequencies() {
|
||||
SparseArray<Long> curCpuFrequenciesByCpus = new SparseArray<>();
|
||||
for (int i = 0; i < mCpuFreqPolicyDirs.length; i++) {
|
||||
File policyDir = mCpuFreqPolicyDirs[i];
|
||||
long curCpuFreqKHz = readCurrentCpuFrequency(policyDir);
|
||||
if (curCpuFreqKHz == 0) {
|
||||
Slogf.w(TAG, "Missing current frequency information at %s",
|
||||
policyDir.getAbsolutePath());
|
||||
continue;
|
||||
}
|
||||
File cpuCoresFile = new File(policyDir, AFFECTED_CPUS_FILE);
|
||||
List<Integer> cpuCores = readCpuCores(cpuCoresFile);
|
||||
if (cpuCores.isEmpty()) {
|
||||
Slogf.e(TAG, "Failed to read CPU cores from %s", cpuCoresFile.getAbsolutePath());
|
||||
continue;
|
||||
}
|
||||
for (int j = 0; j < cpuCores.size(); j++) {
|
||||
curCpuFrequenciesByCpus.append(cpuCores.get(j), curCpuFreqKHz);
|
||||
}
|
||||
}
|
||||
return curCpuFrequenciesByCpus;
|
||||
}
|
||||
|
||||
private long readCurrentCpuFrequency(File policyDir) {
|
||||
ArrayMap<Long, Long> latestTimeInState = readTimeInState(policyDir);
|
||||
if (latestTimeInState == null) {
|
||||
long curCpuFreqKHz = readCpuFreqKHz(new File(policyDir, CUR_CPUFREQ_FILE));
|
||||
return curCpuFreqKHz > 0 ? curCpuFreqKHz :
|
||||
readCpuFreqKHz(new File(policyDir, CUR_SCALING_FREQ_FILE));
|
||||
}
|
||||
String policyDirName = policyDir.getName();
|
||||
if (mTimeInStateByPolicy.containsKey(policyDirName)) {
|
||||
ArrayMap<Long, Long> prevTimeInState = mTimeInStateByPolicy.get(policyDirName);
|
||||
ArrayMap<Long, Long> deltaTimeInState =
|
||||
calculateDeltaTimeInState(prevTimeInState, latestTimeInState);
|
||||
mTimeInStateByPolicy.put(policyDirName, latestTimeInState);
|
||||
return calculateAvgCpuFreq(deltaTimeInState);
|
||||
}
|
||||
mTimeInStateByPolicy.put(policyDirName, latestTimeInState);
|
||||
return calculateAvgCpuFreq(latestTimeInState);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private ArrayMap<Long, Long> readTimeInState(File policyDir) {
|
||||
if (!mHasTimeInStateFile) {
|
||||
return null;
|
||||
}
|
||||
File timeInStateFile = new File(policyDir, TIME_IN_STATE_FILE);
|
||||
try {
|
||||
List<String> lines = Files.readAllLines(timeInStateFile.toPath());
|
||||
if (lines.isEmpty()) {
|
||||
Slogf.w(TAG, "Empty time in state file at %s", timeInStateFile.getAbsolutePath());
|
||||
return null;
|
||||
}
|
||||
ArrayMap<Long, Long> cpuTimeByFrequencies = new ArrayMap<>();
|
||||
for (int i = 0; i < lines.size(); i++) {
|
||||
Matcher m = TIME_IN_STATE_PATTERN.matcher(lines.get(i).trim());
|
||||
if (!m.find()) {
|
||||
continue;
|
||||
}
|
||||
cpuTimeByFrequencies.put(Long.parseLong(m.group("freqKHz")),
|
||||
jiffyStrToMillis(m.group("time")));
|
||||
}
|
||||
return cpuTimeByFrequencies;
|
||||
} catch (Exception e) {
|
||||
Slogf.e(TAG, e, "Failed to read CPU time in state from file: %s",
|
||||
timeInStateFile.getAbsolutePath());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static long readCpuFreqKHz(File file) {
|
||||
if (!file.exists()) {
|
||||
Slogf.e(TAG, "CPU frequency file %s doesn't exist", file.getAbsolutePath());
|
||||
@@ -209,6 +330,37 @@ public final class CpuInfoReader {
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static ArrayMap<Long, Long> calculateDeltaTimeInState(
|
||||
ArrayMap<Long, Long> prevTimeInState, ArrayMap<Long, Long> latestTimeInState) {
|
||||
ArrayMap<Long, Long> deltaTimeInState = new ArrayMap();
|
||||
for (int i = 0; i < latestTimeInState.size(); i++) {
|
||||
long freq = latestTimeInState.keyAt(i);
|
||||
long durationMillis = latestTimeInState.valueAt(i);
|
||||
long deltaDurationMillis;
|
||||
if (prevTimeInState.containsKey(freq)) {
|
||||
long prevDurationMillis = prevTimeInState.get(freq);
|
||||
deltaDurationMillis = durationMillis > prevDurationMillis
|
||||
? (durationMillis - prevDurationMillis) : durationMillis;
|
||||
} else {
|
||||
deltaDurationMillis = durationMillis;
|
||||
}
|
||||
deltaTimeInState.put(freq, deltaDurationMillis);
|
||||
}
|
||||
return deltaTimeInState;
|
||||
}
|
||||
|
||||
private static long calculateAvgCpuFreq(ArrayMap<Long, Long> timeInState) {
|
||||
double totalTimeInState = 0;
|
||||
for (int i = 0; i < timeInState.size(); i++) {
|
||||
totalTimeInState += timeInState.valueAt(i);
|
||||
}
|
||||
double avgFreqKHz = 0;
|
||||
for (int i = 0; i < timeInState.size(); i++) {
|
||||
avgFreqKHz += (timeInState.keyAt(i) * timeInState.valueAt(i)) / totalTimeInState;
|
||||
}
|
||||
return (long) avgFreqKHz;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the list of CPU cores from the given file.
|
||||
*
|
||||
@@ -282,7 +434,7 @@ public final class CpuInfoReader {
|
||||
if (!m.find()) {
|
||||
continue;
|
||||
}
|
||||
cpuUsageStats.append(Integer.parseInt(Objects.requireNonNull(m.group("core"))),
|
||||
cpuUsageStats.append(Integer.parseInt(m.group("core")),
|
||||
new CpuUsageStats(jiffyStrToMillis(m.group("userClockTicks")),
|
||||
jiffyStrToMillis(m.group("niceClockTicks")),
|
||||
jiffyStrToMillis(m.group("sysClockTicks")),
|
||||
@@ -302,7 +454,7 @@ public final class CpuInfoReader {
|
||||
}
|
||||
|
||||
private static long jiffyStrToMillis(String jiffyStr) {
|
||||
return Long.parseLong(Objects.requireNonNull(jiffyStr)) * MILLIS_PER_JIFFY;
|
||||
return Long.parseLong(jiffyStr) * MILLIS_PER_JIFFY;
|
||||
}
|
||||
|
||||
/** Contains information for each CPU core on the system. */
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
0-
|
||||
@@ -0,0 +1 @@
|
||||
"1.23
|
||||
@@ -0,0 +1 @@
|
||||
+2.5
|
||||
@@ -0,0 +1 @@
|
||||
0-
|
||||
@@ -0,0 +1 @@
|
||||
0
|
||||
@@ -0,0 +1 @@
|
||||
0
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1 @@
|
||||
3000000
|
||||
@@ -0,0 +1 @@
|
||||
1000000
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,2 @@
|
||||
2,
|
||||
3
|
||||
@@ -0,0 +1,2 @@
|
||||
2,
|
||||
3
|
||||
@@ -0,0 +1 @@
|
||||
9
|
||||
@@ -0,0 +1 @@
|
||||
2
|
||||
@@ -0,0 +1,2 @@
|
||||
2,
|
||||
-3
|
||||
@@ -0,0 +1,2 @@
|
||||
0-
|
||||
1-2-3
|
||||
@@ -0,0 +1,12 @@
|
||||
cpu 6119889 1575038 10623107 81174407 250978 2293369 192710 16073 0 0
|
||||
cpu0 3224961 795093 5222705 40903695 132281 814674 42897 8195 0 0
|
||||
cpu1 2894928 779945 5400402 40270712 118696 1478694 149813 7878 0 0
|
||||
cpu2 2895928 corrupted 40271712 116696 1479694 147813 8878 0 0
|
||||
cpu3 3234961 785093 5212705 40913695 133281 813674 corrupted
|
||||
intr 1411620772 49 19 0 0 4 0 0 0 1 0 0 1497 3 0 0 0 1 0 0 0 0 459002 0 0 19479985 0 30742819 0 1 0 22977745 0 79 0 10 0 1578 2077 0 207913133 0 53571 0 43 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 142749 719664 0 4096981 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
ctxt 3289727889
|
||||
btime 1648158254
|
||||
processes 7700412
|
||||
procs_running 1
|
||||
procs_blocked 0
|
||||
softirq 190070910 9 21017845 30017 4408 64129752 0 672853 46618585 0 57597441
|
||||
@@ -0,0 +1 @@
|
||||
0
|
||||
@@ -0,0 +1 @@
|
||||
1230000
|
||||
@@ -0,0 +1 @@
|
||||
2500000
|
||||
@@ -0,0 +1 @@
|
||||
0
|
||||
@@ -0,0 +1 @@
|
||||
0
|
||||
@@ -0,0 +1 @@
|
||||
0
|
||||
@@ -0,0 +1,4 @@
|
||||
200000 500
|
||||
350000 500
|
||||
500000 1000
|
||||
2500000 100
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1 @@
|
||||
1450000
|
||||
@@ -0,0 +1 @@
|
||||
2800000
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,4 @@
|
||||
200000 500
|
||||
350000 500
|
||||
500000 1000
|
||||
2800000 100
|
||||
@@ -0,0 +1 @@
|
||||
2,3
|
||||
@@ -0,0 +1 @@
|
||||
2-3
|
||||
@@ -0,0 +1 @@
|
||||
1000000
|
||||
@@ -0,0 +1 @@
|
||||
2000000
|
||||
@@ -0,0 +1,4 @@
|
||||
200000 500
|
||||
350000 500
|
||||
500000 1000
|
||||
2000000 100
|
||||
@@ -0,0 +1 @@
|
||||
0
|
||||
@@ -0,0 +1 @@
|
||||
1000000
|
||||
@@ -0,0 +1 @@
|
||||
2500000
|
||||
@@ -0,0 +1 @@
|
||||
0
|
||||
@@ -0,0 +1 @@
|
||||
0
|
||||
@@ -0,0 +1,4 @@
|
||||
200000 1500
|
||||
350000 1500
|
||||
500000 2000
|
||||
2500000 200
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1 @@
|
||||
2800000
|
||||
@@ -0,0 +1 @@
|
||||
2800000
|
||||
@@ -0,0 +1,4 @@
|
||||
200000 1500
|
||||
350000 1500
|
||||
500000 2000
|
||||
2800000 200
|
||||
@@ -0,0 +1 @@
|
||||
2,3
|
||||
@@ -0,0 +1 @@
|
||||
2000000
|
||||
@@ -0,0 +1 @@
|
||||
2000000
|
||||
@@ -0,0 +1,4 @@
|
||||
200000 1500
|
||||
350000 1500
|
||||
500000 2000
|
||||
2000000 200
|
||||
@@ -0,0 +1 @@
|
||||
0
|
||||
@@ -0,0 +1 @@
|
||||
1230000
|
||||
@@ -0,0 +1 @@
|
||||
2500000
|
||||
@@ -0,0 +1 @@
|
||||
0
|
||||
@@ -0,0 +1 @@
|
||||
0
|
||||
@@ -0,0 +1 @@
|
||||
0
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1 @@
|
||||
1450000
|
||||
@@ -0,0 +1 @@
|
||||
2800000
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1 @@
|
||||
2,3
|
||||
@@ -0,0 +1 @@
|
||||
2-3
|
||||
@@ -0,0 +1 @@
|
||||
1000000
|
||||
@@ -0,0 +1 @@
|
||||
2000000
|
||||
@@ -0,0 +1 @@
|
||||
0
|
||||
@@ -0,0 +1 @@
|
||||
1000000
|
||||
@@ -0,0 +1 @@
|
||||
2500000
|
||||
@@ -0,0 +1 @@
|
||||
0
|
||||
@@ -0,0 +1 @@
|
||||
0
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1 @@
|
||||
2800000
|
||||
@@ -0,0 +1 @@
|
||||
2800000
|
||||
@@ -0,0 +1 @@
|
||||
2,3
|
||||
@@ -0,0 +1 @@
|
||||
2000000
|
||||
@@ -0,0 +1 @@
|
||||
2000000
|
||||
@@ -0,0 +1,2 @@
|
||||
2
|
||||
3
|
||||
@@ -0,0 +1 @@
|
||||
0-3
|
||||
@@ -0,0 +1,12 @@
|
||||
cpu 6119889 1575038 10623107 81174407 250978 2293369 192710 16073 0 0
|
||||
cpu0 3224961 795093 5222705 40903695 132281 814674 42897 8195 0 0
|
||||
cpu1 2894928 779945 5400402 40270712 118696 1478694 149813 7878 0 0
|
||||
cpu2 2895928 778945 5401402 40271712 116696 1479694 147813 8878 0 0
|
||||
cpu3 3234961 785093 5212705 40913695 133281 813674 43897 7195 0 0
|
||||
intr 1411620772 49 19 0 0 4 0 0 0 1 0 0 1497 3 0 0 0 1 0 0 0 0 459002 0 0 19479985 0 30742819 0 1 0 22977745 0 79 0 10 0 1578 2077 0 207913133 0 53571 0 43 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 142749 719664 0 4096981 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
ctxt 3289727889
|
||||
btime 1648158254
|
||||
processes 7700412
|
||||
procs_running 1
|
||||
procs_blocked 0
|
||||
softirq 190070910 9 21017845 30017 4408 64129752 0 672853 46618585 0 57597441
|
||||
@@ -0,0 +1,12 @@
|
||||
cpu 6119889 1575038 10623107 81174407 250978 2293369 192710 16073 0 0
|
||||
cpu0 4224961 895093 6222705 51903695 242281 954674 50897 10295 0 0
|
||||
cpu1 2984928 879945 6400402 40370712 127696 1498694 159813 17878 0 0
|
||||
cpu2 3895928 978945 5401402 41271712 216696 3479694 247813 18878 0 0
|
||||
cpu3 3434961 885093 5312705 40923695 143281 823674 143897 7295 0 0
|
||||
intr 1411620772 49 19 0 0 4 0 0 0 1 0 0 1497 3 0 0 0 1 0 0 0 0 459002 0 0 19479985 0 30742819 0 1 0 22977745 0 79 0 10 0 1578 2077 0 207913133 0 53571 0 43 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 142749 719664 0 4096981 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
ctxt 3289727889
|
||||
btime 1648158254
|
||||
processes 7700412
|
||||
procs_running 1
|
||||
procs_blocked 0
|
||||
softirq 190070910 9 21017845 30017 4408 64129752 0 672853 46618585 0 57597441
|
||||
@@ -0,0 +1,445 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.cpu;
|
||||
|
||||
import static com.android.server.cpu.CpuInfoReader.FLAG_CPUSET_CATEGORY_BACKGROUND;
|
||||
import static com.android.server.cpu.CpuInfoReader.FLAG_CPUSET_CATEGORY_TOP_APP;
|
||||
|
||||
import static com.google.common.truth.Truth.assertWithMessage;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.AssetManager;
|
||||
import android.util.Slog;
|
||||
|
||||
import androidx.test.platform.app.InstrumentationRegistry;
|
||||
|
||||
import com.android.server.ExtendedMockitoTestCase;
|
||||
|
||||
import libcore.io.Streams;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* <p>This class contains unit tests for the {@link CpuInfoReader}.
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public final class CpuInfoReaderTest extends ExtendedMockitoTestCase {
|
||||
private static final String TAG = CpuInfoReaderTest.class.getSimpleName();
|
||||
private static final String ROOT_DIR_NAME = "CpuInfoReaderTest";
|
||||
private static final String VALID_CPUSET_DIR = "valid_cpuset";
|
||||
private static final String VALID_CPUFREQ_WITH_TIME_IN_STATE_DIR =
|
||||
"valid_cpufreq_with_time_in_state";
|
||||
private static final String VALID_CPUFREQ_WITH_TIME_IN_STATE_2_DIR =
|
||||
"valid_cpufreq_with_time_in_state_2";
|
||||
private static final String VALID_CPUFREQ_WITHOUT_TIME_IN_STATE_DIR =
|
||||
"valid_cpufreq_without_time_in_state";
|
||||
private static final String VALID_CPUFREQ_WITHOUT_TIME_IN_STATE_2_DIR =
|
||||
"valid_cpufreq_without_time_in_state_2";
|
||||
private static final String VALID_PROC_STAT = "valid_proc_stat";
|
||||
private static final String VALID_PROC_STAT_2 = "valid_proc_stat_2";
|
||||
private static final String CORRUPTED_CPUFREQ_DIR = "corrupted_cpufreq";
|
||||
private static final String CORRUPTED_CPUSET_DIR = "corrupted_cpuset";
|
||||
private static final String CORRUPTED_PROC_STAT = "corrupted_proc_stat";
|
||||
private static final String EMPTY_DIR = "empty_dir";
|
||||
private static final String EMPTY_FILE = "empty_file";
|
||||
|
||||
private final Context mContext =
|
||||
InstrumentationRegistry.getInstrumentation().getTargetContext();
|
||||
private final File mCacheRoot = new File(mContext.getCacheDir(), ROOT_DIR_NAME);
|
||||
private final AssetManager mAssetManager = mContext.getAssets();
|
||||
|
||||
private CpuInfoReader mCpuInfoReader;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
copyAssets(ROOT_DIR_NAME, mContext.getCacheDir());
|
||||
assertWithMessage("Cache root dir %s", mCacheRoot.getAbsolutePath())
|
||||
.that(mCacheRoot.exists()).isTrue();
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
if (!deleteDirectory(mCacheRoot)) {
|
||||
Slog.e(TAG, "Failed to delete cache root directory " + mCacheRoot.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadCpuInfoWithTimeInState() throws Exception {
|
||||
mCpuInfoReader = new CpuInfoReader(getCacheFile(VALID_CPUSET_DIR),
|
||||
getCacheFile(VALID_CPUFREQ_WITH_TIME_IN_STATE_DIR), getCacheFile(VALID_PROC_STAT));
|
||||
mCpuInfoReader.init();
|
||||
List<CpuInfoReader.CpuInfo> actualCpuInfos = mCpuInfoReader.readCpuInfos();
|
||||
List<CpuInfoReader.CpuInfo> expectedCpuInfos = List.of(
|
||||
new CpuInfoReader.CpuInfo(/* cpuCore= */ 0, FLAG_CPUSET_CATEGORY_TOP_APP,
|
||||
/* curCpuFreqKHz= */ 488_095, /* maxCpuFreqKHz= */ 2_500_000,
|
||||
new CpuInfoReader.CpuUsageStats(/* userTimeMillis= */ 32_249_610,
|
||||
/* niceTimeMillis= */ 7_950_930, /* systemTimeMillis= */ 52_227_050,
|
||||
/* idleTimeMillis= */ 409_036_950,
|
||||
/* iowaitTimeMillis= */ 1_322_810, /* irqTimeMillis= */ 8_146_740,
|
||||
/* softirqTimeMillis= */ 428_970, /* stealTimeMillis= */ 81_950,
|
||||
/* guestTimeMillis= */ 0, /* guestNiceTimeMillis= */ 0)),
|
||||
new CpuInfoReader.CpuInfo(/* cpuCore= */ 1, FLAG_CPUSET_CATEGORY_TOP_APP,
|
||||
/* curCpuFreqKHz= */ 502_380, /* maxCpuFreqKHz= */ 2_800_000,
|
||||
new CpuInfoReader.CpuUsageStats(/* userTimeMillis= */ 28_949_280,
|
||||
/* niceTimeMillis= */ 7_799_450, /* systemTimeMillis= */ 54_004_020,
|
||||
/* idleTimeMillis= */ 402_707_120,
|
||||
/* iowaitTimeMillis= */ 1_186_960, /* irqTimeMillis= */ 14_786_940,
|
||||
/* softirqTimeMillis= */ 1_498_130, /* stealTimeMillis= */ 78_780,
|
||||
/* guestTimeMillis= */ 0, /* guestNiceTimeMillis= */ 0)),
|
||||
new CpuInfoReader.CpuInfo(/* cpuCore= */ 2,
|
||||
FLAG_CPUSET_CATEGORY_TOP_APP | FLAG_CPUSET_CATEGORY_BACKGROUND,
|
||||
/* curCpuFreqKHz= */ 464_285, /* maxCpuFreqKHz= */ 2_000_000,
|
||||
new CpuInfoReader.CpuUsageStats(/* userTimeMillis= */ 28_959_280,
|
||||
/* niceTimeMillis= */ 7_789_450, /* systemTimeMillis= */ 54_014_020,
|
||||
/* idleTimeMillis= */ 402_717_120,
|
||||
/* iowaitTimeMillis= */ 1_166_960, /* irqTimeMillis= */ 14_796_940,
|
||||
/* softirqTimeMillis= */ 1_478_130, /* stealTimeMillis= */ 88_780,
|
||||
/* guestTimeMillis= */ 0, /* guestNiceTimeMillis= */ 0)),
|
||||
new CpuInfoReader.CpuInfo(/* cpuCore= */ 3,
|
||||
FLAG_CPUSET_CATEGORY_TOP_APP | FLAG_CPUSET_CATEGORY_BACKGROUND,
|
||||
/* curCpuFreqKHz= */ 464_285, /* maxCpuFreqKHz= */ 2_000_000,
|
||||
new CpuInfoReader.CpuUsageStats(/* userTimeMillis= */ 32_349_610,
|
||||
/* niceTimeMillis= */ 7_850_930, /* systemTimeMillis= */ 52_127_050,
|
||||
/* idleTimeMillis= */ 409_136_950,
|
||||
/* iowaitTimeMillis= */ 1_332_810, /* irqTimeMillis= */ 8_136_740,
|
||||
/* softirqTimeMillis= */ 438_970, /* stealTimeMillis= */ 71_950,
|
||||
/* guestTimeMillis= */ 0, /* guestNiceTimeMillis= */ 0)));
|
||||
|
||||
assertWithMessage("Cpu infos").that(actualCpuInfos)
|
||||
.containsExactlyElementsIn(expectedCpuInfos);
|
||||
|
||||
mCpuInfoReader.setCpuFreqDir(getCacheFile(VALID_CPUFREQ_WITH_TIME_IN_STATE_2_DIR));
|
||||
mCpuInfoReader.setProcStatFile(getCacheFile(VALID_PROC_STAT_2));
|
||||
|
||||
actualCpuInfos = mCpuInfoReader.readCpuInfos();
|
||||
expectedCpuInfos = List.of(
|
||||
new CpuInfoReader.CpuInfo(/* cpuCore= */ 0, FLAG_CPUSET_CATEGORY_TOP_APP,
|
||||
/* curCpuFreqKHz= */ 419_354, /* maxCpuFreqKHz= */ 2_500_000,
|
||||
new CpuInfoReader.CpuUsageStats(/* userTimeMillis= */ 10_000_000,
|
||||
/* niceTimeMillis= */ 1_000_000, /* systemTimeMillis= */ 10_000_000,
|
||||
/* idleTimeMillis= */ 110_000_000,
|
||||
/* iowaitTimeMillis= */ 1_100_000, /* irqTimeMillis= */ 1_400_000,
|
||||
/* softirqTimeMillis= */ 80_000, /* stealTimeMillis= */ 21_000,
|
||||
/* guestTimeMillis= */ 0, /* guestNiceTimeMillis= */ 0)),
|
||||
new CpuInfoReader.CpuInfo(/* cpuCore= */ 1, FLAG_CPUSET_CATEGORY_TOP_APP,
|
||||
/* curCpuFreqKHz= */ 429_032, /* maxCpuFreqKHz= */ 2_800_000,
|
||||
new CpuInfoReader.CpuUsageStats(/* userTimeMillis= */ 900_000,
|
||||
/* niceTimeMillis= */ 1_000_000, /* systemTimeMillis= */ 10_000_000,
|
||||
/* idleTimeMillis= */ 1_000_000, /* iowaitTimeMillis= */ 90_000,
|
||||
/* irqTimeMillis= */ 200_000, /* softirqTimeMillis= */ 100_000,
|
||||
/* stealTimeMillis= */ 100_000, /* guestTimeMillis= */ 0,
|
||||
/* guestNiceTimeMillis= */ 0)),
|
||||
new CpuInfoReader.CpuInfo(/* cpuCore= */ 2,
|
||||
FLAG_CPUSET_CATEGORY_TOP_APP | FLAG_CPUSET_CATEGORY_BACKGROUND,
|
||||
/* curCpuFreqKHz= */ 403_225, /* maxCpuFreqKHz= */ 2_000_000,
|
||||
new CpuInfoReader.CpuUsageStats(/* userTimeMillis= */ 10_000_000,
|
||||
/* niceTimeMillis= */ 2_000_000, /* systemTimeMillis= */ 0,
|
||||
/* idleTimeMillis= */ 10_000_000, /* iowaitTimeMillis= */ 1_000_000,
|
||||
/* irqTimeMillis= */ 20_000_000, /* softirqTimeMillis= */ 1_000_000,
|
||||
/* stealTimeMillis= */ 100_000, /* guestTimeMillis= */ 0,
|
||||
/* guestNiceTimeMillis= */ 0)),
|
||||
new CpuInfoReader.CpuInfo(/* cpuCore= */ 3,
|
||||
FLAG_CPUSET_CATEGORY_TOP_APP | FLAG_CPUSET_CATEGORY_BACKGROUND,
|
||||
/* curCpuFreqKHz= */ 403_225, /* maxCpuFreqKHz= */ 2_000_000,
|
||||
new CpuInfoReader.CpuUsageStats(/* userTimeMillis= */ 2_000_000,
|
||||
/* niceTimeMillis= */ 1_000_000, /* systemTimeMillis= */ 1_000_000,
|
||||
/* idleTimeMillis= */ 100_000, /* iowaitTimeMillis= */ 100_000,
|
||||
/* irqTimeMillis= */ 100_000, /* softirqTimeMillis= */ 1_000_000,
|
||||
/* stealTimeMillis= */ 1_000, /* guestTimeMillis= */ 0,
|
||||
/* guestNiceTimeMillis= */ 0)));
|
||||
|
||||
assertWithMessage("Second snapshot of cpu infos").that(actualCpuInfos)
|
||||
.containsExactlyElementsIn(expectedCpuInfos);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadCpuInfoWithoutTimeInState() throws Exception {
|
||||
mCpuInfoReader = new CpuInfoReader(getCacheFile(VALID_CPUSET_DIR),
|
||||
getCacheFile(VALID_CPUFREQ_WITHOUT_TIME_IN_STATE_DIR),
|
||||
getCacheFile(VALID_PROC_STAT));
|
||||
mCpuInfoReader.init();
|
||||
List<CpuInfoReader.CpuInfo> actualCpuInfos = mCpuInfoReader.readCpuInfos();
|
||||
List<CpuInfoReader.CpuInfo> expectedCpuInfos = List.of(
|
||||
new CpuInfoReader.CpuInfo(/* cpuCore= */ 0, FLAG_CPUSET_CATEGORY_TOP_APP,
|
||||
/* curCpuFreqKHz= */ 1_230_000, /* maxCpuFreqKHz= */ 2_500_000,
|
||||
new CpuInfoReader.CpuUsageStats(/* userTimeMillis= */ 32_249_610,
|
||||
/* niceTimeMillis= */ 7_950_930, /* systemTimeMillis= */ 52_227_050,
|
||||
/* idleTimeMillis= */ 409_036_950,
|
||||
/* iowaitTimeMillis= */ 1_322_810, /* irqTimeMillis= */ 8_146_740,
|
||||
/* softirqTimeMillis= */ 428_970, /* stealTimeMillis= */ 81_950,
|
||||
/* guestTimeMillis= */ 0, /* guestNiceTimeMillis= */ 0)),
|
||||
new CpuInfoReader.CpuInfo(/* cpuCore= */ 1, FLAG_CPUSET_CATEGORY_TOP_APP,
|
||||
/* curCpuFreqKHz= */ 1_450_000, /* maxCpuFreqKHz= */ 2_800_000,
|
||||
new CpuInfoReader.CpuUsageStats(/* userTimeMillis= */ 28_949_280,
|
||||
/* niceTimeMillis= */ 7_799_450, /* systemTimeMillis= */ 54_004_020,
|
||||
/* idleTimeMillis= */ 402_707_120,
|
||||
/* iowaitTimeMillis= */ 1_186_960, /* irqTimeMillis= */ 14_786_940,
|
||||
/* softirqTimeMillis= */ 1_498_130, /* stealTimeMillis= */ 78_780,
|
||||
/* guestTimeMillis= */ 0, /* guestNiceTimeMillis= */ 0)),
|
||||
new CpuInfoReader.CpuInfo(/* cpuCore= */ 2,
|
||||
FLAG_CPUSET_CATEGORY_TOP_APP | FLAG_CPUSET_CATEGORY_BACKGROUND,
|
||||
/* curCpuFreqKHz= */ 1_000_000, /* maxCpuFreqKHz= */ 2_000_000,
|
||||
new CpuInfoReader.CpuUsageStats(/* userTimeMillis= */ 28_959_280,
|
||||
/* niceTimeMillis= */ 7_789_450, /* systemTimeMillis= */ 54_014_020,
|
||||
/* idleTimeMillis= */ 402_717_120,
|
||||
/* iowaitTimeMillis= */ 1_166_960, /* irqTimeMillis= */ 14_796_940,
|
||||
/* softirqTimeMillis= */ 1_478_130, /* stealTimeMillis= */ 88_780,
|
||||
/* guestTimeMillis= */ 0, /* guestNiceTimeMillis= */ 0)),
|
||||
new CpuInfoReader.CpuInfo(/* cpuCore= */ 3,
|
||||
FLAG_CPUSET_CATEGORY_TOP_APP | FLAG_CPUSET_CATEGORY_BACKGROUND,
|
||||
/* curCpuFreqKHz= */ 1_000_000, /* maxCpuFreqKHz= */ 2_000_000,
|
||||
new CpuInfoReader.CpuUsageStats(/* userTimeMillis= */ 32_349_610,
|
||||
/* niceTimeMillis= */ 7_850_930, /* systemTimeMillis= */ 52_127_050,
|
||||
/* idleTimeMillis= */ 409_136_950,
|
||||
/* iowaitTimeMillis= */ 1_332_810, /* irqTimeMillis= */ 8_136_740,
|
||||
/* softirqTimeMillis= */ 438_970, /* stealTimeMillis= */ 71_950,
|
||||
/* guestTimeMillis= */ 0, /* guestNiceTimeMillis= */ 0)));
|
||||
|
||||
assertWithMessage("Cpu infos").that(actualCpuInfos)
|
||||
.containsExactlyElementsIn(expectedCpuInfos);
|
||||
|
||||
mCpuInfoReader.setCpuFreqDir(getCacheFile(VALID_CPUFREQ_WITHOUT_TIME_IN_STATE_2_DIR));
|
||||
mCpuInfoReader.setProcStatFile(getCacheFile(VALID_PROC_STAT_2));
|
||||
|
||||
actualCpuInfos = mCpuInfoReader.readCpuInfos();
|
||||
expectedCpuInfos = List.of(
|
||||
new CpuInfoReader.CpuInfo(/* cpuCore= */ 0, FLAG_CPUSET_CATEGORY_TOP_APP,
|
||||
/* curCpuFreqKHz= */ 1_000_000, /* maxCpuFreqKHz= */ 2_500_000,
|
||||
new CpuInfoReader.CpuUsageStats(/* userTimeMillis= */ 10_000_000,
|
||||
/* niceTimeMillis= */ 1_000_000, /* systemTimeMillis= */ 10_000_000,
|
||||
/* idleTimeMillis= */ 110_000_000,
|
||||
/* iowaitTimeMillis= */ 1_100_000, /* irqTimeMillis= */ 1_400_000,
|
||||
/* softirqTimeMillis= */ 80_000, /* stealTimeMillis= */ 21_000,
|
||||
/* guestTimeMillis= */ 0, /* guestNiceTimeMillis= */ 0)),
|
||||
new CpuInfoReader.CpuInfo(/* cpuCore= */ 1, FLAG_CPUSET_CATEGORY_TOP_APP,
|
||||
/* curCpuFreqKHz= */ 2_800_000, /* maxCpuFreqKHz= */ 2_800_000,
|
||||
new CpuInfoReader.CpuUsageStats(/* userTimeMillis= */ 900_000,
|
||||
/* niceTimeMillis= */ 1_000_000, /* systemTimeMillis= */ 10_000_000,
|
||||
/* idleTimeMillis= */ 1_000_000, /* iowaitTimeMillis= */ 90_000,
|
||||
/* irqTimeMillis= */ 200_000, /* softirqTimeMillis= */ 100_000,
|
||||
/* stealTimeMillis= */ 100_000, /* guestTimeMillis= */ 0,
|
||||
/* guestNiceTimeMillis= */ 0)),
|
||||
new CpuInfoReader.CpuInfo(/* cpuCore= */ 2,
|
||||
FLAG_CPUSET_CATEGORY_TOP_APP | FLAG_CPUSET_CATEGORY_BACKGROUND,
|
||||
/* curCpuFreqKHz= */ 2_000_000, /* maxCpuFreqKHz= */ 2_000_000,
|
||||
new CpuInfoReader.CpuUsageStats(/* userTimeMillis= */ 10_000_000,
|
||||
/* niceTimeMillis= */ 2_000_000, /* systemTimeMillis= */ 0,
|
||||
/* idleTimeMillis= */ 10_000_000, /* iowaitTimeMillis= */ 1_000_000,
|
||||
/* irqTimeMillis= */ 20_000_000, /* softirqTimeMillis= */ 1_000_000,
|
||||
/* stealTimeMillis= */ 100_000, /* guestTimeMillis= */ 0,
|
||||
/* guestNiceTimeMillis= */ 0)),
|
||||
new CpuInfoReader.CpuInfo(/* cpuCore= */ 3,
|
||||
FLAG_CPUSET_CATEGORY_TOP_APP | FLAG_CPUSET_CATEGORY_BACKGROUND,
|
||||
/* curCpuFreqKHz= */ 2_000_000, /* maxCpuFreqKHz= */ 2_000_000,
|
||||
new CpuInfoReader.CpuUsageStats(/* userTimeMillis= */ 2_000_000,
|
||||
/* niceTimeMillis= */ 1_000_000, /* systemTimeMillis= */ 1_000_000,
|
||||
/* idleTimeMillis= */ 100_000, /* iowaitTimeMillis= */ 100_000,
|
||||
/* irqTimeMillis= */ 100_000, /* softirqTimeMillis= */ 1_000_000,
|
||||
/* stealTimeMillis= */ 1_000, /* guestTimeMillis= */ 0,
|
||||
/* guestNiceTimeMillis= */ 0)));
|
||||
|
||||
assertWithMessage("Second snapshot of cpu infos").that(actualCpuInfos)
|
||||
.containsExactlyElementsIn(expectedCpuInfos);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadCpuInfoWithCorruptedCpuset() throws Exception {
|
||||
mCpuInfoReader = new CpuInfoReader(getCacheFile(CORRUPTED_CPUSET_DIR),
|
||||
getCacheFile(VALID_CPUFREQ_WITH_TIME_IN_STATE_DIR),
|
||||
getCacheFile(VALID_PROC_STAT));
|
||||
mCpuInfoReader.init();
|
||||
List<CpuInfoReader.CpuInfo> actualCpuInfos = mCpuInfoReader.readCpuInfos();
|
||||
List<CpuInfoReader.CpuInfo> expectedCpuInfos = List.of(
|
||||
new CpuInfoReader.CpuInfo(/* cpuCore= */ 0, FLAG_CPUSET_CATEGORY_TOP_APP,
|
||||
/* curCpuFreqKHz= */ 488_095, /* maxCpuFreqKHz= */ 2_500_000,
|
||||
new CpuInfoReader.CpuUsageStats(/* userTimeMillis= */ 32_249_610,
|
||||
/* niceTimeMillis= */ 7_950_930, /* systemTimeMillis= */ 52_227_050,
|
||||
/* idleTimeMillis= */ 409_036_950,
|
||||
/* iowaitTimeMillis= */ 1_322_810, /* irqTimeMillis= */ 8_146_740,
|
||||
/* softirqTimeMillis= */ 428_970, /* stealTimeMillis= */ 81_950,
|
||||
/* guestTimeMillis= */ 0, /* guestNiceTimeMillis= */ 0)),
|
||||
new CpuInfoReader.CpuInfo(/* cpuCore= */ 1, FLAG_CPUSET_CATEGORY_TOP_APP,
|
||||
/* curCpuFreqKHz= */ 502_380, /* maxCpuFreqKHz= */ 2_800_000,
|
||||
new CpuInfoReader.CpuUsageStats(/* userTimeMillis= */ 28_949_280,
|
||||
/* niceTimeMillis= */ 7_799_450, /* systemTimeMillis= */ 54_004_020,
|
||||
/* idleTimeMillis= */ 402_707_120,
|
||||
/* iowaitTimeMillis= */ 1_186_960, /* irqTimeMillis= */ 14_786_940,
|
||||
/* softirqTimeMillis= */ 1_498_130, /* stealTimeMillis= */ 78_780,
|
||||
/* guestTimeMillis= */ 0, /* guestNiceTimeMillis= */ 0)),
|
||||
new CpuInfoReader.CpuInfo(/* cpuCore= */ 2, FLAG_CPUSET_CATEGORY_TOP_APP,
|
||||
/* curCpuFreqKHz= */ 464_285, /* maxCpuFreqKHz= */ 2_000_000,
|
||||
new CpuInfoReader.CpuUsageStats(/* userTimeMillis= */ 28_959_280,
|
||||
/* niceTimeMillis= */ 7_789_450, /* systemTimeMillis= */ 54_014_020,
|
||||
/* idleTimeMillis= */ 402_717_120,
|
||||
/* iowaitTimeMillis= */ 1_166_960, /* irqTimeMillis= */ 14_796_940,
|
||||
/* softirqTimeMillis= */ 1_478_130, /* stealTimeMillis= */ 88_780,
|
||||
/* guestTimeMillis= */ 0, /* guestNiceTimeMillis= */ 0)));
|
||||
|
||||
assertWithMessage("Cpu infos").that(actualCpuInfos)
|
||||
.containsExactlyElementsIn(expectedCpuInfos);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadCpuInfoWithCorruptedCpufreq() throws Exception {
|
||||
mCpuInfoReader = new CpuInfoReader(getCacheFile(VALID_CPUSET_DIR),
|
||||
getCacheFile(CORRUPTED_CPUFREQ_DIR), getCacheFile(VALID_PROC_STAT));
|
||||
mCpuInfoReader.init();
|
||||
List<CpuInfoReader.CpuInfo> actualCpuInfos = mCpuInfoReader.readCpuInfos();
|
||||
List<CpuInfoReader.CpuInfo> expectedCpuInfos = List.of(
|
||||
new CpuInfoReader.CpuInfo(/* cpuCore= */ 1, FLAG_CPUSET_CATEGORY_TOP_APP,
|
||||
/* curCpuFreqKHz= */ 3_000_000, /* maxCpuFreqKHz= */ 1_000_000,
|
||||
new CpuInfoReader.CpuUsageStats(/* userTimeMillis= */ 28_949_280,
|
||||
/* niceTimeMillis= */ 7_799_450, /* systemTimeMillis= */ 54_004_020,
|
||||
/* idleTimeMillis= */ 402_707_120,
|
||||
/* iowaitTimeMillis= */ 1_186_960, /* irqTimeMillis= */ 14_786_940,
|
||||
/* softirqTimeMillis= */ 1_498_130, /* stealTimeMillis= */ 78_780,
|
||||
/* guestTimeMillis= */ 0, /* guestNiceTimeMillis= */ 0)),
|
||||
new CpuInfoReader.CpuInfo(/* cpuCore= */ 2,
|
||||
FLAG_CPUSET_CATEGORY_TOP_APP | FLAG_CPUSET_CATEGORY_BACKGROUND,
|
||||
/* curCpuFreqKHz= */ 9, /* maxCpuFreqKHz= */ 2,
|
||||
new CpuInfoReader.CpuUsageStats(/* userTimeMillis= */ 28_959_280,
|
||||
/* niceTimeMillis= */ 7_789_450, /* systemTimeMillis= */ 54_014_020,
|
||||
/* idleTimeMillis= */ 402_717_120,
|
||||
/* iowaitTimeMillis= */ 1_166_960, /* irqTimeMillis= */ 14_796_940,
|
||||
/* softirqTimeMillis= */ 1_478_130, /* stealTimeMillis= */ 88_780,
|
||||
/* guestTimeMillis= */ 0, /* guestNiceTimeMillis= */ 0)),
|
||||
new CpuInfoReader.CpuInfo(/* cpuCore= */ 3,
|
||||
FLAG_CPUSET_CATEGORY_TOP_APP | FLAG_CPUSET_CATEGORY_BACKGROUND,
|
||||
/* curCpuFreqKHz= */ 9, /* maxCpuFreqKHz= */ 2,
|
||||
new CpuInfoReader.CpuUsageStats(/* userTimeMillis= */ 32_349_610,
|
||||
/* niceTimeMillis= */ 7_850_930, /* systemTimeMillis= */ 52_127_050,
|
||||
/* idleTimeMillis= */ 409_136_950,
|
||||
/* iowaitTimeMillis= */ 1_332_810, /* irqTimeMillis= */ 8_136_740,
|
||||
/* softirqTimeMillis= */ 438_970, /* stealTimeMillis= */ 71_950,
|
||||
/* guestTimeMillis= */ 0, /* guestNiceTimeMillis= */ 0)));
|
||||
|
||||
assertWithMessage("Cpu infos").that(actualCpuInfos)
|
||||
.containsExactlyElementsIn(expectedCpuInfos);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadCpuInfoCorruptedProcStat() throws Exception {
|
||||
mCpuInfoReader = new CpuInfoReader(getCacheFile(VALID_CPUSET_DIR),
|
||||
getCacheFile(VALID_CPUFREQ_WITH_TIME_IN_STATE_DIR),
|
||||
getCacheFile(CORRUPTED_PROC_STAT));
|
||||
mCpuInfoReader.init();
|
||||
List<CpuInfoReader.CpuInfo> actualCpuInfos = mCpuInfoReader.readCpuInfos();
|
||||
List<CpuInfoReader.CpuInfo> expectedCpuInfos = List.of(
|
||||
new CpuInfoReader.CpuInfo(/* cpuCore= */ 0, FLAG_CPUSET_CATEGORY_TOP_APP,
|
||||
/* curCpuFreqKHz= */ 488_095, /* maxCpuFreqKHz= */ 2_500_000,
|
||||
new CpuInfoReader.CpuUsageStats(/* userTimeMillis= */ 32_249_610,
|
||||
/* niceTimeMillis= */ 7_950_930, /* systemTimeMillis= */ 52_227_050,
|
||||
/* idleTimeMillis= */ 409_036_950,
|
||||
/* iowaitTimeMillis= */ 1_322_810, /* irqTimeMillis= */ 8_146_740,
|
||||
/* softirqTimeMillis= */ 428_970, /* stealTimeMillis= */ 81_950,
|
||||
/* guestTimeMillis= */ 0, /* guestNiceTimeMillis= */ 0)),
|
||||
new CpuInfoReader.CpuInfo(/* cpuCore= */ 1,
|
||||
FLAG_CPUSET_CATEGORY_TOP_APP,
|
||||
/* curCpuFreqKHz= */ 502_380, /* maxCpuFreqKHz= */ 2_800_000,
|
||||
new CpuInfoReader.CpuUsageStats(/* userTimeMillis= */ 28_949_280,
|
||||
/* niceTimeMillis= */ 7_799_450, /* systemTimeMillis= */ 54_004_020,
|
||||
/* idleTimeMillis= */ 402_707_120,
|
||||
/* iowaitTimeMillis= */ 1_186_960, /* irqTimeMillis= */ 14_786_940,
|
||||
/* softirqTimeMillis= */ 1_498_130, /* stealTimeMillis= */ 78_780,
|
||||
/* guestTimeMillis= */ 0, /* guestNiceTimeMillis= */ 0)));
|
||||
|
||||
assertWithMessage("Cpu infos").that(actualCpuInfos)
|
||||
.containsExactlyElementsIn(expectedCpuInfos);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadCpuInfoWithEmptyCpuset() throws Exception {
|
||||
File emptyDir = getCacheFile(EMPTY_DIR);
|
||||
assertWithMessage("Make empty dir %s", emptyDir).that(emptyDir.mkdir()).isTrue();
|
||||
mCpuInfoReader = new CpuInfoReader(emptyDir, getCacheFile(
|
||||
VALID_CPUFREQ_WITH_TIME_IN_STATE_DIR),
|
||||
getCacheFile(VALID_PROC_STAT));
|
||||
|
||||
assertWithMessage("Init CPU reader info").that(mCpuInfoReader.init()).isFalse();
|
||||
|
||||
assertWithMessage("Cpu infos").that(mCpuInfoReader.readCpuInfos()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadCpuInfoWithEmptyCpufreq() throws Exception {
|
||||
File emptyDir = getCacheFile(EMPTY_DIR);
|
||||
assertWithMessage("Make empty dir %s", emptyDir).that(emptyDir.mkdir()).isTrue();
|
||||
mCpuInfoReader = new CpuInfoReader(getCacheFile(VALID_CPUSET_DIR), emptyDir,
|
||||
getCacheFile(VALID_PROC_STAT));
|
||||
|
||||
assertWithMessage("Init CPU reader info").that(mCpuInfoReader.init()).isFalse();
|
||||
|
||||
assertWithMessage("Cpu infos").that(mCpuInfoReader.readCpuInfos()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadCpuInfoWithEmptyProcStat() throws Exception {
|
||||
File emptyFile = getCacheFile(EMPTY_FILE);
|
||||
assertWithMessage("Create empty file %s", emptyFile).that(emptyFile.createNewFile())
|
||||
.isTrue();
|
||||
mCpuInfoReader = new CpuInfoReader(getCacheFile(VALID_CPUSET_DIR),
|
||||
getCacheFile(VALID_CPUFREQ_WITH_TIME_IN_STATE_DIR), getCacheFile(EMPTY_FILE));
|
||||
|
||||
assertWithMessage("Cpu infos").that(mCpuInfoReader.readCpuInfos()).isEmpty();
|
||||
}
|
||||
|
||||
private File getCacheFile(String assetName) {
|
||||
return new File(mCacheRoot, assetName);
|
||||
}
|
||||
|
||||
private void copyAssets(String assetPath, File targetRoot) throws Exception {
|
||||
File target = new File(targetRoot, assetPath);
|
||||
String[] assets = mAssetManager.list(assetPath);
|
||||
if (assets == null || assets.length == 0) {
|
||||
try (InputStream in = mAssetManager.open(assetPath);
|
||||
OutputStream out = new FileOutputStream(target)) {
|
||||
Streams.copy(in, out);
|
||||
}
|
||||
return;
|
||||
}
|
||||
assertWithMessage("Make target directory %s", target).that(target.mkdir()).isTrue();
|
||||
for (int i = 0; i < assets.length; i++) {
|
||||
copyAssets(String.format("%s%s%s", assetPath, File.separator, assets[i]), targetRoot);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean deleteDirectory(File rootDir) {
|
||||
if (!rootDir.exists() || !rootDir.isDirectory()) {
|
||||
return false;
|
||||
}
|
||||
for (File file : Objects.requireNonNull(rootDir.listFiles())) {
|
||||
if (file.isDirectory()) {
|
||||
deleteDirectory(file);
|
||||
} else if (!file.delete()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return rootDir.delete();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user