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 19e693aafe0511c2a7ffc571b22abeefba44046225Winsonimport static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID; 2094bc4f2238d8eefb77c63a560aa0de1335ee57abWinsonimport static android.view.View.MeasureSpec; 21e693aafe0511c2a7ffc571b22abeefba44046225Winson 22190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport android.app.ActivityManager; 23190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport android.app.ActivityOptions; 24190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport android.content.ActivityNotFoundException; 25190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport android.content.Context; 26190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport android.content.Intent; 27190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport android.content.res.Resources; 28190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport android.graphics.Bitmap; 29190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport android.graphics.Canvas; 30190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport android.graphics.Rect; 313150e574e6e903a17193e0b90433d69c0e20ae4cWinsonimport android.graphics.RectF; 3222574afa00b7e32b7c4c5a1b98deebd67751b364Winsonimport android.graphics.drawable.Drawable; 33190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport android.os.Handler; 34190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport android.os.SystemClock; 35190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport android.os.UserHandle; 361b58561f66a9453754b1b419296899fdc08b4c93Winsonimport android.util.Log; 37190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport android.util.MutableBoolean; 38d64ef3ef33c50a03b4be3b2baaa93aab7319fca8Filip Gruszczynskiimport android.view.AppTransitionAnimationSpec; 39190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport android.view.LayoutInflater; 40b61e654b9a46e79827355104760a3ac5228380bcWinsonimport android.view.ViewConfiguration; 41db21bbd2caf05322864f09ec45a0c572cf071123Jorim Jaggiimport android.view.WindowManager; 42c0d7058b14c24cd07912f5629c26b39b7b4673d5Winson 43675c5d8e5a6fd98e8324798e1ef31df20cee5b0fWinsonimport android.widget.Toast; 44190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport com.android.internal.logging.MetricsLogger; 45db21bbd2caf05322864f09ec45a0c572cf071123Jorim Jaggiimport com.android.internal.policy.DockedDividerUtils; 46190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport com.android.systemui.R; 47190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport com.android.systemui.SystemUIApplication; 48412e18058dc2cd5779d2451fce7fd74631f9e237Winsonimport com.android.systemui.recents.events.EventBus; 49899327f5cbbfb0eae5562b262ccea860c98f6bc4Jorim Jaggiimport com.android.systemui.recents.events.activity.DockedTopTaskEvent; 501b58561f66a9453754b1b419296899fdc08b4c93Winsonimport com.android.systemui.recents.events.activity.EnterRecentsWindowLastAnimationFrameEvent; 51412e18058dc2cd5779d2451fce7fd74631f9e237Winsonimport com.android.systemui.recents.events.activity.HideRecentsEvent; 520d14d4da91c3d8b1221269712d5abf43a7cf9f31Winsonimport com.android.systemui.recents.events.activity.IterateRecentsEvent; 53b61e654b9a46e79827355104760a3ac5228380bcWinsonimport com.android.systemui.recents.events.activity.LaunchNextTaskRequestEvent; 54cdb06caebb5f6f554b2ed8c76963970d8cc0ab54Jorim Jaggiimport com.android.systemui.recents.events.activity.RecentsActivityStartingEvent; 55412e18058dc2cd5779d2451fce7fd74631f9e237Winsonimport com.android.systemui.recents.events.activity.ToggleRecentsEvent; 56190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport com.android.systemui.recents.events.component.RecentsVisibilityChangedEvent; 57190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport com.android.systemui.recents.events.component.ScreenPinningRequestEvent; 58dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggiimport com.android.systemui.recents.events.ui.DraggingInRecentsEndedEvent; 59dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggiimport com.android.systemui.recents.events.ui.DraggingInRecentsEvent; 606b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinsonimport com.android.systemui.recents.misc.DozeTrigger; 61ab84fc56114c0963c6f701de9725f5413ab76da9Winsonimport com.android.systemui.recents.misc.ForegroundThread; 62190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport com.android.systemui.recents.misc.SystemServicesProxy; 63938a50b424eb73ee96d34c96b5e2cbd11f733d7aJaewan Kimimport com.android.systemui.recents.misc.SystemServicesProxy.TaskStackListener; 64190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport com.android.systemui.recents.model.RecentsTaskLoadPlan; 65190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport com.android.systemui.recents.model.RecentsTaskLoader; 66190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport com.android.systemui.recents.model.Task; 67190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport com.android.systemui.recents.model.TaskGrouping; 68190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport com.android.systemui.recents.model.TaskStack; 6936a5a2c7003ef8157f276b411c3fda47ad2f75e3Winsonimport com.android.systemui.recents.views.TaskStackLayoutAlgorithm; 701b58561f66a9453754b1b419296899fdc08b4c93Winsonimport com.android.systemui.recents.views.TaskStackView; 71e693aafe0511c2a7ffc571b22abeefba44046225Winsonimport com.android.systemui.recents.views.TaskStackViewScroller; 72190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport com.android.systemui.recents.views.TaskViewHeader; 73190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport com.android.systemui.recents.views.TaskViewTransform; 74db21bbd2caf05322864f09ec45a0c572cf071123Jorim Jaggiimport com.android.systemui.stackdivider.DividerView; 75d8b1d63f96580fe961e1751e7b4f56c90c1e0a76Winsonimport com.android.systemui.statusbar.BaseStatusBar; 76cdb06caebb5f6f554b2ed8c76963970d8cc0ab54Jorim Jaggiimport com.android.systemui.statusbar.phone.NavigationBarGestureHelper; 77190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport com.android.systemui.statusbar.phone.PhoneStatusBar; 78190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 79190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport java.util.ArrayList; 80190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 81190fe3bf88388fcb109af64571e3baa0d01f1c37Winson/** 82190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * An implementation of the Recents component for the current user. For secondary users, this can 83190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * be called remotely from the system user. 84190fe3bf88388fcb109af64571e3baa0d01f1c37Winson */ 85cdb06caebb5f6f554b2ed8c76963970d8cc0ab54Jorim Jaggipublic class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener { 86190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 87190fe3bf88388fcb109af64571e3baa0d01f1c37Winson private final static String TAG = "RecentsImpl"; 88b61e654b9a46e79827355104760a3ac5228380bcWinson 896b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson // The minimum amount of time between each recents button press that we will handle 906b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson private final static int MIN_TOGGLE_DELAY_MS = 350; 91b61e654b9a46e79827355104760a3ac5228380bcWinson 926b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson // The duration within which the user releasing the alt tab (from when they pressed alt tab) 936b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson // that the fast alt-tab animation will run. If the user's alt-tab takes longer than this 946b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson // duration, then we will toggle recents after this duration. 956b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson private final static int FAST_ALT_TAB_DELAY_MS = 225; 96190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 97190fe3bf88388fcb109af64571e3baa0d01f1c37Winson public final static String RECENTS_PACKAGE = "com.android.systemui"; 98190fe3bf88388fcb109af64571e3baa0d01f1c37Winson public final static String RECENTS_ACTIVITY = "com.android.systemui.recents.RecentsActivity"; 99e693aafe0511c2a7ffc571b22abeefba44046225Winson 100190fe3bf88388fcb109af64571e3baa0d01f1c37Winson /** 101938a50b424eb73ee96d34c96b5e2cbd11f733d7aJaewan Kim * An implementation of TaskStackListener, that allows us to listen for changes to the system 102190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * task stacks and update recents accordingly. 103190fe3bf88388fcb109af64571e3baa0d01f1c37Winson */ 104938a50b424eb73ee96d34c96b5e2cbd11f733d7aJaewan Kim class TaskStackListenerImpl extends TaskStackListener { 105190fe3bf88388fcb109af64571e3baa0d01f1c37Winson @Override 106190fe3bf88388fcb109af64571e3baa0d01f1c37Winson public void onTaskStackChanged() { 107938a50b424eb73ee96d34c96b5e2cbd11f733d7aJaewan Kim // Preloads the next task 108a0fdeec66caa4d70786c7f6f31f79a24eef9da10Jorim Jaggi RecentsConfiguration config = Recents.getConfiguration(); 109190fe3bf88388fcb109af64571e3baa0d01f1c37Winson if (config.svelteLevel == RecentsConfiguration.SVELTE_NONE) { 110e7f138c7f0a190c86cec10fb32fa106aacae4093Winson RecentsTaskLoader loader = Recents.getTaskLoader(); 111e7f138c7f0a190c86cec10fb32fa106aacae4093Winson SystemServicesProxy ssp = Recents.getSystemServices(); 112d46b72788e8811d2e423ea1e5b2ff104ecb7f721Winson ActivityManager.RunningTaskInfo runningTaskInfo = ssp.getRunningTask(); 113190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 114190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Load the next task only if we aren't svelte 115190fe3bf88388fcb109af64571e3baa0d01f1c37Winson RecentsTaskLoadPlan plan = loader.createLoadPlan(mContext); 116dfd7be012b889f92d3e7e6d80ff7fe6b55c75901Winson loader.preloadTasks(plan, -1, false /* includeFrontMostExcludedTask */); 117190fe3bf88388fcb109af64571e3baa0d01f1c37Winson RecentsTaskLoadPlan.Options launchOpts = new RecentsTaskLoadPlan.Options(); 118190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // This callback is made when a new activity is launched and the old one is paused 119190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // so ignore the current activity and try and preload the thumbnail for the 120190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // previous one. 121190fe3bf88388fcb109af64571e3baa0d01f1c37Winson if (runningTaskInfo != null) { 122190fe3bf88388fcb109af64571e3baa0d01f1c37Winson launchOpts.runningTaskId = runningTaskInfo.id; 123190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 124190fe3bf88388fcb109af64571e3baa0d01f1c37Winson launchOpts.numVisibleTasks = 2; 125190fe3bf88388fcb109af64571e3baa0d01f1c37Winson launchOpts.numVisibleTaskThumbnails = 2; 126190fe3bf88388fcb109af64571e3baa0d01f1c37Winson launchOpts.onlyLoadForCache = true; 127190fe3bf88388fcb109af64571e3baa0d01f1c37Winson launchOpts.onlyLoadPausedActivities = true; 128190fe3bf88388fcb109af64571e3baa0d01f1c37Winson loader.loadTasks(mContext, plan, launchOpts); 129190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 130190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 131190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 132190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 1334bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan protected static RecentsTaskLoadPlan sInstanceLoadPlan; 134190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 1354bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan protected Context mContext; 1364bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan protected Handler mHandler; 137190fe3bf88388fcb109af64571e3baa0d01f1c37Winson TaskStackListenerImpl mTaskStackListener; 138dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi boolean mDraggingInRecents; 139e161f08e98fdbe6fe83f70ffa1ea11142a027ebeJorim Jaggi boolean mLaunchedWhileDocking; 140190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 141190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Task launching 142190fe3bf88388fcb109af64571e3baa0d01f1c37Winson Rect mTaskStackBounds = new Rect(); 143190fe3bf88388fcb109af64571e3baa0d01f1c37Winson TaskViewTransform mTmpTransform = new TaskViewTransform(); 144190fe3bf88388fcb109af64571e3baa0d01f1c37Winson int mStatusBarHeight; 145190fe3bf88388fcb109af64571e3baa0d01f1c37Winson int mNavBarHeight; 146190fe3bf88388fcb109af64571e3baa0d01f1c37Winson int mNavBarWidth; 147190fe3bf88388fcb109af64571e3baa0d01f1c37Winson int mTaskBarHeight; 148190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 149190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Header (for transition) 150190fe3bf88388fcb109af64571e3baa0d01f1c37Winson TaskViewHeader mHeaderBar; 151190fe3bf88388fcb109af64571e3baa0d01f1c37Winson final Object mHeaderBarLock = new Object(); 1524bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan protected TaskStackView mDummyStackView; 153190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 154190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Variables to keep track of if we need to start recents after binding 1554bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan protected boolean mTriggeredFromAltTab; 1564bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan protected long mLastToggleTime; 1576b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson DozeTrigger mFastAltTabTrigger = new DozeTrigger(FAST_ALT_TAB_DELAY_MS, new Runnable() { 1586b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson @Override 1596b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson public void run() { 1606b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson // When this fires, then the user has not released alt-tab for at least 1616b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson // FAST_ALT_TAB_DELAY_MS milliseconds 162435b2e43cb131d0b38ba19f335aec78bb83944b2Jorim Jaggi showRecents(mTriggeredFromAltTab, false /* draggingInRecents */, true /* animate */, 163db21bbd2caf05322864f09ec45a0c572cf071123Jorim Jaggi false /* reloadTasks */, false /* fromHome */, 164db21bbd2caf05322864f09ec45a0c572cf071123Jorim Jaggi DividerView.INVALID_RECENTS_GROW_TARGET); 1656b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson } 1666b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson }); 167190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 168aeb298c4db913b376fb6053ec30c132a93e04635Winson protected Bitmap mThumbTransitionBitmapCache; 169190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 170190fe3bf88388fcb109af64571e3baa0d01f1c37Winson public RecentsImpl(Context context) { 171190fe3bf88388fcb109af64571e3baa0d01f1c37Winson mContext = context; 172190fe3bf88388fcb109af64571e3baa0d01f1c37Winson mHandler = new Handler(); 173190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 174ab84fc56114c0963c6f701de9725f5413ab76da9Winson // Initialize the static foreground thread 175ab84fc56114c0963c6f701de9725f5413ab76da9Winson ForegroundThread.get(); 176ab84fc56114c0963c6f701de9725f5413ab76da9Winson 177190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Register the task stack listener 178938a50b424eb73ee96d34c96b5e2cbd11f733d7aJaewan Kim mTaskStackListener = new TaskStackListenerImpl(); 179e7f138c7f0a190c86cec10fb32fa106aacae4093Winson SystemServicesProxy ssp = Recents.getSystemServices(); 180e7f138c7f0a190c86cec10fb32fa106aacae4093Winson ssp.registerTaskStackListener(mTaskStackListener); 181190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 182190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Initialize the static configuration resources 183670ea71f1b4ae59a0cd6608ae44b0fb78a1144c4Winson LayoutInflater inflater = LayoutInflater.from(mContext); 184670ea71f1b4ae59a0cd6608ae44b0fb78a1144c4Winson mDummyStackView = new TaskStackView(mContext); 185670ea71f1b4ae59a0cd6608ae44b0fb78a1144c4Winson mHeaderBar = (TaskViewHeader) inflater.inflate(R.layout.recents_task_view_header, 186670ea71f1b4ae59a0cd6608ae44b0fb78a1144c4Winson null, false); 187670ea71f1b4ae59a0cd6608ae44b0fb78a1144c4Winson reloadResources(); 18816ef39a7f6f000af761cf2c2a3e2823a0fbd0c4cWinson } 189190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 190501d59dcea4e48f4abf00fbe671d17290cb1e66cWinson Chung public void onBootCompleted() { 191190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // When we start, preload the data associated with the previous recent tasks. 192190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // We can use a new plan since the caches will be the same. 193e7f138c7f0a190c86cec10fb32fa106aacae4093Winson RecentsTaskLoader loader = Recents.getTaskLoader(); 194190fe3bf88388fcb109af64571e3baa0d01f1c37Winson RecentsTaskLoadPlan plan = loader.createLoadPlan(mContext); 195dfd7be012b889f92d3e7e6d80ff7fe6b55c75901Winson loader.preloadTasks(plan, -1, false /* includeFrontMostExcludedTask */); 196190fe3bf88388fcb109af64571e3baa0d01f1c37Winson RecentsTaskLoadPlan.Options launchOpts = new RecentsTaskLoadPlan.Options(); 197296278a0679375b8c43962a9e3c9bb4e8ab201e7Winson Chung launchOpts.numVisibleTasks = loader.getIconCacheSize(); 198190fe3bf88388fcb109af64571e3baa0d01f1c37Winson launchOpts.numVisibleTaskThumbnails = loader.getThumbnailCacheSize(); 199190fe3bf88388fcb109af64571e3baa0d01f1c37Winson launchOpts.onlyLoadForCache = true; 200190fe3bf88388fcb109af64571e3baa0d01f1c37Winson loader.loadTasks(mContext, plan, launchOpts); 201190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 202190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 203190fe3bf88388fcb109af64571e3baa0d01f1c37Winson public void onConfigurationChanged() { 20496f78f50464a0f394802ff0709ba7276976ef275Winson Resources res = mContext.getResources(); 205670ea71f1b4ae59a0cd6608ae44b0fb78a1144c4Winson reloadResources(); 206670ea71f1b4ae59a0cd6608ae44b0fb78a1144c4Winson mDummyStackView.reloadOnConfigurationChange(); 20796f78f50464a0f394802ff0709ba7276976ef275Winson // Update the header bar direction directly as it is not attached to anything and does not 20896f78f50464a0f394802ff0709ba7276976ef275Winson // layout except in updateHeaderBarLayout() 20996f78f50464a0f394802ff0709ba7276976ef275Winson mHeaderBar.setLayoutDirection(res.getConfiguration().getLayoutDirection()); 210670ea71f1b4ae59a0cd6608ae44b0fb78a1144c4Winson mHeaderBar.onConfigurationChanged(); 21196f78f50464a0f394802ff0709ba7276976ef275Winson mHeaderBar.forceLayout(); 21296f78f50464a0f394802ff0709ba7276976ef275Winson mHeaderBar.measure( 21396f78f50464a0f394802ff0709ba7276976ef275Winson MeasureSpec.makeMeasureSpec(mHeaderBar.getMeasuredWidth(), MeasureSpec.EXACTLY), 21496f78f50464a0f394802ff0709ba7276976ef275Winson MeasureSpec.makeMeasureSpec(mHeaderBar.getMeasuredHeight(), MeasureSpec.EXACTLY)); 215190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 216190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 217190fe3bf88388fcb109af64571e3baa0d01f1c37Winson /** 218190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * This is only called from the system user's Recents. Secondary users will instead proxy their 219190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * visibility change events through to the system user via 220190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * {@link Recents#onBusEvent(RecentsVisibilityChangedEvent)}. 221190fe3bf88388fcb109af64571e3baa0d01f1c37Winson */ 222190fe3bf88388fcb109af64571e3baa0d01f1c37Winson public void onVisibilityChanged(Context context, boolean visible) { 223ab216609f1608e61827d955fcc9fd0560bc52e4dWinson Recents.getSystemServices().setRecentsVisibility(visible); 224190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 225190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 226190fe3bf88388fcb109af64571e3baa0d01f1c37Winson /** 227190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * This is only called from the system user's Recents. Secondary users will instead proxy their 228190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * visibility change events through to the system user via 229190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * {@link Recents#onBusEvent(ScreenPinningRequestEvent)}. 230190fe3bf88388fcb109af64571e3baa0d01f1c37Winson */ 2310f051f5abdb31024d862a954cc4c4716b1dde616Andrii Kulian public void onStartScreenPinning(Context context, int taskId) { 232190fe3bf88388fcb109af64571e3baa0d01f1c37Winson SystemUIApplication app = (SystemUIApplication) context; 233190fe3bf88388fcb109af64571e3baa0d01f1c37Winson PhoneStatusBar statusBar = app.getComponent(PhoneStatusBar.class); 234190fe3bf88388fcb109af64571e3baa0d01f1c37Winson if (statusBar != null) { 2350f051f5abdb31024d862a954cc4c4716b1dde616Andrii Kulian statusBar.showScreenPinningRequest(taskId, false); 236190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 237190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 238190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 239bb42a46631b4cecdd03bd628feeb8270d412ebd3Jorim Jaggi public void showRecents(boolean triggeredFromAltTab, boolean draggingInRecents, 240db21bbd2caf05322864f09ec45a0c572cf071123Jorim Jaggi boolean animate, boolean launchedWhileDockingTask, boolean fromHome, 241db21bbd2caf05322864f09ec45a0c572cf071123Jorim Jaggi int growTarget) { 242190fe3bf88388fcb109af64571e3baa0d01f1c37Winson mTriggeredFromAltTab = triggeredFromAltTab; 243dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi mDraggingInRecents = draggingInRecents; 244e161f08e98fdbe6fe83f70ffa1ea11142a027ebeJorim Jaggi mLaunchedWhileDocking = launchedWhileDockingTask; 245e693aafe0511c2a7ffc571b22abeefba44046225Winson if (mFastAltTabTrigger.isAsleep()) { 246e693aafe0511c2a7ffc571b22abeefba44046225Winson // Fast alt-tab duration has elapsed, fall through to showing Recents and reset 247e693aafe0511c2a7ffc571b22abeefba44046225Winson mFastAltTabTrigger.stopDozing(); 2486b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson } else if (mFastAltTabTrigger.isDozing()) { 249e693aafe0511c2a7ffc571b22abeefba44046225Winson // Fast alt-tab duration has not elapsed. If this is triggered by a different 250e693aafe0511c2a7ffc571b22abeefba44046225Winson // showRecents() call, then ignore that call for now. 251e693aafe0511c2a7ffc571b22abeefba44046225Winson // TODO: We can not handle quick tabs that happen between the initial showRecents() call 252e693aafe0511c2a7ffc571b22abeefba44046225Winson // that started the activity and the activity starting up. The severity of this 253e693aafe0511c2a7ffc571b22abeefba44046225Winson // is inversely proportional to the FAST_ALT_TAB_DELAY_MS duration though. 2546b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson if (!triggeredFromAltTab) { 2556b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson return; 2566b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson } 2576b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson mFastAltTabTrigger.stopDozing(); 258e693aafe0511c2a7ffc571b22abeefba44046225Winson } else if (triggeredFromAltTab) { 259e693aafe0511c2a7ffc571b22abeefba44046225Winson // The fast alt-tab detector is not yet running, so start the trigger and wait for the 260e693aafe0511c2a7ffc571b22abeefba44046225Winson // hideRecents() call, or for the fast alt-tab duration to elapse 261e693aafe0511c2a7ffc571b22abeefba44046225Winson mFastAltTabTrigger.startDozing(); 262e693aafe0511c2a7ffc571b22abeefba44046225Winson return; 2636b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson } 264190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 265190fe3bf88388fcb109af64571e3baa0d01f1c37Winson try { 266190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Check if the top task is in the home stack, and start the recents activity 267e7f138c7f0a190c86cec10fb32fa106aacae4093Winson SystemServicesProxy ssp = Recents.getSystemServices(); 268d7cb517b4ce10fa98213da18ccdb2261fb797f7cWinson boolean forceVisible = launchedWhileDockingTask || draggingInRecents; 269d7cb517b4ce10fa98213da18ccdb2261fb797f7cWinson MutableBoolean isHomeStackVisible = new MutableBoolean(forceVisible); 270d7cb517b4ce10fa98213da18ccdb2261fb797f7cWinson if (forceVisible || !ssp.isRecentsActivityVisible(isHomeStackVisible)) { 271d46b72788e8811d2e423ea1e5b2ff104ecb7f721Winson ActivityManager.RunningTaskInfo runningTask = ssp.getRunningTask(); 272d46b72788e8811d2e423ea1e5b2ff104ecb7f721Winson startRecentsActivity(runningTask, isHomeStackVisible.value || fromHome, animate, 273d46b72788e8811d2e423ea1e5b2ff104ecb7f721Winson growTarget); 274190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 275190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } catch (ActivityNotFoundException e) { 2761b58561f66a9453754b1b419296899fdc08b4c93Winson Log.e(TAG, "Failed to launch RecentsActivity", e); 277190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 278190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 279190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 280190fe3bf88388fcb109af64571e3baa0d01f1c37Winson public void hideRecents(boolean triggeredFromAltTab, boolean triggeredFromHomeKey) { 2812799eca21715390faf10596884b65165528f89c4Winson if (triggeredFromAltTab && mFastAltTabTrigger.isDozing()) { 2822799eca21715390faf10596884b65165528f89c4Winson // The user has released alt-tab before the trigger has run, so just show the next 2832799eca21715390faf10596884b65165528f89c4Winson // task immediately 2842799eca21715390faf10596884b65165528f89c4Winson showNextTask(); 2856b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson 2862799eca21715390faf10596884b65165528f89c4Winson // Cancel the fast alt-tab trigger 2872799eca21715390faf10596884b65165528f89c4Winson mFastAltTabTrigger.stopDozing(); 2882799eca21715390faf10596884b65165528f89c4Winson return; 289190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 2902799eca21715390faf10596884b65165528f89c4Winson 2912799eca21715390faf10596884b65165528f89c4Winson // Defer to the activity to handle hiding recents, if it handles it, then it must still 2922799eca21715390faf10596884b65165528f89c4Winson // be visible 2932799eca21715390faf10596884b65165528f89c4Winson EventBus.getDefault().post(new HideRecentsEvent(triggeredFromAltTab, 2942799eca21715390faf10596884b65165528f89c4Winson triggeredFromHomeKey)); 295190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 296190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 297db21bbd2caf05322864f09ec45a0c572cf071123Jorim Jaggi public void toggleRecents(int growTarget) { 2986b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson // Skip this toggle if we are already waiting to trigger recents via alt-tab 2996b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson if (mFastAltTabTrigger.isDozing()) { 3006b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson return; 3016b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson } 3026b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson 303dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi mDraggingInRecents = false; 304e161f08e98fdbe6fe83f70ffa1ea11142a027ebeJorim Jaggi mLaunchedWhileDocking = false; 305190fe3bf88388fcb109af64571e3baa0d01f1c37Winson mTriggeredFromAltTab = false; 306190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 307190fe3bf88388fcb109af64571e3baa0d01f1c37Winson try { 308e7f138c7f0a190c86cec10fb32fa106aacae4093Winson SystemServicesProxy ssp = Recents.getSystemServices(); 309d46b72788e8811d2e423ea1e5b2ff104ecb7f721Winson MutableBoolean isHomeStackVisible = new MutableBoolean(true); 310b61e654b9a46e79827355104760a3ac5228380bcWinson long elapsedTime = SystemClock.elapsedRealtime() - mLastToggleTime; 311b61e654b9a46e79827355104760a3ac5228380bcWinson 312d46b72788e8811d2e423ea1e5b2ff104ecb7f721Winson if (ssp.isRecentsActivityVisible(isHomeStackVisible)) { 313e693aafe0511c2a7ffc571b22abeefba44046225Winson RecentsDebugFlags debugFlags = Recents.getDebugFlags(); 3145da4347b41b105dc6c6c01bf2810af3ce3013229Winson RecentsConfiguration config = Recents.getConfiguration(); 3155da4347b41b105dc6c6c01bf2810af3ce3013229Winson RecentsActivityLaunchState launchState = config.getLaunchState(); 316ead5c0fc20e5c60a68cd017af0b8eacaf1167a1cWinson Chung if (!launchState.launchedWithAltTab) { 317b61e654b9a46e79827355104760a3ac5228380bcWinson // If the user taps quickly 318e693aafe0511c2a7ffc571b22abeefba44046225Winson if (!debugFlags.isPagingEnabled() || 319e693aafe0511c2a7ffc571b22abeefba44046225Winson (ViewConfiguration.getDoubleTapMinTime() < elapsedTime && 320e693aafe0511c2a7ffc571b22abeefba44046225Winson elapsedTime < ViewConfiguration.getDoubleTapTimeout())) { 321b61e654b9a46e79827355104760a3ac5228380bcWinson // Launch the next focused task 322b61e654b9a46e79827355104760a3ac5228380bcWinson EventBus.getDefault().post(new LaunchNextTaskRequestEvent()); 323b61e654b9a46e79827355104760a3ac5228380bcWinson } else { 324b61e654b9a46e79827355104760a3ac5228380bcWinson // Notify recents to move onto the next task 325b61e654b9a46e79827355104760a3ac5228380bcWinson EventBus.getDefault().post(new IterateRecentsEvent()); 326b61e654b9a46e79827355104760a3ac5228380bcWinson } 3270d14d4da91c3d8b1221269712d5abf43a7cf9f31Winson } else { 3280d14d4da91c3d8b1221269712d5abf43a7cf9f31Winson // If the user has toggled it too quickly, then just eat up the event here (it's 3290d14d4da91c3d8b1221269712d5abf43a7cf9f31Winson // better than showing a janky screenshot). 3300d14d4da91c3d8b1221269712d5abf43a7cf9f31Winson // NOTE: Ideally, the screenshot mechanism would take the window transform into 3310d14d4da91c3d8b1221269712d5abf43a7cf9f31Winson // account 332b61e654b9a46e79827355104760a3ac5228380bcWinson if (elapsedTime < MIN_TOGGLE_DELAY_MS) { 3330d14d4da91c3d8b1221269712d5abf43a7cf9f31Winson return; 3340d14d4da91c3d8b1221269712d5abf43a7cf9f31Winson } 3350d14d4da91c3d8b1221269712d5abf43a7cf9f31Winson 3360d14d4da91c3d8b1221269712d5abf43a7cf9f31Winson EventBus.getDefault().post(new ToggleRecentsEvent()); 3370d14d4da91c3d8b1221269712d5abf43a7cf9f31Winson mLastToggleTime = SystemClock.elapsedRealtime(); 3380d14d4da91c3d8b1221269712d5abf43a7cf9f31Winson } 339190fe3bf88388fcb109af64571e3baa0d01f1c37Winson return; 340190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } else { 3410d14d4da91c3d8b1221269712d5abf43a7cf9f31Winson // If the user has toggled it too quickly, then just eat up the event here (it's 3420d14d4da91c3d8b1221269712d5abf43a7cf9f31Winson // better than showing a janky screenshot). 3430d14d4da91c3d8b1221269712d5abf43a7cf9f31Winson // NOTE: Ideally, the screenshot mechanism would take the window transform into 3440d14d4da91c3d8b1221269712d5abf43a7cf9f31Winson // account 345b61e654b9a46e79827355104760a3ac5228380bcWinson if (elapsedTime < MIN_TOGGLE_DELAY_MS) { 3460d14d4da91c3d8b1221269712d5abf43a7cf9f31Winson return; 3470d14d4da91c3d8b1221269712d5abf43a7cf9f31Winson } 3480d14d4da91c3d8b1221269712d5abf43a7cf9f31Winson 349190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Otherwise, start the recents activity 350d46b72788e8811d2e423ea1e5b2ff104ecb7f721Winson ActivityManager.RunningTaskInfo runningTask = ssp.getRunningTask(); 351d46b72788e8811d2e423ea1e5b2ff104ecb7f721Winson startRecentsActivity(runningTask, isHomeStackVisible.value, true /* animate */, 352d46b72788e8811d2e423ea1e5b2ff104ecb7f721Winson growTarget); 353d8b1d63f96580fe961e1751e7b4f56c90c1e0a76Winson 354d8b1d63f96580fe961e1751e7b4f56c90c1e0a76Winson // Only close the other system windows if we are actually showing recents 355d8b1d63f96580fe961e1751e7b4f56c90c1e0a76Winson ssp.sendCloseSystemWindows(BaseStatusBar.SYSTEM_DIALOG_REASON_RECENT_APPS); 3560d14d4da91c3d8b1221269712d5abf43a7cf9f31Winson mLastToggleTime = SystemClock.elapsedRealtime(); 357190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 358190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } catch (ActivityNotFoundException e) { 3591b58561f66a9453754b1b419296899fdc08b4c93Winson Log.e(TAG, "Failed to launch RecentsActivity", e); 360190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 361190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 362190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 363190fe3bf88388fcb109af64571e3baa0d01f1c37Winson public void preloadRecents() { 364190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Preload only the raw task list into a new load plan (which will be consumed by the 365190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // RecentsActivity) only if there is a task to animate to. 366e7f138c7f0a190c86cec10fb32fa106aacae4093Winson SystemServicesProxy ssp = Recents.getSystemServices(); 367d46b72788e8811d2e423ea1e5b2ff104ecb7f721Winson MutableBoolean isHomeStackVisible = new MutableBoolean(true); 368d46b72788e8811d2e423ea1e5b2ff104ecb7f721Winson if (!ssp.isRecentsActivityVisible(isHomeStackVisible)) { 369d46b72788e8811d2e423ea1e5b2ff104ecb7f721Winson ActivityManager.RunningTaskInfo runningTask = ssp.getRunningTask(); 3705b4e0d2b11b2b3579bac36fde5ac3805346618ccWinson RecentsTaskLoader loader = Recents.getTaskLoader(); 3715b4e0d2b11b2b3579bac36fde5ac3805346618ccWinson sInstanceLoadPlan = loader.createLoadPlan(mContext); 372dfd7be012b889f92d3e7e6d80ff7fe6b55c75901Winson sInstanceLoadPlan.preloadRawTasks(!isHomeStackVisible.value); 373dfd7be012b889f92d3e7e6d80ff7fe6b55c75901Winson loader.preloadTasks(sInstanceLoadPlan, runningTask.id, !isHomeStackVisible.value); 374190fe3bf88388fcb109af64571e3baa0d01f1c37Winson TaskStack stack = sInstanceLoadPlan.getTaskStack(); 3754b057c6787624b75613769a857ccdf51114bb7f2Winson if (stack.getTaskCount() > 0) { 376aeb298c4db913b376fb6053ec30c132a93e04635Winson // Only preload the icon (but not the thumbnail since it may not have been taken for 377aeb298c4db913b376fb6053ec30c132a93e04635Winson // the pausing activity) 378c4a038ad28009eb5840cf9f6aefbd2c873cee02eWinson preloadIcon(runningTask.id); 379aeb298c4db913b376fb6053ec30c132a93e04635Winson 380aeb298c4db913b376fb6053ec30c132a93e04635Winson // At this point, we don't know anything about the stack state. So only calculate 381aeb298c4db913b376fb6053ec30c132a93e04635Winson // the dimensions of the thumbnail that we need for the transition into Recents, but 382aeb298c4db913b376fb6053ec30c132a93e04635Winson // do not draw it until we construct the activity options when we start Recents 383db21bbd2caf05322864f09ec45a0c572cf071123Jorim Jaggi updateHeaderBarLayout(stack, null /* window rect override*/); 384190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 385190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 386190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 387190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 388190fe3bf88388fcb109af64571e3baa0d01f1c37Winson public void cancelPreloadingRecents() { 389190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Do nothing 390190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 391190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 392dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi public void onDraggingInRecents(float distanceFromTop) { 393dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi EventBus.getDefault().sendOntoMainThread(new DraggingInRecentsEvent(distanceFromTop)); 394dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi } 395dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi 396dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi public void onDraggingInRecentsEnded(float velocity) { 397dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi EventBus.getDefault().sendOntoMainThread(new DraggingInRecentsEndedEvent(velocity)); 398dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi } 399dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi 400675c5d8e5a6fd98e8324798e1ef31df20cee5b0fWinson public void onShowCurrentUserToast(int msgResId, int msgLength) { 401675c5d8e5a6fd98e8324798e1ef31df20cee5b0fWinson Toast.makeText(mContext, msgResId, msgLength).show(); 402675c5d8e5a6fd98e8324798e1ef31df20cee5b0fWinson } 403675c5d8e5a6fd98e8324798e1ef31df20cee5b0fWinson 4046b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson /** 4056b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson * Transitions to the next recent task in the stack. 4066b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson */ 4076b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson public void showNextTask() { 4086b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson SystemServicesProxy ssp = Recents.getSystemServices(); 4096b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson RecentsTaskLoader loader = Recents.getTaskLoader(); 4106b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson RecentsTaskLoadPlan plan = loader.createLoadPlan(mContext); 411dfd7be012b889f92d3e7e6d80ff7fe6b55c75901Winson loader.preloadTasks(plan, -1, false /* includeFrontMostExcludedTask */); 4126b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson TaskStack focusedStack = plan.getTaskStack(); 4136b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson 4146b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson // Return early if there are no tasks in the focused stack 4154b057c6787624b75613769a857ccdf51114bb7f2Winson if (focusedStack == null || focusedStack.getTaskCount() == 0) return; 4166b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson 4176b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson // Return early if there is no running task 418d46b72788e8811d2e423ea1e5b2ff104ecb7f721Winson ActivityManager.RunningTaskInfo runningTask = ssp.getRunningTask(); 4196b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson if (runningTask == null) return; 4206b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson 4216b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson // Find the task in the recents list 422d46b72788e8811d2e423ea1e5b2ff104ecb7f721Winson boolean isRunningTaskInHomeStack = SystemServicesProxy.isHomeStack(runningTask.stackId); 423250608a5cd08862f4752a924d51710805850db8aWinson ArrayList<Task> tasks = focusedStack.getStackTasks(); 4246b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson Task toTask = null; 4256b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson ActivityOptions launchOpts = null; 4266b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson int taskCount = tasks.size(); 4276b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson for (int i = taskCount - 1; i >= 1; i--) { 4286b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson Task task = tasks.get(i); 429d46b72788e8811d2e423ea1e5b2ff104ecb7f721Winson if (isRunningTaskInHomeStack) { 430e86deb8adb022ba7721a1af1112d3a45e757095cWinson toTask = tasks.get(i - 1); 431e86deb8adb022ba7721a1af1112d3a45e757095cWinson launchOpts = ActivityOptions.makeCustomAnimation(mContext, 432e86deb8adb022ba7721a1af1112d3a45e757095cWinson R.anim.recents_launch_next_affiliated_task_target, 433e86deb8adb022ba7721a1af1112d3a45e757095cWinson R.anim.recents_fast_toggle_app_home_exit); 434e86deb8adb022ba7721a1af1112d3a45e757095cWinson break; 435e86deb8adb022ba7721a1af1112d3a45e757095cWinson } else if (task.key.id == runningTask.id) { 4366b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson toTask = tasks.get(i - 1); 4376b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson launchOpts = ActivityOptions.makeCustomAnimation(mContext, 4386b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson R.anim.recents_launch_prev_affiliated_task_target, 4396b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson R.anim.recents_launch_prev_affiliated_task_source); 4406b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson break; 4416b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson } 4426b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson } 4436b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson 4446b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson // Return early if there is no next task 4456b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson if (toTask == null) { 4466b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson ssp.startInPlaceAnimationOnFrontMostApplication( 4476b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson ActivityOptions.makeCustomInPlaceAnimation(mContext, 4486b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson R.anim.recents_launch_prev_affiliated_task_bounce)); 4496b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson return; 4506b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson } 4516b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson 4526b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson // Launch the task 45364ae08aa16fdf7ee33073979400afa40692342f1Wale Ogunwale ssp.startActivityFromRecents(mContext, toTask.key, toTask.title, launchOpts); 4546b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson } 4556b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson 4566b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson /** 4576b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson * Transitions to the next affiliated task. 4586b92c6e524dbb7598fbeb4aefd98b69e6c13c03aWinson */ 459190fe3bf88388fcb109af64571e3baa0d01f1c37Winson public void showRelativeAffiliatedTask(boolean showNextTask) { 460e7f138c7f0a190c86cec10fb32fa106aacae4093Winson SystemServicesProxy ssp = Recents.getSystemServices(); 461e7f138c7f0a190c86cec10fb32fa106aacae4093Winson RecentsTaskLoader loader = Recents.getTaskLoader(); 462190fe3bf88388fcb109af64571e3baa0d01f1c37Winson RecentsTaskLoadPlan plan = loader.createLoadPlan(mContext); 463dfd7be012b889f92d3e7e6d80ff7fe6b55c75901Winson loader.preloadTasks(plan, -1, false /* includeFrontMostExcludedTask */); 464190fe3bf88388fcb109af64571e3baa0d01f1c37Winson TaskStack focusedStack = plan.getTaskStack(); 465190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 466190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Return early if there are no tasks in the focused stack 4674b057c6787624b75613769a857ccdf51114bb7f2Winson if (focusedStack == null || focusedStack.getTaskCount() == 0) return; 468190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 469190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Return early if there is no running task (can't determine affiliated tasks in this case) 470d46b72788e8811d2e423ea1e5b2ff104ecb7f721Winson ActivityManager.RunningTaskInfo runningTask = ssp.getRunningTask(); 471190fe3bf88388fcb109af64571e3baa0d01f1c37Winson if (runningTask == null) return; 472190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Return early if the running task is in the home stack (optimization) 4735510f6c1b9c20483e1507147eed7b24ac8bb6363Winson if (SystemServicesProxy.isHomeStack(runningTask.stackId)) return; 474190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 475190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Find the task in the recents list 476250608a5cd08862f4752a924d51710805850db8aWinson ArrayList<Task> tasks = focusedStack.getStackTasks(); 477190fe3bf88388fcb109af64571e3baa0d01f1c37Winson Task toTask = null; 478190fe3bf88388fcb109af64571e3baa0d01f1c37Winson ActivityOptions launchOpts = null; 479190fe3bf88388fcb109af64571e3baa0d01f1c37Winson int taskCount = tasks.size(); 480190fe3bf88388fcb109af64571e3baa0d01f1c37Winson int numAffiliatedTasks = 0; 481190fe3bf88388fcb109af64571e3baa0d01f1c37Winson for (int i = 0; i < taskCount; i++) { 482190fe3bf88388fcb109af64571e3baa0d01f1c37Winson Task task = tasks.get(i); 483190fe3bf88388fcb109af64571e3baa0d01f1c37Winson if (task.key.id == runningTask.id) { 484190fe3bf88388fcb109af64571e3baa0d01f1c37Winson TaskGrouping group = task.group; 485190fe3bf88388fcb109af64571e3baa0d01f1c37Winson Task.TaskKey toTaskKey; 486190fe3bf88388fcb109af64571e3baa0d01f1c37Winson if (showNextTask) { 487190fe3bf88388fcb109af64571e3baa0d01f1c37Winson toTaskKey = group.getNextTaskInGroup(task); 488190fe3bf88388fcb109af64571e3baa0d01f1c37Winson launchOpts = ActivityOptions.makeCustomAnimation(mContext, 489190fe3bf88388fcb109af64571e3baa0d01f1c37Winson R.anim.recents_launch_next_affiliated_task_target, 490190fe3bf88388fcb109af64571e3baa0d01f1c37Winson R.anim.recents_launch_next_affiliated_task_source); 491190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } else { 492190fe3bf88388fcb109af64571e3baa0d01f1c37Winson toTaskKey = group.getPrevTaskInGroup(task); 493190fe3bf88388fcb109af64571e3baa0d01f1c37Winson launchOpts = ActivityOptions.makeCustomAnimation(mContext, 494190fe3bf88388fcb109af64571e3baa0d01f1c37Winson R.anim.recents_launch_prev_affiliated_task_target, 495190fe3bf88388fcb109af64571e3baa0d01f1c37Winson R.anim.recents_launch_prev_affiliated_task_source); 496190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 497190fe3bf88388fcb109af64571e3baa0d01f1c37Winson if (toTaskKey != null) { 498190fe3bf88388fcb109af64571e3baa0d01f1c37Winson toTask = focusedStack.findTaskWithId(toTaskKey.id); 499190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 500190fe3bf88388fcb109af64571e3baa0d01f1c37Winson numAffiliatedTasks = group.getTaskCount(); 501190fe3bf88388fcb109af64571e3baa0d01f1c37Winson break; 502190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 503190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 504190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 505190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Return early if there is no next task 506190fe3bf88388fcb109af64571e3baa0d01f1c37Winson if (toTask == null) { 507190fe3bf88388fcb109af64571e3baa0d01f1c37Winson if (numAffiliatedTasks > 1) { 508190fe3bf88388fcb109af64571e3baa0d01f1c37Winson if (showNextTask) { 509e7f138c7f0a190c86cec10fb32fa106aacae4093Winson ssp.startInPlaceAnimationOnFrontMostApplication( 510190fe3bf88388fcb109af64571e3baa0d01f1c37Winson ActivityOptions.makeCustomInPlaceAnimation(mContext, 511190fe3bf88388fcb109af64571e3baa0d01f1c37Winson R.anim.recents_launch_next_affiliated_task_bounce)); 512190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } else { 513e7f138c7f0a190c86cec10fb32fa106aacae4093Winson ssp.startInPlaceAnimationOnFrontMostApplication( 514190fe3bf88388fcb109af64571e3baa0d01f1c37Winson ActivityOptions.makeCustomInPlaceAnimation(mContext, 515190fe3bf88388fcb109af64571e3baa0d01f1c37Winson R.anim.recents_launch_prev_affiliated_task_bounce)); 516190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 517190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 518190fe3bf88388fcb109af64571e3baa0d01f1c37Winson return; 519190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 520190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 521190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Keep track of actually launched affiliated tasks 522190fe3bf88388fcb109af64571e3baa0d01f1c37Winson MetricsLogger.count(mContext, "overview_affiliated_task_launch", 1); 523190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 524190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Launch the task 52564ae08aa16fdf7ee33073979400afa40692342f1Wale Ogunwale ssp.startActivityFromRecents(mContext, toTask.key, toTask.title, launchOpts); 526190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 527190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 528190fe3bf88388fcb109af64571e3baa0d01f1c37Winson public void showNextAffiliatedTask() { 529190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Keep track of when the affiliated task is triggered 530190fe3bf88388fcb109af64571e3baa0d01f1c37Winson MetricsLogger.count(mContext, "overview_affiliated_task_next", 1); 531190fe3bf88388fcb109af64571e3baa0d01f1c37Winson showRelativeAffiliatedTask(true); 532190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 533190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 534190fe3bf88388fcb109af64571e3baa0d01f1c37Winson public void showPrevAffiliatedTask() { 535190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Keep track of when the affiliated task is triggered 536190fe3bf88388fcb109af64571e3baa0d01f1c37Winson MetricsLogger.count(mContext, "overview_affiliated_task_prev", 1); 537190fe3bf88388fcb109af64571e3baa0d01f1c37Winson showRelativeAffiliatedTask(false); 538190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 539190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 540cdb06caebb5f6f554b2ed8c76963970d8cc0ab54Jorim Jaggi public void dockTopTask(int topTaskId, int dragMode, 541cdb06caebb5f6f554b2ed8c76963970d8cc0ab54Jorim Jaggi int stackCreateMode, Rect initialBounds) { 54275b2597e5826662c1740d6f3b81966a9e6a9e7b4Jorim Jaggi SystemServicesProxy ssp = Recents.getSystemServices(); 5439511b0f1e9ac629a4a747a0c9373d33ab33cfc32Jorim Jaggi 5449511b0f1e9ac629a4a747a0c9373d33ab33cfc32Jorim Jaggi // Make sure we inform DividerView before we actually start the activity so we can change 5459511b0f1e9ac629a4a747a0c9373d33ab33cfc32Jorim Jaggi // the resize mode already. 546e4fbd328f83ea0ee086731f852cd6c56a3deb733Chong Zhang if (ssp.moveTaskToDockedStack(topTaskId, stackCreateMode, initialBounds)) { 547899327f5cbbfb0eae5562b262ccea860c98f6bc4Jorim Jaggi EventBus.getDefault().send(new DockedTopTaskEvent(dragMode, initialBounds)); 548e4fbd328f83ea0ee086731f852cd6c56a3deb733Chong Zhang showRecents( 549e4fbd328f83ea0ee086731f852cd6c56a3deb733Chong Zhang false /* triggeredFromAltTab */, 550e4fbd328f83ea0ee086731f852cd6c56a3deb733Chong Zhang dragMode == NavigationBarGestureHelper.DRAG_MODE_RECENTS, 551e4fbd328f83ea0ee086731f852cd6c56a3deb733Chong Zhang false /* animate */, 552681fc7b2670542aae0f3b9ef8f6c7a88db984ea9Jorim Jaggi true /* launchedWhileDockingTask*/, 553db21bbd2caf05322864f09ec45a0c572cf071123Jorim Jaggi false /* fromHome */, 554db21bbd2caf05322864f09ec45a0c572cf071123Jorim Jaggi DividerView.INVALID_RECENTS_GROW_TARGET); 555e4fbd328f83ea0ee086731f852cd6c56a3deb733Chong Zhang } 55675b2597e5826662c1740d6f3b81966a9e6a9e7b4Jorim Jaggi } 55775b2597e5826662c1740d6f3b81966a9e6a9e7b4Jorim Jaggi 558190fe3bf88388fcb109af64571e3baa0d01f1c37Winson /** 559190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * Returns the preloaded load plan and invalidates it. 560190fe3bf88388fcb109af64571e3baa0d01f1c37Winson */ 561190fe3bf88388fcb109af64571e3baa0d01f1c37Winson public static RecentsTaskLoadPlan consumeInstanceLoadPlan() { 562190fe3bf88388fcb109af64571e3baa0d01f1c37Winson RecentsTaskLoadPlan plan = sInstanceLoadPlan; 563190fe3bf88388fcb109af64571e3baa0d01f1c37Winson sInstanceLoadPlan = null; 564190fe3bf88388fcb109af64571e3baa0d01f1c37Winson return plan; 565190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 566190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 567190fe3bf88388fcb109af64571e3baa0d01f1c37Winson /** 568670ea71f1b4ae59a0cd6608ae44b0fb78a1144c4Winson * Reloads all the resources for the current configuration. 569b94443d876d3c9575e88078d0e537bb385f79ca4Winson */ 570670ea71f1b4ae59a0cd6608ae44b0fb78a1144c4Winson private void reloadResources() { 571b94443d876d3c9575e88078d0e537bb385f79ca4Winson Resources res = mContext.getResources(); 572b94443d876d3c9575e88078d0e537bb385f79ca4Winson 573b94443d876d3c9575e88078d0e537bb385f79ca4Winson mStatusBarHeight = res.getDimensionPixelSize( 574b94443d876d3c9575e88078d0e537bb385f79ca4Winson com.android.internal.R.dimen.status_bar_height); 575b94443d876d3c9575e88078d0e537bb385f79ca4Winson mNavBarHeight = res.getDimensionPixelSize( 576b94443d876d3c9575e88078d0e537bb385f79ca4Winson com.android.internal.R.dimen.navigation_bar_height); 577b94443d876d3c9575e88078d0e537bb385f79ca4Winson mNavBarWidth = res.getDimensionPixelSize( 578b94443d876d3c9575e88078d0e537bb385f79ca4Winson com.android.internal.R.dimen.navigation_bar_width); 57925160db73f37619a26a3d87a06625925d881b0fdJorim Jaggi mTaskBarHeight = TaskStackLayoutAlgorithm.getDimensionForDevice(mContext, 580217009356efa2b854ab3981dff8d315a0d679c73Winson R.dimen.recents_task_view_header_height, 581217009356efa2b854ab3981dff8d315a0d679c73Winson R.dimen.recents_task_view_header_height, 582217009356efa2b854ab3981dff8d315a0d679c73Winson R.dimen.recents_task_view_header_height, 583217009356efa2b854ab3981dff8d315a0d679c73Winson R.dimen.recents_task_view_header_height_tablet_land, 584217009356efa2b854ab3981dff8d315a0d679c73Winson R.dimen.recents_task_view_header_height, 585217009356efa2b854ab3981dff8d315a0d679c73Winson R.dimen.recents_task_view_header_height_tablet_land); 586b94443d876d3c9575e88078d0e537bb385f79ca4Winson } 587b94443d876d3c9575e88078d0e537bb385f79ca4Winson 588b94443d876d3c9575e88078d0e537bb385f79ca4Winson /** 589190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * Prepares the header bar layout for the next transition, if the task view bounds has changed 590190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * since the last call, it will attempt to re-measure and layout the header bar to the new size. 591190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * 592f0d1c44a59a10707baa0cca8dd377302260710c1Winson * @param stack the stack to initialize the stack layout with 593db21bbd2caf05322864f09ec45a0c572cf071123Jorim Jaggi * @param windowRectOverride the rectangle to use when calculating the stack state which can 594db21bbd2caf05322864f09ec45a0c572cf071123Jorim Jaggi * be different from the current window rect if recents is resizing 595db21bbd2caf05322864f09ec45a0c572cf071123Jorim Jaggi * while being launched 596190fe3bf88388fcb109af64571e3baa0d01f1c37Winson */ 597db21bbd2caf05322864f09ec45a0c572cf071123Jorim Jaggi private void updateHeaderBarLayout(TaskStack stack, Rect windowRectOverride) { 598e7f138c7f0a190c86cec10fb32fa106aacae4093Winson SystemServicesProxy ssp = Recents.getSystemServices(); 599fc48b072e8caa62849ee305f89f38d248d4a1dedWinson Rect displayRect = ssp.getDisplayRect(); 600c6c89a82144f59475242c75d67529fed943ae30bJorim Jaggi Rect systemInsets = new Rect(); 601c6c89a82144f59475242c75d67529fed943ae30bJorim Jaggi ssp.getStableInsets(systemInsets); 602db21bbd2caf05322864f09ec45a0c572cf071123Jorim Jaggi Rect windowRect = windowRectOverride != null 603db21bbd2caf05322864f09ec45a0c572cf071123Jorim Jaggi ? new Rect(windowRectOverride) 604db21bbd2caf05322864f09ec45a0c572cf071123Jorim Jaggi : ssp.getWindowRect(); 605cf9b8326cecfca3917779c3701aa08eaaad56505Winson // When docked, the nav bar insets are consumed and the activity is measured without insets. 606cf9b8326cecfca3917779c3701aa08eaaad56505Winson // However, the window bounds include the insets, so we need to subtract them here to make 607cf9b8326cecfca3917779c3701aa08eaaad56505Winson // them identical. 608cf9b8326cecfca3917779c3701aa08eaaad56505Winson if (ssp.hasDockedTask()) { 609cf9b8326cecfca3917779c3701aa08eaaad56505Winson windowRect.bottom -= systemInsets.bottom; 610cf9b8326cecfca3917779c3701aa08eaaad56505Winson systemInsets.bottom = 0; 611cf9b8326cecfca3917779c3701aa08eaaad56505Winson } 612c6c89a82144f59475242c75d67529fed943ae30bJorim Jaggi calculateWindowStableInsets(systemInsets, windowRect); 613c6c89a82144f59475242c75d67529fed943ae30bJorim Jaggi windowRect.offsetTo(0, 0); 614190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 61559924fe0d9136cf349759bea1e06b661603f95feWinson TaskStackLayoutAlgorithm stackLayout = mDummyStackView.getStackAlgorithm(); 616190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 617190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Rebind the header bar and draw it for the transition 6188873754f66527d2cc9feab295dd4eef23298212aWinson stackLayout.setSystemInsets(systemInsets); 619f0d1c44a59a10707baa0cca8dd377302260710c1Winson if (stack != null) { 620fc48b072e8caa62849ee305f89f38d248d4a1dedWinson stackLayout.getTaskStackBounds(displayRect, windowRect, systemInsets.top, 621cbb625bc6d22ad806560dd192d3945cdd5021cfbWinson systemInsets.left, systemInsets.right, mTaskStackBounds); 622aeb298c4db913b376fb6053ec30c132a93e04635Winson stackLayout.reset(); 623fc48b072e8caa62849ee305f89f38d248d4a1dedWinson stackLayout.initialize(displayRect, windowRect, mTaskStackBounds, 624f0d1c44a59a10707baa0cca8dd377302260710c1Winson TaskStackLayoutAlgorithm.StackState.getStackStateForStack(stack)); 625a1ededd056d51532ab18354f17f8065ec1134535Winson mDummyStackView.setTasks(stack, false /* allowNotifyStackChanges */); 626190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 627aeb298c4db913b376fb6053ec30c132a93e04635Winson Rect taskViewBounds = stackLayout.getUntransformedTaskViewBounds(); 62894bc4f2238d8eefb77c63a560aa0de1335ee57abWinson if (!taskViewBounds.isEmpty()) { 62994bc4f2238d8eefb77c63a560aa0de1335ee57abWinson int taskViewWidth = taskViewBounds.width(); 63094bc4f2238d8eefb77c63a560aa0de1335ee57abWinson synchronized (mHeaderBarLock) { 63194bc4f2238d8eefb77c63a560aa0de1335ee57abWinson if (mHeaderBar.getMeasuredWidth() != taskViewWidth || 63294bc4f2238d8eefb77c63a560aa0de1335ee57abWinson mHeaderBar.getMeasuredHeight() != mTaskBarHeight) { 63396f78f50464a0f394802ff0709ba7276976ef275Winson mHeaderBar.forceLayout(); 63494bc4f2238d8eefb77c63a560aa0de1335ee57abWinson mHeaderBar.measure( 63594bc4f2238d8eefb77c63a560aa0de1335ee57abWinson MeasureSpec.makeMeasureSpec(taskViewWidth, MeasureSpec.EXACTLY), 63694bc4f2238d8eefb77c63a560aa0de1335ee57abWinson MeasureSpec.makeMeasureSpec(mTaskBarHeight, MeasureSpec.EXACTLY)); 63794bc4f2238d8eefb77c63a560aa0de1335ee57abWinson } 63894bc4f2238d8eefb77c63a560aa0de1335ee57abWinson mHeaderBar.layout(0, 0, taskViewWidth, mTaskBarHeight); 639aeb298c4db913b376fb6053ec30c132a93e04635Winson } 640aeb298c4db913b376fb6053ec30c132a93e04635Winson 64194bc4f2238d8eefb77c63a560aa0de1335ee57abWinson // Update the transition bitmap to match the new header bar height 64294bc4f2238d8eefb77c63a560aa0de1335ee57abWinson if (mThumbTransitionBitmapCache == null || 64394bc4f2238d8eefb77c63a560aa0de1335ee57abWinson (mThumbTransitionBitmapCache.getWidth() != taskViewWidth) || 64494bc4f2238d8eefb77c63a560aa0de1335ee57abWinson (mThumbTransitionBitmapCache.getHeight() != mTaskBarHeight)) { 64594bc4f2238d8eefb77c63a560aa0de1335ee57abWinson mThumbTransitionBitmapCache = Bitmap.createBitmap(taskViewWidth, 64694bc4f2238d8eefb77c63a560aa0de1335ee57abWinson mTaskBarHeight, Bitmap.Config.ARGB_8888); 64794bc4f2238d8eefb77c63a560aa0de1335ee57abWinson } 648aeb298c4db913b376fb6053ec30c132a93e04635Winson } 649190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 650190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 651190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 652190fe3bf88388fcb109af64571e3baa0d01f1c37Winson /** 653c6c89a82144f59475242c75d67529fed943ae30bJorim Jaggi * Given the stable insets and the rect for our window, calculates the insets that affect our 654c6c89a82144f59475242c75d67529fed943ae30bJorim Jaggi * window. 655c6c89a82144f59475242c75d67529fed943ae30bJorim Jaggi */ 656c6c89a82144f59475242c75d67529fed943ae30bJorim Jaggi private void calculateWindowStableInsets(Rect inOutInsets, Rect windowRect) { 657c6c89a82144f59475242c75d67529fed943ae30bJorim Jaggi Rect displayRect = Recents.getSystemServices().getDisplayRect(); 658c6c89a82144f59475242c75d67529fed943ae30bJorim Jaggi 659c6c89a82144f59475242c75d67529fed943ae30bJorim Jaggi // Display rect without insets - available app space 660c6c89a82144f59475242c75d67529fed943ae30bJorim Jaggi Rect appRect = new Rect(displayRect); 661c6c89a82144f59475242c75d67529fed943ae30bJorim Jaggi appRect.inset(inOutInsets); 662c6c89a82144f59475242c75d67529fed943ae30bJorim Jaggi 663c6c89a82144f59475242c75d67529fed943ae30bJorim Jaggi // Our window intersected with available app space 664c6c89a82144f59475242c75d67529fed943ae30bJorim Jaggi Rect windowRectWithInsets = new Rect(windowRect); 665c6c89a82144f59475242c75d67529fed943ae30bJorim Jaggi windowRectWithInsets.intersect(appRect); 666c6c89a82144f59475242c75d67529fed943ae30bJorim Jaggi inOutInsets.left = windowRectWithInsets.left - windowRect.left; 667c6c89a82144f59475242c75d67529fed943ae30bJorim Jaggi inOutInsets.top = windowRectWithInsets.top - windowRect.top; 668c6c89a82144f59475242c75d67529fed943ae30bJorim Jaggi inOutInsets.right = windowRect.right - windowRectWithInsets.right; 669c6c89a82144f59475242c75d67529fed943ae30bJorim Jaggi inOutInsets.bottom = windowRect.bottom - windowRectWithInsets.bottom; 670c6c89a82144f59475242c75d67529fed943ae30bJorim Jaggi } 671c6c89a82144f59475242c75d67529fed943ae30bJorim Jaggi 672c6c89a82144f59475242c75d67529fed943ae30bJorim Jaggi /** 673190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * Preloads the icon of a task. 674190fe3bf88388fcb109af64571e3baa0d01f1c37Winson */ 675c4a038ad28009eb5840cf9f6aefbd2c873cee02eWinson private void preloadIcon(int runningTaskId) { 676190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Ensure that we load the running task's icon 677190fe3bf88388fcb109af64571e3baa0d01f1c37Winson RecentsTaskLoadPlan.Options launchOpts = new RecentsTaskLoadPlan.Options(); 678c4a038ad28009eb5840cf9f6aefbd2c873cee02eWinson launchOpts.runningTaskId = runningTaskId; 679190fe3bf88388fcb109af64571e3baa0d01f1c37Winson launchOpts.loadThumbnails = false; 680190fe3bf88388fcb109af64571e3baa0d01f1c37Winson launchOpts.onlyLoadForCache = true; 681e7f138c7f0a190c86cec10fb32fa106aacae4093Winson Recents.getTaskLoader().loadTasks(mContext, sInstanceLoadPlan, launchOpts); 682190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 683190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 684190fe3bf88388fcb109af64571e3baa0d01f1c37Winson /** 685190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * Creates the activity options for a unknown state->recents transition. 686190fe3bf88388fcb109af64571e3baa0d01f1c37Winson */ 6874bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan protected ActivityOptions getUnknownTransitionActivityOptions() { 688190fe3bf88388fcb109af64571e3baa0d01f1c37Winson return ActivityOptions.makeCustomAnimation(mContext, 689190fe3bf88388fcb109af64571e3baa0d01f1c37Winson R.anim.recents_from_unknown_enter, 690190fe3bf88388fcb109af64571e3baa0d01f1c37Winson R.anim.recents_from_unknown_exit, 6913fb67562c548662910160d5672b1b9558bd6571cWinson mHandler, null); 692190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 693190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 694190fe3bf88388fcb109af64571e3baa0d01f1c37Winson /** 695190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * Creates the activity options for a home->recents transition. 696190fe3bf88388fcb109af64571e3baa0d01f1c37Winson */ 697008ee15fe82c8216e8e4f67e3032de468cc6c92aWinson protected ActivityOptions getHomeTransitionActivityOptions() { 698190fe3bf88388fcb109af64571e3baa0d01f1c37Winson return ActivityOptions.makeCustomAnimation(mContext, 699190fe3bf88388fcb109af64571e3baa0d01f1c37Winson R.anim.recents_from_launcher_enter, 700190fe3bf88388fcb109af64571e3baa0d01f1c37Winson R.anim.recents_from_launcher_exit, 7013fb67562c548662910160d5672b1b9558bd6571cWinson mHandler, null); 702190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 703190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 704190fe3bf88388fcb109af64571e3baa0d01f1c37Winson /** 705190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * Creates the activity options for an app->recents transition. 706190fe3bf88388fcb109af64571e3baa0d01f1c37Winson */ 707190fe3bf88388fcb109af64571e3baa0d01f1c37Winson private ActivityOptions getThumbnailTransitionActivityOptions( 708d46b72788e8811d2e423ea1e5b2ff104ecb7f721Winson ActivityManager.RunningTaskInfo runningTask, TaskStackView stackView, 709d46b72788e8811d2e423ea1e5b2ff104ecb7f721Winson Rect windowOverrideRect) { 710c4a038ad28009eb5840cf9f6aefbd2c873cee02eWinson if (runningTask != null && runningTask.stackId == FREEFORM_WORKSPACE_STACK_ID) { 711d64ef3ef33c50a03b4be3b2baaa93aab7319fca8Filip Gruszczynski ArrayList<AppTransitionAnimationSpec> specs = new ArrayList<>(); 712e693aafe0511c2a7ffc571b22abeefba44046225Winson ArrayList<Task> tasks = stackView.getStack().getStackTasks(); 713e693aafe0511c2a7ffc571b22abeefba44046225Winson TaskStackLayoutAlgorithm stackLayout = stackView.getStackAlgorithm(); 714e693aafe0511c2a7ffc571b22abeefba44046225Winson TaskStackViewScroller stackScroller = stackView.getScroller(); 715e693aafe0511c2a7ffc571b22abeefba44046225Winson 716003eda6c230a1b1c4e3709466c46660e7602d740Winson stackView.updateLayoutAlgorithm(true /* boundScroll */); 71767c79578f94646bade5d336af0d4491179c1b37dWinson stackView.updateToInitialState(); 718e693aafe0511c2a7ffc571b22abeefba44046225Winson 719d64ef3ef33c50a03b4be3b2baaa93aab7319fca8Filip Gruszczynski for (int i = tasks.size() - 1; i >= 0; i--) { 720d64ef3ef33c50a03b4be3b2baaa93aab7319fca8Filip Gruszczynski Task task = tasks.get(i); 721387aac6ad7bde21f2c2510cb8a2f3af3959721e0Winson if (task.isFreeformTask()) { 722e693aafe0511c2a7ffc571b22abeefba44046225Winson mTmpTransform = stackLayout.getStackTransformScreenCoordinates(task, 723db21bbd2caf05322864f09ec45a0c572cf071123Jorim Jaggi stackScroller.getStackScroll(), mTmpTransform, null, 724db21bbd2caf05322864f09ec45a0c572cf071123Jorim Jaggi windowOverrideRect); 725aeb298c4db913b376fb6053ec30c132a93e04635Winson Bitmap thumbnail = drawThumbnailTransitionBitmap(task, mTmpTransform, 726aeb298c4db913b376fb6053ec30c132a93e04635Winson mThumbTransitionBitmapCache); 727d64ef3ef33c50a03b4be3b2baaa93aab7319fca8Filip Gruszczynski Rect toTaskRect = new Rect(); 728d64ef3ef33c50a03b4be3b2baaa93aab7319fca8Filip Gruszczynski mTmpTransform.rect.round(toTaskRect); 729d64ef3ef33c50a03b4be3b2baaa93aab7319fca8Filip Gruszczynski specs.add(new AppTransitionAnimationSpec(task.key.id, thumbnail, toTaskRect)); 730d64ef3ef33c50a03b4be3b2baaa93aab7319fca8Filip Gruszczynski } 731d64ef3ef33c50a03b4be3b2baaa93aab7319fca8Filip Gruszczynski } 732d64ef3ef33c50a03b4be3b2baaa93aab7319fca8Filip Gruszczynski AppTransitionAnimationSpec[] specsArray = new AppTransitionAnimationSpec[specs.size()]; 733d64ef3ef33c50a03b4be3b2baaa93aab7319fca8Filip Gruszczynski specs.toArray(specsArray); 734d64ef3ef33c50a03b4be3b2baaa93aab7319fca8Filip Gruszczynski return ActivityOptions.makeThumbnailAspectScaleDownAnimation(mDummyStackView, 7353fb67562c548662910160d5672b1b9558bd6571cWinson specsArray, mHandler, null, this); 736d64ef3ef33c50a03b4be3b2baaa93aab7319fca8Filip Gruszczynski } else { 737d64ef3ef33c50a03b4be3b2baaa93aab7319fca8Filip Gruszczynski // Update the destination rect 738d64ef3ef33c50a03b4be3b2baaa93aab7319fca8Filip Gruszczynski Task toTask = new Task(); 739db21bbd2caf05322864f09ec45a0c572cf071123Jorim Jaggi TaskViewTransform toTransform = getThumbnailTransitionTransform(stackView, toTask, 740db21bbd2caf05322864f09ec45a0c572cf071123Jorim Jaggi windowOverrideRect); 741aeb298c4db913b376fb6053ec30c132a93e04635Winson Bitmap thumbnail = drawThumbnailTransitionBitmap(toTask, toTransform, 742aeb298c4db913b376fb6053ec30c132a93e04635Winson mThumbTransitionBitmapCache); 743d64ef3ef33c50a03b4be3b2baaa93aab7319fca8Filip Gruszczynski if (thumbnail != null) { 744aeb298c4db913b376fb6053ec30c132a93e04635Winson RectF toTaskRect = toTransform.rect; 745d64ef3ef33c50a03b4be3b2baaa93aab7319fca8Filip Gruszczynski return ActivityOptions.makeThumbnailAspectScaleDownAnimation(mDummyStackView, 746d64ef3ef33c50a03b4be3b2baaa93aab7319fca8Filip Gruszczynski thumbnail, (int) toTaskRect.left, (int) toTaskRect.top, 7473fb67562c548662910160d5672b1b9558bd6571cWinson (int) toTaskRect.width(), (int) toTaskRect.height(), mHandler, null); 748d64ef3ef33c50a03b4be3b2baaa93aab7319fca8Filip Gruszczynski } 749d64ef3ef33c50a03b4be3b2baaa93aab7319fca8Filip Gruszczynski // If both the screenshot and thumbnail fails, then just fall back to the default transition 750d64ef3ef33c50a03b4be3b2baaa93aab7319fca8Filip Gruszczynski return getUnknownTransitionActivityOptions(); 751d64ef3ef33c50a03b4be3b2baaa93aab7319fca8Filip Gruszczynski } 752d64ef3ef33c50a03b4be3b2baaa93aab7319fca8Filip Gruszczynski } 753190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 754190fe3bf88388fcb109af64571e3baa0d01f1c37Winson /** 755190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * Returns the transition rect for the given task id. 756190fe3bf88388fcb109af64571e3baa0d01f1c37Winson */ 757e693aafe0511c2a7ffc571b22abeefba44046225Winson private TaskViewTransform getThumbnailTransitionTransform(TaskStackView stackView, 758db21bbd2caf05322864f09ec45a0c572cf071123Jorim Jaggi Task runningTaskOut, Rect windowOverrideRect) { 759190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Find the running task in the TaskStack 760e693aafe0511c2a7ffc571b22abeefba44046225Winson TaskStack stack = stackView.getStack(); 76165c851e6e9e08656744b6f66d3da188e3283b17dWinson Task launchTask = stack.getLaunchTarget(); 76265c851e6e9e08656744b6f66d3da188e3283b17dWinson if (launchTask != null) { 76365c851e6e9e08656744b6f66d3da188e3283b17dWinson runningTaskOut.copyFrom(launchTask); 76465c851e6e9e08656744b6f66d3da188e3283b17dWinson } else { 765190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // If no task is specified or we can not find the task just use the front most one 76635a8b04140598a5b5c4865254b942adb6a830991Winson launchTask = stack.getStackFrontMostTask(true /* includeFreeform */); 76765c851e6e9e08656744b6f66d3da188e3283b17dWinson runningTaskOut.copyFrom(launchTask); 768190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 769190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 770190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Get the transform for the running task 771003eda6c230a1b1c4e3709466c46660e7602d740Winson stackView.updateLayoutAlgorithm(true /* boundScroll */); 77267c79578f94646bade5d336af0d4491179c1b37dWinson stackView.updateToInitialState(); 7737845e8c4946f6b5dadfcd9c1d64e826bacc50edbWinson stackView.getStackAlgorithm().getStackTransformScreenCoordinates(launchTask, 774db21bbd2caf05322864f09ec45a0c572cf071123Jorim Jaggi stackView.getScroller().getStackScroll(), mTmpTransform, null, windowOverrideRect); 775190fe3bf88388fcb109af64571e3baa0d01f1c37Winson return mTmpTransform; 776190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 777190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 778190fe3bf88388fcb109af64571e3baa0d01f1c37Winson /** 779190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * Draws the header of a task used for the window animation into a bitmap. 780190fe3bf88388fcb109af64571e3baa0d01f1c37Winson */ 781aeb298c4db913b376fb6053ec30c132a93e04635Winson private Bitmap drawThumbnailTransitionBitmap(Task toTask, TaskViewTransform toTransform, 782aeb298c4db913b376fb6053ec30c132a93e04635Winson Bitmap thumbnail) { 7838be1634a543022bd6ee0c1e974d3201d452981e8Winson SystemServicesProxy ssp = Recents.getSystemServices(); 784190fe3bf88388fcb109af64571e3baa0d01f1c37Winson if (toTransform != null && toTask.key != null) { 785190fe3bf88388fcb109af64571e3baa0d01f1c37Winson synchronized (mHeaderBarLock) { 7868be1634a543022bd6ee0c1e974d3201d452981e8Winson boolean disabledInSafeMode = !toTask.isSystemApp && ssp.isInSafeMode(); 787509d0d0c9e2ee165d04e898fea59f8941ac7138dWinson Chung mHeaderBar.onTaskViewSizeChanged((int) toTransform.rect.width(), 788509d0d0c9e2ee165d04e898fea59f8941ac7138dWinson Chung (int) toTransform.rect.height()); 789c742f973b1e506732911c156c5869fd377afc5bfWinson if (RecentsDebugFlags.Static.EnableTransitionThumbnailDebugMode) { 790190fe3bf88388fcb109af64571e3baa0d01f1c37Winson thumbnail.eraseColor(0xFFff0000); 791190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } else { 792aeb298c4db913b376fb6053ec30c132a93e04635Winson thumbnail.eraseColor(0); 793190fe3bf88388fcb109af64571e3baa0d01f1c37Winson Canvas c = new Canvas(thumbnail); 79422574afa00b7e32b7c4c5a1b98deebd67751b364Winson // Workaround for b/27815919, reset the callback so that we do not trigger an 79522574afa00b7e32b7c4c5a1b98deebd67751b364Winson // invalidate on the header bar as a result of updating the icon 79622574afa00b7e32b7c4c5a1b98deebd67751b364Winson Drawable icon = mHeaderBar.getIconView().getDrawable(); 79722574afa00b7e32b7c4c5a1b98deebd67751b364Winson if (icon != null) { 79822574afa00b7e32b7c4c5a1b98deebd67751b364Winson icon.setCallback(null); 79922574afa00b7e32b7c4c5a1b98deebd67751b364Winson } 800d2a030613154e2007d9816e090c39e9726e7adbaWinson mHeaderBar.bindToTask(toTask, false /* touchExplorationEnabled */, 8018be1634a543022bd6ee0c1e974d3201d452981e8Winson disabledInSafeMode); 802d2a030613154e2007d9816e090c39e9726e7adbaWinson mHeaderBar.onTaskDataLoaded(); 803e693aafe0511c2a7ffc571b22abeefba44046225Winson mHeaderBar.setDimAlpha(toTransform.dimAlpha); 804190fe3bf88388fcb109af64571e3baa0d01f1c37Winson mHeaderBar.draw(c); 805190fe3bf88388fcb109af64571e3baa0d01f1c37Winson c.setBitmap(null); 806190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 807190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 808190fe3bf88388fcb109af64571e3baa0d01f1c37Winson return thumbnail.createAshmemBitmap(); 809190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 810190fe3bf88388fcb109af64571e3baa0d01f1c37Winson return null; 811190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 812190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 813190fe3bf88388fcb109af64571e3baa0d01f1c37Winson /** 814190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * Shows the recents activity 815190fe3bf88388fcb109af64571e3baa0d01f1c37Winson */ 816d46b72788e8811d2e423ea1e5b2ff104ecb7f721Winson protected void startRecentsActivity(ActivityManager.RunningTaskInfo runningTask, 817d46b72788e8811d2e423ea1e5b2ff104ecb7f721Winson boolean isHomeStackVisible, boolean animate, int growTarget) { 818e7f138c7f0a190c86cec10fb32fa106aacae4093Winson RecentsTaskLoader loader = Recents.getTaskLoader(); 819c5b12dd37e964b220c0a108e86ad8a2d12805747Winson RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState(); 820fc73eec235131dbf3216891f3cb2b1407e6cc099Winson SystemServicesProxy ssp = Recents.getSystemServices(); 821fc73eec235131dbf3216891f3cb2b1407e6cc099Winson boolean isBlacklisted = (runningTask != null) 822fc73eec235131dbf3216891f3cb2b1407e6cc099Winson ? ssp.isBlackListedActivity(runningTask.baseActivity.getClassName()) 823fc73eec235131dbf3216891f3cb2b1407e6cc099Winson : false; 824190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 825fc73eec235131dbf3216891f3cb2b1407e6cc099Winson int runningTaskId = !mLaunchedWhileDocking && !isBlacklisted && (runningTask != null) 826c4a038ad28009eb5840cf9f6aefbd2c873cee02eWinson ? runningTask.id 827c4a038ad28009eb5840cf9f6aefbd2c873cee02eWinson : -1; 828c4a038ad28009eb5840cf9f6aefbd2c873cee02eWinson 829e5f1faa9f8009a723ab21aed6fe5ab325c61442bWinson // In the case where alt-tab is triggered, we never get a preloadRecents() call, so we 830435b2e43cb131d0b38ba19f335aec78bb83944b2Jorim Jaggi // should always preload the tasks now. If we are dragging in recents, reload them as 831435b2e43cb131d0b38ba19f335aec78bb83944b2Jorim Jaggi // the stacks might have changed. 832fc73eec235131dbf3216891f3cb2b1407e6cc099Winson if (mLaunchedWhileDocking || mTriggeredFromAltTab || sInstanceLoadPlan == null) { 833e5f1faa9f8009a723ab21aed6fe5ab325c61442bWinson // Create a new load plan if preloadRecents() was never triggered 834190fe3bf88388fcb109af64571e3baa0d01f1c37Winson sInstanceLoadPlan = loader.createLoadPlan(mContext); 835190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 836e161f08e98fdbe6fe83f70ffa1ea11142a027ebeJorim Jaggi if (mLaunchedWhileDocking || mTriggeredFromAltTab || !sInstanceLoadPlan.hasTasks()) { 837c4a038ad28009eb5840cf9f6aefbd2c873cee02eWinson loader.preloadTasks(sInstanceLoadPlan, runningTaskId, !isHomeStackVisible); 838190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 839c5b12dd37e964b220c0a108e86ad8a2d12805747Winson 840190fe3bf88388fcb109af64571e3baa0d01f1c37Winson TaskStack stack = sInstanceLoadPlan.getTaskStack(); 841c5b12dd37e964b220c0a108e86ad8a2d12805747Winson boolean hasRecentTasks = stack.getTaskCount() > 0; 842fc73eec235131dbf3216891f3cb2b1407e6cc099Winson boolean useThumbnailTransition = (runningTask != null) && !isHomeStackVisible && 843fc73eec235131dbf3216891f3cb2b1407e6cc099Winson hasRecentTasks; 844190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 845aeb298c4db913b376fb6053ec30c132a93e04635Winson // Update the launch state that we need in updateHeaderBarLayout() 846c5887ea7a0b82cc5909743ce14cbda1dcf1dfc82Jorim Jaggi launchState.launchedFromHome = !useThumbnailTransition && !mLaunchedWhileDocking; 847aeb298c4db913b376fb6053ec30c132a93e04635Winson launchState.launchedFromApp = useThumbnailTransition || mLaunchedWhileDocking; 848fc73eec235131dbf3216891f3cb2b1407e6cc099Winson launchState.launchedFromBlacklistedApp = launchState.launchedFromApp && isBlacklisted; 849aeb298c4db913b376fb6053ec30c132a93e04635Winson launchState.launchedViaDockGesture = mLaunchedWhileDocking; 850aeb298c4db913b376fb6053ec30c132a93e04635Winson launchState.launchedViaDragGesture = mDraggingInRecents; 851c4a038ad28009eb5840cf9f6aefbd2c873cee02eWinson launchState.launchedToTaskId = runningTaskId; 852aeb298c4db913b376fb6053ec30c132a93e04635Winson launchState.launchedWithAltTab = mTriggeredFromAltTab; 853aeb298c4db913b376fb6053ec30c132a93e04635Winson 854aeb298c4db913b376fb6053ec30c132a93e04635Winson // Preload the icon (this will be a null-op if we have preloaded the icon already in 855aeb298c4db913b376fb6053ec30c132a93e04635Winson // preloadRecents()) 856c4a038ad28009eb5840cf9f6aefbd2c873cee02eWinson preloadIcon(runningTaskId); 857aeb298c4db913b376fb6053ec30c132a93e04635Winson 858f0d1c44a59a10707baa0cca8dd377302260710c1Winson // Update the header bar if necessary 859db21bbd2caf05322864f09ec45a0c572cf071123Jorim Jaggi Rect windowOverrideRect = getWindowRectOverride(growTarget); 860db21bbd2caf05322864f09ec45a0c572cf071123Jorim Jaggi updateHeaderBarLayout(stack, windowOverrideRect); 861f0d1c44a59a10707baa0cca8dd377302260710c1Winson 862190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Prepare the dummy stack for the transition 86336a5a2c7003ef8157f276b411c3fda47ad2f75e3Winson TaskStackLayoutAlgorithm.VisibilityReport stackVr = 864190fe3bf88388fcb109af64571e3baa0d01f1c37Winson mDummyStackView.computeStackVisibilityReport(); 865bb42a46631b4cecdd03bd628feeb8270d412ebd3Jorim Jaggi 866aeb298c4db913b376fb6053ec30c132a93e04635Winson // Update the remaining launch state 867c5b12dd37e964b220c0a108e86ad8a2d12805747Winson launchState.launchedNumVisibleTasks = stackVr.numVisibleTasks; 868c5b12dd37e964b220c0a108e86ad8a2d12805747Winson launchState.launchedNumVisibleThumbnails = stackVr.numVisibleThumbnails; 869c5b12dd37e964b220c0a108e86ad8a2d12805747Winson 870bb42a46631b4cecdd03bd628feeb8270d412ebd3Jorim Jaggi if (!animate) { 871c5b12dd37e964b220c0a108e86ad8a2d12805747Winson startRecentsActivity(ActivityOptions.makeCustomAnimation(mContext, -1, -1)); 872bb42a46631b4cecdd03bd628feeb8270d412ebd3Jorim Jaggi return; 873bb42a46631b4cecdd03bd628feeb8270d412ebd3Jorim Jaggi } 874bb42a46631b4cecdd03bd628feeb8270d412ebd3Jorim Jaggi 875aeb298c4db913b376fb6053ec30c132a93e04635Winson ActivityOptions opts; 876fc73eec235131dbf3216891f3cb2b1407e6cc099Winson if (isBlacklisted) { 877fc73eec235131dbf3216891f3cb2b1407e6cc099Winson opts = getUnknownTransitionActivityOptions(); 878fc73eec235131dbf3216891f3cb2b1407e6cc099Winson } else if (useThumbnailTransition) { 879190fe3bf88388fcb109af64571e3baa0d01f1c37Winson // Try starting with a thumbnail transition 880d46b72788e8811d2e423ea1e5b2ff104ecb7f721Winson opts = getThumbnailTransitionActivityOptions(runningTask, mDummyStackView, 881db21bbd2caf05322864f09ec45a0c572cf071123Jorim Jaggi windowOverrideRect); 882aeb298c4db913b376fb6053ec30c132a93e04635Winson } else { 883fa61ce343e91e11bb06545eae00e0659a2942a7dSid Soundararajan // If there is no thumbnail transition, but is launching from home into recents, then 884008ee15fe82c8216e8e4f67e3032de468cc6c92aWinson // use a quick home transition 885aeb298c4db913b376fb6053ec30c132a93e04635Winson opts = hasRecentTasks 886aeb298c4db913b376fb6053ec30c132a93e04635Winson ? getHomeTransitionActivityOptions() 887aeb298c4db913b376fb6053ec30c132a93e04635Winson : getUnknownTransitionActivityOptions(); 888fa61ce343e91e11bb06545eae00e0659a2942a7dSid Soundararajan } 889aeb298c4db913b376fb6053ec30c132a93e04635Winson startRecentsActivity(opts); 890fa61ce343e91e11bb06545eae00e0659a2942a7dSid Soundararajan mLastToggleTime = SystemClock.elapsedRealtime(); 891fa61ce343e91e11bb06545eae00e0659a2942a7dSid Soundararajan } 892fa61ce343e91e11bb06545eae00e0659a2942a7dSid Soundararajan 893db21bbd2caf05322864f09ec45a0c572cf071123Jorim Jaggi private Rect getWindowRectOverride(int growTarget) { 894db21bbd2caf05322864f09ec45a0c572cf071123Jorim Jaggi if (growTarget == DividerView.INVALID_RECENTS_GROW_TARGET) { 895db21bbd2caf05322864f09ec45a0c572cf071123Jorim Jaggi return null; 896db21bbd2caf05322864f09ec45a0c572cf071123Jorim Jaggi } 897db21bbd2caf05322864f09ec45a0c572cf071123Jorim Jaggi Rect result = new Rect(); 898db21bbd2caf05322864f09ec45a0c572cf071123Jorim Jaggi Rect displayRect = Recents.getSystemServices().getDisplayRect(); 899db21bbd2caf05322864f09ec45a0c572cf071123Jorim Jaggi DockedDividerUtils.calculateBoundsForPosition(growTarget, WindowManager.DOCKED_BOTTOM, 900db21bbd2caf05322864f09ec45a0c572cf071123Jorim Jaggi result, displayRect.width(), displayRect.height(), 901db21bbd2caf05322864f09ec45a0c572cf071123Jorim Jaggi Recents.getSystemServices().getDockedDividerSize(mContext)); 902db21bbd2caf05322864f09ec45a0c572cf071123Jorim Jaggi return result; 903db21bbd2caf05322864f09ec45a0c572cf071123Jorim Jaggi } 904db21bbd2caf05322864f09ec45a0c572cf071123Jorim Jaggi 905fa61ce343e91e11bb06545eae00e0659a2942a7dSid Soundararajan /** 906190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * Starts the recents activity. 907190fe3bf88388fcb109af64571e3baa0d01f1c37Winson */ 908c5b12dd37e964b220c0a108e86ad8a2d12805747Winson private void startRecentsActivity(ActivityOptions opts) { 909190fe3bf88388fcb109af64571e3baa0d01f1c37Winson Intent intent = new Intent(); 9104bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan intent.setClassName(RECENTS_PACKAGE, RECENTS_ACTIVITY); 911190fe3bf88388fcb109af64571e3baa0d01f1c37Winson intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK 912190fe3bf88388fcb109af64571e3baa0d01f1c37Winson | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS 913190fe3bf88388fcb109af64571e3baa0d01f1c37Winson | Intent.FLAG_ACTIVITY_TASK_ON_HOME); 914b58c46acec2e270f24ca587a64298f06cefb09cbSid Soundararajan 915190fe3bf88388fcb109af64571e3baa0d01f1c37Winson if (opts != null) { 916190fe3bf88388fcb109af64571e3baa0d01f1c37Winson mContext.startActivityAsUser(intent, opts.toBundle(), UserHandle.CURRENT); 917190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } else { 918190fe3bf88388fcb109af64571e3baa0d01f1c37Winson mContext.startActivityAsUser(intent, UserHandle.CURRENT); 919190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 920cdb06caebb5f6f554b2ed8c76963970d8cc0ab54Jorim Jaggi EventBus.getDefault().send(new RecentsActivityStartingEvent()); 921190fe3bf88388fcb109af64571e3baa0d01f1c37Winson } 922190fe3bf88388fcb109af64571e3baa0d01f1c37Winson 9233fb67562c548662910160d5672b1b9558bd6571cWinson /**** OnAnimationFinishedListener Implementation ****/ 9241a5203dfd5264104db018b8a09d50075b1af9b2dFilip Gruszczynski 9251a5203dfd5264104db018b8a09d50075b1af9b2dFilip Gruszczynski @Override 9261a5203dfd5264104db018b8a09d50075b1af9b2dFilip Gruszczynski public void onAnimationFinished() { 9271a5203dfd5264104db018b8a09d50075b1af9b2dFilip Gruszczynski EventBus.getDefault().post(new EnterRecentsWindowLastAnimationFrameEvent()); 9281a5203dfd5264104db018b8a09d50075b1af9b2dFilip Gruszczynski } 929190fe3bf88388fcb109af64571e3baa0d01f1c37Winson} 930