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 1959924fe0d9136cf349759bea1e06b661603f95feWinsonimport static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_BOTTOM_OR_RIGHT; 2059924fe0d9136cf349759bea1e06b661603f95feWinsonimport static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT; 2159924fe0d9136cf349759bea1e06b661603f95feWinsonimport static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID; 2259924fe0d9136cf349759bea1e06b661603f95feWinsonimport static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID; 2359924fe0d9136cf349759bea1e06b661603f95feWinsonimport static android.view.WindowManager.DOCKED_BOTTOM; 2459924fe0d9136cf349759bea1e06b661603f95feWinsonimport static android.view.WindowManager.DOCKED_INVALID; 2559924fe0d9136cf349759bea1e06b661603f95feWinsonimport static android.view.WindowManager.DOCKED_LEFT; 2659924fe0d9136cf349759bea1e06b661603f95feWinsonimport static android.view.WindowManager.DOCKED_RIGHT; 2759924fe0d9136cf349759bea1e06b661603f95feWinsonimport static android.view.WindowManager.DOCKED_TOP; 2859924fe0d9136cf349759bea1e06b661603f95feWinson 293e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winsonimport android.animation.Animator; 303e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winsonimport android.animation.AnimatorSet; 31882072baacaee4ecd43f0209b691a9af746462f2Winsonimport android.animation.ObjectAnimator; 323e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winsonimport android.animation.PropertyValuesHolder; 3399ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winsonimport android.annotation.IntDef; 34e7f138c7f0a190c86cec10fb32fa106aacae4093Winsonimport android.content.ComponentName; 3535f3050959e43bf378f9a0adcaef13729206c7e4Winsonimport android.content.Context; 363e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winsonimport android.content.res.Configuration; 373e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winsonimport android.content.res.Resources; 3899ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winsonimport android.graphics.Canvas; 39ec396d6399c5c31d697d81e94aff459e9771b0c6Winson Chungimport android.graphics.Color; 4099ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winsonimport android.graphics.Paint; 4199ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winsonimport android.graphics.Point; 42be7607af8875236b9cf7bdb5f5aa089c207529afWinsonimport android.graphics.Rect; 43be7607af8875236b9cf7bdb5f5aa089c207529afWinsonimport android.graphics.RectF; 44882072baacaee4ecd43f0209b691a9af746462f2Winsonimport android.graphics.drawable.ColorDrawable; 455500390a006f2bbea565068234774a36cea076c0Winsonimport android.util.ArrayMap; 465500390a006f2bbea565068234774a36cea076c0Winsonimport android.util.ArraySet; 4799ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winsonimport android.util.IntProperty; 482b9ef6548be89d36ea7629f4a3d8ba7bba1422ceWinson Chungimport android.util.SparseArray; 493e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winsonimport android.view.animation.Interpolator; 50c0d7058b14c24cd07912f5629c26b39b7b4673d5Winson 513e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winsonimport com.android.internal.policy.DockedDividerUtils; 523f32e7eba7aec02edbf542cc11eee13264a5abf2Winsonimport com.android.systemui.Interpolators; 532536c7ed446203ea12b38cf05a88e603f8d1b768Winsonimport com.android.systemui.R; 54e7f138c7f0a190c86cec10fb32fa106aacae4093Winsonimport com.android.systemui.recents.Recents; 55c742f973b1e506732911c156c5869fd377afc5bfWinsonimport com.android.systemui.recents.RecentsDebugFlags; 56ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chungimport com.android.systemui.recents.misc.NamedCounter; 57e7f138c7f0a190c86cec10fb32fa106aacae4093Winsonimport com.android.systemui.recents.misc.SystemServicesProxy; 58a0e88b5013d708ac6ed6518817d83c64c87ae4b1Winson Chungimport com.android.systemui.recents.misc.Utilities; 59be8e696a1f40a61c52a74022f4f084fdc0600f90Winsonimport com.android.systemui.recents.views.AnimationProps; 6059924fe0d9136cf349759bea1e06b661603f95feWinsonimport com.android.systemui.recents.views.DropTarget; 6159924fe0d9136cf349759bea1e06b661603f95feWinsonimport com.android.systemui.recents.views.TaskStackLayoutAlgorithm; 62303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 63d72c315d5eed3a684eee303364b97129cb821689Winsonimport java.io.PrintWriter; 6499ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winsonimport java.lang.annotation.Retention; 6599ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winsonimport java.lang.annotation.RetentionPolicy; 66303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chungimport java.util.ArrayList; 67ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chungimport java.util.Collections; 68ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chungimport java.util.Comparator; 69303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chungimport java.util.List; 70a433fa9c17772f563163ff7db177d091d6aebd5bWinson Chungimport java.util.Random; 71303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 72303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 73303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung/** 74303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung * An interface for a task filter to query whether a particular task should show in a stack. 75303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung */ 76303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chunginterface TaskFilter { 77303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung /** Returns whether the filter accepts the specified task */ 782b9ef6548be89d36ea7629f4a3d8ba7bba1422ceWinson Chung public boolean acceptTask(SparseArray<Task> taskIdMap, Task t, int index); 79303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung} 80303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 81303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung/** 82303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung * A list of filtered tasks. 83303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung */ 84303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chungclass FilteredTaskList { 85eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson 86eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson ArrayList<Task> mTasks = new ArrayList<>(); 87eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson ArrayList<Task> mFilteredTasks = new ArrayList<>(); 885500390a006f2bbea565068234774a36cea076c0Winson ArrayMap<Task.TaskKey, Integer> mTaskIndices = new ArrayMap<>(); 89303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung TaskFilter mFilter; 90303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 91303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung /** Sets the task filter, saving the current touch state */ 92c6a1623cc48581380b698ae87b43bfafb9c935baWinson Chung boolean setFilter(TaskFilter filter) { 935500390a006f2bbea565068234774a36cea076c0Winson ArrayList<Task> prevFilteredTasks = new ArrayList<>(mFilteredTasks); 94303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung mFilter = filter; 95303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung updateFilteredTasks(); 96b44c24fb50845dfbc1f49e78085cf5e01a32067fWinson Chung if (!prevFilteredTasks.equals(mFilteredTasks)) { 97b44c24fb50845dfbc1f49e78085cf5e01a32067fWinson Chung return true; 98b44c24fb50845dfbc1f49e78085cf5e01a32067fWinson Chung } else { 99b44c24fb50845dfbc1f49e78085cf5e01a32067fWinson Chung return false; 100b44c24fb50845dfbc1f49e78085cf5e01a32067fWinson Chung } 101303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 102303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 103303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung /** Removes the task filter and returns the previous touch state */ 104303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung void removeFilter() { 105303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung mFilter = null; 106303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung updateFilteredTasks(); 107303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 108303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 109303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung /** Adds a new task to the task list */ 110303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung void add(Task t) { 111303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung mTasks.add(t); 112303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung updateFilteredTasks(); 113303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 114303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 115eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson /** 116eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson * Moves the given task. 117eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson */ 118eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson public void moveTaskToStack(Task task, int insertIndex, int newStackId) { 119eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson int taskIndex = indexOf(task); 120eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson if (taskIndex != insertIndex) { 121eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson mTasks.remove(taskIndex); 122eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson if (taskIndex < insertIndex) { 123eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson insertIndex--; 124eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson } 125eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson mTasks.add(insertIndex, task); 126eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson } 127eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson 128eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson // Update the stack id now, after we've moved the task, and before we update the 129eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson // filtered tasks 130eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson task.setStackId(newStackId); 131eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson updateFilteredTasks(); 132eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson } 133eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson 134303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung /** Sets the list of tasks */ 135303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung void set(List<Task> tasks) { 136303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung mTasks.clear(); 137303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung mTasks.addAll(tasks); 138303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung updateFilteredTasks(); 139303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 140303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 141303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung /** Removes a task from the base list only if it is in the filtered list */ 142303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung boolean remove(Task t) { 143303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung if (mFilteredTasks.contains(t)) { 144303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung boolean removed = mTasks.remove(t); 145303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung updateFilteredTasks(); 146303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung return removed; 147303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 148303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung return false; 149303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 150303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 151303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung /** Returns the index of this task in the list of filtered tasks */ 152303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung int indexOf(Task t) { 15323746d51d922d3df2cdd2635d0c133366c754438Winson if (t != null && mTaskIndices.containsKey(t.key)) { 154a4ccb86ddc8f9f486aee25fb836f4aff97bf7679Winson Chung return mTaskIndices.get(t.key); 155a4ccb86ddc8f9f486aee25fb836f4aff97bf7679Winson Chung } 156a4ccb86ddc8f9f486aee25fb836f4aff97bf7679Winson Chung return -1; 157303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 158303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 159303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung /** Returns the size of the list of filtered tasks */ 160303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung int size() { 161303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung return mFilteredTasks.size(); 162303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 163303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 164303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung /** Returns whether the filtered list contains this task */ 165303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung boolean contains(Task t) { 166ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung return mTaskIndices.containsKey(t.key); 167303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 168303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 169303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung /** Updates the list of filtered tasks whenever the base task list changes */ 170303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung private void updateFilteredTasks() { 171303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung mFilteredTasks.clear(); 172303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung if (mFilter != null) { 1732b9ef6548be89d36ea7629f4a3d8ba7bba1422ceWinson Chung // Create a sparse array from task id to Task 1742b9ef6548be89d36ea7629f4a3d8ba7bba1422ceWinson Chung SparseArray<Task> taskIdMap = new SparseArray<>(); 175303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung int taskCount = mTasks.size(); 176303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung for (int i = 0; i < taskCount; i++) { 177303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung Task t = mTasks.get(i); 1782b9ef6548be89d36ea7629f4a3d8ba7bba1422ceWinson Chung taskIdMap.put(t.key.id, t); 1792b9ef6548be89d36ea7629f4a3d8ba7bba1422ceWinson Chung } 1802b9ef6548be89d36ea7629f4a3d8ba7bba1422ceWinson Chung 1812b9ef6548be89d36ea7629f4a3d8ba7bba1422ceWinson Chung for (int i = 0; i < taskCount; i++) { 1822b9ef6548be89d36ea7629f4a3d8ba7bba1422ceWinson Chung Task t = mTasks.get(i); 1832b9ef6548be89d36ea7629f4a3d8ba7bba1422ceWinson Chung if (mFilter.acceptTask(taskIdMap, t, i)) { 184303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung mFilteredTasks.add(t); 185303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 186303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 187303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } else { 188303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung mFilteredTasks.addAll(mTasks); 189303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 190ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung updateFilteredTaskIndices(); 191ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 192ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung 193ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung /** Updates the mapping of tasks to indices. */ 194ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung private void updateFilteredTaskIndices() { 195ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung int taskCount = mFilteredTasks.size(); 1965500390a006f2bbea565068234774a36cea076c0Winson mTaskIndices.clear(); 197ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung for (int i = 0; i < taskCount; i++) { 198ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung Task t = mFilteredTasks.get(i); 199ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung mTaskIndices.put(t.key, i); 200ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 201303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 202303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 203303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung /** Returns whether this task list is filtered */ 204303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung boolean hasFilter() { 205303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung return (mFilter != null); 206303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 207303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 208303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung /** Returns the list of filtered tasks */ 209303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung ArrayList<Task> getTasks() { 210303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung return mFilteredTasks; 211303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 212303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung} 213303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 214303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung/** 215303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung * The task stack contains a list of multiple tasks. 216303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung */ 217303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chungpublic class TaskStack { 218ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung 219d72c315d5eed3a684eee303364b97129cb821689Winson private static final String TAG = "TaskStack"; 220d72c315d5eed3a684eee303364b97129cb821689Winson 221ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung /** Task stack callbacks */ 22204dfe0d26b944324ee920001f40d74cff47281d6Winson Chung public interface TaskStackCallbacks { 223062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung /** 224062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung * Notifies when a new task has been added to the stack. 225062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung */ 226062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung void onStackTaskAdded(TaskStack stack, Task newTask); 227062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung 228062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung /** 229062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung * Notifies when a task has been removed from the stack. 230062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung */ 2316c8217ab3072fa65851316a922b482506b3c2a4cWinson void onStackTaskRemoved(TaskStack stack, Task removedTask, Task newFrontMostTask, 232b502690e2d0a120993279a6fe800ad07dccc8872Winson Chung AnimationProps animation, boolean fromDockGesture, 233b502690e2d0a120993279a6fe800ad07dccc8872Winson Chung boolean dismissRecentsIfAllRemoved); 234a1ededd056d51532ab18354f17f8065ec1134535Winson 235a1ededd056d51532ab18354f17f8065ec1134535Winson /** 2363b6ba1ab144c53752841869627a1b9f6d357c404Winson * Notifies when all tasks have been removed from the stack. 2373b6ba1ab144c53752841869627a1b9f6d357c404Winson */ 2383b6ba1ab144c53752841869627a1b9f6d357c404Winson void onStackTasksRemoved(TaskStack stack); 2393b6ba1ab144c53752841869627a1b9f6d357c404Winson 2403b6ba1ab144c53752841869627a1b9f6d357c404Winson /** 241a1ededd056d51532ab18354f17f8065ec1134535Winson * Notifies when tasks in the stack have been updated. 242a1ededd056d51532ab18354f17f8065ec1134535Winson */ 243a1ededd056d51532ab18354f17f8065ec1134535Winson void onStackTasksUpdated(TaskStack stack); 24404dfe0d26b944324ee920001f40d74cff47281d6Winson Chung } 24504dfe0d26b944324ee920001f40d74cff47281d6Winson Chung 246250608a5cd08862f4752a924d51710805850db8aWinson /** 247250608a5cd08862f4752a924d51710805850db8aWinson * The various possible dock states when dragging and dropping a task. 248250608a5cd08862f4752a924d51710805850db8aWinson */ 249f0d1c44a59a10707baa0cca8dd377302260710c1Winson public static class DockState implements DropTarget { 250f0d1c44a59a10707baa0cca8dd377302260710c1Winson 25147dd7c51e9eb20f3cbd7536f60681ae926e2258eManu Cornet public static final int DOCK_AREA_BG_COLOR = 0xFFffffff; 25247dd7c51e9eb20f3cbd7536f60681ae926e2258eManu Cornet public static final int DOCK_AREA_GRID_BG_COLOR = 0xFF000000; 25347dd7c51e9eb20f3cbd7536f60681ae926e2258eManu Cornet 25499ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson // The rotation to apply to the hint text 25599ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson @Retention(RetentionPolicy.SOURCE) 25699ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson @IntDef({HORIZONTAL, VERTICAL}) 25799ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson public @interface TextOrientation {} 25899ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson private static final int HORIZONTAL = 0; 25999ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson private static final int VERTICAL = 1; 26099ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson 2613f32e7eba7aec02edbf542cc11eee13264a5abf2Winson private static final int DOCK_AREA_ALPHA = 80; 26299ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson public static final DockState NONE = new DockState(DOCKED_INVALID, -1, 80, 255, HORIZONTAL, 26399ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson null, null, null); 2643e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson public static final DockState LEFT = new DockState(DOCKED_LEFT, 26599ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT, DOCK_AREA_ALPHA, 0, VERTICAL, 2663e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson new RectF(0, 0, 0.125f, 1), new RectF(0, 0, 0.125f, 1), 2673e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson new RectF(0, 0, 0.5f, 1)); 2683e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson public static final DockState TOP = new DockState(DOCKED_TOP, 26999ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT, DOCK_AREA_ALPHA, 0, HORIZONTAL, 2703e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson new RectF(0, 0, 1, 0.125f), new RectF(0, 0, 1, 0.125f), 2713e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson new RectF(0, 0, 1, 0.5f)); 2723e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson public static final DockState RIGHT = new DockState(DOCKED_RIGHT, 27399ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson DOCKED_STACK_CREATE_MODE_BOTTOM_OR_RIGHT, DOCK_AREA_ALPHA, 0, VERTICAL, 2743e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson new RectF(0.875f, 0, 1, 1), new RectF(0.875f, 0, 1, 1), 2753e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson new RectF(0.5f, 0, 1, 1)); 2763e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson public static final DockState BOTTOM = new DockState(DOCKED_BOTTOM, 27799ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson DOCKED_STACK_CREATE_MODE_BOTTOM_OR_RIGHT, DOCK_AREA_ALPHA, 0, HORIZONTAL, 2783e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson new RectF(0, 0.875f, 1, 1), new RectF(0, 0.875f, 1, 1), 2793e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson new RectF(0, 0.5f, 1, 1)); 280eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson 281eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson @Override 28208deff0a67bd1e2d44477ed7c84c39fb3299fb7cWinson public boolean acceptsDrop(int x, int y, int width, int height, Rect insets, 28308deff0a67bd1e2d44477ed7c84c39fb3299fb7cWinson boolean isCurrentTarget) { 28408deff0a67bd1e2d44477ed7c84c39fb3299fb7cWinson if (isCurrentTarget) { 28508deff0a67bd1e2d44477ed7c84c39fb3299fb7cWinson getMappedRect(expandedTouchDockArea, width, height, mTmpRect); 28608deff0a67bd1e2d44477ed7c84c39fb3299fb7cWinson return mTmpRect.contains(x, y); 28708deff0a67bd1e2d44477ed7c84c39fb3299fb7cWinson } else { 28808deff0a67bd1e2d44477ed7c84c39fb3299fb7cWinson getMappedRect(touchArea, width, height, mTmpRect); 28908deff0a67bd1e2d44477ed7c84c39fb3299fb7cWinson updateBoundsWithSystemInsets(mTmpRect, insets); 29008deff0a67bd1e2d44477ed7c84c39fb3299fb7cWinson return mTmpRect.contains(x, y); 29108deff0a67bd1e2d44477ed7c84c39fb3299fb7cWinson } 292eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson } 293be7607af8875236b9cf7bdb5f5aa089c207529afWinson 294882072baacaee4ecd43f0209b691a9af746462f2Winson // Represents the view state of this dock state 29599ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson public static class ViewState { 29699ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson private static final IntProperty<ViewState> HINT_ALPHA = 29799ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson new IntProperty<ViewState>("drawableAlpha") { 29899ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson @Override 29999ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson public void setValue(ViewState object, int alpha) { 30099ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson object.mHintTextAlpha = alpha; 30199ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson object.dockAreaOverlay.invalidateSelf(); 30299ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson } 30399ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson 30499ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson @Override 30599ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson public Integer get(ViewState object) { 30699ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson return object.mHintTextAlpha; 30799ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson } 30899ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson }; 30999ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson 310882072baacaee4ecd43f0209b691a9af746462f2Winson public final int dockAreaAlpha; 311882072baacaee4ecd43f0209b691a9af746462f2Winson public final ColorDrawable dockAreaOverlay; 31299ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson public final int hintTextAlpha; 31399ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson public final int hintTextOrientation; 31499ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson 31599ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson private final int mHintTextResId; 31699ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson private String mHintText; 31799ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson private Paint mHintTextPaint; 31899ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson private Point mHintTextBounds = new Point(); 31999ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson private int mHintTextAlpha = 255; 32099ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson private AnimatorSet mDockAreaOverlayAnimator; 32199ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson private Rect mTmpRect = new Rect(); 32299ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson 32399ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson private ViewState(int areaAlpha, int hintAlpha, @TextOrientation int hintOrientation, 32499ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson int hintTextResId) { 32599ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson dockAreaAlpha = areaAlpha; 32647dd7c51e9eb20f3cbd7536f60681ae926e2258eManu Cornet dockAreaOverlay = new ColorDrawable(Recents.getConfiguration().isGridEnabled 32747dd7c51e9eb20f3cbd7536f60681ae926e2258eManu Cornet ? DOCK_AREA_GRID_BG_COLOR : DOCK_AREA_BG_COLOR); 328882072baacaee4ecd43f0209b691a9af746462f2Winson dockAreaOverlay.setAlpha(0); 32999ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson hintTextAlpha = hintAlpha; 33099ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson hintTextOrientation = hintOrientation; 33199ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson mHintTextResId = hintTextResId; 33299ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson mHintTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 33399ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson mHintTextPaint.setColor(Color.WHITE); 33499ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson } 33599ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson 33699ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson /** 33799ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson * Updates the view state with the given context. 33899ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson */ 33999ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson public void update(Context context) { 34099ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson Resources res = context.getResources(); 34199ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson mHintText = context.getString(mHintTextResId); 34299ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson mHintTextPaint.setTextSize(res.getDimensionPixelSize( 34399ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson R.dimen.recents_drag_hint_text_size)); 34499ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson mHintTextPaint.getTextBounds(mHintText, 0, mHintText.length(), mTmpRect); 34599ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson mHintTextBounds.set((int) mHintTextPaint.measureText(mHintText), mTmpRect.height()); 34699ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson } 34799ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson 34899ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson /** 34999ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson * Draws the current view state. 35099ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson */ 35199ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson public void draw(Canvas canvas) { 35299ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson // Draw the overlay background 35399ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson if (dockAreaOverlay.getAlpha() > 0) { 35499ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson dockAreaOverlay.draw(canvas); 35599ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson } 35699ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson 35799ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson // Draw the hint text 35899ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson if (mHintTextAlpha > 0) { 35999ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson Rect bounds = dockAreaOverlay.getBounds(); 36099ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson int x = bounds.left + (bounds.width() - mHintTextBounds.x) / 2; 36199ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson int y = bounds.top + (bounds.height() + mHintTextBounds.y) / 2; 36299ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson mHintTextPaint.setAlpha(mHintTextAlpha); 36399ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson if (hintTextOrientation == VERTICAL) { 36499ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson canvas.save(); 36599ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson canvas.rotate(-90f, bounds.centerX(), bounds.centerY()); 36699ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson } 36799ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson canvas.drawText(mHintText, x, y, mHintTextPaint); 36899ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson if (hintTextOrientation == VERTICAL) { 36999ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson canvas.restore(); 37099ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson } 37199ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson } 372882072baacaee4ecd43f0209b691a9af746462f2Winson } 373882072baacaee4ecd43f0209b691a9af746462f2Winson 374882072baacaee4ecd43f0209b691a9af746462f2Winson /** 3753e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson * Creates a new bounds and alpha animation. 376882072baacaee4ecd43f0209b691a9af746462f2Winson */ 37799ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson public void startAnimation(Rect bounds, int areaAlpha, int hintAlpha, int duration, 3783e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson Interpolator interpolator, boolean animateAlpha, boolean animateBounds) { 37999ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson if (mDockAreaOverlayAnimator != null) { 38099ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson mDockAreaOverlayAnimator.cancel(); 3813e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson } 3823e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson 3833f32e7eba7aec02edbf542cc11eee13264a5abf2Winson ObjectAnimator anim; 3843e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson ArrayList<Animator> animators = new ArrayList<>(); 38599ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson if (dockAreaOverlay.getAlpha() != areaAlpha) { 3863e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson if (animateAlpha) { 3873f32e7eba7aec02edbf542cc11eee13264a5abf2Winson anim = ObjectAnimator.ofInt(dockAreaOverlay, 3883f32e7eba7aec02edbf542cc11eee13264a5abf2Winson Utilities.DRAWABLE_ALPHA, dockAreaOverlay.getAlpha(), areaAlpha); 3893f32e7eba7aec02edbf542cc11eee13264a5abf2Winson anim.setDuration(duration); 3903f32e7eba7aec02edbf542cc11eee13264a5abf2Winson anim.setInterpolator(interpolator); 3913f32e7eba7aec02edbf542cc11eee13264a5abf2Winson animators.add(anim); 39299ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson } else { 39399ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson dockAreaOverlay.setAlpha(areaAlpha); 39499ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson } 39599ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson } 39699ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson if (mHintTextAlpha != hintAlpha) { 39799ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson if (animateAlpha) { 3983f32e7eba7aec02edbf542cc11eee13264a5abf2Winson anim = ObjectAnimator.ofInt(this, HINT_ALPHA, mHintTextAlpha, 3993f32e7eba7aec02edbf542cc11eee13264a5abf2Winson hintAlpha); 4003f32e7eba7aec02edbf542cc11eee13264a5abf2Winson anim.setDuration(150); 4013f32e7eba7aec02edbf542cc11eee13264a5abf2Winson anim.setInterpolator(hintAlpha > mHintTextAlpha 4023f32e7eba7aec02edbf542cc11eee13264a5abf2Winson ? Interpolators.ALPHA_IN 4033f32e7eba7aec02edbf542cc11eee13264a5abf2Winson : Interpolators.ALPHA_OUT); 4043f32e7eba7aec02edbf542cc11eee13264a5abf2Winson animators.add(anim); 4053e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson } else { 40699ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson mHintTextAlpha = hintAlpha; 40799ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson dockAreaOverlay.invalidateSelf(); 4083e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson } 4093e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson } 4103e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson if (bounds != null && !dockAreaOverlay.getBounds().equals(bounds)) { 4113e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson if (animateBounds) { 4123e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson PropertyValuesHolder prop = PropertyValuesHolder.ofObject( 41367c79578f94646bade5d336af0d4491179c1b37dWinson Utilities.DRAWABLE_RECT, Utilities.RECT_EVALUATOR, 4143f32e7eba7aec02edbf542cc11eee13264a5abf2Winson new Rect(dockAreaOverlay.getBounds()), bounds); 4153f32e7eba7aec02edbf542cc11eee13264a5abf2Winson anim = ObjectAnimator.ofPropertyValuesHolder(dockAreaOverlay, prop); 4163f32e7eba7aec02edbf542cc11eee13264a5abf2Winson anim.setDuration(duration); 4173f32e7eba7aec02edbf542cc11eee13264a5abf2Winson anim.setInterpolator(interpolator); 4183f32e7eba7aec02edbf542cc11eee13264a5abf2Winson animators.add(anim); 4193e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson } else { 4203e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson dockAreaOverlay.setBounds(bounds); 421882072baacaee4ecd43f0209b691a9af746462f2Winson } 4223e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson } 4233e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson if (!animators.isEmpty()) { 42499ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson mDockAreaOverlayAnimator = new AnimatorSet(); 42599ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson mDockAreaOverlayAnimator.playTogether(animators); 42699ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson mDockAreaOverlayAnimator.start(); 427882072baacaee4ecd43f0209b691a9af746462f2Winson } 428882072baacaee4ecd43f0209b691a9af746462f2Winson } 429882072baacaee4ecd43f0209b691a9af746462f2Winson } 430882072baacaee4ecd43f0209b691a9af746462f2Winson 4313e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson public final int dockSide; 432be7607af8875236b9cf7bdb5f5aa089c207529afWinson public final int createMode; 433882072baacaee4ecd43f0209b691a9af746462f2Winson public final ViewState viewState; 434882072baacaee4ecd43f0209b691a9af746462f2Winson private final RectF touchArea; 4353e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson private final RectF dockArea; 4363e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson private final RectF expandedTouchDockArea; 43708deff0a67bd1e2d44477ed7c84c39fb3299fb7cWinson private static final Rect mTmpRect = new Rect(); 438be7607af8875236b9cf7bdb5f5aa089c207529afWinson 439be7607af8875236b9cf7bdb5f5aa089c207529afWinson /** 440be7607af8875236b9cf7bdb5f5aa089c207529afWinson * @param createMode used to pass to ActivityManager to dock the task 441be7607af8875236b9cf7bdb5f5aa089c207529afWinson * @param touchArea the area in which touch will initiate this dock state 442eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson * @param dockArea the visible dock area 44347dd7c51e9eb20f3cbd7536f60681ae926e2258eManu Cornet * @param expandedTouchDockArea the area in which touch will continue to dock after entering 4443e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson * the initial touch area. This is also the new dock area to 4453e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson * draw. 446be7607af8875236b9cf7bdb5f5aa089c207529afWinson */ 44799ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson DockState(int dockSide, int createMode, int dockAreaAlpha, int hintTextAlpha, 44899ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson @TextOrientation int hintTextOrientation, RectF touchArea, RectF dockArea, 4493e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson RectF expandedTouchDockArea) { 4503e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson this.dockSide = dockSide; 451be7607af8875236b9cf7bdb5f5aa089c207529afWinson this.createMode = createMode; 45299ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson this.viewState = new ViewState(dockAreaAlpha, hintTextAlpha, hintTextOrientation, 45399ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson R.string.recents_drag_hint_message); 454be7607af8875236b9cf7bdb5f5aa089c207529afWinson this.dockArea = dockArea; 455882072baacaee4ecd43f0209b691a9af746462f2Winson this.touchArea = touchArea; 4563e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson this.expandedTouchDockArea = expandedTouchDockArea; 457be7607af8875236b9cf7bdb5f5aa089c207529afWinson } 458be7607af8875236b9cf7bdb5f5aa089c207529afWinson 459be7607af8875236b9cf7bdb5f5aa089c207529afWinson /** 46099ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson * Updates the dock state with the given context. 46199ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson */ 46299ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson public void update(Context context) { 46399ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson viewState.update(context); 46499ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson } 46599ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson 46699ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson /** 467be7607af8875236b9cf7bdb5f5aa089c207529afWinson * Returns the docked task bounds with the given {@param width} and {@param height}. 468be7607af8875236b9cf7bdb5f5aa089c207529afWinson */ 46908deff0a67bd1e2d44477ed7c84c39fb3299fb7cWinson public Rect getPreDockedBounds(int width, int height, Rect insets) { 47008deff0a67bd1e2d44477ed7c84c39fb3299fb7cWinson getMappedRect(dockArea, width, height, mTmpRect); 47108deff0a67bd1e2d44477ed7c84c39fb3299fb7cWinson return updateBoundsWithSystemInsets(mTmpRect, insets); 472be7607af8875236b9cf7bdb5f5aa089c207529afWinson } 4733e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson 4743e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson /** 4753e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson * Returns the expanded docked task bounds with the given {@param width} and 4763e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson * {@param height}. 4773e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson */ 4783e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson public Rect getDockedBounds(int width, int height, int dividerSize, Rect insets, 4793e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson Resources res) { 4803e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson // Calculate the docked task bounds 4813e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson boolean isHorizontalDivision = 4823e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson res.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT; 4833e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson int position = DockedDividerUtils.calculateMiddlePosition(isHorizontalDivision, 4843e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson insets, width, height, dividerSize); 4853e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson Rect newWindowBounds = new Rect(); 4863e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson DockedDividerUtils.calculateBoundsForPosition(position, dockSide, newWindowBounds, 4873e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson width, height, dividerSize); 4883e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson return newWindowBounds; 4893e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson } 4903e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson 4913e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson /** 4923e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson * Returns the task stack bounds with the given {@param width} and 4933e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson * {@param height}. 4943e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson */ 495fc48b072e8caa62849ee305f89f38d248d4a1dedWinson public Rect getDockedTaskStackBounds(Rect displayRect, int width, int height, 496fc48b072e8caa62849ee305f89f38d248d4a1dedWinson int dividerSize, Rect insets, TaskStackLayoutAlgorithm layoutAlgorithm, 497fc48b072e8caa62849ee305f89f38d248d4a1dedWinson Resources res, Rect windowRectOut) { 4983e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson // Calculate the inverse docked task bounds 4993e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson boolean isHorizontalDivision = 5003e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson res.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT; 5013e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson int position = DockedDividerUtils.calculateMiddlePosition(isHorizontalDivision, 5023e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson insets, width, height, dividerSize); 5033e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson DockedDividerUtils.calculateBoundsForPosition(position, 50459924fe0d9136cf349759bea1e06b661603f95feWinson DockedDividerUtils.invertDockSide(dockSide), windowRectOut, width, height, 5053e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson dividerSize); 5063e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson 5073e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson // Calculate the task stack bounds from the new window bounds 5083e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson Rect taskStackBounds = new Rect(); 509d952961977a0eb6c1fefcb0707d1c61741515f68Winson // If the task stack bounds is specifically under the dock area, then ignore the top 510d952961977a0eb6c1fefcb0707d1c61741515f68Winson // inset 511d952961977a0eb6c1fefcb0707d1c61741515f68Winson int top = dockArea.bottom < 1f 512d952961977a0eb6c1fefcb0707d1c61741515f68Winson ? 0 513d952961977a0eb6c1fefcb0707d1c61741515f68Winson : insets.top; 51408deff0a67bd1e2d44477ed7c84c39fb3299fb7cWinson // For now, ignore the left insets since we always dock on the left and show Recents 51508deff0a67bd1e2d44477ed7c84c39fb3299fb7cWinson // on the right 51608deff0a67bd1e2d44477ed7c84c39fb3299fb7cWinson layoutAlgorithm.getTaskStackBounds(displayRect, windowRectOut, top, 0, insets.right, 51708deff0a67bd1e2d44477ed7c84c39fb3299fb7cWinson taskStackBounds); 5183e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson return taskStackBounds; 5193e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson } 52008deff0a67bd1e2d44477ed7c84c39fb3299fb7cWinson 52108deff0a67bd1e2d44477ed7c84c39fb3299fb7cWinson /** 52208deff0a67bd1e2d44477ed7c84c39fb3299fb7cWinson * Returns the expanded bounds in certain dock sides such that the bounds account for the 52308deff0a67bd1e2d44477ed7c84c39fb3299fb7cWinson * system insets (namely the vertical nav bar). This call modifies and returns the given 52408deff0a67bd1e2d44477ed7c84c39fb3299fb7cWinson * {@param bounds}. 52508deff0a67bd1e2d44477ed7c84c39fb3299fb7cWinson */ 52608deff0a67bd1e2d44477ed7c84c39fb3299fb7cWinson private Rect updateBoundsWithSystemInsets(Rect bounds, Rect insets) { 52708deff0a67bd1e2d44477ed7c84c39fb3299fb7cWinson if (dockSide == DOCKED_LEFT) { 52808deff0a67bd1e2d44477ed7c84c39fb3299fb7cWinson bounds.right += insets.left; 52908deff0a67bd1e2d44477ed7c84c39fb3299fb7cWinson } else if (dockSide == DOCKED_RIGHT) { 53008deff0a67bd1e2d44477ed7c84c39fb3299fb7cWinson bounds.left -= insets.right; 53108deff0a67bd1e2d44477ed7c84c39fb3299fb7cWinson } 53208deff0a67bd1e2d44477ed7c84c39fb3299fb7cWinson return bounds; 53308deff0a67bd1e2d44477ed7c84c39fb3299fb7cWinson } 53408deff0a67bd1e2d44477ed7c84c39fb3299fb7cWinson 53508deff0a67bd1e2d44477ed7c84c39fb3299fb7cWinson /** 53608deff0a67bd1e2d44477ed7c84c39fb3299fb7cWinson * Returns the mapped rect to the given dimensions. 53708deff0a67bd1e2d44477ed7c84c39fb3299fb7cWinson */ 53808deff0a67bd1e2d44477ed7c84c39fb3299fb7cWinson private void getMappedRect(RectF bounds, int width, int height, Rect out) { 53908deff0a67bd1e2d44477ed7c84c39fb3299fb7cWinson out.set((int) (bounds.left * width), (int) (bounds.top * height), 54008deff0a67bd1e2d44477ed7c84c39fb3299fb7cWinson (int) (bounds.right * width), (int) (bounds.bottom * height)); 54108deff0a67bd1e2d44477ed7c84c39fb3299fb7cWinson } 542be7607af8875236b9cf7bdb5f5aa089c207529afWinson } 543be7607af8875236b9cf7bdb5f5aa089c207529afWinson 5446976f7bae901d81a354287088ae232ba7236f30eWinson // A comparator that sorts tasks by their freeform state 5456976f7bae901d81a354287088ae232ba7236f30eWinson private Comparator<Task> FREEFORM_COMPARATOR = new Comparator<Task>() { 546509d0d0c9e2ee165d04e898fea59f8941ac7138dWinson Chung @Override 547509d0d0c9e2ee165d04e898fea59f8941ac7138dWinson Chung public int compare(Task o1, Task o2) { 548509d0d0c9e2ee165d04e898fea59f8941ac7138dWinson Chung if (o1.isFreeformTask() && !o2.isFreeformTask()) { 549509d0d0c9e2ee165d04e898fea59f8941ac7138dWinson Chung return 1; 550509d0d0c9e2ee165d04e898fea59f8941ac7138dWinson Chung } else if (o2.isFreeformTask() && !o1.isFreeformTask()) { 551509d0d0c9e2ee165d04e898fea59f8941ac7138dWinson Chung return -1; 552509d0d0c9e2ee165d04e898fea59f8941ac7138dWinson Chung } 5536976f7bae901d81a354287088ae232ba7236f30eWinson return Long.compare(o1.temporarySortIndexInStack, o2.temporarySortIndexInStack); 554509d0d0c9e2ee165d04e898fea59f8941ac7138dWinson Chung } 555509d0d0c9e2ee165d04e898fea59f8941ac7138dWinson Chung }; 556509d0d0c9e2ee165d04e898fea59f8941ac7138dWinson Chung 557509d0d0c9e2ee165d04e898fea59f8941ac7138dWinson Chung 558083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung // The task offset to apply to a task id as a group affiliation 559083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung static final int IndividualTaskIdOffset = 1 << 16; 560083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung 561062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung ArrayList<Task> mRawTaskList = new ArrayList<>(); 562250608a5cd08862f4752a924d51710805850db8aWinson FilteredTaskList mStackTaskList = new FilteredTaskList(); 563303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung TaskStackCallbacks mCb; 564303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 5658f0e3a68cdd3b2403ff8a1677f90b998f4175f40Winson ArrayList<TaskGrouping> mGroups = new ArrayList<>(); 5665500390a006f2bbea565068234774a36cea076c0Winson ArrayMap<Integer, TaskGrouping> mAffinitiesGroups = new ArrayMap<>(); 5678f0e3a68cdd3b2403ff8a1677f90b998f4175f40Winson 5688f0e3a68cdd3b2403ff8a1677f90b998f4175f40Winson public TaskStack() { 5698f0e3a68cdd3b2403ff8a1677f90b998f4175f40Winson // Ensure that we only show non-docked tasks 570250608a5cd08862f4752a924d51710805850db8aWinson mStackTaskList.setFilter(new TaskFilter() { 5718f0e3a68cdd3b2403ff8a1677f90b998f4175f40Winson @Override 5722b9ef6548be89d36ea7629f4a3d8ba7bba1422ceWinson Chung public boolean acceptTask(SparseArray<Task> taskIdMap, Task t, int index) { 573d8f7431d0fe0f5449ca54a15392c3238aa645deaWinson if (RecentsDebugFlags.Static.EnableAffiliatedTaskGroups) { 574d8f7431d0fe0f5449ca54a15392c3238aa645deaWinson if (t.isAffiliatedTask()) { 575d8f7431d0fe0f5449ca54a15392c3238aa645deaWinson // If this task is affiliated with another parent in the stack, then the 576d8f7431d0fe0f5449ca54a15392c3238aa645deaWinson // historical state of this task depends on the state of the parent task 577d8f7431d0fe0f5449ca54a15392c3238aa645deaWinson Task parentTask = taskIdMap.get(t.affiliationTaskId); 578d8f7431d0fe0f5449ca54a15392c3238aa645deaWinson if (parentTask != null) { 579d8f7431d0fe0f5449ca54a15392c3238aa645deaWinson t = parentTask; 580d8f7431d0fe0f5449ca54a15392c3238aa645deaWinson } 5812b9ef6548be89d36ea7629f4a3d8ba7bba1422ceWinson Chung } 5822b9ef6548be89d36ea7629f4a3d8ba7bba1422ceWinson Chung } 5838f6ee48225ad1cdf966c8f406c85113b13833c7bWinson return t.isStackTask; 5848f0e3a68cdd3b2403ff8a1677f90b998f4175f40Winson } 5858f0e3a68cdd3b2403ff8a1677f90b998f4175f40Winson }); 5868f0e3a68cdd3b2403ff8a1677f90b998f4175f40Winson } 587303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 588d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung /** Sets the callbacks for this task stack. */ 589303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung public void setCallbacks(TaskStackCallbacks cb) { 590303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung mCb = cb; 591303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 592303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 593eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson /** 594eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson * Moves the given task to either the front of the freeform workspace or the stack. 595eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson */ 596eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson public void moveTaskToStack(Task task, int newStackId) { 597eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson // Find the index to insert into 598250608a5cd08862f4752a924d51710805850db8aWinson ArrayList<Task> taskList = mStackTaskList.getTasks(); 599eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson int taskCount = taskList.size(); 600eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson if (!task.isFreeformTask() && (newStackId == FREEFORM_WORKSPACE_STACK_ID)) { 601eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson // Insert freeform tasks at the front 602250608a5cd08862f4752a924d51710805850db8aWinson mStackTaskList.moveTaskToStack(task, taskCount, newStackId); 603eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson } else if (task.isFreeformTask() && (newStackId == FULLSCREEN_WORKSPACE_STACK_ID)) { 604eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson // Insert after the first stacked task 605eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson int insertIndex = 0; 606eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson for (int i = taskCount - 1; i >= 0; i--) { 607eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson if (!taskList.get(i).isFreeformTask()) { 608eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson insertIndex = i + 1; 609eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson break; 610eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson } 611eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson } 612250608a5cd08862f4752a924d51710805850db8aWinson mStackTaskList.moveTaskToStack(task, insertIndex, newStackId); 613eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson } 614eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson } 615eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson 6166ac8bd6198f67b64aea2258bdb5f8ed371b5bec1Winson Chung /** Does the actual work associated with removing the task. */ 617250608a5cd08862f4752a924d51710805850db8aWinson void removeTaskImpl(FilteredTaskList taskList, Task t) { 6186ac8bd6198f67b64aea2258bdb5f8ed371b5bec1Winson Chung // Remove the task from the list 619250608a5cd08862f4752a924d51710805850db8aWinson taskList.remove(t); 6206ac8bd6198f67b64aea2258bdb5f8ed371b5bec1Winson Chung // Remove it from the group as well, and if it is empty, remove the group 6216ac8bd6198f67b64aea2258bdb5f8ed371b5bec1Winson Chung TaskGrouping group = t.group; 6224e5fb2f4e1ed4eb119a201541ad89aafac8c53feWinson Chung if (group != null) { 6234e5fb2f4e1ed4eb119a201541ad89aafac8c53feWinson Chung group.removeTask(t); 6244e5fb2f4e1ed4eb119a201541ad89aafac8c53feWinson Chung if (group.getTaskCount() == 0) { 6254e5fb2f4e1ed4eb119a201541ad89aafac8c53feWinson Chung removeGroup(group); 6264e5fb2f4e1ed4eb119a201541ad89aafac8c53feWinson Chung } 6276ac8bd6198f67b64aea2258bdb5f8ed371b5bec1Winson Chung } 6286ac8bd6198f67b64aea2258bdb5f8ed371b5bec1Winson Chung } 6296ac8bd6198f67b64aea2258bdb5f8ed371b5bec1Winson Chung 6308aa9959413a06c3d2ff75e0c7be9e3cb7ac7cd2eWinson /** 6318aa9959413a06c3d2ff75e0c7be9e3cb7ac7cd2eWinson * Removes a task from the stack, with an additional {@param animation} hint to the callbacks on 6328aa9959413a06c3d2ff75e0c7be9e3cb7ac7cd2eWinson * how they should update themselves. 6338aa9959413a06c3d2ff75e0c7be9e3cb7ac7cd2eWinson */ 6342068408d08ca39a5b036daac01e80de45e8c1eabWinson public void removeTask(Task t, AnimationProps animation, boolean fromDockGesture) { 635b502690e2d0a120993279a6fe800ad07dccc8872Winson Chung removeTask(t, animation, fromDockGesture, true /* dismissRecentsIfAllRemoved */); 636b502690e2d0a120993279a6fe800ad07dccc8872Winson Chung } 637b502690e2d0a120993279a6fe800ad07dccc8872Winson Chung 638b502690e2d0a120993279a6fe800ad07dccc8872Winson Chung /** 639b502690e2d0a120993279a6fe800ad07dccc8872Winson Chung * Removes a task from the stack, with an additional {@param animation} hint to the callbacks on 640b502690e2d0a120993279a6fe800ad07dccc8872Winson Chung * how they should update themselves. 641b502690e2d0a120993279a6fe800ad07dccc8872Winson Chung */ 642b502690e2d0a120993279a6fe800ad07dccc8872Winson Chung public void removeTask(Task t, AnimationProps animation, boolean fromDockGesture, 643b502690e2d0a120993279a6fe800ad07dccc8872Winson Chung boolean dismissRecentsIfAllRemoved) { 644250608a5cd08862f4752a924d51710805850db8aWinson if (mStackTaskList.contains(t)) { 645250608a5cd08862f4752a924d51710805850db8aWinson removeTaskImpl(mStackTaskList, t); 64635a8b04140598a5b5c4865254b942adb6a830991Winson Task newFrontMostTask = getStackFrontMostTask(false /* includeFreeform */); 647303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung if (mCb != null) { 648ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung // Notify that a task has been removed 6496c8217ab3072fa65851316a922b482506b3c2a4cWinson mCb.onStackTaskRemoved(this, t, newFrontMostTask, animation, 650b502690e2d0a120993279a6fe800ad07dccc8872Winson Chung fromDockGesture, dismissRecentsIfAllRemoved); 651303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 652303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 6533e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson mRawTaskList.remove(t); 654250608a5cd08862f4752a924d51710805850db8aWinson } 655250608a5cd08862f4752a924d51710805850db8aWinson 656250608a5cd08862f4752a924d51710805850db8aWinson /** 6573b6ba1ab144c53752841869627a1b9f6d357c404Winson * Removes all tasks from the stack. 6583b6ba1ab144c53752841869627a1b9f6d357c404Winson */ 659b502690e2d0a120993279a6fe800ad07dccc8872Winson Chung public void removeAllTasks(boolean notifyStackChanges) { 6603b6ba1ab144c53752841869627a1b9f6d357c404Winson ArrayList<Task> tasks = mStackTaskList.getTasks(); 6613b6ba1ab144c53752841869627a1b9f6d357c404Winson for (int i = tasks.size() - 1; i >= 0; i--) { 6623b6ba1ab144c53752841869627a1b9f6d357c404Winson Task t = tasks.get(i); 6633b6ba1ab144c53752841869627a1b9f6d357c404Winson removeTaskImpl(mStackTaskList, t); 6643b6ba1ab144c53752841869627a1b9f6d357c404Winson mRawTaskList.remove(t); 6653b6ba1ab144c53752841869627a1b9f6d357c404Winson } 666b502690e2d0a120993279a6fe800ad07dccc8872Winson Chung if (mCb != null && notifyStackChanges) { 6673b6ba1ab144c53752841869627a1b9f6d357c404Winson // Notify that all tasks have been removed 6683b6ba1ab144c53752841869627a1b9f6d357c404Winson mCb.onStackTasksRemoved(this); 6693b6ba1ab144c53752841869627a1b9f6d357c404Winson } 6703b6ba1ab144c53752841869627a1b9f6d357c404Winson } 6713b6ba1ab144c53752841869627a1b9f6d357c404Winson 672b502690e2d0a120993279a6fe800ad07dccc8872Winson Chung 673b502690e2d0a120993279a6fe800ad07dccc8872Winson Chung /** 674b502690e2d0a120993279a6fe800ad07dccc8872Winson Chung * @see #setTasks(Context, List, boolean, boolean) 675b502690e2d0a120993279a6fe800ad07dccc8872Winson Chung */ 676b502690e2d0a120993279a6fe800ad07dccc8872Winson Chung public void setTasks(Context context, TaskStack stack, boolean notifyStackChanges) { 677b502690e2d0a120993279a6fe800ad07dccc8872Winson Chung setTasks(context, stack.mRawTaskList, notifyStackChanges); 678b502690e2d0a120993279a6fe800ad07dccc8872Winson Chung } 679b502690e2d0a120993279a6fe800ad07dccc8872Winson Chung 6803b6ba1ab144c53752841869627a1b9f6d357c404Winson /** 681250608a5cd08862f4752a924d51710805850db8aWinson * Sets a few tasks in one go, without calling any callbacks. 682062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung * 683062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung * @param tasks the new set of tasks to replace the current set. 684062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung * @param notifyStackChanges whether or not to callback on specific changes to the list of tasks. 685250608a5cd08862f4752a924d51710805850db8aWinson */ 6868873754f66527d2cc9feab295dd4eef23298212aWinson public void setTasks(Context context, List<Task> tasks, boolean notifyStackChanges) { 687062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung // Compute a has set for each of the tasks 6885500390a006f2bbea565068234774a36cea076c0Winson ArrayMap<Task.TaskKey, Task> currentTasksMap = createTaskKeyMapFromList(mRawTaskList); 6895500390a006f2bbea565068234774a36cea076c0Winson ArrayMap<Task.TaskKey, Task> newTasksMap = createTaskKeyMapFromList(tasks); 6908873754f66527d2cc9feab295dd4eef23298212aWinson ArrayList<Task> addedTasks = new ArrayList<>(); 6916c8217ab3072fa65851316a922b482506b3c2a4cWinson ArrayList<Task> removedTasks = new ArrayList<>(); 6928873754f66527d2cc9feab295dd4eef23298212aWinson ArrayList<Task> allTasks = new ArrayList<>(); 693062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung 694062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung // Disable notifications if there are no callbacks 695062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung if (mCb == null) { 696062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung notifyStackChanges = false; 697062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung } 698062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung 699062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung // Remove any tasks that no longer exist 700062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung int taskCount = mRawTaskList.size(); 7018873754f66527d2cc9feab295dd4eef23298212aWinson for (int i = taskCount - 1; i >= 0; i--) { 702062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung Task task = mRawTaskList.get(i); 703062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung if (!newTasksMap.containsKey(task.key)) { 704062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung if (notifyStackChanges) { 7056c8217ab3072fa65851316a922b482506b3c2a4cWinson removedTasks.add(task); 706062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung } 707062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung } 7089756755db76aeda2065322aa3c26e1a19578d45fWinson Chung task.setGroup(null); 709062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung } 710062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung 711062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung // Add any new tasks 712062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung taskCount = tasks.size(); 713062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung for (int i = 0; i < taskCount; i++) { 7148873754f66527d2cc9feab295dd4eef23298212aWinson Task newTask = tasks.get(i); 7158873754f66527d2cc9feab295dd4eef23298212aWinson Task currentTask = currentTasksMap.get(newTask.key); 7168873754f66527d2cc9feab295dd4eef23298212aWinson if (currentTask == null && notifyStackChanges) { 7178873754f66527d2cc9feab295dd4eef23298212aWinson addedTasks.add(newTask); 7188873754f66527d2cc9feab295dd4eef23298212aWinson } else if (currentTask != null) { 7198873754f66527d2cc9feab295dd4eef23298212aWinson // The current task has bound callbacks, so just copy the data from the new task 7208873754f66527d2cc9feab295dd4eef23298212aWinson // state and add it back into the list 7218873754f66527d2cc9feab295dd4eef23298212aWinson currentTask.copyFrom(newTask); 7228873754f66527d2cc9feab295dd4eef23298212aWinson newTask = currentTask; 723062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung } 7248873754f66527d2cc9feab295dd4eef23298212aWinson allTasks.add(newTask); 725062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung } 726062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung 727062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung // Sort all the tasks to ensure they are ordered correctly 7286976f7bae901d81a354287088ae232ba7236f30eWinson for (int i = allTasks.size() - 1; i >= 0; i--) { 7296976f7bae901d81a354287088ae232ba7236f30eWinson allTasks.get(i).temporarySortIndexInStack = i; 7306976f7bae901d81a354287088ae232ba7236f30eWinson } 7316976f7bae901d81a354287088ae232ba7236f30eWinson Collections.sort(allTasks, FREEFORM_COMPARATOR); 732062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung 7338f6ee48225ad1cdf966c8f406c85113b13833c7bWinson mStackTaskList.set(allTasks); 7348873754f66527d2cc9feab295dd4eef23298212aWinson mRawTaskList = allTasks; 7358873754f66527d2cc9feab295dd4eef23298212aWinson 736a1ededd056d51532ab18354f17f8065ec1134535Winson // Update the affiliated groupings 737a1ededd056d51532ab18354f17f8065ec1134535Winson createAffiliatedGroupings(context); 738a1ededd056d51532ab18354f17f8065ec1134535Winson 7396c8217ab3072fa65851316a922b482506b3c2a4cWinson // Only callback for the removed tasks after the stack has updated 7406c8217ab3072fa65851316a922b482506b3c2a4cWinson int removedTaskCount = removedTasks.size(); 7416c8217ab3072fa65851316a922b482506b3c2a4cWinson Task newFrontMostTask = getStackFrontMostTask(false); 7426c8217ab3072fa65851316a922b482506b3c2a4cWinson for (int i = 0; i < removedTaskCount; i++) { 7436c8217ab3072fa65851316a922b482506b3c2a4cWinson mCb.onStackTaskRemoved(this, removedTasks.get(i), newFrontMostTask, 744b502690e2d0a120993279a6fe800ad07dccc8872Winson Chung AnimationProps.IMMEDIATE, false /* fromDockGesture */, 745b502690e2d0a120993279a6fe800ad07dccc8872Winson Chung true /* dismissRecentsIfAllRemoved */); 7466c8217ab3072fa65851316a922b482506b3c2a4cWinson } 7476c8217ab3072fa65851316a922b482506b3c2a4cWinson 7488873754f66527d2cc9feab295dd4eef23298212aWinson // Only callback for the newly added tasks after this stack has been updated 7498873754f66527d2cc9feab295dd4eef23298212aWinson int addedTaskCount = addedTasks.size(); 7508873754f66527d2cc9feab295dd4eef23298212aWinson for (int i = 0; i < addedTaskCount; i++) { 7518873754f66527d2cc9feab295dd4eef23298212aWinson mCb.onStackTaskAdded(this, addedTasks.get(i)); 7528873754f66527d2cc9feab295dd4eef23298212aWinson } 7538873754f66527d2cc9feab295dd4eef23298212aWinson 754a1ededd056d51532ab18354f17f8065ec1134535Winson // Notify that the task stack has been updated 755a1ededd056d51532ab18354f17f8065ec1134535Winson if (notifyStackChanges) { 756a1ededd056d51532ab18354f17f8065ec1134535Winson mCb.onStackTasksUpdated(this); 757a1ededd056d51532ab18354f17f8065ec1134535Winson } 758303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 759303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 760931c51f54599a227422b2a1c71e922e1458e0291Winson Chung /** 761931c51f54599a227422b2a1c71e922e1458e0291Winson Chung * Gets the front-most task in the stack. 762931c51f54599a227422b2a1c71e922e1458e0291Winson Chung */ 76335a8b04140598a5b5c4865254b942adb6a830991Winson public Task getStackFrontMostTask(boolean includeFreeformTasks) { 764931c51f54599a227422b2a1c71e922e1458e0291Winson Chung ArrayList<Task> stackTasks = mStackTaskList.getTasks(); 765931c51f54599a227422b2a1c71e922e1458e0291Winson Chung if (stackTasks.isEmpty()) { 766931c51f54599a227422b2a1c71e922e1458e0291Winson Chung return null; 767931c51f54599a227422b2a1c71e922e1458e0291Winson Chung } 768931c51f54599a227422b2a1c71e922e1458e0291Winson Chung for (int i = stackTasks.size() - 1; i >= 0; i--) { 769931c51f54599a227422b2a1c71e922e1458e0291Winson Chung Task task = stackTasks.get(i); 77035a8b04140598a5b5c4865254b942adb6a830991Winson if (!task.isFreeformTask() || includeFreeformTasks) { 771931c51f54599a227422b2a1c71e922e1458e0291Winson Chung return task; 772931c51f54599a227422b2a1c71e922e1458e0291Winson Chung } 773931c51f54599a227422b2a1c71e922e1458e0291Winson Chung } 774931c51f54599a227422b2a1c71e922e1458e0291Winson Chung return null; 775ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 776ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung 77704400672962d2e12132f9465928cbf7615c147c4Winson Chung /** Gets the task keys */ 77804400672962d2e12132f9465928cbf7615c147c4Winson Chung public ArrayList<Task.TaskKey> getTaskKeys() { 7798f0e3a68cdd3b2403ff8a1677f90b998f4175f40Winson ArrayList<Task.TaskKey> taskKeys = new ArrayList<>(); 780250608a5cd08862f4752a924d51710805850db8aWinson ArrayList<Task> tasks = computeAllTasksList(); 78104400672962d2e12132f9465928cbf7615c147c4Winson Chung int taskCount = tasks.size(); 78204400672962d2e12132f9465928cbf7615c147c4Winson Chung for (int i = 0; i < taskCount; i++) { 783250608a5cd08862f4752a924d51710805850db8aWinson Task task = tasks.get(i); 784250608a5cd08862f4752a924d51710805850db8aWinson taskKeys.add(task.key); 78504400672962d2e12132f9465928cbf7615c147c4Winson Chung } 78604400672962d2e12132f9465928cbf7615c147c4Winson Chung return taskKeys; 78704400672962d2e12132f9465928cbf7615c147c4Winson Chung } 78804400672962d2e12132f9465928cbf7615c147c4Winson Chung 789250608a5cd08862f4752a924d51710805850db8aWinson /** 790250608a5cd08862f4752a924d51710805850db8aWinson * Returns the set of "active" (non-historical) tasks in the stack that have been used recently. 791250608a5cd08862f4752a924d51710805850db8aWinson */ 792250608a5cd08862f4752a924d51710805850db8aWinson public ArrayList<Task> getStackTasks() { 793250608a5cd08862f4752a924d51710805850db8aWinson return mStackTaskList.getTasks(); 794250608a5cd08862f4752a924d51710805850db8aWinson } 795250608a5cd08862f4752a924d51710805850db8aWinson 796250608a5cd08862f4752a924d51710805850db8aWinson /** 797f24f21695f5609d06402cf61e3500d408b99bdcbWinson * Returns the set of "freeform" tasks in the stack. 798f24f21695f5609d06402cf61e3500d408b99bdcbWinson */ 799f24f21695f5609d06402cf61e3500d408b99bdcbWinson public ArrayList<Task> getFreeformTasks() { 800f24f21695f5609d06402cf61e3500d408b99bdcbWinson ArrayList<Task> freeformTasks = new ArrayList<>(); 801f24f21695f5609d06402cf61e3500d408b99bdcbWinson ArrayList<Task> tasks = mStackTaskList.getTasks(); 802f24f21695f5609d06402cf61e3500d408b99bdcbWinson int taskCount = tasks.size(); 803f24f21695f5609d06402cf61e3500d408b99bdcbWinson for (int i = 0; i < taskCount; i++) { 804f24f21695f5609d06402cf61e3500d408b99bdcbWinson Task task = tasks.get(i); 805f24f21695f5609d06402cf61e3500d408b99bdcbWinson if (task.isFreeformTask()) { 806f24f21695f5609d06402cf61e3500d408b99bdcbWinson freeformTasks.add(task); 807f24f21695f5609d06402cf61e3500d408b99bdcbWinson } 808f24f21695f5609d06402cf61e3500d408b99bdcbWinson } 809f24f21695f5609d06402cf61e3500d408b99bdcbWinson return freeformTasks; 810f24f21695f5609d06402cf61e3500d408b99bdcbWinson } 811f24f21695f5609d06402cf61e3500d408b99bdcbWinson 812f24f21695f5609d06402cf61e3500d408b99bdcbWinson /** 8136976f7bae901d81a354287088ae232ba7236f30eWinson * Computes a set of all the active and historical tasks. 814250608a5cd08862f4752a924d51710805850db8aWinson */ 815250608a5cd08862f4752a924d51710805850db8aWinson public ArrayList<Task> computeAllTasksList() { 816250608a5cd08862f4752a924d51710805850db8aWinson ArrayList<Task> tasks = new ArrayList<>(); 817250608a5cd08862f4752a924d51710805850db8aWinson tasks.addAll(mStackTaskList.getTasks()); 818250608a5cd08862f4752a924d51710805850db8aWinson return tasks; 819303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 820303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 82136a5a2c7003ef8157f276b411c3fda47ad2f75e3Winson /** 8224b057c6787624b75613769a857ccdf51114bb7f2Winson * Returns the number of stack and freeform tasks. 823250608a5cd08862f4752a924d51710805850db8aWinson */ 8244b057c6787624b75613769a857ccdf51114bb7f2Winson public int getTaskCount() { 825250608a5cd08862f4752a924d51710805850db8aWinson return mStackTaskList.size(); 826250608a5cd08862f4752a924d51710805850db8aWinson } 827250608a5cd08862f4752a924d51710805850db8aWinson 828250608a5cd08862f4752a924d51710805850db8aWinson /** 8294b057c6787624b75613769a857ccdf51114bb7f2Winson * Returns the number of stack tasks. 8304b057c6787624b75613769a857ccdf51114bb7f2Winson */ 8314b057c6787624b75613769a857ccdf51114bb7f2Winson public int getStackTaskCount() { 8324b057c6787624b75613769a857ccdf51114bb7f2Winson ArrayList<Task> tasks = mStackTaskList.getTasks(); 8334b057c6787624b75613769a857ccdf51114bb7f2Winson int stackCount = 0; 8344b057c6787624b75613769a857ccdf51114bb7f2Winson int taskCount = tasks.size(); 8354b057c6787624b75613769a857ccdf51114bb7f2Winson for (int i = 0; i < taskCount; i++) { 8364b057c6787624b75613769a857ccdf51114bb7f2Winson Task task = tasks.get(i); 8374b057c6787624b75613769a857ccdf51114bb7f2Winson if (!task.isFreeformTask()) { 8384b057c6787624b75613769a857ccdf51114bb7f2Winson stackCount++; 8394b057c6787624b75613769a857ccdf51114bb7f2Winson } 8404b057c6787624b75613769a857ccdf51114bb7f2Winson } 8414b057c6787624b75613769a857ccdf51114bb7f2Winson return stackCount; 8424b057c6787624b75613769a857ccdf51114bb7f2Winson } 8434b057c6787624b75613769a857ccdf51114bb7f2Winson 8444b057c6787624b75613769a857ccdf51114bb7f2Winson /** 8454b057c6787624b75613769a857ccdf51114bb7f2Winson * Returns the number of freeform tasks. 846f0d1c44a59a10707baa0cca8dd377302260710c1Winson */ 8474b057c6787624b75613769a857ccdf51114bb7f2Winson public int getFreeformTaskCount() { 848f0d1c44a59a10707baa0cca8dd377302260710c1Winson ArrayList<Task> tasks = mStackTaskList.getTasks(); 849f0d1c44a59a10707baa0cca8dd377302260710c1Winson int freeformCount = 0; 850f0d1c44a59a10707baa0cca8dd377302260710c1Winson int taskCount = tasks.size(); 851f0d1c44a59a10707baa0cca8dd377302260710c1Winson for (int i = 0; i < taskCount; i++) { 852f0d1c44a59a10707baa0cca8dd377302260710c1Winson Task task = tasks.get(i); 853f0d1c44a59a10707baa0cca8dd377302260710c1Winson if (task.isFreeformTask()) { 854f0d1c44a59a10707baa0cca8dd377302260710c1Winson freeformCount++; 855f0d1c44a59a10707baa0cca8dd377302260710c1Winson } 856f0d1c44a59a10707baa0cca8dd377302260710c1Winson } 857f0d1c44a59a10707baa0cca8dd377302260710c1Winson return freeformCount; 858f0d1c44a59a10707baa0cca8dd377302260710c1Winson } 859f0d1c44a59a10707baa0cca8dd377302260710c1Winson 860f0d1c44a59a10707baa0cca8dd377302260710c1Winson /** 861250608a5cd08862f4752a924d51710805850db8aWinson * Returns the task in stack tasks which is the launch target. 86236a5a2c7003ef8157f276b411c3fda47ad2f75e3Winson */ 86336a5a2c7003ef8157f276b411c3fda47ad2f75e3Winson public Task getLaunchTarget() { 864250608a5cd08862f4752a924d51710805850db8aWinson ArrayList<Task> tasks = mStackTaskList.getTasks(); 86536a5a2c7003ef8157f276b411c3fda47ad2f75e3Winson int taskCount = tasks.size(); 86636a5a2c7003ef8157f276b411c3fda47ad2f75e3Winson for (int i = 0; i < taskCount; i++) { 86736a5a2c7003ef8157f276b411c3fda47ad2f75e3Winson Task task = tasks.get(i); 86836a5a2c7003ef8157f276b411c3fda47ad2f75e3Winson if (task.isLaunchTarget) { 86936a5a2c7003ef8157f276b411c3fda47ad2f75e3Winson return task; 87036a5a2c7003ef8157f276b411c3fda47ad2f75e3Winson } 87136a5a2c7003ef8157f276b411c3fda47ad2f75e3Winson } 87236a5a2c7003ef8157f276b411c3fda47ad2f75e3Winson return null; 87336a5a2c7003ef8157f276b411c3fda47ad2f75e3Winson } 87436a5a2c7003ef8157f276b411c3fda47ad2f75e3Winson 875bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet /** 876b502690e2d0a120993279a6fe800ad07dccc8872Winson Chung * Returns whether the next launch target should actually be the PiP task. 877b502690e2d0a120993279a6fe800ad07dccc8872Winson Chung */ 878b502690e2d0a120993279a6fe800ad07dccc8872Winson Chung public boolean isNextLaunchTargetPip(long lastPipTime) { 879b502690e2d0a120993279a6fe800ad07dccc8872Winson Chung Task launchTarget = getLaunchTarget(); 880b502690e2d0a120993279a6fe800ad07dccc8872Winson Chung Task nextLaunchTarget = getNextLaunchTargetRaw(); 881b502690e2d0a120993279a6fe800ad07dccc8872Winson Chung if (nextLaunchTarget != null && lastPipTime > 0) { 882b502690e2d0a120993279a6fe800ad07dccc8872Winson Chung // If the PiP time is more recent than the next launch target, then launch the PiP task 883b502690e2d0a120993279a6fe800ad07dccc8872Winson Chung return lastPipTime > nextLaunchTarget.key.lastActiveTime; 884b502690e2d0a120993279a6fe800ad07dccc8872Winson Chung } else if (launchTarget != null && lastPipTime > 0 && getTaskCount() == 1) { 885b502690e2d0a120993279a6fe800ad07dccc8872Winson Chung // Otherwise, if there is no next launch target, but there is a PiP, then launch 886b502690e2d0a120993279a6fe800ad07dccc8872Winson Chung // the PiP task 887b502690e2d0a120993279a6fe800ad07dccc8872Winson Chung return true; 888b502690e2d0a120993279a6fe800ad07dccc8872Winson Chung } 889b502690e2d0a120993279a6fe800ad07dccc8872Winson Chung return false; 890b502690e2d0a120993279a6fe800ad07dccc8872Winson Chung } 891b502690e2d0a120993279a6fe800ad07dccc8872Winson Chung 892b502690e2d0a120993279a6fe800ad07dccc8872Winson Chung /** 893bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet * Returns the task in stack tasks which should be launched next if Recents are toggled 894b502690e2d0a120993279a6fe800ad07dccc8872Winson Chung * again, or null if there is no task to be launched. Callers should check 895b502690e2d0a120993279a6fe800ad07dccc8872Winson Chung * {@link #isNextLaunchTargetPip(long)} before fetching the next raw launch target from the 896b502690e2d0a120993279a6fe800ad07dccc8872Winson Chung * stack. 897bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet */ 898bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet public Task getNextLaunchTarget() { 899b502690e2d0a120993279a6fe800ad07dccc8872Winson Chung Task nextLaunchTarget = getNextLaunchTargetRaw(); 900b502690e2d0a120993279a6fe800ad07dccc8872Winson Chung if (nextLaunchTarget != null) { 901b502690e2d0a120993279a6fe800ad07dccc8872Winson Chung return nextLaunchTarget; 902b502690e2d0a120993279a6fe800ad07dccc8872Winson Chung } 903b502690e2d0a120993279a6fe800ad07dccc8872Winson Chung return getStackTasks().get(getTaskCount() - 1); 904b502690e2d0a120993279a6fe800ad07dccc8872Winson Chung } 905b502690e2d0a120993279a6fe800ad07dccc8872Winson Chung 906b502690e2d0a120993279a6fe800ad07dccc8872Winson Chung private Task getNextLaunchTargetRaw() { 907bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet int taskCount = getTaskCount(); 908bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet if (taskCount == 0) { 909bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet return null; 910bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet } 911bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet int launchTaskIndex = indexOfStackTask(getLaunchTarget()); 912b502690e2d0a120993279a6fe800ad07dccc8872Winson Chung if (launchTaskIndex != -1 && launchTaskIndex > 0) { 913b502690e2d0a120993279a6fe800ad07dccc8872Winson Chung return getStackTasks().get(launchTaskIndex - 1); 914bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet } 915b502690e2d0a120993279a6fe800ad07dccc8872Winson Chung return null; 916bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet } 917bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet 918303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung /** Returns the index of this task in this current task stack */ 919250608a5cd08862f4752a924d51710805850db8aWinson public int indexOfStackTask(Task t) { 920250608a5cd08862f4752a924d51710805850db8aWinson return mStackTaskList.indexOf(t); 921303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 922303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 923b1f749906f5c27114d02ea0c3f8ce0dcea08fd3fWinson Chung /** Finds the task with the specified task id. */ 924b1f749906f5c27114d02ea0c3f8ce0dcea08fd3fWinson Chung public Task findTaskWithId(int taskId) { 925250608a5cd08862f4752a924d51710805850db8aWinson ArrayList<Task> tasks = computeAllTasksList(); 926d72c315d5eed3a684eee303364b97129cb821689Winson int taskCount = tasks.size(); 927d72c315d5eed3a684eee303364b97129cb821689Winson for (int i = 0; i < taskCount; i++) { 928d72c315d5eed3a684eee303364b97129cb821689Winson Task task = tasks.get(i); 929b1f749906f5c27114d02ea0c3f8ce0dcea08fd3fWinson Chung if (task.key.id == taskId) { 930b1f749906f5c27114d02ea0c3f8ce0dcea08fd3fWinson Chung return task; 931b1f749906f5c27114d02ea0c3f8ce0dcea08fd3fWinson Chung } 932b1f749906f5c27114d02ea0c3f8ce0dcea08fd3fWinson Chung } 933b1f749906f5c27114d02ea0c3f8ce0dcea08fd3fWinson Chung return null; 934b1f749906f5c27114d02ea0c3f8ce0dcea08fd3fWinson Chung } 935b1f749906f5c27114d02ea0c3f8ce0dcea08fd3fWinson Chung 936ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung /******** Grouping ********/ 937ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung 938ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung /** Adds a group to the set */ 939ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung public void addGroup(TaskGrouping group) { 940ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung mGroups.add(group); 941ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung mAffinitiesGroups.put(group.affiliation, group); 942ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 943ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung 944ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung public void removeGroup(TaskGrouping group) { 945ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung mGroups.remove(group); 946ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung mAffinitiesGroups.remove(group.affiliation); 947ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 948ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung 949ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung /** Returns the group with the specified affiliation. */ 950083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung public TaskGrouping getGroupWithAffiliation(int affiliation) { 951ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung return mAffinitiesGroups.get(affiliation); 952ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 953ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung 954ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung /** 9558873754f66527d2cc9feab295dd4eef23298212aWinson * Temporary: This method will simulate affiliation groups 956ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung */ 9578873754f66527d2cc9feab295dd4eef23298212aWinson void createAffiliatedGroupings(Context context) { 9588873754f66527d2cc9feab295dd4eef23298212aWinson mGroups.clear(); 9598873754f66527d2cc9feab295dd4eef23298212aWinson mAffinitiesGroups.clear(); 9608873754f66527d2cc9feab295dd4eef23298212aWinson 9616e6bd8776f850a21a3733a03dfa32b04f06163d9Winson if (RecentsDebugFlags.Static.EnableMockTaskGroups) { 9625500390a006f2bbea565068234774a36cea076c0Winson ArrayMap<Task.TaskKey, Task> taskMap = new ArrayMap<>(); 963ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung // Sort all tasks by increasing firstActiveTime of the task 964250608a5cd08862f4752a924d51710805850db8aWinson ArrayList<Task> tasks = mStackTaskList.getTasks(); 965ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung Collections.sort(tasks, new Comparator<Task>() { 966ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung @Override 967ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung public int compare(Task task, Task task2) { 96816bc2a7f379edd7796bb5aa4400e1b7c14376a08Winson Chung return Long.compare(task.key.firstActiveTime, task2.key.firstActiveTime); 969ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 970ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung }); 971ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung // Create groups when sequential packages are the same 972ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung NamedCounter counter = new NamedCounter("task-group", ""); 973ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung int taskCount = tasks.size(); 974ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung String prevPackage = ""; 975083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung int prevAffiliation = -1; 976a433fa9c17772f563163ff7db177d091d6aebd5bWinson Chung Random r = new Random(); 9776e6bd8776f850a21a3733a03dfa32b04f06163d9Winson int groupCountDown = RecentsDebugFlags.Static.MockTaskGroupsTaskCount; 978ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung for (int i = 0; i < taskCount; i++) { 979ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung Task t = tasks.get(i); 980e7f138c7f0a190c86cec10fb32fa106aacae4093Winson String packageName = t.key.getComponent().getPackageName(); 981a433fa9c17772f563163ff7db177d091d6aebd5bWinson Chung packageName = "pkg"; 982ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung TaskGrouping group; 983a433fa9c17772f563163ff7db177d091d6aebd5bWinson Chung if (packageName.equals(prevPackage) && groupCountDown > 0) { 984ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung group = getGroupWithAffiliation(prevAffiliation); 985a433fa9c17772f563163ff7db177d091d6aebd5bWinson Chung groupCountDown--; 986ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } else { 987083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung int affiliation = IndividualTaskIdOffset + t.key.id; 988ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung group = new TaskGrouping(affiliation); 989ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung addGroup(group); 990ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung prevAffiliation = affiliation; 991ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung prevPackage = packageName; 9926e6bd8776f850a21a3733a03dfa32b04f06163d9Winson groupCountDown = RecentsDebugFlags.Static.MockTaskGroupsTaskCount; 993ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 994ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung group.addTask(t); 995ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung taskMap.put(t.key, t); 996ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 997ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung // Sort groups by increasing latestActiveTime of the group 998ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung Collections.sort(mGroups, new Comparator<TaskGrouping>() { 999ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung @Override 1000ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung public int compare(TaskGrouping taskGrouping, TaskGrouping taskGrouping2) { 1001509d0d0c9e2ee165d04e898fea59f8941ac7138dWinson Chung return Long.compare(taskGrouping.latestActiveTimeInGroup, 1002ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung taskGrouping2.latestActiveTimeInGroup); 1003ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 1004ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung }); 10052b9ef6548be89d36ea7629f4a3d8ba7bba1422ceWinson Chung // Sort group tasks by increasing firstActiveTime of the task, and also build a new list 10062b9ef6548be89d36ea7629f4a3d8ba7bba1422ceWinson Chung // of tasks 1007ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung int taskIndex = 0; 1008ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung int groupCount = mGroups.size(); 1009ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung for (int i = 0; i < groupCount; i++) { 1010ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung TaskGrouping group = mGroups.get(i); 1011083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung Collections.sort(group.mTaskKeys, new Comparator<Task.TaskKey>() { 1012ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung @Override 1013ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung public int compare(Task.TaskKey taskKey, Task.TaskKey taskKey2) { 1014509d0d0c9e2ee165d04e898fea59f8941ac7138dWinson Chung return Long.compare(taskKey.firstActiveTime, taskKey2.firstActiveTime); 1015ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 1016ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung }); 1017083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung ArrayList<Task.TaskKey> groupTasks = group.mTaskKeys; 1018ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung int groupTaskCount = groupTasks.size(); 1019ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung for (int j = 0; j < groupTaskCount; j++) { 1020ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung tasks.set(taskIndex, taskMap.get(groupTasks.get(j))); 1021ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung taskIndex++; 1022ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 1023ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 1024250608a5cd08862f4752a924d51710805850db8aWinson mStackTaskList.set(tasks); 1025ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } else { 1026083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung // Create the task groups 10275500390a006f2bbea565068234774a36cea076c0Winson ArrayMap<Task.TaskKey, Task> tasksMap = new ArrayMap<>(); 1028250608a5cd08862f4752a924d51710805850db8aWinson ArrayList<Task> tasks = mStackTaskList.getTasks(); 1029ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung int taskCount = tasks.size(); 1030ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung for (int i = 0; i < taskCount; i++) { 1031ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung Task t = tasks.get(i); 1032083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung TaskGrouping group; 103365c851e6e9e08656744b6f66d3da188e3283b17dWinson if (RecentsDebugFlags.Static.EnableAffiliatedTaskGroups) { 103465c851e6e9e08656744b6f66d3da188e3283b17dWinson int affiliation = t.affiliationTaskId > 0 ? t.affiliationTaskId : 103565c851e6e9e08656744b6f66d3da188e3283b17dWinson IndividualTaskIdOffset + t.key.id; 103665c851e6e9e08656744b6f66d3da188e3283b17dWinson if (mAffinitiesGroups.containsKey(affiliation)) { 103765c851e6e9e08656744b6f66d3da188e3283b17dWinson group = getGroupWithAffiliation(affiliation); 103865c851e6e9e08656744b6f66d3da188e3283b17dWinson } else { 103965c851e6e9e08656744b6f66d3da188e3283b17dWinson group = new TaskGrouping(affiliation); 104065c851e6e9e08656744b6f66d3da188e3283b17dWinson addGroup(group); 104165c851e6e9e08656744b6f66d3da188e3283b17dWinson } 1042083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung } else { 104365c851e6e9e08656744b6f66d3da188e3283b17dWinson group = new TaskGrouping(t.key.id); 1044083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung addGroup(group); 1045083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung } 1046ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung group.addTask(t); 1047ec396d6399c5c31d697d81e94aff459e9771b0c6Winson Chung tasksMap.put(t.key, t); 1048ec396d6399c5c31d697d81e94aff459e9771b0c6Winson Chung } 1049ec396d6399c5c31d697d81e94aff459e9771b0c6Winson Chung // Update the task colors for each of the groups 105035f3050959e43bf378f9a0adcaef13729206c7e4Winson float minAlpha = context.getResources().getFloat( 105135f3050959e43bf378f9a0adcaef13729206c7e4Winson R.dimen.recents_task_affiliation_color_min_alpha_percentage); 1052ec396d6399c5c31d697d81e94aff459e9771b0c6Winson Chung int taskGroupCount = mGroups.size(); 1053ec396d6399c5c31d697d81e94aff459e9771b0c6Winson Chung for (int i = 0; i < taskGroupCount; i++) { 1054ec396d6399c5c31d697d81e94aff459e9771b0c6Winson Chung TaskGrouping group = mGroups.get(i); 1055ec396d6399c5c31d697d81e94aff459e9771b0c6Winson Chung taskCount = group.getTaskCount(); 1056ec396d6399c5c31d697d81e94aff459e9771b0c6Winson Chung // Ignore the groups that only have one task 1057ec396d6399c5c31d697d81e94aff459e9771b0c6Winson Chung if (taskCount <= 1) continue; 1058ec396d6399c5c31d697d81e94aff459e9771b0c6Winson Chung // Calculate the group color distribution 1059296278a0679375b8c43962a9e3c9bb4e8ab201e7Winson Chung int affiliationColor = tasksMap.get(group.mTaskKeys.get(0)).affiliationColor; 1060ec396d6399c5c31d697d81e94aff459e9771b0c6Winson Chung float alphaStep = (1f - minAlpha) / taskCount; 1061ec396d6399c5c31d697d81e94aff459e9771b0c6Winson Chung float alpha = 1f; 1062ec396d6399c5c31d697d81e94aff459e9771b0c6Winson Chung for (int j = 0; j < taskCount; j++) { 1063ec396d6399c5c31d697d81e94aff459e9771b0c6Winson Chung Task t = tasksMap.get(group.mTaskKeys.get(j)); 1064a0e88b5013d708ac6ed6518817d83c64c87ae4b1Winson Chung t.colorPrimary = Utilities.getColorWithOverlay(affiliationColor, Color.WHITE, 1065a0e88b5013d708ac6ed6518817d83c64c87ae4b1Winson Chung alpha); 1066ec396d6399c5c31d697d81e94aff459e9771b0c6Winson Chung alpha -= alphaStep; 1067ec396d6399c5c31d697d81e94aff459e9771b0c6Winson Chung } 1068ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 1069ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 1070ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 1071ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung 1072e7f138c7f0a190c86cec10fb32fa106aacae4093Winson /** 1073e7f138c7f0a190c86cec10fb32fa106aacae4093Winson * Computes the components of tasks in this stack that have been removed as a result of a change 1074e7f138c7f0a190c86cec10fb32fa106aacae4093Winson * in the specified package. 1075e7f138c7f0a190c86cec10fb32fa106aacae4093Winson */ 10765500390a006f2bbea565068234774a36cea076c0Winson public ArraySet<ComponentName> computeComponentsRemoved(String packageName, int userId) { 1077e7f138c7f0a190c86cec10fb32fa106aacae4093Winson // Identify all the tasks that should be removed as a result of the package being removed. 1078e7f138c7f0a190c86cec10fb32fa106aacae4093Winson // Using a set to ensure that we callback once per unique component. 1079e7f138c7f0a190c86cec10fb32fa106aacae4093Winson SystemServicesProxy ssp = Recents.getSystemServices(); 10805500390a006f2bbea565068234774a36cea076c0Winson ArraySet<ComponentName> existingComponents = new ArraySet<>(); 10815500390a006f2bbea565068234774a36cea076c0Winson ArraySet<ComponentName> removedComponents = new ArraySet<>(); 1082e7f138c7f0a190c86cec10fb32fa106aacae4093Winson ArrayList<Task.TaskKey> taskKeys = getTaskKeys(); 1083d72c315d5eed3a684eee303364b97129cb821689Winson int taskKeyCount = taskKeys.size(); 1084d72c315d5eed3a684eee303364b97129cb821689Winson for (int i = 0; i < taskKeyCount; i++) { 1085d72c315d5eed3a684eee303364b97129cb821689Winson Task.TaskKey t = taskKeys.get(i); 1086d72c315d5eed3a684eee303364b97129cb821689Winson 1087e7f138c7f0a190c86cec10fb32fa106aacae4093Winson // Skip if this doesn't apply to the current user 1088e7f138c7f0a190c86cec10fb32fa106aacae4093Winson if (t.userId != userId) continue; 1089e7f138c7f0a190c86cec10fb32fa106aacae4093Winson 1090e7f138c7f0a190c86cec10fb32fa106aacae4093Winson ComponentName cn = t.getComponent(); 1091e7f138c7f0a190c86cec10fb32fa106aacae4093Winson if (cn.getPackageName().equals(packageName)) { 1092e7f138c7f0a190c86cec10fb32fa106aacae4093Winson if (existingComponents.contains(cn)) { 1093e7f138c7f0a190c86cec10fb32fa106aacae4093Winson // If we know that the component still exists in the package, then skip 1094e7f138c7f0a190c86cec10fb32fa106aacae4093Winson continue; 1095e7f138c7f0a190c86cec10fb32fa106aacae4093Winson } 1096e7f138c7f0a190c86cec10fb32fa106aacae4093Winson if (ssp.getActivityInfo(cn, userId) != null) { 1097e7f138c7f0a190c86cec10fb32fa106aacae4093Winson existingComponents.add(cn); 1098e7f138c7f0a190c86cec10fb32fa106aacae4093Winson } else { 1099e7f138c7f0a190c86cec10fb32fa106aacae4093Winson removedComponents.add(cn); 1100e7f138c7f0a190c86cec10fb32fa106aacae4093Winson } 1101e7f138c7f0a190c86cec10fb32fa106aacae4093Winson } 1102e7f138c7f0a190c86cec10fb32fa106aacae4093Winson } 1103e7f138c7f0a190c86cec10fb32fa106aacae4093Winson return removedComponents; 1104e7f138c7f0a190c86cec10fb32fa106aacae4093Winson } 1105e7f138c7f0a190c86cec10fb32fa106aacae4093Winson 1106303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung @Override 1107303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung public String toString() { 11088873754f66527d2cc9feab295dd4eef23298212aWinson String str = "Stack Tasks (" + mStackTaskList.size() + "):\n"; 1109d72c315d5eed3a684eee303364b97129cb821689Winson ArrayList<Task> tasks = mStackTaskList.getTasks(); 1110d72c315d5eed3a684eee303364b97129cb821689Winson int taskCount = tasks.size(); 1111d72c315d5eed3a684eee303364b97129cb821689Winson for (int i = 0; i < taskCount; i++) { 1112d72c315d5eed3a684eee303364b97129cb821689Winson str += " " + tasks.get(i).toString() + "\n"; 1113250608a5cd08862f4752a924d51710805850db8aWinson } 1114303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung return str; 1115303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 1116062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung 1117062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung /** 1118062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung * Given a list of tasks, returns a map of each task's key to the task. 1119062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung */ 11205500390a006f2bbea565068234774a36cea076c0Winson private ArrayMap<Task.TaskKey, Task> createTaskKeyMapFromList(List<Task> tasks) { 11215500390a006f2bbea565068234774a36cea076c0Winson ArrayMap<Task.TaskKey, Task> map = new ArrayMap<>(tasks.size()); 1122062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung int taskCount = tasks.size(); 1123062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung for (int i = 0; i < taskCount; i++) { 1124062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung Task task = tasks.get(i); 1125062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung map.put(task.key, task); 1126062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung } 1127062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung return map; 1128062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung } 1129d72c315d5eed3a684eee303364b97129cb821689Winson 1130d72c315d5eed3a684eee303364b97129cb821689Winson public void dump(String prefix, PrintWriter writer) { 1131d72c315d5eed3a684eee303364b97129cb821689Winson String innerPrefix = prefix + " "; 1132d72c315d5eed3a684eee303364b97129cb821689Winson 1133d72c315d5eed3a684eee303364b97129cb821689Winson writer.print(prefix); writer.print(TAG); 1134d72c315d5eed3a684eee303364b97129cb821689Winson writer.print(" numStackTasks="); writer.print(mStackTaskList.size()); 1135d72c315d5eed3a684eee303364b97129cb821689Winson writer.println(); 1136d72c315d5eed3a684eee303364b97129cb821689Winson ArrayList<Task> tasks = mStackTaskList.getTasks(); 1137d72c315d5eed3a684eee303364b97129cb821689Winson int taskCount = tasks.size(); 1138d72c315d5eed3a684eee303364b97129cb821689Winson for (int i = 0; i < taskCount; i++) { 1139d72c315d5eed3a684eee303364b97129cb821689Winson tasks.get(i).dump(innerPrefix, writer); 1140d72c315d5eed3a684eee303364b97129cb821689Winson } 1141d72c315d5eed3a684eee303364b97129cb821689Winson } 1142062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung} 1143