TaskStack.java revision 9756755db76aeda2065322aa3c26e1a19578d45f
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 19882072baacaee4ecd43f0209b691a9af746462f2Winsonimport android.animation.ObjectAnimator; 20e7f138c7f0a190c86cec10fb32fa106aacae4093Winsonimport android.content.ComponentName; 2135f3050959e43bf378f9a0adcaef13729206c7e4Winsonimport android.content.Context; 22ec396d6399c5c31d697d81e94aff459e9771b0c6Winson Chungimport android.graphics.Color; 23be7607af8875236b9cf7bdb5f5aa089c207529afWinsonimport android.graphics.Rect; 24be7607af8875236b9cf7bdb5f5aa089c207529afWinsonimport android.graphics.RectF; 25882072baacaee4ecd43f0209b691a9af746462f2Winsonimport android.graphics.drawable.ColorDrawable; 262b9ef6548be89d36ea7629f4a3d8ba7bba1422ceWinson Chungimport android.util.SparseArray; 272536c7ed446203ea12b38cf05a88e603f8d1b768Winsonimport com.android.systemui.R; 28e7f138c7f0a190c86cec10fb32fa106aacae4093Winsonimport com.android.systemui.recents.Recents; 29c742f973b1e506732911c156c5869fd377afc5bfWinsonimport com.android.systemui.recents.RecentsDebugFlags; 30ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chungimport com.android.systemui.recents.misc.NamedCounter; 31e7f138c7f0a190c86cec10fb32fa106aacae4093Winsonimport com.android.systemui.recents.misc.SystemServicesProxy; 32a0e88b5013d708ac6ed6518817d83c64c87ae4b1Winson Chungimport com.android.systemui.recents.misc.Utilities; 33eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winsonimport com.android.systemui.recents.views.DropTarget; 34303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 35303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chungimport java.util.ArrayList; 36ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chungimport java.util.Collections; 37ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chungimport java.util.Comparator; 38ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chungimport java.util.HashMap; 39e7f138c7f0a190c86cec10fb32fa106aacae4093Winsonimport java.util.HashSet; 40303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chungimport java.util.List; 41a433fa9c17772f563163ff7db177d091d6aebd5bWinson Chungimport java.util.Random; 42303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 43be7607af8875236b9cf7bdb5f5aa089c207529afWinsonimport static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_BOTTOM_OR_RIGHT; 44be7607af8875236b9cf7bdb5f5aa089c207529afWinsonimport static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT; 45eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winsonimport static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID; 46eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winsonimport static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID; 47be7607af8875236b9cf7bdb5f5aa089c207529afWinson 48303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 49303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung/** 50303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung * An interface for a task filter to query whether a particular task should show in a stack. 51303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung */ 52303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chunginterface TaskFilter { 53303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung /** Returns whether the filter accepts the specified task */ 542b9ef6548be89d36ea7629f4a3d8ba7bba1422ceWinson Chung public boolean acceptTask(SparseArray<Task> taskIdMap, Task t, int index); 55303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung} 56303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 57303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung/** 58303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung * A list of filtered tasks. 59303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung */ 60303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chungclass FilteredTaskList { 61eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson 62eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson private static final String TAG = "FilteredTaskList"; 638b1871d74137d7e36ba0fed5608772f51f62015bWinson private static final boolean DEBUG = false; 64eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson 65eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson ArrayList<Task> mTasks = new ArrayList<>(); 66eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson ArrayList<Task> mFilteredTasks = new ArrayList<>(); 67eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson HashMap<Task.TaskKey, Integer> mTaskIndices = new HashMap<>(); 68303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung TaskFilter mFilter; 69303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 70303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung /** Sets the task filter, saving the current touch state */ 71c6a1623cc48581380b698ae87b43bfafb9c935baWinson Chung boolean setFilter(TaskFilter filter) { 72c6a1623cc48581380b698ae87b43bfafb9c935baWinson Chung ArrayList<Task> prevFilteredTasks = new ArrayList<Task>(mFilteredTasks); 73303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung mFilter = filter; 74303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung updateFilteredTasks(); 75b44c24fb50845dfbc1f49e78085cf5e01a32067fWinson Chung if (!prevFilteredTasks.equals(mFilteredTasks)) { 76b44c24fb50845dfbc1f49e78085cf5e01a32067fWinson Chung return true; 77b44c24fb50845dfbc1f49e78085cf5e01a32067fWinson Chung } else { 78b44c24fb50845dfbc1f49e78085cf5e01a32067fWinson Chung return false; 79b44c24fb50845dfbc1f49e78085cf5e01a32067fWinson Chung } 80303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 81303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 828f0e3a68cdd3b2403ff8a1677f90b998f4175f40Winson /** 838f0e3a68cdd3b2403ff8a1677f90b998f4175f40Winson * Resets the task list, but does not remove the filter. 848f0e3a68cdd3b2403ff8a1677f90b998f4175f40Winson */ 85bc571a980704dc767838935e83c6aed231c406e9Winson Chung void reset() { 86bc571a980704dc767838935e83c6aed231c406e9Winson Chung mTasks.clear(); 87bc571a980704dc767838935e83c6aed231c406e9Winson Chung mFilteredTasks.clear(); 88bc571a980704dc767838935e83c6aed231c406e9Winson Chung mTaskIndices.clear(); 89bc571a980704dc767838935e83c6aed231c406e9Winson Chung } 90bc571a980704dc767838935e83c6aed231c406e9Winson Chung 91303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung /** Removes the task filter and returns the previous touch state */ 92303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung void removeFilter() { 93303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung mFilter = null; 94303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung updateFilteredTasks(); 95303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 96303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 97303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung /** Adds a new task to the task list */ 98303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung void add(Task t) { 99303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung mTasks.add(t); 100303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung updateFilteredTasks(); 101303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 102303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 103eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson /** 104eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson * Moves the given task. 105eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson */ 106eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson public void moveTaskToStack(Task task, int insertIndex, int newStackId) { 107eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson int taskIndex = indexOf(task); 108eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson if (taskIndex != insertIndex) { 109eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson mTasks.remove(taskIndex); 110eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson if (taskIndex < insertIndex) { 111eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson insertIndex--; 112eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson } 113eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson mTasks.add(insertIndex, task); 114eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson } 115eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson 116eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson // Update the stack id now, after we've moved the task, and before we update the 117eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson // filtered tasks 118eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson task.setStackId(newStackId); 119eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson updateFilteredTasks(); 120eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson } 121eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson 122303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung /** Sets the list of tasks */ 123303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung void set(List<Task> tasks) { 124303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung mTasks.clear(); 125303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung mTasks.addAll(tasks); 126303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung updateFilteredTasks(); 127303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 128303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 129303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung /** Removes a task from the base list only if it is in the filtered list */ 130303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung boolean remove(Task t) { 131303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung if (mFilteredTasks.contains(t)) { 132303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung boolean removed = mTasks.remove(t); 133303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung updateFilteredTasks(); 134303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung return removed; 135303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 136303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung return false; 137303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 138303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 139303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung /** Returns the index of this task in the list of filtered tasks */ 140303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung int indexOf(Task t) { 14123746d51d922d3df2cdd2635d0c133366c754438Winson if (t != null && mTaskIndices.containsKey(t.key)) { 142a4ccb86ddc8f9f486aee25fb836f4aff97bf7679Winson Chung return mTaskIndices.get(t.key); 143a4ccb86ddc8f9f486aee25fb836f4aff97bf7679Winson Chung } 144a4ccb86ddc8f9f486aee25fb836f4aff97bf7679Winson Chung return -1; 145303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 146303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 147303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung /** Returns the size of the list of filtered tasks */ 148303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung int size() { 149303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung return mFilteredTasks.size(); 150303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 151303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 152303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung /** Returns whether the filtered list contains this task */ 153303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung boolean contains(Task t) { 154ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung return mTaskIndices.containsKey(t.key); 155303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 156303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 157303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung /** Updates the list of filtered tasks whenever the base task list changes */ 158303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung private void updateFilteredTasks() { 159303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung mFilteredTasks.clear(); 160303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung if (mFilter != null) { 1612b9ef6548be89d36ea7629f4a3d8ba7bba1422ceWinson Chung // Create a sparse array from task id to Task 1622b9ef6548be89d36ea7629f4a3d8ba7bba1422ceWinson Chung SparseArray<Task> taskIdMap = new SparseArray<>(); 163303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung int taskCount = mTasks.size(); 164303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung for (int i = 0; i < taskCount; i++) { 165303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung Task t = mTasks.get(i); 1662b9ef6548be89d36ea7629f4a3d8ba7bba1422ceWinson Chung taskIdMap.put(t.key.id, t); 1672b9ef6548be89d36ea7629f4a3d8ba7bba1422ceWinson Chung } 1682b9ef6548be89d36ea7629f4a3d8ba7bba1422ceWinson Chung 1692b9ef6548be89d36ea7629f4a3d8ba7bba1422ceWinson Chung for (int i = 0; i < taskCount; i++) { 1702b9ef6548be89d36ea7629f4a3d8ba7bba1422ceWinson Chung Task t = mTasks.get(i); 1712b9ef6548be89d36ea7629f4a3d8ba7bba1422ceWinson Chung if (mFilter.acceptTask(taskIdMap, t, i)) { 172303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung mFilteredTasks.add(t); 173303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 174303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 175303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } else { 176303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung mFilteredTasks.addAll(mTasks); 177303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 178ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung updateFilteredTaskIndices(); 179ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 180ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung 181ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung /** Updates the mapping of tasks to indices. */ 182ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung private void updateFilteredTaskIndices() { 183ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung mTaskIndices.clear(); 184ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung int taskCount = mFilteredTasks.size(); 185ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung for (int i = 0; i < taskCount; i++) { 186ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung Task t = mFilteredTasks.get(i); 187ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung mTaskIndices.put(t.key, i); 188ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 189303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 190303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 191303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung /** Returns whether this task list is filtered */ 192303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung boolean hasFilter() { 193303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung return (mFilter != null); 194303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 195303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 196303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung /** Returns the list of filtered tasks */ 197303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung ArrayList<Task> getTasks() { 198303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung return mFilteredTasks; 199303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 200303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung} 201303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 202303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung/** 203303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung * The task stack contains a list of multiple tasks. 204303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung */ 205303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chungpublic class TaskStack { 206ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung 207ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung /** Task stack callbacks */ 20804dfe0d26b944324ee920001f40d74cff47281d6Winson Chung public interface TaskStackCallbacks { 209062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung /** 210062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung * Notifies when a new task has been added to the stack. 211062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung */ 212062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung void onStackTaskAdded(TaskStack stack, Task newTask); 213062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung 214062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung /** 215062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung * Notifies when a task has been removed from the stack. 216062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung */ 217aaf33bc2b27fa0c4b59484059434a0fad3187af4Winson void onStackTaskRemoved(TaskStack stack, Task removedTask, boolean wasFrontMostTask, 218aaf33bc2b27fa0c4b59484059434a0fad3187af4Winson Task newFrontMostTask); 219a0731a1a2611d5a89c5960fe39a7ff09cc8fd5eaWinson 220062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung /** 221062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung * Notifies when a task has been removed from the history. 222062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung */ 223a0731a1a2611d5a89c5960fe39a7ff09cc8fd5eaWinson void onHistoryTaskRemoved(TaskStack stack, Task removedTask); 22404dfe0d26b944324ee920001f40d74cff47281d6Winson Chung } 22504dfe0d26b944324ee920001f40d74cff47281d6Winson Chung 226250608a5cd08862f4752a924d51710805850db8aWinson /** 227250608a5cd08862f4752a924d51710805850db8aWinson * The various possible dock states when dragging and dropping a task. 228250608a5cd08862f4752a924d51710805850db8aWinson */ 229f0d1c44a59a10707baa0cca8dd377302260710c1Winson public static class DockState implements DropTarget { 230f0d1c44a59a10707baa0cca8dd377302260710c1Winson 231f0d1c44a59a10707baa0cca8dd377302260710c1Winson private static final int DOCK_AREA_ALPHA = 192; 232f0d1c44a59a10707baa0cca8dd377302260710c1Winson public static final DockState NONE = new DockState(-1, 96, null, null); 233f0d1c44a59a10707baa0cca8dd377302260710c1Winson public static final DockState LEFT = new DockState( 234f0d1c44a59a10707baa0cca8dd377302260710c1Winson DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT, DOCK_AREA_ALPHA, 235f0d1c44a59a10707baa0cca8dd377302260710c1Winson new RectF(0, 0, 0.25f, 1), new RectF(0, 0, 0.25f, 1)); 236f0d1c44a59a10707baa0cca8dd377302260710c1Winson public static final DockState TOP = new DockState( 237f0d1c44a59a10707baa0cca8dd377302260710c1Winson DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT, DOCK_AREA_ALPHA, 238f0d1c44a59a10707baa0cca8dd377302260710c1Winson new RectF(0, 0, 1, 0.25f), new RectF(0, 0, 1, 0.25f)); 239f0d1c44a59a10707baa0cca8dd377302260710c1Winson public static final DockState RIGHT = new DockState( 240f0d1c44a59a10707baa0cca8dd377302260710c1Winson DOCKED_STACK_CREATE_MODE_BOTTOM_OR_RIGHT, DOCK_AREA_ALPHA, 241f0d1c44a59a10707baa0cca8dd377302260710c1Winson new RectF(0.75f, 0, 1, 1), new RectF(0.75f, 0, 1, 1)); 242f0d1c44a59a10707baa0cca8dd377302260710c1Winson public static final DockState BOTTOM = new DockState( 243f0d1c44a59a10707baa0cca8dd377302260710c1Winson DOCKED_STACK_CREATE_MODE_BOTTOM_OR_RIGHT, DOCK_AREA_ALPHA, 244eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson new RectF(0, 0.75f, 1, 1), new RectF(0, 0.75f, 1, 1)); 245eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson 246eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson @Override 247eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson public boolean acceptsDrop(int x, int y, int width, int height) { 248eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson return touchAreaContainsPoint(width, height, x, y); 249eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson } 250be7607af8875236b9cf7bdb5f5aa089c207529afWinson 251882072baacaee4ecd43f0209b691a9af746462f2Winson // Represents the view state of this dock state 252882072baacaee4ecd43f0209b691a9af746462f2Winson public class ViewState { 253882072baacaee4ecd43f0209b691a9af746462f2Winson public final int dockAreaAlpha; 254882072baacaee4ecd43f0209b691a9af746462f2Winson public final ColorDrawable dockAreaOverlay; 255882072baacaee4ecd43f0209b691a9af746462f2Winson private ObjectAnimator dockAreaOverlayAnimator; 256882072baacaee4ecd43f0209b691a9af746462f2Winson 257882072baacaee4ecd43f0209b691a9af746462f2Winson private ViewState(int alpha) { 258882072baacaee4ecd43f0209b691a9af746462f2Winson dockAreaAlpha = alpha; 259882072baacaee4ecd43f0209b691a9af746462f2Winson dockAreaOverlay = new ColorDrawable(0xFFffffff); 260882072baacaee4ecd43f0209b691a9af746462f2Winson dockAreaOverlay.setAlpha(0); 261882072baacaee4ecd43f0209b691a9af746462f2Winson } 262882072baacaee4ecd43f0209b691a9af746462f2Winson 263882072baacaee4ecd43f0209b691a9af746462f2Winson /** 264882072baacaee4ecd43f0209b691a9af746462f2Winson * Creates a new alpha animation. 265882072baacaee4ecd43f0209b691a9af746462f2Winson */ 266882072baacaee4ecd43f0209b691a9af746462f2Winson public void startAlphaAnimation(int alpha, int duration) { 267882072baacaee4ecd43f0209b691a9af746462f2Winson if (dockAreaOverlay.getAlpha() != alpha) { 268882072baacaee4ecd43f0209b691a9af746462f2Winson if (dockAreaOverlayAnimator != null) { 269882072baacaee4ecd43f0209b691a9af746462f2Winson dockAreaOverlayAnimator.cancel(); 270882072baacaee4ecd43f0209b691a9af746462f2Winson } 271882072baacaee4ecd43f0209b691a9af746462f2Winson dockAreaOverlayAnimator = ObjectAnimator.ofInt(dockAreaOverlay, "alpha", alpha); 272882072baacaee4ecd43f0209b691a9af746462f2Winson dockAreaOverlayAnimator.setDuration(duration); 273882072baacaee4ecd43f0209b691a9af746462f2Winson dockAreaOverlayAnimator.start(); 274882072baacaee4ecd43f0209b691a9af746462f2Winson } 275882072baacaee4ecd43f0209b691a9af746462f2Winson } 276882072baacaee4ecd43f0209b691a9af746462f2Winson } 277882072baacaee4ecd43f0209b691a9af746462f2Winson 278be7607af8875236b9cf7bdb5f5aa089c207529afWinson public final int createMode; 279882072baacaee4ecd43f0209b691a9af746462f2Winson public final ViewState viewState; 280be7607af8875236b9cf7bdb5f5aa089c207529afWinson private final RectF dockArea; 281882072baacaee4ecd43f0209b691a9af746462f2Winson private final RectF touchArea; 282be7607af8875236b9cf7bdb5f5aa089c207529afWinson 283be7607af8875236b9cf7bdb5f5aa089c207529afWinson /** 284be7607af8875236b9cf7bdb5f5aa089c207529afWinson * @param createMode used to pass to ActivityManager to dock the task 285be7607af8875236b9cf7bdb5f5aa089c207529afWinson * @param touchArea the area in which touch will initiate this dock state 286eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson * @param dockArea the visible dock area 287be7607af8875236b9cf7bdb5f5aa089c207529afWinson */ 288eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson DockState(int createMode, int dockAreaAlpha, RectF touchArea, RectF dockArea) { 289be7607af8875236b9cf7bdb5f5aa089c207529afWinson this.createMode = createMode; 290882072baacaee4ecd43f0209b691a9af746462f2Winson this.viewState = new ViewState(dockAreaAlpha); 291be7607af8875236b9cf7bdb5f5aa089c207529afWinson this.dockArea = dockArea; 292882072baacaee4ecd43f0209b691a9af746462f2Winson this.touchArea = touchArea; 293be7607af8875236b9cf7bdb5f5aa089c207529afWinson } 294be7607af8875236b9cf7bdb5f5aa089c207529afWinson 295be7607af8875236b9cf7bdb5f5aa089c207529afWinson /** 296be7607af8875236b9cf7bdb5f5aa089c207529afWinson * Returns whether {@param x} and {@param y} are contained in the touch area scaled to the 297be7607af8875236b9cf7bdb5f5aa089c207529afWinson * given {@param width} and {@param height}. 298be7607af8875236b9cf7bdb5f5aa089c207529afWinson */ 299be7607af8875236b9cf7bdb5f5aa089c207529afWinson public boolean touchAreaContainsPoint(int width, int height, float x, float y) { 300be7607af8875236b9cf7bdb5f5aa089c207529afWinson int left = (int) (touchArea.left * width); 301be7607af8875236b9cf7bdb5f5aa089c207529afWinson int top = (int) (touchArea.top * height); 302be7607af8875236b9cf7bdb5f5aa089c207529afWinson int right = (int) (touchArea.right * width); 303be7607af8875236b9cf7bdb5f5aa089c207529afWinson int bottom = (int) (touchArea.bottom * height); 304be7607af8875236b9cf7bdb5f5aa089c207529afWinson return x >= left && y >= top && x <= right && y <= bottom; 305be7607af8875236b9cf7bdb5f5aa089c207529afWinson } 306be7607af8875236b9cf7bdb5f5aa089c207529afWinson 307be7607af8875236b9cf7bdb5f5aa089c207529afWinson /** 308be7607af8875236b9cf7bdb5f5aa089c207529afWinson * Returns the docked task bounds with the given {@param width} and {@param height}. 309be7607af8875236b9cf7bdb5f5aa089c207529afWinson */ 310be7607af8875236b9cf7bdb5f5aa089c207529afWinson public Rect getDockedBounds(int width, int height) { 311be7607af8875236b9cf7bdb5f5aa089c207529afWinson return new Rect((int) (dockArea.left * width), (int) (dockArea.top * height), 312be7607af8875236b9cf7bdb5f5aa089c207529afWinson (int) (dockArea.right * width), (int) (dockArea.bottom * height)); 313be7607af8875236b9cf7bdb5f5aa089c207529afWinson } 314be7607af8875236b9cf7bdb5f5aa089c207529afWinson } 315be7607af8875236b9cf7bdb5f5aa089c207529afWinson 316250608a5cd08862f4752a924d51710805850db8aWinson // A comparator that sorts tasks by their last active time 317250608a5cd08862f4752a924d51710805850db8aWinson private Comparator<Task> LAST_ACTIVE_TIME_COMPARATOR = new Comparator<Task>() { 318250608a5cd08862f4752a924d51710805850db8aWinson @Override 319250608a5cd08862f4752a924d51710805850db8aWinson public int compare(Task o1, Task o2) { 320250608a5cd08862f4752a924d51710805850db8aWinson return Long.compare(o1.key.lastActiveTime, o2.key.lastActiveTime); 321250608a5cd08862f4752a924d51710805850db8aWinson } 322250608a5cd08862f4752a924d51710805850db8aWinson }; 323250608a5cd08862f4752a924d51710805850db8aWinson 324083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung // The task offset to apply to a task id as a group affiliation 325083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung static final int IndividualTaskIdOffset = 1 << 16; 326083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung 327062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung ArrayList<Task> mRawTaskList = new ArrayList<>(); 328250608a5cd08862f4752a924d51710805850db8aWinson FilteredTaskList mStackTaskList = new FilteredTaskList(); 329250608a5cd08862f4752a924d51710805850db8aWinson FilteredTaskList mHistoryTaskList = new FilteredTaskList(); 330303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung TaskStackCallbacks mCb; 331303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 3328f0e3a68cdd3b2403ff8a1677f90b998f4175f40Winson ArrayList<TaskGrouping> mGroups = new ArrayList<>(); 3338f0e3a68cdd3b2403ff8a1677f90b998f4175f40Winson HashMap<Integer, TaskGrouping> mAffinitiesGroups = new HashMap<>(); 3348f0e3a68cdd3b2403ff8a1677f90b998f4175f40Winson 3358f0e3a68cdd3b2403ff8a1677f90b998f4175f40Winson public TaskStack() { 3368f0e3a68cdd3b2403ff8a1677f90b998f4175f40Winson // Ensure that we only show non-docked tasks 337250608a5cd08862f4752a924d51710805850db8aWinson mStackTaskList.setFilter(new TaskFilter() { 3388f0e3a68cdd3b2403ff8a1677f90b998f4175f40Winson @Override 3392b9ef6548be89d36ea7629f4a3d8ba7bba1422ceWinson Chung public boolean acceptTask(SparseArray<Task> taskIdMap, Task t, int index) { 3402b9ef6548be89d36ea7629f4a3d8ba7bba1422ceWinson Chung if (t.isAffiliatedTask()) { 3412b9ef6548be89d36ea7629f4a3d8ba7bba1422ceWinson Chung // If this task is affiliated with another parent in the stack, then the historical state of this 3422b9ef6548be89d36ea7629f4a3d8ba7bba1422ceWinson Chung // task depends on the state of the parent task 3432b9ef6548be89d36ea7629f4a3d8ba7bba1422ceWinson Chung Task parentTask = taskIdMap.get(t.taskAffiliationId); 3442b9ef6548be89d36ea7629f4a3d8ba7bba1422ceWinson Chung if (parentTask != null) { 3452b9ef6548be89d36ea7629f4a3d8ba7bba1422ceWinson Chung t = parentTask; 3462b9ef6548be89d36ea7629f4a3d8ba7bba1422ceWinson Chung } 3472b9ef6548be89d36ea7629f4a3d8ba7bba1422ceWinson Chung } 348250608a5cd08862f4752a924d51710805850db8aWinson return !t.isHistorical && !SystemServicesProxy.isDockedStack(t.key.stackId); 349250608a5cd08862f4752a924d51710805850db8aWinson } 350250608a5cd08862f4752a924d51710805850db8aWinson }); 351250608a5cd08862f4752a924d51710805850db8aWinson mHistoryTaskList.setFilter(new TaskFilter() { 352250608a5cd08862f4752a924d51710805850db8aWinson @Override 3532b9ef6548be89d36ea7629f4a3d8ba7bba1422ceWinson Chung public boolean acceptTask(SparseArray<Task> taskIdMap, Task t, int index) { 3542b9ef6548be89d36ea7629f4a3d8ba7bba1422ceWinson Chung if (t.isAffiliatedTask()) { 3552b9ef6548be89d36ea7629f4a3d8ba7bba1422ceWinson Chung // If this task is affiliated with another parent in the stack, then the historical state of this 3562b9ef6548be89d36ea7629f4a3d8ba7bba1422ceWinson Chung // task depends on the state of the parent task 3572b9ef6548be89d36ea7629f4a3d8ba7bba1422ceWinson Chung Task parentTask = taskIdMap.get(t.taskAffiliationId); 3582b9ef6548be89d36ea7629f4a3d8ba7bba1422ceWinson Chung if (parentTask != null) { 3592b9ef6548be89d36ea7629f4a3d8ba7bba1422ceWinson Chung t = parentTask; 3602b9ef6548be89d36ea7629f4a3d8ba7bba1422ceWinson Chung } 3612b9ef6548be89d36ea7629f4a3d8ba7bba1422ceWinson Chung } 362250608a5cd08862f4752a924d51710805850db8aWinson return t.isHistorical && !SystemServicesProxy.isDockedStack(t.key.stackId); 3638f0e3a68cdd3b2403ff8a1677f90b998f4175f40Winson } 3648f0e3a68cdd3b2403ff8a1677f90b998f4175f40Winson }); 3658f0e3a68cdd3b2403ff8a1677f90b998f4175f40Winson } 366303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 367d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung /** Sets the callbacks for this task stack. */ 368303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung public void setCallbacks(TaskStackCallbacks cb) { 369303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung mCb = cb; 370303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 371303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 372bc571a980704dc767838935e83c6aed231c406e9Winson Chung /** Resets this TaskStack. */ 373bc571a980704dc767838935e83c6aed231c406e9Winson Chung public void reset() { 374bc571a980704dc767838935e83c6aed231c406e9Winson Chung mCb = null; 375250608a5cd08862f4752a924d51710805850db8aWinson mStackTaskList.reset(); 376250608a5cd08862f4752a924d51710805850db8aWinson mHistoryTaskList.reset(); 377bc571a980704dc767838935e83c6aed231c406e9Winson Chung mGroups.clear(); 378bc571a980704dc767838935e83c6aed231c406e9Winson Chung mAffinitiesGroups.clear(); 379bc571a980704dc767838935e83c6aed231c406e9Winson Chung } 380bc571a980704dc767838935e83c6aed231c406e9Winson Chung 381eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson /** 382eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson * Moves the given task to either the front of the freeform workspace or the stack. 383eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson */ 384eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson public void moveTaskToStack(Task task, int newStackId) { 385eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson // Find the index to insert into 386250608a5cd08862f4752a924d51710805850db8aWinson ArrayList<Task> taskList = mStackTaskList.getTasks(); 387eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson int taskCount = taskList.size(); 388eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson if (!task.isFreeformTask() && (newStackId == FREEFORM_WORKSPACE_STACK_ID)) { 389eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson // Insert freeform tasks at the front 390250608a5cd08862f4752a924d51710805850db8aWinson mStackTaskList.moveTaskToStack(task, taskCount, newStackId); 391eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson } else if (task.isFreeformTask() && (newStackId == FULLSCREEN_WORKSPACE_STACK_ID)) { 392eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson // Insert after the first stacked task 393eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson int insertIndex = 0; 394eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson for (int i = taskCount - 1; i >= 0; i--) { 395eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson if (!taskList.get(i).isFreeformTask()) { 396eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson insertIndex = i + 1; 397eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson break; 398eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson } 399eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson } 400250608a5cd08862f4752a924d51710805850db8aWinson mStackTaskList.moveTaskToStack(task, insertIndex, newStackId); 401eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson } 402eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson } 403eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson 4046ac8bd6198f67b64aea2258bdb5f8ed371b5bec1Winson Chung /** Does the actual work associated with removing the task. */ 405250608a5cd08862f4752a924d51710805850db8aWinson void removeTaskImpl(FilteredTaskList taskList, Task t) { 4066ac8bd6198f67b64aea2258bdb5f8ed371b5bec1Winson Chung // Remove the task from the list 407250608a5cd08862f4752a924d51710805850db8aWinson taskList.remove(t); 4086ac8bd6198f67b64aea2258bdb5f8ed371b5bec1Winson Chung // Remove it from the group as well, and if it is empty, remove the group 4096ac8bd6198f67b64aea2258bdb5f8ed371b5bec1Winson Chung TaskGrouping group = t.group; 4104e5fb2f4e1ed4eb119a201541ad89aafac8c53feWinson Chung if (group != null) { 4114e5fb2f4e1ed4eb119a201541ad89aafac8c53feWinson Chung group.removeTask(t); 4124e5fb2f4e1ed4eb119a201541ad89aafac8c53feWinson Chung if (group.getTaskCount() == 0) { 4134e5fb2f4e1ed4eb119a201541ad89aafac8c53feWinson Chung removeGroup(group); 4144e5fb2f4e1ed4eb119a201541ad89aafac8c53feWinson Chung } 4156ac8bd6198f67b64aea2258bdb5f8ed371b5bec1Winson Chung } 4166ac8bd6198f67b64aea2258bdb5f8ed371b5bec1Winson Chung // Update the lock-to-app state 4176ac8bd6198f67b64aea2258bdb5f8ed371b5bec1Winson Chung t.lockToThisTask = false; 4186ac8bd6198f67b64aea2258bdb5f8ed371b5bec1Winson Chung } 4196ac8bd6198f67b64aea2258bdb5f8ed371b5bec1Winson Chung 420303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung /** Removes a task */ 421303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung public void removeTask(Task t) { 422250608a5cd08862f4752a924d51710805850db8aWinson if (mStackTaskList.contains(t)) { 423250608a5cd08862f4752a924d51710805850db8aWinson boolean wasFrontMostTask = (getStackFrontMostTask() == t); 424250608a5cd08862f4752a924d51710805850db8aWinson removeTaskImpl(mStackTaskList, t); 425250608a5cd08862f4752a924d51710805850db8aWinson Task newFrontMostTask = getStackFrontMostTask(); 42656e09b42a0f1670970872bef611a8036904ad6bfJason Monk if (newFrontMostTask != null && newFrontMostTask.lockToTaskEnabled) { 42756e09b42a0f1670970872bef611a8036904ad6bfJason Monk newFrontMostTask.lockToThisTask = true; 4281f24c7e37bc794057a156a730c7e4b53b01212edWinson Chung } 429303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung if (mCb != null) { 430ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung // Notify that a task has been removed 431aaf33bc2b27fa0c4b59484059434a0fad3187af4Winson mCb.onStackTaskRemoved(this, t, wasFrontMostTask, newFrontMostTask); 432303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 433250608a5cd08862f4752a924d51710805850db8aWinson } else if (mHistoryTaskList.contains(t)) { 434250608a5cd08862f4752a924d51710805850db8aWinson removeTaskImpl(mHistoryTaskList, t); 435303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung if (mCb != null) { 436ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung // Notify that a task has been removed 437a0731a1a2611d5a89c5960fe39a7ff09cc8fd5eaWinson mCb.onHistoryTaskRemoved(this, t); 438303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 439303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 440250608a5cd08862f4752a924d51710805850db8aWinson } 441250608a5cd08862f4752a924d51710805850db8aWinson 442250608a5cd08862f4752a924d51710805850db8aWinson /** 443250608a5cd08862f4752a924d51710805850db8aWinson * Sets a few tasks in one go, without calling any callbacks. 444062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung * 445062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung * @param tasks the new set of tasks to replace the current set. 446062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung * @param notifyStackChanges whether or not to callback on specific changes to the list of tasks. 447250608a5cd08862f4752a924d51710805850db8aWinson */ 448062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung public void setTasks(List<Task> tasks, boolean notifyStackChanges) { 449062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung // Compute a has set for each of the tasks 450062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung HashMap<Task.TaskKey, Task> currentTasksMap = createTaskKeyMapFromList(mRawTaskList); 451062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung HashMap<Task.TaskKey, Task> newTasksMap = createTaskKeyMapFromList(tasks); 452062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung 453062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung ArrayList<Task> newTasks = new ArrayList<>(); 454062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung 455062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung // Disable notifications if there are no callbacks 456062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung if (mCb == null) { 457062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung notifyStackChanges = false; 458062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung } 459062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung 460062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung // Remove any tasks that no longer exist 461062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung int taskCount = mRawTaskList.size(); 462062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung for (int i = 0; i < taskCount; i++) { 463062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung Task task = mRawTaskList.get(i); 464062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung if (!newTasksMap.containsKey(task.key)) { 465062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung if (notifyStackChanges) { 466062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung mCb.onStackTaskRemoved(this, task, i == (taskCount - 1), null); 467062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung } 468062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung } 4699756755db76aeda2065322aa3c26e1a19578d45fWinson Chung task.setGroup(null); 470062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung } 471062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung 472062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung // Add any new tasks 473062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung taskCount = tasks.size(); 474062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung for (int i = 0; i < taskCount; i++) { 475062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung Task task = tasks.get(i); 476062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung if (!currentTasksMap.containsKey(task.key)) { 477062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung if (notifyStackChanges) { 478062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung mCb.onStackTaskAdded(this, task); 479062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung } 480062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung newTasks.add(task); 481062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung } else { 482062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung newTasks.add(currentTasksMap.get(task.key)); 483062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung } 484062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung } 485062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung 486062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung // Sort all the tasks to ensure they are ordered correctly 487062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung Collections.sort(newTasks, LAST_ACTIVE_TIME_COMPARATOR); 488062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung 489062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung // TODO: Update screen pinning for the new front-most task post refactoring lockToTask out 490062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung // of the Task 491062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung 492062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung // Filter out the historical tasks from this new list 493250608a5cd08862f4752a924d51710805850db8aWinson ArrayList<Task> stackTasks = new ArrayList<>(); 494250608a5cd08862f4752a924d51710805850db8aWinson ArrayList<Task> historyTasks = new ArrayList<>(); 495062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung int newTaskCount = newTasks.size(); 496062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung for (int i = 0; i < newTaskCount; i++) { 497062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung Task task = newTasks.get(i); 498250608a5cd08862f4752a924d51710805850db8aWinson if (task.isHistorical) { 499250608a5cd08862f4752a924d51710805850db8aWinson historyTasks.add(task); 500250608a5cd08862f4752a924d51710805850db8aWinson } else { 501250608a5cd08862f4752a924d51710805850db8aWinson stackTasks.add(task); 502303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 503303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 504062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung 505250608a5cd08862f4752a924d51710805850db8aWinson mStackTaskList.set(stackTasks); 506250608a5cd08862f4752a924d51710805850db8aWinson mHistoryTaskList.set(historyTasks); 507062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung mRawTaskList.clear(); 508062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung mRawTaskList.addAll(newTasks); 5099756755db76aeda2065322aa3c26e1a19578d45fWinson Chung mGroups.clear(); 5109756755db76aeda2065322aa3c26e1a19578d45fWinson Chung mAffinitiesGroups.clear(); 511303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 512303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 513ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung /** Gets the front task */ 514250608a5cd08862f4752a924d51710805850db8aWinson public Task getStackFrontMostTask() { 515250608a5cd08862f4752a924d51710805850db8aWinson if (mStackTaskList.size() == 0) return null; 516250608a5cd08862f4752a924d51710805850db8aWinson return mStackTaskList.getTasks().get(mStackTaskList.size() - 1); 517ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 518ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung 51904400672962d2e12132f9465928cbf7615c147c4Winson Chung /** Gets the task keys */ 52004400672962d2e12132f9465928cbf7615c147c4Winson Chung public ArrayList<Task.TaskKey> getTaskKeys() { 5218f0e3a68cdd3b2403ff8a1677f90b998f4175f40Winson ArrayList<Task.TaskKey> taskKeys = new ArrayList<>(); 522250608a5cd08862f4752a924d51710805850db8aWinson ArrayList<Task> tasks = computeAllTasksList(); 52304400672962d2e12132f9465928cbf7615c147c4Winson Chung int taskCount = tasks.size(); 52404400672962d2e12132f9465928cbf7615c147c4Winson Chung for (int i = 0; i < taskCount; i++) { 525250608a5cd08862f4752a924d51710805850db8aWinson Task task = tasks.get(i); 526250608a5cd08862f4752a924d51710805850db8aWinson taskKeys.add(task.key); 52704400672962d2e12132f9465928cbf7615c147c4Winson Chung } 52804400672962d2e12132f9465928cbf7615c147c4Winson Chung return taskKeys; 52904400672962d2e12132f9465928cbf7615c147c4Winson Chung } 53004400672962d2e12132f9465928cbf7615c147c4Winson Chung 531250608a5cd08862f4752a924d51710805850db8aWinson /** 532250608a5cd08862f4752a924d51710805850db8aWinson * Returns the set of "active" (non-historical) tasks in the stack that have been used recently. 533250608a5cd08862f4752a924d51710805850db8aWinson */ 534250608a5cd08862f4752a924d51710805850db8aWinson public ArrayList<Task> getStackTasks() { 535250608a5cd08862f4752a924d51710805850db8aWinson return mStackTaskList.getTasks(); 536250608a5cd08862f4752a924d51710805850db8aWinson } 537250608a5cd08862f4752a924d51710805850db8aWinson 538250608a5cd08862f4752a924d51710805850db8aWinson /** 539250608a5cd08862f4752a924d51710805850db8aWinson * Returns the set of tasks that are inactive. These tasks will be presented in a separate 540250608a5cd08862f4752a924d51710805850db8aWinson * history view. 541250608a5cd08862f4752a924d51710805850db8aWinson */ 542250608a5cd08862f4752a924d51710805850db8aWinson public ArrayList<Task> getHistoricalTasks() { 543250608a5cd08862f4752a924d51710805850db8aWinson return mHistoryTaskList.getTasks(); 544303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 545303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 546250608a5cd08862f4752a924d51710805850db8aWinson /** 547250608a5cd08862f4752a924d51710805850db8aWinson * Computes a set of all the active and historical tasks ordered by their last active time. 548250608a5cd08862f4752a924d51710805850db8aWinson */ 549250608a5cd08862f4752a924d51710805850db8aWinson public ArrayList<Task> computeAllTasksList() { 550250608a5cd08862f4752a924d51710805850db8aWinson ArrayList<Task> tasks = new ArrayList<>(); 551250608a5cd08862f4752a924d51710805850db8aWinson tasks.addAll(mStackTaskList.getTasks()); 552250608a5cd08862f4752a924d51710805850db8aWinson tasks.addAll(mHistoryTaskList.getTasks()); 553250608a5cd08862f4752a924d51710805850db8aWinson Collections.sort(tasks, LAST_ACTIVE_TIME_COMPARATOR); 554250608a5cd08862f4752a924d51710805850db8aWinson return tasks; 555303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 556303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 55736a5a2c7003ef8157f276b411c3fda47ad2f75e3Winson /** 558250608a5cd08862f4752a924d51710805850db8aWinson * Returns the number of tasks in the active stack. 559250608a5cd08862f4752a924d51710805850db8aWinson */ 560250608a5cd08862f4752a924d51710805850db8aWinson public int getStackTaskCount() { 561250608a5cd08862f4752a924d51710805850db8aWinson return mStackTaskList.size(); 562250608a5cd08862f4752a924d51710805850db8aWinson } 563250608a5cd08862f4752a924d51710805850db8aWinson 564250608a5cd08862f4752a924d51710805850db8aWinson /** 565f0d1c44a59a10707baa0cca8dd377302260710c1Winson * Returns the number of freeform tasks in the active stack. 566f0d1c44a59a10707baa0cca8dd377302260710c1Winson */ 567f0d1c44a59a10707baa0cca8dd377302260710c1Winson public int getStackTaskFreeformCount() { 568f0d1c44a59a10707baa0cca8dd377302260710c1Winson ArrayList<Task> tasks = mStackTaskList.getTasks(); 569f0d1c44a59a10707baa0cca8dd377302260710c1Winson int freeformCount = 0; 570f0d1c44a59a10707baa0cca8dd377302260710c1Winson int taskCount = tasks.size(); 571f0d1c44a59a10707baa0cca8dd377302260710c1Winson for (int i = 0; i < taskCount; i++) { 572f0d1c44a59a10707baa0cca8dd377302260710c1Winson Task task = tasks.get(i); 573f0d1c44a59a10707baa0cca8dd377302260710c1Winson if (task.isFreeformTask()) { 574f0d1c44a59a10707baa0cca8dd377302260710c1Winson freeformCount++; 575f0d1c44a59a10707baa0cca8dd377302260710c1Winson } 576f0d1c44a59a10707baa0cca8dd377302260710c1Winson } 577f0d1c44a59a10707baa0cca8dd377302260710c1Winson return freeformCount; 578f0d1c44a59a10707baa0cca8dd377302260710c1Winson } 579f0d1c44a59a10707baa0cca8dd377302260710c1Winson 580f0d1c44a59a10707baa0cca8dd377302260710c1Winson /** 581250608a5cd08862f4752a924d51710805850db8aWinson * Returns the task in stack tasks which is the launch target. 58236a5a2c7003ef8157f276b411c3fda47ad2f75e3Winson */ 58336a5a2c7003ef8157f276b411c3fda47ad2f75e3Winson public Task getLaunchTarget() { 584250608a5cd08862f4752a924d51710805850db8aWinson ArrayList<Task> tasks = mStackTaskList.getTasks(); 58536a5a2c7003ef8157f276b411c3fda47ad2f75e3Winson int taskCount = tasks.size(); 58636a5a2c7003ef8157f276b411c3fda47ad2f75e3Winson for (int i = 0; i < taskCount; i++) { 58736a5a2c7003ef8157f276b411c3fda47ad2f75e3Winson Task task = tasks.get(i); 58836a5a2c7003ef8157f276b411c3fda47ad2f75e3Winson if (task.isLaunchTarget) { 58936a5a2c7003ef8157f276b411c3fda47ad2f75e3Winson return task; 59036a5a2c7003ef8157f276b411c3fda47ad2f75e3Winson } 59136a5a2c7003ef8157f276b411c3fda47ad2f75e3Winson } 59236a5a2c7003ef8157f276b411c3fda47ad2f75e3Winson return null; 59336a5a2c7003ef8157f276b411c3fda47ad2f75e3Winson } 59436a5a2c7003ef8157f276b411c3fda47ad2f75e3Winson 595303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung /** Returns the index of this task in this current task stack */ 596250608a5cd08862f4752a924d51710805850db8aWinson public int indexOfStackTask(Task t) { 597250608a5cd08862f4752a924d51710805850db8aWinson return mStackTaskList.indexOf(t); 598303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 599303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 600b1f749906f5c27114d02ea0c3f8ce0dcea08fd3fWinson Chung /** Finds the task with the specified task id. */ 601b1f749906f5c27114d02ea0c3f8ce0dcea08fd3fWinson Chung public Task findTaskWithId(int taskId) { 602250608a5cd08862f4752a924d51710805850db8aWinson ArrayList<Task> tasks = computeAllTasksList(); 603250608a5cd08862f4752a924d51710805850db8aWinson for (Task task : tasks) { 604b1f749906f5c27114d02ea0c3f8ce0dcea08fd3fWinson Chung if (task.key.id == taskId) { 605b1f749906f5c27114d02ea0c3f8ce0dcea08fd3fWinson Chung return task; 606b1f749906f5c27114d02ea0c3f8ce0dcea08fd3fWinson Chung } 607b1f749906f5c27114d02ea0c3f8ce0dcea08fd3fWinson Chung } 608b1f749906f5c27114d02ea0c3f8ce0dcea08fd3fWinson Chung return null; 609b1f749906f5c27114d02ea0c3f8ce0dcea08fd3fWinson Chung } 610b1f749906f5c27114d02ea0c3f8ce0dcea08fd3fWinson Chung 611ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung /******** Grouping ********/ 612ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung 613ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung /** Adds a group to the set */ 614ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung public void addGroup(TaskGrouping group) { 615ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung mGroups.add(group); 616ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung mAffinitiesGroups.put(group.affiliation, group); 617ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 618ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung 619ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung public void removeGroup(TaskGrouping group) { 620ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung mGroups.remove(group); 621ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung mAffinitiesGroups.remove(group.affiliation); 622ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 623ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung 624ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung /** Returns the group with the specified affiliation. */ 625083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung public TaskGrouping getGroupWithAffiliation(int affiliation) { 626ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung return mAffinitiesGroups.get(affiliation); 627ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 628ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung 629ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung /** 630ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung * Temporary: This method will simulate affiliation groups by 631ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung */ 63235f3050959e43bf378f9a0adcaef13729206c7e4Winson public void createAffiliatedGroupings(Context context) { 633c742f973b1e506732911c156c5869fd377afc5bfWinson if (RecentsDebugFlags.Static.EnableSimulatedTaskGroups) { 634ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung HashMap<Task.TaskKey, Task> taskMap = new HashMap<Task.TaskKey, Task>(); 635ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung // Sort all tasks by increasing firstActiveTime of the task 636250608a5cd08862f4752a924d51710805850db8aWinson ArrayList<Task> tasks = mStackTaskList.getTasks(); 637ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung Collections.sort(tasks, new Comparator<Task>() { 638ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung @Override 639ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung public int compare(Task task, Task task2) { 64016bc2a7f379edd7796bb5aa4400e1b7c14376a08Winson Chung return Long.compare(task.key.firstActiveTime, task2.key.firstActiveTime); 641ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 642ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung }); 643ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung // Create groups when sequential packages are the same 644ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung NamedCounter counter = new NamedCounter("task-group", ""); 645ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung int taskCount = tasks.size(); 646ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung String prevPackage = ""; 647083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung int prevAffiliation = -1; 648a433fa9c17772f563163ff7db177d091d6aebd5bWinson Chung Random r = new Random(); 649c742f973b1e506732911c156c5869fd377afc5bfWinson int groupCountDown = RecentsDebugFlags.Static.TaskAffiliationsGroupCount; 650ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung for (int i = 0; i < taskCount; i++) { 651ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung Task t = tasks.get(i); 652e7f138c7f0a190c86cec10fb32fa106aacae4093Winson String packageName = t.key.getComponent().getPackageName(); 653a433fa9c17772f563163ff7db177d091d6aebd5bWinson Chung packageName = "pkg"; 654ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung TaskGrouping group; 655a433fa9c17772f563163ff7db177d091d6aebd5bWinson Chung if (packageName.equals(prevPackage) && groupCountDown > 0) { 656ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung group = getGroupWithAffiliation(prevAffiliation); 657a433fa9c17772f563163ff7db177d091d6aebd5bWinson Chung groupCountDown--; 658ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } else { 659083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung int affiliation = IndividualTaskIdOffset + t.key.id; 660ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung group = new TaskGrouping(affiliation); 661ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung addGroup(group); 662ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung prevAffiliation = affiliation; 663ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung prevPackage = packageName; 664c742f973b1e506732911c156c5869fd377afc5bfWinson groupCountDown = RecentsDebugFlags.Static.TaskAffiliationsGroupCount; 665ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 666ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung group.addTask(t); 667ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung taskMap.put(t.key, t); 668ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 669ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung // Sort groups by increasing latestActiveTime of the group 670ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung Collections.sort(mGroups, new Comparator<TaskGrouping>() { 671ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung @Override 672ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung public int compare(TaskGrouping taskGrouping, TaskGrouping taskGrouping2) { 673ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung return (int) (taskGrouping.latestActiveTimeInGroup - 674ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung taskGrouping2.latestActiveTimeInGroup); 675ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 676ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung }); 6772b9ef6548be89d36ea7629f4a3d8ba7bba1422ceWinson Chung // Sort group tasks by increasing firstActiveTime of the task, and also build a new list 6782b9ef6548be89d36ea7629f4a3d8ba7bba1422ceWinson Chung // of tasks 679ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung int taskIndex = 0; 680ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung int groupCount = mGroups.size(); 681ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung for (int i = 0; i < groupCount; i++) { 682ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung TaskGrouping group = mGroups.get(i); 683083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung Collections.sort(group.mTaskKeys, new Comparator<Task.TaskKey>() { 684ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung @Override 685ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung public int compare(Task.TaskKey taskKey, Task.TaskKey taskKey2) { 686ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung return (int) (taskKey.firstActiveTime - taskKey2.firstActiveTime); 687ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 688ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung }); 689083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung ArrayList<Task.TaskKey> groupTasks = group.mTaskKeys; 690ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung int groupTaskCount = groupTasks.size(); 691ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung for (int j = 0; j < groupTaskCount; j++) { 692ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung tasks.set(taskIndex, taskMap.get(groupTasks.get(j))); 693ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung taskIndex++; 694ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 695ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 696250608a5cd08862f4752a924d51710805850db8aWinson mStackTaskList.set(tasks); 697ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } else { 698083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung // Create the task groups 6992b9ef6548be89d36ea7629f4a3d8ba7bba1422ceWinson Chung HashMap<Task.TaskKey, Task> tasksMap = new HashMap<>(); 700250608a5cd08862f4752a924d51710805850db8aWinson ArrayList<Task> tasks = mStackTaskList.getTasks(); 701ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung int taskCount = tasks.size(); 702ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung for (int i = 0; i < taskCount; i++) { 703ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung Task t = tasks.get(i); 704083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung TaskGrouping group; 7052b9ef6548be89d36ea7629f4a3d8ba7bba1422ceWinson Chung int affiliation = t.taskAffiliationId > 0 ? t.taskAffiliationId : 706083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung IndividualTaskIdOffset + t.key.id; 707083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung if (mAffinitiesGroups.containsKey(affiliation)) { 708083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung group = getGroupWithAffiliation(affiliation); 709083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung } else { 710083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung group = new TaskGrouping(affiliation); 711083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung addGroup(group); 712083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung } 713ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung group.addTask(t); 714ec396d6399c5c31d697d81e94aff459e9771b0c6Winson Chung tasksMap.put(t.key, t); 715ec396d6399c5c31d697d81e94aff459e9771b0c6Winson Chung } 716ec396d6399c5c31d697d81e94aff459e9771b0c6Winson Chung // Update the task colors for each of the groups 71735f3050959e43bf378f9a0adcaef13729206c7e4Winson float minAlpha = context.getResources().getFloat( 71835f3050959e43bf378f9a0adcaef13729206c7e4Winson R.dimen.recents_task_affiliation_color_min_alpha_percentage); 719ec396d6399c5c31d697d81e94aff459e9771b0c6Winson Chung int taskGroupCount = mGroups.size(); 720ec396d6399c5c31d697d81e94aff459e9771b0c6Winson Chung for (int i = 0; i < taskGroupCount; i++) { 721ec396d6399c5c31d697d81e94aff459e9771b0c6Winson Chung TaskGrouping group = mGroups.get(i); 722ec396d6399c5c31d697d81e94aff459e9771b0c6Winson Chung taskCount = group.getTaskCount(); 723ec396d6399c5c31d697d81e94aff459e9771b0c6Winson Chung // Ignore the groups that only have one task 724ec396d6399c5c31d697d81e94aff459e9771b0c6Winson Chung if (taskCount <= 1) continue; 725ec396d6399c5c31d697d81e94aff459e9771b0c6Winson Chung // Calculate the group color distribution 726ec396d6399c5c31d697d81e94aff459e9771b0c6Winson Chung int affiliationColor = tasksMap.get(group.mTaskKeys.get(0)).taskAffiliationColor; 727ec396d6399c5c31d697d81e94aff459e9771b0c6Winson Chung float alphaStep = (1f - minAlpha) / taskCount; 728ec396d6399c5c31d697d81e94aff459e9771b0c6Winson Chung float alpha = 1f; 729ec396d6399c5c31d697d81e94aff459e9771b0c6Winson Chung for (int j = 0; j < taskCount; j++) { 730ec396d6399c5c31d697d81e94aff459e9771b0c6Winson Chung Task t = tasksMap.get(group.mTaskKeys.get(j)); 731a0e88b5013d708ac6ed6518817d83c64c87ae4b1Winson Chung t.colorPrimary = Utilities.getColorWithOverlay(affiliationColor, Color.WHITE, 732a0e88b5013d708ac6ed6518817d83c64c87ae4b1Winson Chung alpha); 733ec396d6399c5c31d697d81e94aff459e9771b0c6Winson Chung alpha -= alphaStep; 734ec396d6399c5c31d697d81e94aff459e9771b0c6Winson Chung } 735ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 736ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 737ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 738ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung 739e7f138c7f0a190c86cec10fb32fa106aacae4093Winson /** 740e7f138c7f0a190c86cec10fb32fa106aacae4093Winson * Computes the components of tasks in this stack that have been removed as a result of a change 741e7f138c7f0a190c86cec10fb32fa106aacae4093Winson * in the specified package. 742e7f138c7f0a190c86cec10fb32fa106aacae4093Winson */ 743e7f138c7f0a190c86cec10fb32fa106aacae4093Winson public HashSet<ComponentName> computeComponentsRemoved(String packageName, int userId) { 744e7f138c7f0a190c86cec10fb32fa106aacae4093Winson // Identify all the tasks that should be removed as a result of the package being removed. 745e7f138c7f0a190c86cec10fb32fa106aacae4093Winson // Using a set to ensure that we callback once per unique component. 746e7f138c7f0a190c86cec10fb32fa106aacae4093Winson SystemServicesProxy ssp = Recents.getSystemServices(); 747e7f138c7f0a190c86cec10fb32fa106aacae4093Winson HashSet<ComponentName> existingComponents = new HashSet<>(); 748e7f138c7f0a190c86cec10fb32fa106aacae4093Winson HashSet<ComponentName> removedComponents = new HashSet<>(); 749e7f138c7f0a190c86cec10fb32fa106aacae4093Winson ArrayList<Task.TaskKey> taskKeys = getTaskKeys(); 750e7f138c7f0a190c86cec10fb32fa106aacae4093Winson for (Task.TaskKey t : taskKeys) { 751e7f138c7f0a190c86cec10fb32fa106aacae4093Winson // Skip if this doesn't apply to the current user 752e7f138c7f0a190c86cec10fb32fa106aacae4093Winson if (t.userId != userId) continue; 753e7f138c7f0a190c86cec10fb32fa106aacae4093Winson 754e7f138c7f0a190c86cec10fb32fa106aacae4093Winson ComponentName cn = t.getComponent(); 755e7f138c7f0a190c86cec10fb32fa106aacae4093Winson if (cn.getPackageName().equals(packageName)) { 756e7f138c7f0a190c86cec10fb32fa106aacae4093Winson if (existingComponents.contains(cn)) { 757e7f138c7f0a190c86cec10fb32fa106aacae4093Winson // If we know that the component still exists in the package, then skip 758e7f138c7f0a190c86cec10fb32fa106aacae4093Winson continue; 759e7f138c7f0a190c86cec10fb32fa106aacae4093Winson } 760e7f138c7f0a190c86cec10fb32fa106aacae4093Winson if (ssp.getActivityInfo(cn, userId) != null) { 761e7f138c7f0a190c86cec10fb32fa106aacae4093Winson existingComponents.add(cn); 762e7f138c7f0a190c86cec10fb32fa106aacae4093Winson } else { 763e7f138c7f0a190c86cec10fb32fa106aacae4093Winson removedComponents.add(cn); 764e7f138c7f0a190c86cec10fb32fa106aacae4093Winson } 765e7f138c7f0a190c86cec10fb32fa106aacae4093Winson } 766e7f138c7f0a190c86cec10fb32fa106aacae4093Winson } 767e7f138c7f0a190c86cec10fb32fa106aacae4093Winson return removedComponents; 768e7f138c7f0a190c86cec10fb32fa106aacae4093Winson } 769e7f138c7f0a190c86cec10fb32fa106aacae4093Winson 770303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung @Override 771303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung public String toString() { 772250608a5cd08862f4752a924d51710805850db8aWinson String str = "Stack Tasks:\n"; 773250608a5cd08862f4752a924d51710805850db8aWinson for (Task t : mStackTaskList.getTasks()) { 774250608a5cd08862f4752a924d51710805850db8aWinson str += " " + t.toString() + "\n"; 775250608a5cd08862f4752a924d51710805850db8aWinson } 776250608a5cd08862f4752a924d51710805850db8aWinson str += "Historical Tasks:\n"; 777250608a5cd08862f4752a924d51710805850db8aWinson for (Task t : mHistoryTaskList.getTasks()) { 778303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung str += " " + t.toString() + "\n"; 779303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 780303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung return str; 781303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 782062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung 783062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung /** 784062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung * Given a list of tasks, returns a map of each task's key to the task. 785062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung */ 786062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung private HashMap<Task.TaskKey, Task> createTaskKeyMapFromList(List<Task> tasks) { 787062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung HashMap<Task.TaskKey, Task> map = new HashMap<>(); 788062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung int taskCount = tasks.size(); 789062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung for (int i = 0; i < taskCount; i++) { 790062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung Task task = tasks.get(i); 791062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung map.put(task.key, task); 792062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung } 793062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung return map; 794062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung } 795062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung} 796