Loading quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java +3 −2 Original line number Diff line number Diff line Loading @@ -88,6 +88,7 @@ import com.android.launcher3.testing.TestLogging; 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; Loading @@ -105,7 +106,6 @@ import com.android.systemui.unfold.updates.RotationChangeProvider; 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 Loading Loading @@ -877,8 +877,9 @@ public class TaskbarActivityContext extends BaseTaskbarContext { * (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 = Loading quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java +8 −4 Original line number Diff line number Diff line Loading @@ -30,16 +30,15 @@ import androidx.annotation.Nullable; 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 Loading Loading @@ -189,8 +188,12 @@ public class TaskbarUIController { 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 Loading @@ -206,8 +209,9 @@ public class TaskbarUIController { */ 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); Loading quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java +5 −1 Original line number Diff line number Diff line Loading @@ -136,6 +136,7 @@ import com.android.launcher3.uioverrides.touchcontrollers.TaskViewTouchControlle 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; Loading Loading @@ -574,10 +575,13 @@ public class QuickstepLauncher extends Launcher { @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 Loading quickstep/src/com/android/quickstep/util/SplitSelectStateController.java +7 −6 Original line number Diff line number Diff line Loading @@ -29,7 +29,6 @@ import android.app.ActivityManager; 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; Loading Loading @@ -58,6 +57,7 @@ import com.android.launcher3.statehandlers.DepthController; 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; Loading Loading @@ -162,7 +162,7 @@ public class SplitSelectStateController { * 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; Loading @@ -170,12 +170,12 @@ public class SplitSelectStateController { 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; } Loading @@ -189,13 +189,14 @@ public class SplitSelectStateController { * 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(); } /** Loading quickstep/tests/src/com/android/quickstep/util/SplitSelectStateControllerTest.kt +137 −3 Original line number Diff line number Diff line Loading @@ -23,12 +23,14 @@ import android.content.Context 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 Loading Loading @@ -60,6 +62,9 @@ class SplitSelectStateControllerTest { 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) Loading @@ -77,6 +82,7 @@ class SplitSelectStateControllerTest { @Test fun activeTasks_noMatchingTasks() { val nonMatchingComponent = ComponentKey(ComponentName("no", "match"), primaryUserHandle) val groupTask1 = generateGroupTask( ComponentName("pomegranate", "juice"), Loading @@ -100,7 +106,7 @@ class SplitSelectStateControllerTest { val consumer = withArgCaptor<Consumer<ArrayList<GroupTask>>> { splitSelectStateController.findLastActiveTaskAndRunCallback( ComponentName("no", "match"), nonMatchingComponent, taskConsumer ) verify(recentsModel).getTasks(capture()) Loading @@ -114,6 +120,8 @@ class SplitSelectStateControllerTest { fun activeTasks_singleMatchingTask() { val matchingPackage = "hotdog" val matchingClass = "juice" val matchingComponent = ComponentKey(ComponentName(matchingPackage, matchingClass), primaryUserHandle) val groupTask1 = generateGroupTask( ComponentName(matchingPackage, matchingClass), Loading Loading @@ -149,7 +157,100 @@ class SplitSelectStateControllerTest { val consumer = withArgCaptor<Consumer<ArrayList<GroupTask>>> { splitSelectStateController.findLastActiveTaskAndRunCallback( 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()) Loading @@ -163,6 +264,8 @@ class SplitSelectStateControllerTest { fun activeTasks_multipleMatchMostRecentTask() { val matchingPackage = "hotdog" val matchingClass = "juice" val matchingComponent = ComponentKey(ComponentName(matchingPackage, matchingClass), primaryUserHandle) val groupTask1 = generateGroupTask( ComponentName(matchingPackage, matchingClass), Loading Loading @@ -198,7 +301,7 @@ class SplitSelectStateControllerTest { val consumer = withArgCaptor<Consumer<ArrayList<GroupTask>>> { splitSelectStateController.findLastActiveTaskAndRunCallback( ComponentName(matchingPackage, matchingClass), matchingComponent, taskConsumer ) verify(recentsModel).getTasks(capture()) Loading Loading @@ -245,6 +348,7 @@ class SplitSelectStateControllerTest { assertFalse(splitSelectStateController.isSplitSelectActive) } // Generate GroupTask with default userId. private fun generateGroupTask( task1ComponentName: ComponentName, task2ComponentName: ComponentName Loading @@ -268,4 +372,34 @@ class SplitSelectStateControllerTest { 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) ) } } Loading
quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java +3 −2 Original line number Diff line number Diff line Loading @@ -88,6 +88,7 @@ import com.android.launcher3.testing.TestLogging; 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; Loading @@ -105,7 +106,6 @@ import com.android.systemui.unfold.updates.RotationChangeProvider; 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 Loading Loading @@ -877,8 +877,9 @@ public class TaskbarActivityContext extends BaseTaskbarContext { * (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 = Loading
quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java +8 −4 Original line number Diff line number Diff line Loading @@ -30,16 +30,15 @@ import androidx.annotation.Nullable; 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 Loading Loading @@ -189,8 +188,12 @@ public class TaskbarUIController { 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 Loading @@ -206,8 +209,9 @@ public class TaskbarUIController { */ 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); Loading
quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java +5 −1 Original line number Diff line number Diff line Loading @@ -136,6 +136,7 @@ import com.android.launcher3.uioverrides.touchcontrollers.TaskViewTouchControlle 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; Loading Loading @@ -574,10 +575,13 @@ public class QuickstepLauncher extends Launcher { @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 Loading
quickstep/src/com/android/quickstep/util/SplitSelectStateController.java +7 −6 Original line number Diff line number Diff line Loading @@ -29,7 +29,6 @@ import android.app.ActivityManager; 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; Loading Loading @@ -58,6 +57,7 @@ import com.android.launcher3.statehandlers.DepthController; 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; Loading Loading @@ -162,7 +162,7 @@ public class SplitSelectStateController { * 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; Loading @@ -170,12 +170,12 @@ public class SplitSelectStateController { 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; } Loading @@ -189,13 +189,14 @@ public class SplitSelectStateController { * 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(); } /** Loading
quickstep/tests/src/com/android/quickstep/util/SplitSelectStateControllerTest.kt +137 −3 Original line number Diff line number Diff line Loading @@ -23,12 +23,14 @@ import android.content.Context 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 Loading Loading @@ -60,6 +62,9 @@ class SplitSelectStateControllerTest { 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) Loading @@ -77,6 +82,7 @@ class SplitSelectStateControllerTest { @Test fun activeTasks_noMatchingTasks() { val nonMatchingComponent = ComponentKey(ComponentName("no", "match"), primaryUserHandle) val groupTask1 = generateGroupTask( ComponentName("pomegranate", "juice"), Loading @@ -100,7 +106,7 @@ class SplitSelectStateControllerTest { val consumer = withArgCaptor<Consumer<ArrayList<GroupTask>>> { splitSelectStateController.findLastActiveTaskAndRunCallback( ComponentName("no", "match"), nonMatchingComponent, taskConsumer ) verify(recentsModel).getTasks(capture()) Loading @@ -114,6 +120,8 @@ class SplitSelectStateControllerTest { fun activeTasks_singleMatchingTask() { val matchingPackage = "hotdog" val matchingClass = "juice" val matchingComponent = ComponentKey(ComponentName(matchingPackage, matchingClass), primaryUserHandle) val groupTask1 = generateGroupTask( ComponentName(matchingPackage, matchingClass), Loading Loading @@ -149,7 +157,100 @@ class SplitSelectStateControllerTest { val consumer = withArgCaptor<Consumer<ArrayList<GroupTask>>> { splitSelectStateController.findLastActiveTaskAndRunCallback( 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()) Loading @@ -163,6 +264,8 @@ class SplitSelectStateControllerTest { fun activeTasks_multipleMatchMostRecentTask() { val matchingPackage = "hotdog" val matchingClass = "juice" val matchingComponent = ComponentKey(ComponentName(matchingPackage, matchingClass), primaryUserHandle) val groupTask1 = generateGroupTask( ComponentName(matchingPackage, matchingClass), Loading Loading @@ -198,7 +301,7 @@ class SplitSelectStateControllerTest { val consumer = withArgCaptor<Consumer<ArrayList<GroupTask>>> { splitSelectStateController.findLastActiveTaskAndRunCallback( ComponentName(matchingPackage, matchingClass), matchingComponent, taskConsumer ) verify(recentsModel).getTasks(capture()) Loading Loading @@ -245,6 +348,7 @@ class SplitSelectStateControllerTest { assertFalse(splitSelectStateController.isSplitSelectActive) } // Generate GroupTask with default userId. private fun generateGroupTask( task1ComponentName: ComponentName, task2ComponentName: ComponentName Loading @@ -268,4 +372,34 @@ class SplitSelectStateControllerTest { 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) ) } }