Purge StoreWriteQueue items to avoid system health issues
If queue gets too deep we may run out of memory or cause other
system health issues.
Test: TaskSnapshotPersisterLoaderTest
Bug: 38416992
Bug: 37631016
Change-Id: I725c9a458f78af2e625f2451bb0030176035f596
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotPersister.java b/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
index 866bfc0..297e288 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
@@ -39,6 +39,7 @@
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayDeque;
+import java.util.ArrayList;
/**
* Persists {@link TaskSnapshot}s to disk.
@@ -55,10 +56,13 @@
private static final int QUALITY = 95;
private static final String PROTO_EXTENSION = ".proto";
private static final String BITMAP_EXTENSION = ".jpg";
+ private static final int MAX_STORE_QUEUE_DEPTH = 2;
@GuardedBy("mLock")
private final ArrayDeque<WriteQueueItem> mWriteQueue = new ArrayDeque<>();
@GuardedBy("mLock")
+ private final ArrayDeque<StoreWriteQueueItem> mStoreQueueItems = new ArrayDeque<>();
+ @GuardedBy("mLock")
private boolean mQueueIdling;
@GuardedBy("mLock")
private boolean mPaused;
@@ -153,11 +157,22 @@
@GuardedBy("mLock")
private void sendToQueueLocked(WriteQueueItem item) {
mWriteQueue.offer(item);
+ item.onQueuedLocked();
+ ensureStoreQueueDepthLocked();
if (!mPaused) {
mLock.notifyAll();
}
}
+ @GuardedBy("mLock")
+ private void ensureStoreQueueDepthLocked() {
+ while (mStoreQueueItems.size() > MAX_STORE_QUEUE_DEPTH) {
+ final StoreWriteQueueItem item = mStoreQueueItems.poll();
+ mWriteQueue.remove(item);
+ Slog.i(TAG, "Queue is too deep! Purged item with taskid=" + item.mTaskId);
+ }
+ }
+
private File getDirectory(int userId) {
return new File(mDirectoryResolver.getSystemDirectoryForUser(userId), SNAPSHOTS_DIRNAME);
}
@@ -202,6 +217,9 @@
next = null;
} else {
next = mWriteQueue.poll();
+ if (next != null) {
+ next.onDequeuedLocked();
+ }
}
}
if (next != null) {
@@ -226,6 +244,18 @@
private abstract class WriteQueueItem {
abstract void write();
+
+ /**
+ * Called when this queue item has been put into the queue.
+ */
+ void onQueuedLocked() {
+ }
+
+ /**
+ * Called when this queue item has been taken out of the queue.
+ */
+ void onDequeuedLocked() {
+ }
}
private class StoreWriteQueueItem extends WriteQueueItem {
@@ -240,6 +270,16 @@
}
@Override
+ void onQueuedLocked() {
+ mStoreQueueItems.offer(this);
+ }
+
+ @Override
+ void onDequeuedLocked() {
+ mStoreQueueItems.remove(this);
+ }
+
+ @Override
void write() {
if (!createDirectory(mUserId)) {
Slog.e(TAG, "Unable to create snapshot directory for user dir="