RecentsImpl.java revision 3150e574e6e903a17193e0b90433d69c0e20ae4c
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; 33190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport android.util.MutableBoolean; 34190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport android.view.LayoutInflater; 35190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport android.view.View; 36190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport com.android.internal.logging.MetricsLogger; 37190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport com.android.systemui.Prefs; 38190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport com.android.systemui.R; 39190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport com.android.systemui.SystemUIApplication; 40412e18058dc2cd5779d2451fce7fd74631f9e237Winsonimport com.android.systemui.recents.events.EventBus; 41412e18058dc2cd5779d2451fce7fd74631f9e237Winsonimport com.android.systemui.recents.events.activity.EnterRecentsWindowAnimationStartedEvent; 42412e18058dc2cd5779d2451fce7fd74631f9e237Winsonimport com.android.systemui.recents.events.activity.HideRecentsEvent; 43412e18058dc2cd5779d2451fce7fd74631f9e237Winsonimport com.android.systemui.recents.events.activity.ToggleRecentsEvent; 44190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport com.android.systemui.recents.events.component.RecentsVisibilityChangedEvent; 45190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport com.android.systemui.recents.events.component.ScreenPinningRequestEvent; 46190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport com.android.systemui.recents.misc.Console; 47ab84fc56114c0963c6f701de9725f5413ab76da9Winsonimport com.android.systemui.recents.misc.ForegroundThread; 48190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport com.android.systemui.recents.misc.SystemServicesProxy; 49190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport com.android.systemui.recents.model.RecentsTaskLoadPlan; 50190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport com.android.systemui.recents.model.RecentsTaskLoader; 51190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport com.android.systemui.recents.model.Task; 52190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport com.android.systemui.recents.model.TaskGrouping; 53190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport com.android.systemui.recents.model.TaskStack; 54190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport com.android.systemui.recents.views.TaskStackView; 55190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport com.android.systemui.recents.views.TaskStackViewLayoutAlgorithm; 56190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport com.android.systemui.recents.views.TaskViewHeader; 57190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport com.android.systemui.recents.views.TaskViewTransform; 58190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport com.android.systemui.statusbar.phone.PhoneStatusBar; 59190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 60190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport java.util.ArrayList; 61190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 62190fe3bf88388fcb109af64571e3baa0d01f1c37Winson/** 63190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * An implementation of the Recents component for the current user. For secondary users, this can 64190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * be called remotely from the system user. 65190fe3bf88388fcb109af64571e3baa0d01f1c37Winson */ 66190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonpublic class RecentsImpl extends IRecentsNonSystemUserCallbacks.Stub 67190fe3bf88388fcb109af64571e3baa0d01f1c37Winson implements ActivityOptions.OnAnimationStartedListener { 68190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 69190fe3bf88388fcb109af64571e3baa0d01f1c37Winson private final static String TAG = "RecentsImpl"; 70ab84fc56114c0963c6f701de9725f5413ab76da9Winson private final static boolean DEBUG = false; 71190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 72412e18058dc2cd5779d2451fce7fd74631f9e237Winson private final static int sMinToggleDelay = 350; 73190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 74190fe3bf88388fcb109af64571e3baa0d01f1c37Winson public final static String RECENTS_PACKAGE = "com.android.systemui"; 75190fe3bf88388fcb109af64571e3baa0d01f1c37Winson public final static String RECENTS_ACTIVITY = "com.android.systemui.recents.RecentsActivity"; 76190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 77190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 78190fe3bf88388fcb109af64571e3baa0d01f1c37Winson /** 79190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * An implementation of ITaskStackListener, that allows us to listen for changes to the system 80190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * task stacks and update recents accordingly. 81190fe3bf88388fcb109af64571e3baa0d01f1c37Winson */ 82190fe3bf88388fcb109af64571e3baa0d01f1c37Winson class TaskStackListenerImpl extends ITaskStackListener.Stub implements Runnable { 83190fe3bf88388fcb109af64571e3baa0d01f1c37Winson Handler mHandler; 84190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 85190fe3bf88388fcb109af64571e3baa0d01f1c37Winson public TaskStackListenerImpl(Handler handler) { 86190fe3bf88388fcb109af64571e3baa0d01f1c37Winson mHandler = handler; 87190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 88190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 89190fe3bf88388fcb109af64571e3baa0d01f1c37Winson @Override 90190fe3bf88388fcb109af64571e3baa0d01f1c37Winson public void onTaskStackChanged() { 91190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Debounce any task stack changes 92190fe3bf88388fcb109af64571e3baa0d01f1c37Winson mHandler.removeCallbacks(this); 93190fe3bf88388fcb109af64571e3baa0d01f1c37Winson mHandler.post(this); 94190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 95190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 96190fe3bf88388fcb109af64571e3baa0d01f1c37Winson /** Preloads the next task */ 97190fe3bf88388fcb109af64571e3baa0d01f1c37Winson public void run() { 98190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // TODO: Temporarily skip this if multi stack is enabled 99190fe3bf88388fcb109af64571e3baa0d01f1c37Winson /* 100190fe3bf88388fcb109af64571e3baa0d01f1c37Winson RecentsConfiguration config = RecentsConfiguration.getInstance(); 101190fe3bf88388fcb109af64571e3baa0d01f1c37Winson if (config.svelteLevel == RecentsConfiguration.SVELTE_NONE) { 102e7f138c7f0a190c86cec10fb32fa106aacae4093Winson RecentsTaskLoader loader = Recents.getTaskLoader(); 103e7f138c7f0a190c86cec10fb32fa106aacae4093Winson SystemServicesProxy ssp = Recents.getSystemServices(); 104190fe3bf88388fcb109af64571e3baa0d01f1c37Winson ActivityManager.RunningTaskInfo runningTaskInfo = ssp.getTopMostTask(); 105190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 106190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Load the next task only if we aren't svelte 107190fe3bf88388fcb109af64571e3baa0d01f1c37Winson RecentsTaskLoadPlan plan = loader.createLoadPlan(mContext); 108190fe3bf88388fcb109af64571e3baa0d01f1c37Winson loader.preloadTasks(plan, true); 109190fe3bf88388fcb109af64571e3baa0d01f1c37Winson RecentsTaskLoadPlan.Options launchOpts = new RecentsTaskLoadPlan.Options(); 110190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // This callback is made when a new activity is launched and the old one is paused 111190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // so ignore the current activity and try and preload the thumbnail for the 112190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // previous one. 113190fe3bf88388fcb109af64571e3baa0d01f1c37Winson if (runningTaskInfo != null) { 114190fe3bf88388fcb109af64571e3baa0d01f1c37Winson launchOpts.runningTaskId = runningTaskInfo.id; 115190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 116190fe3bf88388fcb109af64571e3baa0d01f1c37Winson launchOpts.numVisibleTasks = 2; 117190fe3bf88388fcb109af64571e3baa0d01f1c37Winson launchOpts.numVisibleTaskThumbnails = 2; 118190fe3bf88388fcb109af64571e3baa0d01f1c37Winson launchOpts.onlyLoadForCache = true; 119190fe3bf88388fcb109af64571e3baa0d01f1c37Winson launchOpts.onlyLoadPausedActivities = true; 120190fe3bf88388fcb109af64571e3baa0d01f1c37Winson loader.loadTasks(mContext, plan, launchOpts); 121190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 122190fe3bf88388fcb109af64571e3baa0d01f1c37Winson */ 123190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 124190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 125190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 126e7f138c7f0a190c86cec10fb32fa106aacae4093Winson private static RecentsTaskLoadPlan sInstanceLoadPlan; 127190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 128190fe3bf88388fcb109af64571e3baa0d01f1c37Winson Context mContext; 129190fe3bf88388fcb109af64571e3baa0d01f1c37Winson Handler mHandler; 130190fe3bf88388fcb109af64571e3baa0d01f1c37Winson TaskStackListenerImpl mTaskStackListener; 131190fe3bf88388fcb109af64571e3baa0d01f1c37Winson RecentsAppWidgetHost mAppWidgetHost; 132190fe3bf88388fcb109af64571e3baa0d01f1c37Winson boolean mBootCompleted; 133190fe3bf88388fcb109af64571e3baa0d01f1c37Winson boolean mStartAnimationTriggered; 134190fe3bf88388fcb109af64571e3baa0d01f1c37Winson boolean mCanReuseTaskStackViews = true; 135190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 136190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Task launching 137190fe3bf88388fcb109af64571e3baa0d01f1c37Winson RecentsConfiguration mConfig; 138190fe3bf88388fcb109af64571e3baa0d01f1c37Winson Rect mSearchBarBounds = new Rect(); 139190fe3bf88388fcb109af64571e3baa0d01f1c37Winson Rect mTaskStackBounds = new Rect(); 140190fe3bf88388fcb109af64571e3baa0d01f1c37Winson Rect mLastTaskViewBounds = new Rect(); 141190fe3bf88388fcb109af64571e3baa0d01f1c37Winson TaskViewTransform mTmpTransform = new TaskViewTransform(); 142190fe3bf88388fcb109af64571e3baa0d01f1c37Winson int mStatusBarHeight; 143190fe3bf88388fcb109af64571e3baa0d01f1c37Winson int mNavBarHeight; 144190fe3bf88388fcb109af64571e3baa0d01f1c37Winson int mNavBarWidth; 145190fe3bf88388fcb109af64571e3baa0d01f1c37Winson int mTaskBarHeight; 146190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 147190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Header (for transition) 148190fe3bf88388fcb109af64571e3baa0d01f1c37Winson TaskViewHeader mHeaderBar; 149190fe3bf88388fcb109af64571e3baa0d01f1c37Winson final Object mHeaderBarLock = new Object(); 150190fe3bf88388fcb109af64571e3baa0d01f1c37Winson TaskStackView mDummyStackView; 151190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 152190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Variables to keep track of if we need to start recents after binding 153190fe3bf88388fcb109af64571e3baa0d01f1c37Winson boolean mTriggeredFromAltTab; 154190fe3bf88388fcb109af64571e3baa0d01f1c37Winson long mLastToggleTime; 155190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 156190fe3bf88388fcb109af64571e3baa0d01f1c37Winson Bitmap mThumbnailTransitionBitmapCache; 157190fe3bf88388fcb109af64571e3baa0d01f1c37Winson Task mThumbnailTransitionBitmapCacheKey; 158190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 159190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 160190fe3bf88388fcb109af64571e3baa0d01f1c37Winson public RecentsImpl(Context context) { 161190fe3bf88388fcb109af64571e3baa0d01f1c37Winson mContext = context; 162190fe3bf88388fcb109af64571e3baa0d01f1c37Winson mHandler = new Handler(); 163190fe3bf88388fcb109af64571e3baa0d01f1c37Winson mAppWidgetHost = new RecentsAppWidgetHost(mContext, Constants.Values.App.AppWidgetHostId); 164190fe3bf88388fcb109af64571e3baa0d01f1c37Winson Resources res = mContext.getResources(); 165190fe3bf88388fcb109af64571e3baa0d01f1c37Winson LayoutInflater inflater = LayoutInflater.from(mContext); 166190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 167ab84fc56114c0963c6f701de9725f5413ab76da9Winson // Initialize the static foreground thread 168ab84fc56114c0963c6f701de9725f5413ab76da9Winson ForegroundThread.get(); 169ab84fc56114c0963c6f701de9725f5413ab76da9Winson 170190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Register the task stack listener 171190fe3bf88388fcb109af64571e3baa0d01f1c37Winson mTaskStackListener = new TaskStackListenerImpl(mHandler); 172e7f138c7f0a190c86cec10fb32fa106aacae4093Winson SystemServicesProxy ssp = Recents.getSystemServices(); 173e7f138c7f0a190c86cec10fb32fa106aacae4093Winson ssp.registerTaskStackListener(mTaskStackListener); 174190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 175190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Initialize the static configuration resources 176e7f138c7f0a190c86cec10fb32fa106aacae4093Winson mConfig = RecentsConfiguration.initialize(mContext, ssp); 177190fe3bf88388fcb109af64571e3baa0d01f1c37Winson mStatusBarHeight = res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height); 178190fe3bf88388fcb109af64571e3baa0d01f1c37Winson mNavBarHeight = res.getDimensionPixelSize(com.android.internal.R.dimen.navigation_bar_height); 179190fe3bf88388fcb109af64571e3baa0d01f1c37Winson mNavBarWidth = res.getDimensionPixelSize(com.android.internal.R.dimen.navigation_bar_width); 180190fe3bf88388fcb109af64571e3baa0d01f1c37Winson mTaskBarHeight = res.getDimensionPixelSize(R.dimen.recents_task_bar_height); 181190fe3bf88388fcb109af64571e3baa0d01f1c37Winson mDummyStackView = new TaskStackView(mContext, new TaskStack()); 182190fe3bf88388fcb109af64571e3baa0d01f1c37Winson mHeaderBar = (TaskViewHeader) inflater.inflate(R.layout.recents_task_view_header, 183190fe3bf88388fcb109af64571e3baa0d01f1c37Winson null, false); 184190fe3bf88388fcb109af64571e3baa0d01f1c37Winson reloadHeaderBarLayout(true /* tryAndBindSearchWidget */); 185190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 186190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // When we start, preload the data associated with the previous recent tasks. 187190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // We can use a new plan since the caches will be the same. 188e7f138c7f0a190c86cec10fb32fa106aacae4093Winson RecentsTaskLoader loader = Recents.getTaskLoader(); 189190fe3bf88388fcb109af64571e3baa0d01f1c37Winson RecentsTaskLoadPlan plan = loader.createLoadPlan(mContext); 190190fe3bf88388fcb109af64571e3baa0d01f1c37Winson loader.preloadTasks(plan, true /* isTopTaskHome */); 191190fe3bf88388fcb109af64571e3baa0d01f1c37Winson RecentsTaskLoadPlan.Options launchOpts = new RecentsTaskLoadPlan.Options(); 192190fe3bf88388fcb109af64571e3baa0d01f1c37Winson launchOpts.numVisibleTasks = loader.getApplicationIconCacheSize(); 193190fe3bf88388fcb109af64571e3baa0d01f1c37Winson launchOpts.numVisibleTaskThumbnails = loader.getThumbnailCacheSize(); 194190fe3bf88388fcb109af64571e3baa0d01f1c37Winson launchOpts.onlyLoadForCache = true; 195190fe3bf88388fcb109af64571e3baa0d01f1c37Winson loader.loadTasks(mContext, plan, launchOpts); 196190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 197190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 198190fe3bf88388fcb109af64571e3baa0d01f1c37Winson public void onBootCompleted() { 199190fe3bf88388fcb109af64571e3baa0d01f1c37Winson mBootCompleted = true; 200190fe3bf88388fcb109af64571e3baa0d01f1c37Winson reloadHeaderBarLayout(true /* tryAndBindSearchWidget */); 201190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 202190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 203190fe3bf88388fcb109af64571e3baa0d01f1c37Winson @Override 204190fe3bf88388fcb109af64571e3baa0d01f1c37Winson public void onConfigurationChanged() { 205190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Don't reuse task stack views if the configuration changes 206190fe3bf88388fcb109af64571e3baa0d01f1c37Winson mCanReuseTaskStackViews = false; 207190fe3bf88388fcb109af64571e3baa0d01f1c37Winson mConfig.updateOnConfigurationChange(); 208190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 209190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 210190fe3bf88388fcb109af64571e3baa0d01f1c37Winson /** 211190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * This is only called from the system user's Recents. Secondary users will instead proxy their 212190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * visibility change events through to the system user via 213190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * {@link Recents#onBusEvent(RecentsVisibilityChangedEvent)}. 214190fe3bf88388fcb109af64571e3baa0d01f1c37Winson */ 215190fe3bf88388fcb109af64571e3baa0d01f1c37Winson public void onVisibilityChanged(Context context, boolean visible) { 216190fe3bf88388fcb109af64571e3baa0d01f1c37Winson SystemUIApplication app = (SystemUIApplication) context; 217190fe3bf88388fcb109af64571e3baa0d01f1c37Winson PhoneStatusBar statusBar = app.getComponent(PhoneStatusBar.class); 218190fe3bf88388fcb109af64571e3baa0d01f1c37Winson if (statusBar != null) { 219190fe3bf88388fcb109af64571e3baa0d01f1c37Winson statusBar.updateRecentsVisibility(visible); 220190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 221190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 222190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 223190fe3bf88388fcb109af64571e3baa0d01f1c37Winson /** 224190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * This is only called from the system user's Recents. Secondary users will instead proxy their 225190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * visibility change events through to the system user via 226190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * {@link Recents#onBusEvent(ScreenPinningRequestEvent)}. 227190fe3bf88388fcb109af64571e3baa0d01f1c37Winson */ 228190fe3bf88388fcb109af64571e3baa0d01f1c37Winson public void onStartScreenPinning(Context context) { 229190fe3bf88388fcb109af64571e3baa0d01f1c37Winson SystemUIApplication app = (SystemUIApplication) context; 230190fe3bf88388fcb109af64571e3baa0d01f1c37Winson PhoneStatusBar statusBar = app.getComponent(PhoneStatusBar.class); 231190fe3bf88388fcb109af64571e3baa0d01f1c37Winson if (statusBar != null) { 232190fe3bf88388fcb109af64571e3baa0d01f1c37Winson statusBar.showScreenPinningRequest(false); 233190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 234190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 235190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 236190fe3bf88388fcb109af64571e3baa0d01f1c37Winson @Override 237190fe3bf88388fcb109af64571e3baa0d01f1c37Winson public void showRecents(boolean triggeredFromAltTab) { 238190fe3bf88388fcb109af64571e3baa0d01f1c37Winson mTriggeredFromAltTab = triggeredFromAltTab; 239190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 240190fe3bf88388fcb109af64571e3baa0d01f1c37Winson try { 241190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Check if the top task is in the home stack, and start the recents activity 242e7f138c7f0a190c86cec10fb32fa106aacae4093Winson SystemServicesProxy ssp = Recents.getSystemServices(); 243e7f138c7f0a190c86cec10fb32fa106aacae4093Winson ActivityManager.RunningTaskInfo topTask = ssp.getTopMostTask(); 244190fe3bf88388fcb109af64571e3baa0d01f1c37Winson MutableBoolean isTopTaskHome = new MutableBoolean(true); 245e7f138c7f0a190c86cec10fb32fa106aacae4093Winson if (topTask == null || !ssp.isRecentsTopMost(topTask, isTopTaskHome)) { 246190fe3bf88388fcb109af64571e3baa0d01f1c37Winson startRecentsActivity(topTask, isTopTaskHome.value); 247190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 248190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } catch (ActivityNotFoundException e) { 249190fe3bf88388fcb109af64571e3baa0d01f1c37Winson Console.logRawError("Failed to launch RecentAppsIntent", e); 250190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 251190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 252190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 253190fe3bf88388fcb109af64571e3baa0d01f1c37Winson @Override 254190fe3bf88388fcb109af64571e3baa0d01f1c37Winson public void hideRecents(boolean triggeredFromAltTab, boolean triggeredFromHomeKey) { 255190fe3bf88388fcb109af64571e3baa0d01f1c37Winson if (mBootCompleted) { 256190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Defer to the activity to handle hiding recents, if it handles it, then it must still 257190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // be visible 258e7f138c7f0a190c86cec10fb32fa106aacae4093Winson EventBus.getDefault().post(new HideRecentsEvent(triggeredFromAltTab, 259412e18058dc2cd5779d2451fce7fd74631f9e237Winson triggeredFromHomeKey)); 260190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 261190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 262190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 263190fe3bf88388fcb109af64571e3baa0d01f1c37Winson @Override 264190fe3bf88388fcb109af64571e3baa0d01f1c37Winson public void toggleRecents() { 265190fe3bf88388fcb109af64571e3baa0d01f1c37Winson mTriggeredFromAltTab = false; 266190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 267190fe3bf88388fcb109af64571e3baa0d01f1c37Winson try { 268190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // If the user has toggled it too quickly, then just eat up the event here (it's better 269190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // than showing a janky screenshot). 270190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // NOTE: Ideally, the screenshot mechanism would take the window transform into account 271190fe3bf88388fcb109af64571e3baa0d01f1c37Winson if ((SystemClock.elapsedRealtime() - mLastToggleTime) < sMinToggleDelay) { 272190fe3bf88388fcb109af64571e3baa0d01f1c37Winson return; 273190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 274190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 275190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // If Recents is the front most activity, then we should just communicate with it 276190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // directly to launch the first task or dismiss itself 277e7f138c7f0a190c86cec10fb32fa106aacae4093Winson SystemServicesProxy ssp = Recents.getSystemServices(); 278e7f138c7f0a190c86cec10fb32fa106aacae4093Winson ActivityManager.RunningTaskInfo topTask = ssp.getTopMostTask(); 279190fe3bf88388fcb109af64571e3baa0d01f1c37Winson MutableBoolean isTopTaskHome = new MutableBoolean(true); 280e7f138c7f0a190c86cec10fb32fa106aacae4093Winson if (topTask != null && ssp.isRecentsTopMost(topTask, isTopTaskHome)) { 281190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Notify recents to toggle itself 282e7f138c7f0a190c86cec10fb32fa106aacae4093Winson EventBus.getDefault().post(new ToggleRecentsEvent()); 283190fe3bf88388fcb109af64571e3baa0d01f1c37Winson mLastToggleTime = SystemClock.elapsedRealtime(); 284190fe3bf88388fcb109af64571e3baa0d01f1c37Winson return; 285190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } else { 286190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Otherwise, start the recents activity 287190fe3bf88388fcb109af64571e3baa0d01f1c37Winson startRecentsActivity(topTask, isTopTaskHome.value); 288190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 289190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } catch (ActivityNotFoundException e) { 290190fe3bf88388fcb109af64571e3baa0d01f1c37Winson Console.logRawError("Failed to launch RecentAppsIntent", e); 291190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 292190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 293190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 294190fe3bf88388fcb109af64571e3baa0d01f1c37Winson @Override 295190fe3bf88388fcb109af64571e3baa0d01f1c37Winson public void preloadRecents() { 296190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Preload only the raw task list into a new load plan (which will be consumed by the 297190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // RecentsActivity) only if there is a task to animate to. 298e7f138c7f0a190c86cec10fb32fa106aacae4093Winson SystemServicesProxy ssp = Recents.getSystemServices(); 299e7f138c7f0a190c86cec10fb32fa106aacae4093Winson ActivityManager.RunningTaskInfo topTask = ssp.getTopMostTask(); 300190fe3bf88388fcb109af64571e3baa0d01f1c37Winson MutableBoolean topTaskHome = new MutableBoolean(true); 301e7f138c7f0a190c86cec10fb32fa106aacae4093Winson RecentsTaskLoader loader = Recents.getTaskLoader(); 302190fe3bf88388fcb109af64571e3baa0d01f1c37Winson sInstanceLoadPlan = loader.createLoadPlan(mContext); 303e7f138c7f0a190c86cec10fb32fa106aacae4093Winson if (topTask != null && !ssp.isRecentsTopMost(topTask, topTaskHome)) { 304190fe3bf88388fcb109af64571e3baa0d01f1c37Winson sInstanceLoadPlan.preloadRawTasks(topTaskHome.value); 305190fe3bf88388fcb109af64571e3baa0d01f1c37Winson loader.preloadTasks(sInstanceLoadPlan, topTaskHome.value); 306190fe3bf88388fcb109af64571e3baa0d01f1c37Winson TaskStack stack = sInstanceLoadPlan.getTaskStack(); 307190fe3bf88388fcb109af64571e3baa0d01f1c37Winson if (stack.getTaskCount() > 0) { 308ab84fc56114c0963c6f701de9725f5413ab76da9Winson // We try and draw the thumbnail transition bitmap in parallel before 309ab84fc56114c0963c6f701de9725f5413ab76da9Winson // toggle/show recents is called 310190fe3bf88388fcb109af64571e3baa0d01f1c37Winson preCacheThumbnailTransitionBitmapAsync(topTask, stack, mDummyStackView); 311190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 312190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 313190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 314190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 315190fe3bf88388fcb109af64571e3baa0d01f1c37Winson @Override 316190fe3bf88388fcb109af64571e3baa0d01f1c37Winson public void cancelPreloadingRecents() { 317190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Do nothing 318190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 319190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 320190fe3bf88388fcb109af64571e3baa0d01f1c37Winson public void showRelativeAffiliatedTask(boolean showNextTask) { 321190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Return early if there is no focused stack 322e7f138c7f0a190c86cec10fb32fa106aacae4093Winson SystemServicesProxy ssp = Recents.getSystemServices(); 323e7f138c7f0a190c86cec10fb32fa106aacae4093Winson int focusedStackId = ssp.getFocusedStack(); 324e7f138c7f0a190c86cec10fb32fa106aacae4093Winson RecentsTaskLoader loader = Recents.getTaskLoader(); 325190fe3bf88388fcb109af64571e3baa0d01f1c37Winson RecentsTaskLoadPlan plan = loader.createLoadPlan(mContext); 326190fe3bf88388fcb109af64571e3baa0d01f1c37Winson loader.preloadTasks(plan, true /* isTopTaskHome */); 327190fe3bf88388fcb109af64571e3baa0d01f1c37Winson TaskStack focusedStack = plan.getTaskStack(); 328190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 329190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Return early if there are no tasks in the focused stack 330190fe3bf88388fcb109af64571e3baa0d01f1c37Winson if (focusedStack == null || focusedStack.getTaskCount() == 0) return; 331190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 332e7f138c7f0a190c86cec10fb32fa106aacae4093Winson ActivityManager.RunningTaskInfo runningTask = ssp.getTopMostTask(); 333190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Return early if there is no running task (can't determine affiliated tasks in this case) 334190fe3bf88388fcb109af64571e3baa0d01f1c37Winson if (runningTask == null) return; 335190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Return early if the running task is in the home stack (optimization) 336e7f138c7f0a190c86cec10fb32fa106aacae4093Winson if (ssp.isInHomeStack(runningTask.id)) return; 337190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 338190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Find the task in the recents list 339190fe3bf88388fcb109af64571e3baa0d01f1c37Winson ArrayList<Task> tasks = focusedStack.getTasks(); 340190fe3bf88388fcb109af64571e3baa0d01f1c37Winson Task toTask = null; 341190fe3bf88388fcb109af64571e3baa0d01f1c37Winson ActivityOptions launchOpts = null; 342190fe3bf88388fcb109af64571e3baa0d01f1c37Winson int taskCount = tasks.size(); 343190fe3bf88388fcb109af64571e3baa0d01f1c37Winson int numAffiliatedTasks = 0; 344190fe3bf88388fcb109af64571e3baa0d01f1c37Winson for (int i = 0; i < taskCount; i++) { 345190fe3bf88388fcb109af64571e3baa0d01f1c37Winson Task task = tasks.get(i); 346190fe3bf88388fcb109af64571e3baa0d01f1c37Winson if (task.key.id == runningTask.id) { 347190fe3bf88388fcb109af64571e3baa0d01f1c37Winson TaskGrouping group = task.group; 348190fe3bf88388fcb109af64571e3baa0d01f1c37Winson Task.TaskKey toTaskKey; 349190fe3bf88388fcb109af64571e3baa0d01f1c37Winson if (showNextTask) { 350190fe3bf88388fcb109af64571e3baa0d01f1c37Winson toTaskKey = group.getNextTaskInGroup(task); 351190fe3bf88388fcb109af64571e3baa0d01f1c37Winson launchOpts = ActivityOptions.makeCustomAnimation(mContext, 352190fe3bf88388fcb109af64571e3baa0d01f1c37Winson R.anim.recents_launch_next_affiliated_task_target, 353190fe3bf88388fcb109af64571e3baa0d01f1c37Winson R.anim.recents_launch_next_affiliated_task_source); 354190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } else { 355190fe3bf88388fcb109af64571e3baa0d01f1c37Winson toTaskKey = group.getPrevTaskInGroup(task); 356190fe3bf88388fcb109af64571e3baa0d01f1c37Winson launchOpts = ActivityOptions.makeCustomAnimation(mContext, 357190fe3bf88388fcb109af64571e3baa0d01f1c37Winson R.anim.recents_launch_prev_affiliated_task_target, 358190fe3bf88388fcb109af64571e3baa0d01f1c37Winson R.anim.recents_launch_prev_affiliated_task_source); 359190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 360190fe3bf88388fcb109af64571e3baa0d01f1c37Winson if (toTaskKey != null) { 361190fe3bf88388fcb109af64571e3baa0d01f1c37Winson toTask = focusedStack.findTaskWithId(toTaskKey.id); 362190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 363190fe3bf88388fcb109af64571e3baa0d01f1c37Winson numAffiliatedTasks = group.getTaskCount(); 364190fe3bf88388fcb109af64571e3baa0d01f1c37Winson break; 365190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 366190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 367190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 368190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Return early if there is no next task 369190fe3bf88388fcb109af64571e3baa0d01f1c37Winson if (toTask == null) { 370190fe3bf88388fcb109af64571e3baa0d01f1c37Winson if (numAffiliatedTasks > 1) { 371190fe3bf88388fcb109af64571e3baa0d01f1c37Winson if (showNextTask) { 372e7f138c7f0a190c86cec10fb32fa106aacae4093Winson ssp.startInPlaceAnimationOnFrontMostApplication( 373190fe3bf88388fcb109af64571e3baa0d01f1c37Winson ActivityOptions.makeCustomInPlaceAnimation(mContext, 374190fe3bf88388fcb109af64571e3baa0d01f1c37Winson R.anim.recents_launch_next_affiliated_task_bounce)); 375190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } else { 376e7f138c7f0a190c86cec10fb32fa106aacae4093Winson ssp.startInPlaceAnimationOnFrontMostApplication( 377190fe3bf88388fcb109af64571e3baa0d01f1c37Winson ActivityOptions.makeCustomInPlaceAnimation(mContext, 378190fe3bf88388fcb109af64571e3baa0d01f1c37Winson R.anim.recents_launch_prev_affiliated_task_bounce)); 379190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 380190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 381190fe3bf88388fcb109af64571e3baa0d01f1c37Winson return; 382190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 383190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 384190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Keep track of actually launched affiliated tasks 385190fe3bf88388fcb109af64571e3baa0d01f1c37Winson MetricsLogger.count(mContext, "overview_affiliated_task_launch", 1); 386190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 387190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Launch the task 388190fe3bf88388fcb109af64571e3baa0d01f1c37Winson if (toTask.isActive) { 389190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Bring an active task to the foreground 390e7f138c7f0a190c86cec10fb32fa106aacae4093Winson ssp.moveTaskToFront(toTask.key.id, launchOpts); 391190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } else { 392e7f138c7f0a190c86cec10fb32fa106aacae4093Winson ssp.startActivityFromRecents(mContext, toTask.key.id, toTask.activityLabel, launchOpts); 393190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 394190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 395190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 396190fe3bf88388fcb109af64571e3baa0d01f1c37Winson public void showNextAffiliatedTask() { 397190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Keep track of when the affiliated task is triggered 398190fe3bf88388fcb109af64571e3baa0d01f1c37Winson MetricsLogger.count(mContext, "overview_affiliated_task_next", 1); 399190fe3bf88388fcb109af64571e3baa0d01f1c37Winson showRelativeAffiliatedTask(true); 400190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 401190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 402190fe3bf88388fcb109af64571e3baa0d01f1c37Winson public void showPrevAffiliatedTask() { 403190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Keep track of when the affiliated task is triggered 404190fe3bf88388fcb109af64571e3baa0d01f1c37Winson MetricsLogger.count(mContext, "overview_affiliated_task_prev", 1); 405190fe3bf88388fcb109af64571e3baa0d01f1c37Winson showRelativeAffiliatedTask(false); 406190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 407190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 408190fe3bf88388fcb109af64571e3baa0d01f1c37Winson /** 409190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * Returns the preloaded load plan and invalidates it. 410190fe3bf88388fcb109af64571e3baa0d01f1c37Winson */ 411190fe3bf88388fcb109af64571e3baa0d01f1c37Winson public static RecentsTaskLoadPlan consumeInstanceLoadPlan() { 412190fe3bf88388fcb109af64571e3baa0d01f1c37Winson RecentsTaskLoadPlan plan = sInstanceLoadPlan; 413190fe3bf88388fcb109af64571e3baa0d01f1c37Winson sInstanceLoadPlan = null; 414190fe3bf88388fcb109af64571e3baa0d01f1c37Winson return plan; 415190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 416190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 417190fe3bf88388fcb109af64571e3baa0d01f1c37Winson /** 418190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * Prepares the header bar layout for the next transition, if the task view bounds has changed 419190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * since the last call, it will attempt to re-measure and layout the header bar to the new size. 420190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * 421190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * @param tryAndBindSearchWidget if set, will attempt to fetch and bind the search widget if one 422190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * is not already bound (can be expensive) 423190fe3bf88388fcb109af64571e3baa0d01f1c37Winson */ 424190fe3bf88388fcb109af64571e3baa0d01f1c37Winson private void reloadHeaderBarLayout(boolean tryAndBindSearchWidget) { 425e7f138c7f0a190c86cec10fb32fa106aacae4093Winson SystemServicesProxy ssp = Recents.getSystemServices(); 426e7f138c7f0a190c86cec10fb32fa106aacae4093Winson Rect windowRect = ssp.getWindowRect(); 427190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 428190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Update the configuration for the current state 429e7f138c7f0a190c86cec10fb32fa106aacae4093Winson mConfig.update(mContext, ssp, ssp.getWindowRect()); 430190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 431190fe3bf88388fcb109af64571e3baa0d01f1c37Winson if (tryAndBindSearchWidget) { 432190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Try and pre-emptively bind the search widget on startup to ensure that we 433190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // have the right thumbnail bounds to animate to. 434190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Note: We have to reload the widget id before we get the task stack bounds below 435e7f138c7f0a190c86cec10fb32fa106aacae4093Winson if (ssp.getOrBindSearchAppWidget(mContext, mAppWidgetHost) != null) { 436e7f138c7f0a190c86cec10fb32fa106aacae4093Winson mConfig.getSearchBarBounds(windowRect, mStatusBarHeight, mSearchBarBounds); 437190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 438190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 439190fe3bf88388fcb109af64571e3baa0d01f1c37Winson Rect systemInsets = new Rect(0, mStatusBarHeight, 440190fe3bf88388fcb109af64571e3baa0d01f1c37Winson (mConfig.hasTransposedNavBar ? mNavBarWidth : 0), 441190fe3bf88388fcb109af64571e3baa0d01f1c37Winson (mConfig.hasTransposedNavBar ? 0 : mNavBarHeight)); 442190fe3bf88388fcb109af64571e3baa0d01f1c37Winson mConfig.getTaskStackBounds(windowRect, systemInsets.top, systemInsets.right, 443190fe3bf88388fcb109af64571e3baa0d01f1c37Winson mSearchBarBounds, mTaskStackBounds); 444190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 445190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Rebind the header bar and draw it for the transition 446190fe3bf88388fcb109af64571e3baa0d01f1c37Winson TaskStackViewLayoutAlgorithm algo = mDummyStackView.getStackAlgorithm(); 447190fe3bf88388fcb109af64571e3baa0d01f1c37Winson Rect taskStackBounds = new Rect(mTaskStackBounds); 448190fe3bf88388fcb109af64571e3baa0d01f1c37Winson algo.setSystemInsets(systemInsets); 449190fe3bf88388fcb109af64571e3baa0d01f1c37Winson algo.computeRects(windowRect.width(), windowRect.height(), taskStackBounds); 450190fe3bf88388fcb109af64571e3baa0d01f1c37Winson Rect taskViewBounds = algo.getUntransformedTaskViewBounds(); 451190fe3bf88388fcb109af64571e3baa0d01f1c37Winson if (!taskViewBounds.equals(mLastTaskViewBounds)) { 452190fe3bf88388fcb109af64571e3baa0d01f1c37Winson mLastTaskViewBounds.set(taskViewBounds); 453190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 454190fe3bf88388fcb109af64571e3baa0d01f1c37Winson int taskViewWidth = taskViewBounds.width(); 455190fe3bf88388fcb109af64571e3baa0d01f1c37Winson synchronized (mHeaderBarLock) { 456190fe3bf88388fcb109af64571e3baa0d01f1c37Winson mHeaderBar.measure( 457190fe3bf88388fcb109af64571e3baa0d01f1c37Winson View.MeasureSpec.makeMeasureSpec(taskViewWidth, View.MeasureSpec.EXACTLY), 458190fe3bf88388fcb109af64571e3baa0d01f1c37Winson View.MeasureSpec.makeMeasureSpec(mTaskBarHeight, View.MeasureSpec.EXACTLY)); 459190fe3bf88388fcb109af64571e3baa0d01f1c37Winson mHeaderBar.layout(0, 0, taskViewWidth, mTaskBarHeight); 460190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 461190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 462190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 463190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 464190fe3bf88388fcb109af64571e3baa0d01f1c37Winson /** 465190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * Preloads the icon of a task. 466190fe3bf88388fcb109af64571e3baa0d01f1c37Winson */ 467190fe3bf88388fcb109af64571e3baa0d01f1c37Winson private void preloadIcon(ActivityManager.RunningTaskInfo task) { 468190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Ensure that we load the running task's icon 469190fe3bf88388fcb109af64571e3baa0d01f1c37Winson RecentsTaskLoadPlan.Options launchOpts = new RecentsTaskLoadPlan.Options(); 470190fe3bf88388fcb109af64571e3baa0d01f1c37Winson launchOpts.runningTaskId = task.id; 471190fe3bf88388fcb109af64571e3baa0d01f1c37Winson launchOpts.loadThumbnails = false; 472190fe3bf88388fcb109af64571e3baa0d01f1c37Winson launchOpts.onlyLoadForCache = true; 473e7f138c7f0a190c86cec10fb32fa106aacae4093Winson Recents.getTaskLoader().loadTasks(mContext, sInstanceLoadPlan, launchOpts); 474190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 475190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 476190fe3bf88388fcb109af64571e3baa0d01f1c37Winson /** 477190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * Caches the header thumbnail used for a window animation asynchronously into 478190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * {@link #mThumbnailTransitionBitmapCache}. 479190fe3bf88388fcb109af64571e3baa0d01f1c37Winson */ 480190fe3bf88388fcb109af64571e3baa0d01f1c37Winson private void preCacheThumbnailTransitionBitmapAsync(ActivityManager.RunningTaskInfo topTask, 481190fe3bf88388fcb109af64571e3baa0d01f1c37Winson TaskStack stack, TaskStackView stackView) { 482190fe3bf88388fcb109af64571e3baa0d01f1c37Winson preloadIcon(topTask); 483190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 484190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Update the header bar if necessary 485190fe3bf88388fcb109af64571e3baa0d01f1c37Winson reloadHeaderBarLayout(false /* tryAndBindSearchWidget */); 486190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 487190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Update the destination rect 488190fe3bf88388fcb109af64571e3baa0d01f1c37Winson mDummyStackView.updateMinMaxScrollForStack(stack); 489190fe3bf88388fcb109af64571e3baa0d01f1c37Winson final Task toTask = new Task(); 490190fe3bf88388fcb109af64571e3baa0d01f1c37Winson final TaskViewTransform toTransform = getThumbnailTransitionTransform(stack, stackView, 491190fe3bf88388fcb109af64571e3baa0d01f1c37Winson topTask.id, toTask); 492ab84fc56114c0963c6f701de9725f5413ab76da9Winson ForegroundThread.getHandler().post(new Runnable() { 493190fe3bf88388fcb109af64571e3baa0d01f1c37Winson @Override 494ab84fc56114c0963c6f701de9725f5413ab76da9Winson public void run() { 495ab84fc56114c0963c6f701de9725f5413ab76da9Winson final Bitmap transitionBitmap = drawThumbnailTransitionBitmap(toTask, toTransform); 496ab84fc56114c0963c6f701de9725f5413ab76da9Winson mHandler.post(new Runnable() { 497ab84fc56114c0963c6f701de9725f5413ab76da9Winson @Override 498ab84fc56114c0963c6f701de9725f5413ab76da9Winson public void run() { 499ab84fc56114c0963c6f701de9725f5413ab76da9Winson mThumbnailTransitionBitmapCache = transitionBitmap; 500ab84fc56114c0963c6f701de9725f5413ab76da9Winson mThumbnailTransitionBitmapCacheKey = toTask; 501ab84fc56114c0963c6f701de9725f5413ab76da9Winson } 502ab84fc56114c0963c6f701de9725f5413ab76da9Winson }); 503190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 504ab84fc56114c0963c6f701de9725f5413ab76da9Winson }); 505190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 506190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 507190fe3bf88388fcb109af64571e3baa0d01f1c37Winson /** 508190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * Creates the activity options for a unknown state->recents transition. 509190fe3bf88388fcb109af64571e3baa0d01f1c37Winson */ 510190fe3bf88388fcb109af64571e3baa0d01f1c37Winson private ActivityOptions getUnknownTransitionActivityOptions() { 511190fe3bf88388fcb109af64571e3baa0d01f1c37Winson return ActivityOptions.makeCustomAnimation(mContext, 512190fe3bf88388fcb109af64571e3baa0d01f1c37Winson R.anim.recents_from_unknown_enter, 513190fe3bf88388fcb109af64571e3baa0d01f1c37Winson R.anim.recents_from_unknown_exit, 514190fe3bf88388fcb109af64571e3baa0d01f1c37Winson mHandler, this); 515190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 516190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 517190fe3bf88388fcb109af64571e3baa0d01f1c37Winson /** 518190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * Creates the activity options for a home->recents transition. 519190fe3bf88388fcb109af64571e3baa0d01f1c37Winson */ 520190fe3bf88388fcb109af64571e3baa0d01f1c37Winson private ActivityOptions getHomeTransitionActivityOptions(boolean fromSearchHome) { 521190fe3bf88388fcb109af64571e3baa0d01f1c37Winson if (fromSearchHome) { 522190fe3bf88388fcb109af64571e3baa0d01f1c37Winson return ActivityOptions.makeCustomAnimation(mContext, 523190fe3bf88388fcb109af64571e3baa0d01f1c37Winson R.anim.recents_from_search_launcher_enter, 524190fe3bf88388fcb109af64571e3baa0d01f1c37Winson R.anim.recents_from_search_launcher_exit, 525190fe3bf88388fcb109af64571e3baa0d01f1c37Winson mHandler, this); 526190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 527190fe3bf88388fcb109af64571e3baa0d01f1c37Winson return ActivityOptions.makeCustomAnimation(mContext, 528190fe3bf88388fcb109af64571e3baa0d01f1c37Winson R.anim.recents_from_launcher_enter, 529190fe3bf88388fcb109af64571e3baa0d01f1c37Winson R.anim.recents_from_launcher_exit, 530190fe3bf88388fcb109af64571e3baa0d01f1c37Winson mHandler, this); 531190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 532190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 533190fe3bf88388fcb109af64571e3baa0d01f1c37Winson /** 534190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * Creates the activity options for an app->recents transition. 535190fe3bf88388fcb109af64571e3baa0d01f1c37Winson */ 536190fe3bf88388fcb109af64571e3baa0d01f1c37Winson private ActivityOptions getThumbnailTransitionActivityOptions( 537190fe3bf88388fcb109af64571e3baa0d01f1c37Winson ActivityManager.RunningTaskInfo topTask, TaskStack stack, TaskStackView stackView) { 538190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 539190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Update the destination rect 540190fe3bf88388fcb109af64571e3baa0d01f1c37Winson Task toTask = new Task(); 541190fe3bf88388fcb109af64571e3baa0d01f1c37Winson TaskViewTransform toTransform = getThumbnailTransitionTransform(stack, stackView, 542190fe3bf88388fcb109af64571e3baa0d01f1c37Winson topTask.id, toTask); 5433150e574e6e903a17193e0b90433d69c0e20ae4cWinson RectF toTaskRect = toTransform.rect; 544190fe3bf88388fcb109af64571e3baa0d01f1c37Winson Bitmap thumbnail; 545190fe3bf88388fcb109af64571e3baa0d01f1c37Winson if (mThumbnailTransitionBitmapCacheKey != null 546190fe3bf88388fcb109af64571e3baa0d01f1c37Winson && mThumbnailTransitionBitmapCacheKey.key != null 547190fe3bf88388fcb109af64571e3baa0d01f1c37Winson && mThumbnailTransitionBitmapCacheKey.key.equals(toTask.key)) { 548190fe3bf88388fcb109af64571e3baa0d01f1c37Winson thumbnail = mThumbnailTransitionBitmapCache; 549190fe3bf88388fcb109af64571e3baa0d01f1c37Winson mThumbnailTransitionBitmapCacheKey = null; 550190fe3bf88388fcb109af64571e3baa0d01f1c37Winson mThumbnailTransitionBitmapCache = null; 551190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } else { 552190fe3bf88388fcb109af64571e3baa0d01f1c37Winson preloadIcon(topTask); 553190fe3bf88388fcb109af64571e3baa0d01f1c37Winson thumbnail = drawThumbnailTransitionBitmap(toTask, toTransform); 554190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 555190fe3bf88388fcb109af64571e3baa0d01f1c37Winson if (thumbnail != null) { 556190fe3bf88388fcb109af64571e3baa0d01f1c37Winson return ActivityOptions.makeThumbnailAspectScaleDownAnimation(mDummyStackView, 5573150e574e6e903a17193e0b90433d69c0e20ae4cWinson thumbnail, (int) toTaskRect.left, (int) toTaskRect.top, 5583150e574e6e903a17193e0b90433d69c0e20ae4cWinson (int) toTaskRect.width(), (int) toTaskRect.height(), mHandler, this); 559190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 560190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 561190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // If both the screenshot and thumbnail fails, then just fall back to the default transition 562190fe3bf88388fcb109af64571e3baa0d01f1c37Winson return getUnknownTransitionActivityOptions(); 563190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 564190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 565190fe3bf88388fcb109af64571e3baa0d01f1c37Winson /** 566190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * Returns the transition rect for the given task id. 567190fe3bf88388fcb109af64571e3baa0d01f1c37Winson */ 568190fe3bf88388fcb109af64571e3baa0d01f1c37Winson private TaskViewTransform getThumbnailTransitionTransform(TaskStack stack, 569190fe3bf88388fcb109af64571e3baa0d01f1c37Winson TaskStackView stackView, int runningTaskId, Task runningTaskOut) { 570190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Find the running task in the TaskStack 571190fe3bf88388fcb109af64571e3baa0d01f1c37Winson Task task = null; 572190fe3bf88388fcb109af64571e3baa0d01f1c37Winson ArrayList<Task> tasks = stack.getTasks(); 573190fe3bf88388fcb109af64571e3baa0d01f1c37Winson if (runningTaskId != -1) { 574190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Otherwise, try and find the task with the 575190fe3bf88388fcb109af64571e3baa0d01f1c37Winson int taskCount = tasks.size(); 576190fe3bf88388fcb109af64571e3baa0d01f1c37Winson for (int i = taskCount - 1; i >= 0; i--) { 577190fe3bf88388fcb109af64571e3baa0d01f1c37Winson Task t = tasks.get(i); 578190fe3bf88388fcb109af64571e3baa0d01f1c37Winson if (t.key.id == runningTaskId) { 579190fe3bf88388fcb109af64571e3baa0d01f1c37Winson task = t; 580190fe3bf88388fcb109af64571e3baa0d01f1c37Winson runningTaskOut.copyFrom(t); 581190fe3bf88388fcb109af64571e3baa0d01f1c37Winson break; 582190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 583190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 584190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 585190fe3bf88388fcb109af64571e3baa0d01f1c37Winson if (task == null) { 586190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // If no task is specified or we can not find the task just use the front most one 587190fe3bf88388fcb109af64571e3baa0d01f1c37Winson task = tasks.get(tasks.size() - 1); 588190fe3bf88388fcb109af64571e3baa0d01f1c37Winson runningTaskOut.copyFrom(task); 589190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 590190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 591190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Get the transform for the running task 592190fe3bf88388fcb109af64571e3baa0d01f1c37Winson stackView.getScroller().setStackScrollToInitialState(); 593190fe3bf88388fcb109af64571e3baa0d01f1c37Winson mTmpTransform = stackView.getStackAlgorithm().getStackTransform(task, 594190fe3bf88388fcb109af64571e3baa0d01f1c37Winson stackView.getScroller().getStackScroll(), mTmpTransform, null); 595190fe3bf88388fcb109af64571e3baa0d01f1c37Winson return mTmpTransform; 596190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 597190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 598190fe3bf88388fcb109af64571e3baa0d01f1c37Winson /** 599190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * Draws the header of a task used for the window animation into a bitmap. 600190fe3bf88388fcb109af64571e3baa0d01f1c37Winson */ 601190fe3bf88388fcb109af64571e3baa0d01f1c37Winson private Bitmap drawThumbnailTransitionBitmap(Task toTask, TaskViewTransform toTransform) { 602190fe3bf88388fcb109af64571e3baa0d01f1c37Winson if (toTransform != null && toTask.key != null) { 603190fe3bf88388fcb109af64571e3baa0d01f1c37Winson Bitmap thumbnail; 604190fe3bf88388fcb109af64571e3baa0d01f1c37Winson synchronized (mHeaderBarLock) { 605190fe3bf88388fcb109af64571e3baa0d01f1c37Winson int toHeaderWidth = (int) (mHeaderBar.getMeasuredWidth() * toTransform.scale); 606190fe3bf88388fcb109af64571e3baa0d01f1c37Winson int toHeaderHeight = (int) (mHeaderBar.getMeasuredHeight() * toTransform.scale); 607190fe3bf88388fcb109af64571e3baa0d01f1c37Winson thumbnail = Bitmap.createBitmap(toHeaderWidth, toHeaderHeight, 608190fe3bf88388fcb109af64571e3baa0d01f1c37Winson Bitmap.Config.ARGB_8888); 609190fe3bf88388fcb109af64571e3baa0d01f1c37Winson if (Constants.DebugFlags.App.EnableTransitionThumbnailDebugMode) { 610190fe3bf88388fcb109af64571e3baa0d01f1c37Winson thumbnail.eraseColor(0xFFff0000); 611190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } else { 612190fe3bf88388fcb109af64571e3baa0d01f1c37Winson Canvas c = new Canvas(thumbnail); 613190fe3bf88388fcb109af64571e3baa0d01f1c37Winson c.scale(toTransform.scale, toTransform.scale); 614190fe3bf88388fcb109af64571e3baa0d01f1c37Winson mHeaderBar.rebindToTask(toTask); 615190fe3bf88388fcb109af64571e3baa0d01f1c37Winson mHeaderBar.draw(c); 616190fe3bf88388fcb109af64571e3baa0d01f1c37Winson c.setBitmap(null); 617190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 618190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 619190fe3bf88388fcb109af64571e3baa0d01f1c37Winson return thumbnail.createAshmemBitmap(); 620190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 621190fe3bf88388fcb109af64571e3baa0d01f1c37Winson return null; 622190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 623190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 624190fe3bf88388fcb109af64571e3baa0d01f1c37Winson /** 625190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * Shows the recents activity 626190fe3bf88388fcb109af64571e3baa0d01f1c37Winson */ 627190fe3bf88388fcb109af64571e3baa0d01f1c37Winson private void startRecentsActivity(ActivityManager.RunningTaskInfo topTask, 628190fe3bf88388fcb109af64571e3baa0d01f1c37Winson boolean isTopTaskHome) { 629e7f138c7f0a190c86cec10fb32fa106aacae4093Winson SystemServicesProxy ssp = Recents.getSystemServices(); 630e7f138c7f0a190c86cec10fb32fa106aacae4093Winson RecentsTaskLoader loader = Recents.getTaskLoader(); 631190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 632190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Update the header bar if necessary 633190fe3bf88388fcb109af64571e3baa0d01f1c37Winson reloadHeaderBarLayout(false /* tryAndBindSearchWidget */); 634190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 635190fe3bf88388fcb109af64571e3baa0d01f1c37Winson if (sInstanceLoadPlan == null) { 636190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Create a new load plan if onPreloadRecents() was never triggered 637190fe3bf88388fcb109af64571e3baa0d01f1c37Winson sInstanceLoadPlan = loader.createLoadPlan(mContext); 638190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 639190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 640190fe3bf88388fcb109af64571e3baa0d01f1c37Winson if (!sInstanceLoadPlan.hasTasks()) { 641190fe3bf88388fcb109af64571e3baa0d01f1c37Winson loader.preloadTasks(sInstanceLoadPlan, isTopTaskHome); 642190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 643190fe3bf88388fcb109af64571e3baa0d01f1c37Winson TaskStack stack = sInstanceLoadPlan.getTaskStack(); 644190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 645190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Prepare the dummy stack for the transition 646190fe3bf88388fcb109af64571e3baa0d01f1c37Winson mDummyStackView.updateMinMaxScrollForStack(stack); 647190fe3bf88388fcb109af64571e3baa0d01f1c37Winson TaskStackViewLayoutAlgorithm.VisibilityReport stackVr = 648190fe3bf88388fcb109af64571e3baa0d01f1c37Winson mDummyStackView.computeStackVisibilityReport(); 649190fe3bf88388fcb109af64571e3baa0d01f1c37Winson boolean hasRecentTasks = stack.getTaskCount() > 0; 650190fe3bf88388fcb109af64571e3baa0d01f1c37Winson boolean useThumbnailTransition = (topTask != null) && !isTopTaskHome && hasRecentTasks; 651190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 652190fe3bf88388fcb109af64571e3baa0d01f1c37Winson if (useThumbnailTransition) { 653190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Try starting with a thumbnail transition 654190fe3bf88388fcb109af64571e3baa0d01f1c37Winson ActivityOptions opts = getThumbnailTransitionActivityOptions(topTask, stack, 655190fe3bf88388fcb109af64571e3baa0d01f1c37Winson mDummyStackView); 656190fe3bf88388fcb109af64571e3baa0d01f1c37Winson if (opts != null) { 657190fe3bf88388fcb109af64571e3baa0d01f1c37Winson startRecentsActivity(topTask, opts, false /* fromHome */, 658190fe3bf88388fcb109af64571e3baa0d01f1c37Winson false /* fromSearchHome */, true /* fromThumbnail */, stackVr); 659190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } else { 660190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Fall through below to the non-thumbnail transition 661190fe3bf88388fcb109af64571e3baa0d01f1c37Winson useThumbnailTransition = false; 662190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 663190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 664190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 665190fe3bf88388fcb109af64571e3baa0d01f1c37Winson if (!useThumbnailTransition) { 666190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // If there is no thumbnail transition, but is launching from home into recents, then 667190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // use a quick home transition and do the animation from home 668190fe3bf88388fcb109af64571e3baa0d01f1c37Winson if (hasRecentTasks) { 669e7f138c7f0a190c86cec10fb32fa106aacae4093Winson String homeActivityPackage = ssp.getHomeActivityPackageName(); 670e7f138c7f0a190c86cec10fb32fa106aacae4093Winson String searchWidgetPackage = Prefs.getString(mContext, 671e7f138c7f0a190c86cec10fb32fa106aacae4093Winson Prefs.Key.SEARCH_APP_WIDGET_PACKAGE, null); 672190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 673190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Determine whether we are coming from a search owned home activity 674190fe3bf88388fcb109af64571e3baa0d01f1c37Winson boolean fromSearchHome = (homeActivityPackage != null) && 675190fe3bf88388fcb109af64571e3baa0d01f1c37Winson homeActivityPackage.equals(searchWidgetPackage); 676190fe3bf88388fcb109af64571e3baa0d01f1c37Winson ActivityOptions opts = getHomeTransitionActivityOptions(fromSearchHome); 677190fe3bf88388fcb109af64571e3baa0d01f1c37Winson startRecentsActivity(topTask, opts, true /* fromHome */, fromSearchHome, 678190fe3bf88388fcb109af64571e3baa0d01f1c37Winson false /* fromThumbnail */, stackVr); 679190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } else { 680190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Otherwise we do the normal fade from an unknown source 681190fe3bf88388fcb109af64571e3baa0d01f1c37Winson ActivityOptions opts = getUnknownTransitionActivityOptions(); 682190fe3bf88388fcb109af64571e3baa0d01f1c37Winson startRecentsActivity(topTask, opts, true /* fromHome */, 683190fe3bf88388fcb109af64571e3baa0d01f1c37Winson false /* fromSearchHome */, false /* fromThumbnail */, stackVr); 684190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 685190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 686190fe3bf88388fcb109af64571e3baa0d01f1c37Winson mLastToggleTime = SystemClock.elapsedRealtime(); 687190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 688190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 689190fe3bf88388fcb109af64571e3baa0d01f1c37Winson /** 690190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * Starts the recents activity. 691190fe3bf88388fcb109af64571e3baa0d01f1c37Winson */ 692190fe3bf88388fcb109af64571e3baa0d01f1c37Winson private void startRecentsActivity(ActivityManager.RunningTaskInfo topTask, 693190fe3bf88388fcb109af64571e3baa0d01f1c37Winson ActivityOptions opts, boolean fromHome, boolean fromSearchHome, boolean fromThumbnail, 694190fe3bf88388fcb109af64571e3baa0d01f1c37Winson TaskStackViewLayoutAlgorithm.VisibilityReport vr) { 695e7f138c7f0a190c86cec10fb32fa106aacae4093Winson mStartAnimationTriggered = false; 696e7f138c7f0a190c86cec10fb32fa106aacae4093Winson 697190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Update the configuration based on the launch options 698190fe3bf88388fcb109af64571e3baa0d01f1c37Winson RecentsActivityLaunchState launchState = mConfig.getLaunchState(); 699190fe3bf88388fcb109af64571e3baa0d01f1c37Winson launchState.launchedFromHome = fromSearchHome || fromHome; 700190fe3bf88388fcb109af64571e3baa0d01f1c37Winson launchState.launchedFromSearchHome = fromSearchHome; 701190fe3bf88388fcb109af64571e3baa0d01f1c37Winson launchState.launchedFromAppWithThumbnail = fromThumbnail; 702190fe3bf88388fcb109af64571e3baa0d01f1c37Winson launchState.launchedToTaskId = (topTask != null) ? topTask.id : -1; 703190fe3bf88388fcb109af64571e3baa0d01f1c37Winson launchState.launchedWithAltTab = mTriggeredFromAltTab; 704190fe3bf88388fcb109af64571e3baa0d01f1c37Winson launchState.launchedReuseTaskStackViews = mCanReuseTaskStackViews; 705190fe3bf88388fcb109af64571e3baa0d01f1c37Winson launchState.launchedNumVisibleTasks = vr.numVisibleTasks; 706190fe3bf88388fcb109af64571e3baa0d01f1c37Winson launchState.launchedNumVisibleThumbnails = vr.numVisibleThumbnails; 707190fe3bf88388fcb109af64571e3baa0d01f1c37Winson launchState.launchedHasConfigurationChanged = false; 708190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 709190fe3bf88388fcb109af64571e3baa0d01f1c37Winson Intent intent = new Intent(); 710190fe3bf88388fcb109af64571e3baa0d01f1c37Winson intent.setClassName(RECENTS_PACKAGE, RECENTS_ACTIVITY); 711190fe3bf88388fcb109af64571e3baa0d01f1c37Winson intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK 712190fe3bf88388fcb109af64571e3baa0d01f1c37Winson | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS 713190fe3bf88388fcb109af64571e3baa0d01f1c37Winson | Intent.FLAG_ACTIVITY_TASK_ON_HOME); 714190fe3bf88388fcb109af64571e3baa0d01f1c37Winson if (opts != null) { 715190fe3bf88388fcb109af64571e3baa0d01f1c37Winson mContext.startActivityAsUser(intent, opts.toBundle(), UserHandle.CURRENT); 716190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } else { 717190fe3bf88388fcb109af64571e3baa0d01f1c37Winson mContext.startActivityAsUser(intent, UserHandle.CURRENT); 718190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 719190fe3bf88388fcb109af64571e3baa0d01f1c37Winson mCanReuseTaskStackViews = true; 720190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 721190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 722190fe3bf88388fcb109af64571e3baa0d01f1c37Winson /**** OnAnimationStartedListener Implementation ****/ 723190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 724190fe3bf88388fcb109af64571e3baa0d01f1c37Winson @Override 725190fe3bf88388fcb109af64571e3baa0d01f1c37Winson public void onAnimationStarted() { 726190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Notify recents to start the enter animation 727190fe3bf88388fcb109af64571e3baa0d01f1c37Winson if (!mStartAnimationTriggered) { 728412e18058dc2cd5779d2451fce7fd74631f9e237Winson mStartAnimationTriggered = true; 729e7f138c7f0a190c86cec10fb32fa106aacae4093Winson EventBus.getDefault().post(new EnterRecentsWindowAnimationStartedEvent()); 730190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 731190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 732190fe3bf88388fcb109af64571e3baa0d01f1c37Winson} 733