5/ Fix inverted dependency for ShellCommandHandler

- Instead of ShellCommandHandler referencing the controllers that it
  needs to dump/call on, invert it so that controllers register a
  dump/command callback when they are initialized

Test: atest WMShellUnitTests
Test: atest SystemUITests
Test: adb shell dumpsys activity service SystemUIservice WMShell
Test: adb shell dumpsys activity service SystemUIservice WMShell splitscreen <cmd>
Test: adb shell dumpsys activity service SystemUIservice WMShell help
Bug: 238217847
Change-Id: I673e5f7dd11ed7af326d52da8e793356169f1d8f
This commit is contained in:
Winson Chung
2022-07-09 03:18:35 +00:00
parent 8df4942e0d
commit 38caa7a7df
24 changed files with 433 additions and 235 deletions

View File

@@ -55,6 +55,7 @@ import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.compatui.CompatUIController;
import com.android.wm.shell.recents.RecentTasksController;
import com.android.wm.shell.startingsurface.StartingWindowController;
import com.android.wm.shell.sysui.ShellCommandHandler;
import com.android.wm.shell.sysui.ShellInit;
import com.android.wm.shell.unfold.UnfoldAnimationController;
@@ -72,6 +73,7 @@ import java.util.function.Consumer;
*/
public class ShellTaskOrganizer extends TaskOrganizer implements
CompatUIController.CompatUICallback {
private static final String TAG = "ShellTaskOrganizer";
// Intentionally using negative numbers here so the positive numbers can be used
// for task id specific listeners that will be added later.
@@ -90,8 +92,6 @@ public class ShellTaskOrganizer extends TaskOrganizer implements
})
public @interface TaskListenerType {}
private static final String TAG = "ShellTaskOrganizer";
/**
* Callbacks for when the tasks change in the system.
*/
@@ -177,6 +177,9 @@ public class ShellTaskOrganizer extends TaskOrganizer implements
@Nullable
private final CompatUIController mCompatUI;
@NonNull
private final ShellCommandHandler mShellCommandHandler;
@Nullable
private final Optional<RecentTasksController> mRecentTasks;
@@ -187,29 +190,33 @@ public class ShellTaskOrganizer extends TaskOrganizer implements
private RunningTaskInfo mLastFocusedTaskInfo;
public ShellTaskOrganizer(ShellExecutor mainExecutor) {
this(null /* shellInit */, null /* taskOrganizerController */, null /* compatUI */,
this(null /* shellInit */, null /* shellCommandHandler */,
null /* taskOrganizerController */, null /* compatUI */,
Optional.empty() /* unfoldAnimationController */,
Optional.empty() /* recentTasksController */,
mainExecutor);
}
public ShellTaskOrganizer(ShellInit shellInit,
ShellCommandHandler shellCommandHandler,
@Nullable CompatUIController compatUI,
Optional<UnfoldAnimationController> unfoldAnimationController,
Optional<RecentTasksController> recentTasks,
ShellExecutor mainExecutor) {
this(shellInit, null /* taskOrganizerController */, compatUI,
this(shellInit, shellCommandHandler, null /* taskOrganizerController */, compatUI,
unfoldAnimationController, recentTasks, mainExecutor);
}
@VisibleForTesting
protected ShellTaskOrganizer(ShellInit shellInit,
ShellCommandHandler shellCommandHandler,
ITaskOrganizerController taskOrganizerController,
@Nullable CompatUIController compatUI,
Optional<UnfoldAnimationController> unfoldAnimationController,
Optional<RecentTasksController> recentTasks,
ShellExecutor mainExecutor) {
super(taskOrganizerController, mainExecutor);
mShellCommandHandler = shellCommandHandler;
mCompatUI = compatUI;
mRecentTasks = recentTasks;
mUnfoldAnimationController = unfoldAnimationController.orElse(null);
@@ -219,6 +226,7 @@ public class ShellTaskOrganizer extends TaskOrganizer implements
}
private void onInit() {
mShellCommandHandler.addDumpCallback(this::dump, this);
if (mCompatUI != null) {
mCompatUI.setCompatUICallback(this);
}

View File

@@ -174,13 +174,14 @@ public abstract class WMShellBaseModule {
@Provides
static ShellTaskOrganizer provideShellTaskOrganizer(
ShellInit shellInit,
ShellCommandHandler shellCommandHandler,
CompatUIController compatUI,
Optional<UnfoldAnimationController> unfoldAnimationController,
Optional<RecentTasksController> recentTasksOptional,
@ShellMainThread ShellExecutor mainExecutor
) {
return new ShellTaskOrganizer(shellInit, compatUI, unfoldAnimationController,
recentTasksOptional, mainExecutor);
return new ShellTaskOrganizer(shellInit, shellCommandHandler, compatUI,
unfoldAnimationController, recentTasksOptional, mainExecutor);
}
@WMSingleton
@@ -188,6 +189,7 @@ public abstract class WMShellBaseModule {
static KidsModeTaskOrganizer provideKidsModeTaskOrganizer(
Context context,
ShellInit shellInit,
ShellCommandHandler shellCommandHandler,
SyncTransactionQueue syncTransactionQueue,
DisplayController displayController,
DisplayInsetsController displayInsetsController,
@@ -196,9 +198,9 @@ public abstract class WMShellBaseModule {
@ShellMainThread ShellExecutor mainExecutor,
@ShellMainThread Handler mainHandler
) {
return new KidsModeTaskOrganizer(context, shellInit, syncTransactionQueue,
displayController, displayInsetsController, unfoldAnimationController,
recentTasksOptional, mainExecutor, mainHandler);
return new KidsModeTaskOrganizer(context, shellInit, shellCommandHandler,
syncTransactionQueue, displayController, displayInsetsController,
unfoldAnimationController, recentTasksOptional, mainExecutor, mainHandler);
}
@WMSingleton
@@ -388,12 +390,13 @@ public abstract class WMShellBaseModule {
@Provides
static Optional<HideDisplayCutoutController> provideHideDisplayCutoutController(Context context,
ShellInit shellInit,
ShellCommandHandler shellCommandHandler,
ShellController shellController,
DisplayController displayController,
@ShellMainThread ShellExecutor mainExecutor) {
return Optional.ofNullable(
HideDisplayCutoutController.create(context, shellInit, shellController,
displayController, mainExecutor));
HideDisplayCutoutController.create(context, shellInit, shellCommandHandler,
shellController, displayController, mainExecutor));
}
//
@@ -471,12 +474,13 @@ public abstract class WMShellBaseModule {
static Optional<RecentTasksController> provideRecentTasksController(
Context context,
ShellInit shellInit,
ShellCommandHandler shellCommandHandler,
TaskStackListenerImpl taskStackListener,
@ShellMainThread ShellExecutor mainExecutor
) {
return Optional.ofNullable(
RecentTasksController.create(context, shellInit, taskStackListener,
mainExecutor));
RecentTasksController.create(context, shellInit, shellCommandHandler,
taskStackListener, mainExecutor));
}
//
@@ -654,8 +658,9 @@ public abstract class WMShellBaseModule {
@WMSingleton
@Provides
static ShellController provideShellController(ShellInit shellInit,
ShellCommandHandler shellCommandHandler,
@ShellMainThread ShellExecutor mainExecutor) {
return new ShellController(shellInit, mainExecutor);
return new ShellController(shellInit, shellCommandHandler, mainExecutor);
}
//
@@ -681,12 +686,15 @@ public abstract class WMShellBaseModule {
KidsModeTaskOrganizer kidsModeTaskOrganizer,
Optional<BubbleController> bubblesOptional,
Optional<SplitScreenController> splitScreenOptional,
Optional<Pip> pipOptional,
Optional<PipTouchHandler> pipTouchHandlerOptional,
FullscreenTaskListener fullscreenTaskListener,
Optional<UnfoldAnimationController> unfoldAnimationController,
Optional<UnfoldTransitionHandler> unfoldTransitionHandler,
Optional<FreeformComponents> freeformComponents,
Optional<RecentTasksController> recentTasksOptional,
Optional<OneHandedController> oneHandedControllerOptional,
Optional<HideDisplayCutoutController> hideDisplayCutoutControllerOptional,
ActivityEmbeddingController activityEmbeddingOptional,
Transitions transitions,
StartingWindowController startingWindow,
@@ -702,18 +710,7 @@ public abstract class WMShellBaseModule {
@WMSingleton
@Provides
static ShellCommandHandler provideShellCommandHandlerImpl(
ShellController shellController,
ShellTaskOrganizer shellTaskOrganizer,
KidsModeTaskOrganizer kidsModeTaskOrganizer,
Optional<SplitScreenController> splitScreenOptional,
Optional<Pip> pipOptional,
Optional<OneHandedController> oneHandedOptional,
Optional<HideDisplayCutoutController> hideDisplayCutout,
Optional<RecentTasksController> recentTasksOptional,
@ShellMainThread ShellExecutor mainExecutor) {
return new ShellCommandHandler(shellController, shellTaskOrganizer,
kidsModeTaskOrganizer, splitScreenOptional, pipOptional, oneHandedOptional,
hideDisplayCutout, recentTasksOptional, mainExecutor);
static ShellCommandHandler provideShellCommandHandler() {
return new ShellCommandHandler();
}
}

View File

@@ -74,6 +74,7 @@ import com.android.wm.shell.pip.phone.PipMotionHelper;
import com.android.wm.shell.pip.phone.PipTouchHandler;
import com.android.wm.shell.recents.RecentTasksController;
import com.android.wm.shell.splitscreen.SplitScreenController;
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.transition.SplitscreenPipMixedHandler;
@@ -249,6 +250,7 @@ public abstract class WMShellModule {
@DynamicOverride
static OneHandedController provideOneHandedController(Context context,
ShellInit shellInit,
ShellCommandHandler shellCommandHandler,
ShellController shellController,
WindowManager windowManager,
DisplayController displayController,
@@ -258,9 +260,9 @@ public abstract class WMShellModule {
InteractionJankMonitor jankMonitor,
@ShellMainThread ShellExecutor mainExecutor,
@ShellMainThread Handler mainHandler) {
return OneHandedController.create(context, shellInit, shellController, windowManager,
displayController, displayLayout, taskStackListener, jankMonitor, uiEventLogger,
mainExecutor, mainHandler);
return OneHandedController.create(context, shellInit, shellCommandHandler, shellController,
windowManager, displayController, displayLayout, taskStackListener, jankMonitor,
uiEventLogger, mainExecutor, mainHandler);
}
//
@@ -273,6 +275,7 @@ public abstract class WMShellModule {
static SplitScreenController provideSplitScreenController(
Context context,
ShellInit shellInit,
ShellCommandHandler shellCommandHandler,
ShellController shellController,
ShellTaskOrganizer shellTaskOrganizer,
SyncTransactionQueue syncQueue,
@@ -286,10 +289,10 @@ public abstract class WMShellModule {
IconProvider iconProvider,
Optional<RecentTasksController> recentTasks,
@ShellMainThread ShellExecutor mainExecutor) {
return new SplitScreenController(context, shellInit, shellController, shellTaskOrganizer,
syncQueue, rootTaskDisplayAreaOrganizer, displayController, displayImeController,
displayInsetsController, dragAndDropController, transitions, transactionPool,
iconProvider, recentTasks, mainExecutor);
return new SplitScreenController(context, shellInit, shellCommandHandler, shellController,
shellTaskOrganizer, syncQueue, rootTaskDisplayAreaOrganizer, displayController,
displayImeController, displayInsetsController, dragAndDropController, transitions,
transactionPool, iconProvider, recentTasks, mainExecutor);
}
//
@@ -298,20 +301,29 @@ public abstract class WMShellModule {
@WMSingleton
@Provides
static Optional<Pip> providePip(Context context, ShellInit shellInit,
ShellController shellController, DisplayController displayController,
PipAppOpsListener pipAppOpsListener, PipBoundsAlgorithm pipBoundsAlgorithm,
PipKeepClearAlgorithm pipKeepClearAlgorithm, PipBoundsState pipBoundsState,
PipMotionHelper pipMotionHelper, PipMediaController pipMediaController,
PhonePipMenuController phonePipMenuController, PipTaskOrganizer pipTaskOrganizer,
static Optional<Pip> providePip(Context context,
ShellInit shellInit,
ShellCommandHandler shellCommandHandler,
ShellController shellController,
DisplayController displayController,
PipAppOpsListener pipAppOpsListener,
PipBoundsAlgorithm pipBoundsAlgorithm,
PipKeepClearAlgorithm pipKeepClearAlgorithm,
PipBoundsState pipBoundsState,
PipMotionHelper pipMotionHelper,
PipMediaController pipMediaController,
PhonePipMenuController phonePipMenuController,
PipTaskOrganizer pipTaskOrganizer,
PipTransitionState pipTransitionState,
PipTouchHandler pipTouchHandler, PipTransitionController pipTransitionController,
PipTouchHandler pipTouchHandler,
PipTransitionController pipTransitionController,
WindowManagerShellWrapper windowManagerShellWrapper,
TaskStackListenerImpl taskStackListener,
PipParamsChangedForwarder pipParamsChangedForwarder,
Optional<OneHandedController> oneHandedController,
@ShellMainThread ShellExecutor mainExecutor) {
return Optional.ofNullable(PipController.create(context, shellInit, shellController,
return Optional.ofNullable(PipController.create(
context, shellInit, shellCommandHandler, shellController,
displayController, pipAppOpsListener, pipBoundsAlgorithm, pipKeepClearAlgorithm,
pipBoundsState, pipMotionHelper, pipMediaController, phonePipMenuController,
pipTaskOrganizer, pipTransitionState, pipTouchHandler, pipTransitionController,

View File

@@ -59,9 +59,9 @@ WMShell SysUI service:
adb shell dumpsys activity service SystemUIService WMShell
```
If information should be added to the dump, make updates to:
- `WMShell` if you are dumping SysUI state
- `ShellCommandHandler` if you are dumping Shell state
If information should be added to the dump, either:
- Update `WMShell` if you are dumping SysUI state
- Inject `ShellCommandHandler` into your Shell class, and add a dump callback
## Debugging in Android Studio

View File

@@ -32,7 +32,7 @@ interfaces provided by the Shell and the rest of SystemUI.
More detail can be found in [go/wm-sysui-dagger](http://go/wm-sysui-dagger).
## Interfaces to Shell components
## Interfaces from SysUI to Shell components
Within the same process, the WM Shell components can be running on a different thread than the main
SysUI thread (disabled on certain products). This introduces challenges where we have to be
@@ -54,12 +54,30 @@ For example, you might have:
Adding an interface to a Shell component may seem like a lot of boiler plate, but is currently
necessary to maintain proper threading and logic isolation.
## Configuration changes & other SysUI events
## Listening for Configuration changes & other SysUI events
Aside from direct calls into Shell controllers for exposed features, the Shell also receives
Aside from direct calls into Shell controllers for exposed features, the Shell also receives
common event callbacks from SysUI via the `ShellController`. This includes things like:
- Configuration changes
- TODO: Shell init
- TODO: Shell command
- TODO: Keyguard events
- Keyguard events
- Shell init
- Shell dumps & commands
For other events which are specific to the Shell feature, then you can add callback methods on
the Shell feature interface. Any such calls should <u>**never**</u> be synchronous calls as
they will need to post to the Shell main thread to run.
## Shell commands & Dumps
Since the Shell library is a part of the SysUI process, it relies on SysUI to trigger commands
on individual Shell components, or to dump individual shell components.
```shell
# Dump everything
adb shell dumpsys activity service SystemUIService WMShell
# Run a specific command
adb shell dumpsys activity service SystemUIService WMShell help
adb shell dumpsys activity service SystemUIService WMShell <cmd> <args> ...
```

View File

@@ -27,6 +27,7 @@ import androidx.annotation.VisibleForTesting;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.sysui.ConfigurationChangeListener;
import com.android.wm.shell.sysui.ShellCommandHandler;
import com.android.wm.shell.sysui.ShellController;
import com.android.wm.shell.sysui.ShellInit;
@@ -39,6 +40,7 @@ public class HideDisplayCutoutController implements ConfigurationChangeListener
private static final String TAG = "HideDisplayCutoutController";
private final Context mContext;
private final ShellCommandHandler mShellCommandHandler;
private final ShellController mShellController;
private final HideDisplayCutoutOrganizer mOrganizer;
@VisibleForTesting
@@ -51,6 +53,7 @@ public class HideDisplayCutoutController implements ConfigurationChangeListener
@Nullable
public static HideDisplayCutoutController create(Context context,
ShellInit shellInit,
ShellCommandHandler shellCommandHandler,
ShellController shellController,
DisplayController displayController,
ShellExecutor mainExecutor) {
@@ -63,20 +66,24 @@ public class HideDisplayCutoutController implements ConfigurationChangeListener
HideDisplayCutoutOrganizer organizer =
new HideDisplayCutoutOrganizer(context, displayController, mainExecutor);
return new HideDisplayCutoutController(context, shellInit, shellController, organizer);
return new HideDisplayCutoutController(context, shellInit, shellCommandHandler,
shellController, organizer);
}
HideDisplayCutoutController(Context context,
ShellInit shellInit,
ShellCommandHandler shellCommandHandler,
ShellController shellController,
HideDisplayCutoutOrganizer organizer) {
mContext = context;
mShellCommandHandler = shellCommandHandler;
mShellController = shellController;
mOrganizer = organizer;
shellInit.addInitCallback(this::onInit, this);
}
private void onInit() {
mShellCommandHandler.addDumpCallback(this::dump, this);
updateStatus();
mShellController.addConfigurationChangeListener(this);
}
@@ -105,11 +112,11 @@ public class HideDisplayCutoutController implements ConfigurationChangeListener
updateStatus();
}
public void dump(@NonNull PrintWriter pw) {
final String prefix = " ";
public void dump(@NonNull PrintWriter pw, String prefix) {
final String innerPrefix = " ";
pw.print(TAG);
pw.println(" states: ");
pw.print(prefix);
pw.print(innerPrefix);
pw.print("mEnabled=");
pw.println(mEnabled);
mOrganizer.dump(pw);

View File

@@ -50,6 +50,7 @@ import com.android.wm.shell.common.DisplayLayout;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.recents.RecentTasksController;
import com.android.wm.shell.sysui.ShellCommandHandler;
import com.android.wm.shell.sysui.ShellInit;
import com.android.wm.shell.unfold.UnfoldAnimationController;
@@ -73,6 +74,7 @@ public class KidsModeTaskOrganizer extends ShellTaskOrganizer {
private final Handler mMainHandler;
private final Context mContext;
private final ShellCommandHandler mShellCommandHandler;
private final SyncTransactionQueue mSyncQueue;
private final DisplayController mDisplayController;
private final DisplayInsetsController mDisplayInsetsController;
@@ -141,6 +143,8 @@ public class KidsModeTaskOrganizer extends ShellTaskOrganizer {
@VisibleForTesting
KidsModeTaskOrganizer(
Context context,
ShellInit shellInit,
ShellCommandHandler shellCommandHandler,
ITaskOrganizerController taskOrganizerController,
SyncTransactionQueue syncTransactionQueue,
DisplayController displayController,
@@ -150,19 +154,23 @@ public class KidsModeTaskOrganizer extends ShellTaskOrganizer {
KidsModeSettingsObserver kidsModeSettingsObserver,
ShellExecutor mainExecutor,
Handler mainHandler) {
super(/* shellInit= */ null, taskOrganizerController, /* compatUI= */ null,
unfoldAnimationController, recentTasks, mainExecutor);
// Note: we don't call super with the shell init because we will be initializing manually
super(/* shellInit= */ null, /* shellCommandHandler= */ null, taskOrganizerController,
/* compatUI= */ null, unfoldAnimationController, recentTasks, mainExecutor);
mContext = context;
mShellCommandHandler = shellCommandHandler;
mMainHandler = mainHandler;
mSyncQueue = syncTransactionQueue;
mDisplayController = displayController;
mDisplayInsetsController = displayInsetsController;
mKidsModeSettingsObserver = kidsModeSettingsObserver;
shellInit.addInitCallback(this::onInit, this);
}
public KidsModeTaskOrganizer(
Context context,
ShellInit shellInit,
ShellCommandHandler shellCommandHandler,
SyncTransactionQueue syncTransactionQueue,
DisplayController displayController,
DisplayInsetsController displayInsetsController,
@@ -171,9 +179,10 @@ public class KidsModeTaskOrganizer extends ShellTaskOrganizer {
ShellExecutor mainExecutor,
Handler mainHandler) {
// Note: we don't call super with the shell init because we will be initializing manually
super(/* shellInit= */ null, /* compatUI= */ null, unfoldAnimationController, recentTasks,
mainExecutor);
super(/* shellInit= */ null, /* taskOrganizerController= */ null, /* compatUI= */ null,
unfoldAnimationController, recentTasks, mainExecutor);
mContext = context;
mShellCommandHandler = shellCommandHandler;
mMainHandler = mainHandler;
mSyncQueue = syncTransactionQueue;
mDisplayController = displayController;
@@ -185,6 +194,9 @@ public class KidsModeTaskOrganizer extends ShellTaskOrganizer {
* Initializes kids mode status.
*/
public void onInit() {
if (mShellCommandHandler != null) {
mShellCommandHandler.addDumpCallback(this::dump, this);
}
if (mKidsModeSettingsObserver == null) {
mKidsModeSettingsObserver = new KidsModeSettingsObserver(mMainHandler, mContext);
}

View File

@@ -56,6 +56,7 @@ import com.android.wm.shell.common.TaskStackListenerImpl;
import com.android.wm.shell.common.annotations.ExternalThread;
import com.android.wm.shell.sysui.ConfigurationChangeListener;
import com.android.wm.shell.sysui.KeyguardChangeListener;
import com.android.wm.shell.sysui.ShellCommandHandler;
import com.android.wm.shell.sysui.ShellController;
import com.android.wm.shell.sysui.ShellInit;
@@ -86,6 +87,7 @@ public class OneHandedController implements RemoteCallable<OneHandedController>,
private Context mContext;
private final ShellCommandHandler mShellCommandHandler;
private final ShellController mShellController;
private final AccessibilityManager mAccessibilityManager;
private final DisplayController mDisplayController;
@@ -194,7 +196,8 @@ public class OneHandedController implements RemoteCallable<OneHandedController>,
* Creates {@link OneHandedController}, returns {@code null} if the feature is not supported.
*/
public static OneHandedController create(Context context,
ShellInit shellInit, ShellController shellController, WindowManager windowManager,
ShellInit shellInit, ShellCommandHandler shellCommandHandler,
ShellController shellController, WindowManager windowManager,
DisplayController displayController, DisplayLayout displayLayout,
TaskStackListenerImpl taskStackListener,
InteractionJankMonitor jankMonitor, UiEventLogger uiEventLogger,
@@ -214,15 +217,16 @@ public class OneHandedController implements RemoteCallable<OneHandedController>,
context, displayLayout, settingsUtil, animationController, tutorialHandler,
jankMonitor, mainExecutor);
OneHandedUiEventLogger oneHandedUiEventsLogger = new OneHandedUiEventLogger(uiEventLogger);
return new OneHandedController(context, shellInit, shellController, displayController,
organizer, touchHandler, tutorialHandler, settingsUtil, accessibilityUtil,
timeoutHandler, oneHandedState, oneHandedUiEventsLogger, taskStackListener,
mainExecutor, mainHandler);
return new OneHandedController(context, shellInit, shellCommandHandler, shellController,
displayController, organizer, touchHandler, tutorialHandler, settingsUtil,
accessibilityUtil, timeoutHandler, oneHandedState, oneHandedUiEventsLogger,
taskStackListener, mainExecutor, mainHandler);
}
@VisibleForTesting
OneHandedController(Context context,
ShellInit shellInit,
ShellCommandHandler shellCommandHandler,
ShellController shellController,
DisplayController displayController,
OneHandedDisplayAreaOrganizer displayAreaOrganizer,
@@ -237,6 +241,7 @@ public class OneHandedController implements RemoteCallable<OneHandedController>,
ShellExecutor mainExecutor,
Handler mainHandler) {
mContext = context;
mShellCommandHandler = shellCommandHandler;
mShellController = shellController;
mOneHandedSettingsUtil = settingsUtil;
mOneHandedAccessibilityUtil = oneHandedAccessibilityUtil;
@@ -274,6 +279,7 @@ public class OneHandedController implements RemoteCallable<OneHandedController>,
}
private void onInit() {
mShellCommandHandler.addDumpCallback(this::dump, this);
mDisplayController.addDisplayWindowListener(mDisplaysChangedListener);
mDisplayController.addDisplayChangingController(this);
setupCallback();
@@ -629,7 +635,7 @@ public class OneHandedController implements RemoteCallable<OneHandedController>,
updateOneHandedEnabled();
}
public void dump(@NonNull PrintWriter pw) {
public void dump(@NonNull PrintWriter pw, String prefix) {
final String innerPrefix = " ";
pw.println();
pw.println(TAG);

View File

@@ -20,7 +20,6 @@ import android.graphics.Rect;
import com.android.wm.shell.common.annotations.ExternalThread;
import java.io.PrintWriter;
import java.util.function.Consumer;
/**
@@ -99,12 +98,4 @@ public interface Pip {
* view hierarchy or destroyed.
*/
default void removePipExclusionBoundsChangeListener(Consumer<Rect> listener) { }
/**
* Dump the current state and information if need.
*
* @param pw The stream to dump information to.
*/
default void dump(PrintWriter pw) {
}
}

View File

@@ -89,6 +89,7 @@ import com.android.wm.shell.pip.PipUtils;
import com.android.wm.shell.protolog.ShellProtoLogGroup;
import com.android.wm.shell.sysui.ConfigurationChangeListener;
import com.android.wm.shell.sysui.KeyguardChangeListener;
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.transition.Transitions;
@@ -123,6 +124,7 @@ public class PipController implements PipTransitionController.PipTransitionCallb
private TaskStackListenerImpl mTaskStackListener;
private PipParamsChangedForwarder mPipParamsChangedForwarder;
private Optional<OneHandedController> mOneHandedController;
private final ShellCommandHandler mShellCommandHandler;
private final ShellController mShellController;
protected final PipImpl mImpl;
@@ -297,6 +299,7 @@ public class PipController implements PipTransitionController.PipTransitionCallb
@Nullable
public static Pip create(Context context,
ShellInit shellInit,
ShellCommandHandler shellCommandHandler,
ShellController shellController,
DisplayController displayController,
PipAppOpsListener pipAppOpsListener,
@@ -321,10 +324,10 @@ public class PipController implements PipTransitionController.PipTransitionCallb
return null;
}
return new PipController(context, shellInit, shellController, displayController,
pipAppOpsListener, pipBoundsAlgorithm, pipKeepClearAlgorithm, pipBoundsState,
pipMotionHelper, pipMediaController, phonePipMenuController, pipTaskOrganizer,
pipTransitionState, pipTouchHandler, pipTransitionController,
return new PipController(context, shellInit, shellCommandHandler, shellController,
displayController, pipAppOpsListener, pipBoundsAlgorithm, pipKeepClearAlgorithm,
pipBoundsState, pipMotionHelper, pipMediaController, phonePipMenuController,
pipTaskOrganizer, pipTransitionState, pipTouchHandler, pipTransitionController,
windowManagerShellWrapper, taskStackListener, pipParamsChangedForwarder,
oneHandedController, mainExecutor)
.mImpl;
@@ -332,6 +335,7 @@ public class PipController implements PipTransitionController.PipTransitionCallb
protected PipController(Context context,
ShellInit shellInit,
ShellCommandHandler shellCommandHandler,
ShellController shellController,
DisplayController displayController,
PipAppOpsListener pipAppOpsListener,
@@ -358,6 +362,7 @@ public class PipController implements PipTransitionController.PipTransitionCallb
}
mContext = context;
mShellCommandHandler = shellCommandHandler;
mShellController = shellController;
mImpl = new PipImpl();
mWindowManagerShellWrapper = windowManagerShellWrapper;
@@ -385,6 +390,7 @@ public class PipController implements PipTransitionController.PipTransitionCallb
}
private void onInit() {
mShellCommandHandler.addDumpCallback(this::dump, this);
mPipInputConsumer = new PipInputConsumer(WindowManagerGlobal.getWindowManagerService(),
INPUT_CONSUMER_PIP, mMainExecutor);
mPipTransitionController.registerPipTransitionCallback(this);
@@ -914,7 +920,7 @@ public class PipController implements PipTransitionController.PipTransitionCallb
return true;
}
private void dump(PrintWriter pw) {
private void dump(PrintWriter pw, String prefix) {
final String innerPrefix = " ";
pw.println(TAG);
mMenuController.dump(pw, innerPrefix);
@@ -1002,18 +1008,6 @@ public class PipController implements PipTransitionController.PipTransitionCallb
PipController.this.showPictureInPictureMenu();
});
}
@Override
public void dump(PrintWriter pw) {
try {
mMainExecutor.executeBlocking(() -> {
PipController.this.dump(pw);
});
} catch (InterruptedException e) {
ProtoLog.e(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
"%s: Failed to dump PipController in 2s", TAG);
}
}
}
/**

View File

@@ -44,6 +44,7 @@ import com.android.wm.shell.common.TaskStackListenerImpl;
import com.android.wm.shell.common.annotations.ExternalThread;
import com.android.wm.shell.common.annotations.ShellMainThread;
import com.android.wm.shell.protolog.ShellProtoLogGroup;
import com.android.wm.shell.sysui.ShellCommandHandler;
import com.android.wm.shell.sysui.ShellInit;
import com.android.wm.shell.util.GroupedRecentTaskInfo;
import com.android.wm.shell.util.SplitBounds;
@@ -62,6 +63,7 @@ public class RecentTasksController implements TaskStackListenerCallback,
private static final String TAG = RecentTasksController.class.getSimpleName();
private final Context mContext;
private final ShellCommandHandler mShellCommandHandler;
private final ShellExecutor mMainExecutor;
private final TaskStackListenerImpl mTaskStackListener;
private final RecentTasks mImpl = new RecentTasksImpl();
@@ -87,20 +89,24 @@ public class RecentTasksController implements TaskStackListenerCallback,
public static RecentTasksController create(
Context context,
ShellInit shellInit,
ShellCommandHandler shellCommandHandler,
TaskStackListenerImpl taskStackListener,
@ShellMainThread ShellExecutor mainExecutor
) {
if (!context.getResources().getBoolean(com.android.internal.R.bool.config_hasRecents)) {
return null;
}
return new RecentTasksController(context, shellInit, taskStackListener, mainExecutor);
return new RecentTasksController(context, shellInit, shellCommandHandler, taskStackListener,
mainExecutor);
}
RecentTasksController(Context context,
ShellInit shellInit,
ShellCommandHandler shellCommandHandler,
TaskStackListenerImpl taskStackListener,
ShellExecutor mainExecutor) {
mContext = context;
mShellCommandHandler = shellCommandHandler;
mIsDesktopMode = mContext.getPackageManager().hasSystemFeature(FEATURE_PC);
mTaskStackListener = taskStackListener;
mMainExecutor = mainExecutor;
@@ -112,6 +118,7 @@ public class RecentTasksController implements TaskStackListenerCallback,
}
private void onInit() {
mShellCommandHandler.addDumpCallback(this::dump, this);
mTaskStackListener.addListener(this);
}

View File

@@ -83,6 +83,7 @@ import com.android.wm.shell.protolog.ShellProtoLogGroup;
import com.android.wm.shell.recents.RecentTasksController;
import com.android.wm.shell.splitscreen.SplitScreen.StageType;
import com.android.wm.shell.sysui.KeyguardChangeListener;
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.transition.Transitions;
@@ -131,6 +132,7 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
@Retention(RetentionPolicy.SOURCE)
@interface ExitReason{}
private final ShellCommandHandler mShellCommandHandler;
private final ShellController mShellController;
private final ShellTaskOrganizer mTaskOrganizer;
private final SyncTransactionQueue mSyncQueue;
@@ -147,6 +149,7 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
private final SplitscreenEventLogger mLogger;
private final IconProvider mIconProvider;
private final Optional<RecentTasksController> mRecentTasksOptional;
private final SplitScreenShellCommandHandler mSplitScreenShellCommandHandler;
private StageCoordinator mStageCoordinator;
// Only used for the legacy recents animation from splitscreen to allow the tasks to be animated
@@ -155,6 +158,7 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
public SplitScreenController(Context context,
ShellInit shellInit,
ShellCommandHandler shellCommandHandler,
ShellController shellController,
ShellTaskOrganizer shellTaskOrganizer,
SyncTransactionQueue syncQueue,
@@ -168,6 +172,7 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
IconProvider iconProvider,
Optional<RecentTasksController> recentTasks,
ShellExecutor mainExecutor) {
mShellCommandHandler = shellCommandHandler;
mShellController = shellController;
mTaskOrganizer = shellTaskOrganizer;
mSyncQueue = syncQueue;
@@ -183,6 +188,7 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
mLogger = new SplitscreenEventLogger();
mIconProvider = iconProvider;
mRecentTasksOptional = recentTasks;
mSplitScreenShellCommandHandler = new SplitScreenShellCommandHandler(this);
// TODO(b/238217847): Temporarily add this check here until we can remove the dynamic
// override for this controller from the base module
if (ActivityTaskManager.supportsSplitScreenMultiWindow(context)) {
@@ -200,6 +206,9 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
*/
@VisibleForTesting
void onInit() {
mShellCommandHandler.addDumpCallback(this::dump, this);
mShellCommandHandler.addCommandCallback("splitscreen", mSplitScreenShellCommandHandler,
this);
mShellController.addKeyguardChangeListener(this);
if (mStageCoordinator == null) {
// TODO: Multi-display

View File

@@ -0,0 +1,96 @@
/*
* Copyright (C) 2022 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.splitscreen;
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT;
import com.android.wm.shell.sysui.ShellCommandHandler;
import java.io.PrintWriter;
/**
* Handles the shell commands for the SplitscreenController.
*/
public class SplitScreenShellCommandHandler implements
ShellCommandHandler.ShellCommandActionHandler {
private final SplitScreenController mController;
public SplitScreenShellCommandHandler(SplitScreenController controller) {
mController = controller;
}
@Override
public boolean onShellCommand(String[] args, PrintWriter pw) {
switch (args[0]) {
case "moveToSideStage":
return runMoveToSideStage(args, pw);
case "removeFromSideStage":
return runRemoveFromSideStage(args, pw);
case "setSideStagePosition":
return runSetSideStagePosition(args, pw);
default:
pw.println("Invalid command: " + args[0]);
return false;
}
}
private boolean runMoveToSideStage(String[] args, PrintWriter pw) {
if (args.length < 3) {
// First argument is the action name.
pw.println("Error: task id should be provided as arguments");
return false;
}
final int taskId = new Integer(args[1]);
final int sideStagePosition = args.length > 3
? new Integer(args[2]) : SPLIT_POSITION_BOTTOM_OR_RIGHT;
mController.moveToSideStage(taskId, sideStagePosition);
return true;
}
private boolean runRemoveFromSideStage(String[] args, PrintWriter pw) {
if (args.length < 2) {
// First argument is the action name.
pw.println("Error: task id should be provided as arguments");
return false;
}
final int taskId = new Integer(args[1]);
mController.removeFromSideStage(taskId);
return true;
}
private boolean runSetSideStagePosition(String[] args, PrintWriter pw) {
if (args.length < 2) {
// First argument is the action name.
pw.println("Error: side stage position should be provided as arguments");
return false;
}
final int position = new Integer(args[1]);
mController.setSideStagePosition(position);
return true;
}
@Override
public void printShellCommandHelp(PrintWriter pw, String prefix) {
pw.println(prefix + "moveToSideStage <taskId> <SideStagePosition>");
pw.println(prefix + " Move a task with given id in split-screen mode.");
pw.println(prefix + "removeFromSideStage <taskId>");
pw.println(prefix + " Remove a task with given id in split-screen mode.");
pw.println(prefix + "setSideStagePosition <SideStagePosition>");
pw.println(prefix + " Sets the position of the side-stage.");
}
}

View File

@@ -16,19 +16,14 @@
package com.android.wm.shell.sysui;
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT;
import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_INIT;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.hidedisplaycutout.HideDisplayCutoutController;
import com.android.wm.shell.kidsmode.KidsModeTaskOrganizer;
import com.android.wm.shell.onehanded.OneHandedController;
import com.android.wm.shell.pip.Pip;
import com.android.wm.shell.recents.RecentTasksController;
import com.android.wm.shell.splitscreen.SplitScreenController;
import com.android.internal.protolog.common.ProtoLog;
import java.io.PrintWriter;
import java.util.Optional;
import java.util.Arrays;
import java.util.TreeMap;
import java.util.function.BiConsumer;
/**
* An entry point into the shell for dumping shell internal state and running adb commands.
@@ -38,52 +33,61 @@ import java.util.Optional;
public final class ShellCommandHandler {
private static final String TAG = ShellCommandHandler.class.getSimpleName();
private final Optional<SplitScreenController> mSplitScreenOptional;
private final Optional<Pip> mPipOptional;
private final Optional<OneHandedController> mOneHandedOptional;
private final Optional<HideDisplayCutoutController> mHideDisplayCutout;
private final Optional<RecentTasksController> mRecentTasks;
private final ShellTaskOrganizer mShellTaskOrganizer;
private final KidsModeTaskOrganizer mKidsModeTaskOrganizer;
// We're using a TreeMap to keep them sorted by command name
private final TreeMap<String, BiConsumer<PrintWriter, String>> mDumpables = new TreeMap<>();
private final TreeMap<String, ShellCommandActionHandler> mCommands = new TreeMap<>();
public ShellCommandHandler(
ShellController shellController,
ShellTaskOrganizer shellTaskOrganizer,
KidsModeTaskOrganizer kidsModeTaskOrganizer,
Optional<SplitScreenController> splitScreenOptional,
Optional<Pip> pipOptional,
Optional<OneHandedController> oneHandedOptional,
Optional<HideDisplayCutoutController> hideDisplayCutout,
Optional<RecentTasksController> recentTasks,
ShellExecutor mainExecutor) {
mShellTaskOrganizer = shellTaskOrganizer;
mKidsModeTaskOrganizer = kidsModeTaskOrganizer;
mRecentTasks = recentTasks;
mSplitScreenOptional = splitScreenOptional;
mPipOptional = pipOptional;
mOneHandedOptional = oneHandedOptional;
mHideDisplayCutout = hideDisplayCutout;
// TODO(238217847): To be removed once the command handler dependencies are inverted
shellController.setShellCommandHandler(this);
public interface ShellCommandActionHandler {
/**
* Handles the given command.
*
* @param args the arguments starting with the action name, then the action arguments
* @param pw the write to print output to
*/
boolean onShellCommand(String[] args, PrintWriter pw);
/**
* Prints the help for this class of commands. Implementations do not need to print the
* command class.
*/
void printShellCommandHelp(PrintWriter pw, String prefix);
}
/**
* Adds a callback to run when the Shell is being dumped.
*
* @param callback the callback to be made when Shell is dumped, takes the print writer and
* a prefix
* @param instance used for debugging only
*/
public <T> void addDumpCallback(BiConsumer<PrintWriter, String> callback, T instance) {
mDumpables.put(instance.getClass().getSimpleName(), callback);
ProtoLog.v(WM_SHELL_INIT, "Adding dump callback for %s",
instance.getClass().getSimpleName());
}
/**
* Adds an action callback to be invoked when the user runs that particular command from adb.
*
* @param commandClass the top level class of command to invoke
* @param actions the interface to callback when an action of this class is invoked
* @param instance used for debugging only
*/
public <T> void addCommandCallback(String commandClass, ShellCommandActionHandler actions,
T instance) {
mCommands.put(commandClass, actions);
ProtoLog.v(WM_SHELL_INIT, "Adding command class %s for %s", commandClass,
instance.getClass().getSimpleName());
}
/** Dumps WM Shell internal state. */
public void dump(PrintWriter pw) {
mShellTaskOrganizer.dump(pw, "");
pw.println();
pw.println();
mPipOptional.ifPresent(pip -> pip.dump(pw));
mOneHandedOptional.ifPresent(oneHanded -> oneHanded.dump(pw));
mHideDisplayCutout.ifPresent(hideDisplayCutout -> hideDisplayCutout.dump(pw));
pw.println();
pw.println();
mSplitScreenOptional.ifPresent(splitScreen -> splitScreen.dump(pw, ""));
pw.println();
pw.println();
mRecentTasks.ifPresent(recentTasks -> recentTasks.dump(pw, ""));
pw.println();
pw.println();
mKidsModeTaskOrganizer.dump(pw, "");
for (String key : mDumpables.keySet()) {
final BiConsumer<PrintWriter, String> r = mDumpables.get(key);
r.accept(pw, "");
pw.println();
}
}
@@ -93,72 +97,32 @@ public final class ShellCommandHandler {
// Argument at position 0 is "WMShell".
return false;
}
switch (args[1]) {
case "moveToSideStage":
return runMoveToSideStage(args, pw);
case "removeFromSideStage":
return runRemoveFromSideStage(args, pw);
case "setSideStagePosition":
return runSetSideStagePosition(args, pw);
case "help":
return runHelp(pw);
default:
return false;
}
}
private boolean runMoveToSideStage(String[] args, PrintWriter pw) {
if (args.length < 3) {
// First arguments are "WMShell" and command name.
pw.println("Error: task id should be provided as arguments");
final String cmdClass = args[1];
if (cmdClass.toLowerCase().equals("help")) {
return runHelp(pw);
}
if (!mCommands.containsKey(cmdClass)) {
return false;
}
final int taskId = new Integer(args[2]);
final int sideStagePosition = args.length > 3
? new Integer(args[3]) : SPLIT_POSITION_BOTTOM_OR_RIGHT;
mSplitScreenOptional.ifPresent(split -> split.moveToSideStage(taskId, sideStagePosition));
return true;
}
private boolean runRemoveFromSideStage(String[] args, PrintWriter pw) {
if (args.length < 3) {
// First arguments are "WMShell" and command name.
pw.println("Error: task id should be provided as arguments");
return false;
}
final int taskId = new Integer(args[2]);
mSplitScreenOptional.ifPresent(split -> split.removeFromSideStage(taskId));
return true;
}
private boolean runSetSideStagePosition(String[] args, PrintWriter pw) {
if (args.length < 3) {
// First arguments are "WMShell" and command name.
pw.println("Error: side stage position should be provided as arguments");
return false;
}
final int position = new Integer(args[2]);
mSplitScreenOptional.ifPresent(split -> split.setSideStagePosition(position));
// Only pass the actions onwards as arguments to the callback
final ShellCommandActionHandler actions = mCommands.get(args[1]);
final String[] cmdClassArgs = Arrays.copyOfRange(args, 2, args.length);
actions.onShellCommand(cmdClassArgs, pw);
return true;
}
private boolean runHelp(PrintWriter pw) {
pw.println("Window Manager Shell commands:");
for (String commandClass : mCommands.keySet()) {
pw.println(" " + commandClass);
mCommands.get(commandClass).printShellCommandHelp(pw, " ");
}
pw.println(" help");
pw.println(" Print this help text.");
pw.println(" <no arguments provided>");
pw.println(" Dump Window Manager Shell internal state");
pw.println(" pair <taskId1> <taskId2>");
pw.println(" unpair <taskId>");
pw.println(" Pairs/unpairs tasks with given ids.");
pw.println(" moveToSideStage <taskId> <SideStagePosition>");
pw.println(" Move a task with given id in split-screen mode.");
pw.println(" removeFromSideStage <taskId>");
pw.println(" Remove a task with given id in split-screen mode.");
pw.println(" setSideStageOutline <true/false>");
pw.println(" Enable/Disable outline on the side-stage.");
pw.println(" setSideStagePosition <SideStagePosition>");
pw.println(" Sets the position of the side-stage.");
pw.println(" Dump all Window Manager Shell internal state");
return true;
}
}

View File

@@ -45,11 +45,10 @@ public class ShellController {
private static final String TAG = ShellController.class.getSimpleName();
private final ShellInit mShellInit;
private final ShellCommandHandler mShellCommandHandler;
private final ShellExecutor mMainExecutor;
private final ShellInterfaceImpl mImpl = new ShellInterfaceImpl();
private ShellCommandHandler mShellCommandHandler;
private final CopyOnWriteArrayList<ConfigurationChangeListener> mConfigChangeListeners =
new CopyOnWriteArrayList<>();
private final CopyOnWriteArrayList<KeyguardChangeListener> mKeyguardChangeListeners =
@@ -57,8 +56,10 @@ public class ShellController {
private Configuration mLastConfiguration;
public ShellController(ShellInit shellInit, ShellExecutor mainExecutor) {
public ShellController(ShellInit shellInit, ShellCommandHandler shellCommandHandler,
ShellExecutor mainExecutor) {
mShellInit = shellInit;
mShellCommandHandler = shellCommandHandler;
mMainExecutor = mainExecutor;
}
@@ -69,15 +70,6 @@ public class ShellController {
return mImpl;
}
/**
* Sets the command handler to call back to.
* TODO(238217847): This is only exposed this way until we can remove the dependencies from the
* command handler to other classes.
*/
public void setShellCommandHandler(ShellCommandHandler shellCommandHandler) {
mShellCommandHandler = shellCommandHandler;
}
/**
* Adds a new configuration listener. The configuration change callbacks are not made in any
* particular order.

View File

@@ -59,6 +59,7 @@ import androidx.test.filters.SmallTest;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.compatui.CompatUIController;
import com.android.wm.shell.sysui.ShellCommandHandler;
import com.android.wm.shell.sysui.ShellInit;
import org.junit.Before;
@@ -85,10 +86,12 @@ public class ShellTaskOrganizerTests extends ShellTestCase {
@Mock
private CompatUIController mCompatUI;
@Mock
private ShellInit mShellInit;
private ShellExecutor mTestExecutor;
@Mock
private ShellCommandHandler mShellCommandHandler;
ShellTaskOrganizer mOrganizer;
private final ShellExecutor mTestExecutor = mock(ShellExecutor.class);
private ShellTaskOrganizer mOrganizer;
private ShellInit mShellInit;
private class TrackingTaskListener implements ShellTaskOrganizer.TaskListener {
final ArrayList<RunningTaskInfo> appeared = new ArrayList<>();
@@ -132,8 +135,11 @@ public class ShellTaskOrganizerTests extends ShellTestCase {
doReturn(ParceledListSlice.<TaskAppearedInfo>emptyList())
.when(mTaskOrganizerController).registerTaskOrganizer(any());
} catch (RemoteException e) {}
mOrganizer = spy(new ShellTaskOrganizer(mShellInit, mTaskOrganizerController,
mCompatUI, Optional.empty(), Optional.empty(), mTestExecutor));
mShellInit = spy(new ShellInit(mTestExecutor));
mOrganizer = spy(new ShellTaskOrganizer(mShellInit, mShellCommandHandler,
mTaskOrganizerController, mCompatUI, Optional.empty(), Optional.empty(),
mTestExecutor));
mShellInit.init();
}
@Test
@@ -142,9 +148,12 @@ public class ShellTaskOrganizerTests extends ShellTestCase {
}
@Test
public void testRegisterOrganizer_sendRegisterTaskOrganizer() throws RemoteException {
mOrganizer.registerOrganizer();
public void instantiate_addDumpCallback() {
verify(mShellCommandHandler, times(1)).addDumpCallback(any(), any());
}
@Test
public void testInit_sendRegisterTaskOrganizer() throws RemoteException {
verify(mTaskOrganizerController).registerTaskOrganizer(any(ITaskOrganizer.class));
}

View File

@@ -32,6 +32,7 @@ import androidx.test.platform.app.InstrumentationRegistry;
import com.android.wm.shell.ShellTestCase;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.sysui.ShellCommandHandler;
import com.android.wm.shell.sysui.ShellController;
import com.android.wm.shell.sysui.ShellInit;
@@ -48,6 +49,8 @@ public class HideDisplayCutoutControllerTest extends ShellTestCase {
private TestableContext mContext = new TestableContext(
InstrumentationRegistry.getInstrumentation().getTargetContext(), null);
@Mock
private ShellCommandHandler mShellCommandHandler;
@Mock
private ShellController mShellController;
@Mock
@@ -60,8 +63,8 @@ public class HideDisplayCutoutControllerTest extends ShellTestCase {
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
mShellInit = spy(new ShellInit(mock(ShellExecutor.class)));
mHideDisplayCutoutController = new HideDisplayCutoutController(
mContext, mShellInit, mShellController, mMockDisplayAreaOrganizer);
mHideDisplayCutoutController = new HideDisplayCutoutController(mContext, mShellInit,
mShellCommandHandler, mShellController, mMockDisplayAreaOrganizer);
mShellInit.init();
}
@@ -70,6 +73,11 @@ public class HideDisplayCutoutControllerTest extends ShellTestCase {
verify(mShellInit, times(1)).addInitCallback(any(), any());
}
@Test
public void instantiateController_registerDumpCallback() {
verify(mShellCommandHandler, times(1)).addDumpCallback(any(), any());
}
@Test
public void instantiateController_registerConfigChangeListener() {
verify(mShellController, times(1)).addConfigurationChangeListener(any());

View File

@@ -49,6 +49,7 @@ import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.DisplayInsetsController;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.sysui.ShellCommandHandler;
import com.android.wm.shell.sysui.ShellInit;
import org.junit.Before;
@@ -74,6 +75,7 @@ public class KidsModeTaskOrganizerTest extends ShellTestCase {
@Mock private WindowContainerTransaction mTransaction;
@Mock private KidsModeSettingsObserver mObserver;
@Mock private ShellInit mShellInit;
@Mock private ShellCommandHandler mShellCommandHandler;
@Mock private DisplayInsetsController mDisplayInsetsController;
KidsModeTaskOrganizer mOrganizer;
@@ -87,13 +89,19 @@ public class KidsModeTaskOrganizerTest extends ShellTestCase {
} catch (RemoteException e) {
}
// NOTE: KidsModeTaskOrganizer should have a null CompatUIController.
mOrganizer = spy(new KidsModeTaskOrganizer(mContext, mTaskOrganizerController,
mSyncTransactionQueue, mDisplayController, mDisplayInsetsController,
Optional.empty(), Optional.empty(), mObserver, mTestExecutor, mHandler));
mOrganizer = spy(new KidsModeTaskOrganizer(mContext, mShellInit, mShellCommandHandler,
mTaskOrganizerController, mSyncTransactionQueue, mDisplayController,
mDisplayInsetsController, Optional.empty(), Optional.empty(), mObserver,
mTestExecutor, mHandler));
doReturn(mTransaction).when(mOrganizer).getWindowContainerTransaction();
doReturn(new InsetsState()).when(mDisplayController).getInsetsState(DEFAULT_DISPLAY);
}
@Test
public void instantiateController_addInitCallback() {
verify(mShellInit, times(1)).addInitCallback(any(), any());
}
@Test
public void testKidsModeOn() {
doReturn(true).when(mObserver).isEnabled();

View File

@@ -48,6 +48,7 @@ import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.DisplayLayout;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.TaskStackListenerImpl;
import com.android.wm.shell.sysui.ShellCommandHandler;
import com.android.wm.shell.sysui.ShellController;
import com.android.wm.shell.sysui.ShellInit;
@@ -69,6 +70,8 @@ public class OneHandedControllerTest extends OneHandedTestCase {
OneHandedState mSpiedTransitionState;
ShellInit mShellInit;
@Mock
ShellCommandHandler mMockShellCommandHandler;
@Mock
ShellController mMockShellController;
@Mock
@@ -129,6 +132,7 @@ public class OneHandedControllerTest extends OneHandedTestCase {
mSpiedOneHandedController = spy(new OneHandedController(
mContext,
mShellInit,
mMockShellCommandHandler,
mMockShellController,
mMockDisplayController,
mMockDisplayAreaOrganizer,
@@ -151,6 +155,11 @@ public class OneHandedControllerTest extends OneHandedTestCase {
verify(mShellInit, times(1)).addInitCallback(any(), any());
}
@Test
public void instantiateController_registerDumpCallback() {
verify(mMockShellCommandHandler, times(1)).addDumpCallback(any(), any());
}
@Test
public void testControllerRegistersConfigChangeListener() {
verify(mMockShellController, times(1)).addConfigurationChangeListener(any());

View File

@@ -41,6 +41,7 @@ import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.DisplayLayout;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.TaskStackListenerImpl;
import com.android.wm.shell.sysui.ShellCommandHandler;
import com.android.wm.shell.sysui.ShellController;
import com.android.wm.shell.sysui.ShellInit;
@@ -64,6 +65,8 @@ public class OneHandedStateTest extends OneHandedTestCase {
@Mock
ShellInit mMockShellInit;
@Mock
ShellCommandHandler mMockShellCommandHandler;
@Mock
ShellController mMockShellController;
@Mock
DisplayController mMockDisplayController;
@@ -115,6 +118,7 @@ public class OneHandedStateTest extends OneHandedTestCase {
mSpiedOneHandedController = spy(new OneHandedController(
mContext,
mMockShellInit,
mMockShellCommandHandler,
mMockShellController,
mMockDisplayController,
mMockDisplayAreaOrganizer,

View File

@@ -55,6 +55,7 @@ import com.android.wm.shell.pip.PipSnapAlgorithm;
import com.android.wm.shell.pip.PipTaskOrganizer;
import com.android.wm.shell.pip.PipTransitionController;
import com.android.wm.shell.pip.PipTransitionState;
import com.android.wm.shell.sysui.ShellCommandHandler;
import com.android.wm.shell.sysui.ShellController;
import com.android.wm.shell.sysui.ShellInit;
@@ -77,6 +78,7 @@ public class PipControllerTest extends ShellTestCase {
private PipController mPipController;
private ShellInit mShellInit;
@Mock private ShellCommandHandler mMockShellCommandHandler;
@Mock private ShellController mMockShellController;
@Mock private DisplayController mMockDisplayController;
@Mock private PhonePipMenuController mMockPhonePipMenuController;
@@ -108,9 +110,9 @@ public class PipControllerTest extends ShellTestCase {
return null;
}).when(mMockExecutor).execute(any());
mShellInit = spy(new ShellInit(mMockExecutor));
mPipController = new PipController(mContext, mShellInit, mMockShellController,
mMockDisplayController, mMockPipAppOpsListener, mMockPipBoundsAlgorithm,
mMockPipKeepClearAlgorithm,
mPipController = new PipController(mContext, mShellInit, mMockShellCommandHandler,
mMockShellController, mMockDisplayController, mMockPipAppOpsListener,
mMockPipBoundsAlgorithm, mMockPipKeepClearAlgorithm,
mMockPipBoundsState, mMockPipMotionHelper, mMockPipMediaController,
mMockPhonePipMenuController, mMockPipTaskOrganizer, mMockPipTransitionState,
mMockPipTouchHandler, mMockPipTransitionController, mMockWindowManagerShellWrapper,
@@ -126,6 +128,11 @@ public class PipControllerTest extends ShellTestCase {
verify(mShellInit, times(1)).addInitCallback(any(), any());
}
@Test
public void instantiateController_registerDumpCallback() {
verify(mMockShellCommandHandler, times(1)).addDumpCallback(any(), any());
}
@Test
public void instantiatePipController_registerConfigChangeListener() {
verify(mMockShellController, times(1)).addConfigurationChangeListener(any());
@@ -159,9 +166,9 @@ public class PipControllerTest extends ShellTestCase {
when(spyContext.getPackageManager()).thenReturn(mockPackageManager);
ShellInit shellInit = new ShellInit(mMockExecutor);
assertNull(PipController.create(spyContext, shellInit, mMockShellController,
mMockDisplayController, mMockPipAppOpsListener, mMockPipBoundsAlgorithm,
mMockPipKeepClearAlgorithm,
assertNull(PipController.create(spyContext, shellInit, mMockShellCommandHandler,
mMockShellController, mMockDisplayController, mMockPipAppOpsListener,
mMockPipBoundsAlgorithm, mMockPipKeepClearAlgorithm,
mMockPipBoundsState, mMockPipMotionHelper, mMockPipMediaController,
mMockPhonePipMenuController, mMockPipTaskOrganizer, mMockPipTransitionState,
mMockPipTouchHandler, mMockPipTransitionController, mMockWindowManagerShellWrapper,

View File

@@ -23,7 +23,9 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.isA;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.reset;
@@ -48,6 +50,7 @@ import com.android.wm.shell.ShellTestCase;
import com.android.wm.shell.TestShellExecutor;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.TaskStackListenerImpl;
import com.android.wm.shell.sysui.ShellCommandHandler;
import com.android.wm.shell.sysui.ShellInit;
import com.android.wm.shell.util.GroupedRecentTaskInfo;
import com.android.wm.shell.util.SplitBounds;
@@ -73,21 +76,35 @@ public class RecentTasksControllerTest extends ShellTestCase {
@Mock
private TaskStackListenerImpl mTaskStackListener;
@Mock
private ShellInit mShellInit;
private ShellCommandHandler mShellCommandHandler;
private ShellTaskOrganizer mShellTaskOrganizer;
private RecentTasksController mRecentTasksController;
private ShellInit mShellInit;
private ShellExecutor mMainExecutor;
@Before
public void setUp() {
mMainExecutor = new TestShellExecutor();
when(mContext.getPackageManager()).thenReturn(mock(PackageManager.class));
mShellInit = spy(new ShellInit(mMainExecutor));
mRecentTasksController = spy(new RecentTasksController(mContext, mShellInit,
mTaskStackListener, mMainExecutor));
mShellTaskOrganizer = new ShellTaskOrganizer(mShellInit,
mShellCommandHandler, mTaskStackListener, mMainExecutor));
mShellTaskOrganizer = new ShellTaskOrganizer(mShellInit, mShellCommandHandler,
null /* sizeCompatUI */, Optional.empty(), Optional.of(mRecentTasksController),
mMainExecutor);
mShellInit.init();
}
@Test
public void instantiateController_addInitCallback() {
verify(mShellInit, times(1)).addInitCallback(any(), isA(RecentTasksController.class));
}
@Test
public void instantiateController_addDumpCallback() {
verify(mShellCommandHandler, times(1)).addDumpCallback(any(),
isA(RecentTasksController.class));
}
@Test

View File

@@ -26,6 +26,7 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
@@ -53,6 +54,7 @@ import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.common.TransactionPool;
import com.android.wm.shell.draganddrop.DragAndDropController;
import com.android.wm.shell.recents.RecentTasksController;
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.transition.Transitions;
@@ -72,8 +74,9 @@ import java.util.Optional;
@RunWith(AndroidJUnit4.class)
public class SplitScreenControllerTests extends ShellTestCase {
@Mock ShellController mShellController;
@Mock ShellInit mShellInit;
@Mock ShellController mShellController;
@Mock ShellCommandHandler mShellCommandHandler;
@Mock ShellTaskOrganizer mTaskOrganizer;
@Mock SyncTransactionQueue mSyncQueue;
@Mock RootTaskDisplayAreaOrganizer mRootTDAOrganizer;
@@ -93,9 +96,10 @@ public class SplitScreenControllerTests extends ShellTestCase {
public void setup() {
MockitoAnnotations.initMocks(this);
mSplitScreenController = spy(new SplitScreenController(mContext, mShellInit,
mShellController, mTaskOrganizer, mSyncQueue, mRootTDAOrganizer, mDisplayController,
mDisplayImeController, mDisplayInsetsController, mDragAndDropController,
mTransitions, mTransactionPool, mIconProvider, mRecentTasks, mMainExecutor));
mShellCommandHandler, mShellController, mTaskOrganizer, mSyncQueue,
mRootTDAOrganizer, mDisplayController, mDisplayImeController,
mDisplayInsetsController, mDragAndDropController, mTransitions, mTransactionPool,
mIconProvider, mRecentTasks, mMainExecutor));
}
@Test
@@ -103,8 +107,25 @@ public class SplitScreenControllerTests extends ShellTestCase {
verify(mShellInit, times(1)).addInitCallback(any(), any());
}
@Test
public void instantiateController_registerDumpCallback() {
doReturn(mMainExecutor).when(mTaskOrganizer).getExecutor();
when(mDisplayController.getDisplayLayout(anyInt())).thenReturn(new DisplayLayout());
mSplitScreenController.onInit();
verify(mShellCommandHandler, times(1)).addDumpCallback(any(), any());
}
@Test
public void instantiateController_registerCommandCallback() {
doReturn(mMainExecutor).when(mTaskOrganizer).getExecutor();
when(mDisplayController.getDisplayLayout(anyInt())).thenReturn(new DisplayLayout());
mSplitScreenController.onInit();
verify(mShellCommandHandler, times(1)).addCommandCallback(eq("splitscreen"), any(), any());
}
@Test
public void testControllerRegistersKeyguardChangeListener() {
doReturn(mMainExecutor).when(mTaskOrganizer).getExecutor();
when(mDisplayController.getDisplayLayout(anyInt())).thenReturn(new DisplayLayout());
mSplitScreenController.onInit();
verify(mShellController, times(1)).addKeyguardChangeListener(any());

View File

@@ -45,6 +45,8 @@ public class ShellControllerTest extends ShellTestCase {
@Mock
private ShellInit mShellInit;
@Mock
private ShellCommandHandler mShellCommandHandler;
@Mock
private ShellExecutor mExecutor;
private ShellController mController;
@@ -56,7 +58,7 @@ public class ShellControllerTest extends ShellTestCase {
MockitoAnnotations.initMocks(this);
mKeyguardChangeListener = new TestKeyguardChangeListener();
mConfigChangeListener = new TestConfigurationChangeListener();
mController = new ShellController(mShellInit, mExecutor);
mController = new ShellController(mShellInit, mShellCommandHandler, mExecutor);
mController.onConfigurationChanged(getConfigurationCopy());
}