RecentsImpl.java revision b1e71d09f24be2c18120146eaae1ffd9444feb9a
1190fe3bf88388fcb109af64571e3baa0d01f1c37Winson/* 2190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * Copyright (C) 2015 The Android Open Source Project 3190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * 4190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * Licensed under the Apache License, Version 2.0 (the "License"); 5190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * you may not use this file except in compliance with the License. 6190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * You may obtain a copy of the License at 7190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * 8190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * http://www.apache.org/licenses/LICENSE-2.0 9190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * 10190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * Unless required by applicable law or agreed to in writing, software 11190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * distributed under the License is distributed on an "AS IS" BASIS, 12190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * See the License for the specific language governing permissions and 14190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * limitations under the License. 15190fe3bf88388fcb109af64571e3baa0d01f1c37Winson */ 16190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 17190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonpackage com.android.systemui.recents; 18190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 19190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport android.app.ActivityManager; 20190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport android.app.ActivityOptions; 21190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport android.app.ITaskStackListener; 22190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport android.content.ActivityNotFoundException; 23190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport android.content.Context; 24190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport android.content.Intent; 25190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport android.content.res.Resources; 26190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport android.graphics.Bitmap; 27190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport android.graphics.Canvas; 28190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport android.graphics.Rect; 293150e574e6e903a17193e0b90433d69c0e20ae4cWinsonimport android.graphics.RectF; 30190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport android.os.Handler; 31190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport android.os.SystemClock; 32190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport android.os.UserHandle; 331b58561f66a9453754b1b419296899fdc08b4c93Winsonimport android.util.Log; 34190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport android.util.MutableBoolean; 35d64ef3ef33c50a03b4be3b2baaa93aab7319fca8Filip Gruszczynskiimport android.view.AppTransitionAnimationSpec; 36190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport android.view.LayoutInflater; 37190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport android.view.View; 38030979c1e4ad269efa747eb3c03a4b0e3d820f55Jorim Jaggi 39190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport com.android.internal.logging.MetricsLogger; 40190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport com.android.systemui.Prefs; 41190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport com.android.systemui.R; 42190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport com.android.systemui.SystemUIApplication; 43412e18058dc2cd5779d2451fce7fd74631f9e237Winsonimport com.android.systemui.recents.events.EventBus; 441b58561f66a9453754b1b419296899fdc08b4c93Winsonimport com.android.systemui.recents.events.activity.EnterRecentsWindowLastAnimationFrameEvent; 45412e18058dc2cd5779d2451fce7fd74631f9e237Winsonimport com.android.systemui.recents.events.activity.HideRecentsEvent; 460d14d4da91c3d8b1221269712d5abf43a7cf9f31Winsonimport com.android.systemui.recents.events.activity.IterateRecentsEvent; 47412e18058dc2cd5779d2451fce7fd74631f9e237Winsonimport com.android.systemui.recents.events.activity.ToggleRecentsEvent; 48190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport com.android.systemui.recents.events.component.RecentsVisibilityChangedEvent; 49190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport com.android.systemui.recents.events.component.ScreenPinningRequestEvent; 50dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggiimport com.android.systemui.recents.events.ui.DraggingInRecentsEndedEvent; 51dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggiimport com.android.systemui.recents.events.ui.DraggingInRecentsEvent; 526b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinsonimport com.android.systemui.recents.misc.DozeTrigger; 53ab84fc56114c0963c6f701de9725f5413ab76da9Winsonimport com.android.systemui.recents.misc.ForegroundThread; 54190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport com.android.systemui.recents.misc.SystemServicesProxy; 55190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport com.android.systemui.recents.model.RecentsTaskLoadPlan; 56190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport com.android.systemui.recents.model.RecentsTaskLoader; 57190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport com.android.systemui.recents.model.Task; 58190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport com.android.systemui.recents.model.TaskGrouping; 59190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport com.android.systemui.recents.model.TaskStack; 6036a5a2c7003ef8157f276b411c3fda47ad2f75e3Winsonimport com.android.systemui.recents.views.TaskStackLayoutAlgorithm; 611b58561f66a9453754b1b419296899fdc08b4c93Winsonimport com.android.systemui.recents.views.TaskStackView; 62190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport com.android.systemui.recents.views.TaskViewHeader; 63190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport com.android.systemui.recents.views.TaskViewTransform; 64190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport com.android.systemui.statusbar.phone.PhoneStatusBar; 65190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 66190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport java.util.ArrayList; 67190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 681b58561f66a9453754b1b419296899fdc08b4c93Winsonimport static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID; 691b58561f66a9453754b1b419296899fdc08b4c93Winson 70190fe3bf88388fcb109af64571e3baa0d01f1c37Winson/** 71190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * An implementation of the Recents component for the current user. For secondary users, this can 72190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * be called remotely from the system user. 73190fe3bf88388fcb109af64571e3baa0d01f1c37Winson */ 741a4dfe593aafda057ac9cb3086b84588d88cd09fFilip Gruszczynskipublic class RecentsImpl extends IRecentsNonSystemUserCallbacks.Stub implements 751a4dfe593aafda057ac9cb3086b84588d88cd09fFilip Gruszczynski ActivityOptions.OnAnimationFinishedListener { 76190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 77190fe3bf88388fcb109af64571e3baa0d01f1c37Winson private final static String TAG = "RecentsImpl"; 78ab84fc56114c0963c6f701de9725f5413ab76da9Winson private final static boolean DEBUG = false; 79190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 806b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson // The minimum amount of time between each recents button press that we will handle 816b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson private final static int MIN_TOGGLE_DELAY_MS = 350; 826b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson // The duration within which the user releasing the alt tab (from when they pressed alt tab) 836b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson // that the fast alt-tab animation will run. If the user's alt-tab takes longer than this 846b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson // duration, then we will toggle recents after this duration. 856b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson private final static int FAST_ALT_TAB_DELAY_MS = 225; 86190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 87190fe3bf88388fcb109af64571e3baa0d01f1c37Winson public final static String RECENTS_PACKAGE = "com.android.systemui"; 88190fe3bf88388fcb109af64571e3baa0d01f1c37Winson public final static String RECENTS_ACTIVITY = "com.android.systemui.recents.RecentsActivity"; 89190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 90190fe3bf88388fcb109af64571e3baa0d01f1c37Winson /** 91190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * An implementation of ITaskStackListener, that allows us to listen for changes to the system 92190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * task stacks and update recents accordingly. 93190fe3bf88388fcb109af64571e3baa0d01f1c37Winson */ 94190fe3bf88388fcb109af64571e3baa0d01f1c37Winson class TaskStackListenerImpl extends ITaskStackListener.Stub implements Runnable { 95190fe3bf88388fcb109af64571e3baa0d01f1c37Winson Handler mHandler; 96190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 97190fe3bf88388fcb109af64571e3baa0d01f1c37Winson public TaskStackListenerImpl(Handler handler) { 98190fe3bf88388fcb109af64571e3baa0d01f1c37Winson mHandler = handler; 99190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 100190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 101190fe3bf88388fcb109af64571e3baa0d01f1c37Winson @Override 102190fe3bf88388fcb109af64571e3baa0d01f1c37Winson public void onTaskStackChanged() { 103190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Debounce any task stack changes 104190fe3bf88388fcb109af64571e3baa0d01f1c37Winson mHandler.removeCallbacks(this); 105190fe3bf88388fcb109af64571e3baa0d01f1c37Winson mHandler.post(this); 106190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 107190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 108190fe3bf88388fcb109af64571e3baa0d01f1c37Winson /** Preloads the next task */ 109190fe3bf88388fcb109af64571e3baa0d01f1c37Winson public void run() { 110190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // TODO: Temporarily skip this if multi stack is enabled 111190fe3bf88388fcb109af64571e3baa0d01f1c37Winson /* 112190fe3bf88388fcb109af64571e3baa0d01f1c37Winson RecentsConfiguration config = RecentsConfiguration.getInstance(); 113190fe3bf88388fcb109af64571e3baa0d01f1c37Winson if (config.svelteLevel == RecentsConfiguration.SVELTE_NONE) { 114e7f138c7f0a190c86cec10fb32fa106aacae4093Winson RecentsTaskLoader loader = Recents.getTaskLoader(); 115e7f138c7f0a190c86cec10fb32fa106aacae4093Winson SystemServicesProxy ssp = Recents.getSystemServices(); 116190fe3bf88388fcb109af64571e3baa0d01f1c37Winson ActivityManager.RunningTaskInfo runningTaskInfo = ssp.getTopMostTask(); 117190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 118190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Load the next task only if we aren't svelte 119190fe3bf88388fcb109af64571e3baa0d01f1c37Winson RecentsTaskLoadPlan plan = loader.createLoadPlan(mContext); 120190fe3bf88388fcb109af64571e3baa0d01f1c37Winson loader.preloadTasks(plan, true); 121190fe3bf88388fcb109af64571e3baa0d01f1c37Winson RecentsTaskLoadPlan.Options launchOpts = new RecentsTaskLoadPlan.Options(); 122190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // This callback is made when a new activity is launched and the old one is paused 123190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // so ignore the current activity and try and preload the thumbnail for the 124190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // previous one. 125190fe3bf88388fcb109af64571e3baa0d01f1c37Winson if (runningTaskInfo != null) { 126190fe3bf88388fcb109af64571e3baa0d01f1c37Winson launchOpts.runningTaskId = runningTaskInfo.id; 127190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 128190fe3bf88388fcb109af64571e3baa0d01f1c37Winson launchOpts.numVisibleTasks = 2; 129190fe3bf88388fcb109af64571e3baa0d01f1c37Winson launchOpts.numVisibleTaskThumbnails = 2; 130190fe3bf88388fcb109af64571e3baa0d01f1c37Winson launchOpts.onlyLoadForCache = true; 131190fe3bf88388fcb109af64571e3baa0d01f1c37Winson launchOpts.onlyLoadPausedActivities = true; 132190fe3bf88388fcb109af64571e3baa0d01f1c37Winson loader.loadTasks(mContext, plan, launchOpts); 133190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 134190fe3bf88388fcb109af64571e3baa0d01f1c37Winson */ 135190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 136190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 137190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 138e7f138c7f0a190c86cec10fb32fa106aacae4093Winson private static RecentsTaskLoadPlan sInstanceLoadPlan; 139190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 140190fe3bf88388fcb109af64571e3baa0d01f1c37Winson Context mContext; 141190fe3bf88388fcb109af64571e3baa0d01f1c37Winson Handler mHandler; 142190fe3bf88388fcb109af64571e3baa0d01f1c37Winson TaskStackListenerImpl mTaskStackListener; 143190fe3bf88388fcb109af64571e3baa0d01f1c37Winson RecentsAppWidgetHost mAppWidgetHost; 144190fe3bf88388fcb109af64571e3baa0d01f1c37Winson boolean mBootCompleted; 145190fe3bf88388fcb109af64571e3baa0d01f1c37Winson boolean mCanReuseTaskStackViews = true; 146dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi boolean mDraggingInRecents; 147190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 148190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Task launching 149190fe3bf88388fcb109af64571e3baa0d01f1c37Winson Rect mSearchBarBounds = new Rect(); 150190fe3bf88388fcb109af64571e3baa0d01f1c37Winson Rect mTaskStackBounds = new Rect(); 151190fe3bf88388fcb109af64571e3baa0d01f1c37Winson Rect mLastTaskViewBounds = new Rect(); 152190fe3bf88388fcb109af64571e3baa0d01f1c37Winson TaskViewTransform mTmpTransform = new TaskViewTransform(); 153190fe3bf88388fcb109af64571e3baa0d01f1c37Winson int mStatusBarHeight; 154190fe3bf88388fcb109af64571e3baa0d01f1c37Winson int mNavBarHeight; 155190fe3bf88388fcb109af64571e3baa0d01f1c37Winson int mNavBarWidth; 156190fe3bf88388fcb109af64571e3baa0d01f1c37Winson int mTaskBarHeight; 157190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 158190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Header (for transition) 159190fe3bf88388fcb109af64571e3baa0d01f1c37Winson TaskViewHeader mHeaderBar; 160190fe3bf88388fcb109af64571e3baa0d01f1c37Winson final Object mHeaderBarLock = new Object(); 161190fe3bf88388fcb109af64571e3baa0d01f1c37Winson TaskStackView mDummyStackView; 162190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 163190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Variables to keep track of if we need to start recents after binding 164190fe3bf88388fcb109af64571e3baa0d01f1c37Winson boolean mTriggeredFromAltTab; 165190fe3bf88388fcb109af64571e3baa0d01f1c37Winson long mLastToggleTime; 1666b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson DozeTrigger mFastAltTabTrigger = new DozeTrigger(FAST_ALT_TAB_DELAY_MS, new Runnable() { 1676b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson @Override 1686b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson public void run() { 1696b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson // When this fires, then the user has not released alt-tab for at least 1706b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson // FAST_ALT_TAB_DELAY_MS milliseconds 171bb42a46631b4cecdd03bd628feeb8270d412ebd3Jorim Jaggi showRecents(mTriggeredFromAltTab, false /* draggingInRecents */, true /* animate */); 1726b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson } 1736b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson }); 174190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 175190fe3bf88388fcb109af64571e3baa0d01f1c37Winson Bitmap mThumbnailTransitionBitmapCache; 176190fe3bf88388fcb109af64571e3baa0d01f1c37Winson Task mThumbnailTransitionBitmapCacheKey; 177190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 178190fe3bf88388fcb109af64571e3baa0d01f1c37Winson public RecentsImpl(Context context) { 179190fe3bf88388fcb109af64571e3baa0d01f1c37Winson mContext = context; 180190fe3bf88388fcb109af64571e3baa0d01f1c37Winson mHandler = new Handler(); 1811b58561f66a9453754b1b419296899fdc08b4c93Winson mAppWidgetHost = new RecentsAppWidgetHost(mContext, RecentsAppWidgetHost.HOST_ID); 182190fe3bf88388fcb109af64571e3baa0d01f1c37Winson Resources res = mContext.getResources(); 183190fe3bf88388fcb109af64571e3baa0d01f1c37Winson LayoutInflater inflater = LayoutInflater.from(mContext); 184190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 185ab84fc56114c0963c6f701de9725f5413ab76da9Winson // Initialize the static foreground thread 186ab84fc56114c0963c6f701de9725f5413ab76da9Winson ForegroundThread.get(); 187ab84fc56114c0963c6f701de9725f5413ab76da9Winson 188190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Register the task stack listener 189190fe3bf88388fcb109af64571e3baa0d01f1c37Winson mTaskStackListener = new TaskStackListenerImpl(mHandler); 190e7f138c7f0a190c86cec10fb32fa106aacae4093Winson SystemServicesProxy ssp = Recents.getSystemServices(); 191e7f138c7f0a190c86cec10fb32fa106aacae4093Winson ssp.registerTaskStackListener(mTaskStackListener); 192190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 193190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Initialize the static configuration resources 194190fe3bf88388fcb109af64571e3baa0d01f1c37Winson mStatusBarHeight = res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height); 195190fe3bf88388fcb109af64571e3baa0d01f1c37Winson mNavBarHeight = res.getDimensionPixelSize(com.android.internal.R.dimen.navigation_bar_height); 196190fe3bf88388fcb109af64571e3baa0d01f1c37Winson mNavBarWidth = res.getDimensionPixelSize(com.android.internal.R.dimen.navigation_bar_width); 197190fe3bf88388fcb109af64571e3baa0d01f1c37Winson mTaskBarHeight = res.getDimensionPixelSize(R.dimen.recents_task_bar_height); 198190fe3bf88388fcb109af64571e3baa0d01f1c37Winson mDummyStackView = new TaskStackView(mContext, new TaskStack()); 199190fe3bf88388fcb109af64571e3baa0d01f1c37Winson mHeaderBar = (TaskViewHeader) inflater.inflate(R.layout.recents_task_view_header, 200190fe3bf88388fcb109af64571e3baa0d01f1c37Winson null, false); 201190fe3bf88388fcb109af64571e3baa0d01f1c37Winson reloadHeaderBarLayout(true /* tryAndBindSearchWidget */); 202190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 203190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // When we start, preload the data associated with the previous recent tasks. 204190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // We can use a new plan since the caches will be the same. 205e7f138c7f0a190c86cec10fb32fa106aacae4093Winson RecentsTaskLoader loader = Recents.getTaskLoader(); 206190fe3bf88388fcb109af64571e3baa0d01f1c37Winson RecentsTaskLoadPlan plan = loader.createLoadPlan(mContext); 207190fe3bf88388fcb109af64571e3baa0d01f1c37Winson loader.preloadTasks(plan, true /* isTopTaskHome */); 208190fe3bf88388fcb109af64571e3baa0d01f1c37Winson RecentsTaskLoadPlan.Options launchOpts = new RecentsTaskLoadPlan.Options(); 209190fe3bf88388fcb109af64571e3baa0d01f1c37Winson launchOpts.numVisibleTasks = loader.getApplicationIconCacheSize(); 210190fe3bf88388fcb109af64571e3baa0d01f1c37Winson launchOpts.numVisibleTaskThumbnails = loader.getThumbnailCacheSize(); 211190fe3bf88388fcb109af64571e3baa0d01f1c37Winson launchOpts.onlyLoadForCache = true; 212190fe3bf88388fcb109af64571e3baa0d01f1c37Winson loader.loadTasks(mContext, plan, launchOpts); 213190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 214190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 215190fe3bf88388fcb109af64571e3baa0d01f1c37Winson public void onBootCompleted() { 216190fe3bf88388fcb109af64571e3baa0d01f1c37Winson mBootCompleted = true; 217190fe3bf88388fcb109af64571e3baa0d01f1c37Winson reloadHeaderBarLayout(true /* tryAndBindSearchWidget */); 218190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 219190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 220190fe3bf88388fcb109af64571e3baa0d01f1c37Winson @Override 221190fe3bf88388fcb109af64571e3baa0d01f1c37Winson public void onConfigurationChanged() { 222190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Don't reuse task stack views if the configuration changes 223190fe3bf88388fcb109af64571e3baa0d01f1c37Winson mCanReuseTaskStackViews = false; 22453ec42cb17693b2d631746e1e5d31021a3359163Winson Recents.getConfiguration().updateOnConfigurationChange(); 225190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 226190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 227190fe3bf88388fcb109af64571e3baa0d01f1c37Winson /** 228190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * This is only called from the system user's Recents. Secondary users will instead proxy their 229190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * visibility change events through to the system user via 230190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * {@link Recents#onBusEvent(RecentsVisibilityChangedEvent)}. 231190fe3bf88388fcb109af64571e3baa0d01f1c37Winson */ 232190fe3bf88388fcb109af64571e3baa0d01f1c37Winson public void onVisibilityChanged(Context context, boolean visible) { 233190fe3bf88388fcb109af64571e3baa0d01f1c37Winson SystemUIApplication app = (SystemUIApplication) context; 234190fe3bf88388fcb109af64571e3baa0d01f1c37Winson PhoneStatusBar statusBar = app.getComponent(PhoneStatusBar.class); 235190fe3bf88388fcb109af64571e3baa0d01f1c37Winson if (statusBar != null) { 236190fe3bf88388fcb109af64571e3baa0d01f1c37Winson statusBar.updateRecentsVisibility(visible); 237190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 238190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 239190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 240190fe3bf88388fcb109af64571e3baa0d01f1c37Winson /** 241190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * This is only called from the system user's Recents. Secondary users will instead proxy their 242190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * visibility change events through to the system user via 243190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * {@link Recents#onBusEvent(ScreenPinningRequestEvent)}. 244190fe3bf88388fcb109af64571e3baa0d01f1c37Winson */ 245190fe3bf88388fcb109af64571e3baa0d01f1c37Winson public void onStartScreenPinning(Context context) { 246190fe3bf88388fcb109af64571e3baa0d01f1c37Winson SystemUIApplication app = (SystemUIApplication) context; 247190fe3bf88388fcb109af64571e3baa0d01f1c37Winson PhoneStatusBar statusBar = app.getComponent(PhoneStatusBar.class); 248190fe3bf88388fcb109af64571e3baa0d01f1c37Winson if (statusBar != null) { 249190fe3bf88388fcb109af64571e3baa0d01f1c37Winson statusBar.showScreenPinningRequest(false); 250190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 251190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 252190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 253190fe3bf88388fcb109af64571e3baa0d01f1c37Winson @Override 254bb42a46631b4cecdd03bd628feeb8270d412ebd3Jorim Jaggi public void showRecents(boolean triggeredFromAltTab, boolean draggingInRecents, 255bb42a46631b4cecdd03bd628feeb8270d412ebd3Jorim Jaggi boolean animate) { 256190fe3bf88388fcb109af64571e3baa0d01f1c37Winson mTriggeredFromAltTab = triggeredFromAltTab; 257dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi mDraggingInRecents = draggingInRecents; 2586b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson if (mFastAltTabTrigger.hasTriggered()) { 2596b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson // We are calling this from the doze trigger, so just fall through to show Recents 2606b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson mFastAltTabTrigger.resetTrigger(); 2616b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson } else if (mFastAltTabTrigger.isDozing()) { 2626b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson // We are dozing but haven't yet triggered, ignore this if this is not another alt-tab, 2636b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson // otherwise, this is an additional tab (alt-tab*), which means that we should trigger 2646b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson // immediately (fall through and disable the pending trigger) 2656b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson // TODO: This is tricky, we need to handle the tab key, but Recents has not yet started 2666b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson // so we may actually additional signal to handle multiple quick tab cases. The 2676b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson // severity of this is inversely proportional to the FAST_ALT_TAB_DELAY_MS 2686b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson // duration though 2696b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson if (!triggeredFromAltTab) { 2706b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson return; 2716b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson } 2726b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson mFastAltTabTrigger.stopDozing(); 2736b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson } else { 2746b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson // Otherwise, the doze trigger is not running, and if this is an alt tab, we should 2756b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson // start the trigger and then wait for the hide (or for it to elapse) 2766b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson if (triggeredFromAltTab) { 2776b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson mFastAltTabTrigger.startDozing(); 2786b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson return; 2796b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson } 2806b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson } 281190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 282190fe3bf88388fcb109af64571e3baa0d01f1c37Winson try { 283190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Check if the top task is in the home stack, and start the recents activity 284e7f138c7f0a190c86cec10fb32fa106aacae4093Winson SystemServicesProxy ssp = Recents.getSystemServices(); 285e7f138c7f0a190c86cec10fb32fa106aacae4093Winson ActivityManager.RunningTaskInfo topTask = ssp.getTopMostTask(); 286190fe3bf88388fcb109af64571e3baa0d01f1c37Winson MutableBoolean isTopTaskHome = new MutableBoolean(true); 287e7f138c7f0a190c86cec10fb32fa106aacae4093Winson if (topTask == null || !ssp.isRecentsTopMost(topTask, isTopTaskHome)) { 288bb42a46631b4cecdd03bd628feeb8270d412ebd3Jorim Jaggi startRecentsActivity(topTask, isTopTaskHome.value, animate); 289190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 290190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } catch (ActivityNotFoundException e) { 2911b58561f66a9453754b1b419296899fdc08b4c93Winson Log.e(TAG, "Failed to launch RecentsActivity", e); 292190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 293190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 294190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 295190fe3bf88388fcb109af64571e3baa0d01f1c37Winson @Override 296190fe3bf88388fcb109af64571e3baa0d01f1c37Winson public void hideRecents(boolean triggeredFromAltTab, boolean triggeredFromHomeKey) { 297190fe3bf88388fcb109af64571e3baa0d01f1c37Winson if (mBootCompleted) { 2986b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson if (triggeredFromAltTab && mFastAltTabTrigger.isDozing()) { 2996b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson // The user has released alt-tab before the trigger has run, so just show the next 3006b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson // task immediately 3016b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson showNextTask(); 3026b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson 3036b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson // Cancel the fast alt-tab trigger 3046b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson mFastAltTabTrigger.stopDozing(); 3056b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson mFastAltTabTrigger.resetTrigger(); 3066b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson return; 3076b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson } 3086b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson 309190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Defer to the activity to handle hiding recents, if it handles it, then it must still 310190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // be visible 311e7f138c7f0a190c86cec10fb32fa106aacae4093Winson EventBus.getDefault().post(new HideRecentsEvent(triggeredFromAltTab, 312412e18058dc2cd5779d2451fce7fd74631f9e237Winson triggeredFromHomeKey)); 313190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 314190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 315190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 316190fe3bf88388fcb109af64571e3baa0d01f1c37Winson @Override 317190fe3bf88388fcb109af64571e3baa0d01f1c37Winson public void toggleRecents() { 3186b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson // Skip this toggle if we are already waiting to trigger recents via alt-tab 3196b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson if (mFastAltTabTrigger.isDozing()) { 3206b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson return; 3216b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson } 3226b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson 323dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi mDraggingInRecents = false; 324190fe3bf88388fcb109af64571e3baa0d01f1c37Winson mTriggeredFromAltTab = false; 325190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 326190fe3bf88388fcb109af64571e3baa0d01f1c37Winson try { 327e7f138c7f0a190c86cec10fb32fa106aacae4093Winson SystemServicesProxy ssp = Recents.getSystemServices(); 328e7f138c7f0a190c86cec10fb32fa106aacae4093Winson ActivityManager.RunningTaskInfo topTask = ssp.getTopMostTask(); 329190fe3bf88388fcb109af64571e3baa0d01f1c37Winson MutableBoolean isTopTaskHome = new MutableBoolean(true); 330e7f138c7f0a190c86cec10fb32fa106aacae4093Winson if (topTask != null && ssp.isRecentsTopMost(topTask, isTopTaskHome)) { 3315da4347b41b105dc6c6c01bf2810af3ce3013229Winson RecentsConfiguration config = Recents.getConfiguration(); 3325da4347b41b105dc6c6c01bf2810af3ce3013229Winson RecentsActivityLaunchState launchState = config.getLaunchState(); 333c742f973b1e506732911c156c5869fd377afc5bfWinson RecentsDebugFlags flags = Recents.getDebugFlags(); 3348b1871d74137d7e36ba0fed5608772f51f62015bWinson if (flags.isPageOnToggleEnabled() && !launchState.launchedWithAltTab) { 3350d14d4da91c3d8b1221269712d5abf43a7cf9f31Winson // Notify recents to move onto the next task 3360d14d4da91c3d8b1221269712d5abf43a7cf9f31Winson EventBus.getDefault().post(new IterateRecentsEvent()); 3370d14d4da91c3d8b1221269712d5abf43a7cf9f31Winson } else { 3380d14d4da91c3d8b1221269712d5abf43a7cf9f31Winson // If the user has toggled it too quickly, then just eat up the event here (it's 3390d14d4da91c3d8b1221269712d5abf43a7cf9f31Winson // better than showing a janky screenshot). 3400d14d4da91c3d8b1221269712d5abf43a7cf9f31Winson // NOTE: Ideally, the screenshot mechanism would take the window transform into 3410d14d4da91c3d8b1221269712d5abf43a7cf9f31Winson // account 3426b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson if ((SystemClock.elapsedRealtime() - mLastToggleTime) < MIN_TOGGLE_DELAY_MS) { 3430d14d4da91c3d8b1221269712d5abf43a7cf9f31Winson return; 3440d14d4da91c3d8b1221269712d5abf43a7cf9f31Winson } 3450d14d4da91c3d8b1221269712d5abf43a7cf9f31Winson 3460d14d4da91c3d8b1221269712d5abf43a7cf9f31Winson EventBus.getDefault().post(new ToggleRecentsEvent()); 3470d14d4da91c3d8b1221269712d5abf43a7cf9f31Winson mLastToggleTime = SystemClock.elapsedRealtime(); 3480d14d4da91c3d8b1221269712d5abf43a7cf9f31Winson } 349190fe3bf88388fcb109af64571e3baa0d01f1c37Winson return; 350190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } else { 3510d14d4da91c3d8b1221269712d5abf43a7cf9f31Winson // If the user has toggled it too quickly, then just eat up the event here (it's 3520d14d4da91c3d8b1221269712d5abf43a7cf9f31Winson // better than showing a janky screenshot). 3530d14d4da91c3d8b1221269712d5abf43a7cf9f31Winson // NOTE: Ideally, the screenshot mechanism would take the window transform into 3540d14d4da91c3d8b1221269712d5abf43a7cf9f31Winson // account 3556b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson if ((SystemClock.elapsedRealtime() - mLastToggleTime) < MIN_TOGGLE_DELAY_MS) { 3560d14d4da91c3d8b1221269712d5abf43a7cf9f31Winson return; 3570d14d4da91c3d8b1221269712d5abf43a7cf9f31Winson } 3580d14d4da91c3d8b1221269712d5abf43a7cf9f31Winson 359190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Otherwise, start the recents activity 360bb42a46631b4cecdd03bd628feeb8270d412ebd3Jorim Jaggi startRecentsActivity(topTask, isTopTaskHome.value, true /* animate */); 3610d14d4da91c3d8b1221269712d5abf43a7cf9f31Winson mLastToggleTime = SystemClock.elapsedRealtime(); 362190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 363190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } catch (ActivityNotFoundException e) { 3641b58561f66a9453754b1b419296899fdc08b4c93Winson Log.e(TAG, "Failed to launch RecentsActivity", e); 365190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 366190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 367190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 368190fe3bf88388fcb109af64571e3baa0d01f1c37Winson @Override 369190fe3bf88388fcb109af64571e3baa0d01f1c37Winson public void preloadRecents() { 370190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Preload only the raw task list into a new load plan (which will be consumed by the 371190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // RecentsActivity) only if there is a task to animate to. 372e7f138c7f0a190c86cec10fb32fa106aacae4093Winson SystemServicesProxy ssp = Recents.getSystemServices(); 373e7f138c7f0a190c86cec10fb32fa106aacae4093Winson ActivityManager.RunningTaskInfo topTask = ssp.getTopMostTask(); 374190fe3bf88388fcb109af64571e3baa0d01f1c37Winson MutableBoolean topTaskHome = new MutableBoolean(true); 375e7f138c7f0a190c86cec10fb32fa106aacae4093Winson RecentsTaskLoader loader = Recents.getTaskLoader(); 376190fe3bf88388fcb109af64571e3baa0d01f1c37Winson sInstanceLoadPlan = loader.createLoadPlan(mContext); 377e7f138c7f0a190c86cec10fb32fa106aacae4093Winson if (topTask != null && !ssp.isRecentsTopMost(topTask, topTaskHome)) { 378190fe3bf88388fcb109af64571e3baa0d01f1c37Winson sInstanceLoadPlan.preloadRawTasks(topTaskHome.value); 379190fe3bf88388fcb109af64571e3baa0d01f1c37Winson loader.preloadTasks(sInstanceLoadPlan, topTaskHome.value); 380190fe3bf88388fcb109af64571e3baa0d01f1c37Winson TaskStack stack = sInstanceLoadPlan.getTaskStack(); 381190fe3bf88388fcb109af64571e3baa0d01f1c37Winson if (stack.getTaskCount() > 0) { 382ab84fc56114c0963c6f701de9725f5413ab76da9Winson // We try and draw the thumbnail transition bitmap in parallel before 383ab84fc56114c0963c6f701de9725f5413ab76da9Winson // toggle/show recents is called 384190fe3bf88388fcb109af64571e3baa0d01f1c37Winson preCacheThumbnailTransitionBitmapAsync(topTask, stack, mDummyStackView); 385190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 386190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 387190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 388190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 389190fe3bf88388fcb109af64571e3baa0d01f1c37Winson @Override 390190fe3bf88388fcb109af64571e3baa0d01f1c37Winson public void cancelPreloadingRecents() { 391190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Do nothing 392190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 393190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 394dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi @Override 395dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi public void onDraggingInRecents(float distanceFromTop) { 396dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi EventBus.getDefault().sendOntoMainThread(new DraggingInRecentsEvent(distanceFromTop)); 397dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi } 398dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi 399dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi @Override 400dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi public void onDraggingInRecentsEnded(float velocity) { 401dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi EventBus.getDefault().sendOntoMainThread(new DraggingInRecentsEndedEvent(velocity)); 402dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi } 403dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi 4046b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson /** 4056b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson * Transitions to the next recent task in the stack. 4066b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson */ 4076b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson public void showNextTask() { 4086b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson SystemServicesProxy ssp = Recents.getSystemServices(); 4096b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson RecentsTaskLoader loader = Recents.getTaskLoader(); 4106b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson RecentsTaskLoadPlan plan = loader.createLoadPlan(mContext); 4116b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson loader.preloadTasks(plan, true /* isTopTaskHome */); 4126b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson TaskStack focusedStack = plan.getTaskStack(); 4136b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson 4146b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson // Return early if there are no tasks in the focused stack 4156b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson if (focusedStack == null || focusedStack.getTaskCount() == 0) return; 4166b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson 4176b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson ActivityManager.RunningTaskInfo runningTask = ssp.getTopMostTask(); 4186b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson // Return early if there is no running task 4196b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson if (runningTask == null) return; 4206b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson 4216b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson // Find the task in the recents list 422e86deb8adb022ba7721a1af1112d3a45e757095cWinson boolean isTopTaskHome = SystemServicesProxy.isHomeStack(runningTask.stackId); 4236b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson ArrayList<Task> tasks = focusedStack.getTasks(); 4246b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson Task toTask = null; 4256b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson ActivityOptions launchOpts = null; 4266b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson int taskCount = tasks.size(); 4276b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson for (int i = taskCount - 1; i >= 1; i--) { 4286b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson Task task = tasks.get(i); 429e86deb8adb022ba7721a1af1112d3a45e757095cWinson if (isTopTaskHome) { 430e86deb8adb022ba7721a1af1112d3a45e757095cWinson toTask = tasks.get(i - 1); 431e86deb8adb022ba7721a1af1112d3a45e757095cWinson launchOpts = ActivityOptions.makeCustomAnimation(mContext, 432e86deb8adb022ba7721a1af1112d3a45e757095cWinson R.anim.recents_launch_next_affiliated_task_target, 433e86deb8adb022ba7721a1af1112d3a45e757095cWinson R.anim.recents_fast_toggle_app_home_exit); 434e86deb8adb022ba7721a1af1112d3a45e757095cWinson break; 435e86deb8adb022ba7721a1af1112d3a45e757095cWinson } else if (task.key.id == runningTask.id) { 4366b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson toTask = tasks.get(i - 1); 4376b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson launchOpts = ActivityOptions.makeCustomAnimation(mContext, 4386b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson R.anim.recents_launch_prev_affiliated_task_target, 4396b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson R.anim.recents_launch_prev_affiliated_task_source); 4406b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson break; 4416b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson } 4426b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson } 4436b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson 4446b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson // Return early if there is no next task 4456b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson if (toTask == null) { 4466b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson ssp.startInPlaceAnimationOnFrontMostApplication( 4476b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson ActivityOptions.makeCustomInPlaceAnimation(mContext, 4486b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson R.anim.recents_launch_prev_affiliated_task_bounce)); 4496b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson return; 4506b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson } 4516b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson 4526b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson // Launch the task 4536b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson ssp.startActivityFromRecents(mContext, toTask.key.id, toTask.activityLabel, launchOpts); 4546b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson } 4556b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson 4566b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson /** 4576b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson * Transitions to the next affiliated task. 4586b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson */ 459190fe3bf88388fcb109af64571e3baa0d01f1c37Winson public void showRelativeAffiliatedTask(boolean showNextTask) { 460e7f138c7f0a190c86cec10fb32fa106aacae4093Winson SystemServicesProxy ssp = Recents.getSystemServices(); 461e7f138c7f0a190c86cec10fb32fa106aacae4093Winson RecentsTaskLoader loader = Recents.getTaskLoader(); 462190fe3bf88388fcb109af64571e3baa0d01f1c37Winson RecentsTaskLoadPlan plan = loader.createLoadPlan(mContext); 463190fe3bf88388fcb109af64571e3baa0d01f1c37Winson loader.preloadTasks(plan, true /* isTopTaskHome */); 464190fe3bf88388fcb109af64571e3baa0d01f1c37Winson TaskStack focusedStack = plan.getTaskStack(); 465190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 466190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Return early if there are no tasks in the focused stack 467190fe3bf88388fcb109af64571e3baa0d01f1c37Winson if (focusedStack == null || focusedStack.getTaskCount() == 0) return; 468190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 469e7f138c7f0a190c86cec10fb32fa106aacae4093Winson ActivityManager.RunningTaskInfo runningTask = ssp.getTopMostTask(); 470190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Return early if there is no running task (can't determine affiliated tasks in this case) 471190fe3bf88388fcb109af64571e3baa0d01f1c37Winson if (runningTask == null) return; 472190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Return early if the running task is in the home stack (optimization) 4735510f6c1b9c20483e1507147eed7b24ac8bb6363Winson if (SystemServicesProxy.isHomeStack(runningTask.stackId)) return; 474190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 475190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Find the task in the recents list 476190fe3bf88388fcb109af64571e3baa0d01f1c37Winson ArrayList<Task> tasks = focusedStack.getTasks(); 477190fe3bf88388fcb109af64571e3baa0d01f1c37Winson Task toTask = null; 478190fe3bf88388fcb109af64571e3baa0d01f1c37Winson ActivityOptions launchOpts = null; 479190fe3bf88388fcb109af64571e3baa0d01f1c37Winson int taskCount = tasks.size(); 480190fe3bf88388fcb109af64571e3baa0d01f1c37Winson int numAffiliatedTasks = 0; 481190fe3bf88388fcb109af64571e3baa0d01f1c37Winson for (int i = 0; i < taskCount; i++) { 482190fe3bf88388fcb109af64571e3baa0d01f1c37Winson Task task = tasks.get(i); 483190fe3bf88388fcb109af64571e3baa0d01f1c37Winson if (task.key.id == runningTask.id) { 484190fe3bf88388fcb109af64571e3baa0d01f1c37Winson TaskGrouping group = task.group; 485190fe3bf88388fcb109af64571e3baa0d01f1c37Winson Task.TaskKey toTaskKey; 486190fe3bf88388fcb109af64571e3baa0d01f1c37Winson if (showNextTask) { 487190fe3bf88388fcb109af64571e3baa0d01f1c37Winson toTaskKey = group.getNextTaskInGroup(task); 488190fe3bf88388fcb109af64571e3baa0d01f1c37Winson launchOpts = ActivityOptions.makeCustomAnimation(mContext, 489190fe3bf88388fcb109af64571e3baa0d01f1c37Winson R.anim.recents_launch_next_affiliated_task_target, 490190fe3bf88388fcb109af64571e3baa0d01f1c37Winson R.anim.recents_launch_next_affiliated_task_source); 491190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } else { 492190fe3bf88388fcb109af64571e3baa0d01f1c37Winson toTaskKey = group.getPrevTaskInGroup(task); 493190fe3bf88388fcb109af64571e3baa0d01f1c37Winson launchOpts = ActivityOptions.makeCustomAnimation(mContext, 494190fe3bf88388fcb109af64571e3baa0d01f1c37Winson R.anim.recents_launch_prev_affiliated_task_target, 495190fe3bf88388fcb109af64571e3baa0d01f1c37Winson R.anim.recents_launch_prev_affiliated_task_source); 496190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 497190fe3bf88388fcb109af64571e3baa0d01f1c37Winson if (toTaskKey != null) { 498190fe3bf88388fcb109af64571e3baa0d01f1c37Winson toTask = focusedStack.findTaskWithId(toTaskKey.id); 499190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 500190fe3bf88388fcb109af64571e3baa0d01f1c37Winson numAffiliatedTasks = group.getTaskCount(); 501190fe3bf88388fcb109af64571e3baa0d01f1c37Winson break; 502190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 503190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 504190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 505190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Return early if there is no next task 506190fe3bf88388fcb109af64571e3baa0d01f1c37Winson if (toTask == null) { 507190fe3bf88388fcb109af64571e3baa0d01f1c37Winson if (numAffiliatedTasks > 1) { 508190fe3bf88388fcb109af64571e3baa0d01f1c37Winson if (showNextTask) { 509e7f138c7f0a190c86cec10fb32fa106aacae4093Winson ssp.startInPlaceAnimationOnFrontMostApplication( 510190fe3bf88388fcb109af64571e3baa0d01f1c37Winson ActivityOptions.makeCustomInPlaceAnimation(mContext, 511190fe3bf88388fcb109af64571e3baa0d01f1c37Winson R.anim.recents_launch_next_affiliated_task_bounce)); 512190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } else { 513e7f138c7f0a190c86cec10fb32fa106aacae4093Winson ssp.startInPlaceAnimationOnFrontMostApplication( 514190fe3bf88388fcb109af64571e3baa0d01f1c37Winson ActivityOptions.makeCustomInPlaceAnimation(mContext, 515190fe3bf88388fcb109af64571e3baa0d01f1c37Winson R.anim.recents_launch_prev_affiliated_task_bounce)); 516190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 517190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 518190fe3bf88388fcb109af64571e3baa0d01f1c37Winson return; 519190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 520190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 521190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Keep track of actually launched affiliated tasks 522190fe3bf88388fcb109af64571e3baa0d01f1c37Winson MetricsLogger.count(mContext, "overview_affiliated_task_launch", 1); 523190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 524190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Launch the task 52583c1b07a99a6ddd80c30cfc101f3de037a0d215dWinson ssp.startActivityFromRecents(mContext, toTask.key.id, toTask.activityLabel, launchOpts); 526190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 527190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 528190fe3bf88388fcb109af64571e3baa0d01f1c37Winson public void showNextAffiliatedTask() { 529190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Keep track of when the affiliated task is triggered 530190fe3bf88388fcb109af64571e3baa0d01f1c37Winson MetricsLogger.count(mContext, "overview_affiliated_task_next", 1); 531190fe3bf88388fcb109af64571e3baa0d01f1c37Winson showRelativeAffiliatedTask(true); 532190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 533190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 534190fe3bf88388fcb109af64571e3baa0d01f1c37Winson public void showPrevAffiliatedTask() { 535190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Keep track of when the affiliated task is triggered 536190fe3bf88388fcb109af64571e3baa0d01f1c37Winson MetricsLogger.count(mContext, "overview_affiliated_task_prev", 1); 537190fe3bf88388fcb109af64571e3baa0d01f1c37Winson showRelativeAffiliatedTask(false); 538190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 539190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 540dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi public void dockTopTask(boolean draggingInRecents) { 54175b2597e5826662c1740d6f3b81966a9e6a9e7b4Jorim Jaggi SystemServicesProxy ssp = Recents.getSystemServices(); 54275b2597e5826662c1740d6f3b81966a9e6a9e7b4Jorim Jaggi ActivityManager.RunningTaskInfo topTask = ssp.getTopMostTask(); 54338c96cb83446009458558c438b066e38eacab0f2Winson if (topTask != null && !SystemServicesProxy.isHomeStack(topTask.stackId)) { 544030979c1e4ad269efa747eb3c03a4b0e3d820f55Jorim Jaggi ssp.moveTaskToDockedStack(topTask.id, 54575b2597e5826662c1740d6f3b81966a9e6a9e7b4Jorim Jaggi ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT); 546bb42a46631b4cecdd03bd628feeb8270d412ebd3Jorim Jaggi showRecents(false /* triggeredFromAltTab */, draggingInRecents, false /* animate */); 54775b2597e5826662c1740d6f3b81966a9e6a9e7b4Jorim Jaggi } 54875b2597e5826662c1740d6f3b81966a9e6a9e7b4Jorim Jaggi } 54975b2597e5826662c1740d6f3b81966a9e6a9e7b4Jorim Jaggi 550190fe3bf88388fcb109af64571e3baa0d01f1c37Winson /** 551190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * Returns the preloaded load plan and invalidates it. 552190fe3bf88388fcb109af64571e3baa0d01f1c37Winson */ 553190fe3bf88388fcb109af64571e3baa0d01f1c37Winson public static RecentsTaskLoadPlan consumeInstanceLoadPlan() { 554190fe3bf88388fcb109af64571e3baa0d01f1c37Winson RecentsTaskLoadPlan plan = sInstanceLoadPlan; 555190fe3bf88388fcb109af64571e3baa0d01f1c37Winson sInstanceLoadPlan = null; 556190fe3bf88388fcb109af64571e3baa0d01f1c37Winson return plan; 557190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 558190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 559190fe3bf88388fcb109af64571e3baa0d01f1c37Winson /** 560190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * Prepares the header bar layout for the next transition, if the task view bounds has changed 561190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * since the last call, it will attempt to re-measure and layout the header bar to the new size. 562190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * 563190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * @param tryAndBindSearchWidget if set, will attempt to fetch and bind the search widget if one 564190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * is not already bound (can be expensive) 565190fe3bf88388fcb109af64571e3baa0d01f1c37Winson */ 566190fe3bf88388fcb109af64571e3baa0d01f1c37Winson private void reloadHeaderBarLayout(boolean tryAndBindSearchWidget) { 56753ec42cb17693b2d631746e1e5d31021a3359163Winson RecentsConfiguration config = Recents.getConfiguration(); 568e7f138c7f0a190c86cec10fb32fa106aacae4093Winson SystemServicesProxy ssp = Recents.getSystemServices(); 569e7f138c7f0a190c86cec10fb32fa106aacae4093Winson Rect windowRect = ssp.getWindowRect(); 570190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 571190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Update the configuration for the current state 57253ec42cb17693b2d631746e1e5d31021a3359163Winson config.update(mContext, ssp, ssp.getWindowRect()); 573190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 574c742f973b1e506732911c156c5869fd377afc5bfWinson if (!RecentsDebugFlags.Static.DisableSearchBar && tryAndBindSearchWidget) { 575190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Try and pre-emptively bind the search widget on startup to ensure that we 576190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // have the right thumbnail bounds to animate to. 577190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Note: We have to reload the widget id before we get the task stack bounds below 578e7f138c7f0a190c86cec10fb32fa106aacae4093Winson if (ssp.getOrBindSearchAppWidget(mContext, mAppWidgetHost) != null) { 57953ec42cb17693b2d631746e1e5d31021a3359163Winson config.getSearchBarBounds(windowRect, mStatusBarHeight, mSearchBarBounds); 580190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 581190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 582190fe3bf88388fcb109af64571e3baa0d01f1c37Winson Rect systemInsets = new Rect(0, mStatusBarHeight, 58353ec42cb17693b2d631746e1e5d31021a3359163Winson (config.hasTransposedNavBar ? mNavBarWidth : 0), 58453ec42cb17693b2d631746e1e5d31021a3359163Winson (config.hasTransposedNavBar ? 0 : mNavBarHeight)); 58553ec42cb17693b2d631746e1e5d31021a3359163Winson config.getTaskStackBounds(windowRect, systemInsets.top, systemInsets.right, 586190fe3bf88388fcb109af64571e3baa0d01f1c37Winson mSearchBarBounds, mTaskStackBounds); 587190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 588190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Rebind the header bar and draw it for the transition 58936a5a2c7003ef8157f276b411c3fda47ad2f75e3Winson TaskStackLayoutAlgorithm algo = mDummyStackView.getStackAlgorithm(); 590190fe3bf88388fcb109af64571e3baa0d01f1c37Winson Rect taskStackBounds = new Rect(mTaskStackBounds); 591190fe3bf88388fcb109af64571e3baa0d01f1c37Winson algo.setSystemInsets(systemInsets); 59236a5a2c7003ef8157f276b411c3fda47ad2f75e3Winson algo.initialize(taskStackBounds); 593190fe3bf88388fcb109af64571e3baa0d01f1c37Winson Rect taskViewBounds = algo.getUntransformedTaskViewBounds(); 594190fe3bf88388fcb109af64571e3baa0d01f1c37Winson if (!taskViewBounds.equals(mLastTaskViewBounds)) { 595190fe3bf88388fcb109af64571e3baa0d01f1c37Winson mLastTaskViewBounds.set(taskViewBounds); 596190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 597190fe3bf88388fcb109af64571e3baa0d01f1c37Winson int taskViewWidth = taskViewBounds.width(); 598190fe3bf88388fcb109af64571e3baa0d01f1c37Winson synchronized (mHeaderBarLock) { 599190fe3bf88388fcb109af64571e3baa0d01f1c37Winson mHeaderBar.measure( 600190fe3bf88388fcb109af64571e3baa0d01f1c37Winson View.MeasureSpec.makeMeasureSpec(taskViewWidth, View.MeasureSpec.EXACTLY), 601190fe3bf88388fcb109af64571e3baa0d01f1c37Winson View.MeasureSpec.makeMeasureSpec(mTaskBarHeight, View.MeasureSpec.EXACTLY)); 602190fe3bf88388fcb109af64571e3baa0d01f1c37Winson mHeaderBar.layout(0, 0, taskViewWidth, mTaskBarHeight); 603190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 604190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 605190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 606190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 607190fe3bf88388fcb109af64571e3baa0d01f1c37Winson /** 608190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * Preloads the icon of a task. 609190fe3bf88388fcb109af64571e3baa0d01f1c37Winson */ 610190fe3bf88388fcb109af64571e3baa0d01f1c37Winson private void preloadIcon(ActivityManager.RunningTaskInfo task) { 611190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Ensure that we load the running task's icon 612190fe3bf88388fcb109af64571e3baa0d01f1c37Winson RecentsTaskLoadPlan.Options launchOpts = new RecentsTaskLoadPlan.Options(); 613190fe3bf88388fcb109af64571e3baa0d01f1c37Winson launchOpts.runningTaskId = task.id; 614190fe3bf88388fcb109af64571e3baa0d01f1c37Winson launchOpts.loadThumbnails = false; 615190fe3bf88388fcb109af64571e3baa0d01f1c37Winson launchOpts.onlyLoadForCache = true; 616e7f138c7f0a190c86cec10fb32fa106aacae4093Winson Recents.getTaskLoader().loadTasks(mContext, sInstanceLoadPlan, launchOpts); 617190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 618190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 619190fe3bf88388fcb109af64571e3baa0d01f1c37Winson /** 620190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * Caches the header thumbnail used for a window animation asynchronously into 621190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * {@link #mThumbnailTransitionBitmapCache}. 622190fe3bf88388fcb109af64571e3baa0d01f1c37Winson */ 623190fe3bf88388fcb109af64571e3baa0d01f1c37Winson private void preCacheThumbnailTransitionBitmapAsync(ActivityManager.RunningTaskInfo topTask, 624190fe3bf88388fcb109af64571e3baa0d01f1c37Winson TaskStack stack, TaskStackView stackView) { 625190fe3bf88388fcb109af64571e3baa0d01f1c37Winson preloadIcon(topTask); 626190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 627190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Update the header bar if necessary 628190fe3bf88388fcb109af64571e3baa0d01f1c37Winson reloadHeaderBarLayout(false /* tryAndBindSearchWidget */); 629190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 630190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Update the destination rect 631eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson mDummyStackView.updateLayoutForStack(stack); 632190fe3bf88388fcb109af64571e3baa0d01f1c37Winson final Task toTask = new Task(); 633190fe3bf88388fcb109af64571e3baa0d01f1c37Winson final TaskViewTransform toTransform = getThumbnailTransitionTransform(stack, stackView, 634190fe3bf88388fcb109af64571e3baa0d01f1c37Winson topTask.id, toTask); 6353fb67562c548662910160d5672b1b9558bd6571cWinson ForegroundThread.getHandler().postAtFrontOfQueue(new Runnable() { 636190fe3bf88388fcb109af64571e3baa0d01f1c37Winson @Override 637ab84fc56114c0963c6f701de9725f5413ab76da9Winson public void run() { 638ab84fc56114c0963c6f701de9725f5413ab76da9Winson final Bitmap transitionBitmap = drawThumbnailTransitionBitmap(toTask, toTransform); 639ab84fc56114c0963c6f701de9725f5413ab76da9Winson mHandler.post(new Runnable() { 640ab84fc56114c0963c6f701de9725f5413ab76da9Winson @Override 641ab84fc56114c0963c6f701de9725f5413ab76da9Winson public void run() { 642ab84fc56114c0963c6f701de9725f5413ab76da9Winson mThumbnailTransitionBitmapCache = transitionBitmap; 643ab84fc56114c0963c6f701de9725f5413ab76da9Winson mThumbnailTransitionBitmapCacheKey = toTask; 644ab84fc56114c0963c6f701de9725f5413ab76da9Winson } 645ab84fc56114c0963c6f701de9725f5413ab76da9Winson }); 646190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 647ab84fc56114c0963c6f701de9725f5413ab76da9Winson }); 648190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 649190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 650190fe3bf88388fcb109af64571e3baa0d01f1c37Winson /** 651190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * Creates the activity options for a unknown state->recents transition. 652190fe3bf88388fcb109af64571e3baa0d01f1c37Winson */ 653190fe3bf88388fcb109af64571e3baa0d01f1c37Winson private ActivityOptions getUnknownTransitionActivityOptions() { 654190fe3bf88388fcb109af64571e3baa0d01f1c37Winson return ActivityOptions.makeCustomAnimation(mContext, 655190fe3bf88388fcb109af64571e3baa0d01f1c37Winson R.anim.recents_from_unknown_enter, 656190fe3bf88388fcb109af64571e3baa0d01f1c37Winson R.anim.recents_from_unknown_exit, 6573fb67562c548662910160d5672b1b9558bd6571cWinson mHandler, null); 658190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 659190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 660190fe3bf88388fcb109af64571e3baa0d01f1c37Winson /** 661190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * Creates the activity options for a home->recents transition. 662190fe3bf88388fcb109af64571e3baa0d01f1c37Winson */ 663190fe3bf88388fcb109af64571e3baa0d01f1c37Winson private ActivityOptions getHomeTransitionActivityOptions(boolean fromSearchHome) { 664190fe3bf88388fcb109af64571e3baa0d01f1c37Winson if (fromSearchHome) { 665190fe3bf88388fcb109af64571e3baa0d01f1c37Winson return ActivityOptions.makeCustomAnimation(mContext, 666190fe3bf88388fcb109af64571e3baa0d01f1c37Winson R.anim.recents_from_search_launcher_enter, 667190fe3bf88388fcb109af64571e3baa0d01f1c37Winson R.anim.recents_from_search_launcher_exit, 6683fb67562c548662910160d5672b1b9558bd6571cWinson mHandler, null); 669190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 670190fe3bf88388fcb109af64571e3baa0d01f1c37Winson return ActivityOptions.makeCustomAnimation(mContext, 671190fe3bf88388fcb109af64571e3baa0d01f1c37Winson R.anim.recents_from_launcher_enter, 672190fe3bf88388fcb109af64571e3baa0d01f1c37Winson R.anim.recents_from_launcher_exit, 6733fb67562c548662910160d5672b1b9558bd6571cWinson mHandler, null); 674190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 675190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 676190fe3bf88388fcb109af64571e3baa0d01f1c37Winson /** 677190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * Creates the activity options for an app->recents transition. 678190fe3bf88388fcb109af64571e3baa0d01f1c37Winson */ 679190fe3bf88388fcb109af64571e3baa0d01f1c37Winson private ActivityOptions getThumbnailTransitionActivityOptions( 680190fe3bf88388fcb109af64571e3baa0d01f1c37Winson ActivityManager.RunningTaskInfo topTask, TaskStack stack, TaskStackView stackView) { 681d64ef3ef33c50a03b4be3b2baaa93aab7319fca8Filip Gruszczynski if (topTask.stackId == FREEFORM_WORKSPACE_STACK_ID) { 682d64ef3ef33c50a03b4be3b2baaa93aab7319fca8Filip Gruszczynski ArrayList<AppTransitionAnimationSpec> specs = new ArrayList<>(); 683d64ef3ef33c50a03b4be3b2baaa93aab7319fca8Filip Gruszczynski stackView.getScroller().setStackScrollToInitialState(); 684d64ef3ef33c50a03b4be3b2baaa93aab7319fca8Filip Gruszczynski ArrayList<Task> tasks = stack.getTasks(); 685d64ef3ef33c50a03b4be3b2baaa93aab7319fca8Filip Gruszczynski for (int i = tasks.size() - 1; i >= 0; i--) { 686d64ef3ef33c50a03b4be3b2baaa93aab7319fca8Filip Gruszczynski Task task = tasks.get(i); 687d64ef3ef33c50a03b4be3b2baaa93aab7319fca8Filip Gruszczynski if (SystemServicesProxy.isFreeformStack(task.key.stackId)) { 688d64ef3ef33c50a03b4be3b2baaa93aab7319fca8Filip Gruszczynski mTmpTransform = stackView.getStackAlgorithm().getStackTransform(task, 689d64ef3ef33c50a03b4be3b2baaa93aab7319fca8Filip Gruszczynski stackView.getScroller().getStackScroll(), mTmpTransform, null); 690d64ef3ef33c50a03b4be3b2baaa93aab7319fca8Filip Gruszczynski Rect toTaskRect = new Rect(); 691d64ef3ef33c50a03b4be3b2baaa93aab7319fca8Filip Gruszczynski mTmpTransform.rect.round(toTaskRect); 692d64ef3ef33c50a03b4be3b2baaa93aab7319fca8Filip Gruszczynski Bitmap thumbnail = getThumbnailBitmap(topTask, task, mTmpTransform); 693d64ef3ef33c50a03b4be3b2baaa93aab7319fca8Filip Gruszczynski specs.add(new AppTransitionAnimationSpec(task.key.id, thumbnail, toTaskRect)); 694d64ef3ef33c50a03b4be3b2baaa93aab7319fca8Filip Gruszczynski } 695d64ef3ef33c50a03b4be3b2baaa93aab7319fca8Filip Gruszczynski } 696d64ef3ef33c50a03b4be3b2baaa93aab7319fca8Filip Gruszczynski AppTransitionAnimationSpec[] specsArray = new AppTransitionAnimationSpec[specs.size()]; 697d64ef3ef33c50a03b4be3b2baaa93aab7319fca8Filip Gruszczynski specs.toArray(specsArray); 698d64ef3ef33c50a03b4be3b2baaa93aab7319fca8Filip Gruszczynski return ActivityOptions.makeThumbnailAspectScaleDownAnimation(mDummyStackView, 6993fb67562c548662910160d5672b1b9558bd6571cWinson specsArray, mHandler, null, this); 700d64ef3ef33c50a03b4be3b2baaa93aab7319fca8Filip Gruszczynski } else { 701d64ef3ef33c50a03b4be3b2baaa93aab7319fca8Filip Gruszczynski // Update the destination rect 702d64ef3ef33c50a03b4be3b2baaa93aab7319fca8Filip Gruszczynski Task toTask = new Task(); 703d64ef3ef33c50a03b4be3b2baaa93aab7319fca8Filip Gruszczynski TaskViewTransform toTransform = getThumbnailTransitionTransform(stack, stackView, 704d64ef3ef33c50a03b4be3b2baaa93aab7319fca8Filip Gruszczynski topTask.id, toTask); 705d64ef3ef33c50a03b4be3b2baaa93aab7319fca8Filip Gruszczynski RectF toTaskRect = toTransform.rect; 706d64ef3ef33c50a03b4be3b2baaa93aab7319fca8Filip Gruszczynski Bitmap thumbnail = getThumbnailBitmap(topTask, toTask, toTransform); 707d64ef3ef33c50a03b4be3b2baaa93aab7319fca8Filip Gruszczynski if (thumbnail != null) { 708d64ef3ef33c50a03b4be3b2baaa93aab7319fca8Filip Gruszczynski return ActivityOptions.makeThumbnailAspectScaleDownAnimation(mDummyStackView, 709d64ef3ef33c50a03b4be3b2baaa93aab7319fca8Filip Gruszczynski thumbnail, (int) toTaskRect.left, (int) toTaskRect.top, 7103fb67562c548662910160d5672b1b9558bd6571cWinson (int) toTaskRect.width(), (int) toTaskRect.height(), mHandler, null); 711d64ef3ef33c50a03b4be3b2baaa93aab7319fca8Filip Gruszczynski } 712d64ef3ef33c50a03b4be3b2baaa93aab7319fca8Filip Gruszczynski // If both the screenshot and thumbnail fails, then just fall back to the default transition 713d64ef3ef33c50a03b4be3b2baaa93aab7319fca8Filip Gruszczynski return getUnknownTransitionActivityOptions(); 714d64ef3ef33c50a03b4be3b2baaa93aab7319fca8Filip Gruszczynski } 715d64ef3ef33c50a03b4be3b2baaa93aab7319fca8Filip Gruszczynski } 716190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 717d64ef3ef33c50a03b4be3b2baaa93aab7319fca8Filip Gruszczynski private Bitmap getThumbnailBitmap(ActivityManager.RunningTaskInfo topTask, Task toTask, 718d64ef3ef33c50a03b4be3b2baaa93aab7319fca8Filip Gruszczynski TaskViewTransform toTransform) { 719190fe3bf88388fcb109af64571e3baa0d01f1c37Winson Bitmap thumbnail; 720190fe3bf88388fcb109af64571e3baa0d01f1c37Winson if (mThumbnailTransitionBitmapCacheKey != null 721190fe3bf88388fcb109af64571e3baa0d01f1c37Winson && mThumbnailTransitionBitmapCacheKey.key != null 722190fe3bf88388fcb109af64571e3baa0d01f1c37Winson && mThumbnailTransitionBitmapCacheKey.key.equals(toTask.key)) { 723190fe3bf88388fcb109af64571e3baa0d01f1c37Winson thumbnail = mThumbnailTransitionBitmapCache; 724190fe3bf88388fcb109af64571e3baa0d01f1c37Winson mThumbnailTransitionBitmapCacheKey = null; 725190fe3bf88388fcb109af64571e3baa0d01f1c37Winson mThumbnailTransitionBitmapCache = null; 726190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } else { 727190fe3bf88388fcb109af64571e3baa0d01f1c37Winson preloadIcon(topTask); 728190fe3bf88388fcb109af64571e3baa0d01f1c37Winson thumbnail = drawThumbnailTransitionBitmap(toTask, toTransform); 729190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 730d64ef3ef33c50a03b4be3b2baaa93aab7319fca8Filip Gruszczynski return thumbnail; 731190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 732190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 733190fe3bf88388fcb109af64571e3baa0d01f1c37Winson /** 734190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * Returns the transition rect for the given task id. 735190fe3bf88388fcb109af64571e3baa0d01f1c37Winson */ 736190fe3bf88388fcb109af64571e3baa0d01f1c37Winson private TaskViewTransform getThumbnailTransitionTransform(TaskStack stack, 737190fe3bf88388fcb109af64571e3baa0d01f1c37Winson TaskStackView stackView, int runningTaskId, Task runningTaskOut) { 738190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Find the running task in the TaskStack 739190fe3bf88388fcb109af64571e3baa0d01f1c37Winson Task task = null; 740190fe3bf88388fcb109af64571e3baa0d01f1c37Winson ArrayList<Task> tasks = stack.getTasks(); 741190fe3bf88388fcb109af64571e3baa0d01f1c37Winson if (runningTaskId != -1) { 742190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Otherwise, try and find the task with the 743190fe3bf88388fcb109af64571e3baa0d01f1c37Winson int taskCount = tasks.size(); 744190fe3bf88388fcb109af64571e3baa0d01f1c37Winson for (int i = taskCount - 1; i >= 0; i--) { 745190fe3bf88388fcb109af64571e3baa0d01f1c37Winson Task t = tasks.get(i); 746190fe3bf88388fcb109af64571e3baa0d01f1c37Winson if (t.key.id == runningTaskId) { 747190fe3bf88388fcb109af64571e3baa0d01f1c37Winson task = t; 748190fe3bf88388fcb109af64571e3baa0d01f1c37Winson runningTaskOut.copyFrom(t); 749190fe3bf88388fcb109af64571e3baa0d01f1c37Winson break; 750190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 751190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 752190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 753190fe3bf88388fcb109af64571e3baa0d01f1c37Winson if (task == null) { 754190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // If no task is specified or we can not find the task just use the front most one 755190fe3bf88388fcb109af64571e3baa0d01f1c37Winson task = tasks.get(tasks.size() - 1); 756190fe3bf88388fcb109af64571e3baa0d01f1c37Winson runningTaskOut.copyFrom(task); 757190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 758190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 759190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Get the transform for the running task 760190fe3bf88388fcb109af64571e3baa0d01f1c37Winson stackView.getScroller().setStackScrollToInitialState(); 761190fe3bf88388fcb109af64571e3baa0d01f1c37Winson mTmpTransform = stackView.getStackAlgorithm().getStackTransform(task, 762190fe3bf88388fcb109af64571e3baa0d01f1c37Winson stackView.getScroller().getStackScroll(), mTmpTransform, null); 763190fe3bf88388fcb109af64571e3baa0d01f1c37Winson return mTmpTransform; 764190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 765190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 766190fe3bf88388fcb109af64571e3baa0d01f1c37Winson /** 767190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * Draws the header of a task used for the window animation into a bitmap. 768190fe3bf88388fcb109af64571e3baa0d01f1c37Winson */ 769190fe3bf88388fcb109af64571e3baa0d01f1c37Winson private Bitmap drawThumbnailTransitionBitmap(Task toTask, TaskViewTransform toTransform) { 770190fe3bf88388fcb109af64571e3baa0d01f1c37Winson if (toTransform != null && toTask.key != null) { 771190fe3bf88388fcb109af64571e3baa0d01f1c37Winson Bitmap thumbnail; 772190fe3bf88388fcb109af64571e3baa0d01f1c37Winson synchronized (mHeaderBarLock) { 773190fe3bf88388fcb109af64571e3baa0d01f1c37Winson int toHeaderWidth = (int) (mHeaderBar.getMeasuredWidth() * toTransform.scale); 774190fe3bf88388fcb109af64571e3baa0d01f1c37Winson int toHeaderHeight = (int) (mHeaderBar.getMeasuredHeight() * toTransform.scale); 775190fe3bf88388fcb109af64571e3baa0d01f1c37Winson thumbnail = Bitmap.createBitmap(toHeaderWidth, toHeaderHeight, 776190fe3bf88388fcb109af64571e3baa0d01f1c37Winson Bitmap.Config.ARGB_8888); 777c742f973b1e506732911c156c5869fd377afc5bfWinson if (RecentsDebugFlags.Static.EnableTransitionThumbnailDebugMode) { 778190fe3bf88388fcb109af64571e3baa0d01f1c37Winson thumbnail.eraseColor(0xFFff0000); 779190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } else { 780190fe3bf88388fcb109af64571e3baa0d01f1c37Winson Canvas c = new Canvas(thumbnail); 781190fe3bf88388fcb109af64571e3baa0d01f1c37Winson c.scale(toTransform.scale, toTransform.scale); 782190fe3bf88388fcb109af64571e3baa0d01f1c37Winson mHeaderBar.rebindToTask(toTask); 783190fe3bf88388fcb109af64571e3baa0d01f1c37Winson mHeaderBar.draw(c); 784190fe3bf88388fcb109af64571e3baa0d01f1c37Winson c.setBitmap(null); 785190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 786190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 787190fe3bf88388fcb109af64571e3baa0d01f1c37Winson return thumbnail.createAshmemBitmap(); 788190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 789190fe3bf88388fcb109af64571e3baa0d01f1c37Winson return null; 790190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 791190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 792190fe3bf88388fcb109af64571e3baa0d01f1c37Winson /** 793190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * Shows the recents activity 794190fe3bf88388fcb109af64571e3baa0d01f1c37Winson */ 795190fe3bf88388fcb109af64571e3baa0d01f1c37Winson private void startRecentsActivity(ActivityManager.RunningTaskInfo topTask, 796bb42a46631b4cecdd03bd628feeb8270d412ebd3Jorim Jaggi boolean isTopTaskHome, boolean animate) { 797e7f138c7f0a190c86cec10fb32fa106aacae4093Winson RecentsTaskLoader loader = Recents.getTaskLoader(); 798190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 799190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Update the header bar if necessary 800190fe3bf88388fcb109af64571e3baa0d01f1c37Winson reloadHeaderBarLayout(false /* tryAndBindSearchWidget */); 801190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 802e5f1faa9f8009a723ab21aed6fe5ab325c61442bWinson // In the case where alt-tab is triggered, we never get a preloadRecents() call, so we 803e5f1faa9f8009a723ab21aed6fe5ab325c61442bWinson // should always preload the tasks now 804e5f1faa9f8009a723ab21aed6fe5ab325c61442bWinson if (mTriggeredFromAltTab ||sInstanceLoadPlan == null) { 805e5f1faa9f8009a723ab21aed6fe5ab325c61442bWinson // Create a new load plan if preloadRecents() was never triggered 806190fe3bf88388fcb109af64571e3baa0d01f1c37Winson sInstanceLoadPlan = loader.createLoadPlan(mContext); 807190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 808e5f1faa9f8009a723ab21aed6fe5ab325c61442bWinson if (mTriggeredFromAltTab || !sInstanceLoadPlan.hasTasks()) { 809190fe3bf88388fcb109af64571e3baa0d01f1c37Winson loader.preloadTasks(sInstanceLoadPlan, isTopTaskHome); 810190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 811190fe3bf88388fcb109af64571e3baa0d01f1c37Winson TaskStack stack = sInstanceLoadPlan.getTaskStack(); 812190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 813190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Prepare the dummy stack for the transition 814eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson mDummyStackView.updateLayoutForStack(stack); 81536a5a2c7003ef8157f276b411c3fda47ad2f75e3Winson TaskStackLayoutAlgorithm.VisibilityReport stackVr = 816190fe3bf88388fcb109af64571e3baa0d01f1c37Winson mDummyStackView.computeStackVisibilityReport(); 817bb42a46631b4cecdd03bd628feeb8270d412ebd3Jorim Jaggi 818bb42a46631b4cecdd03bd628feeb8270d412ebd3Jorim Jaggi if (!animate) { 819bb42a46631b4cecdd03bd628feeb8270d412ebd3Jorim Jaggi ActivityOptions opts = ActivityOptions.makeCustomAnimation(mContext, -1, -1); 820bb42a46631b4cecdd03bd628feeb8270d412ebd3Jorim Jaggi startRecentsActivity(topTask, opts, false /* fromHome */, 821bb42a46631b4cecdd03bd628feeb8270d412ebd3Jorim Jaggi false /* fromSearchHome */, false /* fromThumbnail*/, stackVr); 822bb42a46631b4cecdd03bd628feeb8270d412ebd3Jorim Jaggi return; 823bb42a46631b4cecdd03bd628feeb8270d412ebd3Jorim Jaggi } 824bb42a46631b4cecdd03bd628feeb8270d412ebd3Jorim Jaggi 825190fe3bf88388fcb109af64571e3baa0d01f1c37Winson boolean hasRecentTasks = stack.getTaskCount() > 0; 826190fe3bf88388fcb109af64571e3baa0d01f1c37Winson boolean useThumbnailTransition = (topTask != null) && !isTopTaskHome && hasRecentTasks; 827190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 828190fe3bf88388fcb109af64571e3baa0d01f1c37Winson if (useThumbnailTransition) { 829190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Try starting with a thumbnail transition 830190fe3bf88388fcb109af64571e3baa0d01f1c37Winson ActivityOptions opts = getThumbnailTransitionActivityOptions(topTask, stack, 831190fe3bf88388fcb109af64571e3baa0d01f1c37Winson mDummyStackView); 832190fe3bf88388fcb109af64571e3baa0d01f1c37Winson if (opts != null) { 833190fe3bf88388fcb109af64571e3baa0d01f1c37Winson startRecentsActivity(topTask, opts, false /* fromHome */, 834190fe3bf88388fcb109af64571e3baa0d01f1c37Winson false /* fromSearchHome */, true /* fromThumbnail */, stackVr); 835190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } else { 836190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Fall through below to the non-thumbnail transition 837190fe3bf88388fcb109af64571e3baa0d01f1c37Winson useThumbnailTransition = false; 838190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 839190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 840190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 841190fe3bf88388fcb109af64571e3baa0d01f1c37Winson if (!useThumbnailTransition) { 842190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // If there is no thumbnail transition, but is launching from home into recents, then 843190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // use a quick home transition and do the animation from home 844c742f973b1e506732911c156c5869fd377afc5bfWinson if (!RecentsDebugFlags.Static.DisableSearchBar && hasRecentTasks) { 8455da4347b41b105dc6c6c01bf2810af3ce3013229Winson SystemServicesProxy ssp = Recents.getSystemServices(); 846e7f138c7f0a190c86cec10fb32fa106aacae4093Winson String homeActivityPackage = ssp.getHomeActivityPackageName(); 847e7f138c7f0a190c86cec10fb32fa106aacae4093Winson String searchWidgetPackage = Prefs.getString(mContext, 848c742f973b1e506732911c156c5869fd377afc5bfWinson Prefs.Key.OVERVIEW_SEARCH_APP_WIDGET_PACKAGE, null); 849190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 850190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Determine whether we are coming from a search owned home activity 851190fe3bf88388fcb109af64571e3baa0d01f1c37Winson boolean fromSearchHome = (homeActivityPackage != null) && 852190fe3bf88388fcb109af64571e3baa0d01f1c37Winson homeActivityPackage.equals(searchWidgetPackage); 853190fe3bf88388fcb109af64571e3baa0d01f1c37Winson ActivityOptions opts = getHomeTransitionActivityOptions(fromSearchHome); 854190fe3bf88388fcb109af64571e3baa0d01f1c37Winson startRecentsActivity(topTask, opts, true /* fromHome */, fromSearchHome, 855190fe3bf88388fcb109af64571e3baa0d01f1c37Winson false /* fromThumbnail */, stackVr); 856190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } else { 857190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Otherwise we do the normal fade from an unknown source 858190fe3bf88388fcb109af64571e3baa0d01f1c37Winson ActivityOptions opts = getUnknownTransitionActivityOptions(); 859190fe3bf88388fcb109af64571e3baa0d01f1c37Winson startRecentsActivity(topTask, opts, true /* fromHome */, 860190fe3bf88388fcb109af64571e3baa0d01f1c37Winson false /* fromSearchHome */, false /* fromThumbnail */, stackVr); 861190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 862190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 863190fe3bf88388fcb109af64571e3baa0d01f1c37Winson mLastToggleTime = SystemClock.elapsedRealtime(); 864190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 865190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 866190fe3bf88388fcb109af64571e3baa0d01f1c37Winson /** 867190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * Starts the recents activity. 868190fe3bf88388fcb109af64571e3baa0d01f1c37Winson */ 869190fe3bf88388fcb109af64571e3baa0d01f1c37Winson private void startRecentsActivity(ActivityManager.RunningTaskInfo topTask, 870190fe3bf88388fcb109af64571e3baa0d01f1c37Winson ActivityOptions opts, boolean fromHome, boolean fromSearchHome, boolean fromThumbnail, 87136a5a2c7003ef8157f276b411c3fda47ad2f75e3Winson TaskStackLayoutAlgorithm.VisibilityReport vr) { 872190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Update the configuration based on the launch options 87353ec42cb17693b2d631746e1e5d31021a3359163Winson RecentsConfiguration config = Recents.getConfiguration(); 87453ec42cb17693b2d631746e1e5d31021a3359163Winson RecentsActivityLaunchState launchState = config.getLaunchState(); 875190fe3bf88388fcb109af64571e3baa0d01f1c37Winson launchState.launchedFromHome = fromSearchHome || fromHome; 876190fe3bf88388fcb109af64571e3baa0d01f1c37Winson launchState.launchedFromSearchHome = fromSearchHome; 877190fe3bf88388fcb109af64571e3baa0d01f1c37Winson launchState.launchedFromAppWithThumbnail = fromThumbnail; 878190fe3bf88388fcb109af64571e3baa0d01f1c37Winson launchState.launchedToTaskId = (topTask != null) ? topTask.id : -1; 879190fe3bf88388fcb109af64571e3baa0d01f1c37Winson launchState.launchedWithAltTab = mTriggeredFromAltTab; 880190fe3bf88388fcb109af64571e3baa0d01f1c37Winson launchState.launchedReuseTaskStackViews = mCanReuseTaskStackViews; 881190fe3bf88388fcb109af64571e3baa0d01f1c37Winson launchState.launchedNumVisibleTasks = vr.numVisibleTasks; 882190fe3bf88388fcb109af64571e3baa0d01f1c37Winson launchState.launchedNumVisibleThumbnails = vr.numVisibleThumbnails; 883190fe3bf88388fcb109af64571e3baa0d01f1c37Winson launchState.launchedHasConfigurationChanged = false; 884b1e71d09f24be2c18120146eaae1ffd9444feb9aWinson launchState.launchedViaDragGesture = mDraggingInRecents; 885190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 886190fe3bf88388fcb109af64571e3baa0d01f1c37Winson Intent intent = new Intent(); 887190fe3bf88388fcb109af64571e3baa0d01f1c37Winson intent.setClassName(RECENTS_PACKAGE, RECENTS_ACTIVITY); 888190fe3bf88388fcb109af64571e3baa0d01f1c37Winson intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK 889190fe3bf88388fcb109af64571e3baa0d01f1c37Winson | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS 890190fe3bf88388fcb109af64571e3baa0d01f1c37Winson | Intent.FLAG_ACTIVITY_TASK_ON_HOME); 891190fe3bf88388fcb109af64571e3baa0d01f1c37Winson if (opts != null) { 892190fe3bf88388fcb109af64571e3baa0d01f1c37Winson mContext.startActivityAsUser(intent, opts.toBundle(), UserHandle.CURRENT); 893190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } else { 894190fe3bf88388fcb109af64571e3baa0d01f1c37Winson mContext.startActivityAsUser(intent, UserHandle.CURRENT); 895190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 896190fe3bf88388fcb109af64571e3baa0d01f1c37Winson mCanReuseTaskStackViews = true; 897190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 898190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 8993fb67562c548662910160d5672b1b9558bd6571cWinson /**** OnAnimationFinishedListener Implementation ****/ 9001a5203dfd5264104db018b8a09d50075b1af9b2dFilip Gruszczynski 9011a5203dfd5264104db018b8a09d50075b1af9b2dFilip Gruszczynski @Override 9021a5203dfd5264104db018b8a09d50075b1af9b2dFilip Gruszczynski public void onAnimationFinished() { 9031a5203dfd5264104db018b8a09d50075b1af9b2dFilip Gruszczynski EventBus.getDefault().post(new EnterRecentsWindowLastAnimationFrameEvent()); 9041a5203dfd5264104db018b8a09d50075b1af9b2dFilip Gruszczynski } 905190fe3bf88388fcb109af64571e3baa0d01f1c37Winson} 906