Improve wake lock logging
- ACQ events should continue to be printed until their corresponding REL event is removed from the log
- the package name will be printed
Bug: 283254680
Test: atest WakeLockLogTest
Test: atest NotifierTest
Change-Id: Ibfdedc4213d6aa055aef40ba689fb466aef6498d
diff --git a/services/core/java/com/android/server/power/Notifier.java b/services/core/java/com/android/server/power/Notifier.java
index a694e31..3ecc985 100644
--- a/services/core/java/com/android/server/power/Notifier.java
+++ b/services/core/java/com/android/server/power/Notifier.java
@@ -222,7 +222,7 @@
mShowWirelessChargingAnimationConfig = context.getResources().getBoolean(
com.android.internal.R.bool.config_showBuiltinWirelessChargingAnim);
- mWakeLockLog = new WakeLockLog();
+ mWakeLockLog = new WakeLockLog(context);
// Initialize interactive state for battery stats.
try {
diff --git a/services/core/java/com/android/server/power/WakeLockLog.java b/services/core/java/com/android/server/power/WakeLockLog.java
index d20c7f1..d3486a4 100644
--- a/services/core/java/com/android/server/power/WakeLockLog.java
+++ b/services/core/java/com/android/server/power/WakeLockLog.java
@@ -16,20 +16,26 @@
package com.android.server.power;
+import android.content.Context;
+import android.content.pm.PackageManager;
import android.os.PowerManager;
import android.text.TextUtils;
import android.util.Slog;
+import android.util.SparseArray;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.BackgroundThread;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.ConcurrentModificationException;
import java.util.Date;
import java.util.Iterator;
+import java.util.List;
import java.util.NoSuchElementException;
+import java.util.Objects;
/**
* Simple Log for wake lock events. Optimized to reduce memory usage.
@@ -117,7 +123,7 @@
private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("MM-dd HH:mm:ss.SSS");
/**
- * Lock protects WakeLockLock.dump (binder thread) from conflicting with changes to the log
+ * Lock protects WakeLockLog.dump (binder thread) from conflicting with changes to the log
* happening on the background thread.
*/
private final Object mLock = new Object();
@@ -126,18 +132,20 @@
private final TheLog mLog;
private final TagDatabase mTagDatabase;
private final SimpleDateFormat mDumpsysDateFormat;
+ private final Context mContext;
- WakeLockLog() {
- this(new Injector());
+ WakeLockLog(Context context) {
+ this(new Injector(), context);
}
@VisibleForTesting
- WakeLockLog(Injector injector) {
+ WakeLockLog(Injector injector, Context context) {
mInjector = injector;
mTagDatabase = new TagDatabase(injector);
EntryByteTranslator translator = new EntryByteTranslator(mTagDatabase);
mLog = new TheLog(injector, translator, mTagDatabase);
mDumpsysDateFormat = injector.getDateFormat();
+ mContext = context;
}
/**
@@ -176,10 +184,24 @@
try {
synchronized (mLock) {
pw.println("Wake Lock Log");
- LogEntry tempEntry = new LogEntry(); // Temporary entry for the iterator to reuse.
- final Iterator<LogEntry> iterator = mLog.getAllItems(tempEntry);
int numEvents = 0;
int numResets = 0;
+ SparseArray<String[]> uidToPackagesCache = new SparseArray();
+
+ for (int i = 0; i < mLog.mSavedAcquisitions.size(); i++) {
+ numEvents++;
+ LogEntry entry = mLog.mSavedAcquisitions.get(i);
+
+ entry.updatePackageName(uidToPackagesCache, mContext.getPackageManager());
+
+ if (DEBUG) {
+ pw.print("Saved acquisition no. " + i);
+ }
+ entry.dump(pw, mDumpsysDateFormat);
+ }
+
+ LogEntry tempEntry = new LogEntry(); // Temporary entry for the iterator to reuse.
+ final Iterator<LogEntry> iterator = mLog.getAllItems(tempEntry);
while (iterator.hasNext()) {
String address = null;
if (DEBUG) {
@@ -192,6 +214,8 @@
numResets++;
} else {
numEvents++;
+ entry.updatePackageName(uidToPackagesCache,
+ mContext.getPackageManager());
if (DEBUG) {
pw.print(address);
}
@@ -381,6 +405,11 @@
*/
public int flags;
+ /**
+ * The name of the package that acquired the wake lock
+ */
+ public String packageName;
+
LogEntry() {}
LogEntry(long time, int type, TagData tag, int flags) {
@@ -438,8 +467,13 @@
}
sb.append(dateFormat.format(new Date(time)))
.append(" - ")
- .append(tag == null ? "---" : tag.ownerUid)
- .append(" - ")
+ .append(tag == null ? "---" : tag.ownerUid);
+ if (packageName != null) {
+ sb.append(" (");
+ sb.append(packageName);
+ sb.append(")");
+ }
+ sb.append(" - ")
.append(type == TYPE_ACQUIRE ? "ACQ" : "REL")
.append(" ")
.append(tag == null ? "UNKNOWN" : tag.tag);
@@ -463,6 +497,36 @@
sb.append(",system-wakelock");
}
}
+
+ /**
+ * Update the package name using the cache if available or the package manager.
+ * @param uidToPackagesCache The cache of package names
+ * @param packageManager The package manager
+ */
+ public void updatePackageName(SparseArray<String[]> uidToPackagesCache,
+ PackageManager packageManager) {
+ if (tag == null) {
+ return;
+ }
+
+ String[] packages;
+ if (uidToPackagesCache.contains(tag.ownerUid)) {
+ packages = uidToPackagesCache.get(tag.ownerUid);
+ } else {
+ packages = packageManager.getPackagesForUid(tag.ownerUid);
+ uidToPackagesCache.put(tag.ownerUid, packages);
+ }
+
+ if (packages != null && packages.length > 0) {
+ packageName = packages[0];
+ if (packages.length > 1) {
+ StringBuilder sb = new StringBuilder();
+ sb.append(packageName)
+ .append(",...");
+ packageName = sb.toString();
+ }
+ }
+ }
}
/**
@@ -744,6 +808,12 @@
private final TagDatabase mTagDatabase;
+ /**
+ * Wake lock acquisition events should continue to be printed until their corresponding
+ * release event is removed from the log.
+ */
+ private final List<LogEntry> mSavedAcquisitions;
+
TheLog(Injector injector, EntryByteTranslator translator, TagDatabase tagDatabase) {
final int logSize = Math.max(injector.getLogSize(), LOG_SIZE_MIN);
mBuffer = new byte[logSize];
@@ -758,6 +828,8 @@
removeTagIndex(index);
}
});
+
+ mSavedAcquisitions = new ArrayList();
}
/**
@@ -976,6 +1048,19 @@
// Copy the contents of the start of the buffer to our temporary buffer.
LogEntry entry = readEntryAt(mStart, mStartTime, null);
+ if (entry.type == TYPE_ACQUIRE) {
+ // We'll continue to print the event until the corresponding release event is also
+ // removed from the log.
+ mSavedAcquisitions.add(entry);
+ } else if (entry.type == TYPE_RELEASE) {
+ // We no longer need to print the corresponding acquire event.
+ for (int i = 0; i < mSavedAcquisitions.size(); i++) {
+ if (Objects.equals(mSavedAcquisitions.get(i).tag, entry.tag)) {
+ mSavedAcquisitions.remove(i);
+ break;
+ }
+ }
+ }
if (DEBUG) {
Slog.d(TAG, "Removing oldest item at @ " + mStart + ", found: " + entry);
}
diff --git a/services/tests/servicestests/src/com/android/server/power/WakeLockLogTest.java b/services/tests/servicestests/src/com/android/server/power/WakeLockLogTest.java
index a73fcb8..7af4b3d 100644
--- a/services/tests/servicestests/src/com/android/server/power/WakeLockLogTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/WakeLockLogTest.java
@@ -18,11 +18,18 @@
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.content.Context;
+import android.content.pm.PackageManager;
import android.os.PowerManager;
+import org.junit.Before;
import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
import java.io.PrintWriter;
import java.io.StringWriter;
@@ -34,12 +41,27 @@
*/
public class WakeLockLogTest {
+ @Mock
+ private Context mContext;
+
+ @Mock
+ private PackageManager mPackageManager;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ when(mContext.getPackageManager()).thenReturn(mPackageManager);
+
+ when(mPackageManager.getPackagesForUid(101)).thenReturn(new String[]{ "some.package1" });
+ when(mPackageManager.getPackagesForUid(102)).thenReturn(new String[]{ "some.package2" });
+ }
+
@Test
public void testAddTwoItems() {
final int tagDatabaseSize = 128;
final int logSize = 20;
TestInjector injectorSpy = spy(new TestInjector(tagDatabaseSize, logSize));
- WakeLockLog log = new WakeLockLog(injectorSpy);
+ WakeLockLog log = new WakeLockLog(injectorSpy, mContext);
when(injectorSpy.currentTimeMillis()).thenReturn(1000L);
log.onWakeLockAcquired("TagPartial", 101,
@@ -50,8 +72,10 @@
PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP);
assertEquals("Wake Lock Log\n"
- + " 01-01 00:00:01.000 - 101 - ACQ TagPartial (partial,on-after-release)\n"
- + " 01-01 00:00:01.150 - 102 - ACQ TagFull (full,acq-causes-wake)\n"
+ + " 01-01 00:00:01.000 - 101 (some.package1) - ACQ TagPartial "
+ + "(partial,on-after-release)\n"
+ + " 01-01 00:00:01.150 - 102 (some.package2) - ACQ TagFull "
+ + "(full,acq-causes-wake)\n"
+ " -\n"
+ " Events: 2, Time-Resets: 0\n"
+ " Buffer, Bytes used: 6\n",
@@ -63,7 +87,7 @@
final int tagDatabaseSize = 128;
final int logSize = 20;
TestInjector injectorSpy = spy(new TestInjector(tagDatabaseSize, logSize));
- WakeLockLog log = new WakeLockLog(injectorSpy);
+ WakeLockLog log = new WakeLockLog(injectorSpy, mContext);
when(injectorSpy.currentTimeMillis()).thenReturn(1000L);
log.onWakeLockAcquired("TagPartial", 101, PowerManager.PARTIAL_WAKE_LOCK);
@@ -72,8 +96,8 @@
log.onWakeLockAcquired("TagFull", 102, PowerManager.FULL_WAKE_LOCK);
assertEquals("Wake Lock Log\n"
- + " 01-01 00:00:01.000 - 101 - ACQ TagPartial (partial)\n"
- + " 01-01 00:00:01.350 - 102 - ACQ TagFull (full)\n"
+ + " 01-01 00:00:01.000 - 101 (some.package1) - ACQ TagPartial (partial)\n"
+ + " 01-01 00:00:01.350 - 102 (some.package2) - ACQ TagFull (full)\n"
+ " -\n"
+ " Events: 2, Time-Resets: 1\n"
+ " Buffer, Bytes used: 15\n",
@@ -85,7 +109,7 @@
final int tagDatabaseSize = 2;
final int logSize = 20;
TestInjector injectorSpy = spy(new TestInjector(tagDatabaseSize, logSize));
- WakeLockLog log = new WakeLockLog(injectorSpy);
+ WakeLockLog log = new WakeLockLog(injectorSpy, mContext);
when(injectorSpy.currentTimeMillis()).thenReturn(1000L);
log.onWakeLockAcquired("TagPartial", 101, PowerManager.PARTIAL_WAKE_LOCK);
@@ -95,7 +119,7 @@
assertEquals("Wake Lock Log\n"
+ " 01-01 00:00:01.000 - --- - ACQ UNKNOWN (partial)\n"
- + " 01-01 00:00:01.150 - 102 - ACQ TagFull (full)\n"
+ + " 01-01 00:00:01.150 - 102 (some.package2) - ACQ TagFull (full)\n"
+ " -\n"
+ " Events: 2, Time-Resets: 0\n"
+ " Buffer, Bytes used: 6\n",
@@ -107,26 +131,55 @@
final int tagDatabaseSize = 6;
final int logSize = 10;
TestInjector injectorSpy = spy(new TestInjector(tagDatabaseSize, logSize));
- WakeLockLog log = new WakeLockLog(injectorSpy);
+ WakeLockLog log = new WakeLockLog(injectorSpy, mContext);
- // This first item will get deleted when ring buffer loops around
+ // Wake lock 1 acquired - log size = 3
when(injectorSpy.currentTimeMillis()).thenReturn(1000L);
log.onWakeLockAcquired("TagPartial", 101, PowerManager.PARTIAL_WAKE_LOCK);
+ // Wake lock 2 acquired - log size = 3 + 3 = 6
when(injectorSpy.currentTimeMillis()).thenReturn(1150L);
log.onWakeLockAcquired("TagFull", 102, PowerManager.FULL_WAKE_LOCK);
+
+ // Wake lock 3 acquired - log size = 6 + 3 = 9
when(injectorSpy.currentTimeMillis()).thenReturn(1151L);
log.onWakeLockAcquired("TagThree", 101, PowerManager.PARTIAL_WAKE_LOCK);
+
+ // We need more space - wake lock 1 acquisition is removed from the log and saved in the
+ // list. Log size = 9 - 3 + 2 = 8
when(injectorSpy.currentTimeMillis()).thenReturn(1152L);
+ log.onWakeLockReleased("TagThree", 101);
+
+ // We need more space - wake lock 2 acquisition is removed from the log and saved in the
+ // list. Log size = 8 - 3 + 2 = 7
+ when(injectorSpy.currentTimeMillis()).thenReturn(1153L);
+ log.onWakeLockReleased("TagPartial", 101);
+
+ // We need more space - wake lock 3 acquisition is removed from the log and saved in the
+ // list. Log size = 7 - 3 + 3 = 7
+ when(injectorSpy.currentTimeMillis()).thenReturn(1154L);
log.onWakeLockAcquired("TagFour", 101, PowerManager.PARTIAL_WAKE_LOCK);
+ // We need more space - wake lock 3 release is removed from the log and wake lock 3
+ // acquisition is removed from the list. Log size = 7 - 2 + 3 = 8
+ when(injectorSpy.currentTimeMillis()).thenReturn(1155L);
+ log.onWakeLockAcquired("TagFive", 101, PowerManager.PARTIAL_WAKE_LOCK);
+
+ // We need more space - wake lock 1 release is removed from the log and wake lock 1
+ // acquisition is removed from the list. Log size = 8 - 2 + 2 = 8
+ when(injectorSpy.currentTimeMillis()).thenReturn(1156L);
+ log.onWakeLockReleased("TagFull", 102);
+
+ // Wake lock 2 acquisition is still printed because its release have not rolled off the log
+ // yet.
assertEquals("Wake Lock Log\n"
- + " 01-01 00:00:01.150 - 102 - ACQ TagFull (full)\n"
- + " 01-01 00:00:01.151 - 101 - ACQ TagThree (partial)\n"
- + " 01-01 00:00:01.152 - 101 - ACQ TagFour (partial)\n"
+ + " 01-01 00:00:01.150 - 102 (some.package2) - ACQ TagFull (full)\n"
+ + " 01-01 00:00:01.154 - 101 (some.package1) - ACQ TagFour (partial)\n"
+ + " 01-01 00:00:01.155 - 101 (some.package1) - ACQ TagFive (partial)\n"
+ + " 01-01 00:00:01.156 - 102 (some.package2) - REL TagFull\n"
+ " -\n"
- + " Events: 3, Time-Resets: 0\n"
- + " Buffer, Bytes used: 9\n",
+ + " Events: 4, Time-Resets: 0\n"
+ + " Buffer, Bytes used: 8\n",
dumpLog(log, false));
}
@@ -135,7 +188,7 @@
final int tagDatabaseSize = 6;
final int logSize = 10;
TestInjector injectorSpy = spy(new TestInjector(tagDatabaseSize, logSize));
- WakeLockLog log = new WakeLockLog(injectorSpy);
+ WakeLockLog log = new WakeLockLog(injectorSpy, mContext);
// Bad tag means it wont get written
when(injectorSpy.currentTimeMillis()).thenReturn(1000L);
@@ -153,14 +206,15 @@
final int tagDatabaseSize = 6;
final int logSize = 10;
TestInjector injectorSpy = spy(new TestInjector(tagDatabaseSize, logSize));
- WakeLockLog log = new WakeLockLog(injectorSpy);
+ WakeLockLog log = new WakeLockLog(injectorSpy, mContext);
when(injectorSpy.currentTimeMillis()).thenReturn(1000L);
log.onWakeLockAcquired("*job*/com.one.two.3hree/.one..Last", 101,
PowerManager.PARTIAL_WAKE_LOCK);
assertEquals("Wake Lock Log\n"
- + " 01-01 00:00:01.000 - 101 - ACQ *job*/c.o.t.3/.o..Last (partial)\n"
+ + " 01-01 00:00:01.000 - 101 (some.package1) - ACQ "
+ + "*job*/c.o.t.3/.o..Last (partial)\n"
+ " -\n"
+ " Events: 1, Time-Resets: 0\n"
+ " Buffer, Bytes used: 3\n",
@@ -172,7 +226,7 @@
final int tagDatabaseSize = 6;
final int logSize = 10;
TestInjector injectorSpy = spy(new TestInjector(tagDatabaseSize, logSize));
- WakeLockLog log = new WakeLockLog(injectorSpy);
+ WakeLockLog log = new WakeLockLog(injectorSpy, mContext);
when(injectorSpy.currentTimeMillis()).thenReturn(1000L);
log.onWakeLockAcquired("HowdyTag", 101, PowerManager.PARTIAL_WAKE_LOCK);
@@ -180,8 +234,8 @@
log.onWakeLockReleased("HowdyTag", 101);
assertEquals("Wake Lock Log\n"
- + " 01-01 00:00:01.000 - 101 - ACQ HowdyTag (partial)\n"
- + " 01-01 00:00:01.001 - 101 - REL HowdyTag\n"
+ + " 01-01 00:00:01.000 - 101 (some.package1) - ACQ HowdyTag (partial)\n"
+ + " 01-01 00:00:01.001 - 101 (some.package1) - REL HowdyTag\n"
+ " -\n"
+ " Events: 2, Time-Resets: 0\n"
+ " Buffer, Bytes used: 5\n"
@@ -194,7 +248,7 @@
final int tagDatabaseSize = 6;
final int logSize = 10;
TestInjector injectorSpy = spy(new TestInjector(tagDatabaseSize, logSize));
- WakeLockLog log = new WakeLockLog(injectorSpy);
+ WakeLockLog log = new WakeLockLog(injectorSpy, mContext);
when(injectorSpy.currentTimeMillis()).thenReturn(1100L);
log.onWakeLockAcquired("HowdyTag", 101, PowerManager.PARTIAL_WAKE_LOCK);
@@ -204,7 +258,7 @@
log.onWakeLockReleased("HowdyTag", 101);
assertEquals("Wake Lock Log\n"
- + " 01-01 00:00:01.100 - 101 - ACQ HowdyTag (partial)\n"
+ + " 01-01 00:00:01.100 - 101 (some.package1) - ACQ HowdyTag (partial)\n"
+ " -\n"
+ " Events: 1, Time-Resets: 0\n"
+ " Buffer, Bytes used: 3\n",
@@ -216,20 +270,153 @@
final int tagDatabaseSize = 6;
final int logSize = 10;
TestInjector injectorSpy = spy(new TestInjector(tagDatabaseSize, logSize));
- WakeLockLog log = new WakeLockLog(injectorSpy);
+ WakeLockLog log = new WakeLockLog(injectorSpy, mContext);
when(injectorSpy.currentTimeMillis()).thenReturn(1000L);
log.onWakeLockAcquired("TagPartial", 101,
PowerManager.PARTIAL_WAKE_LOCK | PowerManager.SYSTEM_WAKELOCK);
assertEquals("Wake Lock Log\n"
- + " 01-01 00:00:01.000 - 101 - ACQ TagPartial (partial,system-wakelock)\n"
+ + " 01-01 00:00:01.000 - 101 (some.package1) - ACQ TagPartial "
+ + "(partial,system-wakelock)\n"
+ " -\n"
+ " Events: 1, Time-Resets: 0\n"
+ " Buffer, Bytes used: 3\n",
dumpLog(log, false));
}
+ @Test
+ public void testAddItemWithNoPackageName() {
+ final int tagDatabaseSize = 128;
+ final int logSize = 20;
+ TestInjector injectorSpy = spy(new TestInjector(tagDatabaseSize, logSize));
+ WakeLockLog log = new WakeLockLog(injectorSpy, mContext);
+
+ when(mPackageManager.getPackagesForUid(101)).thenReturn(null);
+ when(injectorSpy.currentTimeMillis()).thenReturn(1000L);
+ log.onWakeLockAcquired("TagPartial", 101,
+ PowerManager.PARTIAL_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE);
+
+ assertEquals("Wake Lock Log\n"
+ + " 01-01 00:00:01.000 - 101 - ACQ TagPartial "
+ + "(partial,on-after-release)\n"
+ + " -\n"
+ + " Events: 1, Time-Resets: 0\n"
+ + " Buffer, Bytes used: 3\n",
+ dumpLog(log, false));
+ }
+
+ @Test
+ public void testAddItemWithMultiplePackageNames() {
+ final int tagDatabaseSize = 128;
+ final int logSize = 20;
+ TestInjector injectorSpy = spy(new TestInjector(tagDatabaseSize, logSize));
+ WakeLockLog log = new WakeLockLog(injectorSpy, mContext);
+
+ when(mPackageManager.getPackagesForUid(101)).thenReturn(
+ new String[]{ "some.package1", "some.package2", "some.package3" });
+
+ when(injectorSpy.currentTimeMillis()).thenReturn(1000L);
+ log.onWakeLockAcquired("TagPartial", 101,
+ PowerManager.PARTIAL_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE);
+
+ assertEquals("Wake Lock Log\n"
+ + " 01-01 00:00:01.000 - 101 (some.package1,...) - ACQ TagPartial "
+ + "(partial,on-after-release)\n"
+ + " -\n"
+ + " Events: 1, Time-Resets: 0\n"
+ + " Buffer, Bytes used: 3\n",
+ dumpLog(log, false));
+ }
+
+ @Test
+ public void testAddItemsWithRepeatOwnerUid_UsesCache() {
+ final int tagDatabaseSize = 128;
+ final int logSize = 20;
+ TestInjector injectorSpy = spy(new TestInjector(tagDatabaseSize, logSize));
+ WakeLockLog log = new WakeLockLog(injectorSpy, mContext);
+
+ when(injectorSpy.currentTimeMillis()).thenReturn(1000L);
+ log.onWakeLockAcquired("TagPartial", 101,
+ PowerManager.PARTIAL_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE);
+
+ when(injectorSpy.currentTimeMillis()).thenReturn(1150L);
+ log.onWakeLockAcquired("TagFull", 101,
+ PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP);
+
+ when(injectorSpy.currentTimeMillis()).thenReturn(1151L);
+ log.onWakeLockAcquired("TagFull2", 101,
+ PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP);
+
+ assertEquals("Wake Lock Log\n"
+ + " 01-01 00:00:01.000 - 101 (some.package1) - ACQ TagPartial "
+ + "(partial,on-after-release)\n"
+ + " 01-01 00:00:01.150 - 101 (some.package1) - ACQ TagFull "
+ + "(full,acq-causes-wake)\n"
+ + " 01-01 00:00:01.151 - 101 (some.package1) - ACQ TagFull2 "
+ + "(full,acq-causes-wake)\n"
+ + " -\n"
+ + " Events: 3, Time-Resets: 0\n"
+ + " Buffer, Bytes used: 9\n",
+ dumpLog(log, false));
+
+ verify(mPackageManager, times(1)).getPackagesForUid(101);
+ }
+
+ @Test
+ public void testAddItemsWithRepeatOwnerUid_SavedAcquisitions_UsesCache() {
+ final int tagDatabaseSize = 128;
+ final int logSize = 10;
+ TestInjector injectorSpy = spy(new TestInjector(tagDatabaseSize, logSize));
+ WakeLockLog log = new WakeLockLog(injectorSpy, mContext);
+
+ when(injectorSpy.currentTimeMillis()).thenReturn(1000L);
+ log.onWakeLockAcquired("TagPartial", 101,
+ PowerManager.PARTIAL_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE);
+
+ when(injectorSpy.currentTimeMillis()).thenReturn(1150L);
+ log.onWakeLockAcquired("TagFull", 101,
+ PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP);
+
+ when(injectorSpy.currentTimeMillis()).thenReturn(1151L);
+ log.onWakeLockAcquired("TagFull2", 101,
+ PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP);
+
+ when(injectorSpy.currentTimeMillis()).thenReturn(1152L);
+ log.onWakeLockAcquired("TagFull3", 101,
+ PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP);
+
+ when(injectorSpy.currentTimeMillis()).thenReturn(1153L);
+ log.onWakeLockAcquired("TagFull4", 101,
+ PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP);
+
+ when(injectorSpy.currentTimeMillis()).thenReturn(1154L);
+ log.onWakeLockAcquired("TagFull5", 101,
+ PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP);
+
+ // The first 3 events have been removed from the log and they exist in the saved
+ // acquisitions list. They should also use the cache when fetching the package names.
+ assertEquals("Wake Lock Log\n"
+ + " 01-01 00:00:01.000 - 101 (some.package1) - ACQ TagPartial "
+ + "(partial,on-after-release)\n"
+ + " 01-01 00:00:01.150 - 101 (some.package1) - ACQ TagFull "
+ + "(full,acq-causes-wake)\n"
+ + " 01-01 00:00:01.151 - 101 (some.package1) - ACQ TagFull2 "
+ + "(full,acq-causes-wake)\n"
+ + " 01-01 00:00:01.152 - 101 (some.package1) - ACQ TagFull3 "
+ + "(full,acq-causes-wake)\n"
+ + " 01-01 00:00:01.153 - 101 (some.package1) - ACQ TagFull4 "
+ + "(full,acq-causes-wake)\n"
+ + " 01-01 00:00:01.154 - 101 (some.package1) - ACQ TagFull5 "
+ + "(full,acq-causes-wake)\n"
+ + " -\n"
+ + " Events: 6, Time-Resets: 0\n"
+ + " Buffer, Bytes used: 9\n",
+ dumpLog(log, false));
+
+ verify(mPackageManager, times(1)).getPackagesForUid(101);
+ }
+
private String dumpLog(WakeLockLog log, boolean includeTagDb) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);