summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Jorim Jaggi <jjaggi@google.com> 2017-05-12 15:40:43 +0200
committer Jorim Jaggi <jjaggi@google.com> 2017-05-13 12:33:59 +0200
commit44f4bcb80df76608d4db048aacc27760472d6a2d (patch)
tree5032bfbb75e88f6bfa5a7f7b93770f38aafeb1ed
parentd70695ee34611bee420d901ac9e6470d8c211519 (diff)
Fix recents entry delay
- Start loading things after we drew our first frame. - Don't load high res task until low res tasks have been loaded: In case the snapshot is already in cache in system_server the low-res task loader will load the full res snapshot, leading to GC pressure due to registerNativeAlloc. Now, if both task loader load the same snapshot at the same time we are very likely to trigger a blocking GC alloc. Test: Open recents, look at systrace Change-Id: I10c263dc8929742611ad9fbb32f65bc8ac3100bd Fixes: 36851903 Bug: 32668632
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/model/HighResThumbnailLoader.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java31
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/recents/model/HighResThumbnailLoaderTest.java6
4 files changed, 45 insertions, 10 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index 7bc591f4832a..c0e4b99b856e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -222,6 +222,10 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD
getApplicationContext()).onActionEnd(
LatencyTracker.ACTION_TOGGLE_RECENTS));
}
+ DejankUtils.postAfterTraversal(() -> {
+ Recents.getTaskLoader().startLoader(RecentsActivity.this);
+ Recents.getTaskLoader().getHighResThumbnailLoader().setVisible(true);
+ });
return true;
}
};
@@ -376,8 +380,6 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD
// Notify of the next draw
mRecentsView.getViewTreeObserver().addOnPreDrawListener(mRecentsDrawnEventListener);
-
- Recents.getTaskLoader().getHighResThumbnailLoader().setVisible(true);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/HighResThumbnailLoader.java b/packages/SystemUI/src/com/android/systemui/recents/model/HighResThumbnailLoader.java
index be8da9f38478..974139ad8670 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/HighResThumbnailLoader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/HighResThumbnailLoader.java
@@ -50,6 +50,7 @@ public class HighResThumbnailLoader implements TaskCallbacks {
private boolean mLoading;
private boolean mVisible;
private boolean mFlingingFast;
+ private boolean mTaskLoadQueueIdle;
public HighResThumbnailLoader(SystemServicesProxy ssp, Looper looper) {
mMainThreadHandler = new Handler(looper);
@@ -71,13 +72,22 @@ public class HighResThumbnailLoader implements TaskCallbacks {
updateLoading();
}
+ /**
+ * Sets whether the other task load queue is idling. Avoid double-loading bitmaps by not
+ * starting this queue until the other queue is idling.
+ */
+ public void setTaskLoadQueueIdle(boolean idle) {
+ mTaskLoadQueueIdle = idle;
+ updateLoading();
+ }
+
@VisibleForTesting
boolean isLoading() {
return mLoading;
}
private void updateLoading() {
- setLoading(mVisible && !mFlingingFast);
+ setLoading(mVisible && !mFlingingFast && mTaskLoadQueueIdle);
}
private void setLoading(boolean loading) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
index 802cb8315484..97a9659c70fb 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
@@ -48,6 +48,7 @@ import java.util.concurrent.ConcurrentLinkedQueue;
* A Task load queue
*/
class TaskResourceLoadQueue {
+
ConcurrentLinkedQueue<Task> mQueue = new ConcurrentLinkedQueue<Task>();
/** Adds a new task to the load queue */
@@ -104,15 +105,18 @@ class BackgroundTaskLoader implements Runnable {
boolean mCancelled;
boolean mWaitingOnLoadQueue;
+ private final OnIdleChangedListener mOnIdleChangedListener;
+
/** Constructor, creates a new loading thread that loads task resources in the background */
public BackgroundTaskLoader(TaskResourceLoadQueue loadQueue,
TaskKeyLruCache<Drawable> iconCache, Bitmap defaultThumbnail,
- BitmapDrawable defaultIcon) {
+ BitmapDrawable defaultIcon, OnIdleChangedListener onIdleChangedListener) {
mLoadQueue = loadQueue;
mIconCache = iconCache;
mDefaultThumbnail = defaultThumbnail;
mDefaultIcon = defaultIcon;
mMainThreadHandler = new Handler();
+ mOnIdleChangedListener = onIdleChangedListener;
mLoadThread = new HandlerThread("Recents-TaskResourceLoader",
android.os.Process.THREAD_PRIORITY_BACKGROUND);
mLoadThread.start();
@@ -169,7 +173,11 @@ class BackgroundTaskLoader implements Runnable {
synchronized(mLoadQueue) {
try {
mWaitingOnLoadQueue = true;
+ mMainThreadHandler.post(
+ () -> mOnIdleChangedListener.onIdleChanged(true));
mLoadQueue.wait();
+ mMainThreadHandler.post(
+ () -> mOnIdleChangedListener.onIdleChanged(false));
mWaitingOnLoadQueue = false;
} catch (InterruptedException ie) {
ie.printStackTrace();
@@ -230,6 +238,10 @@ class BackgroundTaskLoader implements Runnable {
}
}
}
+
+ interface OnIdleChangedListener {
+ void onIdleChanged(boolean idle);
+ }
}
/**
@@ -298,15 +310,16 @@ public class RecentsTaskLoader {
// Initialize the proxy, cache and loaders
int numRecentTasks = ActivityManager.getMaxRecentTasksStatic();
+ mHighResThumbnailLoader = new HighResThumbnailLoader(Recents.getSystemServices(),
+ Looper.getMainLooper());
mLoadQueue = new TaskResourceLoadQueue();
mIconCache = new TaskKeyLruCache<>(iconCacheSize, mClearActivityInfoOnEviction);
mActivityLabelCache = new TaskKeyLruCache<>(numRecentTasks, mClearActivityInfoOnEviction);
mContentDescriptionCache = new TaskKeyLruCache<>(numRecentTasks,
mClearActivityInfoOnEviction);
mActivityInfoCache = new LruCache(numRecentTasks);
- mLoader = new BackgroundTaskLoader(mLoadQueue, mIconCache, mDefaultThumbnail, mDefaultIcon);
- mHighResThumbnailLoader = new HighResThumbnailLoader(Recents.getSystemServices(),
- Looper.getMainLooper());
+ mLoader = new BackgroundTaskLoader(mLoadQueue, mIconCache, mDefaultThumbnail, mDefaultIcon,
+ mHighResThumbnailLoader::setTaskLoadQueueIdle);
}
/** Returns the size of the app icon cache. */
@@ -360,9 +373,6 @@ public class RecentsTaskLoader {
mTempCache.evictAll();
if (!opts.onlyLoadForCache) {
mNumVisibleTasksLoaded = opts.numVisibleTasks;
-
- // Start the loader
- mLoader.start(context);
}
}
@@ -608,6 +618,13 @@ public class RecentsTaskLoader {
}
/**
+ * Starts loading tasks.
+ */
+ public void startLoader(Context ctx) {
+ mLoader.start(ctx);
+ }
+
+ /**
* Stops the task loader and clears all queued, pending task loads.
*/
private void stopLoader() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/recents/model/HighResThumbnailLoaderTest.java b/packages/SystemUI/tests/src/com/android/systemui/recents/model/HighResThumbnailLoaderTest.java
index 4d632af4c935..f57b6b361467 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/recents/model/HighResThumbnailLoaderTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/recents/model/HighResThumbnailLoaderTest.java
@@ -62,6 +62,7 @@ public class HighResThumbnailLoaderTest extends SysuiTestCase {
when(mMockSystemServicesProxy.getTaskThumbnail(anyInt(), anyBoolean()))
.thenReturn(mThumbnailData);
mLoader.setVisible(true);
+ mLoader.setTaskLoadQueueIdle(true);
}
@Test
@@ -75,6 +76,11 @@ public class HighResThumbnailLoaderTest extends SysuiTestCase {
assertFalse(mLoader.isLoading());
mLoader.setFlingingFast(false);
assertTrue(mLoader.isLoading());
+ mLoader.setFlingingFast(false);
+ mLoader.setTaskLoadQueueIdle(false);
+ assertFalse(mLoader.isLoading());
+ mLoader.setTaskLoadQueueIdle(true);
+ assertTrue(mLoader.isLoading());
}
@Test