From 44f4bcb80df76608d4db048aacc27760472d6a2d Mon Sep 17 00:00:00 2001 From: Jorim Jaggi Date: Fri, 12 May 2017 15:40:43 +0200 Subject: [PATCH 1/2] 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 --- .../systemui/recents/RecentsActivity.java | 6 ++-- .../recents/model/HighResThumbnailLoader.java | 12 ++++++- .../recents/model/RecentsTaskLoader.java | 31 ++++++++++++++----- .../model/HighResThumbnailLoaderTest.java | 6 ++++ 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 7bc591f4832a8..c0e4b99b856ec 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 be8da9f384781..974139ad86701 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 802cb83154845..97a9659c70fb2 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 mQueue = new ConcurrentLinkedQueue(); /** 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 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); } } @@ -607,6 +617,13 @@ public class RecentsTaskLoader { return activityInfo; } + /** + * Starts loading tasks. + */ + public void startLoader(Context ctx) { + mLoader.start(ctx); + } + /** * Stops the task loader and clears all queued, pending task loads. */ 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 4d632af4c9354..f57b6b3614675 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 From ddb449efd9671f4c89470d645acd0b84e6a6ff15 Mon Sep 17 00:00:00 2001 From: Jorim Jaggi Date: Fri, 12 May 2017 16:32:58 +0200 Subject: [PATCH 2/2] Get rid of a lot of binder calls Lead to delays when entering recents. Test: Open recents Bug: 32668632 Change-Id: I7b5504d0c11208d9c4d55de2eace6407d186f25c --- .../android/systemui/RecentsComponent.java | 2 +- .../com/android/systemui/recents/Recents.java | 4 +- .../recents/misc/SystemServicesProxy.java | 39 ++++++++++++------- .../recents/model/RecentsTaskLoadPlan.java | 3 +- .../systemui/stackdivider/DividerView.java | 2 +- 5 files changed, 31 insertions(+), 19 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/RecentsComponent.java b/packages/SystemUI/src/com/android/systemui/RecentsComponent.java index 9b74cd62d06b6..cdad8aedff211 100644 --- a/packages/SystemUI/src/com/android/systemui/RecentsComponent.java +++ b/packages/SystemUI/src/com/android/systemui/RecentsComponent.java @@ -23,7 +23,7 @@ import android.view.View; public interface RecentsComponent { void showRecentApps(boolean triggeredFromAltTab, boolean fromHome); void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHomeKey); - void toggleRecents(Display display); + void toggleRecents(); void preloadRecents(); void showNextAffiliatedTask(); void showPrevAffiliatedTask(); diff --git a/packages/SystemUI/src/com/android/systemui/recents/Recents.java b/packages/SystemUI/src/com/android/systemui/recents/Recents.java index d3bd89ff2e471..72dd2da1d3abe 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/Recents.java +++ b/packages/SystemUI/src/com/android/systemui/recents/Recents.java @@ -324,14 +324,14 @@ public class Recents extends SystemUI @Override public void toggleRecentApps() { - toggleRecents(mContext.getSystemService(WindowManager.class).getDefaultDisplay()); + toggleRecents(); } /** * Toggles the Recents activity. */ @Override - public void toggleRecents(Display display) { + public void toggleRecents() { // Ensure the device has been provisioned before allowing the user to interact with // recents if (!isUserSetup()) { diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java index f431517cfe77d..8594ec629dfda 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java +++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java @@ -27,6 +27,7 @@ import static android.provider.Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDO import android.annotation.NonNull; import android.app.ActivityManager; +import android.app.ActivityManager.StackInfo; import android.app.ActivityManager.TaskSnapshot; import android.app.ActivityOptions; import android.app.AppGlobals; @@ -95,6 +96,8 @@ import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Random; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; /** * Acts as a shim around the real system services that we need to access data from, and provides @@ -143,6 +146,7 @@ public class SystemServicesProxy { Canvas mBgProtectionCanvas; private final Handler mHandler = new H(); + private final ExecutorService mOnewayExecutor = Executors.newSingleThreadExecutor(); /** * An abstract class to track task stack changes. @@ -466,13 +470,20 @@ public class SystemServicesProxy { if (mIam == null) return false; try { - ActivityManager.StackInfo homeStackInfo = mIam.getStackInfo( - ActivityManager.StackId.HOME_STACK_ID); - ActivityManager.StackInfo fullscreenStackInfo = mIam.getStackInfo( - ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID); - ActivityManager.StackInfo recentsStackInfo = mIam.getStackInfo( - ActivityManager.StackId.RECENTS_STACK_ID); - + List stackInfos = mIam.getAllStackInfos(); + ActivityManager.StackInfo homeStackInfo = null; + ActivityManager.StackInfo fullscreenStackInfo = null; + ActivityManager.StackInfo recentsStackInfo = null; + for (int i = 0; i < stackInfos.size(); i++) { + StackInfo stackInfo = stackInfos.get(i); + if (stackInfo.stackId == HOME_STACK_ID) { + homeStackInfo = stackInfo; + } else if (stackInfo.stackId == FULLSCREEN_WORKSPACE_STACK_ID) { + fullscreenStackInfo = stackInfo; + } else if (stackInfo.stackId == RECENTS_STACK_ID) { + recentsStackInfo = stackInfo; + } + } boolean homeStackVisibleNotOccluded = isStackNotOccluded(homeStackInfo, fullscreenStackInfo); boolean recentsStackVisibleNotOccluded = isStackNotOccluded(recentsStackInfo, @@ -755,10 +766,12 @@ public class SystemServicesProxy { * Sends a message to close other system windows. */ public void sendCloseSystemWindows(String reason) { - try { - mIam.closeSystemDialogs(reason); - } catch (RemoteException e) { - } + mOnewayExecutor.submit(() -> { + try { + mIam.closeSystemDialogs(reason); + } catch (RemoteException e) { + } + }); } /** @@ -998,9 +1011,7 @@ public class SystemServicesProxy { * Returns the current user id. */ public int getCurrentUser() { - if (mAm == null) return 0; - - return mAm.getCurrentUser(); + return KeyguardUpdateMonitor.getCurrentUser(); } /** diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java index 4b53cd112d96b..7ee0906430006 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java +++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java @@ -33,6 +33,7 @@ import android.util.SparseArray; import android.util.SparseBooleanArray; import android.util.SparseIntArray; +import com.android.keyguard.KeyguardUpdateMonitor; import com.android.systemui.Prefs; import com.android.systemui.R; import com.android.systemui.recents.Recents; @@ -86,7 +87,7 @@ public class RecentsTaskLoadPlan { mCurrentQuietProfiles.clear(); if (currentUserId == UserHandle.USER_CURRENT) { - currentUserId = ActivityManager.getCurrentUser(); + currentUserId = KeyguardUpdateMonitor.getCurrentUser(); } UserManager userManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); List profiles = userManager.getProfiles(currentUserId); diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java index 90c65580c7fdf..48543d02f93d7 100644 --- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java +++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java @@ -1151,7 +1151,7 @@ public class DividerView extends FrameLayout implements OnTouchListener, */ public int growsRecents() { boolean result = mGrowRecents - && mWindowManagerProxy.getDockSide() == WindowManager.DOCKED_TOP + && mDockSide == WindowManager.DOCKED_TOP && getCurrentPosition() == getSnapAlgorithm().getLastSplitTarget().position; if (result) { return getSnapAlgorithm().getMiddleTarget().position;