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, 2326c8217ab3072fa65851316a922b482506b3c2a4cWinson AnimationProps animation, boolean fromDockGesture); 233a1ededd056d51532ab18354f17f8065ec1134535Winson 234a1ededd056d51532ab18354f17f8065ec1134535Winson /** 2353b6ba1ab144c53752841869627a1b9f6d357c404Winson * Notifies when all tasks have been removed from the stack. 2363b6ba1ab144c53752841869627a1b9f6d357c404Winson */ 2373b6ba1ab144c53752841869627a1b9f6d357c404Winson void onStackTasksRemoved(TaskStack stack); 2383b6ba1ab144c53752841869627a1b9f6d357c404Winson 2393b6ba1ab144c53752841869627a1b9f6d357c404Winson /** 240a1ededd056d51532ab18354f17f8065ec1134535Winson * Notifies when tasks in the stack have been updated. 241a1ededd056d51532ab18354f17f8065ec1134535Winson */ 242a1ededd056d51532ab18354f17f8065ec1134535Winson void onStackTasksUpdated(TaskStack stack); 24304dfe0d26b944324ee920001f40d74cff47281d6Winson Chung } 24404dfe0d26b944324ee920001f40d74cff47281d6Winson Chung 245250608a5cd08862f4752a924d51710805850db8aWinson /** 246250608a5cd08862f4752a924d51710805850db8aWinson * The various possible dock states when dragging and dropping a task. 247250608a5cd08862f4752a924d51710805850db8aWinson */ 248f0d1c44a59a10707baa0cca8dd377302260710c1Winson public static class DockState implements DropTarget { 249f0d1c44a59a10707baa0cca8dd377302260710c1Winson 25099ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson // The rotation to apply to the hint text 25199ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson @Retention(RetentionPolicy.SOURCE) 25299ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson @IntDef({HORIZONTAL, VERTICAL}) 25399ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson public @interface TextOrientation {} 25499ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson private static final int HORIZONTAL = 0; 25599ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson private static final int VERTICAL = 1; 25699ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson 2573f32e7eba7aec02edbf542cc11eee13264a5abf2Winson private static final int DOCK_AREA_ALPHA = 80; 25899ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson public static final DockState NONE = new DockState(DOCKED_INVALID, -1, 80, 255, HORIZONTAL, 25999ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson null, null, null); 2603e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson public static final DockState LEFT = new DockState(DOCKED_LEFT, 26199ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT, DOCK_AREA_ALPHA, 0, VERTICAL, 2623e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson new RectF(0, 0, 0.125f, 1), new RectF(0, 0, 0.125f, 1), 2633e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson new RectF(0, 0, 0.5f, 1)); 2643e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson public static final DockState TOP = new DockState(DOCKED_TOP, 26599ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT, DOCK_AREA_ALPHA, 0, HORIZONTAL, 2663e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson new RectF(0, 0, 1, 0.125f), new RectF(0, 0, 1, 0.125f), 2673e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson new RectF(0, 0, 1, 0.5f)); 2683e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson public static final DockState RIGHT = new DockState(DOCKED_RIGHT, 26999ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson DOCKED_STACK_CREATE_MODE_BOTTOM_OR_RIGHT, DOCK_AREA_ALPHA, 0, VERTICAL, 2703e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson new RectF(0.875f, 0, 1, 1), new RectF(0.875f, 0, 1, 1), 2713e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson new RectF(0.5f, 0, 1, 1)); 2723e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson public static final DockState BOTTOM = new DockState(DOCKED_BOTTOM, 27399ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson DOCKED_STACK_CREATE_MODE_BOTTOM_OR_RIGHT, DOCK_AREA_ALPHA, 0, HORIZONTAL, 2743e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson new RectF(0, 0.875f, 1, 1), new RectF(0, 0.875f, 1, 1), 2753e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson new RectF(0, 0.5f, 1, 1)); 276eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson 277eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson @Override 2783e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson public boolean acceptsDrop(int x, int y, int width, int height, boolean isCurrentTarget) { 2793e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson return isCurrentTarget 2803e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson ? areaContainsPoint(expandedTouchDockArea, width, height, x, y) 2813e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson : areaContainsPoint(touchArea, width, height, x, y); 282eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson } 283be7607af8875236b9cf7bdb5f5aa089c207529afWinson 284882072baacaee4ecd43f0209b691a9af746462f2Winson // Represents the view state of this dock state 28599ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson public static class ViewState { 28699ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson private static final IntProperty<ViewState> HINT_ALPHA = 28799ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson new IntProperty<ViewState>("drawableAlpha") { 28899ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson @Override 28999ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson public void setValue(ViewState object, int alpha) { 29099ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson object.mHintTextAlpha = alpha; 29199ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson object.dockAreaOverlay.invalidateSelf(); 29299ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson } 29399ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson 29499ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson @Override 29599ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson public Integer get(ViewState object) { 29699ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson return object.mHintTextAlpha; 29799ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson } 29899ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson }; 29999ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson 300882072baacaee4ecd43f0209b691a9af746462f2Winson public final int dockAreaAlpha; 301882072baacaee4ecd43f0209b691a9af746462f2Winson public final ColorDrawable dockAreaOverlay; 30299ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson public final int hintTextAlpha; 30399ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson public final int hintTextOrientation; 30499ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson 30599ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson private final int mHintTextResId; 30699ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson private String mHintText; 30799ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson private Paint mHintTextPaint; 30899ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson private Point mHintTextBounds = new Point(); 30999ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson private int mHintTextAlpha = 255; 31099ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson private AnimatorSet mDockAreaOverlayAnimator; 31199ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson private Rect mTmpRect = new Rect(); 31299ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson 31399ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson private ViewState(int areaAlpha, int hintAlpha, @TextOrientation int hintOrientation, 31499ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson int hintTextResId) { 31599ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson dockAreaAlpha = areaAlpha; 316882072baacaee4ecd43f0209b691a9af746462f2Winson dockAreaOverlay = new ColorDrawable(0xFFffffff); 317882072baacaee4ecd43f0209b691a9af746462f2Winson dockAreaOverlay.setAlpha(0); 31899ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson hintTextAlpha = hintAlpha; 31999ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson hintTextOrientation = hintOrientation; 32099ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson mHintTextResId = hintTextResId; 32199ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson mHintTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 32299ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson mHintTextPaint.setColor(Color.WHITE); 32399ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson } 32499ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson 32599ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson /** 32699ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson * Updates the view state with the given context. 32799ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson */ 32899ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson public void update(Context context) { 32999ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson Resources res = context.getResources(); 33099ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson mHintText = context.getString(mHintTextResId); 33199ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson mHintTextPaint.setTextSize(res.getDimensionPixelSize( 33299ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson R.dimen.recents_drag_hint_text_size)); 33399ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson mHintTextPaint.getTextBounds(mHintText, 0, mHintText.length(), mTmpRect); 33499ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson mHintTextBounds.set((int) mHintTextPaint.measureText(mHintText), mTmpRect.height()); 33599ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson } 33699ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson 33799ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson /** 33899ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson * Draws the current view state. 33999ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson */ 34099ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson public void draw(Canvas canvas) { 34199ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson // Draw the overlay background 34299ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson if (dockAreaOverlay.getAlpha() > 0) { 34399ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson dockAreaOverlay.draw(canvas); 34499ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson } 34599ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson 34699ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson // Draw the hint text 34799ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson if (mHintTextAlpha > 0) { 34899ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson Rect bounds = dockAreaOverlay.getBounds(); 34999ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson int x = bounds.left + (bounds.width() - mHintTextBounds.x) / 2; 35099ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson int y = bounds.top + (bounds.height() + mHintTextBounds.y) / 2; 35199ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson mHintTextPaint.setAlpha(mHintTextAlpha); 35299ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson if (hintTextOrientation == VERTICAL) { 35399ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson canvas.save(); 35499ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson canvas.rotate(-90f, bounds.centerX(), bounds.centerY()); 35599ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson } 35699ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson canvas.drawText(mHintText, x, y, mHintTextPaint); 35799ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson if (hintTextOrientation == VERTICAL) { 35899ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson canvas.restore(); 35999ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson } 36099ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson } 361882072baacaee4ecd43f0209b691a9af746462f2Winson } 362882072baacaee4ecd43f0209b691a9af746462f2Winson 363882072baacaee4ecd43f0209b691a9af746462f2Winson /** 3643e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson * Creates a new bounds and alpha animation. 365882072baacaee4ecd43f0209b691a9af746462f2Winson */ 36699ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson public void startAnimation(Rect bounds, int areaAlpha, int hintAlpha, int duration, 3673e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson Interpolator interpolator, boolean animateAlpha, boolean animateBounds) { 36899ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson if (mDockAreaOverlayAnimator != null) { 36999ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson mDockAreaOverlayAnimator.cancel(); 3703e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson } 3713e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson 3723f32e7eba7aec02edbf542cc11eee13264a5abf2Winson ObjectAnimator anim; 3733e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson ArrayList<Animator> animators = new ArrayList<>(); 37499ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson if (dockAreaOverlay.getAlpha() != areaAlpha) { 3753e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson if (animateAlpha) { 3763f32e7eba7aec02edbf542cc11eee13264a5abf2Winson anim = ObjectAnimator.ofInt(dockAreaOverlay, 3773f32e7eba7aec02edbf542cc11eee13264a5abf2Winson Utilities.DRAWABLE_ALPHA, dockAreaOverlay.getAlpha(), areaAlpha); 3783f32e7eba7aec02edbf542cc11eee13264a5abf2Winson anim.setDuration(duration); 3793f32e7eba7aec02edbf542cc11eee13264a5abf2Winson anim.setInterpolator(interpolator); 3803f32e7eba7aec02edbf542cc11eee13264a5abf2Winson animators.add(anim); 38199ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson } else { 38299ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson dockAreaOverlay.setAlpha(areaAlpha); 38399ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson } 38499ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson } 38599ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson if (mHintTextAlpha != hintAlpha) { 38699ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson if (animateAlpha) { 3873f32e7eba7aec02edbf542cc11eee13264a5abf2Winson anim = ObjectAnimator.ofInt(this, HINT_ALPHA, mHintTextAlpha, 3883f32e7eba7aec02edbf542cc11eee13264a5abf2Winson hintAlpha); 3893f32e7eba7aec02edbf542cc11eee13264a5abf2Winson anim.setDuration(150); 3903f32e7eba7aec02edbf542cc11eee13264a5abf2Winson anim.setInterpolator(hintAlpha > mHintTextAlpha 3913f32e7eba7aec02edbf542cc11eee13264a5abf2Winson ? Interpolators.ALPHA_IN 3923f32e7eba7aec02edbf542cc11eee13264a5abf2Winson : Interpolators.ALPHA_OUT); 3933f32e7eba7aec02edbf542cc11eee13264a5abf2Winson animators.add(anim); 3943e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson } else { 39599ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson mHintTextAlpha = hintAlpha; 39699ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson dockAreaOverlay.invalidateSelf(); 3973e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson } 3983e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson } 3993e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson if (bounds != null && !dockAreaOverlay.getBounds().equals(bounds)) { 4003e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson if (animateBounds) { 4013e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson PropertyValuesHolder prop = PropertyValuesHolder.ofObject( 40267c79578f94646bade5d336af0d4491179c1b37dWinson Utilities.DRAWABLE_RECT, Utilities.RECT_EVALUATOR, 4033f32e7eba7aec02edbf542cc11eee13264a5abf2Winson new Rect(dockAreaOverlay.getBounds()), bounds); 4043f32e7eba7aec02edbf542cc11eee13264a5abf2Winson anim = ObjectAnimator.ofPropertyValuesHolder(dockAreaOverlay, prop); 4053f32e7eba7aec02edbf542cc11eee13264a5abf2Winson anim.setDuration(duration); 4063f32e7eba7aec02edbf542cc11eee13264a5abf2Winson anim.setInterpolator(interpolator); 4073f32e7eba7aec02edbf542cc11eee13264a5abf2Winson animators.add(anim); 4083e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson } else { 4093e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson dockAreaOverlay.setBounds(bounds); 410882072baacaee4ecd43f0209b691a9af746462f2Winson } 4113e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson } 4123e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson if (!animators.isEmpty()) { 41399ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson mDockAreaOverlayAnimator = new AnimatorSet(); 41499ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson mDockAreaOverlayAnimator.playTogether(animators); 41599ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson mDockAreaOverlayAnimator.start(); 416882072baacaee4ecd43f0209b691a9af746462f2Winson } 417882072baacaee4ecd43f0209b691a9af746462f2Winson } 418882072baacaee4ecd43f0209b691a9af746462f2Winson } 419882072baacaee4ecd43f0209b691a9af746462f2Winson 4203e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson public final int dockSide; 421be7607af8875236b9cf7bdb5f5aa089c207529afWinson public final int createMode; 422882072baacaee4ecd43f0209b691a9af746462f2Winson public final ViewState viewState; 423882072baacaee4ecd43f0209b691a9af746462f2Winson private final RectF touchArea; 4243e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson private final RectF dockArea; 4253e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson private final RectF expandedTouchDockArea; 426be7607af8875236b9cf7bdb5f5aa089c207529afWinson 427be7607af8875236b9cf7bdb5f5aa089c207529afWinson /** 428be7607af8875236b9cf7bdb5f5aa089c207529afWinson * @param createMode used to pass to ActivityManager to dock the task 429be7607af8875236b9cf7bdb5f5aa089c207529afWinson * @param touchArea the area in which touch will initiate this dock state 430eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson * @param dockArea the visible dock area 4313e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson * @param expandedTouchDockArea the areain which touch will continue to dock after entering 4323e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson * the initial touch area. This is also the new dock area to 4333e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson * draw. 434be7607af8875236b9cf7bdb5f5aa089c207529afWinson */ 43599ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson DockState(int dockSide, int createMode, int dockAreaAlpha, int hintTextAlpha, 43699ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson @TextOrientation int hintTextOrientation, RectF touchArea, RectF dockArea, 4373e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson RectF expandedTouchDockArea) { 4383e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson this.dockSide = dockSide; 439be7607af8875236b9cf7bdb5f5aa089c207529afWinson this.createMode = createMode; 44099ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson this.viewState = new ViewState(dockAreaAlpha, hintTextAlpha, hintTextOrientation, 44199ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson R.string.recents_drag_hint_message); 442be7607af8875236b9cf7bdb5f5aa089c207529afWinson this.dockArea = dockArea; 443882072baacaee4ecd43f0209b691a9af746462f2Winson this.touchArea = touchArea; 4443e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson this.expandedTouchDockArea = expandedTouchDockArea; 445be7607af8875236b9cf7bdb5f5aa089c207529afWinson } 446be7607af8875236b9cf7bdb5f5aa089c207529afWinson 447be7607af8875236b9cf7bdb5f5aa089c207529afWinson /** 44899ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson * Updates the dock state with the given context. 44999ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson */ 45099ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson public void update(Context context) { 45199ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson viewState.update(context); 45299ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson } 45399ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson 45499ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6Winson /** 4553e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson * Returns whether {@param x} and {@param y} are contained in the area scaled to the 456be7607af8875236b9cf7bdb5f5aa089c207529afWinson * given {@param width} and {@param height}. 457be7607af8875236b9cf7bdb5f5aa089c207529afWinson */ 4583e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson public boolean areaContainsPoint(RectF area, int width, int height, float x, float y) { 4593e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson int left = (int) (area.left * width); 4603e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson int top = (int) (area.top * height); 4613e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson int right = (int) (area.right * width); 4623e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson int bottom = (int) (area.bottom * height); 463be7607af8875236b9cf7bdb5f5aa089c207529afWinson return x >= left && y >= top && x <= right && y <= bottom; 464be7607af8875236b9cf7bdb5f5aa089c207529afWinson } 465be7607af8875236b9cf7bdb5f5aa089c207529afWinson 466be7607af8875236b9cf7bdb5f5aa089c207529afWinson /** 467be7607af8875236b9cf7bdb5f5aa089c207529afWinson * Returns the docked task bounds with the given {@param width} and {@param height}. 468be7607af8875236b9cf7bdb5f5aa089c207529afWinson */ 4693e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson public Rect getPreDockedBounds(int width, int height) { 470be7607af8875236b9cf7bdb5f5aa089c207529afWinson return new Rect((int) (dockArea.left * width), (int) (dockArea.top * height), 471be7607af8875236b9cf7bdb5f5aa089c207529afWinson (int) (dockArea.right * width), (int) (dockArea.bottom * height)); 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; 514fc48b072e8caa62849ee305f89f38d248d4a1dedWinson layoutAlgorithm.getTaskStackBounds(displayRect, windowRectOut, top, insets.right, 515fc48b072e8caa62849ee305f89f38d248d4a1dedWinson taskStackBounds); 5163e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson return taskStackBounds; 5173e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson } 518be7607af8875236b9cf7bdb5f5aa089c207529afWinson } 519be7607af8875236b9cf7bdb5f5aa089c207529afWinson 5206976f7bae901d81a354287088ae232ba7236f30eWinson // A comparator that sorts tasks by their freeform state 5216976f7bae901d81a354287088ae232ba7236f30eWinson private Comparator<Task> FREEFORM_COMPARATOR = new Comparator<Task>() { 522509d0d0c9e2ee165d04e898fea59f8941ac7138dWinson Chung @Override 523509d0d0c9e2ee165d04e898fea59f8941ac7138dWinson Chung public int compare(Task o1, Task o2) { 524509d0d0c9e2ee165d04e898fea59f8941ac7138dWinson Chung if (o1.isFreeformTask() && !o2.isFreeformTask()) { 525509d0d0c9e2ee165d04e898fea59f8941ac7138dWinson Chung return 1; 526509d0d0c9e2ee165d04e898fea59f8941ac7138dWinson Chung } else if (o2.isFreeformTask() && !o1.isFreeformTask()) { 527509d0d0c9e2ee165d04e898fea59f8941ac7138dWinson Chung return -1; 528509d0d0c9e2ee165d04e898fea59f8941ac7138dWinson Chung } 5296976f7bae901d81a354287088ae232ba7236f30eWinson return Long.compare(o1.temporarySortIndexInStack, o2.temporarySortIndexInStack); 530509d0d0c9e2ee165d04e898fea59f8941ac7138dWinson Chung } 531509d0d0c9e2ee165d04e898fea59f8941ac7138dWinson Chung }; 532509d0d0c9e2ee165d04e898fea59f8941ac7138dWinson Chung 533509d0d0c9e2ee165d04e898fea59f8941ac7138dWinson Chung 534083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung // The task offset to apply to a task id as a group affiliation 535083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung static final int IndividualTaskIdOffset = 1 << 16; 536083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung 537062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung ArrayList<Task> mRawTaskList = new ArrayList<>(); 538250608a5cd08862f4752a924d51710805850db8aWinson FilteredTaskList mStackTaskList = new FilteredTaskList(); 539303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung TaskStackCallbacks mCb; 540303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 5418f0e3a68cdd3b2403ff8a1677f90b998f4175f40Winson ArrayList<TaskGrouping> mGroups = new ArrayList<>(); 5425500390a006f2bbea565068234774a36cea076c0Winson ArrayMap<Integer, TaskGrouping> mAffinitiesGroups = new ArrayMap<>(); 5438f0e3a68cdd3b2403ff8a1677f90b998f4175f40Winson 5448f0e3a68cdd3b2403ff8a1677f90b998f4175f40Winson public TaskStack() { 5458f0e3a68cdd3b2403ff8a1677f90b998f4175f40Winson // Ensure that we only show non-docked tasks 546250608a5cd08862f4752a924d51710805850db8aWinson mStackTaskList.setFilter(new TaskFilter() { 5478f0e3a68cdd3b2403ff8a1677f90b998f4175f40Winson @Override 5482b9ef6548be89d36ea7629f4a3d8ba7bba1422ceWinson Chung public boolean acceptTask(SparseArray<Task> taskIdMap, Task t, int index) { 549d8f7431d0fe0f5449ca54a15392c3238aa645deaWinson if (RecentsDebugFlags.Static.EnableAffiliatedTaskGroups) { 550d8f7431d0fe0f5449ca54a15392c3238aa645deaWinson if (t.isAffiliatedTask()) { 551d8f7431d0fe0f5449ca54a15392c3238aa645deaWinson // If this task is affiliated with another parent in the stack, then the 552d8f7431d0fe0f5449ca54a15392c3238aa645deaWinson // historical state of this task depends on the state of the parent task 553d8f7431d0fe0f5449ca54a15392c3238aa645deaWinson Task parentTask = taskIdMap.get(t.affiliationTaskId); 554d8f7431d0fe0f5449ca54a15392c3238aa645deaWinson if (parentTask != null) { 555d8f7431d0fe0f5449ca54a15392c3238aa645deaWinson t = parentTask; 556d8f7431d0fe0f5449ca54a15392c3238aa645deaWinson } 5572b9ef6548be89d36ea7629f4a3d8ba7bba1422ceWinson Chung } 5582b9ef6548be89d36ea7629f4a3d8ba7bba1422ceWinson Chung } 5598f6ee48225ad1cdf966c8f406c85113b13833c7bWinson return t.isStackTask; 5608f0e3a68cdd3b2403ff8a1677f90b998f4175f40Winson } 5618f0e3a68cdd3b2403ff8a1677f90b998f4175f40Winson }); 5628f0e3a68cdd3b2403ff8a1677f90b998f4175f40Winson } 563303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 564d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung /** Sets the callbacks for this task stack. */ 565303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung public void setCallbacks(TaskStackCallbacks cb) { 566303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung mCb = cb; 567303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 568303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 569eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson /** 570eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson * Moves the given task to either the front of the freeform workspace or the stack. 571eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson */ 572eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson public void moveTaskToStack(Task task, int newStackId) { 573eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson // Find the index to insert into 574250608a5cd08862f4752a924d51710805850db8aWinson ArrayList<Task> taskList = mStackTaskList.getTasks(); 575eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson int taskCount = taskList.size(); 576eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson if (!task.isFreeformTask() && (newStackId == FREEFORM_WORKSPACE_STACK_ID)) { 577eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson // Insert freeform tasks at the front 578250608a5cd08862f4752a924d51710805850db8aWinson mStackTaskList.moveTaskToStack(task, taskCount, newStackId); 579eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson } else if (task.isFreeformTask() && (newStackId == FULLSCREEN_WORKSPACE_STACK_ID)) { 580eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson // Insert after the first stacked task 581eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson int insertIndex = 0; 582eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson for (int i = taskCount - 1; i >= 0; i--) { 583eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson if (!taskList.get(i).isFreeformTask()) { 584eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson insertIndex = i + 1; 585eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson break; 586eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson } 587eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson } 588250608a5cd08862f4752a924d51710805850db8aWinson mStackTaskList.moveTaskToStack(task, insertIndex, newStackId); 589eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson } 590eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson } 591eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson 5926ac8bd6198f67b64aea2258bdb5f8ed371b5bec1Winson Chung /** Does the actual work associated with removing the task. */ 593250608a5cd08862f4752a924d51710805850db8aWinson void removeTaskImpl(FilteredTaskList taskList, Task t) { 5946ac8bd6198f67b64aea2258bdb5f8ed371b5bec1Winson Chung // Remove the task from the list 595250608a5cd08862f4752a924d51710805850db8aWinson taskList.remove(t); 5966ac8bd6198f67b64aea2258bdb5f8ed371b5bec1Winson Chung // Remove it from the group as well, and if it is empty, remove the group 5976ac8bd6198f67b64aea2258bdb5f8ed371b5bec1Winson Chung TaskGrouping group = t.group; 5984e5fb2f4e1ed4eb119a201541ad89aafac8c53feWinson Chung if (group != null) { 5994e5fb2f4e1ed4eb119a201541ad89aafac8c53feWinson Chung group.removeTask(t); 6004e5fb2f4e1ed4eb119a201541ad89aafac8c53feWinson Chung if (group.getTaskCount() == 0) { 6014e5fb2f4e1ed4eb119a201541ad89aafac8c53feWinson Chung removeGroup(group); 6024e5fb2f4e1ed4eb119a201541ad89aafac8c53feWinson Chung } 6036ac8bd6198f67b64aea2258bdb5f8ed371b5bec1Winson Chung } 6046ac8bd6198f67b64aea2258bdb5f8ed371b5bec1Winson Chung } 6056ac8bd6198f67b64aea2258bdb5f8ed371b5bec1Winson Chung 6068aa9959413a06c3d2ff75e0c7be9e3cb7ac7cd2eWinson /** 6078aa9959413a06c3d2ff75e0c7be9e3cb7ac7cd2eWinson * Removes a task from the stack, with an additional {@param animation} hint to the callbacks on 6088aa9959413a06c3d2ff75e0c7be9e3cb7ac7cd2eWinson * how they should update themselves. 6098aa9959413a06c3d2ff75e0c7be9e3cb7ac7cd2eWinson */ 6102068408d08ca39a5b036daac01e80de45e8c1eabWinson public void removeTask(Task t, AnimationProps animation, boolean fromDockGesture) { 611250608a5cd08862f4752a924d51710805850db8aWinson if (mStackTaskList.contains(t)) { 612250608a5cd08862f4752a924d51710805850db8aWinson removeTaskImpl(mStackTaskList, t); 61335a8b04140598a5b5c4865254b942adb6a830991Winson Task newFrontMostTask = getStackFrontMostTask(false /* includeFreeform */); 614303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung if (mCb != null) { 615ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung // Notify that a task has been removed 6166c8217ab3072fa65851316a922b482506b3c2a4cWinson mCb.onStackTaskRemoved(this, t, newFrontMostTask, animation, 6172068408d08ca39a5b036daac01e80de45e8c1eabWinson fromDockGesture); 618303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 619303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 6203e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson mRawTaskList.remove(t); 621250608a5cd08862f4752a924d51710805850db8aWinson } 622250608a5cd08862f4752a924d51710805850db8aWinson 623250608a5cd08862f4752a924d51710805850db8aWinson /** 6243b6ba1ab144c53752841869627a1b9f6d357c404Winson * Removes all tasks from the stack. 6253b6ba1ab144c53752841869627a1b9f6d357c404Winson */ 6263b6ba1ab144c53752841869627a1b9f6d357c404Winson public void removeAllTasks() { 6273b6ba1ab144c53752841869627a1b9f6d357c404Winson ArrayList<Task> tasks = mStackTaskList.getTasks(); 6283b6ba1ab144c53752841869627a1b9f6d357c404Winson for (int i = tasks.size() - 1; i >= 0; i--) { 6293b6ba1ab144c53752841869627a1b9f6d357c404Winson Task t = tasks.get(i); 6303b6ba1ab144c53752841869627a1b9f6d357c404Winson removeTaskImpl(mStackTaskList, t); 6313b6ba1ab144c53752841869627a1b9f6d357c404Winson mRawTaskList.remove(t); 6323b6ba1ab144c53752841869627a1b9f6d357c404Winson } 6333b6ba1ab144c53752841869627a1b9f6d357c404Winson if (mCb != null) { 6343b6ba1ab144c53752841869627a1b9f6d357c404Winson // Notify that all tasks have been removed 6353b6ba1ab144c53752841869627a1b9f6d357c404Winson mCb.onStackTasksRemoved(this); 6363b6ba1ab144c53752841869627a1b9f6d357c404Winson } 6373b6ba1ab144c53752841869627a1b9f6d357c404Winson } 6383b6ba1ab144c53752841869627a1b9f6d357c404Winson 6393b6ba1ab144c53752841869627a1b9f6d357c404Winson /** 640250608a5cd08862f4752a924d51710805850db8aWinson * Sets a few tasks in one go, without calling any callbacks. 641062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung * 642062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung * @param tasks the new set of tasks to replace the current set. 643062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung * @param notifyStackChanges whether or not to callback on specific changes to the list of tasks. 644250608a5cd08862f4752a924d51710805850db8aWinson */ 6458873754f66527d2cc9feab295dd4eef23298212aWinson public void setTasks(Context context, List<Task> tasks, boolean notifyStackChanges) { 646062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung // Compute a has set for each of the tasks 6475500390a006f2bbea565068234774a36cea076c0Winson ArrayMap<Task.TaskKey, Task> currentTasksMap = createTaskKeyMapFromList(mRawTaskList); 6485500390a006f2bbea565068234774a36cea076c0Winson ArrayMap<Task.TaskKey, Task> newTasksMap = createTaskKeyMapFromList(tasks); 6498873754f66527d2cc9feab295dd4eef23298212aWinson ArrayList<Task> addedTasks = new ArrayList<>(); 6506c8217ab3072fa65851316a922b482506b3c2a4cWinson ArrayList<Task> removedTasks = new ArrayList<>(); 6518873754f66527d2cc9feab295dd4eef23298212aWinson ArrayList<Task> allTasks = new ArrayList<>(); 652062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung 653062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung // Disable notifications if there are no callbacks 654062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung if (mCb == null) { 655062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung notifyStackChanges = false; 656062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung } 657062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung 658062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung // Remove any tasks that no longer exist 659062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung int taskCount = mRawTaskList.size(); 6608873754f66527d2cc9feab295dd4eef23298212aWinson for (int i = taskCount - 1; i >= 0; i--) { 661062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung Task task = mRawTaskList.get(i); 662062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung if (!newTasksMap.containsKey(task.key)) { 663062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung if (notifyStackChanges) { 6646c8217ab3072fa65851316a922b482506b3c2a4cWinson removedTasks.add(task); 665062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung } 666062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung } 6679756755db76aeda2065322aa3c26e1a19578d45fWinson Chung task.setGroup(null); 668062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung } 669062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung 670062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung // Add any new tasks 671062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung taskCount = tasks.size(); 672062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung for (int i = 0; i < taskCount; i++) { 6738873754f66527d2cc9feab295dd4eef23298212aWinson Task newTask = tasks.get(i); 6748873754f66527d2cc9feab295dd4eef23298212aWinson Task currentTask = currentTasksMap.get(newTask.key); 6758873754f66527d2cc9feab295dd4eef23298212aWinson if (currentTask == null && notifyStackChanges) { 6768873754f66527d2cc9feab295dd4eef23298212aWinson addedTasks.add(newTask); 6778873754f66527d2cc9feab295dd4eef23298212aWinson } else if (currentTask != null) { 6788873754f66527d2cc9feab295dd4eef23298212aWinson // The current task has bound callbacks, so just copy the data from the new task 6798873754f66527d2cc9feab295dd4eef23298212aWinson // state and add it back into the list 6808873754f66527d2cc9feab295dd4eef23298212aWinson currentTask.copyFrom(newTask); 6818873754f66527d2cc9feab295dd4eef23298212aWinson newTask = currentTask; 682062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung } 6838873754f66527d2cc9feab295dd4eef23298212aWinson allTasks.add(newTask); 684062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung } 685062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung 686062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung // Sort all the tasks to ensure they are ordered correctly 6876976f7bae901d81a354287088ae232ba7236f30eWinson for (int i = allTasks.size() - 1; i >= 0; i--) { 6886976f7bae901d81a354287088ae232ba7236f30eWinson allTasks.get(i).temporarySortIndexInStack = i; 6896976f7bae901d81a354287088ae232ba7236f30eWinson } 6906976f7bae901d81a354287088ae232ba7236f30eWinson Collections.sort(allTasks, FREEFORM_COMPARATOR); 691062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung 6928f6ee48225ad1cdf966c8f406c85113b13833c7bWinson mStackTaskList.set(allTasks); 6938873754f66527d2cc9feab295dd4eef23298212aWinson mRawTaskList = allTasks; 6948873754f66527d2cc9feab295dd4eef23298212aWinson 695a1ededd056d51532ab18354f17f8065ec1134535Winson // Update the affiliated groupings 696a1ededd056d51532ab18354f17f8065ec1134535Winson createAffiliatedGroupings(context); 697a1ededd056d51532ab18354f17f8065ec1134535Winson 6986c8217ab3072fa65851316a922b482506b3c2a4cWinson // Only callback for the removed tasks after the stack has updated 6996c8217ab3072fa65851316a922b482506b3c2a4cWinson int removedTaskCount = removedTasks.size(); 7006c8217ab3072fa65851316a922b482506b3c2a4cWinson Task newFrontMostTask = getStackFrontMostTask(false); 7016c8217ab3072fa65851316a922b482506b3c2a4cWinson for (int i = 0; i < removedTaskCount; i++) { 7026c8217ab3072fa65851316a922b482506b3c2a4cWinson mCb.onStackTaskRemoved(this, removedTasks.get(i), newFrontMostTask, 7036c8217ab3072fa65851316a922b482506b3c2a4cWinson AnimationProps.IMMEDIATE, false /* fromDockGesture */); 7046c8217ab3072fa65851316a922b482506b3c2a4cWinson } 7056c8217ab3072fa65851316a922b482506b3c2a4cWinson 7068873754f66527d2cc9feab295dd4eef23298212aWinson // Only callback for the newly added tasks after this stack has been updated 7078873754f66527d2cc9feab295dd4eef23298212aWinson int addedTaskCount = addedTasks.size(); 7088873754f66527d2cc9feab295dd4eef23298212aWinson for (int i = 0; i < addedTaskCount; i++) { 7098873754f66527d2cc9feab295dd4eef23298212aWinson mCb.onStackTaskAdded(this, addedTasks.get(i)); 7108873754f66527d2cc9feab295dd4eef23298212aWinson } 7118873754f66527d2cc9feab295dd4eef23298212aWinson 712a1ededd056d51532ab18354f17f8065ec1134535Winson // Notify that the task stack has been updated 713a1ededd056d51532ab18354f17f8065ec1134535Winson if (notifyStackChanges) { 714a1ededd056d51532ab18354f17f8065ec1134535Winson mCb.onStackTasksUpdated(this); 715a1ededd056d51532ab18354f17f8065ec1134535Winson } 716303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 717303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 718931c51f54599a227422b2a1c71e922e1458e0291Winson Chung /** 719931c51f54599a227422b2a1c71e922e1458e0291Winson Chung * Gets the front-most task in the stack. 720931c51f54599a227422b2a1c71e922e1458e0291Winson Chung */ 72135a8b04140598a5b5c4865254b942adb6a830991Winson public Task getStackFrontMostTask(boolean includeFreeformTasks) { 722931c51f54599a227422b2a1c71e922e1458e0291Winson Chung ArrayList<Task> stackTasks = mStackTaskList.getTasks(); 723931c51f54599a227422b2a1c71e922e1458e0291Winson Chung if (stackTasks.isEmpty()) { 724931c51f54599a227422b2a1c71e922e1458e0291Winson Chung return null; 725931c51f54599a227422b2a1c71e922e1458e0291Winson Chung } 726931c51f54599a227422b2a1c71e922e1458e0291Winson Chung for (int i = stackTasks.size() - 1; i >= 0; i--) { 727931c51f54599a227422b2a1c71e922e1458e0291Winson Chung Task task = stackTasks.get(i); 72835a8b04140598a5b5c4865254b942adb6a830991Winson if (!task.isFreeformTask() || includeFreeformTasks) { 729931c51f54599a227422b2a1c71e922e1458e0291Winson Chung return task; 730931c51f54599a227422b2a1c71e922e1458e0291Winson Chung } 731931c51f54599a227422b2a1c71e922e1458e0291Winson Chung } 732931c51f54599a227422b2a1c71e922e1458e0291Winson Chung return null; 733ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 734ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung 73504400672962d2e12132f9465928cbf7615c147c4Winson Chung /** Gets the task keys */ 73604400672962d2e12132f9465928cbf7615c147c4Winson Chung public ArrayList<Task.TaskKey> getTaskKeys() { 7378f0e3a68cdd3b2403ff8a1677f90b998f4175f40Winson ArrayList<Task.TaskKey> taskKeys = new ArrayList<>(); 738250608a5cd08862f4752a924d51710805850db8aWinson ArrayList<Task> tasks = computeAllTasksList(); 73904400672962d2e12132f9465928cbf7615c147c4Winson Chung int taskCount = tasks.size(); 74004400672962d2e12132f9465928cbf7615c147c4Winson Chung for (int i = 0; i < taskCount; i++) { 741250608a5cd08862f4752a924d51710805850db8aWinson Task task = tasks.get(i); 742250608a5cd08862f4752a924d51710805850db8aWinson taskKeys.add(task.key); 74304400672962d2e12132f9465928cbf7615c147c4Winson Chung } 74404400672962d2e12132f9465928cbf7615c147c4Winson Chung return taskKeys; 74504400672962d2e12132f9465928cbf7615c147c4Winson Chung } 74604400672962d2e12132f9465928cbf7615c147c4Winson Chung 747250608a5cd08862f4752a924d51710805850db8aWinson /** 748250608a5cd08862f4752a924d51710805850db8aWinson * Returns the set of "active" (non-historical) tasks in the stack that have been used recently. 749250608a5cd08862f4752a924d51710805850db8aWinson */ 750250608a5cd08862f4752a924d51710805850db8aWinson public ArrayList<Task> getStackTasks() { 751250608a5cd08862f4752a924d51710805850db8aWinson return mStackTaskList.getTasks(); 752250608a5cd08862f4752a924d51710805850db8aWinson } 753250608a5cd08862f4752a924d51710805850db8aWinson 754250608a5cd08862f4752a924d51710805850db8aWinson /** 755f24f21695f5609d06402cf61e3500d408b99bdcbWinson * Returns the set of "freeform" tasks in the stack. 756f24f21695f5609d06402cf61e3500d408b99bdcbWinson */ 757f24f21695f5609d06402cf61e3500d408b99bdcbWinson public ArrayList<Task> getFreeformTasks() { 758f24f21695f5609d06402cf61e3500d408b99bdcbWinson ArrayList<Task> freeformTasks = new ArrayList<>(); 759f24f21695f5609d06402cf61e3500d408b99bdcbWinson ArrayList<Task> tasks = mStackTaskList.getTasks(); 760f24f21695f5609d06402cf61e3500d408b99bdcbWinson int taskCount = tasks.size(); 761f24f21695f5609d06402cf61e3500d408b99bdcbWinson for (int i = 0; i < taskCount; i++) { 762f24f21695f5609d06402cf61e3500d408b99bdcbWinson Task task = tasks.get(i); 763f24f21695f5609d06402cf61e3500d408b99bdcbWinson if (task.isFreeformTask()) { 764f24f21695f5609d06402cf61e3500d408b99bdcbWinson freeformTasks.add(task); 765f24f21695f5609d06402cf61e3500d408b99bdcbWinson } 766f24f21695f5609d06402cf61e3500d408b99bdcbWinson } 767f24f21695f5609d06402cf61e3500d408b99bdcbWinson return freeformTasks; 768f24f21695f5609d06402cf61e3500d408b99bdcbWinson } 769f24f21695f5609d06402cf61e3500d408b99bdcbWinson 770f24f21695f5609d06402cf61e3500d408b99bdcbWinson /** 7716976f7bae901d81a354287088ae232ba7236f30eWinson * Computes a set of all the active and historical tasks. 772250608a5cd08862f4752a924d51710805850db8aWinson */ 773250608a5cd08862f4752a924d51710805850db8aWinson public ArrayList<Task> computeAllTasksList() { 774250608a5cd08862f4752a924d51710805850db8aWinson ArrayList<Task> tasks = new ArrayList<>(); 775250608a5cd08862f4752a924d51710805850db8aWinson tasks.addAll(mStackTaskList.getTasks()); 776250608a5cd08862f4752a924d51710805850db8aWinson return tasks; 777303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 778303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 77936a5a2c7003ef8157f276b411c3fda47ad2f75e3Winson /** 7804b057c6787624b75613769a857ccdf51114bb7f2Winson * Returns the number of stack and freeform tasks. 781250608a5cd08862f4752a924d51710805850db8aWinson */ 7824b057c6787624b75613769a857ccdf51114bb7f2Winson public int getTaskCount() { 783250608a5cd08862f4752a924d51710805850db8aWinson return mStackTaskList.size(); 784250608a5cd08862f4752a924d51710805850db8aWinson } 785250608a5cd08862f4752a924d51710805850db8aWinson 786250608a5cd08862f4752a924d51710805850db8aWinson /** 7874b057c6787624b75613769a857ccdf51114bb7f2Winson * Returns the number of stack tasks. 7884b057c6787624b75613769a857ccdf51114bb7f2Winson */ 7894b057c6787624b75613769a857ccdf51114bb7f2Winson public int getStackTaskCount() { 7904b057c6787624b75613769a857ccdf51114bb7f2Winson ArrayList<Task> tasks = mStackTaskList.getTasks(); 7914b057c6787624b75613769a857ccdf51114bb7f2Winson int stackCount = 0; 7924b057c6787624b75613769a857ccdf51114bb7f2Winson int taskCount = tasks.size(); 7934b057c6787624b75613769a857ccdf51114bb7f2Winson for (int i = 0; i < taskCount; i++) { 7944b057c6787624b75613769a857ccdf51114bb7f2Winson Task task = tasks.get(i); 7954b057c6787624b75613769a857ccdf51114bb7f2Winson if (!task.isFreeformTask()) { 7964b057c6787624b75613769a857ccdf51114bb7f2Winson stackCount++; 7974b057c6787624b75613769a857ccdf51114bb7f2Winson } 7984b057c6787624b75613769a857ccdf51114bb7f2Winson } 7994b057c6787624b75613769a857ccdf51114bb7f2Winson return stackCount; 8004b057c6787624b75613769a857ccdf51114bb7f2Winson } 8014b057c6787624b75613769a857ccdf51114bb7f2Winson 8024b057c6787624b75613769a857ccdf51114bb7f2Winson /** 8034b057c6787624b75613769a857ccdf51114bb7f2Winson * Returns the number of freeform tasks. 804f0d1c44a59a10707baa0cca8dd377302260710c1Winson */ 8054b057c6787624b75613769a857ccdf51114bb7f2Winson public int getFreeformTaskCount() { 806f0d1c44a59a10707baa0cca8dd377302260710c1Winson ArrayList<Task> tasks = mStackTaskList.getTasks(); 807f0d1c44a59a10707baa0cca8dd377302260710c1Winson int freeformCount = 0; 808f0d1c44a59a10707baa0cca8dd377302260710c1Winson int taskCount = tasks.size(); 809f0d1c44a59a10707baa0cca8dd377302260710c1Winson for (int i = 0; i < taskCount; i++) { 810f0d1c44a59a10707baa0cca8dd377302260710c1Winson Task task = tasks.get(i); 811f0d1c44a59a10707baa0cca8dd377302260710c1Winson if (task.isFreeformTask()) { 812f0d1c44a59a10707baa0cca8dd377302260710c1Winson freeformCount++; 813f0d1c44a59a10707baa0cca8dd377302260710c1Winson } 814f0d1c44a59a10707baa0cca8dd377302260710c1Winson } 815f0d1c44a59a10707baa0cca8dd377302260710c1Winson return freeformCount; 816f0d1c44a59a10707baa0cca8dd377302260710c1Winson } 817f0d1c44a59a10707baa0cca8dd377302260710c1Winson 818f0d1c44a59a10707baa0cca8dd377302260710c1Winson /** 819250608a5cd08862f4752a924d51710805850db8aWinson * Returns the task in stack tasks which is the launch target. 82036a5a2c7003ef8157f276b411c3fda47ad2f75e3Winson */ 82136a5a2c7003ef8157f276b411c3fda47ad2f75e3Winson public Task getLaunchTarget() { 822250608a5cd08862f4752a924d51710805850db8aWinson ArrayList<Task> tasks = mStackTaskList.getTasks(); 82336a5a2c7003ef8157f276b411c3fda47ad2f75e3Winson int taskCount = tasks.size(); 82436a5a2c7003ef8157f276b411c3fda47ad2f75e3Winson for (int i = 0; i < taskCount; i++) { 82536a5a2c7003ef8157f276b411c3fda47ad2f75e3Winson Task task = tasks.get(i); 82636a5a2c7003ef8157f276b411c3fda47ad2f75e3Winson if (task.isLaunchTarget) { 82736a5a2c7003ef8157f276b411c3fda47ad2f75e3Winson return task; 82836a5a2c7003ef8157f276b411c3fda47ad2f75e3Winson } 82936a5a2c7003ef8157f276b411c3fda47ad2f75e3Winson } 83036a5a2c7003ef8157f276b411c3fda47ad2f75e3Winson return null; 83136a5a2c7003ef8157f276b411c3fda47ad2f75e3Winson } 83236a5a2c7003ef8157f276b411c3fda47ad2f75e3Winson 833303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung /** Returns the index of this task in this current task stack */ 834250608a5cd08862f4752a924d51710805850db8aWinson public int indexOfStackTask(Task t) { 835250608a5cd08862f4752a924d51710805850db8aWinson return mStackTaskList.indexOf(t); 836303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 837303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung 838b1f749906f5c27114d02ea0c3f8ce0dcea08fd3fWinson Chung /** Finds the task with the specified task id. */ 839b1f749906f5c27114d02ea0c3f8ce0dcea08fd3fWinson Chung public Task findTaskWithId(int taskId) { 840250608a5cd08862f4752a924d51710805850db8aWinson ArrayList<Task> tasks = computeAllTasksList(); 841d72c315d5eed3a684eee303364b97129cb821689Winson int taskCount = tasks.size(); 842d72c315d5eed3a684eee303364b97129cb821689Winson for (int i = 0; i < taskCount; i++) { 843d72c315d5eed3a684eee303364b97129cb821689Winson Task task = tasks.get(i); 844b1f749906f5c27114d02ea0c3f8ce0dcea08fd3fWinson Chung if (task.key.id == taskId) { 845b1f749906f5c27114d02ea0c3f8ce0dcea08fd3fWinson Chung return task; 846b1f749906f5c27114d02ea0c3f8ce0dcea08fd3fWinson Chung } 847b1f749906f5c27114d02ea0c3f8ce0dcea08fd3fWinson Chung } 848b1f749906f5c27114d02ea0c3f8ce0dcea08fd3fWinson Chung return null; 849b1f749906f5c27114d02ea0c3f8ce0dcea08fd3fWinson Chung } 850b1f749906f5c27114d02ea0c3f8ce0dcea08fd3fWinson Chung 851ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung /******** Grouping ********/ 852ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung 853ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung /** Adds a group to the set */ 854ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung public void addGroup(TaskGrouping group) { 855ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung mGroups.add(group); 856ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung mAffinitiesGroups.put(group.affiliation, group); 857ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 858ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung 859ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung public void removeGroup(TaskGrouping group) { 860ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung mGroups.remove(group); 861ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung mAffinitiesGroups.remove(group.affiliation); 862ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 863ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung 864ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung /** Returns the group with the specified affiliation. */ 865083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung public TaskGrouping getGroupWithAffiliation(int affiliation) { 866ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung return mAffinitiesGroups.get(affiliation); 867ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 868ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung 869ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung /** 8708873754f66527d2cc9feab295dd4eef23298212aWinson * Temporary: This method will simulate affiliation groups 871ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung */ 8728873754f66527d2cc9feab295dd4eef23298212aWinson void createAffiliatedGroupings(Context context) { 8738873754f66527d2cc9feab295dd4eef23298212aWinson mGroups.clear(); 8748873754f66527d2cc9feab295dd4eef23298212aWinson mAffinitiesGroups.clear(); 8758873754f66527d2cc9feab295dd4eef23298212aWinson 8766e6bd8776f850a21a3733a03dfa32b04f06163d9Winson if (RecentsDebugFlags.Static.EnableMockTaskGroups) { 8775500390a006f2bbea565068234774a36cea076c0Winson ArrayMap<Task.TaskKey, Task> taskMap = new ArrayMap<>(); 878ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung // Sort all tasks by increasing firstActiveTime of the task 879250608a5cd08862f4752a924d51710805850db8aWinson ArrayList<Task> tasks = mStackTaskList.getTasks(); 880ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung Collections.sort(tasks, new Comparator<Task>() { 881ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung @Override 882ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung public int compare(Task task, Task task2) { 88316bc2a7f379edd7796bb5aa4400e1b7c14376a08Winson Chung return Long.compare(task.key.firstActiveTime, task2.key.firstActiveTime); 884ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 885ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung }); 886ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung // Create groups when sequential packages are the same 887ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung NamedCounter counter = new NamedCounter("task-group", ""); 888ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung int taskCount = tasks.size(); 889ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung String prevPackage = ""; 890083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung int prevAffiliation = -1; 891a433fa9c17772f563163ff7db177d091d6aebd5bWinson Chung Random r = new Random(); 8926e6bd8776f850a21a3733a03dfa32b04f06163d9Winson int groupCountDown = RecentsDebugFlags.Static.MockTaskGroupsTaskCount; 893ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung for (int i = 0; i < taskCount; i++) { 894ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung Task t = tasks.get(i); 895e7f138c7f0a190c86cec10fb32fa106aacae4093Winson String packageName = t.key.getComponent().getPackageName(); 896a433fa9c17772f563163ff7db177d091d6aebd5bWinson Chung packageName = "pkg"; 897ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung TaskGrouping group; 898a433fa9c17772f563163ff7db177d091d6aebd5bWinson Chung if (packageName.equals(prevPackage) && groupCountDown > 0) { 899ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung group = getGroupWithAffiliation(prevAffiliation); 900a433fa9c17772f563163ff7db177d091d6aebd5bWinson Chung groupCountDown--; 901ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } else { 902083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung int affiliation = IndividualTaskIdOffset + t.key.id; 903ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung group = new TaskGrouping(affiliation); 904ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung addGroup(group); 905ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung prevAffiliation = affiliation; 906ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung prevPackage = packageName; 9076e6bd8776f850a21a3733a03dfa32b04f06163d9Winson groupCountDown = RecentsDebugFlags.Static.MockTaskGroupsTaskCount; 908ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 909ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung group.addTask(t); 910ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung taskMap.put(t.key, t); 911ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 912ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung // Sort groups by increasing latestActiveTime of the group 913ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung Collections.sort(mGroups, new Comparator<TaskGrouping>() { 914ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung @Override 915ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung public int compare(TaskGrouping taskGrouping, TaskGrouping taskGrouping2) { 916509d0d0c9e2ee165d04e898fea59f8941ac7138dWinson Chung return Long.compare(taskGrouping.latestActiveTimeInGroup, 917ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung taskGrouping2.latestActiveTimeInGroup); 918ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 919ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung }); 9202b9ef6548be89d36ea7629f4a3d8ba7bba1422ceWinson Chung // Sort group tasks by increasing firstActiveTime of the task, and also build a new list 9212b9ef6548be89d36ea7629f4a3d8ba7bba1422ceWinson Chung // of tasks 922ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung int taskIndex = 0; 923ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung int groupCount = mGroups.size(); 924ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung for (int i = 0; i < groupCount; i++) { 925ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung TaskGrouping group = mGroups.get(i); 926083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung Collections.sort(group.mTaskKeys, new Comparator<Task.TaskKey>() { 927ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung @Override 928ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung public int compare(Task.TaskKey taskKey, Task.TaskKey taskKey2) { 929509d0d0c9e2ee165d04e898fea59f8941ac7138dWinson Chung return Long.compare(taskKey.firstActiveTime, taskKey2.firstActiveTime); 930ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 931ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung }); 932083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung ArrayList<Task.TaskKey> groupTasks = group.mTaskKeys; 933ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung int groupTaskCount = groupTasks.size(); 934ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung for (int j = 0; j < groupTaskCount; j++) { 935ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung tasks.set(taskIndex, taskMap.get(groupTasks.get(j))); 936ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung taskIndex++; 937ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 938ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 939250608a5cd08862f4752a924d51710805850db8aWinson mStackTaskList.set(tasks); 940ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } else { 941083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung // Create the task groups 9425500390a006f2bbea565068234774a36cea076c0Winson ArrayMap<Task.TaskKey, Task> tasksMap = new ArrayMap<>(); 943250608a5cd08862f4752a924d51710805850db8aWinson ArrayList<Task> tasks = mStackTaskList.getTasks(); 944ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung int taskCount = tasks.size(); 945ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung for (int i = 0; i < taskCount; i++) { 946ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung Task t = tasks.get(i); 947083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung TaskGrouping group; 94865c851e6e9e08656744b6f66d3da188e3283b17dWinson if (RecentsDebugFlags.Static.EnableAffiliatedTaskGroups) { 94965c851e6e9e08656744b6f66d3da188e3283b17dWinson int affiliation = t.affiliationTaskId > 0 ? t.affiliationTaskId : 95065c851e6e9e08656744b6f66d3da188e3283b17dWinson IndividualTaskIdOffset + t.key.id; 95165c851e6e9e08656744b6f66d3da188e3283b17dWinson if (mAffinitiesGroups.containsKey(affiliation)) { 95265c851e6e9e08656744b6f66d3da188e3283b17dWinson group = getGroupWithAffiliation(affiliation); 95365c851e6e9e08656744b6f66d3da188e3283b17dWinson } else { 95465c851e6e9e08656744b6f66d3da188e3283b17dWinson group = new TaskGrouping(affiliation); 95565c851e6e9e08656744b6f66d3da188e3283b17dWinson addGroup(group); 95665c851e6e9e08656744b6f66d3da188e3283b17dWinson } 957083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung } else { 95865c851e6e9e08656744b6f66d3da188e3283b17dWinson group = new TaskGrouping(t.key.id); 959083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung addGroup(group); 960083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung } 961ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung group.addTask(t); 962ec396d6399c5c31d697d81e94aff459e9771b0c6Winson Chung tasksMap.put(t.key, t); 963ec396d6399c5c31d697d81e94aff459e9771b0c6Winson Chung } 964ec396d6399c5c31d697d81e94aff459e9771b0c6Winson Chung // Update the task colors for each of the groups 96535f3050959e43bf378f9a0adcaef13729206c7e4Winson float minAlpha = context.getResources().getFloat( 96635f3050959e43bf378f9a0adcaef13729206c7e4Winson R.dimen.recents_task_affiliation_color_min_alpha_percentage); 967ec396d6399c5c31d697d81e94aff459e9771b0c6Winson Chung int taskGroupCount = mGroups.size(); 968ec396d6399c5c31d697d81e94aff459e9771b0c6Winson Chung for (int i = 0; i < taskGroupCount; i++) { 969ec396d6399c5c31d697d81e94aff459e9771b0c6Winson Chung TaskGrouping group = mGroups.get(i); 970ec396d6399c5c31d697d81e94aff459e9771b0c6Winson Chung taskCount = group.getTaskCount(); 971ec396d6399c5c31d697d81e94aff459e9771b0c6Winson Chung // Ignore the groups that only have one task 972ec396d6399c5c31d697d81e94aff459e9771b0c6Winson Chung if (taskCount <= 1) continue; 973ec396d6399c5c31d697d81e94aff459e9771b0c6Winson Chung // Calculate the group color distribution 974296278a0679375b8c43962a9e3c9bb4e8ab201e7Winson Chung int affiliationColor = tasksMap.get(group.mTaskKeys.get(0)).affiliationColor; 975ec396d6399c5c31d697d81e94aff459e9771b0c6Winson Chung float alphaStep = (1f - minAlpha) / taskCount; 976ec396d6399c5c31d697d81e94aff459e9771b0c6Winson Chung float alpha = 1f; 977ec396d6399c5c31d697d81e94aff459e9771b0c6Winson Chung for (int j = 0; j < taskCount; j++) { 978ec396d6399c5c31d697d81e94aff459e9771b0c6Winson Chung Task t = tasksMap.get(group.mTaskKeys.get(j)); 979a0e88b5013d708ac6ed6518817d83c64c87ae4b1Winson Chung t.colorPrimary = Utilities.getColorWithOverlay(affiliationColor, Color.WHITE, 980a0e88b5013d708ac6ed6518817d83c64c87ae4b1Winson Chung alpha); 981ec396d6399c5c31d697d81e94aff459e9771b0c6Winson Chung alpha -= alphaStep; 982ec396d6399c5c31d697d81e94aff459e9771b0c6Winson Chung } 983ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 984ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 985ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung } 986ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung 987e7f138c7f0a190c86cec10fb32fa106aacae4093Winson /** 988e7f138c7f0a190c86cec10fb32fa106aacae4093Winson * Computes the components of tasks in this stack that have been removed as a result of a change 989e7f138c7f0a190c86cec10fb32fa106aacae4093Winson * in the specified package. 990e7f138c7f0a190c86cec10fb32fa106aacae4093Winson */ 9915500390a006f2bbea565068234774a36cea076c0Winson public ArraySet<ComponentName> computeComponentsRemoved(String packageName, int userId) { 992e7f138c7f0a190c86cec10fb32fa106aacae4093Winson // Identify all the tasks that should be removed as a result of the package being removed. 993e7f138c7f0a190c86cec10fb32fa106aacae4093Winson // Using a set to ensure that we callback once per unique component. 994e7f138c7f0a190c86cec10fb32fa106aacae4093Winson SystemServicesProxy ssp = Recents.getSystemServices(); 9955500390a006f2bbea565068234774a36cea076c0Winson ArraySet<ComponentName> existingComponents = new ArraySet<>(); 9965500390a006f2bbea565068234774a36cea076c0Winson ArraySet<ComponentName> removedComponents = new ArraySet<>(); 997e7f138c7f0a190c86cec10fb32fa106aacae4093Winson ArrayList<Task.TaskKey> taskKeys = getTaskKeys(); 998d72c315d5eed3a684eee303364b97129cb821689Winson int taskKeyCount = taskKeys.size(); 999d72c315d5eed3a684eee303364b97129cb821689Winson for (int i = 0; i < taskKeyCount; i++) { 1000d72c315d5eed3a684eee303364b97129cb821689Winson Task.TaskKey t = taskKeys.get(i); 1001d72c315d5eed3a684eee303364b97129cb821689Winson 1002e7f138c7f0a190c86cec10fb32fa106aacae4093Winson // Skip if this doesn't apply to the current user 1003e7f138c7f0a190c86cec10fb32fa106aacae4093Winson if (t.userId != userId) continue; 1004e7f138c7f0a190c86cec10fb32fa106aacae4093Winson 1005e7f138c7f0a190c86cec10fb32fa106aacae4093Winson ComponentName cn = t.getComponent(); 1006e7f138c7f0a190c86cec10fb32fa106aacae4093Winson if (cn.getPackageName().equals(packageName)) { 1007e7f138c7f0a190c86cec10fb32fa106aacae4093Winson if (existingComponents.contains(cn)) { 1008e7f138c7f0a190c86cec10fb32fa106aacae4093Winson // If we know that the component still exists in the package, then skip 1009e7f138c7f0a190c86cec10fb32fa106aacae4093Winson continue; 1010e7f138c7f0a190c86cec10fb32fa106aacae4093Winson } 1011e7f138c7f0a190c86cec10fb32fa106aacae4093Winson if (ssp.getActivityInfo(cn, userId) != null) { 1012e7f138c7f0a190c86cec10fb32fa106aacae4093Winson existingComponents.add(cn); 1013e7f138c7f0a190c86cec10fb32fa106aacae4093Winson } else { 1014e7f138c7f0a190c86cec10fb32fa106aacae4093Winson removedComponents.add(cn); 1015e7f138c7f0a190c86cec10fb32fa106aacae4093Winson } 1016e7f138c7f0a190c86cec10fb32fa106aacae4093Winson } 1017e7f138c7f0a190c86cec10fb32fa106aacae4093Winson } 1018e7f138c7f0a190c86cec10fb32fa106aacae4093Winson return removedComponents; 1019e7f138c7f0a190c86cec10fb32fa106aacae4093Winson } 1020e7f138c7f0a190c86cec10fb32fa106aacae4093Winson 1021303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung @Override 1022303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung public String toString() { 10238873754f66527d2cc9feab295dd4eef23298212aWinson String str = "Stack Tasks (" + mStackTaskList.size() + "):\n"; 1024d72c315d5eed3a684eee303364b97129cb821689Winson ArrayList<Task> tasks = mStackTaskList.getTasks(); 1025d72c315d5eed3a684eee303364b97129cb821689Winson int taskCount = tasks.size(); 1026d72c315d5eed3a684eee303364b97129cb821689Winson for (int i = 0; i < taskCount; i++) { 1027d72c315d5eed3a684eee303364b97129cb821689Winson str += " " + tasks.get(i).toString() + "\n"; 1028250608a5cd08862f4752a924d51710805850db8aWinson } 1029303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung return str; 1030303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung } 1031062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung 1032062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung /** 1033062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung * Given a list of tasks, returns a map of each task's key to the task. 1034062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung */ 10355500390a006f2bbea565068234774a36cea076c0Winson private ArrayMap<Task.TaskKey, Task> createTaskKeyMapFromList(List<Task> tasks) { 10365500390a006f2bbea565068234774a36cea076c0Winson ArrayMap<Task.TaskKey, Task> map = new ArrayMap<>(tasks.size()); 1037062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung int taskCount = tasks.size(); 1038062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung for (int i = 0; i < taskCount; i++) { 1039062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung Task task = tasks.get(i); 1040062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung map.put(task.key, task); 1041062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung } 1042062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung return map; 1043062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung } 1044d72c315d5eed3a684eee303364b97129cb821689Winson 1045d72c315d5eed3a684eee303364b97129cb821689Winson public void dump(String prefix, PrintWriter writer) { 1046d72c315d5eed3a684eee303364b97129cb821689Winson String innerPrefix = prefix + " "; 1047d72c315d5eed3a684eee303364b97129cb821689Winson 1048d72c315d5eed3a684eee303364b97129cb821689Winson writer.print(prefix); writer.print(TAG); 1049d72c315d5eed3a684eee303364b97129cb821689Winson writer.print(" numStackTasks="); writer.print(mStackTaskList.size()); 1050d72c315d5eed3a684eee303364b97129cb821689Winson writer.println(); 1051d72c315d5eed3a684eee303364b97129cb821689Winson ArrayList<Task> tasks = mStackTaskList.getTasks(); 1052d72c315d5eed3a684eee303364b97129cb821689Winson int taskCount = tasks.size(); 1053d72c315d5eed3a684eee303364b97129cb821689Winson for (int i = 0; i < taskCount; i++) { 1054d72c315d5eed3a684eee303364b97129cb821689Winson tasks.get(i).dump(innerPrefix, writer); 1055d72c315d5eed3a684eee303364b97129cb821689Winson } 1056d72c315d5eed3a684eee303364b97129cb821689Winson } 1057062667710edcad7a01d7ece3e2bc4a83ee2a2ca3Winson Chung} 1058