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