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/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/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/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/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/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/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java index 8f24ec712e83b..24a2927dbd795 100644 --- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java +++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java @@ -1159,7 +1159,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; 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