diff options
6 files changed, 103 insertions, 5 deletions
diff --git a/apct-tests/perftests/core/src/android/os/KernelCpuThreadReaderPerfTest.java b/apct-tests/perftests/core/src/android/os/KernelCpuThreadReaderPerfTest.java index 92348497101e..0c30302d63a3 100644 --- a/apct-tests/perftests/core/src/android/os/KernelCpuThreadReaderPerfTest.java +++ b/apct-tests/perftests/core/src/android/os/KernelCpuThreadReaderPerfTest.java @@ -40,7 +40,7 @@ public class KernelCpuThreadReaderPerfTest { public final PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter(); private final KernelCpuThreadReader mKernelCpuThreadReader = - KernelCpuThreadReader.create(8, uid -> 1000 <= uid && uid < 2000); + KernelCpuThreadReader.create(8, uid -> 1000 <= uid && uid < 2000, 0); @Test public void timeReadCurrentProcessCpuUsage() { diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index e14bb66828a4..539ad8dfd1db 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -14334,6 +14334,7 @@ public final class Settings { * <pre> * num_buckets (int) * collected_uids (string) + * minimum_total_cpu_usage_millis (int) * </pre> * * @hide diff --git a/core/java/com/android/internal/os/KernelCpuThreadReader.java b/core/java/com/android/internal/os/KernelCpuThreadReader.java index b1328e862273..6bbfc2b1277a 100644 --- a/core/java/com/android/internal/os/KernelCpuThreadReader.java +++ b/core/java/com/android/internal/os/KernelCpuThreadReader.java @@ -109,6 +109,12 @@ public class KernelCpuThreadReader { private Predicate<Integer> mUidPredicate; /** + * If a thread has strictly less than {@code minimumTotalCpuUsageMillis} total CPU usage, it + * will not be reported + */ + private int mMinimumTotalCpuUsageMillis; + + /** * Where the proc filesystem is mounted */ private final Path mProcPath; @@ -142,10 +148,12 @@ public class KernelCpuThreadReader { public KernelCpuThreadReader( int numBuckets, Predicate<Integer> uidPredicate, + int minimumTotalCpuUsageMillis, Path procPath, Path initialTimeInStatePath, Injector injector) throws IOException { mUidPredicate = uidPredicate; + mMinimumTotalCpuUsageMillis = minimumTotalCpuUsageMillis; mProcPath = procPath; mProcTimeInStateReader = new ProcTimeInStateReader(initialTimeInStatePath); mInjector = injector; @@ -158,11 +166,13 @@ public class KernelCpuThreadReader { * @return the reader, null if an exception was thrown during creation */ @Nullable - public static KernelCpuThreadReader create(int numBuckets, Predicate<Integer> uidPredicate) { + public static KernelCpuThreadReader create( + int numBuckets, Predicate<Integer> uidPredicate, int minimumTotalCpuUsageMillis) { try { return new KernelCpuThreadReader( numBuckets, uidPredicate, + minimumTotalCpuUsageMillis, DEFAULT_PROC_PATH, DEFAULT_INITIAL_TIME_IN_STATE_PATH, new Injector()); @@ -308,6 +318,18 @@ public class KernelCpuThreadReader { } /** + * If a thread has strictly less than {@code minimumTotalCpuUsageMillis} total CPU usage, it + * will not be reported + */ + void setMinimumTotalCpuUsageMillis(int minimumTotalCpuUsageMillis) { + if (minimumTotalCpuUsageMillis < 0) { + Slog.w(TAG, "Negative minimumTotalCpuUsageMillis: " + minimumTotalCpuUsageMillis); + return; + } + mMinimumTotalCpuUsageMillis = minimumTotalCpuUsageMillis; + } + + /** * Get the CPU frequencies that correspond to the times reported in * {@link ThreadCpuUsage#usageTimesMillis} */ @@ -346,6 +368,15 @@ public class KernelCpuThreadReader { } int[] cpuUsages = mFrequencyBucketCreator.getBucketedValues(cpuUsagesLong); + // Check if the total CPU usage below the threshold + int totalCpuUsage = 0; + for (int i = 0; i < cpuUsages.length; i++) { + totalCpuUsage += cpuUsages[i]; + } + if (totalCpuUsage < mMinimumTotalCpuUsageMillis) { + return null; + } + return new ThreadCpuUsage(threadId, threadName, cpuUsages); } diff --git a/core/java/com/android/internal/os/KernelCpuThreadReaderSettingsObserver.java b/core/java/com/android/internal/os/KernelCpuThreadReaderSettingsObserver.java index 77f6a17acdc9..718bcb43bd9a 100644 --- a/core/java/com/android/internal/os/KernelCpuThreadReaderSettingsObserver.java +++ b/core/java/com/android/internal/os/KernelCpuThreadReaderSettingsObserver.java @@ -59,6 +59,13 @@ public class KernelCpuThreadReaderSettingsObserver extends ContentObserver { private static final String COLLECTED_UIDS_SETTINGS_KEY = "collected_uids"; private static final String COLLECTED_UIDS_DEFAULT = "1000-1000"; + /** + * Minimum total CPU usage to report + */ + private static final String MINIMUM_TOTAL_CPU_USAGE_MILLIS_SETTINGS_KEY = + "minimum_total_cpu_usage_millis"; + private static final int MINIMUM_TOTAL_CPU_USAGE_MILLIS_DEFAULT = 0; + private final Context mContext; @Nullable @@ -87,7 +94,8 @@ public class KernelCpuThreadReaderSettingsObserver extends ContentObserver { mContext = context; mKernelCpuThreadReader = KernelCpuThreadReader.create( NUM_BUCKETS_DEFAULT, - UidPredicate.fromString(COLLECTED_UIDS_DEFAULT)); + UidPredicate.fromString(COLLECTED_UIDS_DEFAULT), + MINIMUM_TOTAL_CPU_USAGE_MILLIS_DEFAULT); } @Override @@ -124,6 +132,9 @@ public class KernelCpuThreadReaderSettingsObserver extends ContentObserver { mKernelCpuThreadReader.setNumBuckets( parser.getInt(NUM_BUCKETS_SETTINGS_KEY, NUM_BUCKETS_DEFAULT)); mKernelCpuThreadReader.setUidPredicate(uidPredicate); + mKernelCpuThreadReader.setMinimumTotalCpuUsageMillis(parser.getInt( + MINIMUM_TOTAL_CPU_USAGE_MILLIS_SETTINGS_KEY, + MINIMUM_TOTAL_CPU_USAGE_MILLIS_DEFAULT)); } /** diff --git a/core/tests/coretests/src/com/android/internal/os/KernelCpuThreadReaderEndToEndTest.java b/core/tests/coretests/src/com/android/internal/os/KernelCpuThreadReaderEndToEndTest.java index 3ddd8aaeba2c..ae1660607a90 100644 --- a/core/tests/coretests/src/com/android/internal/os/KernelCpuThreadReaderEndToEndTest.java +++ b/core/tests/coretests/src/com/android/internal/os/KernelCpuThreadReaderEndToEndTest.java @@ -123,7 +123,7 @@ public class KernelCpuThreadReaderEndToEndTest { // Get thread data from KernelCpuThreadReader final KernelCpuThreadReader kernelCpuThreadReader = - KernelCpuThreadReader.create(8, uid -> uid == Process.myUid()); + KernelCpuThreadReader.create(8, uid -> uid == Process.myUid(), 0); assertNotNull(kernelCpuThreadReader); final ProcessCpuUsage currentProcessCpuUsage = kernelCpuThreadReader.getCurrentProcessCpuUsage(); diff --git a/core/tests/coretests/src/com/android/internal/os/KernelCpuThreadReaderTest.java b/core/tests/coretests/src/com/android/internal/os/KernelCpuThreadReaderTest.java index b9744f599a9a..442ece5a884d 100644 --- a/core/tests/coretests/src/com/android/internal/os/KernelCpuThreadReaderTest.java +++ b/core/tests/coretests/src/com/android/internal/os/KernelCpuThreadReaderTest.java @@ -103,6 +103,7 @@ public class KernelCpuThreadReaderTest { final KernelCpuThreadReader kernelCpuThreadReader = new KernelCpuThreadReader( 8, uid -> 1000 <= uid && uid < 2000, + 0, mProcDirectory.toPath(), mProcDirectory.toPath().resolve("self/task/" + THREAD_IDS[0] + "/time_in_state"), processUtils); @@ -144,6 +145,7 @@ public class KernelCpuThreadReaderTest { final KernelCpuThreadReader kernelCpuThreadReader = new KernelCpuThreadReader( 8, uidPredicate, + 0, mProcDirectory.toPath(), mProcDirectory.toPath().resolve(uids[0] + "/task/" + uids[0] + "/time_in_state"), processUtils); @@ -162,6 +164,60 @@ public class KernelCpuThreadReaderTest { } } + @Test + public void testReader_filtersLowUsage() throws IOException { + int[] uids = new int[]{0, 1, 2, 3, 4}; + int[] cpuUsage = new int[]{10, 0, 2, 100, 3}; + int[] expectedUids = new int[]{0, 3, 4}; + Predicate<Integer> uidPredicate = uid -> true; + KernelCpuThreadReader.Injector processUtils = + new KernelCpuThreadReader.Injector() { + @Override + public int myPid() { + return 0; + } + + @Override + public int myUid() { + return 0; + } + + @Override + public int getUidForPid(int pid) { + return pid; + } + }; + + for (int i = 0; i < uids.length; i++) { + int uid = uids[i]; + setupDirectory( + mProcDirectory.toPath().resolve(String.valueOf(uid)), + new int[]{uid * 10}, + "process" + uid, + new String[]{"thread" + uid}, + new int[]{1000}, + new int[][]{{cpuUsage[i]}}); + } + final KernelCpuThreadReader kernelCpuThreadReader = new KernelCpuThreadReader( + 8, + uidPredicate, + 30, + mProcDirectory.toPath(), + mProcDirectory.toPath().resolve(uids[0] + "/task/" + uids[0] + "/time_in_state"), + processUtils); + ArrayList<KernelCpuThreadReader.ProcessCpuUsage> processCpuUsageByUids = + kernelCpuThreadReader.getProcessCpuUsageByUids(); + processCpuUsageByUids.sort(Comparator.comparing(usage -> usage.uid)); + + assertEquals(expectedUids.length, processCpuUsageByUids.size()); + for (int i = 0; i < expectedUids.length; i++) { + KernelCpuThreadReader.ProcessCpuUsage processCpuUsage = + processCpuUsageByUids.get(i); + assertEquals(expectedUids[i], processCpuUsage.uid); + } + + } + private void setupDirectory(Path processPath, int[] threadIds, String processName, String[] threadNames, int[] cpuFrequencies, int[][] cpuTimes) throws IOException { // Make /proc/$PID @@ -328,7 +384,6 @@ public class KernelCpuThreadReaderTest { new long[]{1, 1, 1, 1, 1, 1, 1, 1})); } - @Test public void testGetBigFrequenciesStartIndex_simple() { assertEquals( |