Merge "Make KernelSingleProcessCpuThreadReader aggregate CPU times"
This commit is contained in:
committed by
Android (Google) Code Review
commit
5dc9d9725a
@@ -1019,8 +1019,6 @@ public class BatteryStatsImpl extends BatteryStats {
|
||||
*/
|
||||
private LongSamplingCounterArray mSystemServerCpuTimesUs;
|
||||
|
||||
private long[] mTmpSystemServerCpuTimesUs;
|
||||
|
||||
/**
|
||||
* Times spent by the system server threads grouped by cluster and CPU speed.
|
||||
*/
|
||||
@@ -12432,41 +12430,15 @@ public class BatteryStatsImpl extends BatteryStats {
|
||||
return;
|
||||
}
|
||||
|
||||
int numCpuClusters = mPowerProfile.getNumCpuClusters();
|
||||
if (mSystemServerCpuTimesUs == null) {
|
||||
mSystemServerCpuTimesUs = new LongSamplingCounterArray(mOnBatteryTimeBase);
|
||||
mSystemServerThreadCpuTimesUs = new LongSamplingCounterArray(mOnBatteryTimeBase);
|
||||
mBinderThreadCpuTimesUs = new LongSamplingCounterArray(mOnBatteryTimeBase);
|
||||
}
|
||||
mSystemServerCpuTimesUs.addCountLocked(systemServiceCpuThreadTimes.processCpuTimesUs);
|
||||
mSystemServerThreadCpuTimesUs.addCountLocked(systemServiceCpuThreadTimes.threadCpuTimesUs);
|
||||
mBinderThreadCpuTimesUs.addCountLocked(systemServiceCpuThreadTimes.binderThreadCpuTimesUs);
|
||||
|
||||
long totalCpuTimeAllThreads = 0;
|
||||
for (int index = systemServiceCpuThreadTimes.threadCpuTimesUs.length - 1; index >= 0;
|
||||
index--) {
|
||||
totalCpuTimeAllThreads += systemServiceCpuThreadTimes.threadCpuTimesUs[index];
|
||||
}
|
||||
|
||||
// Estimate per cluster per frequency CPU time for the entire process
|
||||
// by distributing the total process CPU time proportionately to how much
|
||||
// CPU time its threads took on those clusters/frequencies. This algorithm
|
||||
// works more accurately when when we have equally distributed concurrency.
|
||||
// TODO(b/169279846): obtain actual process CPU times from the kernel
|
||||
long processCpuTime = systemServiceCpuThreadTimes.processCpuTimeUs;
|
||||
if (mTmpSystemServerCpuTimesUs == null) {
|
||||
mTmpSystemServerCpuTimesUs =
|
||||
new long[systemServiceCpuThreadTimes.threadCpuTimesUs.length];
|
||||
}
|
||||
for (int index = systemServiceCpuThreadTimes.threadCpuTimesUs.length - 1; index >= 0;
|
||||
index--) {
|
||||
mTmpSystemServerCpuTimesUs[index] =
|
||||
processCpuTime * systemServiceCpuThreadTimes.threadCpuTimesUs[index]
|
||||
/ totalCpuTimeAllThreads;
|
||||
|
||||
}
|
||||
|
||||
mSystemServerCpuTimesUs.addCountLocked(mTmpSystemServerCpuTimesUs);
|
||||
|
||||
if (DEBUG_BINDER_STATS) {
|
||||
Slog.d(TAG, "System server threads per CPU cluster (binder threads/total threads/%)");
|
||||
long totalCpuTimeMs = 0;
|
||||
@@ -12480,6 +12452,7 @@ public class BatteryStatsImpl extends BatteryStats {
|
||||
final long[] binderThreadCpuTimesUs =
|
||||
mBinderThreadCpuTimesUs.getCountsLocked(0);
|
||||
int index = 0;
|
||||
int numCpuClusters = mPowerProfile.getNumCpuClusters();
|
||||
for (int cluster = 0; cluster < numCpuClusters; cluster++) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("cpu").append(cpuIndex).append(": [");
|
||||
|
||||
@@ -33,8 +33,7 @@ import java.nio.file.DirectoryStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Iterates over all threads owned by a given process, and return the CPU usage for
|
||||
@@ -151,7 +150,7 @@ public class KernelSingleProcessCpuThreadReader {
|
||||
|
||||
/**
|
||||
* Get the CPU frequencies that correspond to the times reported in {@link
|
||||
* ThreadCpuUsage#usageTimesMillis}
|
||||
* ProcessCpuUsage#processCpuTimesMillis} etc.
|
||||
*/
|
||||
public int getCpuFrequencyCount() {
|
||||
if (mFrequencyCount == 0) {
|
||||
@@ -163,14 +162,22 @@ public class KernelSingleProcessCpuThreadReader {
|
||||
/**
|
||||
* Get the total and per-thread CPU usage of the process with the PID specified in the
|
||||
* constructor.
|
||||
* @param selectedThreadIds a SORTED array of native Thread IDs whose CPU times should
|
||||
* be aggregated as a group. This is expected to be a subset
|
||||
* of all thread IDs owned by the process.
|
||||
*/
|
||||
@Nullable
|
||||
public ProcessCpuUsage getProcessCpuUsage() {
|
||||
public ProcessCpuUsage getProcessCpuUsage(int[] selectedThreadIds) {
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "Reading CPU thread usages with directory " + mProcPath + " process ID "
|
||||
+ mPid);
|
||||
}
|
||||
|
||||
if (!isSorted(selectedThreadIds)) {
|
||||
throw new IllegalArgumentException("selectedThreadIds is not sorted: "
|
||||
+ Arrays.toString(selectedThreadIds));
|
||||
}
|
||||
|
||||
if (!Process.readProcFile(mProcessStatFilePath, PROCESS_FULL_STATS_FORMAT, null,
|
||||
mProcessFullStatsData, null)) {
|
||||
Slog.e(TAG, "Failed to read process stat file " + mProcessStatFilePath);
|
||||
@@ -182,39 +189,43 @@ public class KernelSingleProcessCpuThreadReader {
|
||||
|
||||
long processCpuTimeMillis = (utime + stime) * mJiffyMillis;
|
||||
|
||||
final ArrayList<ThreadCpuUsage> threadCpuUsages = new ArrayList<>();
|
||||
int cpuFrequencyCount = getCpuFrequencyCount();
|
||||
ProcessCpuUsage processCpuUsage = new ProcessCpuUsage(cpuFrequencyCount);
|
||||
try (DirectoryStream<Path> threadPaths = Files.newDirectoryStream(mThreadsDirectoryPath)) {
|
||||
for (Path threadDirectory : threadPaths) {
|
||||
ThreadCpuUsage threadCpuUsage = getThreadCpuUsage(threadDirectory);
|
||||
if (threadCpuUsage == null) {
|
||||
continue;
|
||||
}
|
||||
threadCpuUsages.add(threadCpuUsage);
|
||||
readThreadCpuUsage(processCpuUsage, selectedThreadIds, threadDirectory);
|
||||
}
|
||||
} catch (IOException | DirectoryIteratorException e) {
|
||||
// Expected when a process finishes
|
||||
return null;
|
||||
}
|
||||
|
||||
// If we found no threads, then the process has exited while we were reading from it
|
||||
if (threadCpuUsages.isEmpty()) {
|
||||
return null;
|
||||
// Estimate per cluster per frequency CPU time for the entire process
|
||||
// by distributing the total process CPU time proportionately to how much
|
||||
// CPU time its threads took on those clusters/frequencies. This algorithm
|
||||
// works more accurately when when we have equally distributed concurrency.
|
||||
// TODO(b/169279846): obtain actual process CPU times from the kernel
|
||||
long totalCpuTimeAllThreads = 0;
|
||||
for (int i = cpuFrequencyCount - 1; i >= 0; i--) {
|
||||
totalCpuTimeAllThreads += processCpuUsage.threadCpuTimesMillis[i];
|
||||
}
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "Read CPU usage of " + threadCpuUsages.size() + " threads");
|
||||
|
||||
for (int i = cpuFrequencyCount - 1; i >= 0; i--) {
|
||||
processCpuUsage.processCpuTimesMillis[i] =
|
||||
processCpuTimeMillis * processCpuUsage.threadCpuTimesMillis[i]
|
||||
/ totalCpuTimeAllThreads;
|
||||
}
|
||||
return new ProcessCpuUsage(processCpuTimeMillis, threadCpuUsages);
|
||||
|
||||
return processCpuUsage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a thread's CPU usage
|
||||
* Reads a thread's CPU usage and aggregates the per-cluster per-frequency CPU times.
|
||||
*
|
||||
* @param threadDirectory the {@code /proc} directory of the thread
|
||||
* @return thread CPU usage. Null if the thread exited and its {@code proc} directory was
|
||||
* removed while collecting information
|
||||
*/
|
||||
@Nullable
|
||||
private ThreadCpuUsage getThreadCpuUsage(Path threadDirectory) {
|
||||
private void readThreadCpuUsage(ProcessCpuUsage processCpuUsage, int[] selectedThreadIds,
|
||||
Path threadDirectory) {
|
||||
// Get the thread ID from the directory name
|
||||
final int threadId;
|
||||
try {
|
||||
@@ -222,38 +233,45 @@ public class KernelSingleProcessCpuThreadReader {
|
||||
threadId = Integer.parseInt(directoryName);
|
||||
} catch (NumberFormatException e) {
|
||||
Slog.w(TAG, "Failed to parse thread ID when iterating over /proc/*/task", e);
|
||||
return null;
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the CPU statistics from the directory
|
||||
final Path threadCpuStatPath = threadDirectory.resolve(CPU_STATISTICS_FILENAME);
|
||||
final long[] cpuUsages = mProcTimeInStateReader.getUsageTimesMillis(threadCpuStatPath);
|
||||
if (cpuUsages == null) {
|
||||
return null;
|
||||
return;
|
||||
}
|
||||
|
||||
return new ThreadCpuUsage(threadId, cpuUsages);
|
||||
final int cpuFrequencyCount = getCpuFrequencyCount();
|
||||
final boolean isSelectedThread = Arrays.binarySearch(selectedThreadIds, threadId) >= 0;
|
||||
for (int i = cpuFrequencyCount - 1; i >= 0; i--) {
|
||||
processCpuUsage.threadCpuTimesMillis[i] += cpuUsages[i];
|
||||
if (isSelectedThread) {
|
||||
processCpuUsage.selectedThreadCpuTimesMillis[i] += cpuUsages[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** CPU usage of a process and all of its threads */
|
||||
/** CPU usage of a process, all of its threads and a selected subset of its threads */
|
||||
public static class ProcessCpuUsage {
|
||||
public final long cpuTimeMillis;
|
||||
public final List<ThreadCpuUsage> threadCpuUsages;
|
||||
public long[] processCpuTimesMillis;
|
||||
public long[] threadCpuTimesMillis;
|
||||
public long[] selectedThreadCpuTimesMillis;
|
||||
|
||||
ProcessCpuUsage(long cpuTimeMillis, List<ThreadCpuUsage> threadCpuUsages) {
|
||||
this.cpuTimeMillis = cpuTimeMillis;
|
||||
this.threadCpuUsages = threadCpuUsages;
|
||||
public ProcessCpuUsage(int cpuFrequencyCount) {
|
||||
processCpuTimesMillis = new long[cpuFrequencyCount];
|
||||
threadCpuTimesMillis = new long[cpuFrequencyCount];
|
||||
selectedThreadCpuTimesMillis = new long[cpuFrequencyCount];
|
||||
}
|
||||
}
|
||||
|
||||
/** CPU usage of a thread */
|
||||
public static class ThreadCpuUsage {
|
||||
public final int threadId;
|
||||
public final long[] usageTimesMillis;
|
||||
|
||||
ThreadCpuUsage(int threadId, long[] usageTimesMillis) {
|
||||
this.threadId = threadId;
|
||||
this.usageTimesMillis = usageTimesMillis;
|
||||
private static boolean isSorted(int[] array) {
|
||||
for (int i = 0; i < array.length - 1; i++) {
|
||||
if (array[i] > array[i + 1]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,6 @@ import com.android.internal.annotations.VisibleForTesting;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Reads /proc/UID/task/TID/time_in_state files to obtain statistics on CPU usage
|
||||
@@ -34,10 +33,7 @@ public class SystemServerCpuThreadReader {
|
||||
private final KernelSingleProcessCpuThreadReader mKernelCpuThreadReader;
|
||||
private int[] mBinderThreadNativeTids = new int[0]; // Sorted
|
||||
|
||||
private long mProcessCpuTimeUs;
|
||||
private long[] mThreadCpuTimesUs;
|
||||
private long[] mBinderThreadCpuTimesUs;
|
||||
private long mLastProcessCpuTimeUs;
|
||||
private long[] mLastProcessCpuTimeUs;
|
||||
private long[] mLastThreadCpuTimesUs;
|
||||
private long[] mLastBinderThreadCpuTimesUs;
|
||||
|
||||
@@ -46,14 +42,15 @@ public class SystemServerCpuThreadReader {
|
||||
*/
|
||||
public static class SystemServiceCpuThreadTimes {
|
||||
// The entire process
|
||||
public long processCpuTimeUs;
|
||||
public long[] processCpuTimesUs;
|
||||
// All threads
|
||||
public long[] threadCpuTimesUs;
|
||||
// Just the threads handling incoming binder calls
|
||||
public long[] binderThreadCpuTimesUs;
|
||||
}
|
||||
|
||||
private SystemServiceCpuThreadTimes mDeltaCpuThreadTimes = new SystemServiceCpuThreadTimes();
|
||||
private final SystemServiceCpuThreadTimes mDeltaCpuThreadTimes =
|
||||
new SystemServiceCpuThreadTimes();
|
||||
|
||||
/**
|
||||
* Creates a configured instance of SystemServerCpuThreadReader.
|
||||
@@ -83,59 +80,38 @@ public class SystemServerCpuThreadReader {
|
||||
*/
|
||||
@Nullable
|
||||
public SystemServiceCpuThreadTimes readDelta() {
|
||||
int numCpuFrequencies = mKernelCpuThreadReader.getCpuFrequencyCount();
|
||||
if (mBinderThreadCpuTimesUs == null) {
|
||||
mThreadCpuTimesUs = new long[numCpuFrequencies];
|
||||
mBinderThreadCpuTimesUs = new long[numCpuFrequencies];
|
||||
|
||||
final int numCpuFrequencies = mKernelCpuThreadReader.getCpuFrequencyCount();
|
||||
if (mLastProcessCpuTimeUs == null) {
|
||||
mLastProcessCpuTimeUs = new long[numCpuFrequencies];
|
||||
mLastThreadCpuTimesUs = new long[numCpuFrequencies];
|
||||
mLastBinderThreadCpuTimesUs = new long[numCpuFrequencies];
|
||||
|
||||
mDeltaCpuThreadTimes.processCpuTimesUs = new long[numCpuFrequencies];
|
||||
mDeltaCpuThreadTimes.threadCpuTimesUs = new long[numCpuFrequencies];
|
||||
mDeltaCpuThreadTimes.binderThreadCpuTimesUs = new long[numCpuFrequencies];
|
||||
}
|
||||
|
||||
mProcessCpuTimeUs = 0;
|
||||
Arrays.fill(mThreadCpuTimesUs, 0);
|
||||
Arrays.fill(mBinderThreadCpuTimesUs, 0);
|
||||
|
||||
KernelSingleProcessCpuThreadReader.ProcessCpuUsage processCpuUsage =
|
||||
mKernelCpuThreadReader.getProcessCpuUsage();
|
||||
final KernelSingleProcessCpuThreadReader.ProcessCpuUsage processCpuUsage =
|
||||
mKernelCpuThreadReader.getProcessCpuUsage(mBinderThreadNativeTids);
|
||||
if (processCpuUsage == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
mProcessCpuTimeUs = processCpuUsage.cpuTimeMillis * 1000;
|
||||
|
||||
List<KernelSingleProcessCpuThreadReader.ThreadCpuUsage> threadCpuUsages =
|
||||
processCpuUsage.threadCpuUsages;
|
||||
int threadCpuUsagesSize = threadCpuUsages.size();
|
||||
for (int i = 0; i < threadCpuUsagesSize; i++) {
|
||||
KernelSingleProcessCpuThreadReader.ThreadCpuUsage tcu = threadCpuUsages.get(i);
|
||||
boolean isBinderThread =
|
||||
Arrays.binarySearch(mBinderThreadNativeTids, tcu.threadId) >= 0;
|
||||
for (int k = 0; k < numCpuFrequencies; k++) {
|
||||
long usageTimeUs = tcu.usageTimesMillis[k] * 1000;
|
||||
mThreadCpuTimesUs[k] += usageTimeUs;
|
||||
if (isBinderThread) {
|
||||
mBinderThreadCpuTimesUs[k] += usageTimeUs;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < mThreadCpuTimesUs.length; i++) {
|
||||
mDeltaCpuThreadTimes.processCpuTimeUs =
|
||||
Math.max(0, mProcessCpuTimeUs - mLastProcessCpuTimeUs);
|
||||
for (int i = numCpuFrequencies - 1; i >= 0; i--) {
|
||||
long processCpuTimesUs = processCpuUsage.processCpuTimesMillis[i] * 1000;
|
||||
long threadCpuTimesUs = processCpuUsage.threadCpuTimesMillis[i] * 1000;
|
||||
long binderThreadCpuTimesUs = processCpuUsage.selectedThreadCpuTimesMillis[i] * 1000;
|
||||
mDeltaCpuThreadTimes.processCpuTimesUs[i] =
|
||||
Math.max(0, processCpuTimesUs - mLastProcessCpuTimeUs[i]);
|
||||
mDeltaCpuThreadTimes.threadCpuTimesUs[i] =
|
||||
Math.max(0, mThreadCpuTimesUs[i] - mLastThreadCpuTimesUs[i]);
|
||||
Math.max(0, threadCpuTimesUs - mLastThreadCpuTimesUs[i]);
|
||||
mDeltaCpuThreadTimes.binderThreadCpuTimesUs[i] =
|
||||
Math.max(0, mBinderThreadCpuTimesUs[i] - mLastBinderThreadCpuTimesUs[i]);
|
||||
mLastThreadCpuTimesUs[i] = mThreadCpuTimesUs[i];
|
||||
mLastBinderThreadCpuTimesUs[i] = mBinderThreadCpuTimesUs[i];
|
||||
Math.max(0, binderThreadCpuTimesUs - mLastBinderThreadCpuTimesUs[i]);
|
||||
mLastProcessCpuTimeUs[i] = processCpuTimesUs;
|
||||
mLastThreadCpuTimesUs[i] = threadCpuTimesUs;
|
||||
mLastBinderThreadCpuTimesUs[i] = binderThreadCpuTimesUs;
|
||||
}
|
||||
|
||||
mLastProcessCpuTimeUs = mProcessCpuTimeUs;
|
||||
|
||||
return mDeltaCpuThreadTimes;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,8 +38,6 @@ import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
@SmallTest
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
@@ -59,31 +57,21 @@ public class KernelSingleProcessCpuThreadReaderTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getThreadCpuUsage() throws IOException {
|
||||
public void getProcessCpuUsage() throws IOException {
|
||||
setupDirectory(42,
|
||||
new int[] {42, 1, 2, 3},
|
||||
new int[] {1000, 2000},
|
||||
// Units are 10ms aka 10000Us
|
||||
new int[][] {{100, 200}, {0, 200}, {100, 300}, {0, 400}},
|
||||
new int[] {1400, 1500});
|
||||
new int[][] {{100, 200}, {0, 200}, {100, 300}, {0, 600}},
|
||||
new int[] {4500, 500});
|
||||
|
||||
KernelSingleProcessCpuThreadReader reader = new KernelSingleProcessCpuThreadReader(42,
|
||||
mProcDirectory.toPath());
|
||||
KernelSingleProcessCpuThreadReader.ProcessCpuUsage processCpuUsage =
|
||||
reader.getProcessCpuUsage();
|
||||
assertThat(processCpuUsage.cpuTimeMillis).isEqualTo(29000);
|
||||
List<KernelSingleProcessCpuThreadReader.ThreadCpuUsage> threadCpuUsage =
|
||||
processCpuUsage.threadCpuUsages;
|
||||
threadCpuUsage.sort(Comparator.comparingInt(o -> o.threadId));
|
||||
assertThat(threadCpuUsage).hasSize(4);
|
||||
assertThat(threadCpuUsage.get(0).threadId).isEqualTo(1);
|
||||
assertThat(threadCpuUsage.get(0).usageTimesMillis).isEqualTo(new long[]{0, 2000});
|
||||
assertThat(threadCpuUsage.get(1).threadId).isEqualTo(2);
|
||||
assertThat(threadCpuUsage.get(1).usageTimesMillis).isEqualTo(new long[]{1000, 3000});
|
||||
assertThat(threadCpuUsage.get(2).threadId).isEqualTo(3);
|
||||
assertThat(threadCpuUsage.get(2).usageTimesMillis).isEqualTo(new long[]{0, 4000});
|
||||
assertThat(threadCpuUsage.get(3).threadId).isEqualTo(42);
|
||||
assertThat(threadCpuUsage.get(3).usageTimesMillis).isEqualTo(new long[]{1000, 2000});
|
||||
reader.getProcessCpuUsage(new int[] {2, 3});
|
||||
assertThat(processCpuUsage.threadCpuTimesMillis).isEqualTo(new long[] {2000, 13000});
|
||||
assertThat(processCpuUsage.selectedThreadCpuTimesMillis).isEqualTo(new long[] {1000, 9000});
|
||||
assertThat(processCpuUsage.processCpuTimesMillis).isEqualTo(new long[] {6666, 43333});
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -66,7 +66,7 @@ public class SystemServicePowerCalculatorTest {
|
||||
public void testCalculateApp() {
|
||||
// Test Power Profile has two CPU clusters with 3 and 4 speeds, thus 7 freq times total
|
||||
mMockSystemServerCpuThreadReader.setCpuTimes(
|
||||
210000,
|
||||
new long[] {10000, 15000, 20000, 25000, 30000, 35000, 40000},
|
||||
new long[] {30000, 40000, 50000, 60000, 70000, 80000, 90000},
|
||||
new long[] {20000, 30000, 40000, 50000, 60000, 70000, 80000});
|
||||
|
||||
@@ -107,13 +107,13 @@ public class SystemServicePowerCalculatorTest {
|
||||
mMockBatteryStats.getUidStatsLocked(workSourceUid1), 0);
|
||||
mSystemServicePowerCalculator.calculateApp(app1, app1.uidObj, 0, 0,
|
||||
BatteryStats.STATS_SINCE_CHARGED);
|
||||
assertEquals(0.00018958, app1.systemServiceCpuPowerMah, 0.0000001);
|
||||
assertEquals(0.00016269, app1.systemServiceCpuPowerMah, 0.0000001);
|
||||
|
||||
BatterySipper app2 = new BatterySipper(BatterySipper.DrainType.APP,
|
||||
mMockBatteryStats.getUidStatsLocked(workSourceUid2), 0);
|
||||
mSystemServicePowerCalculator.calculateApp(app2, app2.uidObj, 0, 0,
|
||||
BatteryStats.STATS_SINCE_CHARGED);
|
||||
assertEquals(0.00170625, app2.systemServiceCpuPowerMah, 0.0000001);
|
||||
assertEquals(0.00146426, app2.systemServiceCpuPowerMah, 0.0000001);
|
||||
}
|
||||
|
||||
private static class MockKernelCpuUidFreqTimeReader extends
|
||||
@@ -148,9 +148,9 @@ public class SystemServicePowerCalculatorTest {
|
||||
super(null);
|
||||
}
|
||||
|
||||
public void setCpuTimes(long processCpuTimeUs, long[] threadCpuTimesUs,
|
||||
public void setCpuTimes(long[] processCpuTimesUs, long[] threadCpuTimesUs,
|
||||
long[] binderThreadCpuTimesUs) {
|
||||
mThreadTimes.processCpuTimeUs = processCpuTimeUs;
|
||||
mThreadTimes.processCpuTimesUs = processCpuTimesUs;
|
||||
mThreadTimes.threadCpuTimesUs = threadCpuTimesUs;
|
||||
mThreadTimes.binderThreadCpuTimesUs = binderThreadCpuTimesUs;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user