summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Pragya Bajoria <pragyabajoria@google.com> 2024-11-26 23:07:53 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2024-11-26 23:07:53 +0000
commit60b9c6ea9ab19a9cc026d6b715aa6e0e8bf643d7 (patch)
tree93fc461327c291f7a3655ff0fac0dba07c08cef9
parentdd56cbca41b8bf803186770a11a9a4472b7e8d73 (diff)
parent5c5ec0c92e5cfc81588e79bf9ac016cddb6cd6f5 (diff)
Merge "Update Desktop Mode repositories to be user-aware." into main
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java17
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java23
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java54
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/dagger/pip/Pip1Module.java6
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/dagger/pip/Pip2Module.java6
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopActivityOrientationChangeHandler.kt9
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopImmersiveController.kt18
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopMixedTransitionHandler.kt4
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopRepository.kt24
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTaskChangeListener.kt10
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt16
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksLimiter.kt27
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksTransitionObserver.kt13
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopUserRepositories.kt109
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/compatui/SystemModalsTransitionHandler.kt6
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/persistence/DesktopPersistentRepository.kt25
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/persistence/DesktopRepositoryInitializer.kt6
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/persistence/DesktopRepositoryInitializerImpl.kt63
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java62
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java19
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipScheduler.java12
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java54
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopHeaderManageWindowsMenu.kt5
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java32
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java42
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingDecorViewModel.kt5
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingWindowDecoration.kt4
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIControllerTest.java30
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopActivityOrientationChangeHandlerTest.kt21
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopImmersiveControllerTest.kt10
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopMixedTransitionHandlerTest.kt10
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopRepositoryTest.kt8
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTaskChangeListenerTest.kt96
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt19
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksLimiterTest.kt20
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksTransitionObserverTest.kt7
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/compatui/SystemModalsTransitionHandlerTest.kt9
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/persistence/DesktopPersistentRepositoryTest.kt9
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/persistence/DesktopRepositoryInitializerTest.kt231
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/freeform/FreeformTaskListenerTests.java50
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java6
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip2/phone/PipSchedulerTest.java6
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentTasksControllerTest.java38
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentsTransitionHandlerTest.java8
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopHeaderManageWindowsMenuTest.kt20
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTestsBase.kt9
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java15
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingDecorViewModelTest.kt6
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingWindowDecorationTest.kt17
49 files changed, 910 insertions, 406 deletions
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java
index c99d9ba862c1..9d4b4bbb33de 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java
@@ -54,6 +54,7 @@ import com.android.wm.shell.compatui.api.CompatUIEvent;
import com.android.wm.shell.compatui.api.CompatUIHandler;
import com.android.wm.shell.compatui.api.CompatUIInfo;
import com.android.wm.shell.compatui.impl.CompatUIEvents.SizeCompatRestartButtonClicked;
+import com.android.wm.shell.desktopmode.DesktopUserRepositories;
import com.android.wm.shell.sysui.KeyguardChangeListener;
import com.android.wm.shell.sysui.ShellController;
import com.android.wm.shell.sysui.ShellInit;
@@ -65,6 +66,7 @@ import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
+import java.util.Optional;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Function;
@@ -194,7 +196,7 @@ public class CompatUIController implements OnDisplaysChangedListener,
private final CompatUIStatusManager mCompatUIStatusManager;
@NonNull
- private final IntPredicate mInDesktopModePredicate;
+ private final Optional<DesktopUserRepositories> mDesktopUserRepositories;
public CompatUIController(@NonNull Context context,
@NonNull ShellInit shellInit,
@@ -210,7 +212,7 @@ public class CompatUIController implements OnDisplaysChangedListener,
@NonNull CompatUIShellCommandHandler compatUIShellCommandHandler,
@NonNull AccessibilityManager accessibilityManager,
@NonNull CompatUIStatusManager compatUIStatusManager,
- @NonNull IntPredicate isDesktopModeEnablePredicate) {
+ @NonNull Optional<DesktopUserRepositories> desktopUserRepositories) {
mContext = context;
mShellController = shellController;
mDisplayController = displayController;
@@ -226,7 +228,7 @@ public class CompatUIController implements OnDisplaysChangedListener,
mDisappearTimeSupplier = flags -> accessibilityManager.getRecommendedTimeoutMillis(
DISAPPEAR_DELAY_MS, flags);
mCompatUIStatusManager = compatUIStatusManager;
- mInDesktopModePredicate = isDesktopModeEnablePredicate;
+ mDesktopUserRepositories = desktopUserRepositories;
shellInit.addInitCallback(this::onInit, this);
}
@@ -267,7 +269,6 @@ public class CompatUIController implements OnDisplaysChangedListener,
updateActiveTaskInfo(taskInfo);
}
-
// We're showing the first reachability education so we ignore incoming TaskInfo
// until the education flow has completed or we double tap. The double-tap
// basically cancel all the onboarding flow. We don't have to ignore events in case
@@ -865,7 +866,11 @@ public class CompatUIController implements OnDisplaysChangedListener,
}
private boolean isInDesktopMode(@Nullable TaskInfo taskInfo) {
- return taskInfo != null && Flags.skipCompatUiEducationInDesktopMode()
- && mInDesktopModePredicate.test(taskInfo.displayId);
+ if (mDesktopUserRepositories.isEmpty() || taskInfo == null) {
+ return false;
+ }
+ boolean isDesktopModeShowing = mDesktopUserRepositories.get().getCurrent()
+ .getVisibleTaskCount(taskInfo.displayId) > 0;
+ return Flags.skipCompatUiEducationInDesktopMode() && isDesktopModeShowing;
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
index cb9c20e9b7ec..47084e17d029 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
@@ -87,8 +87,8 @@ import com.android.wm.shell.compatui.impl.DefaultCompatUIHandler;
import com.android.wm.shell.compatui.impl.DefaultCompatUIRepository;
import com.android.wm.shell.compatui.impl.DefaultComponentIdGenerator;
import com.android.wm.shell.desktopmode.DesktopMode;
-import com.android.wm.shell.desktopmode.DesktopRepository;
import com.android.wm.shell.desktopmode.DesktopTasksController;
+import com.android.wm.shell.desktopmode.DesktopUserRepositories;
import com.android.wm.shell.displayareahelper.DisplayAreaHelper;
import com.android.wm.shell.displayareahelper.DisplayAreaHelperController;
import com.android.wm.shell.freeform.FreeformComponents;
@@ -138,7 +138,6 @@ import dagger.Module;
import dagger.Provides;
import java.util.Optional;
-import java.util.function.IntPredicate;
/**
* Provides basic dependencies from {@link com.android.wm.shell}, these dependencies are only
@@ -267,7 +266,7 @@ public abstract class WMShellBaseModule {
Lazy<CompatUIShellCommandHandler> compatUIShellCommandHandler,
Lazy<AccessibilityManager> accessibilityManager,
CompatUIRepository compatUIRepository,
- Optional<DesktopRepository> desktopRepository,
+ Optional<DesktopUserRepositories> desktopUserRepositories,
@NonNull CompatUIState compatUIState,
@NonNull CompatUIComponentIdGenerator componentIdGenerator,
@NonNull CompatUIComponentFactory compatUIComponentFactory,
@@ -280,10 +279,6 @@ public abstract class WMShellBaseModule {
new DefaultCompatUIHandler(compatUIRepository, compatUIState,
componentIdGenerator, compatUIComponentFactory, mainExecutor));
}
- final IntPredicate inDesktopModePredicate =
- desktopRepository.<IntPredicate>map(modeTaskRepository -> displayId ->
- modeTaskRepository.getVisibleTaskCount(displayId) > 0)
- .orElseGet(() -> displayId -> false);
return Optional.of(
new CompatUIController(
context,
@@ -300,7 +295,7 @@ public abstract class WMShellBaseModule {
compatUIShellCommandHandler.get(),
accessibilityManager.get(),
compatUIStatusManager,
- inDesktopModePredicate));
+ desktopUserRepositories));
}
@WMSingleton
@@ -704,14 +699,14 @@ public abstract class WMShellBaseModule {
ShellCommandHandler shellCommandHandler,
TaskStackListenerImpl taskStackListener,
ActivityTaskManager activityTaskManager,
- Optional<DesktopRepository> desktopRepository,
+ Optional<DesktopUserRepositories> desktopUserRepositories,
TaskStackTransitionObserver taskStackTransitionObserver,
@ShellMainThread ShellExecutor mainExecutor
) {
return Optional.ofNullable(
RecentTasksController.create(context, shellInit, shellController,
shellCommandHandler, taskStackListener, activityTaskManager,
- desktopRepository, taskStackTransitionObserver, mainExecutor));
+ desktopUserRepositories, taskStackTransitionObserver, mainExecutor));
}
@BindsOptionalOf
@@ -1002,16 +997,16 @@ public abstract class WMShellBaseModule {
@BindsOptionalOf
@DynamicOverride
- abstract DesktopRepository optionalDesktopRepository();
+ abstract DesktopUserRepositories optionalDesktopUserRepositories();
@WMSingleton
@Provides
- static Optional<DesktopRepository> provideDesktopRepository(Context context,
- @DynamicOverride Optional<Lazy<DesktopRepository>> desktopRepository) {
+ static Optional<DesktopUserRepositories> provideDesktopUserRepositories(Context context,
+ @DynamicOverride Optional<Lazy<DesktopUserRepositories>> desktopUserRepositories) {
// Use optional-of-lazy for the dependency that this provider relies on.
// Lazy ensures that this provider will not be the cause the dependency is created
// when it will not be returned due to the condition below.
- return desktopRepository.flatMap((lazy) -> {
+ return desktopUserRepositories.flatMap((lazy) -> {
if (DesktopModeStatus.canEnterDesktopMode(context)) {
return Optional.of(lazy.get());
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
index bdf598eec859..14cabe16416c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
@@ -92,6 +92,7 @@ import com.android.wm.shell.desktopmode.DesktopTaskChangeListener;
import com.android.wm.shell.desktopmode.DesktopTasksController;
import com.android.wm.shell.desktopmode.DesktopTasksLimiter;
import com.android.wm.shell.desktopmode.DesktopTasksTransitionObserver;
+import com.android.wm.shell.desktopmode.DesktopUserRepositories;
import com.android.wm.shell.desktopmode.DragToDesktopTransitionHandler;
import com.android.wm.shell.desktopmode.EnterDesktopTaskTransitionHandler;
import com.android.wm.shell.desktopmode.ExitDesktopTaskTransitionHandler;
@@ -363,7 +364,7 @@ public abstract class WMShellModule {
Context context,
ShellInit shellInit,
ShellTaskOrganizer shellTaskOrganizer,
- Optional<DesktopRepository> desktopRepository,
+ Optional<DesktopUserRepositories> desktopUserRepositories,
Optional<DesktopTasksController> desktopTasksController,
LaunchAdjacentController launchAdjacentController,
WindowDecorViewModel windowDecorViewModel,
@@ -375,7 +376,7 @@ public abstract class WMShellModule {
context,
init,
shellTaskOrganizer,
- desktopRepository,
+ desktopUserRepositories,
desktopTasksController,
launchAdjacentController,
windowDecorViewModel,
@@ -691,7 +692,7 @@ public abstract class WMShellModule {
DesktopModeDragAndDropTransitionHandler desktopModeDragAndDropTransitionHandler,
ToggleResizeDesktopTaskTransitionHandler toggleResizeDesktopTaskTransitionHandler,
DragToDesktopTransitionHandler dragToDesktopTransitionHandler,
- @DynamicOverride DesktopRepository desktopRepository,
+ @DynamicOverride DesktopUserRepositories desktopUserRepositories,
Optional<DesktopImmersiveController> desktopImmersiveController,
DesktopModeLoggerTransitionObserver desktopModeLoggerTransitionObserver,
LaunchAdjacentController launchAdjacentController,
@@ -727,7 +728,7 @@ public abstract class WMShellModule {
toggleResizeDesktopTaskTransitionHandler,
dragToDesktopTransitionHandler,
desktopImmersiveController.get(),
- desktopRepository,
+ desktopUserRepositories,
recentsTransitionHandler,
multiInstanceHelper,
mainExecutor,
@@ -750,7 +751,7 @@ public abstract class WMShellModule {
ShellTaskOrganizer shellTaskOrganizer,
ToggleResizeDesktopTaskTransitionHandler toggleResizeDesktopTaskTransitionHandler,
ReturnToDragStartAnimator returnToDragStartAnimator,
- @DynamicOverride DesktopRepository desktopRepository,
+ @DynamicOverride DesktopUserRepositories desktopUserRepositories,
DesktopModeEventLogger desktopModeEventLogger) {
return new DesktopTilingDecorViewModel(
context,
@@ -761,7 +762,7 @@ public abstract class WMShellModule {
shellTaskOrganizer,
toggleResizeDesktopTaskTransitionHandler,
returnToDragStartAnimator,
- desktopRepository,
+ desktopUserRepositories,
desktopModeEventLogger
);
}
@@ -769,10 +770,10 @@ public abstract class WMShellModule {
@WMSingleton
@Provides
static Optional<TaskChangeListener> provideDesktopTaskChangeListener(
- Context context, @DynamicOverride DesktopRepository desktopRepository) {
+ Context context, @DynamicOverride DesktopUserRepositories desktopUserRepositories) {
if (ENABLE_WINDOWING_TRANSITION_HANDLERS_OBSERVERS.isTrue()
&& DesktopModeStatus.canEnterDesktopMode(context)) {
- return Optional.of(new DesktopTaskChangeListener(desktopRepository));
+ return Optional.of(new DesktopTaskChangeListener(desktopUserRepositories));
}
return Optional.empty();
}
@@ -782,7 +783,7 @@ public abstract class WMShellModule {
static Optional<DesktopTasksLimiter> provideDesktopTasksLimiter(
Context context,
Transitions transitions,
- @DynamicOverride DesktopRepository desktopRepository,
+ @DynamicOverride DesktopUserRepositories desktopUserRepositories,
ShellTaskOrganizer shellTaskOrganizer,
InteractionJankMonitor interactionJankMonitor,
@ShellMainThread Handler handler) {
@@ -795,7 +796,7 @@ public abstract class WMShellModule {
return Optional.of(
new DesktopTasksLimiter(
transitions,
- desktopRepository,
+ desktopUserRepositories,
shellTaskOrganizer,
maxTaskLimit,
interactionJankMonitor,
@@ -809,7 +810,7 @@ public abstract class WMShellModule {
Context context,
ShellInit shellInit,
Transitions transitions,
- @DynamicOverride DesktopRepository desktopRepository,
+ @DynamicOverride DesktopUserRepositories desktopUserRepositories,
DisplayController displayController,
ShellTaskOrganizer shellTaskOrganizer,
ShellCommandHandler shellCommandHandler) {
@@ -818,7 +819,7 @@ public abstract class WMShellModule {
new DesktopImmersiveController(
shellInit,
transitions,
- desktopRepository,
+ desktopUserRepositories,
displayController,
shellTaskOrganizer,
shellCommandHandler));
@@ -883,7 +884,7 @@ public abstract class WMShellModule {
ShellCommandHandler shellCommandHandler,
IWindowManager windowManager,
ShellTaskOrganizer taskOrganizer,
- @DynamicOverride DesktopRepository desktopRepository,
+ @DynamicOverride DesktopUserRepositories desktopUserRepositories,
DisplayController displayController,
ShellController shellController,
DisplayInsetsController displayInsetsController,
@@ -910,7 +911,7 @@ public abstract class WMShellModule {
}
return Optional.of(new DesktopModeWindowDecorViewModel(context, shellExecutor, mainHandler,
mainChoreographer, bgExecutor, shellInit, shellCommandHandler, windowManager,
- taskOrganizer, desktopRepository, displayController, shellController,
+ taskOrganizer, desktopUserRepositories, displayController, shellController,
displayInsetsController, syncQueue, transitions, desktopTasksController,
desktopImmersiveController.get(),
rootTaskDisplayAreaOrganizer, interactionJankMonitor, genericLinksParser,
@@ -928,7 +929,7 @@ public abstract class WMShellModule {
@ShellAnimationThread ShellExecutor animExecutor,
ShellInit shellInit,
Transitions transitions,
- @DynamicOverride DesktopRepository desktopRepository) {
+ @DynamicOverride DesktopUserRepositories desktopUserRepositories) {
if (!DesktopModeStatus.canEnterDesktopMode(context)
|| !ENABLE_DESKTOP_WINDOWING_MODALS_POLICY.isTrue()
|| !Flags.enableDesktopSystemDialogsTransitions()) {
@@ -937,7 +938,7 @@ public abstract class WMShellModule {
return Optional.of(
new SystemModalsTransitionHandler(
context, mainExecutor, animExecutor, shellInit, transitions,
- desktopRepository));
+ desktopUserRepositories));
}
@WMSingleton
@@ -996,16 +997,17 @@ public abstract class WMShellModule {
@WMSingleton
@Provides
@DynamicOverride
- static DesktopRepository provideDesktopRepository(
+ static DesktopUserRepositories provideDesktopUserRepositories(
Context context,
ShellInit shellInit,
DesktopPersistentRepository desktopPersistentRepository,
DesktopRepositoryInitializer desktopRepositoryInitializer,
- @ShellMainThread CoroutineScope mainScope
+ @ShellMainThread CoroutineScope mainScope,
+ UserManager userManager
) {
- return new DesktopRepository(context, shellInit, desktopPersistentRepository,
+ return new DesktopUserRepositories(context, shellInit, desktopPersistentRepository,
desktopRepositoryInitializer,
- mainScope);
+ mainScope, userManager);
}
@WMSingleton
@@ -1016,7 +1018,7 @@ public abstract class WMShellModule {
ShellTaskOrganizer shellTaskOrganizer,
TaskStackListenerImpl taskStackListener,
ToggleResizeDesktopTaskTransitionHandler toggleResizeDesktopTaskTransitionHandler,
- @DynamicOverride DesktopRepository desktopRepository) {
+ @DynamicOverride DesktopUserRepositories desktopUserRepositories) {
if (DesktopModeStatus.canEnterDesktopMode(context)) {
return Optional.of(
new DesktopActivityOrientationChangeHandler(
@@ -1025,7 +1027,7 @@ public abstract class WMShellModule {
shellTaskOrganizer,
taskStackListener,
toggleResizeDesktopTaskTransitionHandler,
- desktopRepository));
+ desktopUserRepositories));
}
return Optional.empty();
}
@@ -1034,12 +1036,12 @@ public abstract class WMShellModule {
@Provides
static Optional<DesktopTasksTransitionObserver> provideDesktopTasksTransitionObserver(
Context context,
- Optional<DesktopRepository> desktopRepository,
+ Optional<DesktopUserRepositories> desktopUserRepositories,
Transitions transitions,
ShellTaskOrganizer shellTaskOrganizer,
Optional<DesktopMixedTransitionHandler> desktopMixedTransitionHandler,
ShellInit shellInit) {
- return desktopRepository.flatMap(
+ return desktopUserRepositories.flatMap(
repository ->
Optional.of(
new DesktopTasksTransitionObserver(
@@ -1056,7 +1058,7 @@ public abstract class WMShellModule {
static Optional<DesktopMixedTransitionHandler> provideDesktopMixedTransitionHandler(
Context context,
Transitions transitions,
- @DynamicOverride DesktopRepository desktopRepository,
+ @DynamicOverride DesktopUserRepositories desktopUserRepositories,
FreeformTaskTransitionHandler freeformTaskTransitionHandler,
CloseDesktopTaskTransitionHandler closeDesktopTaskTransitionHandler,
Optional<DesktopImmersiveController> desktopImmersiveController,
@@ -1074,7 +1076,7 @@ public abstract class WMShellModule {
new DesktopMixedTransitionHandler(
context,
transitions,
- desktopRepository,
+ desktopUserRepositories,
freeformTaskTransitionHandler,
closeDesktopTaskTransitionHandler,
desktopImmersiveController.get(),
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/pip/Pip1Module.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/pip/Pip1Module.java
index 3cd5df3121c1..cfdfe3d52011 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/pip/Pip1Module.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/pip/Pip1Module.java
@@ -42,7 +42,7 @@ import com.android.wm.shell.common.pip.PipUiEventLogger;
import com.android.wm.shell.common.pip.SizeSpecSource;
import com.android.wm.shell.dagger.WMShellBaseModule;
import com.android.wm.shell.dagger.WMSingleton;
-import com.android.wm.shell.desktopmode.DesktopRepository;
+import com.android.wm.shell.desktopmode.DesktopUserRepositories;
import com.android.wm.shell.onehanded.OneHandedController;
import com.android.wm.shell.pip.PipAnimationController;
import com.android.wm.shell.pip.PipParamsChangedForwarder;
@@ -171,7 +171,7 @@ public abstract class Pip1Module {
PipParamsChangedForwarder pipParamsChangedForwarder,
Optional<SplitScreenController> splitScreenControllerOptional,
Optional<PipPerfHintController> pipPerfHintControllerOptional,
- Optional<DesktopRepository> desktopRepositoryOptional,
+ Optional<DesktopUserRepositories> desktopUserRepositoriesOptional,
RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer,
DisplayController displayController,
PipUiEventLogger pipUiEventLogger, ShellTaskOrganizer shellTaskOrganizer,
@@ -181,7 +181,7 @@ public abstract class Pip1Module {
pipBoundsAlgorithm, menuPhoneController, pipAnimationController,
pipSurfaceTransactionHelper, pipTransitionController, pipParamsChangedForwarder,
splitScreenControllerOptional, pipPerfHintControllerOptional,
- desktopRepositoryOptional, rootTaskDisplayAreaOrganizer, displayController,
+ desktopUserRepositoriesOptional, rootTaskDisplayAreaOrganizer, displayController,
pipUiEventLogger, shellTaskOrganizer, mainExecutor);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/pip/Pip2Module.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/pip/Pip2Module.java
index 7507e0458c48..3a9961917f79 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/pip/Pip2Module.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/pip/Pip2Module.java
@@ -39,7 +39,7 @@ import com.android.wm.shell.common.pip.PipUtils;
import com.android.wm.shell.common.pip.SizeSpecSource;
import com.android.wm.shell.dagger.WMShellBaseModule;
import com.android.wm.shell.dagger.WMSingleton;
-import com.android.wm.shell.desktopmode.DesktopRepository;
+import com.android.wm.shell.desktopmode.DesktopUserRepositories;
import com.android.wm.shell.pip2.phone.PhonePipMenuController;
import com.android.wm.shell.pip2.phone.PipController;
import com.android.wm.shell.pip2.phone.PipMotionHelper;
@@ -131,10 +131,10 @@ public abstract class Pip2Module {
PipBoundsState pipBoundsState,
@ShellMainThread ShellExecutor mainExecutor,
PipTransitionState pipTransitionState,
- Optional<DesktopRepository> desktopRepositoryOptional,
+ Optional<DesktopUserRepositories> desktopUserRepositoriesOptional,
RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer) {
return new PipScheduler(context, pipBoundsState, mainExecutor, pipTransitionState,
- desktopRepositoryOptional, rootTaskDisplayAreaOrganizer);
+ desktopUserRepositoriesOptional, rootTaskDisplayAreaOrganizer);
}
@WMSingleton
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopActivityOrientationChangeHandler.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopActivityOrientationChangeHandler.kt
index 606aa6cd3353..c0bf40b9c461 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopActivityOrientationChangeHandler.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopActivityOrientationChangeHandler.kt
@@ -39,7 +39,7 @@ class DesktopActivityOrientationChangeHandler(
private val shellTaskOrganizer: ShellTaskOrganizer,
private val taskStackListener: TaskStackListenerImpl,
private val resizeHandler: ToggleResizeDesktopTaskTransitionHandler,
- private val taskRepository: DesktopRepository,
+ private val desktopUserRepositories: DesktopUserRepositories,
) {
init {
@@ -81,7 +81,9 @@ class DesktopActivityOrientationChangeHandler(
) {
if (!Flags.respectOrientationChangeForUnresizeable()) return
val task = shellTaskOrganizer.getRunningTaskInfo(taskId) ?: return
- if (!isDesktopModeShowing(task.displayId) || !task.isFreeform || task.isResizeable) return
+ val taskRepository = desktopUserRepositories.current
+ val isDesktopModeShowing = taskRepository.getVisibleTaskCount(task.displayId) > 0
+ if (!isDesktopModeShowing || !task.isFreeform || task.isResizeable) return
val taskBounds = task.configuration.windowConfiguration.bounds
val taskHeight = taskBounds.height()
@@ -106,7 +108,4 @@ class DesktopActivityOrientationChangeHandler(
resizeHandler.startTransition(wct)
}
}
-
- private fun isDesktopModeShowing(displayId: Int): Boolean =
- taskRepository.getVisibleTaskCount(displayId) > 0
} \ No newline at end of file
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopImmersiveController.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopImmersiveController.kt
index dd95273dd4f3..79be698773da 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopImmersiveController.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopImmersiveController.kt
@@ -50,7 +50,7 @@ import java.io.PrintWriter
class DesktopImmersiveController(
shellInit: ShellInit,
private val transitions: Transitions,
- private val desktopRepository: DesktopRepository,
+ private val desktopUserRepositories: DesktopUserRepositories,
private val displayController: DisplayController,
private val shellTaskOrganizer: ShellTaskOrganizer,
private val shellCommandHandler: ShellCommandHandler,
@@ -60,14 +60,14 @@ class DesktopImmersiveController(
constructor(
shellInit: ShellInit,
transitions: Transitions,
- desktopRepository: DesktopRepository,
+ desktopUserRepositories: DesktopUserRepositories,
displayController: DisplayController,
shellTaskOrganizer: ShellTaskOrganizer,
shellCommandHandler: ShellCommandHandler,
) : this(
shellInit,
transitions,
- desktopRepository,
+ desktopUserRepositories,
displayController,
shellTaskOrganizer,
shellCommandHandler,
@@ -177,8 +177,9 @@ class DesktopImmersiveController(
reason: ExitReason,
): ExitResult {
if (!Flags.enableFullyImmersiveInDesktop()) return ExitResult.NoExit
- val immersiveTask = desktopRepository.getTaskInFullImmersiveState(displayId)
- ?: return ExitResult.NoExit
+ val immersiveTask =
+ desktopUserRepositories.current.getTaskInFullImmersiveState(displayId)
+ ?: return ExitResult.NoExit
if (immersiveTask == excludeTaskId) {
return ExitResult.NoExit
}
@@ -210,7 +211,7 @@ class DesktopImmersiveController(
reason: ExitReason,
): ExitResult {
if (!Flags.enableFullyImmersiveInDesktop()) return ExitResult.NoExit
- if (desktopRepository.isTaskInFullImmersiveState(taskInfo.taskId)) {
+ if (desktopUserRepositories.current.isTaskInFullImmersiveState(taskInfo.taskId)) {
// A full immersive task is being minimized, make sure the immersive state is broken
// (i.e. resize back to max bounds).
wct.setBounds(taskInfo.token, getExitDestinationBounds(taskInfo))
@@ -377,6 +378,7 @@ class DesktopImmersiveController(
startTransaction: SurfaceControl.Transaction,
finishTransaction: SurfaceControl.Transaction,
) {
+ val desktopRepository: DesktopRepository = desktopUserRepositories.current
// Check if this is a pending external exit transition.
val pendingExit = pendingExternalExitTransitions
.firstOrNull { pendingExit -> pendingExit.transition == transition }
@@ -412,6 +414,7 @@ class DesktopImmersiveController(
}
val startBounds = immersiveChange.startAbsBounds
logV("Direct move for task#%d in %s direction verified", state.taskId, state.direction)
+
when (state.direction) {
Direction.ENTER -> {
desktopRepository.setTaskInFullImmersiveState(
@@ -484,7 +487,8 @@ class DesktopImmersiveController(
val displayLayout = displayController.getDisplayLayout(taskInfo.displayId)
?: error("Expected non-null display layout for displayId: ${taskInfo.displayId}")
return if (Flags.enableRestoreToPreviousSizeFromDesktopImmersive()) {
- desktopRepository.removeBoundsBeforeFullImmersive(taskInfo.taskId)
+ desktopUserRepositories.current
+ .removeBoundsBeforeFullImmersive(taskInfo.taskId)
?: if (ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS.isTrue()) {
calculateInitialBounds(displayLayout, taskInfo)
} else {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopMixedTransitionHandler.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopMixedTransitionHandler.kt
index 82c2ebc7ec77..96bbd58949bd 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopMixedTransitionHandler.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopMixedTransitionHandler.kt
@@ -49,7 +49,7 @@ import com.android.wm.shell.transition.Transitions.TransitionFinishCallback
class DesktopMixedTransitionHandler(
private val context: Context,
private val transitions: Transitions,
- private val desktopRepository: DesktopRepository,
+ private val desktopUserRepositories: DesktopUserRepositories,
private val freeformTaskTransitionHandler: FreeformTaskTransitionHandler,
private val closeDesktopTaskTransitionHandler: CloseDesktopTaskTransitionHandler,
private val desktopImmersiveController: DesktopImmersiveController,
@@ -405,7 +405,7 @@ class DesktopMixedTransitionHandler(
private fun isLastDesktopTask(change: TransitionInfo.Change): Boolean =
change.taskInfo?.let {
- desktopRepository.getExpandedTaskCount(it.displayId) == 1
+ desktopUserRepositories.getProfile(it.userId).getExpandedTaskCount(it.displayId) == 1
} ?: false
private fun findCloseDesktopTaskChange(info: TransitionInfo): TransitionInfo.Change? {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopRepository.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopRepository.kt
index 7fcb7678f6af..ca3dc2d5426e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopRepository.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopRepository.kt
@@ -16,7 +16,7 @@
package com.android.wm.shell.desktopmode
-import android.content.Context
+import android.content.pm.UserInfo
import android.graphics.Rect
import android.graphics.Region
import android.util.ArrayMap
@@ -30,11 +30,8 @@ import androidx.core.util.keyIterator
import androidx.core.util.valueIterator
import com.android.internal.protolog.ProtoLog
import com.android.wm.shell.desktopmode.persistence.DesktopPersistentRepository
-import com.android.wm.shell.desktopmode.persistence.DesktopRepositoryInitializer
import com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE
import com.android.wm.shell.shared.annotations.ShellMainThread
-import com.android.wm.shell.shared.desktopmode.DesktopModeStatus
-import com.android.wm.shell.sysui.ShellInit
import java.io.PrintWriter
import java.util.concurrent.Executor
import java.util.function.Consumer
@@ -43,13 +40,10 @@ import kotlinx.coroutines.launch
/** Tracks desktop data for Android Desktop Windowing. */
class DesktopRepository (
- private val context: Context,
- shellInit: ShellInit,
private val persistentRepository: DesktopPersistentRepository,
- private val repositoryInitializer: DesktopRepositoryInitializer,
@ShellMainThread private val mainCoroutineScope: CoroutineScope,
+ val userId: Int,
){
-
/**
* Task data tracked per desktop.
*
@@ -117,16 +111,6 @@ class DesktopRepository (
this[displayId] ?: DesktopTaskData().also { this[displayId] = it }
}
- init {
- if (DesktopModeStatus.canEnterDesktopMode(context)) {
- shellInit.addInitCallback(::initRepoFromPersistentStorage, this)
- }
- }
-
- private fun initRepoFromPersistentStorage() {
- repositoryInitializer.initialize(this)
- }
-
/** Adds [activeTasksListener] to be notified of updates to active tasks. */
fun addActiveTaskListener(activeTasksListener: ActiveTasksListener) {
activeTasksListeners.add(activeTasksListener)
@@ -276,6 +260,8 @@ class DesktopRepository (
* the set of visible tasks on that display and notifies listeners.
*/
fun updateTask(displayId: Int, taskId: Int, isVisible: Boolean) {
+ logD("updateTask taskId=%d, displayId=%d, isVisible=%b", taskId, displayId, isVisible)
+
if (isVisible) {
// If task is visible, remove it from any other display besides [displayId].
removeVisibleTask(taskId, excludedDisplayId = displayId)
@@ -495,6 +481,7 @@ class DesktopRepository (
persistentRepository.addOrUpdateDesktop(
// Use display id as desktop id for now since only once desktop per display
// is supported.
+ userId = userId,
desktopId = displayId,
visibleTasks = desktopTaskDataByDisplayIdCopy.visibleTasks,
minimizedTasks = desktopTaskDataByDisplayIdCopy.minimizedTasks,
@@ -529,6 +516,7 @@ class DesktopRepository (
)
pw.println("${innerPrefix}minimizedTasks=${data.minimizedTasks.toDumpString()}")
pw.println("${innerPrefix}fullImmersiveTaskId=${data.fullImmersiveTaskId}")
+ pw.println("${innerPrefix}wallpaperActivityToken=${wallpaperActivityToken}")
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTaskChangeListener.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTaskChangeListener.kt
index 94ac2e665f61..80d8bfba99d2 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTaskChangeListener.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTaskChangeListener.kt
@@ -23,10 +23,12 @@ import com.android.wm.shell.freeform.TaskChangeListener
/** Manages tasks handling specific to Android Desktop Mode. */
class DesktopTaskChangeListener(
- private val desktopRepository: DesktopRepository,
+ private val desktopUserRepositories: DesktopUserRepositories,
) : TaskChangeListener {
override fun onTaskOpening(taskInfo: RunningTaskInfo) {
+ val desktopRepository: DesktopRepository =
+ desktopUserRepositories.getProfile(taskInfo.userId)
if (!isFreeformTask(taskInfo) && desktopRepository.isActiveTask(taskInfo.taskId)) {
desktopRepository.removeFreeformTask(taskInfo.displayId, taskInfo.taskId)
return
@@ -37,6 +39,8 @@ class DesktopTaskChangeListener(
}
override fun onTaskChanging(taskInfo: RunningTaskInfo) {
+ val desktopRepository: DesktopRepository =
+ desktopUserRepositories.getProfile(taskInfo.userId)
if (!desktopRepository.isActiveTask(taskInfo.taskId)) return
// Case 1: Freeform task is changed in Desktop Mode.
@@ -61,6 +65,8 @@ class DesktopTaskChangeListener(
}
override fun onTaskMovingToFront(taskInfo: RunningTaskInfo) {
+ val desktopRepository: DesktopRepository =
+ desktopUserRepositories.getProfile(taskInfo.userId)
if (!desktopRepository.isActiveTask(taskInfo.taskId)) return
if (!isFreeformTask(taskInfo)) {
desktopRepository.removeFreeformTask(taskInfo.displayId, taskInfo.taskId)
@@ -74,6 +80,8 @@ class DesktopTaskChangeListener(
}
override fun onTaskClosing(taskInfo: RunningTaskInfo) {
+ val desktopRepository: DesktopRepository =
+ desktopUserRepositories.getProfile(taskInfo.userId)
if (!desktopRepository.isActiveTask(taskInfo.taskId)) return
// TODO: b/370038902 - Handle Activity#finishAndRemoveTask.
if (!DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_BACK_NAVIGATION.isTrue() ||
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
index 5759a66c6566..5cb94f870a2d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
@@ -159,7 +159,7 @@ class DesktopTasksController(
private val toggleResizeDesktopTaskTransitionHandler: ToggleResizeDesktopTaskTransitionHandler,
private val dragToDesktopTransitionHandler: DragToDesktopTransitionHandler,
private val desktopImmersiveController: DesktopImmersiveController,
- private val taskRepository: DesktopRepository,
+ private val userRepositories: DesktopUserRepositories,
private val recentsTransitionHandler: RecentsTransitionHandler,
private val multiInstanceHelper: MultiInstanceHelper,
@ShellMainThread private val mainExecutor: ShellExecutor,
@@ -177,6 +177,7 @@ class DesktopTasksController(
UserChangeListener {
private val desktopMode: DesktopModeImpl
+ private var taskRepository: DesktopRepository
private var visualIndicator: DesktopModeVisualIndicator? = null
private var userId: Int
private val desktopModeShellCommandHandler: DesktopModeShellCommandHandler =
@@ -229,6 +230,7 @@ class DesktopTasksController(
shellInit.addInitCallback({ onInit() }, this)
}
userId = ActivityManager.getCurrentUser()
+ taskRepository = userRepositories.getProfile(userId)
}
private fun onInit() {
@@ -1239,7 +1241,7 @@ class DesktopTasksController(
/* requestCode= */ 0,
intent,
PendingIntent.FLAG_IMMUTABLE,
- /* bundle= */ null,
+ /* options= */ null,
userHandle
)
wct.sendPendingIntent(pendingIntent, intent, options.toBundle())
@@ -1724,8 +1726,7 @@ class DesktopTasksController(
/** Handle task closing by removing wallpaper activity if it's the last active task */
private fun handleTaskClosing(task: RunningTaskInfo, transition: IBinder, requestType: Int): WindowContainerTransaction? {
logV("handleTaskClosing")
- if (!isDesktopModeShowing(task.displayId))
- return null
+ if (!isDesktopModeShowing(task.displayId)) return null
val wct = WindowContainerTransaction()
performDesktopExitCleanupIfNeeded(task.taskId, wct)
@@ -1742,6 +1743,7 @@ class DesktopTasksController(
)
)
}
+
taskbarDesktopTaskListener?.onTaskbarCornerRoundingUpdate(
doesAnyTaskRequireTaskbarRounding(
task.displayId,
@@ -2327,7 +2329,9 @@ class DesktopTasksController(
// TODO(b/366397912): Support full multi-user mode in Windowing.
override fun onUserChanged(newUserId: Int, userContext: Context) {
+ logV("onUserChanged previousUserId=%d, newUserId=%d", userId, newUserId)
userId = newUserId
+ taskRepository = userRepositories.getProfile(userId)
desktopTilingDecorViewModel.onUserChange()
}
@@ -2350,6 +2354,7 @@ class DesktopTasksController(
val innerPrefix = "$prefix "
pw.println("${prefix}DesktopTasksController")
DesktopModeStatus.dump(pw, innerPrefix, context)
+ pw.println("${prefix}userId=$userId")
taskRepository.dump(pw, innerPrefix)
}
@@ -2378,6 +2383,7 @@ class DesktopTasksController(
displayId: Int,
transitionSource: DesktopModeTransitionSource
) {
+ logV("moveFocusedTaskToDesktop")
mainExecutor.execute {
this@DesktopTasksController.moveFocusedTaskToDesktop(displayId, transitionSource)
}
@@ -2387,12 +2393,14 @@ class DesktopTasksController(
displayId: Int,
transitionSource: DesktopModeTransitionSource
) {
+ logV("moveFocusedTaskToFullscreen")
mainExecutor.execute {
this@DesktopTasksController.enterFullscreen(displayId, transitionSource)
}
}
override fun moveFocusedTaskToStageSplit(displayId: Int, leftOrTop: Boolean) {
+ logV("moveFocusedTaskToStageSplit")
mainExecutor.execute { this@DesktopTasksController.enterSplit(displayId, leftOrTop) }
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksLimiter.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksLimiter.kt
index 77af627a948a..62b200a6174e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksLimiter.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksLimiter.kt
@@ -16,6 +16,7 @@
package com.android.wm.shell.desktopmode
+import android.app.ActivityManager
import android.content.Context
import android.os.Handler
import android.os.IBinder
@@ -31,6 +32,7 @@ import com.android.internal.protolog.ProtoLog
import com.android.wm.shell.ShellTaskOrganizer
import com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE
import com.android.wm.shell.shared.annotations.ShellMainThread
+import com.android.wm.shell.sysui.UserChangeListener;
import com.android.wm.shell.transition.Transitions
import com.android.wm.shell.transition.Transitions.TransitionObserver
@@ -43,7 +45,7 @@ import com.android.wm.shell.transition.Transitions.TransitionObserver
*/
class DesktopTasksLimiter (
transitions: Transitions,
- private val taskRepository: DesktopRepository,
+ private val desktopUserRepositories: DesktopUserRepositories,
private val shellTaskOrganizer: ShellTaskOrganizer,
private val maxTasksLimit: Int,
private val interactionJankMonitor: InteractionJankMonitor,
@@ -54,12 +56,15 @@ class DesktopTasksLimiter (
@VisibleForTesting
val leftoverMinimizedTasksRemover = LeftoverMinimizedTasksRemover()
+ private var userId: Int
+
init {
require(maxTasksLimit > 0) {
"DesktopTasksLimiter: maxTasksLimit should be greater than 0. Current value: $maxTasksLimit."
}
transitions.registerObserver(minimizeTransitionObserver)
- taskRepository.addActiveTaskListener(leftoverMinimizedTasksRemover)
+ userId = ActivityManager.getCurrentUser()
+ desktopUserRepositories.current.addActiveTaskListener(leftoverMinimizedTasksRemover)
logV("Starting limiter with a maximum of %d tasks", maxTasksLimit)
}
@@ -84,6 +89,7 @@ class DesktopTasksLimiter (
startTransaction: SurfaceControl.Transaction,
finishTransaction: SurfaceControl.Transaction
) {
+ val taskRepository = desktopUserRepositories.current
val taskToMinimize = pendingTransitionTokensAndTasks.remove(transition) ?: return
if (!taskRepository.isActiveTask(taskToMinimize.taskId)) return
if (!isTaskReadyForMinimize(info, taskToMinimize)) {
@@ -114,6 +120,7 @@ class DesktopTasksLimiter (
): Boolean {
val taskChange = info.changes.find { change ->
change.taskInfo?.taskId == taskDetails.taskId }
+ val taskRepository = desktopUserRepositories.current
if (taskChange == null) return !taskRepository.isVisibleTask(taskDetails.taskId)
return taskChange.mode == TRANSIT_TO_BACK
}
@@ -151,7 +158,8 @@ class DesktopTasksLimiter (
}
@VisibleForTesting
- inner class LeftoverMinimizedTasksRemover : DesktopRepository.ActiveTasksListener {
+ inner class LeftoverMinimizedTasksRemover
+ : DesktopRepository.ActiveTasksListener, UserChangeListener {
override fun onActiveTasksChanged(displayId: Int) {
// If back navigation is enabled, we shouldn't remove the leftover tasks
if (DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_BACK_NAVIGATION.isTrue()) return
@@ -161,6 +169,7 @@ class DesktopTasksLimiter (
}
fun removeLeftoverMinimizedTasks(displayId: Int, wct: WindowContainerTransaction) {
+ val taskRepository = desktopUserRepositories.current
if (taskRepository.getExpandedTasksOrdered(displayId).isNotEmpty()) return
val remainingMinimizedTasks = taskRepository.getMinimizedTasks(displayId)
if (remainingMinimizedTasks.isEmpty()) return
@@ -173,6 +182,15 @@ class DesktopTasksLimiter (
}
}
}
+
+ override fun onUserChanged(newUserId: Int, userContext: Context) {
+ // Removes active task listener for the previous repository
+ desktopUserRepositories.getProfile(userId).removeActiveTasksListener(this);
+
+ // Sets active listener for the current repository.
+ userId = newUserId
+ desktopUserRepositories.getProfile(newUserId).addActiveTaskListener(this);
+ }
}
/**
@@ -183,6 +201,7 @@ class DesktopTasksLimiter (
*/
private fun minimizeTask(displayId: Int, taskId: Int) {
logV("Minimize taskId=%d, displayId=%d", taskId, displayId)
+ val taskRepository = desktopUserRepositories.current
taskRepository.minimizeTask(displayId, taskId)
}
@@ -196,7 +215,7 @@ class DesktopTasksLimiter (
newFrontTaskId: Int,
): Int? {
logV("addAndGetMinimizeTaskChanges, newFrontTask=%d", newFrontTaskId)
-
+ val taskRepository = desktopUserRepositories.current
val taskIdToMinimize =
getTaskIdToMinimize(
taskRepository.getExpandedTasksOrdered(displayId),
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksTransitionObserver.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksTransitionObserver.kt
index c39c715e685c..d6bb7f95c196 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksTransitionObserver.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksTransitionObserver.kt
@@ -16,6 +16,7 @@
package com.android.wm.shell.desktopmode
+import android.app.ActivityManager
import android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM
import android.content.Context
import android.os.IBinder
@@ -43,7 +44,7 @@ import com.android.wm.shell.transition.Transitions
*/
class DesktopTasksTransitionObserver(
private val context: Context,
- private val desktopRepository: DesktopRepository,
+ private val desktopUserRepositories: DesktopUserRepositories,
private val transitions: Transitions,
private val shellTaskOrganizer: ShellTaskOrganizer,
private val desktopMixedTransitionHandler: DesktopMixedTransitionHandler,
@@ -51,11 +52,13 @@ class DesktopTasksTransitionObserver(
) : Transitions.TransitionObserver {
private var transitionToCloseWallpaper: IBinder? = null
+ private var currentProfileId: Int
init {
if (DesktopModeStatus.canEnterDesktopMode(context)) {
shellInit.addInitCallback(::onInit, this)
}
+ currentProfileId = ActivityManager.getCurrentUser()
}
fun onInit() {
@@ -89,6 +92,7 @@ class DesktopTasksTransitionObserver(
val taskInfo = change.taskInfo
if (taskInfo == null || taskInfo.taskId == -1) continue
+ val desktopRepository = desktopUserRepositories.getProfile(taskInfo.userId)
if (desktopRepository.isActiveTask(taskInfo.taskId) &&
taskInfo.windowingMode != WINDOWING_MODE_FREEFORM) {
desktopRepository.removeFreeformTask(taskInfo.displayId, taskInfo.taskId)
@@ -105,7 +109,7 @@ class DesktopTasksTransitionObserver(
if (taskInfo == null || taskInfo.taskId == -1) {
continue
}
-
+ val desktopRepository = desktopUserRepositories.getProfile(taskInfo.userId)
val visibleTaskCount = desktopRepository.getVisibleTaskCount(taskInfo.displayId)
if (visibleTaskCount > 0 &&
change.mode == TRANSIT_TO_BACK &&
@@ -128,12 +132,13 @@ class DesktopTasksTransitionObserver(
if (taskInfo == null || taskInfo.taskId == -1) {
continue
}
-
+ val desktopRepository = desktopUserRepositories.getProfile(taskInfo.userId)
if (desktopRepository.getVisibleTaskCount(taskInfo.displayId) == 1 &&
change.mode == TRANSIT_CLOSE &&
taskInfo.windowingMode == WINDOWING_MODE_FREEFORM &&
desktopRepository.wallpaperActivityToken != null) {
transitionToCloseWallpaper = transition
+ currentProfileId = taskInfo.userId
}
}
}
@@ -150,6 +155,7 @@ class DesktopTasksTransitionObserver(
// TODO: b/332682201 Update repository state
if (transitionToCloseWallpaper == transition) {
// TODO: b/362469671 - Handle merging the animation when desktop is also closing.
+ val desktopRepository = desktopUserRepositories.getProfile(currentProfileId)
desktopRepository.wallpaperActivityToken?.let { wallpaperActivityToken ->
transitions.startTransition(
TRANSIT_CLOSE,
@@ -167,6 +173,7 @@ class DesktopTasksTransitionObserver(
info.changes.forEach { change ->
change.taskInfo?.let { taskInfo ->
if (DesktopWallpaperActivity.isWallpaperTask(taskInfo)) {
+ val desktopRepository = desktopUserRepositories.getProfile(taskInfo.userId)
when (change.mode) {
WindowManager.TRANSIT_OPEN -> {
desktopRepository.wallpaperActivityToken = taskInfo.token
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopUserRepositories.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopUserRepositories.kt
new file mode 100644
index 000000000000..1e5a1b274729
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopUserRepositories.kt
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.desktopmode
+
+import android.app.ActivityManager
+import android.content.Context
+import android.content.pm.UserInfo
+import android.os.UserManager
+import android.util.SparseArray
+import com.android.window.flags.Flags
+import com.android.internal.protolog.ProtoLog
+import com.android.wm.shell.desktopmode.persistence.DesktopPersistentRepository
+import com.android.wm.shell.desktopmode.persistence.DesktopRepositoryInitializer
+import com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE
+import com.android.wm.shell.shared.annotations.ShellMainThread
+import com.android.wm.shell.shared.desktopmode.DesktopModeStatus
+import com.android.wm.shell.sysui.ShellInit
+import com.android.wm.shell.sysui.UserChangeListener
+import kotlinx.coroutines.CoroutineScope
+
+/** Manages per-user DesktopRepository instances. */
+class DesktopUserRepositories(
+ context: Context,
+ shellInit: ShellInit,
+ private val persistentRepository: DesktopPersistentRepository,
+ private val repositoryInitializer: DesktopRepositoryInitializer,
+ @ShellMainThread private val mainCoroutineScope: CoroutineScope,
+ userManager: UserManager,
+) : UserChangeListener {
+ private var userId: Int
+ private var userIdToProfileIdsMap: MutableMap<Int, List<Int>> = mutableMapOf()
+
+ // TODO(b/357060209): Add caching for this logic to improve efficiency.
+ val current: DesktopRepository
+ get() = desktopRepoByUserId.getOrCreate(userId)
+
+ private val desktopRepoByUserId =
+ object : SparseArray<DesktopRepository>() {
+ /** Gets [DesktopRepository] for existing [userId] or creates a new one. */
+ fun getOrCreate(userId: Int): DesktopRepository =
+ this[userId]
+ ?: DesktopRepository(
+ persistentRepository,
+ mainCoroutineScope,
+ userId)
+ .also { this[userId] = it }
+ }
+
+ init {
+ userId = ActivityManager.getCurrentUser()
+ if (DesktopModeStatus.canEnterDesktopMode(context)) {
+ shellInit.addInitCallback(::initRepoFromPersistentStorage, this)
+ }
+ if (Flags.enableDesktopWindowingHsum()) {
+ userIdToProfileIdsMap[userId] = userManager.getProfiles(userId).map { it.id }
+ }
+ }
+
+ private fun initRepoFromPersistentStorage() {
+ repositoryInitializer.initialize(this)
+ }
+
+ /** Returns [DesktopRepository] for the parent user id. */
+ fun getProfile(profileId: Int): DesktopRepository {
+ if (Flags.enableDesktopWindowingHsum()) {
+ for ((uid, profileIds) in userIdToProfileIdsMap) {
+ if (profileId in profileIds) {
+ return desktopRepoByUserId.getOrCreate(uid)
+ }
+ }
+ }
+ return desktopRepoByUserId.getOrCreate(profileId)
+ }
+
+ override fun onUserChanged(newUserId: Int, userContext: Context) {
+ logD("onUserChanged previousUserId=%d, newUserId=%d", userId, newUserId)
+ userId = newUserId
+ }
+
+ override fun onUserProfilesChanged(profiles: MutableList<UserInfo>) {
+ logD("onUserProfilesChanged profiles=%s", profiles.toString())
+ if (Flags.enableDesktopWindowingHsum()) {
+ // TODO(b/366397912): Remove all persisted profile data when the profile changes.
+ userIdToProfileIdsMap[userId] = profiles.map { it.id }
+ }
+ }
+
+ private fun logD(msg: String, vararg arguments: Any?) {
+ ProtoLog.d(WM_SHELL_DESKTOP_MODE, "%s: $msg", TAG, *arguments)
+ }
+
+ companion object {
+ private const val TAG = "DesktopUserRepositories"
+ }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/compatui/SystemModalsTransitionHandler.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/compatui/SystemModalsTransitionHandler.kt
index 826de08557bd..a428ce18a49e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/compatui/SystemModalsTransitionHandler.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/compatui/SystemModalsTransitionHandler.kt
@@ -29,7 +29,7 @@ import com.android.app.animation.Interpolators
import com.android.internal.protolog.ProtoLog
import com.android.wm.shell.common.ShellExecutor
import com.android.wm.shell.compatui.isTopActivityExemptFromDesktopWindowing
-import com.android.wm.shell.desktopmode.DesktopRepository
+import com.android.wm.shell.desktopmode.DesktopUserRepositories
import com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE
import com.android.wm.shell.shared.TransitionUtil.isClosingMode
import com.android.wm.shell.shared.TransitionUtil.isClosingType
@@ -46,7 +46,7 @@ class SystemModalsTransitionHandler(
private val animExecutor: ShellExecutor,
private val shellInit: ShellInit,
private val transitions: Transitions,
- private val desktopRepository: DesktopRepository,
+ private val desktopUserRepositories: DesktopUserRepositories,
) : TransitionHandler {
private val showingSystemModalsIds = mutableSetOf<Int>()
@@ -156,7 +156,7 @@ class SystemModalsTransitionHandler(
}
private fun isDesktopModeShowing(displayId: Int): Boolean =
- desktopRepository.getVisibleTaskCount(displayId) > 0
+ desktopUserRepositories.current.getVisibleTaskCount(displayId) > 0
override fun handleRequest(
transition: IBinder,
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/persistence/DesktopPersistentRepository.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/persistence/DesktopPersistentRepository.kt
index 9e646f430c98..b7de1f86601c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/persistence/DesktopPersistentRepository.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/persistence/DesktopPersistentRepository.kt
@@ -73,8 +73,8 @@ class DesktopPersistentRepository(
* Reads and returns the [DesktopRepositoryState] proto object from the DataStore for a user. If
* the DataStore is empty or there's an error reading, it returns the default value of Proto.
*/
- private suspend fun getDesktopRepositoryState(
- userId: Int = DEFAULT_USER_ID
+ suspend fun getDesktopRepositoryState(
+ userId: Int
): DesktopRepositoryState? =
try {
dataStoreFlow
@@ -85,12 +85,20 @@ class DesktopPersistentRepository(
null
}
+ suspend fun getUserDesktopRepositoryMap(): Map<Int, DesktopRepositoryState>? =
+ try {
+ dataStoreFlow.first().desktopRepoByUserMap
+ } catch (e: Exception) {
+ Log.e(TAG, "Unable to read from datastore", e)
+ null
+ }
+
/**
* Reads the [Desktop] of a desktop filtering by the [userId] and [desktopId]. Executes the
* [callback] using the [mainCoroutineScope].
*/
suspend fun readDesktop(
- userId: Int = DEFAULT_USER_ID,
+ userId: Int,
desktopId: Int = DEFAULT_DESKTOP_ID,
): Desktop? =
try {
@@ -103,7 +111,7 @@ class DesktopPersistentRepository(
/** Adds or updates a desktop stored in the datastore */
suspend fun addOrUpdateDesktop(
- userId: Int = DEFAULT_USER_ID,
+ userId: Int,
desktopId: Int = 0,
visibleTasks: ArraySet<Int> = ArraySet(),
minimizedTasks: ArraySet<Int> = ArraySet(),
@@ -111,9 +119,9 @@ class DesktopPersistentRepository(
) {
// TODO: b/367609270 - Improve the API to support multi-user
try {
- dataStore.updateData { desktopPersistentRepositories: DesktopPersistentRepositories ->
+ dataStore.updateData { persistentRepositories: DesktopPersistentRepositories ->
val currentRepository =
- desktopPersistentRepositories.getDesktopRepoByUserOrDefault(
+ persistentRepositories.getDesktopRepoByUserOrDefault(
userId, DesktopRepositoryState.getDefaultInstance())
val desktop =
getDesktop(currentRepository, desktopId)
@@ -125,7 +133,7 @@ class DesktopPersistentRepository(
)
.updateZOrder(freeformTasksInZOrder)
- desktopPersistentRepositories
+ persistentRepositories
.toBuilder()
.putDesktopRepoByUser(
userId,
@@ -135,7 +143,7 @@ class DesktopPersistentRepository(
.build())
.build()
}
- } catch (exception: IOException) {
+ } catch (exception: Exception) {
Log.e(
TAG,
"Error in updating desktop mode related data, data is " +
@@ -154,7 +162,6 @@ class DesktopPersistentRepository(
private const val TAG = "DesktopPersistenceRepo"
private const val DESKTOP_REPOSITORIES_DATASTORE_FILE = "desktop_persistent_repositories.pb"
- private const val DEFAULT_USER_ID = 1000
private const val DEFAULT_DESKTOP_ID = 0
object DesktopPersistentRepositoriesSerializer : Serializer<DesktopPersistentRepositories> {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/persistence/DesktopRepositoryInitializer.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/persistence/DesktopRepositoryInitializer.kt
index 771c3d1cb9a1..a26ebbf4c99a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/persistence/DesktopRepositoryInitializer.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/persistence/DesktopRepositoryInitializer.kt
@@ -16,9 +16,9 @@
package com.android.wm.shell.desktopmode.persistence
-import com.android.wm.shell.desktopmode.DesktopRepository
+import com.android.wm.shell.desktopmode.DesktopUserRepositories
-/** Interface for initializing the [DesktopRepository]. */
+/** Interface for initializing the [DesktopUserRepositories]. */
fun interface DesktopRepositoryInitializer {
- fun initialize(repository: DesktopRepository)
+ fun initialize(userRepositories: DesktopUserRepositories)
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/persistence/DesktopRepositoryInitializerImpl.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/persistence/DesktopRepositoryInitializerImpl.kt
index d8156561ff19..9539cbe0e677 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/persistence/DesktopRepositoryInitializerImpl.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/persistence/DesktopRepositoryInitializerImpl.kt
@@ -19,6 +19,7 @@ package com.android.wm.shell.desktopmode.persistence
import android.content.Context
import android.window.DesktopModeFlags
import com.android.wm.shell.desktopmode.DesktopRepository
+import com.android.wm.shell.desktopmode.DesktopUserRepositories
import com.android.wm.shell.shared.annotations.ShellMainThread
import com.android.wm.shell.shared.desktopmode.DesktopModeStatus
import kotlinx.coroutines.CoroutineScope
@@ -35,32 +36,52 @@ class DesktopRepositoryInitializerImpl(
private val persistentRepository: DesktopPersistentRepository,
@ShellMainThread private val mainCoroutineScope: CoroutineScope,
) : DesktopRepositoryInitializer {
- override fun initialize(repository: DesktopRepository) {
+ override fun initialize(userRepositories: DesktopUserRepositories) {
if (!DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_PERSISTENCE.isTrue()) return
// TODO: b/365962554 - Handle the case that user moves to desktop before it's initialized
mainCoroutineScope.launch {
- val desktop = persistentRepository.readDesktop() ?: return@launch
-
- val maxTasks =
- DesktopModeStatus.getMaxTaskLimit(context).takeIf { it > 0 }
- ?: desktop.zOrderedTasksCount
-
- var visibleTasksCount = 0
- desktop.zOrderedTasksList
- // Reverse it so we initialize the repo from bottom to top.
- .reversed()
- .mapNotNull { taskId -> desktop.tasksByTaskIdMap[taskId] }
- .forEach { task ->
- if (task.desktopTaskState == DesktopTaskState.VISIBLE
- && visibleTasksCount < maxTasks
- ) {
- visibleTasksCount++
- repository.addTask(desktop.displayId, task.taskId, isVisible = false)
- } else {
- repository.addTask(desktop.displayId, task.taskId, isVisible = false)
- repository.minimizeTask(desktop.displayId, task.taskId)
+ val desktopUserPersistentRepositoryMap =
+ persistentRepository.getUserDesktopRepositoryMap() ?: return@launch
+ for (userId in desktopUserPersistentRepositoryMap.keys) {
+ val repository = userRepositories.getProfile(userId)
+ val desktopRepositoryState =
+ persistentRepository.getDesktopRepositoryState(userId) ?: continue
+ val desktopByDesktopIdMap = desktopRepositoryState.desktopMap
+ for (desktopId in desktopByDesktopIdMap.keys) {
+ val persistentDesktop =
+ persistentRepository.readDesktop(userId, desktopId) ?: continue
+ val maxTasks =
+ DesktopModeStatus.getMaxTaskLimit(context).takeIf { it > 0 }
+ ?: persistentDesktop.zOrderedTasksCount
+ var visibleTasksCount = 0
+ persistentDesktop.zOrderedTasksList
+ // Reverse it so we initialize the repo from bottom to top.
+ .reversed()
+ .mapNotNull { taskId -> persistentDesktop.tasksByTaskIdMap[taskId] }
+ .forEach { task ->
+ if (task.desktopTaskState == DesktopTaskState.VISIBLE
+ && visibleTasksCount < maxTasks) {
+ visibleTasksCount++
+ repository.addTask(
+ persistentDesktop.displayId,
+ task.taskId,
+ isVisible = false
+ )
+ } else {
+ repository.addTask(
+ persistentDesktop.displayId,
+ task.taskId,
+ isVisible = false
+ )
+ repository.minimizeTask(
+ persistentDesktop.displayId,
+ task.taskId
+ )
+ }
+ }
}
}
}
+
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java
index cd20d97c7964..a17d55fdc2fe 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java
@@ -30,6 +30,7 @@ import com.android.internal.protolog.ProtoLog;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.LaunchAdjacentController;
import com.android.wm.shell.desktopmode.DesktopRepository;
+import com.android.wm.shell.desktopmode.DesktopUserRepositories;
import com.android.wm.shell.desktopmode.DesktopTasksController;
import com.android.wm.shell.protolog.ShellProtoLogGroup;
import com.android.wm.shell.shared.desktopmode.DesktopModeStatus;
@@ -49,7 +50,7 @@ public class FreeformTaskListener implements ShellTaskOrganizer.TaskListener,
private final Context mContext;
private final ShellTaskOrganizer mShellTaskOrganizer;
- private final Optional<DesktopRepository> mDesktopRepository;
+ private final Optional<DesktopUserRepositories> mDesktopUserRepositories;
private final Optional<DesktopTasksController> mDesktopTasksController;
private final WindowDecorViewModel mWindowDecorationViewModel;
private final LaunchAdjacentController mLaunchAdjacentController;
@@ -61,7 +62,7 @@ public class FreeformTaskListener implements ShellTaskOrganizer.TaskListener,
Context context,
ShellInit shellInit,
ShellTaskOrganizer shellTaskOrganizer,
- Optional<DesktopRepository> desktopRepository,
+ Optional<DesktopUserRepositories> desktopUserRepositories,
Optional<DesktopTasksController> desktopTasksController,
LaunchAdjacentController launchAdjacentController,
WindowDecorViewModel windowDecorationViewModel,
@@ -69,7 +70,7 @@ public class FreeformTaskListener implements ShellTaskOrganizer.TaskListener,
mContext = context;
mShellTaskOrganizer = shellTaskOrganizer;
mWindowDecorationViewModel = windowDecorationViewModel;
- mDesktopRepository = desktopRepository;
+ mDesktopUserRepositories = desktopUserRepositories;
mDesktopTasksController = desktopTasksController;
mLaunchAdjacentController = launchAdjacentController;
mTaskChangeListener = taskChangeListener;
@@ -99,8 +100,9 @@ public class FreeformTaskListener implements ShellTaskOrganizer.TaskListener,
if (!DesktopModeFlags.ENABLE_WINDOWING_TRANSITION_HANDLERS_OBSERVERS.isTrue() &&
DesktopModeStatus.canEnterDesktopMode(mContext)) {
- mDesktopRepository.ifPresent(repository -> {
- repository.addTask(taskInfo.displayId, taskInfo.taskId, taskInfo.isVisible);
+ mDesktopUserRepositories.ifPresent(userRepositories -> {
+ DesktopRepository currentRepo = userRepositories.getProfile(taskInfo.userId);
+ currentRepo.addTask(taskInfo.displayId, taskInfo.taskId, taskInfo.isVisible);
});
}
updateLaunchAdjacentController();
@@ -113,21 +115,22 @@ public class FreeformTaskListener implements ShellTaskOrganizer.TaskListener,
mTasks.remove(taskInfo.taskId);
if (!DesktopModeFlags.ENABLE_WINDOWING_TRANSITION_HANDLERS_OBSERVERS.isTrue() &&
- DesktopModeStatus.canEnterDesktopMode(mContext)) {
- mDesktopRepository.ifPresent(repository -> {
- // TODO: b/370038902 - Handle Activity#finishAndRemoveTask.
- if (!DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_BACK_NAVIGATION.isTrue()
- || repository.isClosingTask(taskInfo.taskId)) {
- // A task that's vanishing should be removed:
- // - If it's closed by the X button which means it's marked as a closing task.
- repository.removeClosingTask(taskInfo.taskId);
- repository.removeFreeformTask(taskInfo.displayId, taskInfo.taskId);
- } else {
- repository.updateTask(taskInfo.displayId, taskInfo.taskId, /* isVisible= */
- false);
- repository.minimizeTask(taskInfo.displayId, taskInfo.taskId);
- }
- });
+ DesktopModeStatus.canEnterDesktopMode(mContext)
+ && mDesktopUserRepositories.isPresent()) {
+ DesktopRepository repository =
+ mDesktopUserRepositories.get().getProfile(taskInfo.userId);
+ // TODO: b/370038902 - Handle Activity#finishAndRemoveTask.
+ if (!DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_BACK_NAVIGATION.isTrue()
+ || repository.isClosingTask(taskInfo.taskId)) {
+ // A task that's vanishing should be removed:
+ // - If it's closed by the X button which means it's marked as a closing task.
+ repository.removeClosingTask(taskInfo.taskId);
+ repository.removeFreeformTask(taskInfo.displayId, taskInfo.taskId);
+ } else {
+ repository.updateTask(taskInfo.displayId, taskInfo.taskId, /* isVisible= */
+ false);
+ repository.minimizeTask(taskInfo.displayId, taskInfo.taskId);
+ }
}
mWindowDecorationViewModel.onTaskVanished(taskInfo);
updateLaunchAdjacentController();
@@ -148,11 +151,11 @@ public class FreeformTaskListener implements ShellTaskOrganizer.TaskListener,
// does not propagate all task info changes.
mTaskChangeListener.ifPresent(listener ->
listener.onNonTransitionTaskChanging(taskInfo));
- } else {
- mDesktopRepository.ifPresent(repository -> {
- repository.updateTask(taskInfo.displayId, taskInfo.taskId,
- taskInfo.isVisible);
- });
+ } else if (mDesktopUserRepositories.isPresent()) {
+ DesktopRepository currentRepo =
+ mDesktopUserRepositories.get().getProfile(taskInfo.userId);
+ currentRepo.updateTask(taskInfo.displayId, taskInfo.taskId,
+ taskInfo.isVisible);
}
}
updateLaunchAdjacentController();
@@ -176,10 +179,11 @@ public class FreeformTaskListener implements ShellTaskOrganizer.TaskListener,
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG,
"Freeform Task Focus Changed: #%d focused=%b",
taskInfo.taskId, taskInfo.isFocused);
- if (DesktopModeStatus.canEnterDesktopMode(mContext) && taskInfo.isFocused) {
- mDesktopRepository.ifPresent(repository -> {
- repository.addTask(taskInfo.displayId, taskInfo.taskId, taskInfo.isVisible);
- });
+ if (DesktopModeStatus.canEnterDesktopMode(mContext) && taskInfo.isFocused
+ && mDesktopUserRepositories.isPresent()) {
+ DesktopRepository repository =
+ mDesktopUserRepositories.get().getProfile(taskInfo.userId);
+ repository.addTask(taskInfo.displayId, taskInfo.taskId, taskInfo.isVisible);
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
index fb4afe41e193..af187682d379 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
@@ -94,6 +94,7 @@ import com.android.wm.shell.common.pip.PipPerfHintController;
import com.android.wm.shell.common.pip.PipUiEventLogger;
import com.android.wm.shell.common.pip.PipUtils;
import com.android.wm.shell.desktopmode.DesktopRepository;
+import com.android.wm.shell.desktopmode.DesktopUserRepositories;
import com.android.wm.shell.pip.phone.PipMotionHelper;
import com.android.wm.shell.protolog.ShellProtoLogGroup;
import com.android.wm.shell.shared.animation.Interpolators;
@@ -152,7 +153,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
private final PipSurfaceTransactionHelper mSurfaceTransactionHelper;
private final Optional<SplitScreenController> mSplitScreenOptional;
@Nullable private final PipPerfHintController mPipPerfHintController;
- private final Optional<DesktopRepository> mDesktopRepositoryOptional;
+ private final Optional<DesktopUserRepositories> mDesktopUserRepositoriesOptional;
private final RootTaskDisplayAreaOrganizer mRootTaskDisplayAreaOrganizer;
private final DisplayController mDisplayController;
protected final ShellTaskOrganizer mTaskOrganizer;
@@ -398,7 +399,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
@NonNull PipParamsChangedForwarder pipParamsChangedForwarder,
Optional<SplitScreenController> splitScreenOptional,
Optional<PipPerfHintController> pipPerfHintControllerOptional,
- Optional<DesktopRepository> desktopRepositoryOptional,
+ Optional<DesktopUserRepositories> desktopUserRepositoriesOptional,
RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer,
@NonNull DisplayController displayController,
@NonNull PipUiEventLogger pipUiEventLogger,
@@ -426,7 +427,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
new PipSurfaceTransactionHelper.VsyncSurfaceControlTransactionFactory();
mSplitScreenOptional = splitScreenOptional;
mPipPerfHintController = pipPerfHintControllerOptional.orElse(null);
- mDesktopRepositoryOptional = desktopRepositoryOptional;
+ mDesktopUserRepositoriesOptional = desktopUserRepositoriesOptional;
mRootTaskDisplayAreaOrganizer = rootTaskDisplayAreaOrganizer;
mDisplayController = displayController;
mTaskOrganizer = shellTaskOrganizer;
@@ -764,7 +765,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
// previous freeform bounds that is saved in DesktopRepository.
// 2) If PiP was entered through other means (e.g. user swipe up), exit to initial
// freeform bounds. Note that this case has a flicker at the moment (b/379984108).
- Rect freeformBounds = mDesktopRepositoryOptional.get().removeBoundsBeforeMinimize(
+ Rect freeformBounds = getCurrentRepo().removeBoundsBeforeMinimize(
mTaskInfo.taskId);
return freeformBounds != null
? freeformBounds
@@ -779,11 +780,17 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
/** Returns whether PiP is exiting while we're in desktop mode. */
// TODO(b/377581840): Update this check to include non-minimized cases, e.g. split to PiP etc.
private boolean isPipExitingToDesktopMode() {
- return Flags.enableDesktopWindowingPip() && mDesktopRepositoryOptional.isPresent()
- && (mDesktopRepositoryOptional.get().getVisibleTaskCount(mTaskInfo.displayId) > 0
+ DesktopRepository currentRepo = getCurrentRepo();
+ return Flags.enableDesktopWindowingPip() && currentRepo != null
+ && (currentRepo.getVisibleTaskCount(mTaskInfo.displayId) > 0
|| isDisplayInFreeform());
}
+ private DesktopRepository getCurrentRepo() {
+ return mDesktopUserRepositoriesOptional.map(DesktopUserRepositories::getCurrent).orElse(
+ null);
+ }
+
private void exitLaunchIntoPipTask(WindowContainerTransaction wct) {
wct.startTask(mTaskInfo.launchIntoPipHostTaskId, null /* ActivityOptions */);
mTaskOrganizer.applyTransaction(wct);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipScheduler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipScheduler.java
index 7145e0699765..4461a5c6a70c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipScheduler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipScheduler.java
@@ -39,7 +39,7 @@ import com.android.window.flags.Flags;
import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.pip.PipBoundsState;
-import com.android.wm.shell.desktopmode.DesktopRepository;
+import com.android.wm.shell.desktopmode.DesktopUserRepositories;
import com.android.wm.shell.pip.PipTransitionController;
import com.android.wm.shell.pip2.PipSurfaceTransactionHelper;
import com.android.wm.shell.pip2.animation.PipAlphaAnimator;
@@ -58,7 +58,7 @@ public class PipScheduler {
private final PipBoundsState mPipBoundsState;
private final ShellExecutor mMainExecutor;
private final PipTransitionState mPipTransitionState;
- private final Optional<DesktopRepository> mDesktopRepositoryOptional;
+ private final Optional<DesktopUserRepositories> mDesktopUserRepositoriesOptional;
private final RootTaskDisplayAreaOrganizer mRootTaskDisplayAreaOrganizer;
private PipTransitionController mPipTransitionController;
private PipSurfaceTransactionHelper.SurfaceControlTransactionFactory
@@ -72,13 +72,13 @@ public class PipScheduler {
PipBoundsState pipBoundsState,
ShellExecutor mainExecutor,
PipTransitionState pipTransitionState,
- Optional<DesktopRepository> desktopRepositoryOptional,
+ Optional<DesktopUserRepositories> desktopUserRepositoriesOptional,
RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer) {
mContext = context;
mPipBoundsState = pipBoundsState;
mMainExecutor = mainExecutor;
mPipTransitionState = pipTransitionState;
- mDesktopRepositoryOptional = desktopRepositoryOptional;
+ mDesktopUserRepositoriesOptional = desktopUserRepositoriesOptional;
mRootTaskDisplayAreaOrganizer = rootTaskDisplayAreaOrganizer;
mSurfaceControlTransactionFactory =
@@ -268,8 +268,8 @@ public class PipScheduler {
/** Returns whether PiP is exiting while we're in desktop mode. */
private boolean isPipExitingToDesktopMode() {
- return Flags.enableDesktopWindowingPip() && mDesktopRepositoryOptional.isPresent()
- && (mDesktopRepositoryOptional.get().getVisibleTaskCount(
+ return Flags.enableDesktopWindowingPip() && mDesktopUserRepositoriesOptional.isPresent()
+ && (mDesktopUserRepositoriesOptional.get().getCurrent().getVisibleTaskCount(
Objects.requireNonNull(mPipTransitionState.getPipTaskInfo()).displayId) > 0
|| isDisplayInFreeform());
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java
index 363c95fcf010..441f96728d0c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java
@@ -63,6 +63,7 @@ import com.android.wm.shell.common.SingleInstanceRemoteListener;
import com.android.wm.shell.common.TaskStackListenerCallback;
import com.android.wm.shell.common.TaskStackListenerImpl;
import com.android.wm.shell.desktopmode.DesktopRepository;
+import com.android.wm.shell.desktopmode.DesktopUserRepositories;
import com.android.wm.shell.protolog.ShellProtoLogGroup;
import com.android.wm.shell.shared.GroupedTaskInfo;
import com.android.wm.shell.shared.annotations.ExternalThread;
@@ -72,6 +73,7 @@ import com.android.wm.shell.shared.split.SplitBounds;
import com.android.wm.shell.sysui.ShellCommandHandler;
import com.android.wm.shell.sysui.ShellController;
import com.android.wm.shell.sysui.ShellInit;
+import com.android.wm.shell.sysui.UserChangeListener;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -89,13 +91,14 @@ import java.util.function.Consumer;
*/
public class RecentTasksController implements TaskStackListenerCallback,
RemoteCallable<RecentTasksController>, DesktopRepository.ActiveTasksListener,
- TaskStackTransitionObserver.TaskStackTransitionObserverListener {
+ TaskStackTransitionObserver.TaskStackTransitionObserverListener, UserChangeListener {
private static final String TAG = RecentTasksController.class.getSimpleName();
private final Context mContext;
private final ShellController mShellController;
private final ShellCommandHandler mShellCommandHandler;
- private final Optional<DesktopRepository> mDesktopRepository;
+ private final Optional<DesktopUserRepositories> mDesktopUserRepositories;
+
private final ShellExecutor mMainExecutor;
private final TaskStackListenerImpl mTaskStackListener;
private final RecentTasksImpl mImpl = new RecentTasksImpl();
@@ -108,6 +111,8 @@ public class RecentTasksController implements TaskStackListenerCallback,
// Mapping of split task ids, mappings are symmetrical (ie. if t1 is the taskid of a task in a
// pair, then mSplitTasks[t1] = t2, and mSplitTasks[t2] = t1)
private final SparseIntArray mSplitTasks = new SparseIntArray();
+
+ private int mUserId;
/**
* Maps taskId to {@link SplitBounds} for both taskIDs.
* Meaning there will be two taskId integers mapping to the same object.
@@ -133,7 +138,7 @@ public class RecentTasksController implements TaskStackListenerCallback,
ShellCommandHandler shellCommandHandler,
TaskStackListenerImpl taskStackListener,
ActivityTaskManager activityTaskManager,
- Optional<DesktopRepository> desktopRepository,
+ Optional<DesktopUserRepositories> desktopUserRepositories,
TaskStackTransitionObserver taskStackTransitionObserver,
@ShellMainThread ShellExecutor mainExecutor
) {
@@ -141,7 +146,7 @@ public class RecentTasksController implements TaskStackListenerCallback,
return null;
}
return new RecentTasksController(context, shellInit, shellController, shellCommandHandler,
- taskStackListener, activityTaskManager, desktopRepository,
+ taskStackListener, activityTaskManager, desktopUserRepositories,
taskStackTransitionObserver, mainExecutor);
}
@@ -151,7 +156,7 @@ public class RecentTasksController implements TaskStackListenerCallback,
ShellCommandHandler shellCommandHandler,
TaskStackListenerImpl taskStackListener,
ActivityTaskManager activityTaskManager,
- Optional<DesktopRepository> desktopRepository,
+ Optional<DesktopUserRepositories> desktopUserRepositories,
TaskStackTransitionObserver taskStackTransitionObserver,
ShellExecutor mainExecutor) {
mContext = context;
@@ -160,7 +165,7 @@ public class RecentTasksController implements TaskStackListenerCallback,
mActivityTaskManager = activityTaskManager;
mPcFeatureEnabled = mContext.getPackageManager().hasSystemFeature(FEATURE_PC);
mTaskStackListener = taskStackListener;
- mDesktopRepository = desktopRepository;
+ mDesktopUserRepositories = desktopUserRepositories;
mTaskStackTransitionObserver = taskStackTransitionObserver;
mMainExecutor = mainExecutor;
shellInit.addInitCallback(this::onInit, this);
@@ -175,12 +180,15 @@ public class RecentTasksController implements TaskStackListenerCallback,
}
@RequiresPermission(Manifest.permission.SUBSCRIBE_TO_KEYGUARD_LOCKED_STATE)
- private void onInit() {
+ void onInit() {
mShellController.addExternalInterface(KEY_EXTRA_SHELL_RECENT_TASKS,
this::createExternalInterface, this);
mShellCommandHandler.addDumpCallback(this::dump, this);
+ mUserId = ActivityManager.getCurrentUser();
+ mDesktopUserRepositories.ifPresent(
+ desktopUserRepositories ->
+ desktopUserRepositories.getCurrent().addActiveTaskListener(this));
mTaskStackListener.addListener(this);
- mDesktopRepository.ifPresent(it -> it.addActiveTaskListener(this));
mTaskStackTransitionObserver.addTaskStackTransitionObserverListener(this,
mMainExecutor);
mContext.getSystemService(KeyguardManager.class).addKeyguardLockedStateListener(
@@ -291,9 +299,9 @@ public class RecentTasksController implements TaskStackListenerCallback,
*/
@Override
public void onRecentTaskRemovedForAddTask(int taskId) {
- mDesktopRepository.ifPresent(
- repo -> repo.removeFreeformTask(INVALID_DISPLAY, taskId)
- );
+ mDesktopUserRepositories.ifPresent(
+ desktopUserRepositories -> desktopUserRepositories.getCurrent().removeFreeformTask(
+ INVALID_DISPLAY, taskId));
}
public void onTaskAdded(RunningTaskInfo taskInfo) {
@@ -512,10 +520,9 @@ public class RecentTasksController implements TaskStackListenerCallback,
// If it's not in the mapping, then it was already paired with another task
continue;
}
-
- if (DesktopModeStatus.canEnterDesktopMode(mContext)
- && mDesktopRepository.isPresent()
- && mDesktopRepository.get().isActiveTask(taskInfo.taskId)) {
+ if (DesktopModeStatus.canEnterDesktopMode(mContext) &&
+ mDesktopUserRepositories.isPresent()
+ && mDesktopUserRepositories.get().getCurrent().isActiveTask(taskInfo.taskId)) {
// Freeform tasks will be added as a separate entry
if (mostRecentFreeformTaskIndex == Integer.MAX_VALUE) {
mostRecentFreeformTaskIndex = groupedTasks.size();
@@ -531,7 +538,7 @@ public class RecentTasksController implements TaskStackListenerCallback,
taskInfo.lastNonFullscreenBounds.top);
}
freeformTasks.add(taskInfo);
- if (mDesktopRepository.get().isMinimizedTask(taskInfo.taskId)) {
+ if (mDesktopUserRepositories.get().getCurrent().isMinimizedTask(taskInfo.taskId)) {
minimizedFreeformTasks.add(taskInfo.taskId);
}
continue;
@@ -703,6 +710,21 @@ public class RecentTasksController implements TaskStackListenerCallback,
}
}
+ @Override
+ public void onUserChanged(int newUserId, @NonNull Context userContext) {
+ if (mDesktopUserRepositories.isEmpty()) return;
+
+ DesktopRepository previousUserRepository =
+ mDesktopUserRepositories.get().getProfile(mUserId);
+ mUserId = newUserId;
+ DesktopRepository currentUserRepository =
+ mDesktopUserRepositories.get().getProfile(newUserId);
+
+ // No-op if both profile ids map to the same user.
+ if (previousUserRepository.getUserId() == currentUserRepository.getUserId()) return;
+ previousUserRepository.removeActiveTasksListener(this);
+ currentUserRepository.addActiveTaskListener(this);
+ }
/**
* The interface for calls from outside the host process.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopHeaderManageWindowsMenu.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopHeaderManageWindowsMenu.kt
index 101467df03ac..ff52a45c94e2 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopHeaderManageWindowsMenu.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopHeaderManageWindowsMenu.kt
@@ -32,7 +32,7 @@ import com.android.internal.annotations.VisibleForTesting
import com.android.window.flags.Flags
import com.android.wm.shell.RootTaskDisplayAreaOrganizer
import com.android.wm.shell.common.DisplayController
-import com.android.wm.shell.desktopmode.DesktopRepository
+import com.android.wm.shell.desktopmode.DesktopUserRepositories
import com.android.wm.shell.shared.multiinstance.ManageWindowsViewContainer
import com.android.wm.shell.windowdecor.additionalviewcontainer.AdditionalSystemViewContainer
import com.android.wm.shell.windowdecor.additionalviewcontainer.AdditionalViewContainer
@@ -51,7 +51,7 @@ class DesktopHeaderManageWindowsMenu(
private val displayController: DisplayController,
private val rootTdaOrganizer: RootTaskDisplayAreaOrganizer,
context: Context,
- private val desktopRepository: DesktopRepository,
+ private val desktopUserRepositories: DesktopUserRepositories,
private val surfaceControlBuilderSupplier: Supplier<SurfaceControl.Builder>,
private val surfaceControlTransactionSupplier: Supplier<SurfaceControl.Transaction>,
snapshotList: List<Pair<Int, TaskSnapshot>>,
@@ -76,6 +76,7 @@ class DesktopHeaderManageWindowsMenu(
val flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or
WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH or
WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
+ val desktopRepository = desktopUserRepositories.getProfile(callerTaskInfo.userId)
menuViewContainer = if (Flags.enableFullyImmersiveInDesktop()
&& desktopRepository.isTaskInFullImmersiveState(callerTaskInfo.taskId)) {
// Use system view container so that forcibly shown system bars take effect in
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
index 17b299d745f1..0c077da0a5e8 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
@@ -117,6 +117,7 @@ import com.android.wm.shell.desktopmode.DesktopRepository;
import com.android.wm.shell.desktopmode.DesktopTasksController;
import com.android.wm.shell.desktopmode.DesktopTasksController.SnapPosition;
import com.android.wm.shell.desktopmode.DesktopTasksLimiter;
+import com.android.wm.shell.desktopmode.DesktopUserRepositories;
import com.android.wm.shell.desktopmode.DesktopWallpaperActivity;
import com.android.wm.shell.desktopmode.WindowDecorCaptionHandleRepository;
import com.android.wm.shell.desktopmode.common.ToggleTaskSizeInteraction;
@@ -169,7 +170,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
private final ActivityTaskManager mActivityTaskManager;
private final ShellCommandHandler mShellCommandHandler;
private final ShellTaskOrganizer mTaskOrganizer;
- private final DesktopRepository mDesktopRepository;
+ private final DesktopUserRepositories mDesktopUserRepositories;
private final ShellController mShellController;
private final Context mContext;
private final @ShellMainThread Handler mMainHandler;
@@ -247,7 +248,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
ShellCommandHandler shellCommandHandler,
IWindowManager windowManager,
ShellTaskOrganizer taskOrganizer,
- DesktopRepository desktopRepository,
+ DesktopUserRepositories desktopUserRepositories,
DisplayController displayController,
ShellController shellController,
DisplayInsetsController displayInsetsController,
@@ -278,7 +279,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
shellCommandHandler,
windowManager,
taskOrganizer,
- desktopRepository,
+ desktopUserRepositories,
displayController,
shellController,
displayInsetsController,
@@ -318,7 +319,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
ShellCommandHandler shellCommandHandler,
IWindowManager windowManager,
ShellTaskOrganizer taskOrganizer,
- DesktopRepository desktopRepository,
+ DesktopUserRepositories desktopUserRepositories,
DisplayController displayController,
ShellController shellController,
DisplayInsetsController displayInsetsController,
@@ -352,7 +353,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
mBgExecutor = bgExecutor;
mActivityTaskManager = mContext.getSystemService(ActivityTaskManager.class);
mTaskOrganizer = taskOrganizer;
- mDesktopRepository = desktopRepository;
+ mDesktopUserRepositories = desktopUserRepositories;
mShellController = shellController;
mDisplayController = displayController;
mDisplayInsetsController = displayInsetsController;
@@ -628,12 +629,14 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
);
}
- private void onEnterOrExitImmersive(int taskId) {
- final DesktopModeWindowDecoration decoration = mWindowDecorByTaskId.get(taskId);
+ private void onEnterOrExitImmersive(RunningTaskInfo taskInfo) {
+ final DesktopModeWindowDecoration decoration = mWindowDecorByTaskId.get(taskInfo.taskId);
if (decoration == null) {
return;
}
- if (mDesktopRepository.isTaskInFullImmersiveState(taskId)) {
+ final DesktopRepository desktopRepository = mDesktopUserRepositories.getProfile(
+ taskInfo.userId);
+ if (desktopRepository.isTaskInFullImmersiveState(taskInfo.taskId)) {
mDesktopModeUiEventLogger.log(decoration.mTaskInfo,
DesktopUiEventEnum.DESKTOP_WINDOW_MAXIMIZE_BUTTON_MENU_TAP_TO_RESTORE);
mDesktopImmersiveController.moveTaskToNonImmersive(
@@ -894,7 +897,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
&& TaskInfoKt.getRequestingImmersive(decoration.mTaskInfo)) {
// Task is requesting immersive, so it should either enter or exit immersive,
// depending on immersive state.
- onEnterOrExitImmersive(decoration.mTaskInfo.taskId);
+ onEnterOrExitImmersive(decoration.mTaskInfo);
} else {
// Full immersive is disabled or task doesn't request/support it, so just
// toggle between maximize/restore states.
@@ -1084,8 +1087,10 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
}
final boolean touchingButton = (id == R.id.close_window || id == R.id.maximize_window
|| id == R.id.open_menu_button || id == R.id.minimize_window);
+ final DesktopRepository desktopRepository = mDesktopUserRepositories.getProfile(
+ taskInfo.userId);
final boolean dragAllowed =
- !mDesktopRepository.isTaskInFullImmersiveState(taskInfo.taskId);
+ !desktopRepository.isTaskInFullImmersiveState(taskInfo.taskId);
switch (e.getActionMasked()) {
case MotionEvent.ACTION_DOWN: {
if (dragAllowed) {
@@ -1195,7 +1200,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
&& action != MotionEvent.ACTION_CANCEL)) {
return false;
}
- if (mDesktopRepository.isTaskInFullImmersiveState(mTaskId)) {
+ final DesktopRepository desktopRepository = mDesktopUserRepositories.getCurrent();
+ if (desktopRepository.isTaskInFullImmersiveState(mTaskId)) {
// Disallow double-tap to resize when in full immersive.
return false;
}
@@ -1608,7 +1614,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
mContext.createContextAsUser(UserHandle.of(taskInfo.userId), 0 /* flags */),
mDisplayController,
mSplitScreenController,
- mDesktopRepository,
+ mDesktopUserRepositories,
mTaskOrganizer,
taskInfo,
taskSurface,
@@ -1645,7 +1651,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
return Unit.INSTANCE;
});
windowDecoration.setOnImmersiveOrRestoreClickListener(() -> {
- onEnterOrExitImmersive(taskInfo.taskId);
+ onEnterOrExitImmersive(taskInfo);
return Unit.INSTANCE;
});
windowDecoration.setOnLeftSnapClickListener(() -> {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
index 5eb031218ee1..9cf90a4e7b58 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
@@ -99,7 +99,7 @@ import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.desktopmode.CaptionState;
import com.android.wm.shell.desktopmode.DesktopModeEventLogger;
-import com.android.wm.shell.desktopmode.DesktopRepository;
+import com.android.wm.shell.desktopmode.DesktopUserRepositories;
import com.android.wm.shell.desktopmode.WindowDecorCaptionHandleRepository;
import com.android.wm.shell.shared.annotations.ShellBackgroundThread;
import com.android.wm.shell.shared.desktopmode.DesktopModeStatus;
@@ -206,14 +206,14 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
private final Runnable mCapturedLinkExpiredRunnable = this::onCapturedLinkExpired;
private final MultiInstanceHelper mMultiInstanceHelper;
private final WindowDecorCaptionHandleRepository mWindowDecorCaptionHandleRepository;
- private final DesktopRepository mDesktopRepository;
+ private final DesktopUserRepositories mDesktopUserRepositories;
public DesktopModeWindowDecoration(
Context context,
@NonNull Context userContext,
DisplayController displayController,
SplitScreenController splitScreenController,
- DesktopRepository desktopRepository,
+ DesktopUserRepositories desktopUserRepositories,
ShellTaskOrganizer taskOrganizer,
ActivityManager.RunningTaskInfo taskInfo,
SurfaceControl taskSurface,
@@ -228,10 +228,10 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
MultiInstanceHelper multiInstanceHelper,
WindowDecorCaptionHandleRepository windowDecorCaptionHandleRepository,
DesktopModeEventLogger desktopModeEventLogger) {
- this (context, userContext, displayController, splitScreenController, desktopRepository,
- taskOrganizer, taskInfo, taskSurface, handler, bgExecutor, choreographer, syncQueue,
- appHeaderViewHolderFactory, rootTaskDisplayAreaOrganizer, genericLinksParser,
- assistContentRequester,
+ this (context, userContext, displayController, splitScreenController,
+ desktopUserRepositories, taskOrganizer, taskInfo, taskSurface, handler,
+ bgExecutor, choreographer, syncQueue, appHeaderViewHolderFactory,
+ rootTaskDisplayAreaOrganizer, genericLinksParser, assistContentRequester,
SurfaceControl.Builder::new, SurfaceControl.Transaction::new,
WindowContainerTransaction::new, SurfaceControl::new, new WindowManagerWrapper(
context.getSystemService(WindowManager.class)),
@@ -246,7 +246,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
@NonNull Context userContext,
DisplayController displayController,
SplitScreenController splitScreenController,
- DesktopRepository desktopRepository,
+ DesktopUserRepositories desktopUserRepositories,
ShellTaskOrganizer taskOrganizer,
ActivityManager.RunningTaskInfo taskInfo,
SurfaceControl taskSurface,
@@ -287,7 +287,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
mMultiInstanceHelper = multiInstanceHelper;
mWindowManagerWrapper = windowManagerWrapper;
mWindowDecorCaptionHandleRepository = windowDecorCaptionHandleRepository;
- mDesktopRepository = desktopRepository;
+ mDesktopUserRepositories = desktopUserRepositories;
}
/**
@@ -437,7 +437,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
public void updateDisabledResizingEdge(
DragResizeWindowGeometry.DisabledEdge disabledResizingEdge, boolean shouldDelayUpdate) {
mDisabledResizingEdge = disabledResizingEdge;
- final boolean inFullImmersive = mDesktopRepository
+ final boolean inFullImmersive = mDesktopUserRepositories.getCurrent()
.isTaskInFullImmersiveState(mTaskInfo.taskId);
if (shouldDelayUpdate) {
return;
@@ -541,7 +541,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
mOpenByDefaultDialog.relayout(taskInfo);
}
- final boolean inFullImmersive = mDesktopRepository
+ final boolean inFullImmersive = mDesktopUserRepositories.getProfile(taskInfo.userId)
.isTaskInFullImmersiveState(taskInfo.taskId);
updateRelayoutParams(mRelayoutParams, mContext, taskInfo, applyStartTransactionOnDraw,
shouldSetTaskVisibilityPositionAndCrop, mIsStatusBarVisible,
@@ -1302,9 +1302,11 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
mMaximizeMenu = mMaximizeMenuFactory.create(mSyncQueue, mRootTaskDisplayAreaOrganizer,
mDisplayController, mTaskInfo, mContext,
calculateMaximizeMenuPosition(menuWidth), mSurfaceControlTransactionSupplier);
+
mMaximizeMenu.show(
/* isTaskInImmersiveMode= */ Flags.enableFullyImmersiveInDesktop()
- && mDesktopRepository.isTaskInFullImmersiveState(mTaskInfo.taskId),
+ && mDesktopUserRepositories.getProfile(mTaskInfo.userId)
+ .isTaskInFullImmersiveState(mTaskInfo.taskId),
/* menuWidth= */ menuWidth,
/* showImmersiveOption= */ Flags.enableFullyImmersiveInDesktop()
&& TaskInfoKt.getRequestingImmersive(mTaskInfo),
@@ -1394,7 +1396,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
&& mMinimumInstancesFound;
final boolean shouldShowChangeAspectRatioButton = HandleMenu.Companion
.shouldShowChangeAspectRatioButton(mTaskInfo);
- final boolean inDesktopImmersive = mDesktopRepository
+ final boolean inDesktopImmersive = mDesktopUserRepositories.getProfile(mTaskInfo.userId)
.isTaskInFullImmersiveState(mTaskInfo.taskId);
final boolean isBrowserApp = isBrowserApp();
mHandleMenu = mHandleMenuFactory.create(
@@ -1474,7 +1476,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
mDisplayController,
mRootTaskDisplayAreaOrganizer,
mContext,
- mDesktopRepository,
+ mDesktopUserRepositories,
mSurfaceControlBuilderSupplier,
mSurfaceControlTransactionSupplier,
snapshotList,
@@ -1770,7 +1772,8 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
void setAnimatingTaskResizeOrReposition(boolean animatingTaskResizeOrReposition) {
if (mRelayoutParams.mLayoutResId == R.layout.desktop_mode_app_handle) return;
final boolean inFullImmersive =
- mDesktopRepository.isTaskInFullImmersiveState(mTaskInfo.taskId);
+ mDesktopUserRepositories.getProfile(mTaskInfo.userId)
+ .isTaskInFullImmersiveState(mTaskInfo.taskId);
asAppHeader(mWindowDecorViewHolder).bindData(new AppHeaderViewHolder.HeaderData(
mTaskInfo,
TaskInfoKt.getRequestingImmersive(mTaskInfo),
@@ -1798,8 +1801,9 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
return !animatingTaskResizeOrReposition;
}
final boolean inImmersiveAndRequesting =
- mDesktopRepository.isTaskInFullImmersiveState(mTaskInfo.taskId)
- && TaskInfoKt.getRequestingImmersive(mTaskInfo);
+ mDesktopUserRepositories.getProfile(mTaskInfo.userId)
+ .isTaskInFullImmersiveState(mTaskInfo.taskId)
+ && TaskInfoKt.getRequestingImmersive(mTaskInfo);
return !animatingTaskResizeOrReposition && !inImmersiveAndRequesting;
}
@@ -1820,7 +1824,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
@NonNull Context userContext,
DisplayController displayController,
SplitScreenController splitScreenController,
- DesktopRepository desktopRepository,
+ DesktopUserRepositories desktopUserRepositories,
ShellTaskOrganizer taskOrganizer,
ActivityManager.RunningTaskInfo taskInfo,
SurfaceControl taskSurface,
@@ -1840,7 +1844,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
userContext,
displayController,
splitScreenController,
- desktopRepository,
+ desktopUserRepositories,
taskOrganizer,
taskInfo,
taskSurface,
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingDecorViewModel.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingDecorViewModel.kt
index 0e40a5350a43..9db69d5c1bc5 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingDecorViewModel.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingDecorViewModel.kt
@@ -33,6 +33,7 @@ import com.android.wm.shell.common.SyncTransactionQueue
import com.android.wm.shell.desktopmode.DesktopModeEventLogger
import com.android.wm.shell.desktopmode.DesktopRepository
import com.android.wm.shell.desktopmode.DesktopTasksController
+import com.android.wm.shell.desktopmode.DesktopUserRepositories
import com.android.wm.shell.desktopmode.ReturnToDragStartAnimator
import com.android.wm.shell.desktopmode.ToggleResizeDesktopTaskTransitionHandler
import com.android.wm.shell.transition.Transitions
@@ -48,7 +49,7 @@ class DesktopTilingDecorViewModel(
private val shellTaskOrganizer: ShellTaskOrganizer,
private val toggleResizeDesktopTaskTransitionHandler: ToggleResizeDesktopTaskTransitionHandler,
private val returnToDragStartAnimator: ReturnToDragStartAnimator,
- private val taskRepository: DesktopRepository,
+ private val desktopUserRepositories: DesktopUserRepositories,
private val desktopModeEventLogger: DesktopModeEventLogger,
) : DisplayChangeController.OnDisplayChangingListener {
@VisibleForTesting
@@ -81,7 +82,7 @@ class DesktopTilingDecorViewModel(
shellTaskOrganizer,
toggleResizeDesktopTaskTransitionHandler,
returnToDragStartAnimator,
- taskRepository,
+ desktopUserRepositories,
desktopModeEventLogger,
)
tilingTransitionHandlerByDisplayId.put(displayId, newHandler)
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingWindowDecoration.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingWindowDecoration.kt
index 3b5c6ca2e58a..7ceac52dd2a1 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingWindowDecoration.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingWindowDecoration.kt
@@ -49,6 +49,7 @@ import com.android.wm.shell.desktopmode.DesktopModeEventLogger
import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.ResizeTrigger
import com.android.wm.shell.desktopmode.DesktopRepository
import com.android.wm.shell.desktopmode.DesktopTasksController.SnapPosition
+import com.android.wm.shell.desktopmode.DesktopUserRepositories
import com.android.wm.shell.desktopmode.ReturnToDragStartAnimator
import com.android.wm.shell.desktopmode.ToggleResizeDesktopTaskTransitionHandler
import com.android.wm.shell.transition.Transitions
@@ -72,7 +73,7 @@ class DesktopTilingWindowDecoration(
private val shellTaskOrganizer: ShellTaskOrganizer,
private val toggleResizeDesktopTaskTransitionHandler: ToggleResizeDesktopTaskTransitionHandler,
private val returnToDragStartAnimator: ReturnToDragStartAnimator,
- private val taskRepository: DesktopRepository,
+ private val desktopUserRepositories: DesktopUserRepositories,
private val desktopModeEventLogger: DesktopModeEventLogger,
private val transactionSupplier: Supplier<Transaction> = Supplier { Transaction() },
) :
@@ -630,6 +631,7 @@ class DesktopTilingWindowDecoration(
private fun allTiledTasksVisible(): Boolean {
val leftTiledTask = leftTaskResizingHelper ?: return false
val rightTiledTask = rightTaskResizingHelper ?: return false
+ val taskRepository = desktopUserRepositories.current
return taskRepository.isVisibleTask(leftTiledTask.taskInfo.taskId) &&
taskRepository.isVisibleTask(rightTiledTask.taskInfo.taskId)
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIControllerTest.java
index d5287e742c2c..67573dabf2ec 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIControllerTest.java
@@ -30,6 +30,7 @@ import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
import android.app.ActivityManager.RunningTaskInfo;
import android.app.TaskInfo;
@@ -61,12 +62,16 @@ import com.android.wm.shell.common.DockStateReader;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.compatui.api.CompatUIInfo;
+import com.android.wm.shell.desktopmode.DesktopRepository;
+import com.android.wm.shell.desktopmode.DesktopUserRepositories;
import com.android.wm.shell.sysui.ShellController;
import com.android.wm.shell.sysui.ShellInit;
import com.android.wm.shell.transition.Transitions;
import dagger.Lazy;
+import java.util.Optional;
+
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
@@ -130,6 +135,10 @@ public class CompatUIControllerTest extends ShellTestCase {
private CompatUIShellCommandHandler mCompatUIShellCommandHandler;
@Mock
private AccessibilityManager mAccessibilityManager;
+ @Mock
+ private DesktopUserRepositories mDesktopUserRepositories;
+ @Mock
+ private DesktopRepository mDesktopRepository;
@Captor
ArgumentCaptor<OnInsetsChangedListener> mOnInsetsChangedListenerCaptor;
@@ -137,7 +146,6 @@ public class CompatUIControllerTest extends ShellTestCase {
@NonNull
private CompatUIStatusManager mCompatUIStatusManager;
- private boolean mInDesktopModePredicateResult;
@Before
public void setUp() {
@@ -152,6 +160,8 @@ public class CompatUIControllerTest extends ShellTestCase {
doReturn(TASK_ID).when(mMockLetterboxEduLayout).getTaskId();
doReturn(true).when(mMockLetterboxEduLayout).createLayout(anyBoolean());
doReturn(true).when(mMockLetterboxEduLayout).updateCompatInfo(any(), any(), anyBoolean());
+ doReturn(mDesktopRepository).when(mDesktopUserRepositories).getCurrent();
+ doReturn(mDesktopRepository).when(mDesktopUserRepositories).getProfile(anyInt());
doReturn(DISPLAY_ID).when(mMockRestartDialogLayout).getDisplayId();
doReturn(TASK_ID).when(mMockRestartDialogLayout).getTaskId();
@@ -164,7 +174,7 @@ public class CompatUIControllerTest extends ShellTestCase {
mMockDisplayController, mMockDisplayInsetsController, mMockImeController,
mMockSyncQueue, mMockExecutor, mMockTransitionsLazy, mDockStateReader,
mCompatUIConfiguration, mCompatUIShellCommandHandler, mAccessibilityManager,
- mCompatUIStatusManager, i -> mInDesktopModePredicateResult) {
+ mCompatUIStatusManager, Optional.of(mDesktopUserRepositories)) {
@Override
CompatUIWindowManager createCompatUiWindowManager(Context context, TaskInfo taskInfo,
ShellTaskOrganizer.TaskListener taskListener) {
@@ -707,13 +717,17 @@ public class CompatUIControllerTest extends ShellTestCase {
@RequiresFlagsDisabled(Flags.FLAG_APP_COMPAT_UI_FRAMEWORK)
@EnableFlags(Flags.FLAG_SKIP_COMPAT_UI_EDUCATION_IN_DESKTOP_MODE)
public void testUpdateActiveTaskInfo_removeAllComponentWhenInDesktopModeFlagEnabled() {
- mInDesktopModePredicateResult = false;
TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, /* hasSizeCompat= */ true);
+ when(mDesktopUserRepositories.getCurrent().getVisibleTaskCount(DISPLAY_ID)).thenReturn(0);
+
mController.onCompatInfoChanged(new CompatUIInfo(taskInfo, mMockTaskListener));
+
verify(mController, never()).removeLayouts(taskInfo.taskId);
- mInDesktopModePredicateResult = true;
+ when(mDesktopUserRepositories.getCurrent().getVisibleTaskCount(DISPLAY_ID)).thenReturn(2);
+
mController.onCompatInfoChanged(new CompatUIInfo(taskInfo, mMockTaskListener));
+
verify(mController).removeLayouts(taskInfo.taskId);
}
@@ -721,13 +735,17 @@ public class CompatUIControllerTest extends ShellTestCase {
@RequiresFlagsDisabled(Flags.FLAG_APP_COMPAT_UI_FRAMEWORK)
@DisableFlags(Flags.FLAG_SKIP_COMPAT_UI_EDUCATION_IN_DESKTOP_MODE)
public void testUpdateActiveTaskInfo_removeAllComponentWhenInDesktopModeFlagDisabled() {
- mInDesktopModePredicateResult = false;
+ when(mDesktopUserRepositories.getCurrent().getVisibleTaskCount(DISPLAY_ID)).thenReturn(0);
TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, /* hasSizeCompat= */ true);
+
mController.onCompatInfoChanged(new CompatUIInfo(taskInfo, mMockTaskListener));
+
verify(mController, never()).removeLayouts(taskInfo.taskId);
- mInDesktopModePredicateResult = true;
+ when(mDesktopUserRepositories.getCurrent().getVisibleTaskCount(DISPLAY_ID)).thenReturn(2);
+
mController.onCompatInfoChanged(new CompatUIInfo(taskInfo, mMockTaskListener));
+
verify(mController, never()).removeLayouts(taskInfo.taskId);
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopActivityOrientationChangeHandlerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopActivityOrientationChangeHandlerTest.kt
index 2ea0379e3bf7..41a594a3347a 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopActivityOrientationChangeHandlerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopActivityOrientationChangeHandlerTest.kt
@@ -23,6 +23,7 @@ import android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
import android.content.pm.ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT
import android.graphics.Rect
import android.os.Binder
+import android.os.UserManager
import android.platform.test.annotations.EnableFlags
import android.platform.test.flag.junit.SetFlagsRule
import android.testing.AndroidTestingRunner
@@ -96,11 +97,12 @@ class DesktopActivityOrientationChangeHandlerTest : ShellTestCase() {
@Mock lateinit var taskStackListener: TaskStackListenerImpl
@Mock lateinit var persistentRepository: DesktopPersistentRepository
@Mock lateinit var repositoryInitializer: DesktopRepositoryInitializer
+ @Mock lateinit var userManager: UserManager
private lateinit var mockitoSession: StaticMockitoSession
private lateinit var handler: DesktopActivityOrientationChangeHandler
private lateinit var shellInit: ShellInit
- private lateinit var taskRepository: DesktopRepository
+ private lateinit var userRepositories: DesktopUserRepositories
private lateinit var testScope: CoroutineScope
// Mock running tasks are registered here so we can get the list from mock shell task organizer.
private val runningTasks = mutableListOf<RunningTaskInfo>()
@@ -117,13 +119,14 @@ class DesktopActivityOrientationChangeHandlerTest : ShellTestCase() {
testScope = CoroutineScope(Dispatchers.Unconfined + SupervisorJob())
shellInit = spy(ShellInit(testExecutor))
- taskRepository =
- DesktopRepository(
+ userRepositories =
+ DesktopUserRepositories(
context,
shellInit,
persistentRepository,
repositoryInitializer,
- testScope
+ testScope,
+ userManager
)
whenever(shellTaskOrganizer.getRunningTasks(anyInt())).thenAnswer { runningTasks }
whenever(transitions.startTransition(anyInt(), any(), isNull())).thenAnswer { Binder() }
@@ -132,7 +135,7 @@ class DesktopActivityOrientationChangeHandlerTest : ShellTestCase() {
)
handler = DesktopActivityOrientationChangeHandler(context, shellInit, shellTaskOrganizer,
- taskStackListener, resizeTransitionHandler, taskRepository)
+ taskStackListener, resizeTransitionHandler, userRepositories)
shellInit.init()
}
@@ -156,7 +159,7 @@ class DesktopActivityOrientationChangeHandlerTest : ShellTestCase() {
clearInvocations(shellInit)
handler = DesktopActivityOrientationChangeHandler(context, shellInit, shellTaskOrganizer,
- taskStackListener, resizeTransitionHandler, taskRepository)
+ taskStackListener, resizeTransitionHandler, userRepositories)
verify(shellInit, never()).addInitCallback(any(),
any<DesktopActivityOrientationChangeHandler>())
@@ -180,7 +183,7 @@ class DesktopActivityOrientationChangeHandlerTest : ShellTestCase() {
activityInfo.screenOrientation = SCREEN_ORIENTATION_PORTRAIT
task.topActivityInfo = activityInfo
whenever(shellTaskOrganizer.getRunningTaskInfo(task.taskId)).thenReturn(task)
- taskRepository.addTask(DEFAULT_DISPLAY, task.taskId, isVisible = true)
+ userRepositories.current.addTask(DEFAULT_DISPLAY, task.taskId, isVisible = true)
runningTasks.add(task)
taskStackListener.onActivityRequestedOrientationChanged(task.taskId,
@@ -203,7 +206,7 @@ class DesktopActivityOrientationChangeHandlerTest : ShellTestCase() {
@Test
fun handleActivityOrientationChange_notInDesktopMode_doNothing() {
val task = setUpFreeformTask(isResizeable = false)
- taskRepository.updateTask(task.displayId, task.taskId, isVisible = false)
+ userRepositories.current.updateTask(task.displayId, task.taskId, isVisible = false)
taskStackListener.onActivityRequestedOrientationChanged(task.taskId,
SCREEN_ORIENTATION_LANDSCAPE)
@@ -268,7 +271,7 @@ class DesktopActivityOrientationChangeHandlerTest : ShellTestCase() {
task.topActivityInfo = activityInfo
task.isResizeable = isResizeable
whenever(shellTaskOrganizer.getRunningTaskInfo(task.taskId)).thenReturn(task)
- taskRepository.addTask(displayId, task.taskId, isVisible = true)
+ userRepositories.current.addTask(displayId, task.taskId, isVisible = true)
runningTasks.add(task)
return task
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopImmersiveControllerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopImmersiveControllerTest.kt
index b57c55c4c45a..db4c7465ae48 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopImmersiveControllerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopImmersiveControllerTest.kt
@@ -76,18 +76,19 @@ class DesktopImmersiveControllerTest : ShellTestCase() {
@JvmField @Rule val animatorTestRule = AnimatorTestRule(this)
@Mock private lateinit var mockTransitions: Transitions
- private lateinit var desktopRepository: DesktopRepository
+ private lateinit var userRepositories: DesktopUserRepositories
@Mock private lateinit var mockDisplayController: DisplayController
@Mock private lateinit var mockShellTaskOrganizer: ShellTaskOrganizer
@Mock private lateinit var mockDisplayLayout: DisplayLayout
private val transactionSupplier = { StubTransaction() }
private lateinit var controller: DesktopImmersiveController
+ private lateinit var desktopRepository: DesktopRepository
@Before
fun setUp() {
- desktopRepository = DesktopRepository(
- context, ShellInit(TestShellExecutor()), mock(), mock(), mock()
+ userRepositories = DesktopUserRepositories(
+ context, ShellInit(TestShellExecutor()), mock(), mock(), mock(), mock()
)
whenever(mockDisplayController.getDisplayLayout(DEFAULT_DISPLAY))
.thenReturn(mockDisplayLayout)
@@ -97,12 +98,13 @@ class DesktopImmersiveControllerTest : ShellTestCase() {
controller = DesktopImmersiveController(
shellInit = mock(),
transitions = mockTransitions,
- desktopRepository = desktopRepository,
+ desktopUserRepositories = userRepositories,
displayController = mockDisplayController,
shellTaskOrganizer = mockShellTaskOrganizer,
shellCommandHandler = mock(),
transactionSupplier = transactionSupplier,
)
+ desktopRepository = userRepositories.current
}
@Test
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopMixedTransitionHandlerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopMixedTransitionHandlerTest.kt
index 62717a32d99f..2d5544527436 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopMixedTransitionHandlerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopMixedTransitionHandlerTest.kt
@@ -60,6 +60,7 @@ import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentMatchers.anyInt
import org.mockito.Mock
+import org.mockito.Mockito
import org.mockito.Mockito.times
import org.mockito.Mockito.verify
import org.mockito.kotlin.any
@@ -84,7 +85,7 @@ class DesktopMixedTransitionHandlerTest : ShellTestCase() {
@Mock
lateinit var transitions: Transitions
@Mock
- lateinit var desktopRepository: DesktopRepository
+ lateinit var userRepositories: DesktopUserRepositories
@Mock
lateinit var freeformTaskTransitionHandler: FreeformTaskTransitionHandler
@Mock
@@ -103,16 +104,21 @@ class DesktopMixedTransitionHandlerTest : ShellTestCase() {
lateinit var shellInit: ShellInit
@Mock
lateinit var rootTaskDisplayAreaOrganizer: RootTaskDisplayAreaOrganizer
+ @Mock
+ private lateinit var desktopRepository: DesktopRepository
private lateinit var mixedHandler: DesktopMixedTransitionHandler
+
@Before
fun setUp() {
+ whenever(userRepositories.current).thenReturn(desktopRepository)
+ whenever(userRepositories.getProfile(Mockito.anyInt())).thenReturn(desktopRepository)
mixedHandler =
DesktopMixedTransitionHandler(
context,
transitions,
- desktopRepository,
+ userRepositories,
freeformTaskTransitionHandler,
closeDesktopTaskTransitionHandler,
desktopImmersiveController,
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopRepositoryTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopRepositoryTest.kt
index 7f790d574a7e..9059d7d5342c 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopRepositoryTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopRepositoryTest.kt
@@ -30,7 +30,6 @@ import com.android.wm.shell.TestShellExecutor
import com.android.wm.shell.common.ShellExecutor
import com.android.wm.shell.desktopmode.persistence.Desktop
import com.android.wm.shell.desktopmode.persistence.DesktopPersistentRepository
-import com.android.wm.shell.desktopmode.persistence.DesktopRepositoryInitializer
import com.android.wm.shell.sysui.ShellInit
import com.google.common.truth.Truth.assertThat
import junit.framework.Assert.fail
@@ -70,7 +69,6 @@ class DesktopRepositoryTest : ShellTestCase() {
@Mock private lateinit var testExecutor: ShellExecutor
@Mock private lateinit var persistentRepository: DesktopPersistentRepository
- @Mock lateinit var repositoryInitializer: DesktopRepositoryInitializer
@Before
fun setUp() {
@@ -80,11 +78,9 @@ class DesktopRepositoryTest : ShellTestCase() {
repo =
DesktopRepository(
- context,
- shellInit,
persistentRepository,
- repositoryInitializer,
- datastoreScope
+ datastoreScope,
+ DEFAULT_USER_ID
)
whenever(runBlocking { persistentRepository.readDesktop(any(), any()) }).thenReturn(
Desktop.getDefaultInstance()
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTaskChangeListenerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTaskChangeListenerTest.kt
index 8e323acc4e66..b4daa6637f83 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTaskChangeListenerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTaskChangeListenerTest.kt
@@ -22,6 +22,7 @@ import android.platform.test.flag.junit.SetFlagsRule
import android.testing.AndroidTestingRunner
import androidx.test.filters.SmallTest
import com.android.window.flags.Flags.FLAG_ENABLE_DESKTOP_WINDOWING_BACK_NAVIGATION
+import com.android.wm.shell.desktopmode.DesktopUserRepositories
import com.android.wm.shell.ShellTestCase
import com.android.wm.shell.desktopmode.DesktopTestHelpers.createFreeformTask
import com.android.wm.shell.desktopmode.DesktopTestHelpers.createFullscreenTask
@@ -29,6 +30,7 @@ import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.anyInt
import org.mockito.kotlin.mock
import org.mockito.kotlin.never
import org.mockito.kotlin.verify
@@ -47,131 +49,163 @@ class DesktopTaskChangeListenerTest : ShellTestCase() {
private lateinit var desktopTaskChangeListener: DesktopTaskChangeListener
+ private val desktopUserRepositories = mock<DesktopUserRepositories>()
private val desktopRepository = mock<DesktopRepository>()
@Before
fun setUp() {
- desktopTaskChangeListener = DesktopTaskChangeListener(desktopRepository)
+ desktopTaskChangeListener = DesktopTaskChangeListener(desktopUserRepositories)
+
+ whenever(desktopUserRepositories.current).thenReturn(desktopRepository)
+ whenever(desktopUserRepositories.getProfile(anyInt())).thenReturn(desktopRepository)
}
@Test
fun onTaskOpening_fullscreenTask_notActiveDesktopTask_noop() {
val task = createFullscreenTask().apply { isVisible = true }
- whenever(desktopRepository.isActiveTask(task.taskId)).thenReturn(false)
+ whenever(desktopUserRepositories.current.isActiveTask(task.taskId))
+ .thenReturn(false)
desktopTaskChangeListener.onTaskOpening(task)
- verify(desktopRepository, never()).addTask(task.displayId, task.taskId, task.isVisible)
- verify(desktopRepository, never()).removeFreeformTask(task.displayId, task.taskId)
+ verify(desktopUserRepositories.current, never())
+ .addTask(task.displayId, task.taskId, task.isVisible)
+ verify(desktopUserRepositories.current, never())
+ .removeFreeformTask(task.displayId, task.taskId)
}
@Test
fun onTaskOpening_freeformTask_activeDesktopTask_removesTaskFromRepo() {
val task = createFullscreenTask().apply { isVisible = true }
- whenever(desktopRepository.isActiveTask(task.taskId)).thenReturn(true)
+ whenever(desktopUserRepositories.current.isActiveTask(task.taskId))
+ .thenReturn(true)
desktopTaskChangeListener.onTaskOpening(task)
- verify(desktopRepository).removeFreeformTask(task.displayId, task.taskId)
+ verify(desktopUserRepositories.current).removeFreeformTask(task.displayId, task.taskId)
}
@Test
fun onTaskOpening_freeformTask_visibleDesktopTask_addsTaskToRepository() {
val task = createFreeformTask().apply { isVisible = true }
- whenever(desktopRepository.isActiveTask(task.taskId)).thenReturn(false)
+ whenever(desktopUserRepositories.current.isActiveTask(task.taskId))
+ .thenReturn(false)
desktopTaskChangeListener.onTaskOpening(task)
- verify(desktopRepository).addTask(task.displayId, task.taskId, task.isVisible)
+ verify(desktopUserRepositories.current)
+ .addTask(task.displayId, task.taskId, task.isVisible)
}
@Test
fun onTaskOpening_freeformTask_nonVisibleDesktopTask_addsTaskToRepository() {
val task = createFreeformTask().apply { isVisible = false }
- whenever(desktopRepository.isActiveTask(task.taskId)).thenReturn(true)
+ whenever(desktopUserRepositories.current.isActiveTask(task.taskId))
+ .thenReturn(true)
desktopTaskChangeListener.onTaskOpening(task)
- verify(desktopRepository).addTask(task.displayId, task.taskId, task.isVisible)
+ verify(desktopUserRepositories.current)
+ .addTask(task.displayId, task.taskId, task.isVisible)
}
@Test
fun onTaskChanging_freeformTaskOutsideDesktop_removesTaskFromRepo() {
val task = createFullscreenTask().apply { isVisible = true }
- whenever(desktopRepository.isActiveTask(task.taskId)).thenReturn(true)
+ whenever(desktopUserRepositories.current.isActiveTask(task.taskId))
+ .thenReturn(true)
desktopTaskChangeListener.onTaskChanging(task)
- verify(desktopRepository).removeFreeformTask(task.displayId, task.taskId)
+ verify(desktopUserRepositories.current)
+ .removeFreeformTask(task.displayId, task.taskId)
}
@Test
fun onTaskChanging_visibleTaskInDesktop_updatesTaskVisibility() {
val task = createFreeformTask().apply { isVisible = true }
- whenever(desktopRepository.isActiveTask(task.taskId)).thenReturn(true)
+ whenever(desktopUserRepositories.current.isActiveTask(task.taskId))
+ .thenReturn(true)
desktopTaskChangeListener.onTaskChanging(task)
- verify(desktopRepository).updateTask(task.displayId, task.taskId, task.isVisible)
+ verify(desktopUserRepositories.current)
+ .updateTask(task.displayId, task.taskId, task.isVisible)
}
@Test
fun onTaskChanging_nonVisibleTask_updatesTaskVisibility() {
val task = createFreeformTask().apply { isVisible = false }
- whenever(desktopRepository.isActiveTask(task.taskId)).thenReturn(true)
+ whenever(desktopUserRepositories.current.isActiveTask(task.taskId))
+ .thenReturn(true)
desktopTaskChangeListener.onTaskChanging(task)
- verify(desktopRepository).updateTask(task.displayId, task.taskId, task.isVisible)
+ verify(desktopUserRepositories.current)
+ .updateTask(task.displayId, task.taskId, task.isVisible)
}
@Test
fun onTaskMovingToFront_freeformTaskOutsideDesktop_removesTaskFromRepo() {
val task = createFullscreenTask().apply { isVisible = true }
- whenever(desktopRepository.isActiveTask(task.taskId)).thenReturn(true)
+ whenever(desktopUserRepositories.current.isActiveTask(task.taskId))
+ .thenReturn(true)
desktopTaskChangeListener.onTaskMovingToFront(task)
- verify(desktopRepository).removeFreeformTask(task.displayId, task.taskId)
+ verify(desktopUserRepositories.current)
+ .removeFreeformTask(task.displayId, task.taskId)
}
@Test
@EnableFlags(FLAG_ENABLE_DESKTOP_WINDOWING_BACK_NAVIGATION)
fun onTaskClosing_backNavEnabled_nonClosingTask_minimizesTaskInRepo() {
val task = createFreeformTask().apply { isVisible = true }
- whenever(desktopRepository.isActiveTask(task.taskId)).thenReturn(true)
- whenever(desktopRepository.isClosingTask(task.taskId)).thenReturn(false)
+ whenever(desktopUserRepositories.current.isActiveTask(task.taskId))
+ .thenReturn(true)
+ whenever(desktopUserRepositories.current.isClosingTask(task.taskId))
+ .thenReturn(false)
desktopTaskChangeListener.onTaskClosing(task)
- verify(desktopRepository).updateTask(task.displayId, task.taskId, isVisible = false)
- verify(desktopRepository).minimizeTask(task.displayId, task.taskId)
+ verify(desktopUserRepositories.current)
+ .updateTask(task.displayId, task.taskId, isVisible = false)
+ verify(desktopUserRepositories.current)
+ .minimizeTask(task.displayId, task.taskId)
}
@Test
@DisableFlags(FLAG_ENABLE_DESKTOP_WINDOWING_BACK_NAVIGATION)
fun onTaskClosing_backNavDisabled_closingTask_removesTaskInRepo() {
val task = createFreeformTask().apply { isVisible = true }
- whenever(desktopRepository.isActiveTask(task.taskId)).thenReturn(true)
- whenever(desktopRepository.isClosingTask(task.taskId)).thenReturn(true)
+ whenever(desktopUserRepositories.current.isActiveTask(task.taskId))
+ .thenReturn(true)
+ whenever(desktopUserRepositories.current.isClosingTask(task.taskId))
+ .thenReturn(true)
desktopTaskChangeListener.onTaskClosing(task)
- verify(desktopRepository, never()).minimizeTask(task.displayId, task.taskId)
- verify(desktopRepository).removeClosingTask(task.taskId)
- verify(desktopRepository).removeFreeformTask(task.displayId, task.taskId)
+ verify(desktopUserRepositories.current, never())
+ .minimizeTask(task.displayId, task.taskId)
+ verify(desktopUserRepositories.current)
+ .removeClosingTask(task.taskId)
+ verify(desktopUserRepositories.current)
+ .removeFreeformTask(task.displayId, task.taskId)
}
@Test
@EnableFlags(FLAG_ENABLE_DESKTOP_WINDOWING_BACK_NAVIGATION)
fun onTaskClosing_backNavEnabled_closingTask_removesTaskFromRepo() {
val task = createFreeformTask().apply { isVisible = true }
- whenever(desktopRepository.isActiveTask(task.taskId)).thenReturn(true)
- whenever(desktopRepository.isClosingTask(task.taskId)).thenReturn(true)
+ whenever(desktopUserRepositories.current.isActiveTask(task.taskId))
+ .thenReturn(true)
+ whenever(desktopUserRepositories.current.isClosingTask(task.taskId))
+ .thenReturn(true)
desktopTaskChangeListener.onTaskClosing(task)
- verify(desktopRepository).removeClosingTask(task.taskId)
- verify(desktopRepository).removeFreeformTask(task.displayId, task.taskId)
+ verify(desktopUserRepositories.current).removeClosingTask(task.taskId)
+ verify(desktopUserRepositories.current)
+ .removeFreeformTask(task.displayId, task.taskId)
}
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt
index 547a7b48a67b..c10434aa6d6f 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt
@@ -44,6 +44,7 @@ import android.os.Binder
import android.os.Bundle
import android.os.Handler
import android.os.IBinder
+import android.os.UserManager
import android.platform.test.annotations.DisableFlags
import android.platform.test.annotations.EnableFlags
import android.platform.test.flag.junit.SetFlagsRule
@@ -234,9 +235,11 @@ class DesktopTasksControllerTest : ShellTestCase() {
@Mock private lateinit var resources: Resources
@Mock
lateinit var desktopModeEnterExitTransitionListener: DesktopModeEntryExitTransitionListener
+ @Mock private lateinit var userManager: UserManager
private lateinit var controller: DesktopTasksController
private lateinit var shellInit: ShellInit
private lateinit var taskRepository: DesktopRepository
+ private lateinit var userRepositories: DesktopUserRepositories
private lateinit var desktopTasksLimiter: DesktopTasksLimiter
private lateinit var recentsTransitionStateListener: RecentsTransitionStateListener
private lateinit var testScope: CoroutineScope
@@ -268,12 +271,18 @@ class DesktopTasksControllerTest : ShellTestCase() {
testScope = CoroutineScope(Dispatchers.Unconfined + SupervisorJob())
shellInit = spy(ShellInit(testExecutor))
- taskRepository =
- DesktopRepository(context, shellInit, persistentRepository, repositoryInitializer, testScope)
+ userRepositories =
+ DesktopUserRepositories(
+ context,
+ shellInit,
+ persistentRepository,
+ repositoryInitializer,
+ testScope,
+ userManager)
desktopTasksLimiter =
DesktopTasksLimiter(
transitions,
- taskRepository,
+ userRepositories,
shellTaskOrganizer,
MAX_TASK_LIMIT,
mockInteractionJankMonitor,
@@ -316,6 +325,8 @@ class DesktopTasksControllerTest : ShellTestCase() {
controller.taskbarDesktopTaskListener = taskbarDesktopTaskListener
assumeTrue(ENABLE_SHELL_TRANSITIONS)
+
+ taskRepository = userRepositories.current
}
private fun createController(): DesktopTasksController {
@@ -339,7 +350,7 @@ class DesktopTasksControllerTest : ShellTestCase() {
toggleResizeDesktopTaskTransitionHandler,
dragToDesktopTransitionHandler,
mMockDesktopImmersiveController,
- taskRepository,
+ userRepositories,
recentsTransitionHandler,
multiInstanceHelper,
shellExecutor,
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksLimiterTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksLimiterTest.kt
index 797b12505ef2..0712d58166bb 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksLimiterTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksLimiterTest.kt
@@ -20,6 +20,7 @@ import android.app.ActivityManager.RunningTaskInfo
import android.graphics.Rect
import android.os.Binder
import android.os.Handler
+import android.os.UserManager
import android.platform.test.annotations.DisableFlags
import android.platform.test.annotations.EnableFlags
import android.platform.test.flag.junit.SetFlagsRule
@@ -73,7 +74,6 @@ import org.mockito.kotlin.eq
import org.mockito.kotlin.verify
import org.mockito.quality.Strictness
-
/**
* Test class for {@link DesktopTasksLimiter}
*
@@ -95,9 +95,11 @@ class DesktopTasksLimiterTest : ShellTestCase() {
@Mock lateinit var testExecutor: ShellExecutor
@Mock lateinit var persistentRepository: DesktopPersistentRepository
@Mock lateinit var repositoryInitializer: DesktopRepositoryInitializer
+ @Mock lateinit var userManager: UserManager
private lateinit var mockitoSession: StaticMockitoSession
private lateinit var desktopTasksLimiter: DesktopTasksLimiter
+ private lateinit var userRepositories: DesktopUserRepositories
private lateinit var desktopTaskRepo: DesktopRepository
private lateinit var shellInit: ShellInit
private lateinit var testScope: CoroutineScope
@@ -111,16 +113,18 @@ class DesktopTasksLimiterTest : ShellTestCase() {
Dispatchers.setMain(StandardTestDispatcher())
testScope = CoroutineScope(Dispatchers.Unconfined + SupervisorJob())
- desktopTaskRepo =
- DesktopRepository(
+ userRepositories =
+ DesktopUserRepositories(
context,
shellInit,
persistentRepository,
repositoryInitializer,
- testScope
+ testScope,
+ userManager
)
+ desktopTaskRepo = userRepositories.current
desktopTasksLimiter =
- DesktopTasksLimiter(transitions, desktopTaskRepo, shellTaskOrganizer, MAX_TASK_LIMIT,
+ DesktopTasksLimiter(transitions, userRepositories, shellTaskOrganizer, MAX_TASK_LIMIT,
interactionJankMonitor, mContext, handler)
}
@@ -133,7 +137,7 @@ class DesktopTasksLimiterTest : ShellTestCase() {
@Test
fun createDesktopTasksLimiter_withZeroLimit_shouldThrow() {
assertFailsWith<IllegalArgumentException> {
- DesktopTasksLimiter(transitions, desktopTaskRepo, shellTaskOrganizer, 0,
+ DesktopTasksLimiter(transitions, userRepositories, shellTaskOrganizer, 0,
interactionJankMonitor, mContext, handler)
}
}
@@ -141,7 +145,7 @@ class DesktopTasksLimiterTest : ShellTestCase() {
@Test
fun createDesktopTasksLimiter_withNegativeLimit_shouldThrow() {
assertFailsWith<IllegalArgumentException> {
- DesktopTasksLimiter(transitions, desktopTaskRepo, shellTaskOrganizer, -5,
+ DesktopTasksLimiter(transitions, userRepositories, shellTaskOrganizer, -5,
interactionJankMonitor, mContext, handler)
}
}
@@ -411,7 +415,7 @@ class DesktopTasksLimiterTest : ShellTestCase() {
@Test
fun getTaskToMinimize_tasksAboveLimit_otherLimit_returnsBackTask() {
desktopTasksLimiter =
- DesktopTasksLimiter(transitions, desktopTaskRepo, shellTaskOrganizer, MAX_TASK_LIMIT2,
+ DesktopTasksLimiter(transitions, userRepositories, shellTaskOrganizer, MAX_TASK_LIMIT2,
interactionJankMonitor, mContext, handler)
val tasks = (1..MAX_TASK_LIMIT2 + 1).map { setUpFreeformTask() }
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksTransitionObserverTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksTransitionObserverTest.kt
index 7f1c1db3207a..238483da537c 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksTransitionObserverTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksTransitionObserverTest.kt
@@ -50,6 +50,7 @@ import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.mockito.ArgumentCaptor
+import org.mockito.ArgumentMatchers.anyInt
import org.mockito.ArgumentMatchers.eq
import org.mockito.ArgumentMatchers.isA
import org.mockito.Mockito
@@ -75,6 +76,7 @@ class DesktopTasksTransitionObserverTest {
private val transitions = mock<Transitions>()
private val context = mock<Context>()
private val shellTaskOrganizer = mock<ShellTaskOrganizer>()
+ private val userRepositories = mock<DesktopUserRepositories>()
private val taskRepository = mock<DesktopRepository>()
private val mixedHandler = mock<DesktopMixedTransitionHandler>()
@@ -86,9 +88,12 @@ class DesktopTasksTransitionObserverTest {
whenever(DesktopModeStatus.canEnterDesktopMode(any())).thenReturn(true)
shellInit = spy(ShellInit(testExecutor))
+ whenever(userRepositories.current).thenReturn(taskRepository)
+ whenever(userRepositories.getProfile(anyInt())).thenReturn(taskRepository)
+
transitionObserver =
DesktopTasksTransitionObserver(
- context, taskRepository, transitions, shellTaskOrganizer, mixedHandler, shellInit
+ context, userRepositories, transitions, shellTaskOrganizer, mixedHandler, shellInit
)
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/compatui/SystemModalsTransitionHandlerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/compatui/SystemModalsTransitionHandlerTest.kt
index 226e974d2875..b9d7bbf567b7 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/compatui/SystemModalsTransitionHandlerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/compatui/SystemModalsTransitionHandlerTest.kt
@@ -25,10 +25,11 @@ import android.view.WindowManager.TRANSIT_OPEN
import androidx.test.filters.SmallTest
import com.android.wm.shell.ShellTestCase
import com.android.wm.shell.common.ShellExecutor
-import com.android.wm.shell.desktopmode.DesktopRepository
import com.android.wm.shell.desktopmode.DesktopTestHelpers.createFullscreenTask
import com.android.wm.shell.desktopmode.DesktopTestHelpers.createFullscreenTaskBuilder
import com.android.wm.shell.desktopmode.DesktopTestHelpers.createSystemModalTask
+import com.android.wm.shell.desktopmode.DesktopRepository
+import com.android.wm.shell.desktopmode.DesktopUserRepositories
import com.android.wm.shell.sysui.ShellInit
import com.android.wm.shell.transition.TransitionInfoBuilder
import com.android.wm.shell.transition.Transitions
@@ -49,6 +50,7 @@ class SystemModalsTransitionHandlerTest : ShellTestCase() {
private val animExecutor = mock<ShellExecutor>()
private val shellInit = mock<ShellInit>()
private val transitions = mock<Transitions>()
+ private val desktopUserRepositories = mock<DesktopUserRepositories>()
private val desktopRepository = mock<DesktopRepository>()
private val startT = mock<SurfaceControl.Transaction>()
private val finishT = mock<SurfaceControl.Transaction>()
@@ -58,6 +60,7 @@ class SystemModalsTransitionHandlerTest : ShellTestCase() {
@Before
fun setUp() {
// Simulate having one Desktop task so that we see Desktop Mode as active
+ whenever(desktopUserRepositories.current).thenReturn(desktopRepository)
whenever(desktopRepository.getVisibleTaskCount(anyInt())).thenReturn(1)
transitionHandler = createTransitionHandler()
}
@@ -69,7 +72,7 @@ class SystemModalsTransitionHandlerTest : ShellTestCase() {
animExecutor,
shellInit,
transitions,
- desktopRepository,
+ desktopUserRepositories,
)
@Test
@@ -79,7 +82,7 @@ class SystemModalsTransitionHandlerTest : ShellTestCase() {
@Test
fun startAnimation_desktopNotActive_doesNotAnimate() {
- whenever(desktopRepository.getVisibleTaskCount(anyInt())).thenReturn(1)
+ whenever(desktopUserRepositories.current.getVisibleTaskCount(anyInt())).thenReturn(1)
val info =
TransitionInfoBuilder(TRANSIT_OPEN)
.addChange(TRANSIT_OPEN, createSystemModalTask())
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/persistence/DesktopPersistentRepositoryTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/persistence/DesktopPersistentRepositoryTest.kt
index 8495580f42a5..4f7e80cf8330 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/persistence/DesktopPersistentRepositoryTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/persistence/DesktopPersistentRepositoryTest.kt
@@ -112,7 +112,8 @@ class DesktopPersistentRepositoryTest : ShellTestCase() {
datastoreRepository.addOrUpdateDesktop(
visibleTasks = visibleTasks,
minimizedTasks = minimizedTasks,
- freeformTasksInZOrder = freeformTasksInZOrder)
+ freeformTasksInZOrder = freeformTasksInZOrder,
+ userId = DEFAULT_USER_ID)
val actualDesktop = datastoreRepository.readDesktop(DEFAULT_USER_ID, DEFAULT_DESKTOP_ID)
assertThat(actualDesktop?.tasksByTaskIdMap).hasSize(2)
@@ -135,7 +136,8 @@ class DesktopPersistentRepositoryTest : ShellTestCase() {
datastoreRepository.addOrUpdateDesktop(
visibleTasks = visibleTasks,
minimizedTasks = minimizedTasks,
- freeformTasksInZOrder = freeformTasksInZOrder)
+ freeformTasksInZOrder = freeformTasksInZOrder,
+ userId = DEFAULT_USER_ID)
val actualDesktop = datastoreRepository.readDesktop(DEFAULT_USER_ID, DEFAULT_DESKTOP_ID)
assertThat(actualDesktop?.tasksByTaskIdMap?.get(task.taskId)?.desktopTaskState)
@@ -158,7 +160,8 @@ class DesktopPersistentRepositoryTest : ShellTestCase() {
datastoreRepository.addOrUpdateDesktop(
visibleTasks = visibleTasks,
minimizedTasks = minimizedTasks,
- freeformTasksInZOrder = freeformTasksInZOrder)
+ freeformTasksInZOrder = freeformTasksInZOrder,
+ userId = DEFAULT_USER_ID)
val actualDesktop = datastoreRepository.readDesktop(DEFAULT_USER_ID, DEFAULT_DESKTOP_ID)
assertThat(actualDesktop?.tasksByTaskIdMap).isEmpty()
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/persistence/DesktopRepositoryInitializerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/persistence/DesktopRepositoryInitializerTest.kt
index 975342902814..1c88a290d677 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/persistence/DesktopRepositoryInitializerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/persistence/DesktopRepositoryInitializerTest.kt
@@ -16,14 +16,17 @@
package com.android.wm.shell.desktopmode.persistence
+import android.os.UserManager
import android.platform.test.annotations.EnableFlags
+import android.platform.test.flag.junit.SetFlagsRule
import android.testing.AndroidTestingRunner
import android.view.Display.DEFAULT_DISPLAY
import androidx.test.filters.SmallTest
+import com.android.window.flags.Flags.FLAG_ENABLE_DESKTOP_WINDOWING_HSUM
import com.android.window.flags.Flags.FLAG_ENABLE_DESKTOP_WINDOWING_PERSISTENCE
import com.android.wm.shell.ShellTestCase
import com.android.wm.shell.common.ShellExecutor
-import com.android.wm.shell.desktopmode.DesktopRepository
+import com.android.wm.shell.desktopmode.DesktopUserRepositories
import com.android.wm.shell.sysui.ShellInit
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.CoroutineScope
@@ -36,26 +39,30 @@ import kotlinx.coroutines.test.runTest
import kotlinx.coroutines.test.setMain
import org.junit.After
import org.junit.Before
+import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
-import org.mockito.Mockito.inOrder
import org.mockito.Mockito.spy
-import org.mockito.kotlin.any
import org.mockito.kotlin.mock
-import org.mockito.kotlin.verify
import org.mockito.kotlin.whenever
+
@SmallTest
@RunWith(AndroidTestingRunner::class)
@ExperimentalCoroutinesApi
class DesktopRepositoryInitializerTest : ShellTestCase() {
+ @JvmField
+ @Rule
+ val setFlagsRule = SetFlagsRule()
+
private lateinit var repositoryInitializer: DesktopRepositoryInitializer
private lateinit var shellInit: ShellInit
private lateinit var datastoreScope: CoroutineScope
- private lateinit var desktopRepository: DesktopRepository
+ private lateinit var desktopUserRepositories: DesktopUserRepositories
private val persistentRepository = mock<DesktopPersistentRepository>()
+ private val userManager = mock<UserManager>()
private val testExecutor = mock<ShellExecutor>()
@Before
@@ -65,55 +72,193 @@ class DesktopRepositoryInitializerTest : ShellTestCase() {
datastoreScope = CoroutineScope(Dispatchers.Unconfined + SupervisorJob())
repositoryInitializer =
DesktopRepositoryInitializerImpl(context, persistentRepository, datastoreScope)
- desktopRepository =
- DesktopRepository(
- context, shellInit, persistentRepository, repositoryInitializer, datastoreScope)
+ desktopUserRepositories =
+ DesktopUserRepositories(
+ context, shellInit, persistentRepository, repositoryInitializer, datastoreScope,
+ userManager
+ )
}
@Test
+ @EnableFlags(FLAG_ENABLE_DESKTOP_WINDOWING_PERSISTENCE, FLAG_ENABLE_DESKTOP_WINDOWING_HSUM)
+ fun initWithPersistence_multipleUsers_addedCorrectly() =
+ runTest(StandardTestDispatcher()) {
+ whenever(persistentRepository.getUserDesktopRepositoryMap()).thenReturn(
+ mapOf(
+ USER_ID_1 to desktopRepositoryState1,
+ USER_ID_2 to desktopRepositoryState2
+ )
+ )
+ whenever(persistentRepository.getDesktopRepositoryState(USER_ID_1))
+ .thenReturn(desktopRepositoryState1)
+ whenever(persistentRepository.getDesktopRepositoryState(USER_ID_2))
+ .thenReturn(desktopRepositoryState2)
+ whenever(persistentRepository.readDesktop(USER_ID_1, DESKTOP_ID_1))
+ .thenReturn(desktop1)
+ whenever(persistentRepository.readDesktop(USER_ID_1, DESKTOP_ID_2))
+ .thenReturn(desktop2)
+ whenever(persistentRepository.readDesktop(USER_ID_2, DESKTOP_ID_3))
+ .thenReturn(desktop3)
+
+ repositoryInitializer.initialize(desktopUserRepositories)
+
+ // Desktop Repository currently returns all tasks across desktops for a specific user
+ // since the repository currently doesn't handle desktops. This test logic should be updated
+ // once the repository handles multiple desktops.
+ assertThat(
+ desktopUserRepositories.getProfile(USER_ID_1)
+ .getActiveTasks(DEFAULT_DISPLAY)
+ )
+ .containsExactly(1, 3, 4, 5)
+ .inOrder()
+ assertThat(
+ desktopUserRepositories.getProfile(USER_ID_1)
+ .getExpandedTasksOrdered(DEFAULT_DISPLAY)
+ )
+ .containsExactly(5, 1)
+ .inOrder()
+ assertThat(
+ desktopUserRepositories.getProfile(USER_ID_1)
+ .getMinimizedTasks(DEFAULT_DISPLAY)
+ )
+ .containsExactly(3, 4)
+ .inOrder()
+
+ assertThat(
+ desktopUserRepositories.getProfile(USER_ID_2)
+ .getActiveTasks(DEFAULT_DISPLAY)
+ )
+ .containsExactly(7, 8)
+ .inOrder()
+ assertThat(
+ desktopUserRepositories.getProfile(USER_ID_2)
+ .getExpandedTasksOrdered(DEFAULT_DISPLAY)
+ )
+ .contains(7)
+ assertThat(
+ desktopUserRepositories.getProfile(USER_ID_2)
+ .getMinimizedTasks(DEFAULT_DISPLAY)
+ ).containsExactly(8)
+ }
+
+ @Test
@EnableFlags(FLAG_ENABLE_DESKTOP_WINDOWING_PERSISTENCE)
- fun initWithPersistence_multipleTasks_addedCorrectly() =
+ fun initWithPersistence_singleUser_addedCorrectly() =
runTest(StandardTestDispatcher()) {
- val freeformTasksInZOrder = listOf(1, 2, 3)
- whenever(persistentRepository.readDesktop(any(), any()))
- .thenReturn(
- Desktop.newBuilder()
- .setDesktopId(1)
- .addAllZOrderedTasks(freeformTasksInZOrder)
- .putTasksByTaskId(
- 1,
- DesktopTask.newBuilder()
- .setTaskId(1)
- .setDesktopTaskState(DesktopTaskState.VISIBLE)
- .build())
- .putTasksByTaskId(
- 2,
- DesktopTask.newBuilder()
- .setTaskId(2)
- .setDesktopTaskState(DesktopTaskState.VISIBLE)
- .build())
- .putTasksByTaskId(
- 3,
- DesktopTask.newBuilder()
- .setTaskId(3)
- .setDesktopTaskState(DesktopTaskState.MINIMIZED)
- .build())
- .build())
-
- repositoryInitializer.initialize(desktopRepository)
-
- verify(persistentRepository).readDesktop(any(), any())
- assertThat(desktopRepository.getActiveTasks(DEFAULT_DISPLAY))
- .containsExactly(1, 2, 3)
+ whenever(persistentRepository.getUserDesktopRepositoryMap()).thenReturn(
+ mapOf(
+ USER_ID_1 to desktopRepositoryState1,
+ )
+ )
+ whenever(persistentRepository.getDesktopRepositoryState(USER_ID_1))
+ .thenReturn(desktopRepositoryState1)
+ whenever(persistentRepository.readDesktop(USER_ID_1, DESKTOP_ID_1))
+ .thenReturn(desktop1)
+ whenever(persistentRepository.readDesktop(USER_ID_1, DESKTOP_ID_2))
+ .thenReturn(desktop2)
+
+ repositoryInitializer.initialize(desktopUserRepositories)
+
+ // Desktop Repository currently returns all tasks across desktops for a specific user
+ // since the repository currently doesn't handle desktops. This test logic should be updated
+ // once the repository handles multiple desktops.
+ assertThat(
+ desktopUserRepositories.getProfile(USER_ID_1)
+ .getActiveTasks(DEFAULT_DISPLAY)
+ )
+ .containsExactly(1, 3, 4, 5)
+ .inOrder()
+ assertThat(
+ desktopUserRepositories.getProfile(USER_ID_1)
+ .getExpandedTasksOrdered(DEFAULT_DISPLAY)
+ )
+ .containsExactly(5, 1)
.inOrder()
- assertThat(desktopRepository.getExpandedTasksOrdered(DEFAULT_DISPLAY))
- .containsExactly(1, 2)
+ assertThat(
+ desktopUserRepositories.getProfile(USER_ID_1)
+ .getMinimizedTasks(DEFAULT_DISPLAY)
+ )
+ .containsExactly(3, 4)
.inOrder()
- assertThat(desktopRepository.getMinimizedTasks(DEFAULT_DISPLAY)).containsExactly(3)
}
@After
fun tearDown() {
datastoreScope.cancel()
}
+
+ private companion object {
+ const val USER_ID_1 = 5
+ const val USER_ID_2 = 6
+ const val DESKTOP_ID_1 = 2
+ const val DESKTOP_ID_2 = 3
+ const val DESKTOP_ID_3 = 4
+
+ val freeformTasksInZOrder1 = listOf(1, 3)
+ val desktop1: Desktop = Desktop.newBuilder()
+ .setDesktopId(DESKTOP_ID_1)
+ .addAllZOrderedTasks(freeformTasksInZOrder1)
+ .putTasksByTaskId(
+ 1,
+ DesktopTask.newBuilder()
+ .setTaskId(1)
+ .setDesktopTaskState(DesktopTaskState.VISIBLE)
+ .build()
+ )
+ .putTasksByTaskId(
+ 3,
+ DesktopTask.newBuilder()
+ .setTaskId(3)
+ .setDesktopTaskState(DesktopTaskState.MINIMIZED)
+ .build()
+ )
+ .build()
+
+ val freeformTasksInZOrder2 = listOf(4, 5)
+ val desktop2: Desktop = Desktop.newBuilder()
+ .setDesktopId(DESKTOP_ID_2)
+ .addAllZOrderedTasks(freeformTasksInZOrder2)
+ .putTasksByTaskId(
+ 4,
+ DesktopTask.newBuilder()
+ .setTaskId(4)
+ .setDesktopTaskState(DesktopTaskState.MINIMIZED)
+ .build()
+ )
+ .putTasksByTaskId(
+ 5,
+ DesktopTask.newBuilder()
+ .setTaskId(5)
+ .setDesktopTaskState(DesktopTaskState.VISIBLE)
+ .build()
+ )
+ .build()
+
+ val freeformTasksInZOrder3 = listOf(7, 8)
+ val desktop3: Desktop = Desktop.newBuilder()
+ .setDesktopId(DESKTOP_ID_3)
+ .addAllZOrderedTasks(freeformTasksInZOrder3)
+ .putTasksByTaskId(
+ 7,
+ DesktopTask.newBuilder()
+ .setTaskId(7)
+ .setDesktopTaskState(DesktopTaskState.VISIBLE)
+ .build()
+ )
+ .putTasksByTaskId(
+ 8,
+ DesktopTask.newBuilder()
+ .setTaskId(8)
+ .setDesktopTaskState(DesktopTaskState.MINIMIZED)
+ .build()
+ )
+ .build()
+ val desktopRepositoryState1: DesktopRepositoryState = DesktopRepositoryState.newBuilder()
+ .putDesktop(DESKTOP_ID_1, desktop1)
+ .putDesktop(DESKTOP_ID_2, desktop2)
+ .build()
+ val desktopRepositoryState2: DesktopRepositoryState = DesktopRepositoryState.newBuilder()
+ .putDesktop(DESKTOP_ID_3, desktop3)
+ .build()
+ }
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/freeform/FreeformTaskListenerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/freeform/FreeformTaskListenerTests.java
index b504a88e71fc..794ba48e2581 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/freeform/FreeformTaskListenerTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/freeform/FreeformTaskListenerTests.java
@@ -27,6 +27,7 @@ import static com.android.window.flags.Flags.FLAG_ENABLE_WINDOWING_TRANSITION_HA
import static com.android.window.flags.Flags.FLAG_SHOW_DESKTOP_WINDOWING_DEV_OPTION;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -46,6 +47,7 @@ import com.android.wm.shell.ShellTestCase;
import com.android.wm.shell.TestRunningTaskInfoBuilder;
import com.android.wm.shell.common.LaunchAdjacentController;
import com.android.wm.shell.desktopmode.DesktopRepository;
+import com.android.wm.shell.desktopmode.DesktopUserRepositories;
import com.android.wm.shell.desktopmode.DesktopTasksController;
import com.android.wm.shell.shared.desktopmode.DesktopModeStatus;
import com.android.wm.shell.sysui.ShellInit;
@@ -81,6 +83,8 @@ public final class FreeformTaskListenerTests extends ShellTestCase {
@Mock
private SurfaceControl mMockSurfaceControl;
@Mock
+ private DesktopUserRepositories mDesktopUserRepositories;
+ @Mock
private DesktopRepository mDesktopRepository;
@Mock
private DesktopTasksController mDesktopTasksController;
@@ -101,13 +105,14 @@ public final class FreeformTaskListenerTests extends ShellTestCase {
.mockStatic(DesktopModeStatus.class)
.startMocking();
doReturn(true).when(() -> DesktopModeStatus.canEnterDesktopMode(any()));
-
+ when(mDesktopUserRepositories.getCurrent()).thenReturn(mDesktopRepository);
+ when(mDesktopUserRepositories.getProfile(anyInt())).thenReturn(mDesktopRepository);
mFreeformTaskListener =
new FreeformTaskListener(
mContext,
mShellInit,
mTaskOrganizer,
- Optional.of(mDesktopRepository),
+ Optional.of(mDesktopUserRepositories),
Optional.of(mDesktopTasksController),
mLaunchAdjacentController,
mWindowDecorViewModel,
@@ -123,7 +128,8 @@ public final class FreeformTaskListenerTests extends ShellTestCase {
mFreeformTaskListener.onTaskAppeared(task, mMockSurfaceControl);
- verify(mDesktopRepository).addTask(task.displayId, task.taskId, task.isVisible = true);
+ verify(mDesktopUserRepositories.getCurrent())
+ .addTask(task.displayId, task.taskId, task.isVisible = true);
}
@Test
@@ -135,7 +141,8 @@ public final class FreeformTaskListenerTests extends ShellTestCase {
mFreeformTaskListener.onTaskAppeared(task, mMockSurfaceControl);
- verify(mDesktopRepository).addTask(task.displayId, task.taskId, task.isVisible);
+ verify(mDesktopUserRepositories.getCurrent())
+ .addTask(task.displayId, task.taskId, task.isVisible);
}
@Test
@@ -147,7 +154,8 @@ public final class FreeformTaskListenerTests extends ShellTestCase {
mFreeformTaskListener.onTaskAppeared(task, mMockSurfaceControl);
- verify(mDesktopRepository, never()).addTask(task.displayId, task.taskId, task.isVisible);
+ verify(mDesktopUserRepositories.getCurrent(), never())
+ .addTask(task.displayId, task.taskId, task.isVisible);
}
@Test
@@ -158,7 +166,8 @@ public final class FreeformTaskListenerTests extends ShellTestCase {
mFreeformTaskListener.onFocusTaskChanged(task);
- verify(mDesktopRepository).addTask(task.displayId, task.taskId, task.isVisible);
+ verify(mDesktopUserRepositories.getCurrent())
+ .addTask(task.displayId, task.taskId, task.isVisible);
}
@Test
@@ -171,7 +180,7 @@ public final class FreeformTaskListenerTests extends ShellTestCase {
mFreeformTaskListener.onFocusTaskChanged(fullscreenTask);
- verify(mDesktopRepository, never())
+ verify(mDesktopUserRepositories.getCurrent(), never())
.addTask(fullscreenTask.displayId, fullscreenTask.taskId, fullscreenTask.isVisible);
}
@@ -214,7 +223,7 @@ public final class FreeformTaskListenerTests extends ShellTestCase {
task.displayId = INVALID_DISPLAY;
mFreeformTaskListener.onTaskVanished(task);
- verify(mDesktopRepository).minimizeTask(task.displayId, task.taskId);
+ verify(mDesktopUserRepositories.getCurrent()).minimizeTask(task.displayId, task.taskId);
}
@Test
@@ -227,14 +236,17 @@ public final class FreeformTaskListenerTests extends ShellTestCase {
mFreeformTaskListener.onTaskAppeared(task, mMockSurfaceControl);
- when(mDesktopRepository.isClosingTask(task.taskId)).thenReturn(true);
+ when(mDesktopUserRepositories.getCurrent()
+ .isClosingTask(task.taskId)).thenReturn(true);
task.isVisible = false;
task.displayId = INVALID_DISPLAY;
mFreeformTaskListener.onTaskVanished(task);
- verify(mDesktopRepository, never()).minimizeTask(task.displayId, task.taskId);
- verify(mDesktopRepository).removeClosingTask(task.taskId);
- verify(mDesktopRepository).removeFreeformTask(task.displayId, task.taskId);
+ verify(mDesktopUserRepositories.getCurrent(), never())
+ .minimizeTask(task.displayId, task.taskId);
+ verify(mDesktopUserRepositories.getCurrent()).removeClosingTask(task.taskId);
+ verify(mDesktopUserRepositories.getCurrent())
+ .removeFreeformTask(task.displayId, task.taskId);
}
@Test
@@ -246,9 +258,12 @@ public final class FreeformTaskListenerTests extends ShellTestCase {
mFreeformTaskListener.onTaskVanished(task);
- verify(mDesktopRepository, never()).minimizeTask(task.displayId, task.taskId);
- verify(mDesktopRepository, never()).removeClosingTask(task.taskId);
- verify(mDesktopRepository, never()).removeFreeformTask(task.displayId, task.taskId);
+ verify(mDesktopUserRepositories.getCurrent(), never())
+ .minimizeTask(task.displayId, task.taskId);
+ verify(mDesktopUserRepositories.getCurrent(), never())
+ .removeClosingTask(task.taskId);
+ verify(mDesktopUserRepositories.getCurrent(), never())
+ .removeFreeformTask(task.displayId, task.taskId);
}
@Test
@@ -274,7 +289,8 @@ public final class FreeformTaskListenerTests extends ShellTestCase {
mFreeformTaskListener.onTaskInfoChanged(task);
verify(mTaskChangeListener, never()).onTaskChanging(any());
- verify(mDesktopRepository).updateTask(task.displayId, task.taskId, task.isVisible);
+ verify(mDesktopUserRepositories.getCurrent())
+ .updateTask(task.displayId, task.taskId, task.isVisible);
}
@Test
@@ -289,7 +305,7 @@ public final class FreeformTaskListenerTests extends ShellTestCase {
mFreeformTaskListener.onTaskInfoChanged(task);
verify(mTaskChangeListener).onNonTransitionTaskChanging(any());
- verify(mDesktopRepository, never())
+ verify(mDesktopUserRepositories.getCurrent(), never())
.updateTask(task.displayId, task.taskId, task.isVisible);
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java
index 289fd2d838fd..2eb2c3b8e2f7 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java
@@ -65,7 +65,7 @@ import com.android.wm.shell.common.pip.PipKeepClearAlgorithmInterface;
import com.android.wm.shell.common.pip.PipSnapAlgorithm;
import com.android.wm.shell.common.pip.PipUiEventLogger;
import com.android.wm.shell.common.pip.SizeSpecSource;
-import com.android.wm.shell.desktopmode.DesktopRepository;
+import com.android.wm.shell.desktopmode.DesktopUserRepositories;
import com.android.wm.shell.pip.phone.PhonePipMenuController;
import com.android.wm.shell.splitscreen.SplitScreenController;
@@ -103,7 +103,7 @@ public class PipTaskOrganizerTest extends ShellTestCase {
@Mock private PipSurfaceTransactionHelper mMockPipSurfaceTransactionHelper;
@Mock private PipUiEventLogger mMockPipUiEventLogger;
@Mock private Optional<SplitScreenController> mMockOptionalSplitScreen;
- @Mock private Optional<DesktopRepository> mMockOptionalDesktopRepository;
+ @Mock private Optional<DesktopUserRepositories> mMockOptionalDesktopUserRepositories;
@Mock private RootTaskDisplayAreaOrganizer mRootTaskDisplayAreaOrganizer;
@Mock private ShellTaskOrganizer mMockShellTaskOrganizer;
@Mock private PipParamsChangedForwarder mMockPipParamsChangedForwarder;
@@ -136,7 +136,7 @@ public class PipTaskOrganizerTest extends ShellTestCase {
mMockPipSurfaceTransactionHelper, mMockPipTransitionController,
mMockPipParamsChangedForwarder, mMockOptionalSplitScreen,
Optional.empty() /* pipPerfHintControllerOptional */,
- mMockOptionalDesktopRepository, mRootTaskDisplayAreaOrganizer,
+ mMockOptionalDesktopUserRepositories, mRootTaskDisplayAreaOrganizer,
mMockDisplayController, mMockPipUiEventLogger, mMockShellTaskOrganizer,
mMainExecutor);
mMainExecutor.flushAll();
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip2/phone/PipSchedulerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip2/phone/PipSchedulerTest.java
index 57b6d7f0ac2f..3fe8c109807a 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip2/phone/PipSchedulerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip2/phone/PipSchedulerTest.java
@@ -45,7 +45,7 @@ import androidx.test.filters.SmallTest;
import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.pip.PipBoundsState;
-import com.android.wm.shell.desktopmode.DesktopRepository;
+import com.android.wm.shell.desktopmode.DesktopUserRepositories;
import com.android.wm.shell.pip.PipTransitionController;
import com.android.wm.shell.pip2.PipSurfaceTransactionHelper;
import com.android.wm.shell.pip2.animation.PipAlphaAnimator;
@@ -83,7 +83,7 @@ public class PipSchedulerTest {
@Mock private PipSurfaceTransactionHelper.SurfaceControlTransactionFactory mMockFactory;
@Mock private SurfaceControl.Transaction mMockTransaction;
@Mock private PipAlphaAnimator mMockAlphaAnimator;
- @Mock private Optional<DesktopRepository> mMockOptionalDesktopRepository;
+ @Mock private Optional<DesktopUserRepositories> mMockOptionalDesktopUserRepositories;
@Mock private RootTaskDisplayAreaOrganizer mRootTaskDisplayAreaOrganizer;
@Captor private ArgumentCaptor<Runnable> mRunnableArgumentCaptor;
@@ -102,7 +102,7 @@ public class PipSchedulerTest {
.thenReturn(mMockTransaction);
mPipScheduler = new PipScheduler(mMockContext, mMockPipBoundsState, mMockMainExecutor,
- mMockPipTransitionState, mMockOptionalDesktopRepository,
+ mMockPipTransitionState, mMockOptionalDesktopUserRepositories,
mRootTaskDisplayAreaOrganizer);
mPipScheduler.setPipTransitionController(mMockPipTransitionController);
mPipScheduler.setSurfaceControlTransactionFactory(mMockFactory);
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentTasksControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentTasksControllerTest.java
index 68c8aab8849d..95f371f7000a 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentTasksControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentTasksControllerTest.java
@@ -26,6 +26,8 @@ import static com.android.launcher3.Flags.FLAG_ENABLE_REFACTOR_TASK_THUMBNAIL;
import static com.android.window.flags.Flags.FLAG_ENABLE_DESKTOP_WINDOWING_PERSISTENCE;
import static com.android.wm.shell.shared.split.SplitScreenConstants.SNAP_TO_2_50_50;
+import static com.google.common.truth.Truth.assertThat;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
@@ -57,6 +59,7 @@ import android.content.pm.PackageManager;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.Bundle;
+import android.os.UserManager;
import android.platform.test.annotations.DisableFlags;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule;
@@ -74,6 +77,7 @@ import com.android.wm.shell.TestShellExecutor;
import com.android.wm.shell.common.DisplayInsetsController;
import com.android.wm.shell.common.TaskStackListenerImpl;
import com.android.wm.shell.desktopmode.DesktopRepository;
+import com.android.wm.shell.desktopmode.DesktopUserRepositories;
import com.android.wm.shell.desktopmode.DesktopWallpaperActivity;
import com.android.wm.shell.shared.GroupedTaskInfo;
import com.android.wm.shell.shared.ShellSharedConstants;
@@ -113,8 +117,6 @@ public class RecentTasksControllerTest extends ShellTestCase {
@Mock
private ShellCommandHandler mShellCommandHandler;
@Mock
- private DesktopRepository mDesktopRepository;
- @Mock
private ActivityTaskManager mActivityTaskManager;
@Mock
private DisplayInsetsController mDisplayInsetsController;
@@ -122,6 +124,10 @@ public class RecentTasksControllerTest extends ShellTestCase {
private IRecentTasksListener mRecentTasksListener;
@Mock
private TaskStackTransitionObserver mTaskStackTransitionObserver;
+ @Mock
+ private DesktopUserRepositories mDesktopUserRepositories;
+ @Mock
+ private DesktopRepository mDesktopRepository;
@Rule
public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
@@ -142,6 +148,8 @@ public class RecentTasksControllerTest extends ShellTestCase {
.when(() -> DesktopModeStatus.canEnterDesktopMode(any()));
mMainExecutor = new TestShellExecutor();
+ when(mDesktopUserRepositories.getCurrent()).thenReturn(mDesktopRepository);
+ when(mDesktopUserRepositories.getProfile(anyInt())).thenReturn(mDesktopRepository);
when(mContext.getPackageManager()).thenReturn(mock(PackageManager.class));
when(mContext.getSystemService(KeyguardManager.class))
.thenReturn(mock(KeyguardManager.class));
@@ -150,7 +158,7 @@ public class RecentTasksControllerTest extends ShellTestCase {
mDisplayInsetsController, mMainExecutor));
mRecentTasksControllerReal = new RecentTasksController(mContext, mShellInit,
mShellController, mShellCommandHandler, mTaskStackListener, mActivityTaskManager,
- Optional.of(mDesktopRepository), mTaskStackTransitionObserver,
+ Optional.of(mDesktopUserRepositories), mTaskStackTransitionObserver,
mMainExecutor);
mRecentTasksController = spy(mRecentTasksControllerReal);
mShellTaskOrganizer = new ShellTaskOrganizer(mShellInit, mShellCommandHandler,
@@ -182,6 +190,12 @@ public class RecentTasksControllerTest extends ShellTestCase {
}
@Test
+ public void instantiateController_initializesRepository() {
+ verify(mDesktopUserRepositories, times(1)).getCurrent();
+ verify(mDesktopRepository, times(1)).addActiveTaskListener(any());
+ }
+
+ @Test
public void testInvalidateExternalInterface_unregistersListener() {
// Note: We have to use the real instance of the controller here since that is the instance
// that is passed to ShellController internally, and the instance that the listener will be
@@ -323,8 +337,8 @@ public class RecentTasksControllerTest extends ShellTestCase {
RecentTaskInfo t4 = makeTaskInfo(4);
setRawList(t1, t2, t3, t4);
- when(mDesktopRepository.isActiveTask(1)).thenReturn(true);
- when(mDesktopRepository.isActiveTask(3)).thenReturn(true);
+ when(mDesktopUserRepositories.getCurrent().isActiveTask(1)).thenReturn(true);
+ when(mDesktopUserRepositories.getCurrent().isActiveTask(3)).thenReturn(true);
ArrayList<GroupedTaskInfo> recentTasks =
mRecentTasksController.getRecentTasks(MAX_VALUE, RECENT_IGNORE_UNAVAILABLE, 0);
@@ -362,8 +376,8 @@ public class RecentTasksControllerTest extends ShellTestCase {
new SplitBounds(new Rect(), new Rect(), 1, 2, SNAP_TO_2_50_50);
mRecentTasksController.addSplitPair(t1.taskId, t2.taskId, pair1Bounds);
- when(mDesktopRepository.isActiveTask(3)).thenReturn(true);
- when(mDesktopRepository.isActiveTask(5)).thenReturn(true);
+ when(mDesktopUserRepositories.getCurrent().isActiveTask(3)).thenReturn(true);
+ when(mDesktopUserRepositories.getCurrent().isActiveTask(5)).thenReturn(true);
ArrayList<GroupedTaskInfo> recentTasks =
mRecentTasksController.getRecentTasks(MAX_VALUE, RECENT_IGNORE_UNAVAILABLE, 0);
@@ -402,8 +416,8 @@ public class RecentTasksControllerTest extends ShellTestCase {
RecentTaskInfo t4 = makeTaskInfo(4);
setRawList(t1, t2, t3, t4);
- when(mDesktopRepository.isActiveTask(1)).thenReturn(true);
- when(mDesktopRepository.isActiveTask(3)).thenReturn(true);
+ when(mDesktopUserRepositories.getCurrent().isActiveTask(1)).thenReturn(true);
+ when(mDesktopUserRepositories.getCurrent().isActiveTask(3)).thenReturn(true);
ArrayList<GroupedTaskInfo> recentTasks =
mRecentTasksController.getRecentTasks(MAX_VALUE, RECENT_IGNORE_UNAVAILABLE, 0);
@@ -431,7 +445,9 @@ public class RecentTasksControllerTest extends ShellTestCase {
setRawList(t1, t2, t3, t4, t5);
when(mDesktopRepository.isActiveTask(1)).thenReturn(true);
+ when(mDesktopRepository.isActiveTask(2)).thenReturn(false);
when(mDesktopRepository.isActiveTask(3)).thenReturn(true);
+ when(mDesktopRepository.isActiveTask(4)).thenReturn(false);
when(mDesktopRepository.isActiveTask(5)).thenReturn(true);
when(mDesktopRepository.isMinimizedTask(3)).thenReturn(true);
@@ -470,8 +486,8 @@ public class RecentTasksControllerTest extends ShellTestCase {
t2.lastNonFullscreenBounds = new Rect(150, 250, 350, 450);
setRawList(t1, t2);
- when(mDesktopRepository.isActiveTask(1)).thenReturn(true);
- when(mDesktopRepository.isActiveTask(2)).thenReturn(true);
+ when(mDesktopUserRepositories.getCurrent().isActiveTask(1)).thenReturn(true);
+ when(mDesktopUserRepositories.getCurrent().isActiveTask(2)).thenReturn(true);
ArrayList<GroupedTaskInfo> recentTasks =
mRecentTasksController.getRecentTasks(MAX_VALUE, RECENT_IGNORE_UNAVAILABLE, 0);
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentsTransitionHandlerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentsTransitionHandlerTest.java
index f0f5fe159069..894d238b7e15 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentsTransitionHandlerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentsTransitionHandlerTest.java
@@ -65,6 +65,7 @@ import com.android.wm.shell.TestShellExecutor;
import com.android.wm.shell.common.DisplayInsetsController;
import com.android.wm.shell.common.TaskStackListenerImpl;
import com.android.wm.shell.desktopmode.DesktopRepository;
+import com.android.wm.shell.desktopmode.DesktopUserRepositories;
import com.android.wm.shell.shared.desktopmode.DesktopModeStatus;
import com.android.wm.shell.sysui.ShellCommandHandler;
import com.android.wm.shell.sysui.ShellController;
@@ -100,7 +101,7 @@ public class RecentsTransitionHandlerTest extends ShellTestCase {
@Mock
private ShellCommandHandler mShellCommandHandler;
@Mock
- private DesktopRepository mDesktopRepository;
+ private DesktopUserRepositories mDesktopUserRepositories;
@Mock
private ActivityTaskManager mActivityTaskManager;
@Mock
@@ -112,6 +113,8 @@ public class RecentsTransitionHandlerTest extends ShellTestCase {
@Mock
private Transitions mTransitions;
+ @Mock private DesktopRepository mDesktopRepository;
+
@Rule
public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
@@ -131,6 +134,7 @@ public class RecentsTransitionHandlerTest extends ShellTestCase {
ExtendedMockito.doReturn(true)
.when(() -> DesktopModeStatus.canEnterDesktopMode(any()));
+ when(mDesktopUserRepositories.getCurrent()).thenReturn(mDesktopRepository);
mMainExecutor = new TestShellExecutor();
when(mContext.getPackageManager()).thenReturn(mock(PackageManager.class));
when(mContext.getSystemService(KeyguardManager.class))
@@ -140,7 +144,7 @@ public class RecentsTransitionHandlerTest extends ShellTestCase {
mDisplayInsetsController, mMainExecutor));
mRecentTasksControllerReal = new RecentTasksController(mContext, mShellInit,
mShellController, mShellCommandHandler, mTaskStackListener, mActivityTaskManager,
- Optional.of(mDesktopRepository), mTaskStackTransitionObserver,
+ Optional.of(mDesktopUserRepositories), mTaskStackTransitionObserver,
mMainExecutor);
mRecentTasksController = spy(mRecentTasksControllerReal);
mShellTaskOrganizer = new ShellTaskOrganizer(mShellInit, mShellCommandHandler,
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopHeaderManageWindowsMenuTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopHeaderManageWindowsMenuTest.kt
index 1215c52209a5..44035588887f 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopHeaderManageWindowsMenuTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopHeaderManageWindowsMenuTest.kt
@@ -29,12 +29,13 @@ import com.android.wm.shell.MockToken
import com.android.wm.shell.ShellTestCase
import com.android.wm.shell.TestRunningTaskInfoBuilder
import com.android.wm.shell.TestShellExecutor
-import com.android.wm.shell.desktopmode.DesktopRepository
+import com.android.wm.shell.desktopmode.DesktopUserRepositories
import com.android.wm.shell.sysui.ShellInit
import com.android.wm.shell.windowdecor.additionalviewcontainer.AdditionalSystemViewContainer
import com.google.common.truth.Truth.assertThat
import org.junit.After
import org.junit.Before
+import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@@ -55,17 +56,18 @@ class DesktopHeaderManageWindowsMenuTest : ShellTestCase() {
@Rule
val setFlagsRule: SetFlagsRule = SetFlagsRule()
- private lateinit var desktopRepository: DesktopRepository
+ private lateinit var userRepositories: DesktopUserRepositories
private lateinit var menu: DesktopHeaderManageWindowsMenu
@Before
fun setUp() {
- desktopRepository = DesktopRepository(
+ userRepositories = DesktopUserRepositories(
context = context,
shellInit = ShellInit(TestShellExecutor()),
persistentRepository = mock(),
repositoryInitializer = mock(),
- mainCoroutineScope = mock()
+ mainCoroutineScope = mock(),
+ userManager = mock(),
)
}
@@ -75,15 +77,15 @@ class DesktopHeaderManageWindowsMenuTest : ShellTestCase() {
}
@Test
+ @Ignore("Test is failing internally")
@EnableFlags(Flags.FLAG_ENABLE_FULLY_IMMERSIVE_IN_DESKTOP)
fun testShow_forImmersiveTask_usesSystemViewContainer() {
val task = createFreeformTask()
- desktopRepository.setTaskInFullImmersiveState(
+ userRepositories.getProfile(DEFAULT_USER_ID).setTaskInFullImmersiveState(
displayId = task.displayId,
taskId = task.taskId,
immersive = true
)
-
menu = createMenu(task)
assertThat(menu.menuViewContainer).isInstanceOf(AdditionalSystemViewContainer::class.java)
@@ -96,7 +98,7 @@ class DesktopHeaderManageWindowsMenuTest : ShellTestCase() {
displayController = mock(),
rootTdaOrganizer = mock(),
context = context,
- desktopRepository = desktopRepository,
+ desktopUserRepositories = userRepositories,
surfaceControlBuilderSupplier = { SurfaceControl.Builder() },
surfaceControlTransactionSupplier = { SurfaceControl.Transaction() },
snapshotList = emptyList(),
@@ -109,4 +111,8 @@ class DesktopHeaderManageWindowsMenuTest : ShellTestCase() {
.setActivityType(ACTIVITY_TYPE_STANDARD)
.setWindowingMode(WINDOWING_MODE_FREEFORM)
.build()
+
+ private companion object {
+ const val DEFAULT_USER_ID = 10
+ }
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTestsBase.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTestsBase.kt
index 080f496593cf..afd46078074c 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTestsBase.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTestsBase.kt
@@ -60,6 +60,7 @@ import com.android.wm.shell.desktopmode.DesktopModeUiEventLogger
import com.android.wm.shell.desktopmode.DesktopRepository
import com.android.wm.shell.desktopmode.DesktopTasksController
import com.android.wm.shell.desktopmode.DesktopTasksLimiter
+import com.android.wm.shell.desktopmode.DesktopUserRepositories
import com.android.wm.shell.desktopmode.WindowDecorCaptionHandleRepository
import com.android.wm.shell.desktopmode.education.AppHandleEducationController
import com.android.wm.shell.desktopmode.education.AppToWebEducationController
@@ -108,7 +109,7 @@ open class DesktopModeWindowDecorViewModelTestsBase : ShellTestCase() {
protected val mockTaskOrganizer = mock<ShellTaskOrganizer>()
protected val mockDisplayController = mock<DisplayController>()
protected val mockSplitScreenController = mock<SplitScreenController>()
- protected val mockDesktopRepository = mock<DesktopRepository>()
+ protected val mockDesktopUserRepositories = mock<DesktopUserRepositories>()
protected val mockDisplayLayout = mock<DisplayLayout>()
protected val displayInsetsController = mock<DisplayInsetsController>()
protected val mockSyncQueue = mock<SyncTransactionQueue>()
@@ -142,6 +143,7 @@ open class DesktopModeWindowDecorViewModelTestsBase : ShellTestCase() {
protected val mockAppToWebEducationController = mock<AppToWebEducationController>()
protected val mockFocusTransitionObserver = mock<FocusTransitionObserver>()
protected val mockCaptionHandleRepository = mock<WindowDecorCaptionHandleRepository>()
+ protected val mockDesktopRepository: DesktopRepository = mock<DesktopRepository>()
protected val motionEvent = mock<MotionEvent>()
val displayController = mock<DisplayController>()
val displayLayout = mock<DisplayLayout>()
@@ -168,6 +170,9 @@ open class DesktopModeWindowDecorViewModelTestsBase : ShellTestCase() {
windowDecorByTaskIdSpy.clear()
spyContext.addMockSystemService(InputManager::class.java, mockInputManager)
desktopModeEventLogger = mock<DesktopModeEventLogger>()
+ whenever(mockDesktopUserRepositories.current).thenReturn(mockDesktopRepository)
+ whenever(mockDesktopUserRepositories.getProfile(anyInt()))
+ .thenReturn(mockDesktopRepository)
desktopModeWindowDecorViewModel = DesktopModeWindowDecorViewModel(
spyContext,
testShellExecutor,
@@ -178,7 +183,7 @@ open class DesktopModeWindowDecorViewModelTestsBase : ShellTestCase() {
mockShellCommandHandler,
mockWindowManager,
mockTaskOrganizer,
- mockDesktopRepository,
+ mockDesktopUserRepositories,
mockDisplayController,
mockShellController,
displayInsetsController,
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java
index 03c7c9857d8f..a389bea03141 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java
@@ -109,6 +109,7 @@ import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.desktopmode.CaptionState;
import com.android.wm.shell.desktopmode.DesktopModeEventLogger;
import com.android.wm.shell.desktopmode.DesktopRepository;
+import com.android.wm.shell.desktopmode.DesktopUserRepositories;
import com.android.wm.shell.desktopmode.WindowDecorCaptionHandleRepository;
import com.android.wm.shell.shared.desktopmode.DesktopModeStatus;
import com.android.wm.shell.splitscreen.SplitScreenController;
@@ -165,7 +166,7 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase {
@Mock
private ShellTaskOrganizer mMockShellTaskOrganizer;
@Mock
- private DesktopRepository mMockDesktopRepository;
+ private DesktopUserRepositories mMockDesktopUserRepositories;
@Mock
private Choreographer mMockChoreographer;
@Mock
@@ -214,6 +215,8 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase {
private WindowDecorCaptionHandleRepository mMockCaptionHandleRepository;
@Mock
private DesktopModeEventLogger mDesktopModeEventLogger;
+ @Mock
+ private DesktopRepository mDesktopRepository;
@Captor
private ArgumentCaptor<Function1<Boolean, Unit>> mOnMaxMenuHoverChangeListener;
@Captor
@@ -270,6 +273,8 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase {
when(mMockMultiInstanceHelper.supportsMultiInstanceSplit(any())).thenReturn(false);
when(mMockAppHeaderViewHolderFactory.create(any(), any(), any(), any(), any(), any(), any(),
any())).thenReturn(mMockAppHeaderViewHolder);
+ when(mMockDesktopUserRepositories.getCurrent()).thenReturn(mDesktopRepository);
+ when(mMockDesktopUserRepositories.getProfile(anyInt())).thenReturn(mDesktopRepository);
}
@After
@@ -1469,8 +1474,8 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase {
final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(/* visible= */ true);
final DesktopModeWindowDecoration decoration = createWindowDecoration(taskInfo,
true /* relayout */);
- when(mMockDesktopRepository.isTaskInFullImmersiveState(taskInfo.taskId))
- .thenReturn(true);
+ when(mMockDesktopUserRepositories.getCurrent()
+ .isTaskInFullImmersiveState(taskInfo.taskId)).thenReturn(true);
createHandleMenu(decoration);
@@ -1705,8 +1710,8 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase {
boolean relayout) {
final DesktopModeWindowDecoration windowDecor = new DesktopModeWindowDecoration(mContext,
mContext, mMockDisplayController, mMockSplitScreenController,
- mMockDesktopRepository, mMockShellTaskOrganizer, taskInfo, mMockSurfaceControl,
- mMockHandler, mBgExecutor, mMockChoreographer, mMockSyncQueue,
+ mMockDesktopUserRepositories, mMockShellTaskOrganizer, taskInfo,
+ mMockSurfaceControl, mMockHandler, mBgExecutor, mMockChoreographer, mMockSyncQueue,
mMockAppHeaderViewHolderFactory, mMockRootTaskDisplayAreaOrganizer,
mMockGenericLinksParser, mMockAssistContentRequester, SurfaceControl.Builder::new,
mMockTransactionSupplier, WindowContainerTransaction::new, SurfaceControl::new,
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingDecorViewModelTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingDecorViewModelTest.kt
index d29002199f9d..193c2c25d26d 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingDecorViewModelTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingDecorViewModelTest.kt
@@ -25,7 +25,7 @@ import com.android.wm.shell.ShellTestCase
import com.android.wm.shell.common.DisplayController
import com.android.wm.shell.common.SyncTransactionQueue
import com.android.wm.shell.desktopmode.DesktopModeEventLogger
-import com.android.wm.shell.desktopmode.DesktopRepository
+import com.android.wm.shell.desktopmode.DesktopUserRepositories
import com.android.wm.shell.desktopmode.DesktopTasksController
import com.android.wm.shell.desktopmode.DesktopTestHelpers.createFreeformTask
import com.android.wm.shell.desktopmode.ReturnToDragStartAnimator
@@ -52,7 +52,7 @@ class DesktopTilingDecorViewModelTest : ShellTestCase() {
private val syncQueueMock: SyncTransactionQueue = mock()
private val transitionsMock: Transitions = mock()
private val shellTaskOrganizerMock: ShellTaskOrganizer = mock()
- private val desktopRepository: DesktopRepository = mock()
+ private val userRepositories: DesktopUserRepositories = mock()
private val desktopModeEventLogger: DesktopModeEventLogger = mock()
private val toggleResizeDesktopTaskTransitionHandlerMock:
ToggleResizeDesktopTaskTransitionHandler =
@@ -75,7 +75,7 @@ class DesktopTilingDecorViewModelTest : ShellTestCase() {
shellTaskOrganizerMock,
toggleResizeDesktopTaskTransitionHandlerMock,
returnToDragStartAnimatorMock,
- desktopRepository,
+ userRepositories,
desktopModeEventLogger,
)
whenever(contextMock.createContextAsUser(any(), any())).thenReturn(contextMock)
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingWindowDecorationTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingWindowDecorationTest.kt
index 3b39f1e4a25a..95e2151be96c 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingWindowDecorationTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingWindowDecorationTest.kt
@@ -39,6 +39,7 @@ import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.ResizeT
import com.android.wm.shell.desktopmode.DesktopRepository
import com.android.wm.shell.desktopmode.DesktopTasksController
import com.android.wm.shell.desktopmode.DesktopTestHelpers.createFreeformTask
+import com.android.wm.shell.desktopmode.DesktopUserRepositories
import com.android.wm.shell.desktopmode.ReturnToDragStartAnimator
import com.android.wm.shell.desktopmode.ToggleResizeDesktopTaskTransitionHandler
import com.android.wm.shell.transition.Transitions
@@ -93,10 +94,11 @@ class DesktopTilingWindowDecorationTest : ShellTestCase() {
private val transition: IBinder = mock()
private val info: TransitionInfo = mock()
private val finishCallback: Transitions.TransitionFinishCallback = mock()
- private val desktopRepository: DesktopRepository = mock()
+ private val userRepositories: DesktopUserRepositories = mock()
private val desktopModeEventLogger: DesktopModeEventLogger = mock()
private val desktopTilingDividerWindowManager: DesktopTilingDividerWindowManager = mock()
private val motionEvent: MotionEvent = mock()
+ private val desktopRepository: DesktopRepository = mock()
private lateinit var tilingDecoration: DesktopTilingWindowDecoration
private val split_divider_width = 10
@@ -116,10 +118,11 @@ class DesktopTilingWindowDecorationTest : ShellTestCase() {
shellTaskOrganizer,
toggleResizeDesktopTaskTransitionHandler,
returnToDragStartAnimator,
- desktopRepository,
+ userRepositories,
desktopModeEventLogger,
)
whenever(context.createContextAsUser(any(), any())).thenReturn(context)
+ whenever(userRepositories.current).thenReturn(desktopRepository)
}
@Test
@@ -275,8 +278,8 @@ class DesktopTilingWindowDecorationTest : ShellTestCase() {
}
whenever(context.resources).thenReturn(resources)
whenever(resources.getDimensionPixelSize(any())).thenReturn(split_divider_width)
- whenever(desktopRepository.isVisibleTask(eq(task1.taskId))).thenReturn(true)
- whenever(desktopRepository.isVisibleTask(eq(task2.taskId))).thenReturn(true)
+ whenever(userRepositories.current.isVisibleTask(eq(task1.taskId))).thenReturn(true)
+ whenever(userRepositories.current.isVisibleTask(eq(task2.taskId))).thenReturn(true)
tilingDecoration.onAppTiled(
task1,
@@ -308,7 +311,7 @@ class DesktopTilingWindowDecorationTest : ShellTestCase() {
whenever(context.resources).thenReturn(resources)
whenever(resources.getDimensionPixelSize(any())).thenReturn(split_divider_width)
whenever(desktopWindowDecoration.getLeash()).thenReturn(surfaceControlMock)
- whenever(desktopRepository.isVisibleTask(any())).thenReturn(true)
+ whenever(userRepositories.current.isVisibleTask(any())).thenReturn(true)
tilingDecoration.onAppTiled(
task1,
desktopWindowDecoration,
@@ -341,7 +344,7 @@ class DesktopTilingWindowDecorationTest : ShellTestCase() {
whenever(context.resources).thenReturn(resources)
whenever(resources.getDimensionPixelSize(any())).thenReturn(split_divider_width)
whenever(desktopWindowDecoration.getLeash()).thenReturn(surfaceControlMock)
- whenever(desktopRepository.isVisibleTask(any())).thenReturn(true)
+ whenever(userRepositories.current.isVisibleTask(any())).thenReturn(true)
tilingDecoration.onAppTiled(
task1,
desktopWindowDecoration,
@@ -614,7 +617,7 @@ class DesktopTilingWindowDecorationTest : ShellTestCase() {
private fun createVisibleTask() =
createFreeformTask().also {
- whenever(desktopRepository.isVisibleTask(eq(it.taskId))).thenReturn(true)
+ whenever(userRepositories.current.isVisibleTask(eq(it.taskId))).thenReturn(true)
}
companion object {