TaskStack.java revision 82c8c5e9872b984ba6f43b01da0c7731fd5bf762
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 19ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chungimport com.android.systemui.recents.Constants; 20ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chungimport com.android.systemui.recents.misc.NamedCounter; 21303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 22303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chungimport java.util.ArrayList; 23ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chungimport java.util.Collections; 24ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chungimport java.util.Comparator; 25ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chungimport java.util.HashMap; 26303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chungimport java.util.List; 27a433fa9c17772f563163ff7db177d091d6aebd5bWinson Chungimport java.util.Random; 28303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 29303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 30303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung/** 31303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung * An interface for a task filter to query whether a particular task should show in a stack. 32303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung */ 33303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chunginterface TaskFilter { 34303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung /** Returns whether the filter accepts the specified task */ 35303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung public boolean acceptTask(Task t, int index); 36303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung} 37303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 38303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung/** 39303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung * A list of filtered tasks. 40303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung */ 41303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chungclass FilteredTaskList { 42303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung ArrayList<Task> mTasks = new ArrayList<Task>(); 43303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung ArrayList<Task> mFilteredTasks = new ArrayList<Task>(); 44ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung HashMap<Task.TaskKey, Integer> mTaskIndices = new HashMap<Task.TaskKey, Integer>(); 45303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung TaskFilter mFilter; 46303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 47303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung /** Sets the task filter, saving the current touch state */ 48c6a1623cc48581380b698ae87b43bfafb9c935baWinson Chung boolean setFilter(TaskFilter filter) { 49c6a1623cc48581380b698ae87b43bfafb9c935baWinson Chung ArrayList<Task> prevFilteredTasks = new ArrayList<Task>(mFilteredTasks); 50303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung mFilter = filter; 51303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung updateFilteredTasks(); 52b44c24fb50845dfbc1f49e78085cf5e01a32067fWinson Chung if (!prevFilteredTasks.equals(mFilteredTasks)) { 53b44c24fb50845dfbc1f49e78085cf5e01a32067fWinson Chung return true; 54b44c24fb50845dfbc1f49e78085cf5e01a32067fWinson Chung } else { 55b44c24fb50845dfbc1f49e78085cf5e01a32067fWinson Chung // If the tasks are exactly the same pre/post filter, then just reset it 56b44c24fb50845dfbc1f49e78085cf5e01a32067fWinson Chung mFilter = null; 57b44c24fb50845dfbc1f49e78085cf5e01a32067fWinson Chung return false; 58b44c24fb50845dfbc1f49e78085cf5e01a32067fWinson Chung } 59303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 60303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 61303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung /** Removes the task filter and returns the previous touch state */ 62303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung void removeFilter() { 63303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung mFilter = null; 64303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung updateFilteredTasks(); 65303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 66303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 67303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung /** Adds a new task to the task list */ 68303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung void add(Task t) { 69303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung mTasks.add(t); 70303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung updateFilteredTasks(); 71303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 72303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 73303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung /** Sets the list of tasks */ 74303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung void set(List<Task> tasks) { 75303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung mTasks.clear(); 76303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung mTasks.addAll(tasks); 77303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung updateFilteredTasks(); 78303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 79303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 80303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung /** Removes a task from the base list only if it is in the filtered list */ 81303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung boolean remove(Task t) { 82303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung if (mFilteredTasks.contains(t)) { 83303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung boolean removed = mTasks.remove(t); 84303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung updateFilteredTasks(); 85303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung return removed; 86303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 87303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung return false; 88303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 89303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 90303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung /** Returns the index of this task in the list of filtered tasks */ 91303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung int indexOf(Task t) { 92ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung return mTaskIndices.get(t.key); 93303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 94303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 95303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung /** Returns the size of the list of filtered tasks */ 96303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung int size() { 97303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung return mFilteredTasks.size(); 98303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 99303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 100303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung /** Returns whether the filtered list contains this task */ 101303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung boolean contains(Task t) { 102ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung return mTaskIndices.containsKey(t.key); 103303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 104303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 105303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung /** Updates the list of filtered tasks whenever the base task list changes */ 106303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung private void updateFilteredTasks() { 107303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung mFilteredTasks.clear(); 108303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung if (mFilter != null) { 109303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung int taskCount = mTasks.size(); 110303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung for (int i = 0; i < taskCount; i++) { 111303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung Task t = mTasks.get(i); 112303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung if (mFilter.acceptTask(t, i)) { 113303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung mFilteredTasks.add(t); 114303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 115303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 116303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } else { 117303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung mFilteredTasks.addAll(mTasks); 118303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 119ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung updateFilteredTaskIndices(); 120ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 121ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung 122ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung /** Updates the mapping of tasks to indices. */ 123ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung private void updateFilteredTaskIndices() { 124ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung mTaskIndices.clear(); 125ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung int taskCount = mFilteredTasks.size(); 126ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung for (int i = 0; i < taskCount; i++) { 127ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung Task t = mFilteredTasks.get(i); 128ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung mTaskIndices.put(t.key, i); 129ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 130303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 131303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 132303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung /** Returns whether this task list is filtered */ 133303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung boolean hasFilter() { 134303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung return (mFilter != null); 135303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 136303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 137303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung /** Returns the list of filtered tasks */ 138303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung ArrayList<Task> getTasks() { 139303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung return mFilteredTasks; 140303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 141303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung} 142303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 143303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung/** 144303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung * The task stack contains a list of multiple tasks. 145303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung */ 146303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chungpublic class TaskStack { 147ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung 148ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung /** Task stack callbacks */ 14904dfe0d26b944324ee920001f40d74cff47281d6Winson Chung public interface TaskStackCallbacks { 15004dfe0d26b944324ee920001f40d74cff47281d6Winson Chung /* Notifies when a task has been added to the stack */ 15104dfe0d26b944324ee920001f40d74cff47281d6Winson Chung public void onStackTaskAdded(TaskStack stack, Task t); 15204dfe0d26b944324ee920001f40d74cff47281d6Winson Chung /* Notifies when a task has been removed from the stack */ 1531f24c7e37bc794057a156a730c7e4b53b01212edWinson Chung public void onStackTaskRemoved(TaskStack stack, Task removedTask, Task newFrontMostTask); 15404dfe0d26b944324ee920001f40d74cff47281d6Winson Chung /** Notifies when the stack was filtered */ 15511ca76a53c60a1898956614315ae929668c523d6Winson Chung public void onStackFiltered(TaskStack newStack, ArrayList<Task> curTasks, Task t); 15604dfe0d26b944324ee920001f40d74cff47281d6Winson Chung /** Notifies when the stack was un-filtered */ 15711ca76a53c60a1898956614315ae929668c523d6Winson Chung public void onStackUnfiltered(TaskStack newStack, ArrayList<Task> curTasks); 15804dfe0d26b944324ee920001f40d74cff47281d6Winson Chung } 15904dfe0d26b944324ee920001f40d74cff47281d6Winson Chung 160ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung /** A pair of indices representing the group and task positions in the stack and group. */ 161ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung public static class GroupTaskIndex { 162ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung public int groupIndex; // Index in the stack 163ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung public int taskIndex; // Index in the group 164ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung 165ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung public GroupTaskIndex() {} 166ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung 167ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung public GroupTaskIndex(int gi, int ti) { 168ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung groupIndex = gi; 169ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung taskIndex = ti; 170ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 171ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 172ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung 173083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung // The task offset to apply to a task id as a group affiliation 174083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung static final int IndividualTaskIdOffset = 1 << 16; 175083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung 176303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung FilteredTaskList mTaskList = new FilteredTaskList(); 177303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung TaskStackCallbacks mCb; 178303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 179ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung ArrayList<TaskGrouping> mGroups = new ArrayList<TaskGrouping>(); 180083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung HashMap<Integer, TaskGrouping> mAffinitiesGroups = new HashMap<Integer, TaskGrouping>(); 181303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 182303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung /** Sets the callbacks for this task stack */ 183303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung public void setCallbacks(TaskStackCallbacks cb) { 184303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung mCb = cb; 185303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 186303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 187303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung /** Adds a new task */ 188303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung public void addTask(Task t) { 189303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung mTaskList.add(t); 190303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung if (mCb != null) { 191303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung mCb.onStackTaskAdded(this, t); 192303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 193303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 194303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 195303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung /** Removes a task */ 196303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung public void removeTask(Task t) { 197303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung if (mTaskList.contains(t)) { 198ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung // Remove the task from the list 199303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung mTaskList.remove(t); 200ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung // Remove it from the group as well, and if it is empty, remove the group 201ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung TaskGrouping group = t.group; 202ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung group.removeTask(t); 203ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung if (group.getTaskCount() == 0) { 204ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung removeGroup(group); 205ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 2061f24c7e37bc794057a156a730c7e4b53b01212edWinson Chung // Update the lock-to-app state 2071f24c7e37bc794057a156a730c7e4b53b01212edWinson Chung t.canLockToTask = false; 20882c8c5e9872b984ba6f43b01da0c7731fd5bf762Winson Chung Task newFrontMostTask = getFrontMostTask(); 2091f24c7e37bc794057a156a730c7e4b53b01212edWinson Chung if (newFrontMostTask != null) { 2101f24c7e37bc794057a156a730c7e4b53b01212edWinson Chung newFrontMostTask.canLockToTask = true; 2111f24c7e37bc794057a156a730c7e4b53b01212edWinson Chung } 212303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung if (mCb != null) { 213ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung // Notify that a task has been removed 2141f24c7e37bc794057a156a730c7e4b53b01212edWinson Chung mCb.onStackTaskRemoved(this, t, newFrontMostTask); 215303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 216303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 217303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 218303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 219303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung /** Sets a few tasks in one go */ 220303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung public void setTasks(List<Task> tasks) { 221ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung ArrayList<Task> taskList = mTaskList.getTasks(); 222ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung int taskCount = taskList.size(); 223303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung for (int i = 0; i < taskCount; i++) { 224ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung Task t = taskList.get(i); 225ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung // Remove the task from the list 226ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung mTaskList.remove(t); 227ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung // Remove it from the group as well, and if it is empty, remove the group 228ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung TaskGrouping group = t.group; 229ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung group.removeTask(t); 230ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung if (group.getTaskCount() == 0) { 231ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung removeGroup(group); 232ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 233303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung if (mCb != null) { 234ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung // Notify that a task has been removed 2351f24c7e37bc794057a156a730c7e4b53b01212edWinson Chung mCb.onStackTaskRemoved(this, t, null); 236303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 237303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 238303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung mTaskList.set(tasks); 239303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung for (Task t : tasks) { 240303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung if (mCb != null) { 241303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung mCb.onStackTaskAdded(this, t); 242303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 243303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 244303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 245303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 246ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung /** Gets the front task */ 247ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung public Task getFrontMostTask() { 2481f24c7e37bc794057a156a730c7e4b53b01212edWinson Chung if (mTaskList.size() == 0) return null; 249ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung return mTaskList.getTasks().get(mTaskList.size() - 1); 250ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 251ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung 252303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung /** Gets the tasks */ 253303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung public ArrayList<Task> getTasks() { 254303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung return mTaskList.getTasks(); 255303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 256303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 257303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung /** Gets the number of tasks */ 258303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung public int getTaskCount() { 259303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung return mTaskList.size(); 260303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 261303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 262303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung /** Returns the index of this task in this current task stack */ 263303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung public int indexOfTask(Task t) { 264303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung return mTaskList.indexOf(t); 265303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 266303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 267ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung /******** Filtering ********/ 268303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 269303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung /** Filters the stack into tasks similar to the one specified */ 270c6a1623cc48581380b698ae87b43bfafb9c935baWinson Chung public void filterTasks(final Task t) { 271c6a1623cc48581380b698ae87b43bfafb9c935baWinson Chung ArrayList<Task> oldStack = new ArrayList<Task>(mTaskList.getTasks()); 272c6a1623cc48581380b698ae87b43bfafb9c935baWinson Chung 273303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung // Set the task list filter 274c6a1623cc48581380b698ae87b43bfafb9c935baWinson Chung boolean filtered = mTaskList.setFilter(new TaskFilter() { 275303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung @Override 276c6a1623cc48581380b698ae87b43bfafb9c935baWinson Chung public boolean acceptTask(Task at, int i) { 277c6a1623cc48581380b698ae87b43bfafb9c935baWinson Chung return t.key.baseIntent.getComponent().getPackageName().equals( 278c6a1623cc48581380b698ae87b43bfafb9c935baWinson Chung at.key.baseIntent.getComponent().getPackageName()); 279303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 280303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung }); 281c6a1623cc48581380b698ae87b43bfafb9c935baWinson Chung if (filtered && mCb != null) { 282c6a1623cc48581380b698ae87b43bfafb9c935baWinson Chung mCb.onStackFiltered(this, oldStack, t); 283303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 284303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 285303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 286303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung /** Unfilters the current stack */ 287303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung public void unfilterTasks() { 288c6a1623cc48581380b698ae87b43bfafb9c935baWinson Chung ArrayList<Task> oldStack = new ArrayList<Task>(mTaskList.getTasks()); 289c6a1623cc48581380b698ae87b43bfafb9c935baWinson Chung 290303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung // Unset the filter, then update the virtual scroll 291303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung mTaskList.removeFilter(); 292303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung if (mCb != null) { 293c6a1623cc48581380b698ae87b43bfafb9c935baWinson Chung mCb.onStackUnfiltered(this, oldStack); 294303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 295303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 296303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 297303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung /** Returns whether tasks are currently filtered */ 298303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung public boolean hasFilteredTasks() { 299303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung return mTaskList.hasFilter(); 300303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 301303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 302ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung /******** Grouping ********/ 303ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung 304ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung /** Adds a group to the set */ 305ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung public void addGroup(TaskGrouping group) { 306ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung mGroups.add(group); 307ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung mAffinitiesGroups.put(group.affiliation, group); 308ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 309ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung 310ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung public void removeGroup(TaskGrouping group) { 311ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung mGroups.remove(group); 312ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung mAffinitiesGroups.remove(group.affiliation); 313ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 314ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung 315ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung /** Returns the group with the specified affiliation. */ 316083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung public TaskGrouping getGroupWithAffiliation(int affiliation) { 317ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung return mAffinitiesGroups.get(affiliation); 318ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 319ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung 320ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung /** 321ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung * Temporary: This method will simulate affiliation groups by 322ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung */ 32393748a11cba1b44edbc2e888c997533461355594Winson Chung public void createAffiliatedGroupings() { 324ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung if (Constants.DebugFlags.App.EnableSimulatedTaskGroups) { 325ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung HashMap<Task.TaskKey, Task> taskMap = new HashMap<Task.TaskKey, Task>(); 326ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung // Sort all tasks by increasing firstActiveTime of the task 327ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung ArrayList<Task> tasks = mTaskList.getTasks(); 328ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung Collections.sort(tasks, new Comparator<Task>() { 329ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung @Override 330ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung public int compare(Task task, Task task2) { 331ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung return (int) (task.key.firstActiveTime - task2.key.firstActiveTime); 332ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 333ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung }); 334ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung // Create groups when sequential packages are the same 335ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung NamedCounter counter = new NamedCounter("task-group", ""); 336ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung int taskCount = tasks.size(); 337ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung String prevPackage = ""; 338083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung int prevAffiliation = -1; 339a433fa9c17772f563163ff7db177d091d6aebd5bWinson Chung Random r = new Random(); 340083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung int groupCountDown = 5; 341ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung for (int i = 0; i < taskCount; i++) { 342ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung Task t = tasks.get(i); 343ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung String packageName = t.key.baseIntent.getComponent().getPackageName(); 344a433fa9c17772f563163ff7db177d091d6aebd5bWinson Chung packageName = "pkg"; 345ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung TaskGrouping group; 346a433fa9c17772f563163ff7db177d091d6aebd5bWinson Chung if (packageName.equals(prevPackage) && groupCountDown > 0) { 347ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung group = getGroupWithAffiliation(prevAffiliation); 348a433fa9c17772f563163ff7db177d091d6aebd5bWinson Chung groupCountDown--; 349ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } else { 350083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung int affiliation = IndividualTaskIdOffset + t.key.id; 351ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung group = new TaskGrouping(affiliation); 352ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung addGroup(group); 353ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung prevAffiliation = affiliation; 354ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung prevPackage = packageName; 355083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung groupCountDown = 5; 356ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 357ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung group.addTask(t); 358ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung taskMap.put(t.key, t); 359ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 360ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung // Sort groups by increasing latestActiveTime of the group 361ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung Collections.sort(mGroups, new Comparator<TaskGrouping>() { 362ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung @Override 363ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung public int compare(TaskGrouping taskGrouping, TaskGrouping taskGrouping2) { 364ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung return (int) (taskGrouping.latestActiveTimeInGroup - 365ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung taskGrouping2.latestActiveTimeInGroup); 366ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 367ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung }); 368ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung // Sort group tasks by increasing firstActiveTime of the task, and also build a new list of 369ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung // tasks 370ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung int taskIndex = 0; 371ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung int groupCount = mGroups.size(); 372ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung for (int i = 0; i < groupCount; i++) { 373ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung TaskGrouping group = mGroups.get(i); 374083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung Collections.sort(group.mTaskKeys, new Comparator<Task.TaskKey>() { 375ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung @Override 376ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung public int compare(Task.TaskKey taskKey, Task.TaskKey taskKey2) { 377ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung return (int) (taskKey.firstActiveTime - taskKey2.firstActiveTime); 378ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 379ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung }); 380083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung ArrayList<Task.TaskKey> groupTasks = group.mTaskKeys; 381ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung int groupTaskCount = groupTasks.size(); 382ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung for (int j = 0; j < groupTaskCount; j++) { 383ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung tasks.set(taskIndex, taskMap.get(groupTasks.get(j))); 384ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung taskIndex++; 385ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 386ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 387ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung mTaskList.set(tasks); 388ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } else { 389083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung // Create the task groups 390ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung ArrayList<Task> tasks = mTaskList.getTasks(); 391ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung int taskCount = tasks.size(); 392ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung for (int i = 0; i < taskCount; i++) { 393ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung Task t = tasks.get(i); 394083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung TaskGrouping group; 395083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung int affiliation = t.taskAffiliation > 0 ? t.taskAffiliation : 396083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung IndividualTaskIdOffset + t.key.id; 397083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung if (mAffinitiesGroups.containsKey(affiliation)) { 398083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung group = getGroupWithAffiliation(affiliation); 399083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung } else { 400083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung group = new TaskGrouping(affiliation); 401083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung addGroup(group); 402083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung } 403ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung group.addTask(t); 404ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 405ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 406ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 407ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung 408303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung @Override 409303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung public String toString() { 410303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung String str = "Tasks:\n"; 411303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung for (Task t : mTaskList.getTasks()) { 412303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung str += " " + t.toString() + "\n"; 413303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 414303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung return str; 415303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 416303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung}