TaskStack.java revision d952961977a0eb6c1fefcb0707d1c61741515f68
1303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung/* 2303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung * Copyright (C) 2014 The Android Open Source Project 3303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung * 4303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung * Licensed under the Apache License, Version 2.0 (the "License"); 5303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung * you may not use this file except in compliance with the License. 6303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung * You may obtain a copy of the License at 7303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung * 8303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung * http://www.apache.org/licenses/LICENSE-2.0 9303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung * 10303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung * Unless required by applicable law or agreed to in writing, software 11303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung * distributed under the License is distributed on an "AS IS" BASIS, 12303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung * See the License for the specific language governing permissions and 14303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung * limitations under the License. 15303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung */ 16303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 17303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chungpackage com.android.systemui.recents.model; 18303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 193e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winsonimport android.animation.Animator; 203e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winsonimport android.animation.AnimatorSet; 21882072baacaee4ecd43f0209b691a9af746462f2Winsonimport android.animation.ObjectAnimator; 223e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winsonimport android.animation.PropertyValuesHolder; 233e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winsonimport android.animation.RectEvaluator; 24e7f138c7f0a190c86cec10fb32fa106aacae4093Winsonimport android.content.ComponentName; 2535f3050959e43bf378f9a0adcaef13729206c7e4Winsonimport android.content.Context; 263e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winsonimport android.content.res.Configuration; 273e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winsonimport android.content.res.Resources; 28ec396d6399c5c31d697d81e94aff459e9771b0c6Winson Chungimport android.graphics.Color; 29be7607af8875236b9cf7bdb5f5aa089c207529afWinsonimport android.graphics.Rect; 30be7607af8875236b9cf7bdb5f5aa089c207529afWinsonimport android.graphics.RectF; 31882072baacaee4ecd43f0209b691a9af746462f2Winsonimport android.graphics.drawable.ColorDrawable; 325500390a006f2bbea565068234774a36cea076c0Winsonimport android.util.ArrayMap; 335500390a006f2bbea565068234774a36cea076c0Winsonimport android.util.ArraySet; 342b9ef6548be89d36ea7629f4a3d8ba7bba1422ceWinson Chungimport android.util.SparseArray; 353e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winsonimport android.view.animation.Interpolator; 36c0d7058b14c24cd07912f5629c26b39b7b4673d5Winson 373e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winsonimport com.android.internal.policy.DockedDividerUtils; 382536c7ed446203ea12b38cf05a88e603f8d1b768Winsonimport com.android.systemui.R; 39e7f138c7f0a190c86cec10fb32fa106aacae4093Winsonimport com.android.systemui.recents.Recents; 403e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winsonimport com.android.systemui.recents.RecentsConfiguration; 41c742f973b1e506732911c156c5869fd377afc5bfWinsonimport com.android.systemui.recents.RecentsDebugFlags; 42ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chungimport com.android.systemui.recents.misc.NamedCounter; 43e7f138c7f0a190c86cec10fb32fa106aacae4093Winsonimport com.android.systemui.recents.misc.SystemServicesProxy; 44a0e88b5013d708ac6ed6518817d83c64c87ae4b1Winson Chungimport com.android.systemui.recents.misc.Utilities; 45eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winsonimport com.android.systemui.recents.views.DropTarget; 468aa9959413a06c3d2ff75e0c7be9e3cb7ac7cd2eWinsonimport com.android.systemui.recents.views.TaskViewAnimation; 47303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 48303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chungimport java.util.ArrayList; 49ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chungimport java.util.Collections; 50ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chungimport java.util.Comparator; 51303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chungimport java.util.List; 52a433fa9c17772f563163ff7db177d091d6aebd5bWinson Chungimport java.util.Random; 53303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 54be7607af8875236b9cf7bdb5f5aa089c207529afWinsonimport static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_BOTTOM_OR_RIGHT; 55be7607af8875236b9cf7bdb5f5aa089c207529afWinsonimport static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT; 56eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winsonimport static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID; 57eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winsonimport static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID; 585500390a006f2bbea565068234774a36cea076c0Winsonimport static android.view.WindowManager.DOCKED_BOTTOM; 595500390a006f2bbea565068234774a36cea076c0Winsonimport static android.view.WindowManager.DOCKED_INVALID; 603e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winsonimport static android.view.WindowManager.DOCKED_LEFT; 613e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winsonimport static android.view.WindowManager.DOCKED_RIGHT; 623e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winsonimport static android.view.WindowManager.DOCKED_TOP; 63be7607af8875236b9cf7bdb5f5aa089c207529afWinson 64303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 65303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung/** 66303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung * An interface for a task filter to query whether a particular task should show in a stack. 67303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung */ 68303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chunginterface TaskFilter { 69303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung /** Returns whether the filter accepts the specified task */ 702b9ef6548be89d36ea7629f4a3d8ba7bba1422ceWinson Chung public boolean acceptTask(SparseArray<Task> taskIdMap, Task t, int index); 71303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung} 72303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 73303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung/** 74303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung * A list of filtered tasks. 75303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung */ 76303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chungclass FilteredTaskList { 77eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson 78eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson ArrayList<Task> mTasks = new ArrayList<>(); 79eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson ArrayList<Task> mFilteredTasks = new ArrayList<>(); 805500390a006f2bbea565068234774a36cea076c0Winson ArrayMap<Task.TaskKey, Integer> mTaskIndices = new ArrayMap<>(); 81303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung TaskFilter mFilter; 82303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 83303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung /** Sets the task filter, saving the current touch state */ 84c6a1623cc48581380b698ae87b43bfafb9c935baWinson Chung boolean setFilter(TaskFilter filter) { 855500390a006f2bbea565068234774a36cea076c0Winson ArrayList<Task> prevFilteredTasks = new ArrayList<>(mFilteredTasks); 86303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung mFilter = filter; 87303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung updateFilteredTasks(); 88b44c24fb50845dfbc1f49e78085cf5e01a32067fWinson Chung if (!prevFilteredTasks.equals(mFilteredTasks)) { 89b44c24fb50845dfbc1f49e78085cf5e01a32067fWinson Chung return true; 90b44c24fb50845dfbc1f49e78085cf5e01a32067fWinson Chung } else { 91b44c24fb50845dfbc1f49e78085cf5e01a32067fWinson Chung return false; 92b44c24fb50845dfbc1f49e78085cf5e01a32067fWinson Chung } 93303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 94303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 958f0e3a68cdd3b2403ff8a1677f90b998f4175f40Winson /** 968f0e3a68cdd3b2403ff8a1677f90b998f4175f40Winson * Resets the task list, but does not remove the filter. 978f0e3a68cdd3b2403ff8a1677f90b998f4175f40Winson */ 98bc571a980704dc767838935e83c6aed231c406e9Winson Chung void reset() { 99bc571a980704dc767838935e83c6aed231c406e9Winson Chung mTasks.clear(); 100bc571a980704dc767838935e83c6aed231c406e9Winson Chung mFilteredTasks.clear(); 101bc571a980704dc767838935e83c6aed231c406e9Winson Chung mTaskIndices.clear(); 102bc571a980704dc767838935e83c6aed231c406e9Winson Chung } 103bc571a980704dc767838935e83c6aed231c406e9Winson Chung 104303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung /** Removes the task filter and returns the previous touch state */ 105303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung void removeFilter() { 106303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung mFilter = null; 107303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung updateFilteredTasks(); 108303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 109303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 110303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung /** Adds a new task to the task list */ 111303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung void add(Task t) { 112303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung mTasks.add(t); 113303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung updateFilteredTasks(); 114303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 115303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 116eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson /** 117eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson * Moves the given task. 118eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson */ 119eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson public void moveTaskToStack(Task task, int insertIndex, int newStackId) { 120eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson int taskIndex = indexOf(task); 121eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson if (taskIndex != insertIndex) { 122eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson mTasks.remove(taskIndex); 123eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson if (taskIndex < insertIndex) { 124eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson insertIndex--; 125eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson } 126eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson mTasks.add(insertIndex, task); 127eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson } 128eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson 129eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson // Update the stack id now, after we've moved the task, and before we update the 130eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson // filtered tasks 131eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson task.setStackId(newStackId); 132eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson updateFilteredTasks(); 133eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson } 134eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson 135303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung /** Sets the list of tasks */ 136303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung void set(List<Task> tasks) { 137303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung mTasks.clear(); 138303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung mTasks.addAll(tasks); 139303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung updateFilteredTasks(); 140303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 141303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 142303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung /** Removes a task from the base list only if it is in the filtered list */ 143303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung boolean remove(Task t) { 144303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung if (mFilteredTasks.contains(t)) { 145303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung boolean removed = mTasks.remove(t); 146303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung updateFilteredTasks(); 147303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung return removed; 148303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 149303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung return false; 150303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 151303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 152303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung /** Returns the index of this task in the list of filtered tasks */ 153303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung int indexOf(Task t) { 15423746d51d922d3df2cdd2635d0c133366c754438Winson if (t != null && mTaskIndices.containsKey(t.key)) { 155a4ccb86ddc8f9f486aee25fb836f4aff97bf7679Winson Chung return mTaskIndices.get(t.key); 156a4ccb86ddc8f9f486aee25fb836f4aff97bf7679Winson Chung } 157a4ccb86ddc8f9f486aee25fb836f4aff97bf7679Winson Chung return -1; 158303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 159303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 160303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung /** Returns the size of the list of filtered tasks */ 161303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung int size() { 162303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung return mFilteredTasks.size(); 163303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 164303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 165303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung /** Returns whether the filtered list contains this task */ 166303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung boolean contains(Task t) { 167ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung return mTaskIndices.containsKey(t.key); 168303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 169303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 170303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung /** Updates the list of filtered tasks whenever the base task list changes */ 171303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung private void updateFilteredTasks() { 172303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung mFilteredTasks.clear(); 173303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung if (mFilter != null) { 1742b9ef6548be89d36ea7629f4a3d8ba7bba1422ceWinson Chung // Create a sparse array from task id to Task 1752b9ef6548be89d36ea7629f4a3d8ba7bba1422ceWinson Chung SparseArray<Task> taskIdMap = new SparseArray<>(); 176303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung int taskCount = mTasks.size(); 177303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung for (int i = 0; i < taskCount; i++) { 178303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung Task t = mTasks.get(i); 1792b9ef6548be89d36ea7629f4a3d8ba7bba1422ceWinson Chung taskIdMap.put(t.key.id, t); 1802b9ef6548be89d36ea7629f4a3d8ba7bba1422ceWinson Chung } 1812b9ef6548be89d36ea7629f4a3d8ba7bba1422ceWinson Chung 1822b9ef6548be89d36ea7629f4a3d8ba7bba1422ceWinson Chung for (int i = 0; i < taskCount; i++) { 1832b9ef6548be89d36ea7629f4a3d8ba7bba1422ceWinson Chung Task t = mTasks.get(i); 1842b9ef6548be89d36ea7629f4a3d8ba7bba1422ceWinson Chung if (mFilter.acceptTask(taskIdMap, t, i)) { 185303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung mFilteredTasks.add(t); 186303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 187303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 188303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } else { 189303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung mFilteredTasks.addAll(mTasks); 190303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 191ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung updateFilteredTaskIndices(); 192ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 193ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung 194ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung /** Updates the mapping of tasks to indices. */ 195ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung private void updateFilteredTaskIndices() { 196ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung int taskCount = mFilteredTasks.size(); 1975500390a006f2bbea565068234774a36cea076c0Winson mTaskIndices.clear(); 198ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung for (int i = 0; i < taskCount; i++) { 199ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung Task t = mFilteredTasks.get(i); 200ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung mTaskIndices.put(t.key, i); 201ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 202303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 203303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 204303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung /** Returns whether this task list is filtered */ 205303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung boolean hasFilter() { 206303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung return (mFilter != null); 207303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 208303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 209303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung /** Returns the list of filtered tasks */ 210303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung ArrayList<Task> getTasks() { 211303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung return mFilteredTasks; 212303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 213303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung} 214303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 215303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung/** 216303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung * The task stack contains a list of multiple tasks. 217303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung */ 218303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chungpublic class TaskStack { 219ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung 220ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung /** Task stack callbacks */ 22104dfe0d26b944324ee920001f40d74cff47281d6Winson Chung public interface TaskStackCallbacks { 222062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung /** 223062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung * Notifies when a new task has been added to the stack. 224062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung */ 225062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung void onStackTaskAdded(TaskStack stack, Task newTask); 226062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung 227062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung /** 228062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung * Notifies when a task has been removed from the stack. 229062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung */ 230aaf33bc2b27fa0c4b59484059434a0fad3187af4Winson void onStackTaskRemoved(TaskStack stack, Task removedTask, boolean wasFrontMostTask, 2318aa9959413a06c3d2ff75e0c7be9e3cb7ac7cd2eWinson Task newFrontMostTask, TaskViewAnimation animation); 232a0731a1a2611d5a89c5960fe39a7ff09cc8fd5eaWinson 233062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung /** 234062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung * Notifies when a task has been removed from the history. 235062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung */ 2368aa9959413a06c3d2ff75e0c7be9e3cb7ac7cd2eWinson void onHistoryTaskRemoved(TaskStack stack, Task removedTask, TaskViewAnimation animation); 23704dfe0d26b944324ee920001f40d74cff47281d6Winson Chung } 23804dfe0d26b944324ee920001f40d74cff47281d6Winson Chung 239250608a5cd08862f4752a924d51710805850db8aWinson /** 240250608a5cd08862f4752a924d51710805850db8aWinson * The various possible dock states when dragging and dropping a task. 241250608a5cd08862f4752a924d51710805850db8aWinson */ 242f0d1c44a59a10707baa0cca8dd377302260710c1Winson public static class DockState implements DropTarget { 243f0d1c44a59a10707baa0cca8dd377302260710c1Winson 244f0d1c44a59a10707baa0cca8dd377302260710c1Winson private static final int DOCK_AREA_ALPHA = 192; 2453e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson public static final DockState NONE = new DockState(DOCKED_INVALID, -1, 80, null, null, null); 2463e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson public static final DockState LEFT = new DockState(DOCKED_LEFT, 247f0d1c44a59a10707baa0cca8dd377302260710c1Winson DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT, DOCK_AREA_ALPHA, 2483e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson new RectF(0, 0, 0.125f, 1), new RectF(0, 0, 0.125f, 1), 2493e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson new RectF(0, 0, 0.5f, 1)); 2503e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson public static final DockState TOP = new DockState(DOCKED_TOP, 251f0d1c44a59a10707baa0cca8dd377302260710c1Winson DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT, DOCK_AREA_ALPHA, 2523e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson new RectF(0, 0, 1, 0.125f), new RectF(0, 0, 1, 0.125f), 2533e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson new RectF(0, 0, 1, 0.5f)); 2543e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson public static final DockState RIGHT = new DockState(DOCKED_RIGHT, 255f0d1c44a59a10707baa0cca8dd377302260710c1Winson DOCKED_STACK_CREATE_MODE_BOTTOM_OR_RIGHT, DOCK_AREA_ALPHA, 2563e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson new RectF(0.875f, 0, 1, 1), new RectF(0.875f, 0, 1, 1), 2573e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson new RectF(0.5f, 0, 1, 1)); 2583e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson public static final DockState BOTTOM = new DockState(DOCKED_BOTTOM, 259f0d1c44a59a10707baa0cca8dd377302260710c1Winson DOCKED_STACK_CREATE_MODE_BOTTOM_OR_RIGHT, DOCK_AREA_ALPHA, 2603e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson new RectF(0, 0.875f, 1, 1), new RectF(0, 0.875f, 1, 1), 2613e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson new RectF(0, 0.5f, 1, 1)); 262eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson 263eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson @Override 2643e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson public boolean acceptsDrop(int x, int y, int width, int height, boolean isCurrentTarget) { 2653e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson return isCurrentTarget 2663e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson ? areaContainsPoint(expandedTouchDockArea, width, height, x, y) 2673e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson : areaContainsPoint(touchArea, width, height, x, y); 268eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson } 269be7607af8875236b9cf7bdb5f5aa089c207529afWinson 270882072baacaee4ecd43f0209b691a9af746462f2Winson // Represents the view state of this dock state 271882072baacaee4ecd43f0209b691a9af746462f2Winson public class ViewState { 272882072baacaee4ecd43f0209b691a9af746462f2Winson public final int dockAreaAlpha; 273882072baacaee4ecd43f0209b691a9af746462f2Winson public final ColorDrawable dockAreaOverlay; 2743e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson private AnimatorSet dockAreaOverlayAnimator; 275882072baacaee4ecd43f0209b691a9af746462f2Winson 276882072baacaee4ecd43f0209b691a9af746462f2Winson private ViewState(int alpha) { 277882072baacaee4ecd43f0209b691a9af746462f2Winson dockAreaAlpha = alpha; 278882072baacaee4ecd43f0209b691a9af746462f2Winson dockAreaOverlay = new ColorDrawable(0xFFffffff); 279882072baacaee4ecd43f0209b691a9af746462f2Winson dockAreaOverlay.setAlpha(0); 280882072baacaee4ecd43f0209b691a9af746462f2Winson } 281882072baacaee4ecd43f0209b691a9af746462f2Winson 282882072baacaee4ecd43f0209b691a9af746462f2Winson /** 2833e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson * Creates a new bounds and alpha animation. 284882072baacaee4ecd43f0209b691a9af746462f2Winson */ 2853e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson public void startAnimation(Rect bounds, int alpha, int duration, 2863e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson Interpolator interpolator, boolean animateAlpha, boolean animateBounds) { 2873e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson if (dockAreaOverlayAnimator != null) { 2883e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson dockAreaOverlayAnimator.cancel(); 2893e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson } 2903e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson 2913e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson ArrayList<Animator> animators = new ArrayList<>(); 292882072baacaee4ecd43f0209b691a9af746462f2Winson if (dockAreaOverlay.getAlpha() != alpha) { 2933e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson if (animateAlpha) { 2943e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson animators.add(ObjectAnimator.ofInt(dockAreaOverlay, 2953e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson Utilities.DRAWABLE_ALPHA, dockAreaOverlay.getAlpha(), alpha)); 2963e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson } else { 2973e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson dockAreaOverlay.setAlpha(alpha); 2983e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson } 2993e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson } 3003e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson if (bounds != null && !dockAreaOverlay.getBounds().equals(bounds)) { 3013e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson if (animateBounds) { 3023e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson PropertyValuesHolder prop = PropertyValuesHolder.ofObject( 3033e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson Utilities.DRAWABLE_RECT, new RectEvaluator(new Rect()), 3043e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson dockAreaOverlay.getBounds(), bounds); 3053e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson animators.add(ObjectAnimator.ofPropertyValuesHolder(dockAreaOverlay, prop)); 3063e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson } else { 3073e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson dockAreaOverlay.setBounds(bounds); 308882072baacaee4ecd43f0209b691a9af746462f2Winson } 3093e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson } 3103e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson if (!animators.isEmpty()) { 3113e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson dockAreaOverlayAnimator = new AnimatorSet(); 3123e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson dockAreaOverlayAnimator.playTogether(animators); 313882072baacaee4ecd43f0209b691a9af746462f2Winson dockAreaOverlayAnimator.setDuration(duration); 3143e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson dockAreaOverlayAnimator.setInterpolator(interpolator); 315882072baacaee4ecd43f0209b691a9af746462f2Winson dockAreaOverlayAnimator.start(); 316882072baacaee4ecd43f0209b691a9af746462f2Winson } 317882072baacaee4ecd43f0209b691a9af746462f2Winson } 318882072baacaee4ecd43f0209b691a9af746462f2Winson } 319882072baacaee4ecd43f0209b691a9af746462f2Winson 3203e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson public final int dockSide; 321be7607af8875236b9cf7bdb5f5aa089c207529afWinson public final int createMode; 322882072baacaee4ecd43f0209b691a9af746462f2Winson public final ViewState viewState; 323882072baacaee4ecd43f0209b691a9af746462f2Winson private final RectF touchArea; 3243e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson private final RectF dockArea; 3253e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson private final RectF expandedTouchDockArea; 326be7607af8875236b9cf7bdb5f5aa089c207529afWinson 327be7607af8875236b9cf7bdb5f5aa089c207529afWinson /** 328be7607af8875236b9cf7bdb5f5aa089c207529afWinson * @param createMode used to pass to ActivityManager to dock the task 329be7607af8875236b9cf7bdb5f5aa089c207529afWinson * @param touchArea the area in which touch will initiate this dock state 330eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson * @param dockArea the visible dock area 3313e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson * @param expandedTouchDockArea the areain which touch will continue to dock after entering 3323e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson * the initial touch area. This is also the new dock area to 3333e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson * draw. 334be7607af8875236b9cf7bdb5f5aa089c207529afWinson */ 3353e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson DockState(int dockSide, int createMode, int dockAreaAlpha, RectF touchArea, RectF dockArea, 3363e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson RectF expandedTouchDockArea) { 3373e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson this.dockSide = dockSide; 338be7607af8875236b9cf7bdb5f5aa089c207529afWinson this.createMode = createMode; 339882072baacaee4ecd43f0209b691a9af746462f2Winson this.viewState = new ViewState(dockAreaAlpha); 340be7607af8875236b9cf7bdb5f5aa089c207529afWinson this.dockArea = dockArea; 341882072baacaee4ecd43f0209b691a9af746462f2Winson this.touchArea = touchArea; 3423e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson this.expandedTouchDockArea = expandedTouchDockArea; 343be7607af8875236b9cf7bdb5f5aa089c207529afWinson } 344be7607af8875236b9cf7bdb5f5aa089c207529afWinson 345be7607af8875236b9cf7bdb5f5aa089c207529afWinson /** 3463e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson * Returns whether {@param x} and {@param y} are contained in the area scaled to the 347be7607af8875236b9cf7bdb5f5aa089c207529afWinson * given {@param width} and {@param height}. 348be7607af8875236b9cf7bdb5f5aa089c207529afWinson */ 3493e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson public boolean areaContainsPoint(RectF area, int width, int height, float x, float y) { 3503e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson int left = (int) (area.left * width); 3513e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson int top = (int) (area.top * height); 3523e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson int right = (int) (area.right * width); 3533e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson int bottom = (int) (area.bottom * height); 354be7607af8875236b9cf7bdb5f5aa089c207529afWinson return x >= left && y >= top && x <= right && y <= bottom; 355be7607af8875236b9cf7bdb5f5aa089c207529afWinson } 356be7607af8875236b9cf7bdb5f5aa089c207529afWinson 357be7607af8875236b9cf7bdb5f5aa089c207529afWinson /** 358be7607af8875236b9cf7bdb5f5aa089c207529afWinson * Returns the docked task bounds with the given {@param width} and {@param height}. 359be7607af8875236b9cf7bdb5f5aa089c207529afWinson */ 3603e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson public Rect getPreDockedBounds(int width, int height) { 361be7607af8875236b9cf7bdb5f5aa089c207529afWinson return new Rect((int) (dockArea.left * width), (int) (dockArea.top * height), 362be7607af8875236b9cf7bdb5f5aa089c207529afWinson (int) (dockArea.right * width), (int) (dockArea.bottom * height)); 363be7607af8875236b9cf7bdb5f5aa089c207529afWinson } 3643e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson 3653e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson /** 3663e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson * Returns the expanded docked task bounds with the given {@param width} and 3673e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson * {@param height}. 3683e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson */ 3693e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson public Rect getDockedBounds(int width, int height, int dividerSize, Rect insets, 3703e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson Resources res) { 3713e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson // Calculate the docked task bounds 3723e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson boolean isHorizontalDivision = 3733e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson res.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT; 3743e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson int position = DockedDividerUtils.calculateMiddlePosition(isHorizontalDivision, 3753e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson insets, width, height, dividerSize); 3763e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson Rect newWindowBounds = new Rect(); 3773e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson DockedDividerUtils.calculateBoundsForPosition(position, dockSide, newWindowBounds, 3783e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson width, height, dividerSize); 3793e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson return newWindowBounds; 3803e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson } 3813e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson 3823e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson /** 3833e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson * Returns the task stack bounds with the given {@param width} and 3843e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson * {@param height}. 3853e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson */ 3863e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson public Rect getDockedTaskStackBounds(int width, int height, int dividerSize, Rect insets, 3873e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson Resources res) { 3883e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson RecentsConfiguration config = Recents.getConfiguration(); 3893e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson 3903e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson // Calculate the inverse docked task bounds 3913e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson boolean isHorizontalDivision = 3923e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson res.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT; 3933e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson int position = DockedDividerUtils.calculateMiddlePosition(isHorizontalDivision, 3943e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson insets, width, height, dividerSize); 3953e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson Rect newWindowBounds = new Rect(); 3963e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson DockedDividerUtils.calculateBoundsForPosition(position, 3973e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson DockedDividerUtils.invertDockSide(dockSide), newWindowBounds, width, height, 3983e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson dividerSize); 3993e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson 4003e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson // Calculate the task stack bounds from the new window bounds 4013e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson Rect searchBarSpaceBounds = new Rect(); 4023e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson Rect taskStackBounds = new Rect(); 403d952961977a0eb6c1fefcb0707d1c61741515f68Winson // If the task stack bounds is specifically under the dock area, then ignore the top 404d952961977a0eb6c1fefcb0707d1c61741515f68Winson // inset 405d952961977a0eb6c1fefcb0707d1c61741515f68Winson int top = dockArea.bottom < 1f 406d952961977a0eb6c1fefcb0707d1c61741515f68Winson ? 0 407d952961977a0eb6c1fefcb0707d1c61741515f68Winson : insets.top; 408d952961977a0eb6c1fefcb0707d1c61741515f68Winson config.getTaskStackBounds(newWindowBounds, top, insets.right, 4093e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson searchBarSpaceBounds, taskStackBounds); 4103e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson return taskStackBounds; 4113e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson } 412be7607af8875236b9cf7bdb5f5aa089c207529afWinson } 413be7607af8875236b9cf7bdb5f5aa089c207529afWinson 414250608a5cd08862f4752a924d51710805850db8aWinson // A comparator that sorts tasks by their last active time 415250608a5cd08862f4752a924d51710805850db8aWinson private Comparator<Task> LAST_ACTIVE_TIME_COMPARATOR = new Comparator<Task>() { 416250608a5cd08862f4752a924d51710805850db8aWinson @Override 417250608a5cd08862f4752a924d51710805850db8aWinson public int compare(Task o1, Task o2) { 418250608a5cd08862f4752a924d51710805850db8aWinson return Long.compare(o1.key.lastActiveTime, o2.key.lastActiveTime); 419250608a5cd08862f4752a924d51710805850db8aWinson } 420250608a5cd08862f4752a924d51710805850db8aWinson }; 421250608a5cd08862f4752a924d51710805850db8aWinson 422509d0d0c9e2ee165d04e898fea59f8941ac7138dWinson Chung // A comparator that sorts tasks by their last active time and freeform state 423509d0d0c9e2ee165d04e898fea59f8941ac7138dWinson Chung private Comparator<Task> FREEFORM_LAST_ACTIVE_TIME_COMPARATOR = new Comparator<Task>() { 424509d0d0c9e2ee165d04e898fea59f8941ac7138dWinson Chung @Override 425509d0d0c9e2ee165d04e898fea59f8941ac7138dWinson Chung public int compare(Task o1, Task o2) { 426509d0d0c9e2ee165d04e898fea59f8941ac7138dWinson Chung if (o1.isFreeformTask() && !o2.isFreeformTask()) { 427509d0d0c9e2ee165d04e898fea59f8941ac7138dWinson Chung return 1; 428509d0d0c9e2ee165d04e898fea59f8941ac7138dWinson Chung } else if (o2.isFreeformTask() && !o1.isFreeformTask()) { 429509d0d0c9e2ee165d04e898fea59f8941ac7138dWinson Chung return -1; 430509d0d0c9e2ee165d04e898fea59f8941ac7138dWinson Chung } 431509d0d0c9e2ee165d04e898fea59f8941ac7138dWinson Chung return Long.compare(o1.key.lastActiveTime, o2.key.lastActiveTime); 432509d0d0c9e2ee165d04e898fea59f8941ac7138dWinson Chung } 433509d0d0c9e2ee165d04e898fea59f8941ac7138dWinson Chung }; 434509d0d0c9e2ee165d04e898fea59f8941ac7138dWinson Chung 435509d0d0c9e2ee165d04e898fea59f8941ac7138dWinson Chung 436083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung // The task offset to apply to a task id as a group affiliation 437083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung static final int IndividualTaskIdOffset = 1 << 16; 438083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung 439062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung ArrayList<Task> mRawTaskList = new ArrayList<>(); 440250608a5cd08862f4752a924d51710805850db8aWinson FilteredTaskList mStackTaskList = new FilteredTaskList(); 441250608a5cd08862f4752a924d51710805850db8aWinson FilteredTaskList mHistoryTaskList = new FilteredTaskList(); 442303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung TaskStackCallbacks mCb; 443303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 4448f0e3a68cdd3b2403ff8a1677f90b998f4175f40Winson ArrayList<TaskGrouping> mGroups = new ArrayList<>(); 4455500390a006f2bbea565068234774a36cea076c0Winson ArrayMap<Integer, TaskGrouping> mAffinitiesGroups = new ArrayMap<>(); 4468f0e3a68cdd3b2403ff8a1677f90b998f4175f40Winson 4478f0e3a68cdd3b2403ff8a1677f90b998f4175f40Winson public TaskStack() { 4488f0e3a68cdd3b2403ff8a1677f90b998f4175f40Winson // Ensure that we only show non-docked tasks 449250608a5cd08862f4752a924d51710805850db8aWinson mStackTaskList.setFilter(new TaskFilter() { 4508f0e3a68cdd3b2403ff8a1677f90b998f4175f40Winson @Override 4512b9ef6548be89d36ea7629f4a3d8ba7bba1422ceWinson Chung public boolean acceptTask(SparseArray<Task> taskIdMap, Task t, int index) { 4522b9ef6548be89d36ea7629f4a3d8ba7bba1422ceWinson Chung if (t.isAffiliatedTask()) { 4530583d3d18812d31d50228a6f29cb15b3219c9e94Winson Chung // If this task is affiliated with another parent in the stack, then the 4540583d3d18812d31d50228a6f29cb15b3219c9e94Winson Chung // historical state of this task depends on the state of the parent task 455296278a0679375b8c43962a9e3c9bb4e8ab201e7Winson Chung Task parentTask = taskIdMap.get(t.affiliationTaskId); 4562b9ef6548be89d36ea7629f4a3d8ba7bba1422ceWinson Chung if (parentTask != null) { 4572b9ef6548be89d36ea7629f4a3d8ba7bba1422ceWinson Chung t = parentTask; 4582b9ef6548be89d36ea7629f4a3d8ba7bba1422ceWinson Chung } 4592b9ef6548be89d36ea7629f4a3d8ba7bba1422ceWinson Chung } 4600583d3d18812d31d50228a6f29cb15b3219c9e94Winson Chung return !t.isHistorical; 461250608a5cd08862f4752a924d51710805850db8aWinson } 462250608a5cd08862f4752a924d51710805850db8aWinson }); 463250608a5cd08862f4752a924d51710805850db8aWinson mHistoryTaskList.setFilter(new TaskFilter() { 464250608a5cd08862f4752a924d51710805850db8aWinson @Override 4652b9ef6548be89d36ea7629f4a3d8ba7bba1422ceWinson Chung public boolean acceptTask(SparseArray<Task> taskIdMap, Task t, int index) { 4662b9ef6548be89d36ea7629f4a3d8ba7bba1422ceWinson Chung if (t.isAffiliatedTask()) { 4670583d3d18812d31d50228a6f29cb15b3219c9e94Winson Chung // If this task is affiliated with another parent in the stack, then the 4680583d3d18812d31d50228a6f29cb15b3219c9e94Winson Chung // historical state of this task depends on the state of the parent task 469296278a0679375b8c43962a9e3c9bb4e8ab201e7Winson Chung Task parentTask = taskIdMap.get(t.affiliationTaskId); 4702b9ef6548be89d36ea7629f4a3d8ba7bba1422ceWinson Chung if (parentTask != null) { 4712b9ef6548be89d36ea7629f4a3d8ba7bba1422ceWinson Chung t = parentTask; 4722b9ef6548be89d36ea7629f4a3d8ba7bba1422ceWinson Chung } 4732b9ef6548be89d36ea7629f4a3d8ba7bba1422ceWinson Chung } 4740583d3d18812d31d50228a6f29cb15b3219c9e94Winson Chung return t.isHistorical; 4758f0e3a68cdd3b2403ff8a1677f90b998f4175f40Winson } 4768f0e3a68cdd3b2403ff8a1677f90b998f4175f40Winson }); 4778f0e3a68cdd3b2403ff8a1677f90b998f4175f40Winson } 478303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 479d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung /** Sets the callbacks for this task stack. */ 480303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung public void setCallbacks(TaskStackCallbacks cb) { 481303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung mCb = cb; 482303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 483303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 484bc571a980704dc767838935e83c6aed231c406e9Winson Chung /** Resets this TaskStack. */ 485bc571a980704dc767838935e83c6aed231c406e9Winson Chung public void reset() { 486bc571a980704dc767838935e83c6aed231c406e9Winson Chung mCb = null; 487250608a5cd08862f4752a924d51710805850db8aWinson mStackTaskList.reset(); 488250608a5cd08862f4752a924d51710805850db8aWinson mHistoryTaskList.reset(); 489bc571a980704dc767838935e83c6aed231c406e9Winson Chung mGroups.clear(); 490bc571a980704dc767838935e83c6aed231c406e9Winson Chung mAffinitiesGroups.clear(); 491bc571a980704dc767838935e83c6aed231c406e9Winson Chung } 492bc571a980704dc767838935e83c6aed231c406e9Winson Chung 493eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson /** 494eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson * Moves the given task to either the front of the freeform workspace or the stack. 495eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson */ 496eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson public void moveTaskToStack(Task task, int newStackId) { 497eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson // Find the index to insert into 498250608a5cd08862f4752a924d51710805850db8aWinson ArrayList<Task> taskList = mStackTaskList.getTasks(); 499eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson int taskCount = taskList.size(); 500eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson if (!task.isFreeformTask() && (newStackId == FREEFORM_WORKSPACE_STACK_ID)) { 501eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson // Insert freeform tasks at the front 502250608a5cd08862f4752a924d51710805850db8aWinson mStackTaskList.moveTaskToStack(task, taskCount, newStackId); 503eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson } else if (task.isFreeformTask() && (newStackId == FULLSCREEN_WORKSPACE_STACK_ID)) { 504eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson // Insert after the first stacked task 505eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson int insertIndex = 0; 506eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson for (int i = taskCount - 1; i >= 0; i--) { 507eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson if (!taskList.get(i).isFreeformTask()) { 508eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson insertIndex = i + 1; 509eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson break; 510eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson } 511eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson } 512250608a5cd08862f4752a924d51710805850db8aWinson mStackTaskList.moveTaskToStack(task, insertIndex, newStackId); 513eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson } 514eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson } 515eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson 5166ac8bd6198f67b64aea2258bdb5f8ed371b5bec1Winson Chung /** Does the actual work associated with removing the task. */ 517250608a5cd08862f4752a924d51710805850db8aWinson void removeTaskImpl(FilteredTaskList taskList, Task t) { 5186ac8bd6198f67b64aea2258bdb5f8ed371b5bec1Winson Chung // Remove the task from the list 519250608a5cd08862f4752a924d51710805850db8aWinson taskList.remove(t); 5206ac8bd6198f67b64aea2258bdb5f8ed371b5bec1Winson Chung // Remove it from the group as well, and if it is empty, remove the group 5216ac8bd6198f67b64aea2258bdb5f8ed371b5bec1Winson Chung TaskGrouping group = t.group; 5224e5fb2f4e1ed4eb119a201541ad89aafac8c53feWinson Chung if (group != null) { 5234e5fb2f4e1ed4eb119a201541ad89aafac8c53feWinson Chung group.removeTask(t); 5244e5fb2f4e1ed4eb119a201541ad89aafac8c53feWinson Chung if (group.getTaskCount() == 0) { 5254e5fb2f4e1ed4eb119a201541ad89aafac8c53feWinson Chung removeGroup(group); 5264e5fb2f4e1ed4eb119a201541ad89aafac8c53feWinson Chung } 5276ac8bd6198f67b64aea2258bdb5f8ed371b5bec1Winson Chung } 5286ac8bd6198f67b64aea2258bdb5f8ed371b5bec1Winson Chung } 5296ac8bd6198f67b64aea2258bdb5f8ed371b5bec1Winson Chung 5308aa9959413a06c3d2ff75e0c7be9e3cb7ac7cd2eWinson /** 5318aa9959413a06c3d2ff75e0c7be9e3cb7ac7cd2eWinson * Removes a task from the stack, with an additional {@param animation} hint to the callbacks on 5328aa9959413a06c3d2ff75e0c7be9e3cb7ac7cd2eWinson * how they should update themselves. 5338aa9959413a06c3d2ff75e0c7be9e3cb7ac7cd2eWinson */ 5348aa9959413a06c3d2ff75e0c7be9e3cb7ac7cd2eWinson public void removeTask(Task t, TaskViewAnimation animation) { 535250608a5cd08862f4752a924d51710805850db8aWinson if (mStackTaskList.contains(t)) { 53635a8b04140598a5b5c4865254b942adb6a830991Winson boolean wasFrontMostTask = (getStackFrontMostTask(false /* includeFreeform */) == t); 537250608a5cd08862f4752a924d51710805850db8aWinson removeTaskImpl(mStackTaskList, t); 53835a8b04140598a5b5c4865254b942adb6a830991Winson Task newFrontMostTask = getStackFrontMostTask(false /* includeFreeform */); 539303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung if (mCb != null) { 540ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung // Notify that a task has been removed 5418aa9959413a06c3d2ff75e0c7be9e3cb7ac7cd2eWinson mCb.onStackTaskRemoved(this, t, wasFrontMostTask, newFrontMostTask, animation); 542303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 543250608a5cd08862f4752a924d51710805850db8aWinson } else if (mHistoryTaskList.contains(t)) { 544250608a5cd08862f4752a924d51710805850db8aWinson removeTaskImpl(mHistoryTaskList, t); 545303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung if (mCb != null) { 546ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung // Notify that a task has been removed 5478aa9959413a06c3d2ff75e0c7be9e3cb7ac7cd2eWinson mCb.onHistoryTaskRemoved(this, t, animation); 548303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 549303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 5503e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson mRawTaskList.remove(t); 551250608a5cd08862f4752a924d51710805850db8aWinson } 552250608a5cd08862f4752a924d51710805850db8aWinson 553250608a5cd08862f4752a924d51710805850db8aWinson /** 554250608a5cd08862f4752a924d51710805850db8aWinson * Sets a few tasks in one go, without calling any callbacks. 555062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung * 556062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung * @param tasks the new set of tasks to replace the current set. 557062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung * @param notifyStackChanges whether or not to callback on specific changes to the list of tasks. 558250608a5cd08862f4752a924d51710805850db8aWinson */ 559062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung public void setTasks(List<Task> tasks, boolean notifyStackChanges) { 560062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung // Compute a has set for each of the tasks 5615500390a006f2bbea565068234774a36cea076c0Winson ArrayMap<Task.TaskKey, Task> currentTasksMap = createTaskKeyMapFromList(mRawTaskList); 5625500390a006f2bbea565068234774a36cea076c0Winson ArrayMap<Task.TaskKey, Task> newTasksMap = createTaskKeyMapFromList(tasks); 563062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung 564062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung ArrayList<Task> newTasks = new ArrayList<>(); 565062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung 566062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung // Disable notifications if there are no callbacks 567062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung if (mCb == null) { 568062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung notifyStackChanges = false; 569062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung } 570062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung 571062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung // Remove any tasks that no longer exist 572062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung int taskCount = mRawTaskList.size(); 573062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung for (int i = 0; i < taskCount; i++) { 574062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung Task task = mRawTaskList.get(i); 575062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung if (!newTasksMap.containsKey(task.key)) { 576062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung if (notifyStackChanges) { 5778aa9959413a06c3d2ff75e0c7be9e3cb7ac7cd2eWinson mCb.onStackTaskRemoved(this, task, i == (taskCount - 1), null, 5788aa9959413a06c3d2ff75e0c7be9e3cb7ac7cd2eWinson TaskViewAnimation.IMMEDIATE); 579062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung } 580062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung } 5819756755db76aeda2065322aa3c26e1a19578d45fWinson Chung task.setGroup(null); 582062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung } 583062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung 584062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung // Add any new tasks 585062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung taskCount = tasks.size(); 586062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung for (int i = 0; i < taskCount; i++) { 587062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung Task task = tasks.get(i); 588062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung if (!currentTasksMap.containsKey(task.key)) { 589062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung if (notifyStackChanges) { 590062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung mCb.onStackTaskAdded(this, task); 591062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung } 592062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung newTasks.add(task); 593062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung } else { 594062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung newTasks.add(currentTasksMap.get(task.key)); 595062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung } 596062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung } 597062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung 598062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung // Sort all the tasks to ensure they are ordered correctly 599509d0d0c9e2ee165d04e898fea59f8941ac7138dWinson Chung Collections.sort(newTasks, FREEFORM_LAST_ACTIVE_TIME_COMPARATOR); 600062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung 601062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung // Filter out the historical tasks from this new list 602250608a5cd08862f4752a924d51710805850db8aWinson ArrayList<Task> stackTasks = new ArrayList<>(); 603250608a5cd08862f4752a924d51710805850db8aWinson ArrayList<Task> historyTasks = new ArrayList<>(); 604062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung int newTaskCount = newTasks.size(); 605062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung for (int i = 0; i < newTaskCount; i++) { 606062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung Task task = newTasks.get(i); 607250608a5cd08862f4752a924d51710805850db8aWinson if (task.isHistorical) { 608250608a5cd08862f4752a924d51710805850db8aWinson historyTasks.add(task); 609250608a5cd08862f4752a924d51710805850db8aWinson } else { 610250608a5cd08862f4752a924d51710805850db8aWinson stackTasks.add(task); 611303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 612303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 613062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung 614250608a5cd08862f4752a924d51710805850db8aWinson mStackTaskList.set(stackTasks); 615250608a5cd08862f4752a924d51710805850db8aWinson mHistoryTaskList.set(historyTasks); 616062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung mRawTaskList.clear(); 617062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung mRawTaskList.addAll(newTasks); 6189756755db76aeda2065322aa3c26e1a19578d45fWinson Chung mGroups.clear(); 6199756755db76aeda2065322aa3c26e1a19578d45fWinson Chung mAffinitiesGroups.clear(); 620303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 621303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 622931c51f54599a227422b2a1c71e922e1458e0291Winson Chung /** 623931c51f54599a227422b2a1c71e922e1458e0291Winson Chung * Gets the front-most task in the stack. 624931c51f54599a227422b2a1c71e922e1458e0291Winson Chung */ 62535a8b04140598a5b5c4865254b942adb6a830991Winson public Task getStackFrontMostTask(boolean includeFreeformTasks) { 626931c51f54599a227422b2a1c71e922e1458e0291Winson Chung ArrayList<Task> stackTasks = mStackTaskList.getTasks(); 627931c51f54599a227422b2a1c71e922e1458e0291Winson Chung if (stackTasks.isEmpty()) { 628931c51f54599a227422b2a1c71e922e1458e0291Winson Chung return null; 629931c51f54599a227422b2a1c71e922e1458e0291Winson Chung } 630931c51f54599a227422b2a1c71e922e1458e0291Winson Chung for (int i = stackTasks.size() - 1; i >= 0; i--) { 631931c51f54599a227422b2a1c71e922e1458e0291Winson Chung Task task = stackTasks.get(i); 63235a8b04140598a5b5c4865254b942adb6a830991Winson if (!task.isFreeformTask() || includeFreeformTasks) { 633931c51f54599a227422b2a1c71e922e1458e0291Winson Chung return task; 634931c51f54599a227422b2a1c71e922e1458e0291Winson Chung } 635931c51f54599a227422b2a1c71e922e1458e0291Winson Chung } 636931c51f54599a227422b2a1c71e922e1458e0291Winson Chung return null; 637ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 638ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung 63904400672962d2e12132f9465928cbf7615c147c4Winson Chung /** Gets the task keys */ 64004400672962d2e12132f9465928cbf7615c147c4Winson Chung public ArrayList<Task.TaskKey> getTaskKeys() { 6418f0e3a68cdd3b2403ff8a1677f90b998f4175f40Winson ArrayList<Task.TaskKey> taskKeys = new ArrayList<>(); 642250608a5cd08862f4752a924d51710805850db8aWinson ArrayList<Task> tasks = computeAllTasksList(); 64304400672962d2e12132f9465928cbf7615c147c4Winson Chung int taskCount = tasks.size(); 64404400672962d2e12132f9465928cbf7615c147c4Winson Chung for (int i = 0; i < taskCount; i++) { 645250608a5cd08862f4752a924d51710805850db8aWinson Task task = tasks.get(i); 646250608a5cd08862f4752a924d51710805850db8aWinson taskKeys.add(task.key); 64704400672962d2e12132f9465928cbf7615c147c4Winson Chung } 64804400672962d2e12132f9465928cbf7615c147c4Winson Chung return taskKeys; 64904400672962d2e12132f9465928cbf7615c147c4Winson Chung } 65004400672962d2e12132f9465928cbf7615c147c4Winson Chung 651250608a5cd08862f4752a924d51710805850db8aWinson /** 652250608a5cd08862f4752a924d51710805850db8aWinson * Returns the set of "active" (non-historical) tasks in the stack that have been used recently. 653250608a5cd08862f4752a924d51710805850db8aWinson */ 654250608a5cd08862f4752a924d51710805850db8aWinson public ArrayList<Task> getStackTasks() { 655250608a5cd08862f4752a924d51710805850db8aWinson return mStackTaskList.getTasks(); 656250608a5cd08862f4752a924d51710805850db8aWinson } 657250608a5cd08862f4752a924d51710805850db8aWinson 658250608a5cd08862f4752a924d51710805850db8aWinson /** 659250608a5cd08862f4752a924d51710805850db8aWinson * Returns the set of tasks that are inactive. These tasks will be presented in a separate 660250608a5cd08862f4752a924d51710805850db8aWinson * history view. 661250608a5cd08862f4752a924d51710805850db8aWinson */ 662250608a5cd08862f4752a924d51710805850db8aWinson public ArrayList<Task> getHistoricalTasks() { 663250608a5cd08862f4752a924d51710805850db8aWinson return mHistoryTaskList.getTasks(); 664303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 665303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 666250608a5cd08862f4752a924d51710805850db8aWinson /** 667f24f21695f5609d06402cf61e3500d408b99bdcbWinson * Returns the set of "freeform" tasks in the stack. 668f24f21695f5609d06402cf61e3500d408b99bdcbWinson */ 669f24f21695f5609d06402cf61e3500d408b99bdcbWinson public ArrayList<Task> getFreeformTasks() { 670f24f21695f5609d06402cf61e3500d408b99bdcbWinson ArrayList<Task> freeformTasks = new ArrayList<>(); 671f24f21695f5609d06402cf61e3500d408b99bdcbWinson ArrayList<Task> tasks = mStackTaskList.getTasks(); 672f24f21695f5609d06402cf61e3500d408b99bdcbWinson int taskCount = tasks.size(); 673f24f21695f5609d06402cf61e3500d408b99bdcbWinson for (int i = 0; i < taskCount; i++) { 674f24f21695f5609d06402cf61e3500d408b99bdcbWinson Task task = tasks.get(i); 675f24f21695f5609d06402cf61e3500d408b99bdcbWinson if (task.isFreeformTask()) { 676f24f21695f5609d06402cf61e3500d408b99bdcbWinson freeformTasks.add(task); 677f24f21695f5609d06402cf61e3500d408b99bdcbWinson } 678f24f21695f5609d06402cf61e3500d408b99bdcbWinson } 679f24f21695f5609d06402cf61e3500d408b99bdcbWinson return freeformTasks; 680f24f21695f5609d06402cf61e3500d408b99bdcbWinson } 681f24f21695f5609d06402cf61e3500d408b99bdcbWinson 682f24f21695f5609d06402cf61e3500d408b99bdcbWinson /** 683250608a5cd08862f4752a924d51710805850db8aWinson * Computes a set of all the active and historical tasks ordered by their last active time. 684250608a5cd08862f4752a924d51710805850db8aWinson */ 685250608a5cd08862f4752a924d51710805850db8aWinson public ArrayList<Task> computeAllTasksList() { 686250608a5cd08862f4752a924d51710805850db8aWinson ArrayList<Task> tasks = new ArrayList<>(); 687250608a5cd08862f4752a924d51710805850db8aWinson tasks.addAll(mStackTaskList.getTasks()); 688250608a5cd08862f4752a924d51710805850db8aWinson tasks.addAll(mHistoryTaskList.getTasks()); 689250608a5cd08862f4752a924d51710805850db8aWinson Collections.sort(tasks, LAST_ACTIVE_TIME_COMPARATOR); 690250608a5cd08862f4752a924d51710805850db8aWinson return tasks; 691303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 692303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 69336a5a2c7003ef8157f276b411c3fda47ad2f75e3Winson /** 6944b057c6787624b75613769a857ccdf51114bb7f2Winson * Returns the number of stack and freeform tasks. 695250608a5cd08862f4752a924d51710805850db8aWinson */ 6964b057c6787624b75613769a857ccdf51114bb7f2Winson public int getTaskCount() { 697250608a5cd08862f4752a924d51710805850db8aWinson return mStackTaskList.size(); 698250608a5cd08862f4752a924d51710805850db8aWinson } 699250608a5cd08862f4752a924d51710805850db8aWinson 700250608a5cd08862f4752a924d51710805850db8aWinson /** 7014b057c6787624b75613769a857ccdf51114bb7f2Winson * Returns the number of stack tasks. 7024b057c6787624b75613769a857ccdf51114bb7f2Winson */ 7034b057c6787624b75613769a857ccdf51114bb7f2Winson public int getStackTaskCount() { 7044b057c6787624b75613769a857ccdf51114bb7f2Winson ArrayList<Task> tasks = mStackTaskList.getTasks(); 7054b057c6787624b75613769a857ccdf51114bb7f2Winson int stackCount = 0; 7064b057c6787624b75613769a857ccdf51114bb7f2Winson int taskCount = tasks.size(); 7074b057c6787624b75613769a857ccdf51114bb7f2Winson for (int i = 0; i < taskCount; i++) { 7084b057c6787624b75613769a857ccdf51114bb7f2Winson Task task = tasks.get(i); 7094b057c6787624b75613769a857ccdf51114bb7f2Winson if (!task.isFreeformTask()) { 7104b057c6787624b75613769a857ccdf51114bb7f2Winson stackCount++; 7114b057c6787624b75613769a857ccdf51114bb7f2Winson } 7124b057c6787624b75613769a857ccdf51114bb7f2Winson } 7134b057c6787624b75613769a857ccdf51114bb7f2Winson return stackCount; 7144b057c6787624b75613769a857ccdf51114bb7f2Winson } 7154b057c6787624b75613769a857ccdf51114bb7f2Winson 7164b057c6787624b75613769a857ccdf51114bb7f2Winson /** 7174b057c6787624b75613769a857ccdf51114bb7f2Winson * Returns the number of freeform tasks. 718f0d1c44a59a10707baa0cca8dd377302260710c1Winson */ 7194b057c6787624b75613769a857ccdf51114bb7f2Winson public int getFreeformTaskCount() { 720f0d1c44a59a10707baa0cca8dd377302260710c1Winson ArrayList<Task> tasks = mStackTaskList.getTasks(); 721f0d1c44a59a10707baa0cca8dd377302260710c1Winson int freeformCount = 0; 722f0d1c44a59a10707baa0cca8dd377302260710c1Winson int taskCount = tasks.size(); 723f0d1c44a59a10707baa0cca8dd377302260710c1Winson for (int i = 0; i < taskCount; i++) { 724f0d1c44a59a10707baa0cca8dd377302260710c1Winson Task task = tasks.get(i); 725f0d1c44a59a10707baa0cca8dd377302260710c1Winson if (task.isFreeformTask()) { 726f0d1c44a59a10707baa0cca8dd377302260710c1Winson freeformCount++; 727f0d1c44a59a10707baa0cca8dd377302260710c1Winson } 728f0d1c44a59a10707baa0cca8dd377302260710c1Winson } 729f0d1c44a59a10707baa0cca8dd377302260710c1Winson return freeformCount; 730f0d1c44a59a10707baa0cca8dd377302260710c1Winson } 731f0d1c44a59a10707baa0cca8dd377302260710c1Winson 732f0d1c44a59a10707baa0cca8dd377302260710c1Winson /** 733250608a5cd08862f4752a924d51710805850db8aWinson * Returns the task in stack tasks which is the launch target. 73436a5a2c7003ef8157f276b411c3fda47ad2f75e3Winson */ 73536a5a2c7003ef8157f276b411c3fda47ad2f75e3Winson public Task getLaunchTarget() { 736250608a5cd08862f4752a924d51710805850db8aWinson ArrayList<Task> tasks = mStackTaskList.getTasks(); 73736a5a2c7003ef8157f276b411c3fda47ad2f75e3Winson int taskCount = tasks.size(); 73836a5a2c7003ef8157f276b411c3fda47ad2f75e3Winson for (int i = 0; i < taskCount; i++) { 73936a5a2c7003ef8157f276b411c3fda47ad2f75e3Winson Task task = tasks.get(i); 74036a5a2c7003ef8157f276b411c3fda47ad2f75e3Winson if (task.isLaunchTarget) { 74136a5a2c7003ef8157f276b411c3fda47ad2f75e3Winson return task; 74236a5a2c7003ef8157f276b411c3fda47ad2f75e3Winson } 74336a5a2c7003ef8157f276b411c3fda47ad2f75e3Winson } 74436a5a2c7003ef8157f276b411c3fda47ad2f75e3Winson return null; 74536a5a2c7003ef8157f276b411c3fda47ad2f75e3Winson } 74636a5a2c7003ef8157f276b411c3fda47ad2f75e3Winson 747303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung /** Returns the index of this task in this current task stack */ 748250608a5cd08862f4752a924d51710805850db8aWinson public int indexOfStackTask(Task t) { 749250608a5cd08862f4752a924d51710805850db8aWinson return mStackTaskList.indexOf(t); 750303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 751303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 752b1f749906f5c27114d02ea0c3f8ce0dcea08fd3fWinson Chung /** Finds the task with the specified task id. */ 753b1f749906f5c27114d02ea0c3f8ce0dcea08fd3fWinson Chung public Task findTaskWithId(int taskId) { 754250608a5cd08862f4752a924d51710805850db8aWinson ArrayList<Task> tasks = computeAllTasksList(); 755250608a5cd08862f4752a924d51710805850db8aWinson for (Task task : tasks) { 756b1f749906f5c27114d02ea0c3f8ce0dcea08fd3fWinson Chung if (task.key.id == taskId) { 757b1f749906f5c27114d02ea0c3f8ce0dcea08fd3fWinson Chung return task; 758b1f749906f5c27114d02ea0c3f8ce0dcea08fd3fWinson Chung } 759b1f749906f5c27114d02ea0c3f8ce0dcea08fd3fWinson Chung } 760b1f749906f5c27114d02ea0c3f8ce0dcea08fd3fWinson Chung return null; 761b1f749906f5c27114d02ea0c3f8ce0dcea08fd3fWinson Chung } 762b1f749906f5c27114d02ea0c3f8ce0dcea08fd3fWinson Chung 763ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung /******** Grouping ********/ 764ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung 765ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung /** Adds a group to the set */ 766ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung public void addGroup(TaskGrouping group) { 767ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung mGroups.add(group); 768ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung mAffinitiesGroups.put(group.affiliation, group); 769ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 770ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung 771ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung public void removeGroup(TaskGrouping group) { 772ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung mGroups.remove(group); 773ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung mAffinitiesGroups.remove(group.affiliation); 774ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 775ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung 776ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung /** Returns the group with the specified affiliation. */ 777083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung public TaskGrouping getGroupWithAffiliation(int affiliation) { 778ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung return mAffinitiesGroups.get(affiliation); 779ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 780ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung 781ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung /** 782ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung * Temporary: This method will simulate affiliation groups by 783ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung */ 78435f3050959e43bf378f9a0adcaef13729206c7e4Winson public void createAffiliatedGroupings(Context context) { 7856e6bd8776f850a21a3733a03dfa32b04f06163d9Winson if (RecentsDebugFlags.Static.EnableMockTaskGroups) { 7865500390a006f2bbea565068234774a36cea076c0Winson ArrayMap<Task.TaskKey, Task> taskMap = new ArrayMap<>(); 787ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung // Sort all tasks by increasing firstActiveTime of the task 788250608a5cd08862f4752a924d51710805850db8aWinson ArrayList<Task> tasks = mStackTaskList.getTasks(); 789ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung Collections.sort(tasks, new Comparator<Task>() { 790ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung @Override 791ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung public int compare(Task task, Task task2) { 79216bc2a7f379edd7796bb5aa4400e1b7c14376a08Winson Chung return Long.compare(task.key.firstActiveTime, task2.key.firstActiveTime); 793ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 794ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung }); 795ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung // Create groups when sequential packages are the same 796ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung NamedCounter counter = new NamedCounter("task-group", ""); 797ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung int taskCount = tasks.size(); 798ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung String prevPackage = ""; 799083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung int prevAffiliation = -1; 800a433fa9c17772f563163ff7db177d091d6aebd5bWinson Chung Random r = new Random(); 8016e6bd8776f850a21a3733a03dfa32b04f06163d9Winson int groupCountDown = RecentsDebugFlags.Static.MockTaskGroupsTaskCount; 802ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung for (int i = 0; i < taskCount; i++) { 803ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung Task t = tasks.get(i); 804e7f138c7f0a190c86cec10fb32fa106aacae4093Winson String packageName = t.key.getComponent().getPackageName(); 805a433fa9c17772f563163ff7db177d091d6aebd5bWinson Chung packageName = "pkg"; 806ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung TaskGrouping group; 807a433fa9c17772f563163ff7db177d091d6aebd5bWinson Chung if (packageName.equals(prevPackage) && groupCountDown > 0) { 808ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung group = getGroupWithAffiliation(prevAffiliation); 809a433fa9c17772f563163ff7db177d091d6aebd5bWinson Chung groupCountDown--; 810ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } else { 811083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung int affiliation = IndividualTaskIdOffset + t.key.id; 812ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung group = new TaskGrouping(affiliation); 813ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung addGroup(group); 814ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung prevAffiliation = affiliation; 815ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung prevPackage = packageName; 8166e6bd8776f850a21a3733a03dfa32b04f06163d9Winson groupCountDown = RecentsDebugFlags.Static.MockTaskGroupsTaskCount; 817ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 818ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung group.addTask(t); 819ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung taskMap.put(t.key, t); 820ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 821ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung // Sort groups by increasing latestActiveTime of the group 822ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung Collections.sort(mGroups, new Comparator<TaskGrouping>() { 823ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung @Override 824ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung public int compare(TaskGrouping taskGrouping, TaskGrouping taskGrouping2) { 825509d0d0c9e2ee165d04e898fea59f8941ac7138dWinson Chung return Long.compare(taskGrouping.latestActiveTimeInGroup, 826ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung taskGrouping2.latestActiveTimeInGroup); 827ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 828ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung }); 8292b9ef6548be89d36ea7629f4a3d8ba7bba1422ceWinson Chung // Sort group tasks by increasing firstActiveTime of the task, and also build a new list 8302b9ef6548be89d36ea7629f4a3d8ba7bba1422ceWinson Chung // of tasks 831ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung int taskIndex = 0; 832ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung int groupCount = mGroups.size(); 833ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung for (int i = 0; i < groupCount; i++) { 834ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung TaskGrouping group = mGroups.get(i); 835083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung Collections.sort(group.mTaskKeys, new Comparator<Task.TaskKey>() { 836ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung @Override 837ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung public int compare(Task.TaskKey taskKey, Task.TaskKey taskKey2) { 838509d0d0c9e2ee165d04e898fea59f8941ac7138dWinson Chung return Long.compare(taskKey.firstActiveTime, taskKey2.firstActiveTime); 839ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 840ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung }); 841083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung ArrayList<Task.TaskKey> groupTasks = group.mTaskKeys; 842ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung int groupTaskCount = groupTasks.size(); 843ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung for (int j = 0; j < groupTaskCount; j++) { 844ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung tasks.set(taskIndex, taskMap.get(groupTasks.get(j))); 845ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung taskIndex++; 846ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 847ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 848250608a5cd08862f4752a924d51710805850db8aWinson mStackTaskList.set(tasks); 849ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } else { 850083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung // Create the task groups 8515500390a006f2bbea565068234774a36cea076c0Winson ArrayMap<Task.TaskKey, Task> tasksMap = new ArrayMap<>(); 852250608a5cd08862f4752a924d51710805850db8aWinson ArrayList<Task> tasks = mStackTaskList.getTasks(); 853ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung int taskCount = tasks.size(); 854ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung for (int i = 0; i < taskCount; i++) { 855ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung Task t = tasks.get(i); 856083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung TaskGrouping group; 85765c851e6e9e08656744b6f66d3da188e3283b17dWinson if (RecentsDebugFlags.Static.EnableAffiliatedTaskGroups) { 85865c851e6e9e08656744b6f66d3da188e3283b17dWinson int affiliation = t.affiliationTaskId > 0 ? t.affiliationTaskId : 85965c851e6e9e08656744b6f66d3da188e3283b17dWinson IndividualTaskIdOffset + t.key.id; 86065c851e6e9e08656744b6f66d3da188e3283b17dWinson if (mAffinitiesGroups.containsKey(affiliation)) { 86165c851e6e9e08656744b6f66d3da188e3283b17dWinson group = getGroupWithAffiliation(affiliation); 86265c851e6e9e08656744b6f66d3da188e3283b17dWinson } else { 86365c851e6e9e08656744b6f66d3da188e3283b17dWinson group = new TaskGrouping(affiliation); 86465c851e6e9e08656744b6f66d3da188e3283b17dWinson addGroup(group); 86565c851e6e9e08656744b6f66d3da188e3283b17dWinson } 866083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung } else { 86765c851e6e9e08656744b6f66d3da188e3283b17dWinson group = new TaskGrouping(t.key.id); 868083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung addGroup(group); 869083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung } 870ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung group.addTask(t); 871ec396d6399c5c31d697d81e94aff459e9771b0c6Winson Chung tasksMap.put(t.key, t); 872ec396d6399c5c31d697d81e94aff459e9771b0c6Winson Chung } 873ec396d6399c5c31d697d81e94aff459e9771b0c6Winson Chung // Update the task colors for each of the groups 87435f3050959e43bf378f9a0adcaef13729206c7e4Winson float minAlpha = context.getResources().getFloat( 87535f3050959e43bf378f9a0adcaef13729206c7e4Winson R.dimen.recents_task_affiliation_color_min_alpha_percentage); 876ec396d6399c5c31d697d81e94aff459e9771b0c6Winson Chung int taskGroupCount = mGroups.size(); 877ec396d6399c5c31d697d81e94aff459e9771b0c6Winson Chung for (int i = 0; i < taskGroupCount; i++) { 878ec396d6399c5c31d697d81e94aff459e9771b0c6Winson Chung TaskGrouping group = mGroups.get(i); 879ec396d6399c5c31d697d81e94aff459e9771b0c6Winson Chung taskCount = group.getTaskCount(); 880ec396d6399c5c31d697d81e94aff459e9771b0c6Winson Chung // Ignore the groups that only have one task 881ec396d6399c5c31d697d81e94aff459e9771b0c6Winson Chung if (taskCount <= 1) continue; 882ec396d6399c5c31d697d81e94aff459e9771b0c6Winson Chung // Calculate the group color distribution 883296278a0679375b8c43962a9e3c9bb4e8ab201e7Winson Chung int affiliationColor = tasksMap.get(group.mTaskKeys.get(0)).affiliationColor; 884ec396d6399c5c31d697d81e94aff459e9771b0c6Winson Chung float alphaStep = (1f - minAlpha) / taskCount; 885ec396d6399c5c31d697d81e94aff459e9771b0c6Winson Chung float alpha = 1f; 886ec396d6399c5c31d697d81e94aff459e9771b0c6Winson Chung for (int j = 0; j < taskCount; j++) { 887ec396d6399c5c31d697d81e94aff459e9771b0c6Winson Chung Task t = tasksMap.get(group.mTaskKeys.get(j)); 888a0e88b5013d708ac6ed6518817d83c64c87ae4b1Winson Chung t.colorPrimary = Utilities.getColorWithOverlay(affiliationColor, Color.WHITE, 889a0e88b5013d708ac6ed6518817d83c64c87ae4b1Winson Chung alpha); 890ec396d6399c5c31d697d81e94aff459e9771b0c6Winson Chung alpha -= alphaStep; 891ec396d6399c5c31d697d81e94aff459e9771b0c6Winson Chung } 892ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 893ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 894ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 895ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung 896e7f138c7f0a190c86cec10fb32fa106aacae4093Winson /** 897e7f138c7f0a190c86cec10fb32fa106aacae4093Winson * Computes the components of tasks in this stack that have been removed as a result of a change 898e7f138c7f0a190c86cec10fb32fa106aacae4093Winson * in the specified package. 899e7f138c7f0a190c86cec10fb32fa106aacae4093Winson */ 9005500390a006f2bbea565068234774a36cea076c0Winson public ArraySet<ComponentName> computeComponentsRemoved(String packageName, int userId) { 901e7f138c7f0a190c86cec10fb32fa106aacae4093Winson // Identify all the tasks that should be removed as a result of the package being removed. 902e7f138c7f0a190c86cec10fb32fa106aacae4093Winson // Using a set to ensure that we callback once per unique component. 903e7f138c7f0a190c86cec10fb32fa106aacae4093Winson SystemServicesProxy ssp = Recents.getSystemServices(); 9045500390a006f2bbea565068234774a36cea076c0Winson ArraySet<ComponentName> existingComponents = new ArraySet<>(); 9055500390a006f2bbea565068234774a36cea076c0Winson ArraySet<ComponentName> removedComponents = new ArraySet<>(); 906e7f138c7f0a190c86cec10fb32fa106aacae4093Winson ArrayList<Task.TaskKey> taskKeys = getTaskKeys(); 907e7f138c7f0a190c86cec10fb32fa106aacae4093Winson for (Task.TaskKey t : taskKeys) { 908e7f138c7f0a190c86cec10fb32fa106aacae4093Winson // Skip if this doesn't apply to the current user 909e7f138c7f0a190c86cec10fb32fa106aacae4093Winson if (t.userId != userId) continue; 910e7f138c7f0a190c86cec10fb32fa106aacae4093Winson 911e7f138c7f0a190c86cec10fb32fa106aacae4093Winson ComponentName cn = t.getComponent(); 912e7f138c7f0a190c86cec10fb32fa106aacae4093Winson if (cn.getPackageName().equals(packageName)) { 913e7f138c7f0a190c86cec10fb32fa106aacae4093Winson if (existingComponents.contains(cn)) { 914e7f138c7f0a190c86cec10fb32fa106aacae4093Winson // If we know that the component still exists in the package, then skip 915e7f138c7f0a190c86cec10fb32fa106aacae4093Winson continue; 916e7f138c7f0a190c86cec10fb32fa106aacae4093Winson } 917e7f138c7f0a190c86cec10fb32fa106aacae4093Winson if (ssp.getActivityInfo(cn, userId) != null) { 918e7f138c7f0a190c86cec10fb32fa106aacae4093Winson existingComponents.add(cn); 919e7f138c7f0a190c86cec10fb32fa106aacae4093Winson } else { 920e7f138c7f0a190c86cec10fb32fa106aacae4093Winson removedComponents.add(cn); 921e7f138c7f0a190c86cec10fb32fa106aacae4093Winson } 922e7f138c7f0a190c86cec10fb32fa106aacae4093Winson } 923e7f138c7f0a190c86cec10fb32fa106aacae4093Winson } 924e7f138c7f0a190c86cec10fb32fa106aacae4093Winson return removedComponents; 925e7f138c7f0a190c86cec10fb32fa106aacae4093Winson } 926e7f138c7f0a190c86cec10fb32fa106aacae4093Winson 927303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung @Override 928303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung public String toString() { 929250608a5cd08862f4752a924d51710805850db8aWinson String str = "Stack Tasks:\n"; 930250608a5cd08862f4752a924d51710805850db8aWinson for (Task t : mStackTaskList.getTasks()) { 931250608a5cd08862f4752a924d51710805850db8aWinson str += " " + t.toString() + "\n"; 932250608a5cd08862f4752a924d51710805850db8aWinson } 933250608a5cd08862f4752a924d51710805850db8aWinson str += "Historical Tasks:\n"; 934250608a5cd08862f4752a924d51710805850db8aWinson for (Task t : mHistoryTaskList.getTasks()) { 935303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung str += " " + t.toString() + "\n"; 936303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 937303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung return str; 938303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 939062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung 940062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung /** 941062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung * Given a list of tasks, returns a map of each task's key to the task. 942062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung */ 9435500390a006f2bbea565068234774a36cea076c0Winson private ArrayMap<Task.TaskKey, Task> createTaskKeyMapFromList(List<Task> tasks) { 9445500390a006f2bbea565068234774a36cea076c0Winson ArrayMap<Task.TaskKey, Task> map = new ArrayMap<>(tasks.size()); 945062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung int taskCount = tasks.size(); 946062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung for (int i = 0; i < taskCount; i++) { 947062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung Task task = tasks.get(i); 948062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung map.put(task.key, task); 949062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung } 950062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung return map; 951062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung } 952062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung} 953