Merge "Get wakelock stats from SystemSuspend"
am: dff4801d6b
Change-Id: I96bda190d2935e3a21391e831d23f50526c8fc93
diff --git a/core/java/com/android/internal/os/KernelWakelockReader.java b/core/java/com/android/internal/os/KernelWakelockReader.java
index 3ac58e0..d53fada 100644
--- a/core/java/com/android/internal/os/KernelWakelockReader.java
+++ b/core/java/com/android/internal/os/KernelWakelockReader.java
@@ -27,6 +27,7 @@
import com.android.internal.annotations.VisibleForTesting;
+import java.io.File;
import java.io.FileInputStream;
import java.util.Iterator;
@@ -38,6 +39,7 @@
private static int sKernelWakelockUpdateVersion = 0;
private static final String sWakelockFile = "/proc/wakelocks";
private static final String sWakeupSourceFile = "/d/wakeup_sources";
+ private static final String sSysClassWakeupDir = "/sys/class/wakeup";
private static final int[] PROC_WAKELOCKS_FORMAT = new int[] {
Process.PROC_TAB_TERM|Process.PROC_OUT_STRING| // 0: name
@@ -71,99 +73,108 @@
* @return the updated data.
*/
public final KernelWakelockStats readKernelWakelockStats(KernelWakelockStats staleStats) {
- byte[] buffer = new byte[32*1024];
- int len = 0;
- boolean wakeup_sources;
- final long startTime = SystemClock.uptimeMillis();
+ boolean useSystemSuspend = (new File(sSysClassWakeupDir)).exists();
- final int oldMask = StrictMode.allowThreadDiskReadsMask();
- try {
- FileInputStream is;
- try {
- is = new FileInputStream(sWakelockFile);
- wakeup_sources = false;
- } catch (java.io.FileNotFoundException e) {
+ if (useSystemSuspend) {
+ WakeLockInfo[] wlStats = null;
+ if (mSuspendControlService == null) {
try {
- is = new FileInputStream(sWakeupSourceFile);
- wakeup_sources = true;
- } catch (java.io.FileNotFoundException e2) {
- Slog.wtf(TAG, "neither " + sWakelockFile + " nor " +
- sWakeupSourceFile + " exists");
+ mSuspendControlService = ISuspendControlService.Stub.asInterface(
+ ServiceManager.getServiceOrThrow("suspend_control"));
+ } catch (ServiceNotFoundException e) {
+ Slog.wtf(TAG, "Required service suspend_control not available", e);
return null;
}
}
- int cnt;
- while ((cnt = is.read(buffer, len, buffer.length - len)) > 0) {
- len += cnt;
+ try {
+ wlStats = mSuspendControlService.getWakeLockStats();
+ updateVersion(staleStats);
+ updateWakelockStats(wlStats, staleStats);
+ } catch (RemoteException e) {
+ Slog.wtf(TAG, "Failed to obtain wakelock stats from ISuspendControlService", e);
+ return null;
}
- is.close();
- } catch (java.io.IOException e) {
- Slog.wtf(TAG, "failed to read kernel wakelocks", e);
- return null;
- } finally {
- StrictMode.setThreadPolicyMask(oldMask);
- }
+ return removeOldStats(staleStats);
- final long readTime = SystemClock.uptimeMillis() - startTime;
- if (readTime > 100) {
- Slog.w(TAG, "Reading wakelock stats took " + readTime + "ms");
- }
+ } else {
+ byte[] buffer = new byte[32*1024];
+ int len = 0;
+ boolean wakeup_sources;
+ final long startTime = SystemClock.uptimeMillis();
- if (len > 0) {
- if (len >= buffer.length) {
- Slog.wtf(TAG, "Kernel wake locks exceeded buffer size " + buffer.length);
+ final int oldMask = StrictMode.allowThreadDiskReadsMask();
+ try {
+ FileInputStream is;
+ try {
+ is = new FileInputStream(sWakelockFile);
+ wakeup_sources = false;
+ } catch (java.io.FileNotFoundException e) {
+ try {
+ is = new FileInputStream(sWakeupSourceFile);
+ wakeup_sources = true;
+ } catch (java.io.FileNotFoundException e2) {
+ Slog.wtf(TAG, "neither " + sWakelockFile + " nor " +
+ sWakeupSourceFile + " exists");
+ return null;
+ }
+ }
+
+ int cnt;
+ while ((cnt = is.read(buffer, len, buffer.length - len)) > 0) {
+ len += cnt;
+ }
+
+ is.close();
+ } catch (java.io.IOException e) {
+ Slog.wtf(TAG, "failed to read kernel wakelocks", e);
+ return null;
+ } finally {
+ StrictMode.setThreadPolicyMask(oldMask);
}
- int i;
- for (i=0; i<len; i++) {
- if (buffer[i] == '\0') {
- len = i;
- break;
+
+ final long readTime = SystemClock.uptimeMillis() - startTime;
+ if (readTime > 100) {
+ Slog.w(TAG, "Reading wakelock stats took " + readTime + "ms");
+ }
+
+ if (len > 0) {
+ if (len >= buffer.length) {
+ Slog.wtf(TAG, "Kernel wake locks exceeded buffer size " + buffer.length);
+ }
+ int i;
+ for (i=0; i<len; i++) {
+ if (buffer[i] == '\0') {
+ len = i;
+ break;
+ }
}
}
+
+ updateVersion(staleStats);
+ parseProcWakelocks(buffer, len, wakeup_sources, staleStats);
+ return removeOldStats(staleStats);
}
-
- updateVersion(staleStats);
-
- parseProcWakelocks(buffer, len, wakeup_sources, staleStats);
-
- if (mSuspendControlService == null) {
- try {
- mSuspendControlService = ISuspendControlService.Stub.asInterface(
- ServiceManager.getServiceOrThrow("suspend_control"));
- } catch (ServiceNotFoundException e) {
- Slog.wtf(TAG, "Required service suspend_control not available", e);
- }
- }
-
- try {
- WakeLockInfo[] wlStats = mSuspendControlService.getWakeLockStats();
- getNativeWakelockStats(wlStats, staleStats);
- } catch (RemoteException e) {
- Slog.wtf(TAG, "Failed to obtain wakelock stats from ISuspendControlService", e);
- }
-
- return removeOldStats(staleStats);
}
/**
- * Reads native wakelock stats from SystemSuspend and updates staleStats with the new
- * information.
+ * Updates statleStats with stats from SystemSuspend.
* @param staleStats Existing object to update.
* @return the updated stats.
*/
@VisibleForTesting
- public KernelWakelockStats getNativeWakelockStats(WakeLockInfo[] wlStats,
+ public KernelWakelockStats updateWakelockStats(WakeLockInfo[] wlStats,
final KernelWakelockStats staleStats) {
for (WakeLockInfo info : wlStats) {
if (!staleStats.containsKey(info.name)) {
staleStats.put(info.name, new KernelWakelockStats.Entry((int) info.activeCount,
- info.totalTime, sKernelWakelockUpdateVersion));
+ info.totalTime * 1000 /* ms to us */, sKernelWakelockUpdateVersion));
} else {
KernelWakelockStats.Entry kwlStats = staleStats.get(info.name);
kwlStats.mCount = (int) info.activeCount;
- kwlStats.mTotalTime = info.totalTime;
+ // Convert milliseconds to microseconds
+ kwlStats.mTotalTime = info.totalTime * 1000;
kwlStats.mVersion = sKernelWakelockUpdateVersion;
}
}
diff --git a/core/tests/coretests/src/com/android/internal/os/KernelWakelockReaderTest.java b/core/tests/coretests/src/com/android/internal/os/KernelWakelockReaderTest.java
index 008085e..a935737 100644
--- a/core/tests/coretests/src/com/android/internal/os/KernelWakelockReaderTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/KernelWakelockReaderTest.java
@@ -68,12 +68,7 @@
private WakeLockInfo createWakeLockInfo(String name, int activeCount, long totalTime) {
WakeLockInfo info = new WakeLockInfo();
info.name = name;
- info.pid = 1;
info.activeCount = activeCount;
- info.isActive = true;
- info.activeSince = 0;
- info.lastChange = 0;
- info.maxTime = 0;
info.totalTime = totalTime;
return info;
}
@@ -89,7 +84,7 @@
byte[] buffer, WakeLockInfo[] wlStats) {
mReader.updateVersion(staleStats);
mReader.parseProcWakelocks(buffer, buffer.length, true, staleStats);
- mReader.getNativeWakelockStats(wlStats, staleStats);
+ mReader.updateWakelockStats(wlStats, staleStats);
return mReader.removeOldStats(staleStats);
}
@@ -101,7 +96,7 @@
mReader = new KernelWakelockReader();
}
-// ------------------------- Kernel Wakelock Stats Test ------------------------
+// ------------------------- Legacy Wakelock Stats Test ------------------------
@SmallTest
public void testParseEmptyFile() throws Exception {
KernelWakelockStats staleStats = mReader.parseProcWakelocks(new byte[0], 0, true,
@@ -196,10 +191,10 @@
assertFalse(staleStats.containsKey("Fakelock"));
}
-// -------------------- Native (SystemSuspend) Wakelock Stats Test -------------------
+// -------------------- SystemSuspend Wakelock Stats Test -------------------
@SmallTest
public void testEmptyWakeLockInfoList() {
- KernelWakelockStats staleStats = mReader.getNativeWakelockStats(new WakeLockInfo[0],
+ KernelWakelockStats staleStats = mReader.updateWakelockStats(new WakeLockInfo[0],
new KernelWakelockStats());
assertTrue(staleStats.isEmpty());
@@ -208,9 +203,9 @@
@SmallTest
public void testOneWakeLockInfo() {
WakeLockInfo[] wlStats = new WakeLockInfo[1];
- wlStats[0] = createWakeLockInfo("WakeLock", 20, 10000);
+ wlStats[0] = createWakeLockInfo("WakeLock", 20, 1000); // Milliseconds
- KernelWakelockStats staleStats = mReader.getNativeWakelockStats(wlStats,
+ KernelWakelockStats staleStats = mReader.updateWakelockStats(wlStats,
new KernelWakelockStats());
assertEquals(1, staleStats.size());
@@ -219,16 +214,16 @@
KernelWakelockStats.Entry entry = staleStats.get("WakeLock");
assertEquals(20, entry.mCount);
- assertEquals(10000, entry.mTotalTime);
+ assertEquals(1000 * 1000, entry.mTotalTime); // Microseconds
}
@SmallTest
public void testTwoWakeLockInfos() {
WakeLockInfo[] wlStats = new WakeLockInfo[2];
- wlStats[0] = createWakeLockInfo("WakeLock1", 10, 1000);
- wlStats[1] = createWakeLockInfo("WakeLock2", 20, 2000);
+ wlStats[0] = createWakeLockInfo("WakeLock1", 10, 1000); // Milliseconds
+ wlStats[1] = createWakeLockInfo("WakeLock2", 20, 2000); // Milliseconds
- KernelWakelockStats staleStats = mReader.getNativeWakelockStats(wlStats,
+ KernelWakelockStats staleStats = mReader.updateWakelockStats(wlStats,
new KernelWakelockStats());
assertEquals(2, staleStats.size());
@@ -238,17 +233,17 @@
KernelWakelockStats.Entry entry1 = staleStats.get("WakeLock1");
assertEquals(10, entry1.mCount);
- assertEquals(1000, entry1.mTotalTime);
+ assertEquals(1000 * 1000, entry1.mTotalTime); // Microseconds
KernelWakelockStats.Entry entry2 = staleStats.get("WakeLock2");
assertEquals(20, entry2.mCount);
- assertEquals(2000, entry2.mTotalTime);
+ assertEquals(2000 * 1000, entry2.mTotalTime); // Microseconds
}
@SmallTest
public void testWakeLockInfosBecomeStale() {
WakeLockInfo[] wlStats = new WakeLockInfo[1];
- wlStats[0] = createWakeLockInfo("WakeLock1", 10, 1000);
+ wlStats[0] = createWakeLockInfo("WakeLock1", 10, 1000); // Milliseconds
KernelWakelockStats staleStats = new KernelWakelockStats();
@@ -259,9 +254,9 @@
assertTrue(staleStats.containsKey("WakeLock1"));
KernelWakelockStats.Entry entry = staleStats.get("WakeLock1");
assertEquals(10, entry.mCount);
- assertEquals(1000, entry.mTotalTime);
+ assertEquals(1000 * 1000, entry.mTotalTime); // Microseconds
- wlStats[0] = createWakeLockInfo("WakeLock2", 20, 2000);
+ wlStats[0] = createWakeLockInfo("WakeLock2", 20, 2000); // Milliseconds
readKernelWakelockStats(staleStats, new byte[0], wlStats);
@@ -271,146 +266,6 @@
assertTrue(staleStats.containsKey("WakeLock2"));
entry = staleStats.get("WakeLock2");
assertEquals(20, entry.mCount);
- assertEquals(2000, entry.mTotalTime);
- }
-
-// -------------------- Aggregate Wakelock Stats Tests --------------------
- @SmallTest
- public void testAggregateStatsEmpty() throws Exception {
- KernelWakelockStats staleStats = new KernelWakelockStats();
-
- byte[] buffer = new byte[0];
- WakeLockInfo[] wlStats = new WakeLockInfo[0];
-
- readKernelWakelockStats(staleStats, buffer, wlStats);
-
- assertTrue(staleStats.isEmpty());
- }
-
- @SmallTest
- public void testAggregateStatsNoNativeWakelocks() throws Exception {
- KernelWakelockStats staleStats = new KernelWakelockStats();
-
- byte[] buffer = new ProcFileBuilder()
- .addLine("Wakelock", 34, 123) // Milliseconds
- .getBytes();
- WakeLockInfo[] wlStats = new WakeLockInfo[0];
-
- readKernelWakelockStats(staleStats, buffer, wlStats);
-
- assertEquals(1, staleStats.size());
-
- assertTrue(staleStats.containsKey("Wakelock"));
-
- KernelWakelockStats.Entry entry = staleStats.get("Wakelock");
- assertEquals(34, entry.mCount);
- assertEquals(1000 * 123, entry.mTotalTime); // Microseconds
- }
-
- @SmallTest
- public void testAggregateStatsNoKernelWakelocks() throws Exception {
- KernelWakelockStats staleStats = new KernelWakelockStats();
-
- byte[] buffer = new byte[0];
- WakeLockInfo[] wlStats = new WakeLockInfo[1];
- wlStats[0] = createWakeLockInfo("WakeLock", 10, 1000);
-
- readKernelWakelockStats(staleStats, buffer, wlStats);
-
- assertEquals(1, staleStats.size());
-
- assertTrue(staleStats.containsKey("WakeLock"));
-
- KernelWakelockStats.Entry entry = staleStats.get("WakeLock");
- assertEquals(10, entry.mCount);
- assertEquals(1000, entry.mTotalTime);
- }
-
- @SmallTest
- public void testAggregateStatsBothKernelAndNativeWakelocks() throws Exception {
- KernelWakelockStats staleStats = new KernelWakelockStats();
-
- byte[] buffer = new ProcFileBuilder()
- .addLine("WakeLock1", 34, 123) // Milliseconds
- .getBytes();
- WakeLockInfo[] wlStats = new WakeLockInfo[1];
- wlStats[0] = createWakeLockInfo("WakeLock2", 10, 1000);
-
- readKernelWakelockStats(staleStats, buffer, wlStats);
-
- assertEquals(2, staleStats.size());
-
- assertTrue(staleStats.containsKey("WakeLock1"));
- KernelWakelockStats.Entry entry1 = staleStats.get("WakeLock1");
- assertEquals(34, entry1.mCount);
- assertEquals(123 * 1000, entry1.mTotalTime); // Microseconds
-
- assertTrue(staleStats.containsKey("WakeLock2"));
- KernelWakelockStats.Entry entry2 = staleStats.get("WakeLock2");
- assertEquals(10, entry2.mCount);
- assertEquals(1000, entry2.mTotalTime);
- }
-
- @SmallTest
- public void testAggregateStatsUpdate() throws Exception {
- KernelWakelockStats staleStats = new KernelWakelockStats();
-
- byte[] buffer = new ProcFileBuilder()
- .addLine("WakeLock1", 34, 123) // Milliseconds
- .addLine("WakeLock2", 46, 345) // Milliseconds
- .getBytes();
- WakeLockInfo[] wlStats = new WakeLockInfo[2];
- wlStats[0] = createWakeLockInfo("WakeLock3", 10, 1000);
- wlStats[1] = createWakeLockInfo("WakeLock4", 20, 2000);
-
- readKernelWakelockStats(staleStats, buffer, wlStats);
-
- assertEquals(4, staleStats.size());
-
- assertTrue(staleStats.containsKey("WakeLock1"));
- assertTrue(staleStats.containsKey("WakeLock2"));
- assertTrue(staleStats.containsKey("WakeLock3"));
- assertTrue(staleStats.containsKey("WakeLock4"));
-
- KernelWakelockStats.Entry entry1 = staleStats.get("WakeLock1");
- assertEquals(34, entry1.mCount);
- assertEquals(123 * 1000, entry1.mTotalTime); // Microseconds
-
- KernelWakelockStats.Entry entry2 = staleStats.get("WakeLock2");
- assertEquals(46, entry2.mCount);
- assertEquals(345 * 1000, entry2.mTotalTime); // Microseconds
-
- KernelWakelockStats.Entry entry3 = staleStats.get("WakeLock3");
- assertEquals(10, entry3.mCount);
- assertEquals(1000, entry3.mTotalTime);
-
- KernelWakelockStats.Entry entry4 = staleStats.get("WakeLock4");
- assertEquals(20, entry4.mCount);
- assertEquals(2000, entry4.mTotalTime);
-
- buffer = new ProcFileBuilder()
- .addLine("WakeLock1", 45, 789) // Milliseconds
- .addLine("WakeLock1", 56, 123) // Milliseconds
- .getBytes();
- wlStats = new WakeLockInfo[1];
- wlStats[0] = createWakeLockInfo("WakeLock4", 40, 4000);
-
- readKernelWakelockStats(staleStats, buffer, wlStats);
-
- assertEquals(2, staleStats.size());
-
- assertTrue(staleStats.containsKey("WakeLock1"));
- assertTrue(staleStats.containsKey("WakeLock4"));
-
- assertFalse(staleStats.containsKey("WakeLock2"));
- assertFalse(staleStats.containsKey("WakeLock3"));
-
- entry1 = staleStats.get("WakeLock1");
- assertEquals(45 + 56, entry1.mCount);
- assertEquals((789 + 123) * 1000, entry1.mTotalTime); // Microseconds
-
- entry2 = staleStats.get("WakeLock4");
- assertEquals(40, entry2.mCount);
- assertEquals(4000, entry4.mTotalTime);
+ assertEquals(2000 * 1000, entry.mTotalTime); // Micro seconds
}
}