Merge "Preload expensive objects before user is unlocked." into tm-qpr-dev
diff --git a/OWNERS b/OWNERS
index 962d63a..dd9fbf9 100644
--- a/OWNERS
+++ b/OWNERS
@@ -36,4 +36,4 @@
xuqiu@google.com
per-file FeatureFlags.java, globs = set noparent
-per-file FeatureFlags.java = sunnygoyal@google.com, winsonc@google.com, adamcohen@google.com, hyunyoungs@google.com
+per-file FeatureFlags.java = sunnygoyal@google.com, winsonc@google.com, adamcohen@google.com, hyunyoungs@google.com, captaincole@google.com
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
index ab52adb..dde7d94 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
@@ -88,6 +88,7 @@
import com.android.launcher3.testing.shared.TestProtocol;
import com.android.launcher3.touch.ItemClickHandler;
import com.android.launcher3.touch.ItemClickHandler.ItemClickProxy;
+import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.NavigationMode;
import com.android.launcher3.util.PackageManagerHelper;
@@ -105,7 +106,6 @@
import com.android.systemui.unfold.util.ScopedUnfoldTransitionProgressProvider;
import java.io.PrintWriter;
-import java.util.function.Consumer;
/**
* The {@link ActivityContext} with which we inflate Taskbar-related Views. This allows UI elements
@@ -877,8 +877,9 @@
* (potentially breaking a split pair).
*/
private void launchFromTaskbarPreservingSplitIfVisible(RecentsView recents, ItemInfo info) {
+ ComponentKey componentToBeLaunched = new ComponentKey(info.getTargetComponent(), info.user);
recents.getSplitSelectController().findLastActiveTaskAndRunCallback(
- info.getTargetComponent(),
+ componentToBeLaunched,
foundTask -> {
if (foundTask != null) {
TaskView foundTaskView =
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
index 3479255..b552e9b 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
@@ -30,16 +30,15 @@
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.ItemInfoWithIcon;
+import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.SplitConfigurationOptions;
import com.android.quickstep.util.GroupTask;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskView;
import com.android.quickstep.views.TaskView.TaskIdAttributeContainer;
-import com.android.systemui.shared.recents.model.Task;
import java.io.PrintWriter;
-import java.util.function.Consumer;
/**
* Base class for providing different taskbar UI
@@ -189,8 +188,12 @@
if (recentsView == null) {
return;
}
+
+ ComponentKey componentToBeStaged = new ComponentKey(
+ splitSelectSource.itemInfo.getTargetComponent(),
+ splitSelectSource.itemInfo.user);
recentsView.getSplitSelectController().findLastActiveTaskAndRunCallback(
- splitSelectSource.intent.getComponent(),
+ componentToBeStaged,
foundTask -> {
splitSelectSource.alreadyRunningTaskId = foundTask == null
? INVALID_TASK_ID
@@ -206,8 +209,9 @@
*/
public void triggerSecondAppForSplit(ItemInfoWithIcon info, Intent intent, View startingView) {
RecentsView recents = getRecentsView();
+ ComponentKey secondAppComponent = new ComponentKey(info.getTargetComponent(), info.user);
recents.getSplitSelectController().findLastActiveTaskAndRunCallback(
- info.getTargetComponent(),
+ secondAppComponent,
foundTask -> {
if (foundTask != null) {
TaskView foundTaskView = recents.getTaskViewByTaskId(foundTask.key.id);
diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
index 951a9b6..93baf5b 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
@@ -136,6 +136,7 @@
import com.android.launcher3.uioverrides.touchcontrollers.TransposedQuickSwitchTouchController;
import com.android.launcher3.uioverrides.touchcontrollers.TwoButtonNavbarTouchController;
import com.android.launcher3.util.ActivityOptionsWrapper;
+import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.IntSet;
import com.android.launcher3.util.NavigationMode;
@@ -574,10 +575,13 @@
@Override
public void startSplitSelection(SplitSelectSource splitSelectSource) {
RecentsView recentsView = getOverviewPanel();
+ ComponentKey componentToBeStaged = new ComponentKey(
+ splitSelectSource.itemInfo.getTargetComponent(),
+ splitSelectSource.itemInfo.user);
// Check if there is already an instance of this app running, if so, initiate the split
// using that.
mSplitSelectStateController.findLastActiveTaskAndRunCallback(
- splitSelectSource.intent.getComponent(),
+ componentToBeStaged,
foundTask -> {
splitSelectSource.alreadyRunningTaskId = foundTask == null
? INVALID_TASK_ID
diff --git a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
index d1100c7..5214f7c 100644
--- a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
+++ b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
@@ -29,7 +29,6 @@
import android.app.ActivityOptions;
import android.app.ActivityThread;
import android.app.PendingIntent;
-import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
@@ -58,6 +57,7 @@
import com.android.launcher3.statemanager.StateManager;
import com.android.launcher3.testing.TestLogging;
import com.android.launcher3.testing.shared.TestProtocol;
+import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.SplitConfigurationOptions;
import com.android.launcher3.util.SplitConfigurationOptions.StagePosition;
import com.android.quickstep.RecentsModel;
@@ -162,7 +162,7 @@
* Used in various task-switching or splitscreen operations when we need to check if there is a
* currently running Task of a certain type and use the most recent one.
*/
- public void findLastActiveTaskAndRunCallback(ComponentName componentName,
+ public void findLastActiveTaskAndRunCallback(ComponentKey componentKey,
Consumer<Task> callback) {
mRecentTasksModel.getTasks(taskGroups -> {
Task lastActiveTask = null;
@@ -170,12 +170,12 @@
for (int i = taskGroups.size() - 1; i >= 0; i--) {
GroupTask groupTask = taskGroups.get(i);
Task task1 = groupTask.task1;
- if (isInstanceOfComponent(task1, componentName)) {
+ if (isInstanceOfComponent(task1, componentKey)) {
lastActiveTask = task1;
break;
}
Task task2 = groupTask.task2;
- if (isInstanceOfComponent(task2, componentName)) {
+ if (isInstanceOfComponent(task2, componentKey)) {
lastActiveTask = task2;
break;
}
@@ -189,13 +189,14 @@
* Checks if a given Task is the most recently-active Task of type componentName. Used for
* selecting already-running Tasks for splitscreen.
*/
- public boolean isInstanceOfComponent(@Nullable Task task, ComponentName componentName) {
+ public boolean isInstanceOfComponent(@Nullable Task task, ComponentKey componentKey) {
// Exclude the task that is already staged
if (task == null || task.key.id == mInitialTaskId) {
return false;
}
- return task.key.baseIntent.getComponent().equals(componentName);
+ return task.key.baseIntent.getComponent().equals(componentKey.componentName)
+ && task.key.userId == componentKey.user.getIdentifier();
}
/**
diff --git a/quickstep/tests/src/com/android/quickstep/util/SplitSelectStateControllerTest.kt b/quickstep/tests/src/com/android/quickstep/util/SplitSelectStateControllerTest.kt
index 5abdc93..512df8e 100644
--- a/quickstep/tests/src/com/android/quickstep/util/SplitSelectStateControllerTest.kt
+++ b/quickstep/tests/src/com/android/quickstep/util/SplitSelectStateControllerTest.kt
@@ -23,12 +23,14 @@
import android.content.Intent
import android.graphics.Rect
import android.os.Handler
+import android.os.UserHandle
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.launcher3.LauncherState
import com.android.launcher3.logging.StatsLogManager
import com.android.launcher3.model.data.ItemInfo
import com.android.launcher3.statehandlers.DepthController
import com.android.launcher3.statemanager.StateManager
+import com.android.launcher3.util.ComponentKey
import com.android.launcher3.util.SplitConfigurationOptions
import com.android.launcher3.util.withArgCaptor
import com.android.quickstep.RecentsModel
@@ -60,6 +62,9 @@
lateinit var splitSelectStateController: SplitSelectStateController
+ private val primaryUserHandle = UserHandle(ActivityManager.RunningTaskInfo().userId)
+ private val nonPrimaryUserHandle = UserHandle(ActivityManager.RunningTaskInfo().userId + 10)
+
@Before
fun setup() {
MockitoAnnotations.initMocks(this)
@@ -77,6 +82,7 @@
@Test
fun activeTasks_noMatchingTasks() {
+ val nonMatchingComponent = ComponentKey(ComponentName("no", "match"), primaryUserHandle)
val groupTask1 =
generateGroupTask(
ComponentName("pomegranate", "juice"),
@@ -100,7 +106,7 @@
val consumer =
withArgCaptor<Consumer<ArrayList<GroupTask>>> {
splitSelectStateController.findLastActiveTaskAndRunCallback(
- ComponentName("no", "match"),
+ nonMatchingComponent,
taskConsumer
)
verify(recentsModel).getTasks(capture())
@@ -114,6 +120,8 @@
fun activeTasks_singleMatchingTask() {
val matchingPackage = "hotdog"
val matchingClass = "juice"
+ val matchingComponent =
+ ComponentKey(ComponentName(matchingPackage, matchingClass), primaryUserHandle)
val groupTask1 =
generateGroupTask(
ComponentName(matchingPackage, matchingClass),
@@ -149,7 +157,100 @@
val consumer =
withArgCaptor<Consumer<ArrayList<GroupTask>>> {
splitSelectStateController.findLastActiveTaskAndRunCallback(
- ComponentName(matchingPackage, matchingClass),
+ matchingComponent,
+ taskConsumer
+ )
+ verify(recentsModel).getTasks(capture())
+ }
+
+ // Send our mocked tasks
+ consumer.accept(tasks)
+ }
+
+ @Test
+ fun activeTasks_skipTaskWithDifferentUser() {
+ val matchingPackage = "hotdog"
+ val matchingClass = "juice"
+ val nonPrimaryUserComponent =
+ ComponentKey(ComponentName(matchingPackage, matchingClass), nonPrimaryUserHandle)
+ val groupTask1 =
+ generateGroupTask(
+ ComponentName(matchingPackage, matchingClass),
+ ComponentName("pomegranate", "juice")
+ )
+ val groupTask2 =
+ generateGroupTask(
+ ComponentName("pumpkin", "pie"),
+ ComponentName("personal", "computer")
+ )
+ val tasks: ArrayList<GroupTask> = ArrayList()
+ tasks.add(groupTask1)
+ tasks.add(groupTask2)
+
+ // Assertions happen in the callback we get from what we pass into
+ // #findLastActiveTaskAndRunCallback
+ val taskConsumer =
+ Consumer<Task> { assertNull("No tasks should have matched", it /*task*/) }
+
+ // Capture callback from recentsModel#getTasks()
+ val consumer =
+ withArgCaptor<Consumer<ArrayList<GroupTask>>> {
+ splitSelectStateController.findLastActiveTaskAndRunCallback(
+ nonPrimaryUserComponent,
+ taskConsumer
+ )
+ verify(recentsModel).getTasks(capture())
+ }
+
+ // Send our mocked tasks
+ consumer.accept(tasks)
+ }
+
+ @Test
+ fun activeTasks_findTaskAsNonPrimaryUser() {
+ val matchingPackage = "hotdog"
+ val matchingClass = "juice"
+ val nonPrimaryUserComponent =
+ ComponentKey(ComponentName(matchingPackage, matchingClass), nonPrimaryUserHandle)
+ val groupTask1 =
+ generateGroupTask(
+ ComponentName(matchingPackage, matchingClass),
+ nonPrimaryUserHandle,
+ ComponentName("pomegranate", "juice"),
+ nonPrimaryUserHandle
+ )
+ val groupTask2 =
+ generateGroupTask(
+ ComponentName("pumpkin", "pie"),
+ ComponentName("personal", "computer")
+ )
+ val tasks: ArrayList<GroupTask> = ArrayList()
+ tasks.add(groupTask1)
+ tasks.add(groupTask2)
+
+ // Assertions happen in the callback we get from what we pass into
+ // #findLastActiveTaskAndRunCallback
+ val taskConsumer =
+ Consumer<Task> {
+ assertEquals(
+ "ComponentName package mismatched",
+ it.key.baseIntent.component.packageName,
+ matchingPackage
+ )
+ assertEquals(
+ "ComponentName class mismatched",
+ it.key.baseIntent.component.className,
+ matchingClass
+ )
+ assertEquals("userId mismatched", it.key.userId, nonPrimaryUserHandle.identifier)
+ assertEquals(it, groupTask1.task1)
+ }
+
+ // Capture callback from recentsModel#getTasks()
+ val consumer =
+ withArgCaptor<Consumer<ArrayList<GroupTask>>> {
+ splitSelectStateController.findLastActiveTaskAndRunCallback(
+ nonPrimaryUserComponent,
taskConsumer
)
verify(recentsModel).getTasks(capture())
@@ -163,6 +264,8 @@
fun activeTasks_multipleMatchMostRecentTask() {
val matchingPackage = "hotdog"
val matchingClass = "juice"
+ val matchingComponent =
+ ComponentKey(ComponentName(matchingPackage, matchingClass), primaryUserHandle)
val groupTask1 =
generateGroupTask(
ComponentName(matchingPackage, matchingClass),
@@ -198,7 +301,7 @@
val consumer =
withArgCaptor<Consumer<ArrayList<GroupTask>>> {
splitSelectStateController.findLastActiveTaskAndRunCallback(
- ComponentName(matchingPackage, matchingClass),
+ matchingComponent,
taskConsumer
)
verify(recentsModel).getTasks(capture())
@@ -245,6 +348,7 @@
assertFalse(splitSelectStateController.isSplitSelectActive)
}
+ // Generate GroupTask with default userId.
private fun generateGroupTask(
task1ComponentName: ComponentName,
task2ComponentName: ComponentName
@@ -268,4 +372,34 @@
SplitConfigurationOptions.SplitBounds(Rect(), Rect(), -1, -1)
)
}
+
+ // Generate GroupTask with custom user handles.
+ private fun generateGroupTask(
+ task1ComponentName: ComponentName,
+ userHandle1: UserHandle,
+ task2ComponentName: ComponentName,
+ userHandle2: UserHandle
+ ): GroupTask {
+ val task1 = Task()
+ var taskInfo = ActivityManager.RunningTaskInfo()
+ // Apply custom userHandle1
+ taskInfo.userId = userHandle1.identifier
+ var intent = Intent()
+ intent.component = task1ComponentName
+ taskInfo.baseIntent = intent
+ task1.key = Task.TaskKey(taskInfo)
+ val task2 = Task()
+ taskInfo = ActivityManager.RunningTaskInfo()
+ // Apply custom userHandle2
+ taskInfo.userId = userHandle2.identifier
+ intent = Intent()
+ intent.component = task2ComponentName
+ taskInfo.baseIntent = intent
+ task2.key = Task.TaskKey(taskInfo)
+ return GroupTask(
+ task1,
+ task2,
+ SplitConfigurationOptions.SplitBounds(Rect(), Rect(), -1, -1)
+ )
+ }
}
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index af24334..b1159cd 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -247,10 +247,6 @@
270394392, "ENABLE_SEARCH_RESULT_LAUNCH_TRANSITION", false,
"Enable option to launch search results using the new view container transitions");
- public static final BooleanFlag TWO_PREDICTED_ROWS_ALL_APPS_SEARCH = getReleaseFlag(270394225,
- "TWO_PREDICTED_ROWS_ALL_APPS_SEARCH", false,
- "Use 2 rows of app predictions in All Apps search zero-state");
-
public static final BooleanFlag ENABLE_SHOW_KEYBOARD_OPTION_IN_ALL_APPS = getReleaseFlag(
270394468, "ENABLE_SHOW_KEYBOARD_OPTION_IN_ALL_APPS", true,
"Enable option to show keyboard when going to all-apps");
@@ -354,10 +350,6 @@
"Enable the ability to generate monochromatic icons, if it is not provided by the app"
);
- public static final BooleanFlag ENABLE_DREAM_TRANSITION = getDebugFlag(270396364,
- "ENABLE_DREAM_TRANSITION", true,
- "Enable the launcher transition when the device enters a dream");
-
public static final BooleanFlag ENABLE_TASKBAR_EDU_TOOLTIP = getDebugFlag(270396268,
"ENABLE_TASKBAR_EDU_TOOLTIP", true,
"Enable the tooltip version of the Taskbar education flow.");
@@ -384,10 +376,6 @@
"ENABLE_KEYBOARD_QUICK_SWITCH", false,
"Enables keyboard quick switching");
- public static final BooleanFlag ENABLE_SMARTSPACE_DEFAULT_DATE_REMOVED = getDebugFlag(269761613,
- "ENABLE_SMARTSPACE_DEFAULT_DATE_REMOVED", false,
- "Enables remove smartspace default date");
-
public static class BooleanFlag {
private final boolean mCurrentValue;