Merge "Report CPU online status & avg time in state freq."
This commit is contained in:
committed by
Android (Google) Code Review
commit
2127ea68e3
@@ -16,11 +16,15 @@
|
||||
|
||||
package com.android.server.cpu;
|
||||
|
||||
import static com.android.server.cpu.CpuMonitorService.DEBUG;
|
||||
import static com.android.server.cpu.CpuMonitorService.TAG;
|
||||
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.Nullable;
|
||||
import android.system.Os;
|
||||
import android.system.OsConstants;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.IntArray;
|
||||
import android.util.LongSparseLongArray;
|
||||
import android.util.SparseArray;
|
||||
import android.util.SparseIntArray;
|
||||
|
||||
@@ -31,8 +35,7 @@ import java.io.File;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.nio.file.Files;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.regex.Matcher;
|
||||
@@ -40,7 +43,6 @@ import java.util.regex.Pattern;
|
||||
|
||||
/** Reader to read CPU information from proc and sys fs files exposed by the Kernel. */
|
||||
public final class CpuInfoReader {
|
||||
static final String TAG = CpuInfoReader.class.getSimpleName();
|
||||
static final int FLAG_CPUSET_CATEGORY_TOP_APP = 1 << 0;
|
||||
static final int FLAG_CPUSET_CATEGORY_BACKGROUND = 1 << 1;
|
||||
|
||||
@@ -67,7 +69,7 @@ public final class CpuInfoReader {
|
||||
+ "(?<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);
|
||||
private static final long MILLIS_PER_CLOCK_TICK = 1000L / Os.sysconf(OsConstants._SC_CLK_TCK);
|
||||
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@IntDef(prefix = {"FLAG_CPUSET_CATEGORY_"}, flag = true, value = {
|
||||
@@ -76,14 +78,15 @@ public final class CpuInfoReader {
|
||||
})
|
||||
private @interface CpusetCategory{}
|
||||
|
||||
// TODO(b/242722241): Protect updatable variables with a local lock.
|
||||
private final File mCpusetDir;
|
||||
private final SparseIntArray mCpusetCategoriesByCpus = new SparseIntArray();
|
||||
private final SparseArray<Long> mMaxCpuFrequenciesByCpus = new SparseArray<>();
|
||||
private final ArrayMap<String, ArrayMap<Long, Long>> mTimeInStateByPolicy = new ArrayMap<>();
|
||||
private final SparseArray<File> mCpuFreqPolicyDirsById = new SparseArray<>();
|
||||
private final SparseArray<StaticPolicyInfo> mStaticPolicyInfoById = new SparseArray<>();
|
||||
private final SparseArray<LongSparseLongArray> mTimeInStateByPolicyId = new SparseArray<>();
|
||||
|
||||
private File mCpuFreqDir;
|
||||
private File mProcStatFile;
|
||||
private File[] mCpuFreqPolicyDirs;
|
||||
private SparseArray<CpuUsageStats> mCumulativeCpuUsageStats = new SparseArray<>();
|
||||
private boolean mIsEnabled;
|
||||
private boolean mHasTimeInStateFile;
|
||||
@@ -99,88 +102,206 @@ public final class CpuInfoReader {
|
||||
mProcStatFile = procStatFile;
|
||||
}
|
||||
|
||||
/** Inits CpuInfoReader and returns a boolean to indicate whether the reader is enabled. */
|
||||
/**
|
||||
* Initializes CpuInfoReader and returns a boolean to indicate whether the reader is enabled.
|
||||
*/
|
||||
public boolean init() {
|
||||
mCpuFreqPolicyDirs = mCpuFreqDir.listFiles(
|
||||
if (mCpuFreqPolicyDirsById.size() > 0) {
|
||||
Slogf.w(TAG, "Ignoring duplicate CpuInfoReader init request");
|
||||
return mIsEnabled;
|
||||
}
|
||||
File[] policyDirs = mCpuFreqDir.listFiles(
|
||||
file -> file.isDirectory() && file.getName().startsWith(POLICY_DIR_PREFIX));
|
||||
if (mCpuFreqPolicyDirs == null || mCpuFreqPolicyDirs.length == 0) {
|
||||
if (policyDirs == null || policyDirs.length == 0) {
|
||||
Slogf.w(TAG, "Missing CPU frequency policy directories at %s",
|
||||
mCpuFreqDir.getAbsolutePath());
|
||||
return false;
|
||||
}
|
||||
populateCpuFreqPolicyDirsById(policyDirs);
|
||||
if (mCpuFreqPolicyDirsById.size() == 0) {
|
||||
Slogf.e(TAG, "Failed to parse CPU frequency policy directory paths: %s",
|
||||
Arrays.toString(policyDirs));
|
||||
return false;
|
||||
}
|
||||
readStaticPolicyInfo();
|
||||
if (mStaticPolicyInfoById.size() == 0) {
|
||||
Slogf.e(TAG, "Failed to read static CPU frequency policy info from policy dirs: %s",
|
||||
Arrays.toString(policyDirs));
|
||||
return false;
|
||||
}
|
||||
if (!mProcStatFile.exists()) {
|
||||
Slogf.e(TAG, "Missing proc stat file at %s", mProcStatFile.getAbsolutePath());
|
||||
return false;
|
||||
}
|
||||
readCpusetCategories();
|
||||
if (mCpusetCategoriesByCpus.size() == 0) {
|
||||
Slogf.e(TAG, "Failed to read cpuset information read from %s",
|
||||
mCpusetDir.getAbsolutePath());
|
||||
Slogf.e(TAG, "Failed to read cpuset information from %s", mCpusetDir.getAbsolutePath());
|
||||
return false;
|
||||
}
|
||||
readMaxCpuFrequencies();
|
||||
if (mMaxCpuFrequenciesByCpus.size() == 0) {
|
||||
Slogf.e(TAG, "Failed to read max CPU frequencies from policy directories at %s",
|
||||
mCpuFreqDir.getAbsolutePath());
|
||||
return false;
|
||||
// Certain CPU performance scaling drivers, such as intel_pstate, perform their own CPU
|
||||
// frequency transitions and do not supply this information to the Kernel's cpufreq node.
|
||||
// Thus, the `time_in_state` file won't be available on devices running such scaling
|
||||
// drivers. Check the presence of this file only once during init and do not throw error
|
||||
// when this file is missing. The implementation must accommodate such use cases.
|
||||
for (int i = 0; i < mCpuFreqPolicyDirsById.size() && !mHasTimeInStateFile; ++i) {
|
||||
// If all the CPU cores on a policy are offline, this file might be missing for the
|
||||
// policy. Make sure this file is not available on all policies before marking it as
|
||||
// missing.
|
||||
mHasTimeInStateFile |= new File(mCpuFreqPolicyDirsById.valueAt(i), TIME_IN_STATE_FILE)
|
||||
.exists();
|
||||
}
|
||||
if (!mHasTimeInStateFile) {
|
||||
Slogf.e(TAG, "Time in state file not available for any cpufreq policy");
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
/** Reads CPU information from proc and sys fs files exposed by the Kernel. */
|
||||
public List<CpuInfo> readCpuInfos() {
|
||||
/**
|
||||
* Reads CPU information from proc and sys fs files exposed by the Kernel.
|
||||
*
|
||||
* @return SparseArray keyed by CPU core ID; {@code null} on error or when disabled.
|
||||
*/
|
||||
@Nullable
|
||||
public SparseArray<CpuInfo> readCpuInfos() {
|
||||
if (!mIsEnabled) {
|
||||
return Collections.emptyList();
|
||||
return null;
|
||||
}
|
||||
SparseArray<CpuUsageStats> latestCpuUsageStats = readLatestCpuUsageStats();
|
||||
if (latestCpuUsageStats == null) {
|
||||
SparseArray<CpuUsageStats> cpuUsageStatsByCpus = readLatestCpuUsageStats();
|
||||
if (cpuUsageStatsByCpus == null || cpuUsageStatsByCpus.size() == 0) {
|
||||
Slogf.e(TAG, "Failed to read latest CPU usage stats");
|
||||
return Collections.emptyList();
|
||||
return null;
|
||||
}
|
||||
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);
|
||||
SparseArray<DynamicPolicyInfo> dynamicPolicyInfoById = readDynamicPolicyInfo();
|
||||
if (dynamicPolicyInfoById.size() == 0) {
|
||||
Slogf.e(TAG, "Failed to read dynamic policy infos");
|
||||
return null;
|
||||
}
|
||||
SparseArray<CpuInfo> cpuInfoByCpus = new SparseArray<>();
|
||||
for (int i = 0; i < mStaticPolicyInfoById.size(); i++) {
|
||||
int policyId = mStaticPolicyInfoById.keyAt(i);
|
||||
StaticPolicyInfo staticPolicyInfo = mStaticPolicyInfoById.valueAt(i);
|
||||
DynamicPolicyInfo dynamicPolicyInfo = dynamicPolicyInfoById.get(policyId);
|
||||
if (dynamicPolicyInfo == null) {
|
||||
Slogf.w(TAG, "Missing dynamic policy info for policy ID %d", policyId);
|
||||
continue;
|
||||
}
|
||||
int cpuCategories = mCpusetCategoriesByCpus.get(cpu, -1);
|
||||
if (cpuCategories < 0) {
|
||||
Slogf.w(TAG, "Missing cpuset information for CPU core %d", cpu);
|
||||
long curFreqKHz = CpuInfo.MISSING_FREQUENCY;
|
||||
long maxFreqKHz = CpuInfo.MISSING_FREQUENCY;
|
||||
if (dynamicPolicyInfo.curCpuFreqPair.cpuFreqKHz != CpuInfo.MISSING_FREQUENCY
|
||||
&& staticPolicyInfo.maxCpuFreqPair.cpuFreqKHz != CpuInfo.MISSING_FREQUENCY) {
|
||||
curFreqKHz = dynamicPolicyInfo.curCpuFreqPair.cpuFreqKHz;
|
||||
maxFreqKHz = staticPolicyInfo.maxCpuFreqPair.cpuFreqKHz;
|
||||
} else if (dynamicPolicyInfo.curCpuFreqPair.scalingFreqKHz != CpuInfo.MISSING_FREQUENCY
|
||||
&& staticPolicyInfo.maxCpuFreqPair.scalingFreqKHz
|
||||
!= CpuInfo.MISSING_FREQUENCY) {
|
||||
curFreqKHz = dynamicPolicyInfo.curCpuFreqPair.scalingFreqKHz;
|
||||
maxFreqKHz = staticPolicyInfo.maxCpuFreqPair.scalingFreqKHz;
|
||||
} else {
|
||||
Slogf.w(TAG, "Current and maximum CPU frequency information mismatch/missing for"
|
||||
+ " policy ID %d", policyId);
|
||||
continue;
|
||||
}
|
||||
cpuInfos.add(new CpuInfo(cpu, cpuCategories, curFrequency,
|
||||
mMaxCpuFrequenciesByCpus.get(cpu), latestCpuUsageStats.get(cpu)));
|
||||
for (int coreIdx = 0; coreIdx < staticPolicyInfo.relatedCpuCores.size(); coreIdx++) {
|
||||
int relatedCpuCore = staticPolicyInfo.relatedCpuCores.get(coreIdx);
|
||||
CpuInfo prevCpuInfo = cpuInfoByCpus.get(relatedCpuCore);
|
||||
if (prevCpuInfo != null) {
|
||||
Slogf.wtf(TAG, "CPU info already available for the CPU core %d",
|
||||
relatedCpuCore);
|
||||
if (prevCpuInfo.isOnline) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
int cpusetCategories = mCpusetCategoriesByCpus.get(relatedCpuCore, -1);
|
||||
if (cpusetCategories < 0) {
|
||||
Slogf.w(TAG, "Missing cpuset information for the CPU core %d",
|
||||
relatedCpuCore);
|
||||
continue;
|
||||
}
|
||||
CpuUsageStats usageStats = cpuUsageStatsByCpus.get(relatedCpuCore);
|
||||
if (dynamicPolicyInfo.affectedCpuCores.indexOf(relatedCpuCore) < 0) {
|
||||
cpuInfoByCpus.append(relatedCpuCore, new CpuInfo(relatedCpuCore,
|
||||
cpusetCategories, /* isOnline= */false, CpuInfo.MISSING_FREQUENCY,
|
||||
maxFreqKHz, CpuInfo.MISSING_FREQUENCY, usageStats));
|
||||
continue;
|
||||
}
|
||||
// If a CPU core is online, it must have the usage stats. When the usage stats is
|
||||
// missing, drop the core's CPU info.
|
||||
if (usageStats == null) {
|
||||
Slogf.w(TAG, "Missing CPU usage information for online CPU core %d",
|
||||
relatedCpuCore);
|
||||
continue;
|
||||
}
|
||||
CpuInfo cpuInfo = new CpuInfo(relatedCpuCore, cpusetCategories, /* isOnline= */true,
|
||||
curFreqKHz, maxFreqKHz, dynamicPolicyInfo.avgTimeInStateCpuFreqKHz,
|
||||
usageStats);
|
||||
cpuInfoByCpus.append(relatedCpuCore, cpuInfo);
|
||||
if (DEBUG) {
|
||||
Slogf.d(TAG, "Added %s for CPU core %d", cpuInfo, relatedCpuCore);
|
||||
}
|
||||
}
|
||||
}
|
||||
return cpuInfos;
|
||||
return cpuInfoByCpus;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the CPU frequency for testing.
|
||||
*
|
||||
* <p>Return {@code true} on success. Otherwise, returns {@code false}.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
void setCpuFreqDir(File cpuFreqDir) {
|
||||
boolean setCpuFreqDir(File cpuFreqDir) {
|
||||
File[] cpuFreqPolicyDirs = cpuFreqDir.listFiles(
|
||||
file -> file.isDirectory() && file.getName().startsWith(POLICY_DIR_PREFIX));
|
||||
if (mCpuFreqPolicyDirs == null || mCpuFreqPolicyDirs.length == 0) {
|
||||
if (cpuFreqPolicyDirs == null || cpuFreqPolicyDirs.length == 0) {
|
||||
Slogf.w(TAG, "Failed to set CPU frequency directory. Missing policy directories at %s",
|
||||
mCpuFreqDir.getAbsolutePath());
|
||||
return;
|
||||
cpuFreqDir.getAbsolutePath());
|
||||
return false;
|
||||
}
|
||||
populateCpuFreqPolicyDirsById(cpuFreqPolicyDirs);
|
||||
int numCpuFreqPolicyDirs = mCpuFreqPolicyDirsById.size();
|
||||
int numStaticPolicyInfos = mStaticPolicyInfoById.size();
|
||||
if (numCpuFreqPolicyDirs == 0 || numCpuFreqPolicyDirs != numStaticPolicyInfos) {
|
||||
Slogf.e(TAG, "Failed to set CPU frequency directory to %s. Total CPU frequency "
|
||||
+ "policies (%d) under new path is either 0 or not equal to initial "
|
||||
+ "total CPU frequency policies. Clearing CPU frequency policy "
|
||||
+ "directories", cpuFreqDir.getAbsolutePath(), numCpuFreqPolicyDirs,
|
||||
numStaticPolicyInfos);
|
||||
mCpuFreqPolicyDirsById.clear();
|
||||
return false;
|
||||
}
|
||||
mCpuFreqDir = cpuFreqDir;
|
||||
mCpuFreqPolicyDirs = cpuFreqPolicyDirs;
|
||||
Slogf.i(TAG, "Set CPU frequency directory to %s", cpuFreqDir.getAbsolutePath());
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the proc stat file for testing.
|
||||
*
|
||||
* <p>Return true on success. Otherwise, returns false.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
void setProcStatFile(File procStatFile) {
|
||||
boolean setProcStatFile(File procStatFile) {
|
||||
if (!procStatFile.exists()) {
|
||||
Slogf.e(TAG, "Missing proc stat file at %s", procStatFile.getAbsolutePath());
|
||||
return false;
|
||||
}
|
||||
mProcStatFile = procStatFile;
|
||||
Slogf.i(TAG, "Set proc stat file to %s", procStatFile.getAbsolutePath());
|
||||
return true;
|
||||
}
|
||||
|
||||
private void populateCpuFreqPolicyDirsById(File[] policyDirs) {
|
||||
mCpuFreqPolicyDirsById.clear();
|
||||
for (int i = 0; i < policyDirs.length; i++) {
|
||||
File policyDir = policyDirs[i];
|
||||
String policyIdStr = policyDir.getName().substring(POLICY_DIR_PREFIX.length());
|
||||
if (policyIdStr.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
mCpuFreqPolicyDirsById.append(Integer.parseInt(policyIdStr), policyDir);
|
||||
if (DEBUG) {
|
||||
Slogf.d(TAG, "Cached policy directory %s for policy id %s", policyDir, policyIdStr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void readCpusetCategories() {
|
||||
@@ -200,11 +321,13 @@ public final class CpuInfoReader {
|
||||
cpusetCategory = FLAG_CPUSET_CATEGORY_BACKGROUND;
|
||||
break;
|
||||
default:
|
||||
// Ignore other cpuset categories because the implementation doesn't support
|
||||
// monitoring CPU availability for other cpusets.
|
||||
continue;
|
||||
}
|
||||
File cpuCoresFile = new File(dir.getPath(), CPUS_FILE);
|
||||
List<Integer> cpuCores = readCpuCores(cpuCoresFile);
|
||||
if (cpuCores.isEmpty()) {
|
||||
IntArray cpuCores = readCpuCores(cpuCoresFile);
|
||||
if (cpuCores == null || cpuCores.size() == 0) {
|
||||
Slogf.e(TAG, "Failed to read CPU cores from %s", cpuCoresFile.getAbsolutePath());
|
||||
continue;
|
||||
}
|
||||
@@ -212,80 +335,104 @@ public final class CpuInfoReader {
|
||||
int categories = mCpusetCategoriesByCpus.get(cpuCores.get(j));
|
||||
categories |= cpusetCategory;
|
||||
mCpusetCategoriesByCpus.append(cpuCores.get(j), categories);
|
||||
if (DEBUG) {
|
||||
Slogf.d(TAG, "Mapping CPU core id %d with cpuset categories [%s]",
|
||||
cpuCores.get(j), toCpusetCategoriesStr(categories));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void readMaxCpuFrequencies() {
|
||||
for (int i = 0; i < mCpuFreqPolicyDirs.length; i++) {
|
||||
File policyDir = mCpuFreqPolicyDirs[i];
|
||||
long maxCpuFreqKHz = readMaxCpuFrequency(policyDir);
|
||||
if (maxCpuFreqKHz == 0) {
|
||||
Slogf.w(TAG, "Invalid max CPU frequency read from %s", policyDir.getAbsolutePath());
|
||||
private void readStaticPolicyInfo() {
|
||||
for (int i = 0; i < mCpuFreqPolicyDirsById.size(); i++) {
|
||||
int policyId = mCpuFreqPolicyDirsById.keyAt(i);
|
||||
File policyDir = mCpuFreqPolicyDirsById.valueAt(i);
|
||||
FrequencyPair maxCpuFreqPair = readMaxCpuFrequency(policyDir);
|
||||
if (maxCpuFreqPair.isEmpty()) {
|
||||
Slogf.w(TAG, "Missing max CPU frequency information at %s",
|
||||
policyDir.getAbsolutePath());
|
||||
continue;
|
||||
}
|
||||
File cpuCoresFile = new File(policyDir, RELATED_CPUS_FILE);
|
||||
List<Integer> cpuCores = readCpuCores(cpuCoresFile);
|
||||
if (cpuCores.isEmpty()) {
|
||||
Slogf.e(TAG, "Failed to read CPU cores from %s", cpuCoresFile.getAbsolutePath());
|
||||
IntArray relatedCpuCores = readCpuCores(cpuCoresFile);
|
||||
if (relatedCpuCores == null || relatedCpuCores.size() == 0) {
|
||||
Slogf.e(TAG, "Failed to read related CPU cores from %s",
|
||||
cpuCoresFile.getAbsolutePath());
|
||||
continue;
|
||||
}
|
||||
for (int j = 0; j < cpuCores.size(); j++) {
|
||||
mMaxCpuFrequenciesByCpus.append(cpuCores.get(j), maxCpuFreqKHz);
|
||||
StaticPolicyInfo staticPolicyInfo = new StaticPolicyInfo(maxCpuFreqPair,
|
||||
relatedCpuCores);
|
||||
mStaticPolicyInfoById.append(policyId, staticPolicyInfo);
|
||||
if (DEBUG) {
|
||||
Slogf.d(TAG, "Added static policy info %s for policy id %d", staticPolicyInfo,
|
||||
policyId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private long readMaxCpuFrequency(File policyDir) {
|
||||
long curCpuFreqKHz = readCpuFreqKHz(new File(policyDir, MAX_CPUFREQ_FILE));
|
||||
return curCpuFreqKHz > 0 ? curCpuFreqKHz
|
||||
: readCpuFreqKHz(new File(policyDir, MAX_SCALING_FREQ_FILE));
|
||||
private FrequencyPair readMaxCpuFrequency(File policyDir) {
|
||||
return new FrequencyPair(readCpuFreqKHz(new File(policyDir, MAX_CPUFREQ_FILE)),
|
||||
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) {
|
||||
private SparseArray<DynamicPolicyInfo> readDynamicPolicyInfo() {
|
||||
SparseArray<DynamicPolicyInfo> dynamicPolicyInfoById = new SparseArray<>();
|
||||
for (int i = 0; i < mCpuFreqPolicyDirsById.size(); i++) {
|
||||
int policyId = mCpuFreqPolicyDirsById.keyAt(i);
|
||||
File policyDir = mCpuFreqPolicyDirsById.valueAt(i);
|
||||
FrequencyPair curCpuFreqPair = readCurrentCpuFrequency(policyDir);
|
||||
if (curCpuFreqPair.isEmpty()) {
|
||||
Slogf.w(TAG, "Missing current frequency information at %s",
|
||||
policyDir.getAbsolutePath());
|
||||
continue;
|
||||
}
|
||||
long avgTimeInStateCpuFreqKHz = readAvgTimeInStateCpuFrequency(policyId, policyDir);
|
||||
File cpuCoresFile = new File(policyDir, AFFECTED_CPUS_FILE);
|
||||
List<Integer> cpuCores = readCpuCores(cpuCoresFile);
|
||||
if (cpuCores.isEmpty()) {
|
||||
IntArray affectedCpuCores = readCpuCores(cpuCoresFile);
|
||||
if (affectedCpuCores == null || affectedCpuCores.size() == 0) {
|
||||
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);
|
||||
DynamicPolicyInfo dynamicPolicyInfo = new DynamicPolicyInfo(curCpuFreqPair,
|
||||
avgTimeInStateCpuFreqKHz, affectedCpuCores);
|
||||
dynamicPolicyInfoById.append(policyId, dynamicPolicyInfo);
|
||||
if (DEBUG) {
|
||||
Slogf.d(TAG, "Read dynamic policy info %s for policy id %d", dynamicPolicyInfo,
|
||||
policyId);
|
||||
}
|
||||
}
|
||||
return curCpuFrequenciesByCpus;
|
||||
return dynamicPolicyInfoById;
|
||||
}
|
||||
|
||||
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));
|
||||
private FrequencyPair readCurrentCpuFrequency(File policyDir) {
|
||||
return new FrequencyPair(readCpuFreqKHz(new File(policyDir, CUR_CPUFREQ_FILE)),
|
||||
readCpuFreqKHz(new File(policyDir, CUR_SCALING_FREQ_FILE)));
|
||||
}
|
||||
|
||||
private long readAvgTimeInStateCpuFrequency(int policyId, File policyDir) {
|
||||
LongSparseLongArray latestTimeInState = readTimeInState(policyDir);
|
||||
if (latestTimeInState == null || latestTimeInState.size() == 0) {
|
||||
return CpuInfo.MISSING_FREQUENCY;
|
||||
}
|
||||
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);
|
||||
LongSparseLongArray prevTimeInState = mTimeInStateByPolicyId.get(policyId);
|
||||
if (prevTimeInState == null) {
|
||||
mTimeInStateByPolicyId.put(policyId, latestTimeInState);
|
||||
if (DEBUG) {
|
||||
Slogf.d(TAG, "Added aggregated time in state info for policy id %d", policyId);
|
||||
}
|
||||
return calculateAvgCpuFreq(latestTimeInState);
|
||||
}
|
||||
mTimeInStateByPolicy.put(policyDirName, latestTimeInState);
|
||||
return calculateAvgCpuFreq(latestTimeInState);
|
||||
LongSparseLongArray deltaTimeInState = calculateDeltaTimeInState(prevTimeInState,
|
||||
latestTimeInState);
|
||||
mTimeInStateByPolicyId.put(policyId, latestTimeInState);
|
||||
if (DEBUG) {
|
||||
Slogf.d(TAG, "Added latest delta time in state info for policy id %d", policyId);
|
||||
}
|
||||
return calculateAvgCpuFreq(deltaTimeInState);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private ArrayMap<Long, Long> readTimeInState(File policyDir) {
|
||||
private LongSparseLongArray readTimeInState(File policyDir) {
|
||||
if (!mHasTimeInStateFile) {
|
||||
return null;
|
||||
}
|
||||
@@ -296,14 +443,14 @@ public final class CpuInfoReader {
|
||||
Slogf.w(TAG, "Empty time in state file at %s", timeInStateFile.getAbsolutePath());
|
||||
return null;
|
||||
}
|
||||
ArrayMap<Long, Long> cpuTimeByFrequencies = new ArrayMap<>();
|
||||
LongSparseLongArray cpuTimeByFrequencies = new LongSparseLongArray();
|
||||
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")));
|
||||
clockTickStrToMillis(m.group("time")));
|
||||
}
|
||||
return cpuTimeByFrequencies;
|
||||
} catch (Exception e) {
|
||||
@@ -316,40 +463,35 @@ public final class CpuInfoReader {
|
||||
private static long readCpuFreqKHz(File file) {
|
||||
if (!file.exists()) {
|
||||
Slogf.e(TAG, "CPU frequency file %s doesn't exist", file.getAbsolutePath());
|
||||
return 0;
|
||||
return CpuInfo.MISSING_FREQUENCY;
|
||||
}
|
||||
try {
|
||||
List<String> lines = Files.readAllLines(file.toPath());
|
||||
if (!lines.isEmpty()) {
|
||||
long frequency = Long.parseLong(lines.get(0).trim());
|
||||
return frequency > 0 ? frequency : 0;
|
||||
return frequency > 0 ? frequency : CpuInfo.MISSING_FREQUENCY;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Slogf.e(TAG, e, "Failed to read integer content from file: %s", file.getAbsolutePath());
|
||||
}
|
||||
return 0;
|
||||
return CpuInfo.MISSING_FREQUENCY;
|
||||
}
|
||||
|
||||
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++) {
|
||||
private static LongSparseLongArray calculateDeltaTimeInState(
|
||||
LongSparseLongArray prevTimeInState, LongSparseLongArray latestTimeInState) {
|
||||
int numTimeInStateEntries = latestTimeInState.size();
|
||||
LongSparseLongArray deltaTimeInState = new LongSparseLongArray(numTimeInStateEntries);
|
||||
for (int i = 0; i < numTimeInStateEntries; 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);
|
||||
long prevDurationMillis = prevTimeInState.get(freq);
|
||||
deltaTimeInState.put(freq, durationMillis > prevDurationMillis
|
||||
? (durationMillis - prevDurationMillis) : durationMillis);
|
||||
}
|
||||
return deltaTimeInState;
|
||||
}
|
||||
|
||||
private static long calculateAvgCpuFreq(ArrayMap<Long, Long> timeInState) {
|
||||
private static long calculateAvgCpuFreq(LongSparseLongArray timeInState) {
|
||||
double totalTimeInState = 0;
|
||||
for (int i = 0; i < timeInState.size(); i++) {
|
||||
totalTimeInState += timeInState.valueAt(i);
|
||||
@@ -364,24 +506,27 @@ public final class CpuInfoReader {
|
||||
/**
|
||||
* Reads the list of CPU cores from the given file.
|
||||
*
|
||||
* Reads CPU cores represented in one of the below formats.
|
||||
* <p>Reads CPU cores represented in one of the below formats.
|
||||
* <ul>
|
||||
* <li> Single core id. Eg: 1
|
||||
* <li> Core id range. Eg: 1-4
|
||||
* <li> Comma separated values. Eg: 1, 3-5, 7
|
||||
* </ul>
|
||||
*/
|
||||
private static List<Integer> readCpuCores(File file) {
|
||||
@Nullable
|
||||
private static IntArray readCpuCores(File file) {
|
||||
if (!file.exists()) {
|
||||
Slogf.e(TAG, "Failed to read CPU cores as the file '%s' doesn't exist",
|
||||
file.getAbsolutePath());
|
||||
return Collections.emptyList();
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
List<String> lines = Files.readAllLines(file.toPath());
|
||||
List<Integer> cpuCores = new ArrayList<>();
|
||||
IntArray cpuCores = new IntArray(0);
|
||||
for (int i = 0; i < lines.size(); i++) {
|
||||
String[] pairs = lines.get(i).trim().split(",");
|
||||
String line = lines.get(i);
|
||||
String[] pairs = line.contains(",") ? line.trim().split(",")
|
||||
: line.trim().split(" ");
|
||||
for (int j = 0; j < pairs.length; j++) {
|
||||
String[] minMaxPairs = pairs[j].split("-");
|
||||
if (minMaxPairs.length >= 2) {
|
||||
@@ -404,7 +549,7 @@ public final class CpuInfoReader {
|
||||
} catch (Exception e) {
|
||||
Slogf.e(TAG, e, "Failed to read CPU cores from %s", file.getAbsolutePath());
|
||||
}
|
||||
return Collections.emptyList();
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -435,16 +580,16 @@ public final class CpuInfoReader {
|
||||
continue;
|
||||
}
|
||||
cpuUsageStats.append(Integer.parseInt(m.group("core")),
|
||||
new CpuUsageStats(jiffyStrToMillis(m.group("userClockTicks")),
|
||||
jiffyStrToMillis(m.group("niceClockTicks")),
|
||||
jiffyStrToMillis(m.group("sysClockTicks")),
|
||||
jiffyStrToMillis(m.group("idleClockTicks")),
|
||||
jiffyStrToMillis(m.group("iowaitClockTicks")),
|
||||
jiffyStrToMillis(m.group("irqClockTicks")),
|
||||
jiffyStrToMillis(m.group("softirqClockTicks")),
|
||||
jiffyStrToMillis(m.group("stealClockTicks")),
|
||||
jiffyStrToMillis(m.group("guestClockTicks")),
|
||||
jiffyStrToMillis(m.group("guestNiceClockTicks"))));
|
||||
new CpuUsageStats(clockTickStrToMillis(m.group("userClockTicks")),
|
||||
clockTickStrToMillis(m.group("niceClockTicks")),
|
||||
clockTickStrToMillis(m.group("sysClockTicks")),
|
||||
clockTickStrToMillis(m.group("idleClockTicks")),
|
||||
clockTickStrToMillis(m.group("iowaitClockTicks")),
|
||||
clockTickStrToMillis(m.group("irqClockTicks")),
|
||||
clockTickStrToMillis(m.group("softirqClockTicks")),
|
||||
clockTickStrToMillis(m.group("stealClockTicks")),
|
||||
clockTickStrToMillis(m.group("guestClockTicks")),
|
||||
clockTickStrToMillis(m.group("guestNiceClockTicks"))));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Slogf.e(TAG, e, "Failed to read cpu usage stats from %s",
|
||||
@@ -453,33 +598,64 @@ public final class CpuInfoReader {
|
||||
return cpuUsageStats;
|
||||
}
|
||||
|
||||
private static long jiffyStrToMillis(String jiffyStr) {
|
||||
return Long.parseLong(jiffyStr) * MILLIS_PER_JIFFY;
|
||||
private static long clockTickStrToMillis(String jiffyStr) {
|
||||
return Long.parseLong(jiffyStr) * MILLIS_PER_CLOCK_TICK;
|
||||
}
|
||||
|
||||
private static String toCpusetCategoriesStr(int cpusetCategories) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
if ((cpusetCategories & FLAG_CPUSET_CATEGORY_TOP_APP) != 0) {
|
||||
builder.append("FLAG_CPUSET_CATEGORY_TOP_APP");
|
||||
}
|
||||
if ((cpusetCategories & FLAG_CPUSET_CATEGORY_BACKGROUND) != 0) {
|
||||
if (builder.length() > 0) {
|
||||
builder.append('|');
|
||||
}
|
||||
builder.append("FLAG_CPUSET_CATEGORY_BACKGROUND");
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
/** Contains information for each CPU core on the system. */
|
||||
public static final class CpuInfo {
|
||||
public static final long MISSING_FREQUENCY = 0;
|
||||
|
||||
public final int cpuCore;
|
||||
public final @CpusetCategory int cpusetCategories;
|
||||
@CpusetCategory
|
||||
public final int cpusetCategories;
|
||||
public final boolean isOnline;
|
||||
// Values in the below fields may be missing when a CPU core is offline.
|
||||
public final long curCpuFreqKHz;
|
||||
public final long maxCpuFreqKHz;
|
||||
public final long avgTimeInStateCpuFreqKHz;
|
||||
@Nullable
|
||||
public final CpuUsageStats latestCpuUsageStats;
|
||||
|
||||
CpuInfo(int cpuCore, @CpusetCategory int cpusetCategories, long curCpuFreqKHz,
|
||||
long maxCpuFreqKHz, CpuUsageStats latestCpuUsageStats) {
|
||||
CpuInfo(int cpuCore, @CpusetCategory int cpusetCategories, boolean isOnline,
|
||||
long curCpuFreqKHz, long maxCpuFreqKHz, long avgTimeInStateCpuFreqKHz,
|
||||
CpuUsageStats latestCpuUsageStats) {
|
||||
this.cpuCore = cpuCore;
|
||||
this.cpusetCategories = cpusetCategories;
|
||||
this.isOnline = isOnline;
|
||||
this.curCpuFreqKHz = curCpuFreqKHz;
|
||||
this.maxCpuFreqKHz = maxCpuFreqKHz;
|
||||
this.avgTimeInStateCpuFreqKHz = avgTimeInStateCpuFreqKHz;
|
||||
this.latestCpuUsageStats = latestCpuUsageStats;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new StringBuilder("CpuInfo{ cpuCore = ").append(cpuCore)
|
||||
.append(", cpusetCategories = ").append(cpusetCategories)
|
||||
.append(", curCpuFreqKHz = ").append(curCpuFreqKHz)
|
||||
.append(", maxCpuFreqKHz = ").append(maxCpuFreqKHz)
|
||||
.append(", cpusetCategories = [")
|
||||
.append(toCpusetCategoriesStr(cpusetCategories))
|
||||
.append("], isOnline = ").append(isOnline ? "Yes" : "No")
|
||||
.append(", curCpuFreqKHz = ")
|
||||
.append(curCpuFreqKHz == MISSING_FREQUENCY ? "missing" : curCpuFreqKHz)
|
||||
.append(", maxCpuFreqKHz = ")
|
||||
.append(maxCpuFreqKHz == MISSING_FREQUENCY ? "missing" : maxCpuFreqKHz)
|
||||
.append(", avgTimeInStateCpuFreqKHz = ")
|
||||
.append(avgTimeInStateCpuFreqKHz == MISSING_FREQUENCY ? "missing"
|
||||
: avgTimeInStateCpuFreqKHz)
|
||||
.append(", latestCpuUsageStats = ").append(latestCpuUsageStats)
|
||||
.append(" }").toString();
|
||||
}
|
||||
@@ -494,15 +670,16 @@ public final class CpuInfoReader {
|
||||
}
|
||||
CpuInfo other = (CpuInfo) obj;
|
||||
return cpuCore == other.cpuCore && cpusetCategories == other.cpusetCategories
|
||||
&& curCpuFreqKHz == other.curCpuFreqKHz
|
||||
&& isOnline == other.isOnline && curCpuFreqKHz == other.curCpuFreqKHz
|
||||
&& maxCpuFreqKHz == other.maxCpuFreqKHz
|
||||
&& avgTimeInStateCpuFreqKHz == other.avgTimeInStateCpuFreqKHz
|
||||
&& latestCpuUsageStats.equals(other.latestCpuUsageStats);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(cpuCore, cpusetCategories, curCpuFreqKHz, maxCpuFreqKHz,
|
||||
latestCpuUsageStats);
|
||||
return Objects.hash(cpuCore, cpusetCategories, isOnline, curCpuFreqKHz, maxCpuFreqKHz,
|
||||
avgTimeInStateCpuFreqKHz, latestCpuUsageStats);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -602,4 +779,61 @@ public final class CpuInfoReader {
|
||||
return lhs > rhs ? lhs - rhs : 0;
|
||||
}
|
||||
}
|
||||
|
||||
private static final class FrequencyPair {
|
||||
public final long cpuFreqKHz;
|
||||
public final long scalingFreqKHz;
|
||||
|
||||
FrequencyPair(long cpuFreqKHz, long scalingFreqKHz) {
|
||||
this.cpuFreqKHz = cpuFreqKHz;
|
||||
this.scalingFreqKHz = scalingFreqKHz;
|
||||
}
|
||||
|
||||
boolean isEmpty() {
|
||||
return cpuFreqKHz == CpuInfo.MISSING_FREQUENCY
|
||||
&& scalingFreqKHz == CpuInfo.MISSING_FREQUENCY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "FrequencyPair{cpuFreqKHz=" + cpuFreqKHz + ", scalingFreqKHz=" + scalingFreqKHz
|
||||
+ '}';
|
||||
}
|
||||
}
|
||||
|
||||
private static final class StaticPolicyInfo {
|
||||
public final FrequencyPair maxCpuFreqPair;
|
||||
public final IntArray relatedCpuCores;
|
||||
|
||||
StaticPolicyInfo(FrequencyPair maxCpuFreqPair, IntArray relatedCpuCores) {
|
||||
this.maxCpuFreqPair = maxCpuFreqPair;
|
||||
this.relatedCpuCores = relatedCpuCores;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "StaticPolicyInfo{maxCpuFreqPair=" + maxCpuFreqPair + ", relatedCpuCores="
|
||||
+ relatedCpuCores + '}';
|
||||
}
|
||||
}
|
||||
|
||||
private static final class DynamicPolicyInfo {
|
||||
public final FrequencyPair curCpuFreqPair;
|
||||
public final long avgTimeInStateCpuFreqKHz;
|
||||
public final IntArray affectedCpuCores;
|
||||
|
||||
DynamicPolicyInfo(FrequencyPair curCpuFreqPair, long avgTimeInStateCpuFreqKHz,
|
||||
IntArray affectedCpuCores) {
|
||||
this.curCpuFreqPair = curCpuFreqPair;
|
||||
this.avgTimeInStateCpuFreqKHz = avgTimeInStateCpuFreqKHz;
|
||||
this.affectedCpuCores = affectedCpuCores;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "DynamicPolicyInfo{curCpuFreqPair=" + curCpuFreqPair
|
||||
+ ", avgTimeInStateCpuFreqKHz=" + avgTimeInStateCpuFreqKHz
|
||||
+ ", affectedCpuCores=" + affectedCpuCores + '}';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
2,3
|
||||
2
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
|
||||
package com.android.server.cpu;
|
||||
|
||||
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
|
||||
|
||||
import static com.android.server.cpu.CpuInfoReader.CpuInfo.MISSING_FREQUENCY;
|
||||
import static com.android.server.cpu.CpuInfoReader.FLAG_CPUSET_CATEGORY_BACKGROUND;
|
||||
import static com.android.server.cpu.CpuInfoReader.FLAG_CPUSET_CATEGORY_TOP_APP;
|
||||
|
||||
@@ -23,9 +26,8 @@ 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 android.util.Log;
|
||||
import android.util.SparseArray;
|
||||
|
||||
import com.android.server.ExtendedMockitoTestCase;
|
||||
|
||||
@@ -34,20 +36,14 @@ 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)
|
||||
/** This class contains unit tests for the {@link CpuInfoReader}. */
|
||||
public final class CpuInfoReaderTest extends ExtendedMockitoTestCase {
|
||||
private static final String TAG = CpuInfoReaderTest.class.getSimpleName();
|
||||
private static final String ROOT_DIR_NAME = "CpuInfoReaderTest";
|
||||
@@ -68,334 +64,354 @@ public final class CpuInfoReaderTest extends ExtendedMockitoTestCase {
|
||||
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 Context mContext = 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())
|
||||
assertWithMessage("Cache root dir %s exists", 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());
|
||||
Log.e(TAG, "Failed to delete cache root directory " + mCacheRoot.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadCpuInfoWithTimeInState() throws Exception {
|
||||
mCpuInfoReader = new CpuInfoReader(getCacheFile(VALID_CPUSET_DIR),
|
||||
CpuInfoReader cpuInfoReader = newCpuInfoReader(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);
|
||||
SparseArray<CpuInfoReader.CpuInfo> actualCpuInfos = cpuInfoReader.readCpuInfos();
|
||||
SparseArray<CpuInfoReader.CpuInfo> expectedCpuInfos = new SparseArray<>();
|
||||
expectedCpuInfos.append(0, new CpuInfoReader.CpuInfo(/* cpuCore= */ 0,
|
||||
FLAG_CPUSET_CATEGORY_TOP_APP, /* isOnline= */ true, /* curCpuFreqKHz= */ 1_230_000,
|
||||
/* maxCpuFreqKHz= */ 2_500_000, /* avgTimeInStateCpuFreqKHz= */ 488_095,
|
||||
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)));
|
||||
expectedCpuInfos.append(1, new CpuInfoReader.CpuInfo(/* cpuCore= */ 1,
|
||||
FLAG_CPUSET_CATEGORY_TOP_APP, /* isOnline= */ true, /* curCpuFreqKHz= */ 1_450_000,
|
||||
/* maxCpuFreqKHz= */ 2_800_000, /* avgTimeInStateCpuFreqKHz= */ 502_380,
|
||||
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)));
|
||||
expectedCpuInfos.append(2, new CpuInfoReader.CpuInfo(/* cpuCore= */ 2,
|
||||
FLAG_CPUSET_CATEGORY_TOP_APP | FLAG_CPUSET_CATEGORY_BACKGROUND,
|
||||
/* isOnline= */ true, /* curCpuFreqKHz= */ 1_000_000,
|
||||
/* maxCpuFreqKHz= */ 2_000_000, /* avgTimeInStateCpuFreqKHz= */ 464_285,
|
||||
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)));
|
||||
expectedCpuInfos.append(3, new CpuInfoReader.CpuInfo(/* cpuCore= */ 3,
|
||||
FLAG_CPUSET_CATEGORY_TOP_APP | FLAG_CPUSET_CATEGORY_BACKGROUND,
|
||||
/* isOnline= */ true, /* curCpuFreqKHz= */ 1_000_000,
|
||||
/* maxCpuFreqKHz= */ 2_000_000, /* avgTimeInStateCpuFreqKHz= */ 464_285,
|
||||
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)));
|
||||
|
||||
mCpuInfoReader.setCpuFreqDir(getCacheFile(VALID_CPUFREQ_WITH_TIME_IN_STATE_2_DIR));
|
||||
mCpuInfoReader.setProcStatFile(getCacheFile(VALID_PROC_STAT_2));
|
||||
compareCpuInfos("CPU infos first snapshot", expectedCpuInfos, actualCpuInfos);
|
||||
|
||||
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)));
|
||||
cpuInfoReader.setCpuFreqDir(getCacheFile(VALID_CPUFREQ_WITH_TIME_IN_STATE_2_DIR));
|
||||
cpuInfoReader.setProcStatFile(getCacheFile(VALID_PROC_STAT_2));
|
||||
|
||||
assertWithMessage("Second snapshot of cpu infos").that(actualCpuInfos)
|
||||
.containsExactlyElementsIn(expectedCpuInfos);
|
||||
actualCpuInfos = cpuInfoReader.readCpuInfos();
|
||||
|
||||
expectedCpuInfos.clear();
|
||||
expectedCpuInfos.append(0, new CpuInfoReader.CpuInfo(/* cpuCore= */ 0,
|
||||
FLAG_CPUSET_CATEGORY_TOP_APP, /* isOnline= */ true, /* curCpuFreqKHz= */ 1_000_000,
|
||||
/* maxCpuFreqKHz= */ 2_500_000, /* avgTimeInStateCpuFreqKHz= */ 419_354,
|
||||
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)));
|
||||
expectedCpuInfos.append(1, new CpuInfoReader.CpuInfo(/* cpuCore= */ 1,
|
||||
FLAG_CPUSET_CATEGORY_TOP_APP, /* isOnline= */ true, /* curCpuFreqKHz= */ 2_800_000,
|
||||
/* maxCpuFreqKHz= */ 2_800_000, /* avgTimeInStateCpuFreqKHz= */ 429_032,
|
||||
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)));
|
||||
expectedCpuInfos.append(2, new CpuInfoReader.CpuInfo(/* cpuCore= */ 2,
|
||||
FLAG_CPUSET_CATEGORY_TOP_APP | FLAG_CPUSET_CATEGORY_BACKGROUND,
|
||||
/* isOnline= */ true, /* curCpuFreqKHz= */ 2_000_000,
|
||||
/* maxCpuFreqKHz= */ 2_000_000, /* avgTimeInStateCpuFreqKHz= */ 403_225,
|
||||
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)));
|
||||
expectedCpuInfos.append(3, new CpuInfoReader.CpuInfo(/* cpuCore= */ 3,
|
||||
FLAG_CPUSET_CATEGORY_TOP_APP | FLAG_CPUSET_CATEGORY_BACKGROUND,
|
||||
/* isOnline= */ false, /* curCpuFreqKHz= */ MISSING_FREQUENCY,
|
||||
/* maxCpuFreqKHz= */ 2_000_000, /* avgTimeInStateCpuFreqKHz= */ MISSING_FREQUENCY,
|
||||
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)));
|
||||
|
||||
compareCpuInfos("CPU infos second snapshot", expectedCpuInfos, actualCpuInfos);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadCpuInfoWithoutTimeInState() throws Exception {
|
||||
mCpuInfoReader = new CpuInfoReader(getCacheFile(VALID_CPUSET_DIR),
|
||||
CpuInfoReader cpuInfoReader = newCpuInfoReader(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);
|
||||
SparseArray<CpuInfoReader.CpuInfo> actualCpuInfos = cpuInfoReader.readCpuInfos();
|
||||
SparseArray<CpuInfoReader.CpuInfo> expectedCpuInfos = new SparseArray<>();
|
||||
expectedCpuInfos.append(0, new CpuInfoReader.CpuInfo(/* cpuCore= */ 0,
|
||||
FLAG_CPUSET_CATEGORY_TOP_APP, /* isOnline= */ true, /* curCpuFreqKHz= */ 1_230_000,
|
||||
/* maxCpuFreqKHz= */ 2_500_000, /* avgTimeInStateCpuFreqKHz= */ MISSING_FREQUENCY,
|
||||
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)));
|
||||
expectedCpuInfos.append(1, new CpuInfoReader.CpuInfo(/* cpuCore= */ 1,
|
||||
FLAG_CPUSET_CATEGORY_TOP_APP, /* isOnline= */ true, /* curCpuFreqKHz= */ 1_450_000,
|
||||
/* maxCpuFreqKHz= */ 2_800_000, /* avgTimeInStateCpuFreqKHz= */ MISSING_FREQUENCY,
|
||||
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)));
|
||||
expectedCpuInfos.append(2, new CpuInfoReader.CpuInfo(/* cpuCore= */ 2,
|
||||
FLAG_CPUSET_CATEGORY_TOP_APP | FLAG_CPUSET_CATEGORY_BACKGROUND,
|
||||
/* isOnline= */ true, /* curCpuFreqKHz= */ 1_000_000,
|
||||
/* maxCpuFreqKHz= */ 2_000_000, /* avgTimeInStateCpuFreqKHz= */ MISSING_FREQUENCY,
|
||||
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)));
|
||||
expectedCpuInfos.append(3, new CpuInfoReader.CpuInfo(/* cpuCore= */ 3,
|
||||
FLAG_CPUSET_CATEGORY_TOP_APP | FLAG_CPUSET_CATEGORY_BACKGROUND,
|
||||
/* isOnline= */ true, /* curCpuFreqKHz= */ 1_000_000,
|
||||
/* maxCpuFreqKHz= */ 2_000_000, /* avgTimeInStateCpuFreqKHz= */ MISSING_FREQUENCY,
|
||||
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)));
|
||||
|
||||
mCpuInfoReader.setCpuFreqDir(getCacheFile(VALID_CPUFREQ_WITHOUT_TIME_IN_STATE_2_DIR));
|
||||
mCpuInfoReader.setProcStatFile(getCacheFile(VALID_PROC_STAT_2));
|
||||
compareCpuInfos("CPU infos first snapshot without time_in_state file", expectedCpuInfos,
|
||||
actualCpuInfos);
|
||||
|
||||
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)));
|
||||
cpuInfoReader.setCpuFreqDir(getCacheFile(VALID_CPUFREQ_WITHOUT_TIME_IN_STATE_2_DIR));
|
||||
cpuInfoReader.setProcStatFile(getCacheFile(VALID_PROC_STAT_2));
|
||||
|
||||
assertWithMessage("Second snapshot of cpu infos").that(actualCpuInfos)
|
||||
.containsExactlyElementsIn(expectedCpuInfos);
|
||||
actualCpuInfos = cpuInfoReader.readCpuInfos();
|
||||
|
||||
expectedCpuInfos.clear();
|
||||
expectedCpuInfos.append(0, new CpuInfoReader.CpuInfo(/* cpuCore= */ 0,
|
||||
FLAG_CPUSET_CATEGORY_TOP_APP, /* isOnline= */ true, /* curCpuFreqKHz= */ 1_000_000,
|
||||
/* maxCpuFreqKHz= */ 2_500_000, /* avgTimeInStateCpuFreqKHz= */ MISSING_FREQUENCY,
|
||||
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)));
|
||||
expectedCpuInfos.append(1, new CpuInfoReader.CpuInfo(/* cpuCore= */ 1,
|
||||
FLAG_CPUSET_CATEGORY_TOP_APP, /* isOnline= */ true, /* curCpuFreqKHz= */ 2_800_000,
|
||||
/* maxCpuFreqKHz= */ 2_800_000, /* avgTimeInStateCpuFreqKHz= */ MISSING_FREQUENCY,
|
||||
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)));
|
||||
expectedCpuInfos.append(2, new CpuInfoReader.CpuInfo(/* cpuCore= */ 2,
|
||||
FLAG_CPUSET_CATEGORY_TOP_APP | FLAG_CPUSET_CATEGORY_BACKGROUND,
|
||||
/* isOnline= */ true, /* curCpuFreqKHz= */ 2_000_000,
|
||||
/* maxCpuFreqKHz= */ 2_000_000, /* avgTimeInStateCpuFreqKHz= */ MISSING_FREQUENCY,
|
||||
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)));
|
||||
expectedCpuInfos.append(3, new CpuInfoReader.CpuInfo(/* cpuCore= */ 3,
|
||||
FLAG_CPUSET_CATEGORY_TOP_APP | FLAG_CPUSET_CATEGORY_BACKGROUND,
|
||||
/* isOnline= */ true, /* curCpuFreqKHz= */ 2_000_000,
|
||||
/* maxCpuFreqKHz= */ 2_000_000, /* avgTimeInStateCpuFreqKHz= */ MISSING_FREQUENCY,
|
||||
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)));
|
||||
|
||||
compareCpuInfos("CPU infos second snapshot without time_in_state file", expectedCpuInfos,
|
||||
actualCpuInfos);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadCpuInfoWithCorruptedCpuset() throws Exception {
|
||||
mCpuInfoReader = new CpuInfoReader(getCacheFile(CORRUPTED_CPUSET_DIR),
|
||||
CpuInfoReader cpuInfoReader = newCpuInfoReader(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);
|
||||
SparseArray<CpuInfoReader.CpuInfo> actualCpuInfos = cpuInfoReader.readCpuInfos();
|
||||
SparseArray<CpuInfoReader.CpuInfo> expectedCpuInfos = new SparseArray<>();
|
||||
expectedCpuInfos.append(0, new CpuInfoReader.CpuInfo(/* cpuCore= */ 0,
|
||||
FLAG_CPUSET_CATEGORY_TOP_APP, /* isOnline= */ true, /* curCpuFreqKHz= */ 1_230_000,
|
||||
/* maxCpuFreqKHz= */ 2_500_000, /* avgTimeInStateCpuFreqKHz= */ 488_095,
|
||||
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)));
|
||||
expectedCpuInfos.append(1, new CpuInfoReader.CpuInfo(/* cpuCore= */ 1,
|
||||
FLAG_CPUSET_CATEGORY_TOP_APP, /* isOnline= */ true, /* curCpuFreqKHz= */ 1_450_000,
|
||||
/* maxCpuFreqKHz= */ 2_800_000, /* avgTimeInStateCpuFreqKHz= */ 502_380,
|
||||
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)));
|
||||
expectedCpuInfos.append(2, new CpuInfoReader.CpuInfo(/* cpuCore= */ 2,
|
||||
FLAG_CPUSET_CATEGORY_TOP_APP, /* isOnline= */ true, /* curCpuFreqKHz= */ 1_000_000,
|
||||
/* maxCpuFreqKHz= */ 2_000_000, /* avgTimeInStateCpuFreqKHz= */ 464_285,
|
||||
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)));
|
||||
|
||||
compareCpuInfos("CPU infos with corrupted cpuset", expectedCpuInfos, actualCpuInfos);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadCpuInfoWithCorruptedCpufreq() throws Exception {
|
||||
mCpuInfoReader = new CpuInfoReader(getCacheFile(VALID_CPUSET_DIR),
|
||||
CpuInfoReader cpuInfoReader = newCpuInfoReader(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);
|
||||
SparseArray<CpuInfoReader.CpuInfo> actualCpuInfos = cpuInfoReader.readCpuInfos();
|
||||
SparseArray<CpuInfoReader.CpuInfo> expectedCpuInfos = new SparseArray<>();
|
||||
expectedCpuInfos.append(1, new CpuInfoReader.CpuInfo(/* cpuCore= */ 1,
|
||||
FLAG_CPUSET_CATEGORY_TOP_APP, /* isOnline= */ true, /* curCpuFreqKHz= */ 3_000_000,
|
||||
/* maxCpuFreqKHz= */ 1_000_000, /* avgTimeInStateCpuFreqKHz= */ MISSING_FREQUENCY,
|
||||
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)));
|
||||
expectedCpuInfos.append(2, new CpuInfoReader.CpuInfo(/* cpuCore= */ 2,
|
||||
FLAG_CPUSET_CATEGORY_TOP_APP | FLAG_CPUSET_CATEGORY_BACKGROUND,
|
||||
/* isOnline= */ true, /* curCpuFreqKHz= */ 9, /* maxCpuFreqKHz= */ 2,
|
||||
/* avgTimeInStateCpuFreqKHz= */ MISSING_FREQUENCY,
|
||||
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)));
|
||||
expectedCpuInfos.append(3, new CpuInfoReader.CpuInfo(/* cpuCore= */ 3,
|
||||
FLAG_CPUSET_CATEGORY_TOP_APP | FLAG_CPUSET_CATEGORY_BACKGROUND,
|
||||
/* isOnline= */ true, /* curCpuFreqKHz= */ 9, /* maxCpuFreqKHz= */ 2,
|
||||
/* avgTimeInStateCpuFreqKHz= */ MISSING_FREQUENCY,
|
||||
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)));
|
||||
|
||||
compareCpuInfos("CPU infos with corrupted CPU frequency", expectedCpuInfos,
|
||||
actualCpuInfos);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadCpuInfoCorruptedProcStat() throws Exception {
|
||||
mCpuInfoReader = new CpuInfoReader(getCacheFile(VALID_CPUSET_DIR),
|
||||
public void testReadCpuInfoWithCorruptedProcStat() throws Exception {
|
||||
CpuInfoReader cpuInfoReader = newCpuInfoReader(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);
|
||||
SparseArray<CpuInfoReader.CpuInfo> actualCpuInfos = cpuInfoReader.readCpuInfos();
|
||||
SparseArray<CpuInfoReader.CpuInfo> expectedCpuInfos = new SparseArray<>();
|
||||
expectedCpuInfos.append(0, new CpuInfoReader.CpuInfo(/* cpuCore= */ 0,
|
||||
FLAG_CPUSET_CATEGORY_TOP_APP, /* isOnline= */ true, /* curCpuFreqKHz= */ 1_230_000,
|
||||
/* maxCpuFreqKHz= */ 2_500_000, /* avgTimeInStateCpuFreqKHz= */ 488_095,
|
||||
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)));
|
||||
expectedCpuInfos.append(1, new CpuInfoReader.CpuInfo(/* cpuCore= */ 1,
|
||||
FLAG_CPUSET_CATEGORY_TOP_APP, /* isOnline= */ true, /* curCpuFreqKHz= */ 1_450_000,
|
||||
/* maxCpuFreqKHz= */ 2_800_000, /* avgTimeInStateCpuFreqKHz= */ 502_380,
|
||||
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)));
|
||||
|
||||
compareCpuInfos("CPU infos with corrupted proc stat", expectedCpuInfos, actualCpuInfos);
|
||||
}
|
||||
|
||||
@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(
|
||||
CpuInfoReader cpuInfoReader = 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("Init CPU reader info").that(cpuInfoReader.init()).isFalse();
|
||||
|
||||
assertWithMessage("Cpu infos").that(mCpuInfoReader.readCpuInfos()).isEmpty();
|
||||
assertWithMessage("Cpu infos with empty cpuset").that(cpuInfoReader.readCpuInfos())
|
||||
.isNull();
|
||||
}
|
||||
|
||||
@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,
|
||||
CpuInfoReader cpuInfoReader = new CpuInfoReader(getCacheFile(VALID_CPUSET_DIR), emptyDir,
|
||||
getCacheFile(VALID_PROC_STAT));
|
||||
|
||||
assertWithMessage("Init CPU reader info").that(mCpuInfoReader.init()).isFalse();
|
||||
assertWithMessage("Init CPU reader info").that(cpuInfoReader.init()).isFalse();
|
||||
|
||||
assertWithMessage("Cpu infos").that(mCpuInfoReader.readCpuInfos()).isEmpty();
|
||||
assertWithMessage("Cpu infos with empty CPU frequency").that(cpuInfoReader.readCpuInfos())
|
||||
.isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -403,10 +419,25 @@ public final class CpuInfoReaderTest extends ExtendedMockitoTestCase {
|
||||
File emptyFile = getCacheFile(EMPTY_FILE);
|
||||
assertWithMessage("Create empty file %s", emptyFile).that(emptyFile.createNewFile())
|
||||
.isTrue();
|
||||
mCpuInfoReader = new CpuInfoReader(getCacheFile(VALID_CPUSET_DIR),
|
||||
CpuInfoReader cpuInfoReader = new CpuInfoReader(getCacheFile(VALID_CPUSET_DIR),
|
||||
getCacheFile(VALID_CPUFREQ_WITH_TIME_IN_STATE_DIR), getCacheFile(EMPTY_FILE));
|
||||
|
||||
assertWithMessage("Cpu infos").that(mCpuInfoReader.readCpuInfos()).isEmpty();
|
||||
assertWithMessage("Cpu infos with empty proc stat").that(cpuInfoReader.readCpuInfos())
|
||||
.isNull();
|
||||
}
|
||||
|
||||
private static void compareCpuInfos(String message,
|
||||
SparseArray<CpuInfoReader.CpuInfo> expected,
|
||||
SparseArray<CpuInfoReader.CpuInfo> actual) {
|
||||
assertWithMessage("%s. Total CPU infos", message).that(actual.size())
|
||||
.isEqualTo(expected.size());
|
||||
for (int i = 0; i < expected.size(); i++) {
|
||||
int cpuCoreId = expected.keyAt(i);
|
||||
CpuInfoReader.CpuInfo expectedCpuInfo = expected.valueAt(i);
|
||||
CpuInfoReader.CpuInfo actualCpuInfo = actual.get(cpuCoreId);
|
||||
assertWithMessage("%s. Core %d's CPU info", message, cpuCoreId).that(actualCpuInfo)
|
||||
.isEqualTo(expectedCpuInfo);
|
||||
}
|
||||
}
|
||||
|
||||
private File getCacheFile(String assetName) {
|
||||
@@ -424,11 +455,18 @@ public final class CpuInfoReaderTest extends ExtendedMockitoTestCase {
|
||||
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);
|
||||
for (String assetName : assets) {
|
||||
copyAssets(String.format("%s%s%s", assetPath, File.separator, assetName), targetRoot);
|
||||
}
|
||||
}
|
||||
|
||||
private static CpuInfoReader newCpuInfoReader(File cpusetDir, File cpuFreqDir,
|
||||
File procStatFile) {
|
||||
CpuInfoReader cpuInfoReader = new CpuInfoReader(cpusetDir, cpuFreqDir, procStatFile);
|
||||
assertWithMessage("Initialize CPU info reader").that(cpuInfoReader.init()).isTrue();
|
||||
return cpuInfoReader;
|
||||
}
|
||||
|
||||
private static boolean deleteDirectory(File rootDir) {
|
||||
if (!rootDir.exists() || !rootDir.isDirectory()) {
|
||||
return false;
|
||||
|
||||
Reference in New Issue
Block a user