diff --git a/core/java/com/android/internal/os/KernelWakelockReader.java b/core/java/com/android/internal/os/KernelWakelockReader.java index d53fadacb609f..e09e0e609380e 100644 --- a/core/java/com/android/internal/os/KernelWakelockReader.java +++ b/core/java/com/android/internal/os/KernelWakelockReader.java @@ -76,28 +76,13 @@ public class KernelWakelockReader { boolean useSystemSuspend = (new File(sSysClassWakeupDir)).exists(); if (useSystemSuspend) { - WakeLockInfo[] wlStats = null; - 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); - return null; - } - } - - try { - wlStats = mSuspendControlService.getWakeLockStats(); - updateVersion(staleStats); - updateWakelockStats(wlStats, staleStats); - } catch (RemoteException e) { - Slog.wtf(TAG, "Failed to obtain wakelock stats from ISuspendControlService", e); + // Get both kernel and native wakelock stats from SystemSuspend + updateVersion(staleStats); + if (getWakelockStatsFromSystemSuspend(staleStats) == null) { + Slog.w(TAG, "Failed to get wakelock stats from SystemSuspend"); return null; } - return removeOldStats(staleStats); - } else { byte[] buffer = new byte[32*1024]; int len = 0; @@ -153,11 +138,43 @@ public class KernelWakelockReader { } updateVersion(staleStats); + // Get native wakelock stats from SystemSuspend + if (getWakelockStatsFromSystemSuspend(staleStats) == null) { + Slog.w(TAG, "Failed to get Native wakelock stats from SystemSuspend"); + } + // Get kernel wakelock stats parseProcWakelocks(buffer, len, wakeup_sources, staleStats); return removeOldStats(staleStats); } } + /** + * On success, returns the updated stats from SystemSupend, else returns null. + */ + private KernelWakelockStats getWakelockStatsFromSystemSuspend( + final KernelWakelockStats staleStats) { + WakeLockInfo[] wlStats = null; + 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); + return null; + } + } + + try { + wlStats = mSuspendControlService.getWakeLockStats(); + updateWakelockStats(wlStats, staleStats); + } catch (RemoteException e) { + Slog.wtf(TAG, "Failed to obtain wakelock stats from ISuspendControlService", e); + return null; + } + + return staleStats; + } + /** * Updates statleStats with stats from SystemSuspend. * @param staleStats Existing object to update. 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 a93573724ba19..dc9208de7198f 100644 --- a/core/tests/coretests/src/com/android/internal/os/KernelWakelockReaderTest.java +++ b/core/tests/coretests/src/com/android/internal/os/KernelWakelockReaderTest.java @@ -268,4 +268,144 @@ public class KernelWakelockReaderTest extends TestCase { assertEquals(20, entry.mCount); assertEquals(2000 * 1000, entry.mTotalTime); // Micro seconds } + +// -------------------- 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); // Milliseconds + + readKernelWakelockStats(staleStats, buffer, wlStats); + + assertEquals(1, staleStats.size()); + + assertTrue(staleStats.containsKey("WakeLock")); + + KernelWakelockStats.Entry entry = staleStats.get("WakeLock"); + assertEquals(10, entry.mCount); + assertEquals(1000 * 1000, entry.mTotalTime); // Microseconds + } + + @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); // Milliseconds + + 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 * 1000, entry2.mTotalTime); // Microseconds + } + + @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); // Milliseconds + wlStats[1] = createWakeLockInfo("WakeLock4", 20, 2000); // Milliseconds + + 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 * 1000, entry3.mTotalTime); // Microseconds + + KernelWakelockStats.Entry entry4 = staleStats.get("WakeLock4"); + assertEquals(20, entry4.mCount); + assertEquals(2000 * 1000, entry4.mTotalTime); // Microseconds + + buffer = new ProcFileBuilder() + .addLine("WakeLock1", 45, 789) // Milliseconds + .addLine("WakeLock1", 56, 123) // Milliseconds + .getBytes(); + wlStats = new WakeLockInfo[1]; + wlStats[0] = createWakeLockInfo("WakeLock4", 40, 4000); // Milliseconds + + 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 * 1000, entry4.mTotalTime); // Microseconds + } }