Add single interface for SysUI to call into Shell

- Currently update configuration callbacks to use this interface
  so that individual features don't need to expose their own config
  change callbacks.  Will followup with moving keyguard/shell init
  /shell command handler.

Bug: 238217847
Test: atest WMShellUnitTests

Change-Id: Id526ed588de8cf962e821a3b9e1933a67f354d77
This commit is contained in:
Winson Chung
2022-07-13 17:26:23 +00:00
parent 28eb5d5f7c
commit b5ebf4bede
34 changed files with 738 additions and 278 deletions

View File

@@ -101,6 +101,8 @@ import com.android.wm.shell.draganddrop.DragAndDropController;
import com.android.wm.shell.onehanded.OneHandedController;
import com.android.wm.shell.onehanded.OneHandedTransitionCallback;
import com.android.wm.shell.pip.PinnedStackListenerForwarder;
import com.android.wm.shell.sysui.ConfigurationChangeListener;
import com.android.wm.shell.sysui.ShellController;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -119,7 +121,7 @@ import java.util.function.IntConsumer;
*
* The controller manages addition, removal, and visible state of bubbles on screen.
*/
public class BubbleController {
public class BubbleController implements ConfigurationChangeListener {
private static final String TAG = TAG_WITH_CLASS_NAME ? "BubbleController" : TAG_BUBBLES;
@@ -155,6 +157,7 @@ public class BubbleController {
private final DisplayController mDisplayController;
private final TaskViewTransitions mTaskViewTransitions;
private final SyncTransactionQueue mSyncQueue;
private final ShellController mShellController;
// Used to post to main UI thread
private final ShellExecutor mMainExecutor;
@@ -224,6 +227,7 @@ public class BubbleController {
public BubbleController(Context context,
ShellController shellController,
BubbleData data,
@Nullable BubbleStackView.SurfaceSynchronizer synchronizer,
FloatingContentCoordinator floatingContentCoordinator,
@@ -246,6 +250,7 @@ public class BubbleController {
TaskViewTransitions taskViewTransitions,
SyncTransactionQueue syncQueue) {
mContext = context;
mShellController = shellController;
mLauncherApps = launcherApps;
mBarService = statusBarService == null
? IStatusBarService.Stub.asInterface(
@@ -414,6 +419,8 @@ public class BubbleController {
// Clear out any persisted bubbles on disk that no longer have a valid user.
List<UserInfo> users = mUserManager.getAliveUsers();
mDataRepository.sanitizeBubbles(users);
mShellController.addConfigurationChangeListener(this);
}
@VisibleForTesting
@@ -798,7 +805,8 @@ public class BubbleController {
mSavedBubbleKeysPerUser.remove(userId);
}
private void updateForThemeChanges() {
@Override
public void onThemeChanged() {
if (mStackView != null) {
mStackView.onThemeChanged();
}
@@ -818,7 +826,8 @@ public class BubbleController {
}
}
private void onConfigChanged(Configuration newConfig) {
@Override
public void onConfigurationChanged(Configuration newConfig) {
if (mBubblePositioner != null) {
mBubblePositioner.update();
}
@@ -1677,13 +1686,6 @@ public class BubbleController {
});
}
@Override
public void updateForThemeChanges() {
mMainExecutor.execute(() -> {
BubbleController.this.updateForThemeChanges();
});
}
@Override
public void expandStackAndSelectBubble(BubbleEntry entry) {
mMainExecutor.execute(() -> {
@@ -1822,13 +1824,6 @@ public class BubbleController {
});
}
@Override
public void onConfigChanged(Configuration newConfig) {
mMainExecutor.execute(() -> {
BubbleController.this.onConfigChanged(newConfig);
});
}
@Override
public void onNotificationPanelExpandedChanged(boolean expanded) {
mMainExecutor.execute(

View File

@@ -107,9 +107,6 @@ public interface Bubbles {
/** Tell the stack of bubbles to collapse. */
void collapseStack();
/** Tell the controller need update its UI to fit theme. */
void updateForThemeChanges();
/**
* Request the stack expand if needed, then select the specified Bubble as current.
* If no bubble exists for this entry, one is created.
@@ -255,13 +252,6 @@ public interface Bubbles {
*/
void onUserRemoved(int removedUserId);
/**
* Called when config changed.
*
* @param newConfig the new config.
*/
void onConfigChanged(Configuration newConfig);
/** Description of current bubble state. */
void dump(PrintWriter pw, String[] args);

View File

@@ -48,6 +48,7 @@ import com.android.wm.shell.pip.tv.TvPipNotificationController;
import com.android.wm.shell.pip.tv.TvPipTaskOrganizer;
import com.android.wm.shell.pip.tv.TvPipTransition;
import com.android.wm.shell.splitscreen.SplitScreenController;
import com.android.wm.shell.sysui.ShellController;
import com.android.wm.shell.transition.Transitions;
import java.util.Optional;
@@ -64,6 +65,7 @@ public abstract class TvPipModule {
@Provides
static Optional<Pip> providePip(
Context context,
ShellController shellController,
TvPipBoundsState tvPipBoundsState,
TvPipBoundsAlgorithm tvPipBoundsAlgorithm,
TvPipBoundsController tvPipBoundsController,
@@ -81,6 +83,7 @@ public abstract class TvPipModule {
return Optional.of(
TvPipController.create(
context,
shellController,
tvPipBoundsState,
tvPipBoundsAlgorithm,
tvPipBoundsController,

View File

@@ -82,6 +82,8 @@ import com.android.wm.shell.startingsurface.StartingSurface;
import com.android.wm.shell.startingsurface.StartingWindowController;
import com.android.wm.shell.startingsurface.StartingWindowTypeAlgorithm;
import com.android.wm.shell.startingsurface.phone.PhoneStartingWindowTypeAlgorithm;
import com.android.wm.shell.sysui.ShellController;
import com.android.wm.shell.sysui.ShellInterface;
import com.android.wm.shell.tasksurfacehelper.TaskSurfaceHelper;
import com.android.wm.shell.tasksurfacehelper.TaskSurfaceHelperController;
import com.android.wm.shell.transition.ShellTransitions;
@@ -159,10 +161,13 @@ public abstract class WMShellBaseModule {
@WMSingleton
@Provides
static DragAndDropController provideDragAndDropController(Context context,
DisplayController displayController, UiEventLogger uiEventLogger,
IconProvider iconProvider, @ShellMainThread ShellExecutor mainExecutor) {
return new DragAndDropController(context, displayController, uiEventLogger, iconProvider,
mainExecutor);
ShellController shellController,
DisplayController displayController,
UiEventLogger uiEventLogger,
IconProvider iconProvider,
@ShellMainThread ShellExecutor mainExecutor) {
return new DragAndDropController(context, shellController, displayController, uiEventLogger,
iconProvider, mainExecutor);
}
@WMSingleton
@@ -377,9 +382,11 @@ public abstract class WMShellBaseModule {
@WMSingleton
@Provides
static Optional<HideDisplayCutoutController> provideHideDisplayCutoutController(Context context,
DisplayController displayController, @ShellMainThread ShellExecutor mainExecutor) {
ShellController shellController, DisplayController displayController,
@ShellMainThread ShellExecutor mainExecutor) {
return Optional.ofNullable(
HideDisplayCutoutController.create(context, displayController, mainExecutor));
HideDisplayCutoutController.create(context, shellController, displayController,
mainExecutor));
}
//
@@ -621,6 +628,22 @@ public abstract class WMShellBaseModule {
taskViewTransitions);
}
//
// SysUI -> Shell interface
//
@WMSingleton
@Provides
static ShellInterface provideShellSysuiCallbacks(ShellController shellController) {
return shellController.asShell();
}
@WMSingleton
@Provides
static ShellController provideShellController(@ShellMainThread ShellExecutor mainExecutor) {
return new ShellController(mainExecutor);
}
//
// Misc
//

View File

@@ -71,6 +71,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.ShellController;
import com.android.wm.shell.transition.Transitions;
import com.android.wm.shell.unfold.ShellUnfoldProgressProvider;
import com.android.wm.shell.unfold.UnfoldAnimationController;
@@ -134,6 +135,7 @@ public abstract class WMShellModule {
@WMSingleton
@Provides
static BubbleController provideBubbleController(Context context,
ShellController shellController,
BubbleData data,
FloatingContentCoordinator floatingContentCoordinator,
IStatusBarService statusBarService,
@@ -153,7 +155,7 @@ public abstract class WMShellModule {
@ShellBackgroundThread ShellExecutor bgExecutor,
TaskViewTransitions taskViewTransitions,
SyncTransactionQueue syncQueue) {
return new BubbleController(context, data, null /* synchronizer */,
return new BubbleController(context, shellController, data, null /* synchronizer */,
floatingContentCoordinator,
new BubbleDataRepository(context, launcherApps, mainExecutor),
statusBarService, windowManager, windowManagerShellWrapper, userManager,
@@ -205,12 +207,14 @@ public abstract class WMShellModule {
@Provides
@DynamicOverride
static OneHandedController provideOneHandedController(Context context,
ShellController shellController,
WindowManager windowManager, DisplayController displayController,
DisplayLayout displayLayout, TaskStackListenerImpl taskStackListener,
UiEventLogger uiEventLogger, InteractionJankMonitor jankMonitor,
@ShellMainThread ShellExecutor mainExecutor, @ShellMainThread Handler mainHandler) {
return OneHandedController.create(context, windowManager, displayController, displayLayout,
taskStackListener, jankMonitor, uiEventLogger, mainExecutor, mainHandler);
return OneHandedController.create(context, shellController, windowManager,
displayController, displayLayout, taskStackListener, jankMonitor, uiEventLogger,
mainExecutor, mainHandler);
}
//
@@ -242,7 +246,8 @@ public abstract class WMShellModule {
@WMSingleton
@Provides
static Optional<Pip> providePip(Context context, DisplayController displayController,
static Optional<Pip> providePip(Context context,
ShellController shellController, DisplayController displayController,
PipAppOpsListener pipAppOpsListener, PipBoundsAlgorithm pipBoundsAlgorithm,
PipKeepClearAlgorithm pipKeepClearAlgorithm, PipBoundsState pipBoundsState,
PipMotionHelper pipMotionHelper, PipMediaController pipMediaController,
@@ -254,7 +259,7 @@ public abstract class WMShellModule {
PipParamsChangedForwarder pipParamsChangedForwarder,
Optional<OneHandedController> oneHandedController,
@ShellMainThread ShellExecutor mainExecutor) {
return Optional.ofNullable(PipController.create(context, displayController,
return Optional.ofNullable(PipController.create(context, shellController, displayController,
pipAppOpsListener, pipBoundsAlgorithm, pipKeepClearAlgorithm, pipBoundsState,
pipMotionHelper,
pipMediaController, phonePipMenuController, pipTaskOrganizer, pipTransitionState,

View File

@@ -52,4 +52,14 @@ For example, you might have:
call, and the callback posts to the main SysUI thread
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.
necessary to maintain proper threading and logic isolation.
## Configuration changes & other SysUI events
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

View File

@@ -16,8 +16,6 @@
package com.android.wm.shell.draganddrop;
import android.content.res.Configuration;
import com.android.wm.shell.common.annotations.ExternalThread;
/**
@@ -25,10 +23,4 @@ import com.android.wm.shell.common.annotations.ExternalThread;
*/
@ExternalThread
public interface DragAndDrop {
/** Called when the theme changes. */
void onThemeChanged();
/** Called when the configuration changes. */
void onConfigChanged(Configuration newConfig);
}

View File

@@ -60,6 +60,8 @@ import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.protolog.ShellProtoLogGroup;
import com.android.wm.shell.splitscreen.SplitScreenController;
import com.android.wm.shell.sysui.ConfigurationChangeListener;
import com.android.wm.shell.sysui.ShellController;
import java.util.ArrayList;
import java.util.Optional;
@@ -68,11 +70,12 @@ import java.util.Optional;
* Handles the global drag and drop handling for the Shell.
*/
public class DragAndDropController implements DisplayController.OnDisplaysChangedListener,
View.OnDragListener {
View.OnDragListener, ConfigurationChangeListener {
private static final String TAG = DragAndDropController.class.getSimpleName();
private final Context mContext;
private final ShellController mShellController;
private final DisplayController mDisplayController;
private final DragAndDropEventLogger mLogger;
private final IconProvider mIconProvider;
@@ -92,9 +95,14 @@ public class DragAndDropController implements DisplayController.OnDisplaysChange
void onDragStarted();
}
public DragAndDropController(Context context, DisplayController displayController,
UiEventLogger uiEventLogger, IconProvider iconProvider, ShellExecutor mainExecutor) {
public DragAndDropController(Context context,
ShellController shellController,
DisplayController displayController,
UiEventLogger uiEventLogger,
IconProvider iconProvider,
ShellExecutor mainExecutor) {
mContext = context;
mShellController = shellController;
mDisplayController = displayController;
mLogger = new DragAndDropEventLogger(uiEventLogger);
mIconProvider = iconProvider;
@@ -109,6 +117,7 @@ public class DragAndDropController implements DisplayController.OnDisplaysChange
public void initialize(Optional<SplitScreenController> splitscreen) {
mSplitScreen = splitscreen.orElse(null);
mDisplayController.addDisplayWindowListener(this);
mShellController.addConfigurationChangeListener(this);
}
/** Adds a listener to be notified of drag and drop events. */
@@ -310,13 +319,15 @@ public class DragAndDropController implements DisplayController.OnDisplaysChange
return mimeTypes;
}
private void onThemeChange() {
@Override
public void onThemeChanged() {
for (int i = 0; i < mDisplayDropTargets.size(); i++) {
mDisplayDropTargets.get(i).dragLayout.onThemeChange();
}
}
private void onConfigChanged(Configuration newConfig) {
@Override
public void onConfigurationChanged(Configuration newConfig) {
for (int i = 0; i < mDisplayDropTargets.size(); i++) {
mDisplayDropTargets.get(i).dragLayout.onConfigChanged(newConfig);
}
@@ -344,19 +355,6 @@ public class DragAndDropController implements DisplayController.OnDisplaysChange
}
private class DragAndDropImpl implements DragAndDrop {
@Override
public void onThemeChanged() {
mMainExecutor.execute(() -> {
DragAndDropController.this.onThemeChange();
});
}
@Override
public void onConfigChanged(Configuration newConfig) {
mMainExecutor.execute(() -> {
DragAndDropController.this.onConfigChanged(newConfig);
});
}
// TODO: To be removed
}
}

View File

@@ -16,21 +16,11 @@
package com.android.wm.shell.hidedisplaycutout;
import android.content.res.Configuration;
import androidx.annotation.NonNull;
import com.android.wm.shell.common.annotations.ExternalThread;
import java.io.PrintWriter;
/**
* Interface to engage hide display cutout feature.
*/
@ExternalThread
public interface HideDisplayCutout {
/**
* Notifies {@link Configuration} changed.
*/
void onConfigurationChanged(Configuration newConfig);
}

View File

@@ -19,7 +19,6 @@ package com.android.wm.shell.hidedisplaycutout;
import android.content.Context;
import android.content.res.Configuration;
import android.os.SystemProperties;
import android.util.Slog;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -27,17 +26,19 @@ 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.ShellController;
import java.io.PrintWriter;
import java.util.concurrent.TimeUnit;
/**
* Manages the hide display cutout status.
*/
public class HideDisplayCutoutController {
public class HideDisplayCutoutController implements ConfigurationChangeListener {
private static final String TAG = "HideDisplayCutoutController";
private final Context mContext;
private final ShellController mShellController;
private final HideDisplayCutoutOrganizer mOrganizer;
private final ShellExecutor mMainExecutor;
private final HideDisplayCutoutImpl mImpl = new HideDisplayCutoutImpl();
@@ -49,8 +50,9 @@ public class HideDisplayCutoutController {
* supported.
*/
@Nullable
public static HideDisplayCutoutController create(
Context context, DisplayController displayController, ShellExecutor mainExecutor) {
public static HideDisplayCutoutController create(Context context,
ShellController shellController, DisplayController displayController,
ShellExecutor mainExecutor) {
// The SystemProperty is set for devices that support this feature and is used to control
// whether to create the HideDisplayCutout instance.
// It's defined in the device.mk (e.g. device/google/crosshatch/device.mk).
@@ -60,15 +62,17 @@ public class HideDisplayCutoutController {
HideDisplayCutoutOrganizer organizer =
new HideDisplayCutoutOrganizer(context, displayController, mainExecutor);
return new HideDisplayCutoutController(context, organizer, mainExecutor);
return new HideDisplayCutoutController(context, shellController, organizer, mainExecutor);
}
HideDisplayCutoutController(Context context, HideDisplayCutoutOrganizer organizer,
ShellExecutor mainExecutor) {
HideDisplayCutoutController(Context context, ShellController shellController,
HideDisplayCutoutOrganizer organizer, ShellExecutor mainExecutor) {
mContext = context;
mShellController = shellController;
mOrganizer = organizer;
mMainExecutor = mainExecutor;
updateStatus();
mShellController.addConfigurationChangeListener(this);
}
public HideDisplayCutout asHideDisplayCutout() {
@@ -94,7 +98,8 @@ public class HideDisplayCutoutController {
}
}
private void onConfigurationChanged(Configuration newConfig) {
@Override
public void onConfigurationChanged(Configuration newConfig) {
updateStatus();
}
@@ -109,11 +114,6 @@ public class HideDisplayCutoutController {
}
private class HideDisplayCutoutImpl implements HideDisplayCutout {
@Override
public void onConfigurationChanged(Configuration newConfig) {
mMainExecutor.execute(() -> {
HideDisplayCutoutController.this.onConfigurationChanged(newConfig);
});
}
// TODO: To be removed
}
}

View File

@@ -16,7 +16,6 @@
package com.android.wm.shell.onehanded;
import android.content.res.Configuration;
import android.os.SystemProperties;
import com.android.wm.shell.common.annotations.ExternalThread;
@@ -82,11 +81,6 @@ public interface OneHanded {
*/
void registerTransitionCallback(OneHandedTransitionCallback callback);
/**
* Receive onConfigurationChanged() events
*/
void onConfigChanged(Configuration newConfig);
/**
* Notifies when user switch complete
*/

View File

@@ -54,6 +54,8 @@ import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.TaskStackListenerCallback;
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.ShellController;
import java.io.PrintWriter;
@@ -61,7 +63,7 @@ import java.io.PrintWriter;
* Manages and manipulates the one handed states, transitions, and gesture for phones.
*/
public class OneHandedController implements RemoteCallable<OneHandedController>,
DisplayChangeController.OnDisplayChangingListener {
DisplayChangeController.OnDisplayChangingListener, ConfigurationChangeListener {
private static final String TAG = "OneHandedController";
private static final String ONE_HANDED_MODE_OFFSET_PERCENTAGE =
@@ -81,6 +83,7 @@ public class OneHandedController implements RemoteCallable<OneHandedController>,
private Context mContext;
private final ShellController mShellController;
private final AccessibilityManager mAccessibilityManager;
private final DisplayController mDisplayController;
private final OneHandedSettingsUtil mOneHandedSettingsUtil;
@@ -188,8 +191,9 @@ public class OneHandedController implements RemoteCallable<OneHandedController>,
* Creates {@link OneHandedController}, returns {@code null} if the feature is not supported.
*/
public static OneHandedController create(
Context context, WindowManager windowManager, DisplayController displayController,
DisplayLayout displayLayout, TaskStackListenerImpl taskStackListener,
Context context, ShellController shellController, WindowManager windowManager,
DisplayController displayController, DisplayLayout displayLayout,
TaskStackListenerImpl taskStackListener,
InteractionJankMonitor jankMonitor, UiEventLogger uiEventLogger,
ShellExecutor mainExecutor, Handler mainHandler) {
OneHandedSettingsUtil settingsUtil = new OneHandedSettingsUtil();
@@ -207,14 +211,15 @@ public class OneHandedController implements RemoteCallable<OneHandedController>,
context, displayLayout, settingsUtil, animationController, tutorialHandler,
jankMonitor, mainExecutor);
OneHandedUiEventLogger oneHandedUiEventsLogger = new OneHandedUiEventLogger(uiEventLogger);
return new OneHandedController(context, displayController, organizer, touchHandler,
tutorialHandler, settingsUtil, accessibilityUtil, timeoutHandler, oneHandedState,
oneHandedUiEventsLogger, taskStackListener,
return new OneHandedController(context, shellController, displayController, organizer,
touchHandler, tutorialHandler, settingsUtil, accessibilityUtil, timeoutHandler,
oneHandedState, oneHandedUiEventsLogger, taskStackListener,
mainExecutor, mainHandler);
}
@VisibleForTesting
OneHandedController(Context context,
ShellController shellController,
DisplayController displayController,
OneHandedDisplayAreaOrganizer displayAreaOrganizer,
OneHandedTouchHandler touchHandler,
@@ -228,6 +233,7 @@ public class OneHandedController implements RemoteCallable<OneHandedController>,
ShellExecutor mainExecutor,
Handler mainHandler) {
mContext = context;
mShellController = shellController;
mOneHandedSettingsUtil = settingsUtil;
mOneHandedAccessibilityUtil = oneHandedAccessibilityUtil;
mDisplayAreaOrganizer = displayAreaOrganizer;
@@ -272,6 +278,7 @@ public class OneHandedController implements RemoteCallable<OneHandedController>,
mAccessibilityStateChangeListener);
mState.addSListeners(mTutorialHandler);
mShellController.addConfigurationChangeListener(this);
}
public OneHanded asOneHanded() {
@@ -587,7 +594,8 @@ public class OneHandedController implements RemoteCallable<OneHandedController>,
mLockedDisabled = locked && !enabled;
}
private void onConfigChanged(Configuration newConfig) {
@Override
public void onConfigurationChanged(Configuration newConfig) {
if (mTutorialHandler == null) {
return;
}
@@ -742,13 +750,6 @@ public class OneHandedController implements RemoteCallable<OneHandedController>,
});
}
@Override
public void onConfigChanged(Configuration newConfig) {
mMainExecutor.execute(() -> {
OneHandedController.this.onConfigChanged(newConfig);
});
}
@Override
public void onUserSwitch(int userId) {
mMainExecutor.execute(() -> {

View File

@@ -16,7 +16,6 @@
package com.android.wm.shell.pip;
import android.content.res.Configuration;
import android.graphics.Rect;
import com.android.wm.shell.common.annotations.ExternalThread;
@@ -43,24 +42,6 @@ public interface Pip {
default void expandPip() {
}
/**
* Called when configuration is changed.
*/
default void onConfigurationChanged(Configuration newConfig) {
}
/**
* Called when display size or font size of settings changed
*/
default void onDensityOrFontScaleChanged() {
}
/**
* Called when overlay package change invoked.
*/
default void onOverlayChanged() {
}
/**
* Called when SysUI state changed.
*

View File

@@ -87,6 +87,8 @@ import com.android.wm.shell.pip.PipTransitionController;
import com.android.wm.shell.pip.PipTransitionState;
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.ShellController;
import com.android.wm.shell.transition.Transitions;
import java.io.PrintWriter;
@@ -100,7 +102,7 @@ import java.util.function.Consumer;
* Manages the picture-in-picture (PIP) UI and states for Phones.
*/
public class PipController implements PipTransitionController.PipTransitionCallback,
RemoteCallable<PipController> {
RemoteCallable<PipController>, ConfigurationChangeListener {
private static final String TAG = "PipController";
private Context mContext;
@@ -119,6 +121,7 @@ public class PipController implements PipTransitionController.PipTransitionCallb
private TaskStackListenerImpl mTaskStackListener;
private PipParamsChangedForwarder mPipParamsChangedForwarder;
private Optional<OneHandedController> mOneHandedController;
private final ShellController mShellController;
protected final PipImpl mImpl;
private final Rect mTmpInsetBounds = new Rect();
@@ -290,13 +293,20 @@ public class PipController implements PipTransitionController.PipTransitionCallb
* Instantiates {@link PipController}, returns {@code null} if the feature not supported.
*/
@Nullable
public static Pip create(Context context, DisplayController displayController,
PipAppOpsListener pipAppOpsListener, PipBoundsAlgorithm pipBoundsAlgorithm,
PipKeepClearAlgorithm pipKeepClearAlgorithm, PipBoundsState pipBoundsState,
PipMotionHelper pipMotionHelper, PipMediaController pipMediaController,
PhonePipMenuController phonePipMenuController, PipTaskOrganizer pipTaskOrganizer,
public static Pip create(Context context,
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,
@@ -308,9 +318,9 @@ public class PipController implements PipTransitionController.PipTransitionCallb
return null;
}
return new PipController(context, displayController, pipAppOpsListener, pipBoundsAlgorithm,
pipKeepClearAlgorithm, pipBoundsState, pipMotionHelper, pipMediaController,
phonePipMenuController, pipTaskOrganizer, pipTransitionState,
return new PipController(context, shellController, displayController, pipAppOpsListener,
pipBoundsAlgorithm, pipKeepClearAlgorithm, pipBoundsState, pipMotionHelper,
pipMediaController, phonePipMenuController, pipTaskOrganizer, pipTransitionState,
pipTouchHandler, pipTransitionController,
windowManagerShellWrapper, taskStackListener, pipParamsChangedForwarder,
oneHandedController, mainExecutor)
@@ -318,6 +328,7 @@ public class PipController implements PipTransitionController.PipTransitionCallb
}
protected PipController(Context context,
ShellController shellController,
DisplayController displayController,
PipAppOpsListener pipAppOpsListener,
PipBoundsAlgorithm pipBoundsAlgorithm,
@@ -343,6 +354,7 @@ public class PipController implements PipTransitionController.PipTransitionCallb
}
mContext = context;
mShellController = shellController;
mImpl = new PipImpl();
mWindowManagerShellWrapper = windowManagerShellWrapper;
mDisplayController = displayController;
@@ -513,6 +525,8 @@ public class PipController implements PipTransitionController.PipTransitionCallb
}
});
});
mShellController.addConfigurationChangeListener(this);
}
@Override
@@ -525,18 +539,21 @@ public class PipController implements PipTransitionController.PipTransitionCallb
return mMainExecutor;
}
private void onConfigurationChanged(Configuration newConfig) {
@Override
public void onConfigurationChanged(Configuration newConfig) {
mPipBoundsAlgorithm.onConfigurationChanged(mContext);
mTouchHandler.onConfigurationChanged();
mPipBoundsState.onConfigurationChanged();
}
private void onDensityOrFontScaleChanged() {
@Override
public void onDensityOrFontScaleChanged() {
mPipTaskOrganizer.onDensityOrFontScaleChanged(mContext);
onPipResourceDimensionsChanged();
}
private void onOverlayChanged() {
@Override
public void onThemeChanged() {
mTouchHandler.onOverlayChanged();
onDisplayChanged(new DisplayLayout(mContext, mContext.getDisplay()),
false /* saveRestoreSnapFraction */);
@@ -922,27 +939,6 @@ public class PipController implements PipTransitionController.PipTransitionCallb
});
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
mMainExecutor.execute(() -> {
PipController.this.onConfigurationChanged(newConfig);
});
}
@Override
public void onDensityOrFontScaleChanged() {
mMainExecutor.execute(() -> {
PipController.this.onDensityOrFontScaleChanged();
});
}
@Override
public void onOverlayChanged() {
mMainExecutor.execute(() -> {
PipController.this.onOverlayChanged();
});
}
@Override
public void onSystemUiStateChanged(boolean isSysUiStateValid, int flag) {
mMainExecutor.execute(() -> {

View File

@@ -49,6 +49,8 @@ import com.android.wm.shell.pip.PipParamsChangedForwarder;
import com.android.wm.shell.pip.PipTaskOrganizer;
import com.android.wm.shell.pip.PipTransitionController;
import com.android.wm.shell.protolog.ShellProtoLogGroup;
import com.android.wm.shell.sysui.ConfigurationChangeListener;
import com.android.wm.shell.sysui.ShellController;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -61,7 +63,8 @@ import java.util.Set;
*/
public class TvPipController implements PipTransitionController.PipTransitionCallback,
TvPipBoundsController.PipBoundsListener, TvPipMenuController.Delegate,
TvPipNotificationController.Delegate, DisplayController.OnDisplaysChangedListener {
TvPipNotificationController.Delegate, DisplayController.OnDisplaysChangedListener,
ConfigurationChangeListener {
private static final String TAG = "TvPipController";
static final boolean DEBUG = false;
@@ -93,6 +96,7 @@ public class TvPipController implements PipTransitionController.PipTransitionCal
private final Context mContext;
private final ShellController mShellController;
private final TvPipBoundsState mTvPipBoundsState;
private final TvPipBoundsAlgorithm mTvPipBoundsAlgorithm;
private final TvPipBoundsController mTvPipBoundsController;
@@ -117,6 +121,7 @@ public class TvPipController implements PipTransitionController.PipTransitionCal
public static Pip create(
Context context,
ShellController shellController,
TvPipBoundsState tvPipBoundsState,
TvPipBoundsAlgorithm tvPipBoundsAlgorithm,
TvPipBoundsController tvPipBoundsController,
@@ -133,6 +138,7 @@ public class TvPipController implements PipTransitionController.PipTransitionCal
ShellExecutor mainExecutor) {
return new TvPipController(
context,
shellController,
tvPipBoundsState,
tvPipBoundsAlgorithm,
tvPipBoundsController,
@@ -151,6 +157,7 @@ public class TvPipController implements PipTransitionController.PipTransitionCal
private TvPipController(
Context context,
ShellController shellController,
TvPipBoundsState tvPipBoundsState,
TvPipBoundsAlgorithm tvPipBoundsAlgorithm,
TvPipBoundsController tvPipBoundsController,
@@ -167,6 +174,7 @@ public class TvPipController implements PipTransitionController.PipTransitionCal
ShellExecutor mainExecutor) {
mContext = context;
mMainExecutor = mainExecutor;
mShellController = shellController;
mTvPipBoundsState = tvPipBoundsState;
mTvPipBoundsState.setDisplayId(context.getDisplayId());
@@ -193,9 +201,12 @@ public class TvPipController implements PipTransitionController.PipTransitionCal
registerTaskStackListenerCallback(taskStackListener);
registerWmShellPinnedStackListener(wmShell);
displayController.addDisplayWindowListener(this);
mShellController.addConfigurationChangeListener(this);
}
private void onConfigurationChanged(Configuration newConfig) {
@Override
public void onConfigurationChanged(Configuration newConfig) {
if (DEBUG) {
ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
"%s: onConfigurationChanged(), state=%s", TAG, stateToName(mState));
@@ -668,13 +679,6 @@ public class TvPipController implements PipTransitionController.PipTransitionCal
}
private class TvPipImpl implements Pip {
@Override
public void onConfigurationChanged(Configuration newConfig) {
mMainExecutor.execute(() -> {
TvPipController.this.onConfigurationChanged(newConfig);
});
}
@Override
public void registerSessionListenerForCurrentUser() {
mMainExecutor.execute(() -> {

View File

@@ -44,6 +44,8 @@ public enum ShellProtoLogGroup implements IProtoLogGroup {
Consts.TAG_WM_SHELL),
WM_SHELL_SPLIT_SCREEN(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, false,
Consts.TAG_WM_SHELL),
WM_SHELL_SYSUI_EVENTS(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, false,
Consts.TAG_WM_SHELL),
TEST_GROUP(true, true, false, "WindowManagerShellProtoLogTest");
private final boolean mEnabled;

View File

@@ -0,0 +1,51 @@
/*
* 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.sysui;
import android.content.res.Configuration;
/**
* Callbacks for when the configuration changes.
*/
public interface ConfigurationChangeListener {
/**
* Called when a configuration changes. This precedes all the following callbacks.
*/
default void onConfigurationChanged(Configuration newConfiguration) {}
/**
* Convenience method to the above, called when the density or font scale changes.
*/
default void onDensityOrFontScaleChanged() {}
/**
* Convenience method to the above, called when the smallest screen width changes.
*/
default void onSmallestScreenWidthChanged() {}
/**
* Convenience method to the above, called when the system theme changes, including dark/light
* UI_MODE changes.
*/
default void onThemeChanged() {}
/**
* Convenience method to the above, called when the local list or layout direction changes.
*/
default void onLocaleOrLayoutDirectionChanged() {}
}

View File

@@ -0,0 +1,140 @@
/*
* 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.sysui;
import static android.content.pm.ActivityInfo.CONFIG_ASSETS_PATHS;
import static android.content.pm.ActivityInfo.CONFIG_FONT_SCALE;
import static android.content.pm.ActivityInfo.CONFIG_LAYOUT_DIRECTION;
import static android.content.pm.ActivityInfo.CONFIG_LOCALE;
import static android.content.pm.ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE;
import static android.content.pm.ActivityInfo.CONFIG_UI_MODE;
import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_SYSUI_EVENTS;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
import com.android.internal.protolog.common.ProtoLog;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.annotations.ExternalThread;
import java.io.PrintWriter;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* Handles event callbacks from SysUI that can be used within the Shell.
*/
public class ShellController {
private static final String TAG = ShellController.class.getSimpleName();
private final ShellExecutor mMainExecutor;
private final ShellInterfaceImpl mImpl = new ShellInterfaceImpl();
private final CopyOnWriteArrayList<ConfigurationChangeListener> mListeners =
new CopyOnWriteArrayList<>();
private Configuration mLastConfiguration;
public ShellController(ShellExecutor mainExecutor) {
mMainExecutor = mainExecutor;
}
/**
* Returns the external interface to this controller.
*/
public ShellInterface asShell() {
return mImpl;
}
/**
* Adds a new configuration listener. The configuration change callbacks are not made in any
* particular order.
*/
public void addConfigurationChangeListener(ConfigurationChangeListener listener) {
mListeners.remove(listener);
mListeners.add(listener);
}
/**
* Removes an existing configuration listener.
*/
public void removeConfigurationChangeListener(ConfigurationChangeListener listener) {
mListeners.remove(listener);
}
@VisibleForTesting
void onConfigurationChanged(Configuration newConfig) {
// The initial config is send on startup and doesn't trigger listener callbacks
if (mLastConfiguration == null) {
mLastConfiguration = new Configuration(newConfig);
ProtoLog.v(WM_SHELL_SYSUI_EVENTS, "Initial Configuration: %s", newConfig);
return;
}
final int diff = newConfig.diff(mLastConfiguration);
ProtoLog.v(WM_SHELL_SYSUI_EVENTS, "New configuration change: %s", newConfig);
ProtoLog.v(WM_SHELL_SYSUI_EVENTS, "\tchanges=%s",
Configuration.configurationDiffToString(diff));
final boolean densityFontScaleChanged = (diff & CONFIG_FONT_SCALE) != 0
|| (diff & ActivityInfo.CONFIG_DENSITY) != 0;
final boolean smallestScreenWidthChanged = (diff & CONFIG_SMALLEST_SCREEN_SIZE) != 0;
final boolean themeChanged = (diff & CONFIG_ASSETS_PATHS) != 0
|| (diff & CONFIG_UI_MODE) != 0;
final boolean localOrLayoutDirectionChanged = (diff & CONFIG_LOCALE) != 0
|| (diff & CONFIG_LAYOUT_DIRECTION) != 0;
// Update the last configuration and call listeners
mLastConfiguration.updateFrom(newConfig);
for (ConfigurationChangeListener listener : mListeners) {
listener.onConfigurationChanged(newConfig);
if (densityFontScaleChanged) {
listener.onDensityOrFontScaleChanged();
}
if (smallestScreenWidthChanged) {
listener.onSmallestScreenWidthChanged();
}
if (themeChanged) {
listener.onThemeChanged();
}
if (localOrLayoutDirectionChanged) {
listener.onLocaleOrLayoutDirectionChanged();
}
}
}
public void dump(@NonNull PrintWriter pw, String prefix) {
final String innerPrefix = prefix + " ";
pw.println(prefix + TAG);
pw.println(innerPrefix + "mListeners=" + mListeners.size());
pw.println(innerPrefix + "mLastConfiguration=" + mLastConfiguration);
}
/**
* The interface for calls from outside the Shell, within the host process.
*/
@ExternalThread
private class ShellInterfaceImpl implements ShellInterface {
@Override
public void onConfigurationChanged(Configuration newConfiguration) {
mMainExecutor.execute(() ->
ShellController.this.onConfigurationChanged(newConfiguration));
}
}
}

View File

@@ -0,0 +1,33 @@
/*
* 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.sysui;
import android.content.res.Configuration;
/**
* General interface for notifying the Shell of common SysUI events like configuration or keyguard
* changes.
*
* TODO: Move ShellInit and ShellCommandHandler into this interface
*/
public interface ShellInterface {
/**
* Notifies the Shell that the configuration has changed.
*/
default void onConfigurationChanged(Configuration newConfiguration) {}
}

View File

@@ -21,6 +21,7 @@ import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.DragEvent.ACTION_DRAG_STARTED;
import static org.junit.Assert.assertFalse;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
@@ -48,6 +49,7 @@ import com.android.wm.shell.ShellTestCase;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.splitscreen.SplitScreenController;
import com.android.wm.shell.sysui.ShellController;
import org.junit.Before;
import org.junit.Test;
@@ -66,24 +68,34 @@ public class DragAndDropControllerTest extends ShellTestCase {
@Mock
private Context mContext;
@Mock
private ShellController mShellController;
@Mock
private DisplayController mDisplayController;
@Mock
private UiEventLogger mUiEventLogger;
@Mock
private DragAndDropController.DragAndDropListener mDragAndDropListener;
@Mock
private IconProvider mIconProvider;
@Mock
private ShellExecutor mMainExecutor;
@Mock
private SplitScreenController mSplitScreenController;
private DragAndDropController mController;
@Before
public void setUp() throws RemoteException {
MockitoAnnotations.initMocks(this);
mController = new DragAndDropController(mContext, mDisplayController, mUiEventLogger,
mock(IconProvider.class), mock(ShellExecutor.class));
mController.initialize(Optional.of(mock(SplitScreenController.class)));
mController = new DragAndDropController(mContext, mShellController, mDisplayController,
mUiEventLogger, mIconProvider, mMainExecutor);
mController.initialize(Optional.of(mSplitScreenController));
}
@Test
public void instantiateController_registerConfigChangeListener() {
verify(mShellController, times(1)).addConfigurationChangeListener(any());
}
@Test

View File

@@ -16,7 +16,9 @@
package com.android.wm.shell.hidedisplaycutout;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import android.testing.AndroidTestingRunner;
@@ -28,6 +30,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.ShellController;
import org.junit.Before;
import org.junit.Test;
@@ -42,17 +45,25 @@ public class HideDisplayCutoutControllerTest extends ShellTestCase {
private TestableContext mContext = new TestableContext(
InstrumentationRegistry.getInstrumentation().getTargetContext(), null);
private HideDisplayCutoutController mHideDisplayCutoutController;
@Mock
private ShellController mShellController;
@Mock
private HideDisplayCutoutOrganizer mMockDisplayAreaOrganizer;
@Mock
private ShellExecutor mMockMainExecutor;
private HideDisplayCutoutController mHideDisplayCutoutController;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
mHideDisplayCutoutController = new HideDisplayCutoutController(
mContext, mMockDisplayAreaOrganizer, mMockMainExecutor);
mContext, mShellController, mMockDisplayAreaOrganizer, mMockMainExecutor);
}
@Test
public void instantiateController_registerConfigChangeListener() {
verify(mShellController, times(1)).addConfigurationChangeListener(any());
}
@Test

View File

@@ -30,6 +30,7 @@ import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.atLeastOnce;
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;
@@ -48,6 +49,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.ShellController;
import org.junit.Before;
import org.junit.Test;
@@ -67,6 +69,8 @@ public class OneHandedControllerTest extends OneHandedTestCase {
OneHandedTimeoutHandler mSpiedTimeoutHandler;
OneHandedState mSpiedTransitionState;
@Mock
ShellController mMockShellController;
@Mock
DisplayLayout mDisplayLayout;
@Mock
@@ -123,6 +127,7 @@ public class OneHandedControllerTest extends OneHandedTestCase {
mOneHandedAccessibilityUtil = new OneHandedAccessibilityUtil(mContext);
mSpiedOneHandedController = spy(new OneHandedController(
mContext,
mMockShellController,
mMockDisplayController,
mMockDisplayAreaOrganizer,
mMockTouchHandler,
@@ -138,6 +143,11 @@ public class OneHandedControllerTest extends OneHandedTestCase {
);
}
@Test
public void testControllerRegistersConfigChangeListener() {
verify(mMockShellController, times(1)).addConfigurationChangeListener(any());
}
@Test
public void testDefaultShouldNotInOneHanded() {
// Assert default transition state is STATE_NONE

View File

@@ -31,7 +31,6 @@ import static org.mockito.Mockito.when;
import android.graphics.Rect;
import android.os.Handler;
import android.os.UserHandle;
import android.testing.AndroidTestingRunner;
import android.util.ArrayMap;
import android.view.Display;
@@ -42,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.ShellController;
import org.junit.Before;
import org.junit.Test;
@@ -52,7 +52,6 @@ import org.mockito.MockitoAnnotations;
@SmallTest
@RunWith(AndroidTestingRunner.class)
public class OneHandedStateTest extends OneHandedTestCase {
private int mCurrentUser = UserHandle.myUserId();
Display mDisplay;
DisplayLayout mDisplayLayout;
@@ -61,6 +60,8 @@ public class OneHandedStateTest extends OneHandedTestCase {
OneHandedTimeoutHandler mSpiedTimeoutHandler;
OneHandedState mSpiedState;
@Mock
ShellController mMockShellController;
@Mock
DisplayController mMockDisplayController;
@Mock
@@ -110,6 +111,7 @@ public class OneHandedStateTest extends OneHandedTestCase {
mOneHandedAccessibilityUtil = new OneHandedAccessibilityUtil(mContext);
mSpiedOneHandedController = spy(new OneHandedController(
mContext,
mMockShellController,
mMockDisplayController,
mMockDisplayAreaOrganizer,
mMockTouchHandler,

View File

@@ -24,6 +24,7 @@ import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
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;
@@ -54,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.ShellController;
import org.junit.Before;
import org.junit.Test;
@@ -73,6 +75,7 @@ import java.util.Set;
public class PipControllerTest extends ShellTestCase {
private PipController mPipController;
@Mock private ShellController mMockShellController;
@Mock private DisplayController mMockDisplayController;
@Mock private PhonePipMenuController mMockPhonePipMenuController;
@Mock private PipAppOpsListener mMockPipAppOpsListener;
@@ -102,7 +105,7 @@ public class PipControllerTest extends ShellTestCase {
((Runnable) invocation.getArgument(0)).run();
return null;
}).when(mMockExecutor).execute(any());
mPipController = new PipController(mContext, mMockDisplayController,
mPipController = new PipController(mContext, mMockShellController, mMockDisplayController,
mMockPipAppOpsListener, mMockPipBoundsAlgorithm,
mMockPipKeepClearAlgorithm,
mMockPipBoundsState, mMockPipMotionHelper, mMockPipMediaController,
@@ -114,6 +117,11 @@ public class PipControllerTest extends ShellTestCase {
when(mMockPipTouchHandler.getMotionHelper()).thenReturn(mMockPipMotionHelper);
}
@Test
public void instantiatePipController_registerConfigChangeListener() {
verify(mMockShellController, times(1)).addConfigurationChangeListener(any());
}
@Test
public void instantiatePipController_registersPipTransitionCallback() {
verify(mMockPipTransitionController).registerPipTransitionCallback(any());
@@ -136,7 +144,7 @@ public class PipControllerTest extends ShellTestCase {
when(mockPackageManager.hasSystemFeature(FEATURE_PICTURE_IN_PICTURE)).thenReturn(false);
when(spyContext.getPackageManager()).thenReturn(mockPackageManager);
assertNull(PipController.create(spyContext, mMockDisplayController,
assertNull(PipController.create(spyContext, mMockShellController, mMockDisplayController,
mMockPipAppOpsListener, mMockPipBoundsAlgorithm,
mMockPipKeepClearAlgorithm,
mMockPipBoundsState, mMockPipMotionHelper, mMockPipMediaController,

View File

@@ -0,0 +1,256 @@
/*
* 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.sysui;
import static org.junit.Assert.assertTrue;
import android.content.res.Configuration;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import androidx.test.filters.SmallTest;
import androidx.test.platform.app.InstrumentationRegistry;
import com.android.wm.shell.ShellTestCase;
import com.android.wm.shell.common.ShellExecutor;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.util.Locale;
@SmallTest
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper(setAsMainLooper = true)
public class ShellControllerTest extends ShellTestCase {
@Mock
private ShellExecutor mExecutor;
private ShellController mController;
private TestConfigurationChangeListener mListener;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mListener = new TestConfigurationChangeListener();
mController = new ShellController(mExecutor);
mController.onConfigurationChanged(getConfigurationCopy());
}
@After
public void tearDown() {
// Do nothing
}
@Test
public void testAddConfigurationChangeListener_ensureCallback() {
mController.addConfigurationChangeListener(mListener);
Configuration newConfig = getConfigurationCopy();
newConfig.densityDpi = 200;
mController.onConfigurationChanged(newConfig);
assertTrue(mListener.configChanges == 1);
}
@Test
public void testDoubleAddConfigurationChangeListener_ensureSingleCallback() {
mController.addConfigurationChangeListener(mListener);
mController.addConfigurationChangeListener(mListener);
Configuration newConfig = getConfigurationCopy();
newConfig.densityDpi = 200;
mController.onConfigurationChanged(newConfig);
assertTrue(mListener.configChanges == 1);
}
@Test
public void testAddRemoveConfigurationChangeListener_ensureNoCallback() {
mController.addConfigurationChangeListener(mListener);
mController.removeConfigurationChangeListener(mListener);
Configuration newConfig = getConfigurationCopy();
newConfig.densityDpi = 200;
mController.onConfigurationChanged(newConfig);
assertTrue(mListener.configChanges == 0);
}
@Test
public void testMultipleConfigurationChangeListeners() {
TestConfigurationChangeListener listener2 = new TestConfigurationChangeListener();
mController.addConfigurationChangeListener(mListener);
mController.addConfigurationChangeListener(listener2);
Configuration newConfig = getConfigurationCopy();
newConfig.densityDpi = 200;
mController.onConfigurationChanged(newConfig);
assertTrue(mListener.configChanges == 1);
assertTrue(listener2.configChanges == 1);
}
@Test
public void testRemoveListenerDuringCallback() {
TestConfigurationChangeListener badListener = new TestConfigurationChangeListener() {
@Override
public void onConfigurationChanged(Configuration newConfiguration) {
mController.removeConfigurationChangeListener(this);
}
};
mController.addConfigurationChangeListener(badListener);
mController.addConfigurationChangeListener(mListener);
// Ensure we don't fail just because a listener was removed mid-callback
Configuration newConfig = getConfigurationCopy();
newConfig.densityDpi = 200;
mController.onConfigurationChanged(newConfig);
}
@Test
public void testDensityChangeCallback() {
mController.addConfigurationChangeListener(mListener);
Configuration newConfig = getConfigurationCopy();
newConfig.densityDpi = 200;
mController.onConfigurationChanged(newConfig);
assertTrue(mListener.configChanges == 1);
assertTrue(mListener.densityChanges == 1);
assertTrue(mListener.smallestWidthChanges == 0);
assertTrue(mListener.themeChanges == 0);
assertTrue(mListener.localeChanges == 0);
}
@Test
public void testFontScaleChangeCallback() {
mController.addConfigurationChangeListener(mListener);
Configuration newConfig = getConfigurationCopy();
newConfig.fontScale = 2;
mController.onConfigurationChanged(newConfig);
assertTrue(mListener.configChanges == 1);
assertTrue(mListener.densityChanges == 1);
assertTrue(mListener.smallestWidthChanges == 0);
assertTrue(mListener.themeChanges == 0);
assertTrue(mListener.localeChanges == 0);
}
@Test
public void testSmallestWidthChangeCallback() {
mController.addConfigurationChangeListener(mListener);
Configuration newConfig = getConfigurationCopy();
newConfig.smallestScreenWidthDp = 100;
mController.onConfigurationChanged(newConfig);
assertTrue(mListener.configChanges == 1);
assertTrue(mListener.densityChanges == 0);
assertTrue(mListener.smallestWidthChanges == 1);
assertTrue(mListener.themeChanges == 0);
assertTrue(mListener.localeChanges == 0);
}
@Test
public void testThemeChangeCallback() {
mController.addConfigurationChangeListener(mListener);
Configuration newConfig = getConfigurationCopy();
newConfig.assetsSeq++;
mController.onConfigurationChanged(newConfig);
assertTrue(mListener.configChanges == 1);
assertTrue(mListener.densityChanges == 0);
assertTrue(mListener.smallestWidthChanges == 0);
assertTrue(mListener.themeChanges == 1);
assertTrue(mListener.localeChanges == 0);
}
@Test
public void testNightModeChangeCallback() {
mController.addConfigurationChangeListener(mListener);
Configuration newConfig = getConfigurationCopy();
newConfig.uiMode = Configuration.UI_MODE_NIGHT_YES;
mController.onConfigurationChanged(newConfig);
assertTrue(mListener.configChanges == 1);
assertTrue(mListener.densityChanges == 0);
assertTrue(mListener.smallestWidthChanges == 0);
assertTrue(mListener.themeChanges == 1);
assertTrue(mListener.localeChanges == 0);
}
@Test
public void testLocaleChangeCallback() {
mController.addConfigurationChangeListener(mListener);
Configuration newConfig = getConfigurationCopy();
// Just change the locales to be different
if (newConfig.locale == Locale.CANADA) {
newConfig.locale = Locale.US;
} else {
newConfig.locale = Locale.CANADA;
}
mController.onConfigurationChanged(newConfig);
assertTrue(mListener.configChanges == 1);
assertTrue(mListener.densityChanges == 0);
assertTrue(mListener.smallestWidthChanges == 0);
assertTrue(mListener.themeChanges == 0);
assertTrue(mListener.localeChanges == 1);
}
private Configuration getConfigurationCopy() {
final Configuration c = new Configuration(InstrumentationRegistry.getInstrumentation()
.getTargetContext().getResources().getConfiguration());
// In tests this might be undefined so make sure it's valid
c.assetsSeq = 1;
return c;
}
private class TestConfigurationChangeListener implements ConfigurationChangeListener {
// Counts of number of times each of the callbacks are called
public int configChanges;
public int densityChanges;
public int smallestWidthChanges;
public int themeChanges;
public int localeChanges;
@Override
public void onConfigurationChanged(Configuration newConfiguration) {
configChanges++;
}
@Override
public void onDensityOrFontScaleChanged() {
densityChanges++;
}
@Override
public void onSmallestScreenWidthChanged() {
smallestWidthChanges++;
}
@Override
public void onThemeChanged() {
themeChanges++;
}
@Override
public void onLocaleOrLayoutDirectionChanged() {
localeChanges++;
}
}
}

View File

@@ -27,6 +27,7 @@ import com.android.systemui.dagger.SysUIComponent;
import com.android.systemui.dagger.WMComponent;
import com.android.systemui.util.InitializationChecker;
import com.android.wm.shell.dagger.WMShellConcurrencyModule;
import com.android.wm.shell.sysui.ShellInterface;
import com.android.wm.shell.transition.ShellTransitions;
import java.util.Optional;
@@ -90,6 +91,7 @@ public abstract class SystemUIInitializer {
// Only initialize when not starting from tests since this currently initializes some
// components that shouldn't be run in the test environment
builder = prepareSysUIComponentBuilder(builder, mWMComponent)
.setShell(mWMComponent.getShell())
.setPip(mWMComponent.getPip())
.setSplitScreen(mWMComponent.getSplitScreen())
.setOneHanded(mWMComponent.getOneHanded())
@@ -109,6 +111,7 @@ public abstract class SystemUIInitializer {
// TODO: Call on prepareSysUIComponentBuilder but not with real components. Other option
// is separating this logic into newly creating SystemUITestsFactory.
builder = prepareSysUIComponentBuilder(builder, mWMComponent)
.setShell(new ShellInterface() {})
.setPip(Optional.ofNullable(null))
.setSplitScreen(Optional.ofNullable(null))
.setOneHanded(Optional.ofNullable(null))

View File

@@ -50,6 +50,7 @@ import com.android.wm.shell.pip.Pip;
import com.android.wm.shell.recents.RecentTasks;
import com.android.wm.shell.splitscreen.SplitScreen;
import com.android.wm.shell.startingsurface.StartingSurface;
import com.android.wm.shell.sysui.ShellInterface;
import com.android.wm.shell.tasksurfacehelper.TaskSurfaceHelper;
import com.android.wm.shell.transition.ShellTransitions;
@@ -80,6 +81,9 @@ public interface SysUIComponent {
@SysUISingleton
@Subcomponent.Builder
interface Builder {
@BindsInstance
Builder setShell(ShellInterface s);
@BindsInstance
Builder setPip(Optional<Pip> p);

View File

@@ -90,6 +90,7 @@ import com.android.systemui.wallet.dagger.WalletModule;
import com.android.systemui.wmshell.BubblesManager;
import com.android.wm.shell.bubbles.Bubbles;
import com.android.wm.shell.dagger.DynamicOverride;
import com.android.wm.shell.sysui.ShellController;
import java.util.Optional;
import java.util.concurrent.Executor;
@@ -208,7 +209,6 @@ public abstract class SystemUIModule {
NotificationShadeWindowController notificationShadeWindowController,
KeyguardStateController keyguardStateController,
ShadeController shadeController,
ConfigurationController configurationController,
@Nullable IStatusBarService statusBarService,
INotificationManager notificationManager,
NotificationVisibilityProvider visibilityProvider,
@@ -226,7 +226,6 @@ public abstract class SystemUIModule {
notificationShadeWindowController,
keyguardStateController,
shadeController,
configurationController,
statusBarService,
notificationManager,
visibilityProvider,

View File

@@ -41,6 +41,7 @@ import com.android.wm.shell.pip.Pip;
import com.android.wm.shell.recents.RecentTasks;
import com.android.wm.shell.splitscreen.SplitScreen;
import com.android.wm.shell.startingsurface.StartingSurface;
import com.android.wm.shell.sysui.ShellInterface;
import com.android.wm.shell.tasksurfacehelper.TaskSurfaceHelper;
import com.android.wm.shell.transition.ShellTransitions;
@@ -87,6 +88,9 @@ public interface WMComponent {
@WMSingleton
Optional<ShellCommandHandler> getShellCommandHandler();
@WMSingleton
ShellInterface getShell();
@WMSingleton
Optional<OneHanded> getOneHanded();

View File

@@ -72,7 +72,6 @@ import com.android.systemui.statusbar.notification.collection.render.Notificatio
import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider;
import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.statusbar.phone.StatusBarWindowCallback;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.wm.shell.bubbles.Bubble;
@@ -126,7 +125,6 @@ public class BubblesManager implements Dumpable {
NotificationShadeWindowController notificationShadeWindowController,
KeyguardStateController keyguardStateController,
ShadeController shadeController,
ConfigurationController configurationController,
@Nullable IStatusBarService statusBarService,
INotificationManager notificationManager,
NotificationVisibilityProvider visibilityProvider,
@@ -145,7 +143,6 @@ public class BubblesManager implements Dumpable {
notificationShadeWindowController,
keyguardStateController,
shadeController,
configurationController,
statusBarService,
notificationManager,
visibilityProvider,
@@ -169,7 +166,6 @@ public class BubblesManager implements Dumpable {
NotificationShadeWindowController notificationShadeWindowController,
KeyguardStateController keyguardStateController,
ShadeController shadeController,
ConfigurationController configurationController,
@Nullable IStatusBarService statusBarService,
INotificationManager notificationManager,
NotificationVisibilityProvider visibilityProvider,
@@ -213,23 +209,6 @@ public class BubblesManager implements Dumpable {
}
});
configurationController.addCallback(new ConfigurationController.ConfigurationListener() {
@Override
public void onConfigChanged(Configuration newConfig) {
mBubbles.onConfigChanged(newConfig);
}
@Override
public void onUiModeChanged() {
mBubbles.updateForThemeChanges();
}
@Override
public void onThemeChanged() {
mBubbles.updateForThemeChanges();
}
});
zenModeController.addCallback(new ZenModeController.Callback() {
@Override
public void onZenChanged(int zen) {

View File

@@ -47,7 +47,6 @@ import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.keyguard.ScreenLifecycle;
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.model.SysUiState;
import com.android.systemui.navigationbar.NavigationModeController;
import com.android.systemui.shared.tracing.ProtoTraceable;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.policy.ConfigurationController;
@@ -67,6 +66,7 @@ import com.android.wm.shell.onehanded.OneHandedUiEventLogger;
import com.android.wm.shell.pip.Pip;
import com.android.wm.shell.protolog.ShellProtoLogImpl;
import com.android.wm.shell.splitscreen.SplitScreen;
import com.android.wm.shell.sysui.ShellInterface;
import java.io.PrintWriter;
import java.util.Arrays;
@@ -106,6 +106,7 @@ public final class WMShell extends CoreStartable
| SYSUI_STATE_QUICK_SETTINGS_EXPANDED;
// Shell interfaces
private final ShellInterface mShell;
private final Optional<Pip> mPipOptional;
private final Optional<SplitScreen> mSplitScreenOptional;
private final Optional<OneHanded> mOneHandedOptional;
@@ -118,7 +119,6 @@ public final class WMShell extends CoreStartable
private final ConfigurationController mConfigurationController;
private final KeyguardStateController mKeyguardStateController;
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
private final NavigationModeController mNavigationModeController;
private final ScreenLifecycle mScreenLifecycle;
private final SysUiState mSysUiState;
private final WakefulnessLifecycle mWakefulnessLifecycle;
@@ -135,6 +135,7 @@ public final class WMShell extends CoreStartable
@Inject
public WMShell(Context context,
ShellInterface shell,
Optional<Pip> pipOptional,
Optional<SplitScreen> splitScreenOptional,
Optional<OneHanded> oneHandedOptional,
@@ -146,7 +147,6 @@ public final class WMShell extends CoreStartable
ConfigurationController configurationController,
KeyguardStateController keyguardStateController,
KeyguardUpdateMonitor keyguardUpdateMonitor,
NavigationModeController navigationModeController,
ScreenLifecycle screenLifecycle,
SysUiState sysUiState,
ProtoTracer protoTracer,
@@ -154,11 +154,11 @@ public final class WMShell extends CoreStartable
UserInfoController userInfoController,
@Main Executor sysUiMainExecutor) {
super(context);
mShell = shell;
mCommandQueue = commandQueue;
mConfigurationController = configurationController;
mKeyguardStateController = keyguardStateController;
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
mNavigationModeController = navigationModeController;
mScreenLifecycle = screenLifecycle;
mSysUiState = sysUiState;
mPipOptional = pipOptional;
@@ -176,6 +176,15 @@ public final class WMShell extends CoreStartable
@Override
public void start() {
// Notify with the initial configuration and subscribe for new config changes
mShell.onConfigurationChanged(mContext.getResources().getConfiguration());
mConfigurationController.addCallback(new ConfigurationController.ConfigurationListener() {
@Override
public void onConfigChanged(Configuration newConfig) {
mShell.onConfigurationChanged(newConfig);
}
});
// TODO: Consider piping config change and other common calls to a shell component to
// delegate internally
mProtoTracer.add(this);
@@ -183,9 +192,7 @@ public final class WMShell extends CoreStartable
mPipOptional.ifPresent(this::initPip);
mSplitScreenOptional.ifPresent(this::initSplitScreen);
mOneHandedOptional.ifPresent(this::initOneHanded);
mHideDisplayCutoutOptional.ifPresent(this::initHideDisplayCutout);
mCompatUIOptional.ifPresent(this::initCompatUi);
mDragAndDropOptional.ifPresent(this::initDragAndDrop);
}
@VisibleForTesting
@@ -216,23 +223,6 @@ public final class WMShell extends CoreStartable
pip.onSystemUiStateChanged(mIsSysUiStateValid, sysUiStateFlag);
});
mConfigurationController.addCallback(new ConfigurationController.ConfigurationListener() {
@Override
public void onConfigChanged(Configuration newConfig) {
pip.onConfigurationChanged(newConfig);
}
@Override
public void onDensityOrFontScaleChanged() {
pip.onDensityOrFontScaleChanged();
}
@Override
public void onThemeChanged() {
pip.onOverlayChanged();
}
});
// The media session listener needs to be re-registered when switching users
mUserInfoController.addCallback((String name, Drawable picture, String userAccount) ->
pip.registerSessionListenerForCurrentUser());
@@ -348,23 +338,6 @@ public final class WMShell extends CoreStartable
}
}
});
mConfigurationController.addCallback(new ConfigurationController.ConfigurationListener() {
@Override
public void onConfigChanged(Configuration newConfig) {
oneHanded.onConfigChanged(newConfig);
}
});
}
@VisibleForTesting
void initHideDisplayCutout(HideDisplayCutout hideDisplayCutout) {
mConfigurationController.addCallback(new ConfigurationController.ConfigurationListener() {
@Override
public void onConfigChanged(Configuration newConfig) {
hideDisplayCutout.onConfigurationChanged(newConfig);
}
});
}
@VisibleForTesting
@@ -378,20 +351,6 @@ public final class WMShell extends CoreStartable
mKeyguardStateController.addCallback(mCompatUIKeyguardCallback);
}
void initDragAndDrop(DragAndDrop dragAndDrop) {
mConfigurationController.addCallback(new ConfigurationController.ConfigurationListener() {
@Override
public void onConfigChanged(Configuration newConfig) {
dragAndDrop.onConfigChanged(newConfig);
}
@Override
public void onThemeChanged() {
dragAndDrop.onThemeChanged();
}
});
}
@Override
public void writeToProto(SystemUiTraceProto proto) {
if (proto.wmShell == null) {

View File

@@ -133,6 +133,7 @@ import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.common.TaskStackListenerImpl;
import com.android.wm.shell.draganddrop.DragAndDropController;
import com.android.wm.shell.onehanded.OneHandedController;
import com.android.wm.shell.sysui.ShellController;
import org.junit.Before;
import org.junit.Ignore;
@@ -213,6 +214,8 @@ public class BubblesTest extends SysuiTestCase {
private BubbleEntry mBubbleEntryUser11;
private BubbleEntry mBubbleEntry2User11;
@Mock
private ShellController mShellController;
@Mock
private Bubbles.BubbleExpandListener mBubbleExpandListener;
@Mock
@@ -328,6 +331,7 @@ public class BubblesTest extends SysuiTestCase {
when(mShellTaskOrganizer.getExecutor()).thenReturn(syncExecutor);
mBubbleController = new TestableBubbleController(
mContext,
mShellController,
mBubbleData,
mFloatingContentCoordinator,
mDataRepository,
@@ -356,7 +360,6 @@ public class BubblesTest extends SysuiTestCase {
mNotificationShadeWindowController,
mock(KeyguardStateController.class),
mShadeController,
mConfigurationController,
mStatusBarService,
mock(INotificationManager.class),
mVisibilityProvider,
@@ -377,6 +380,11 @@ public class BubblesTest extends SysuiTestCase {
mEntryListener = mNotifListenerCaptor.getValue();
}
@Test
public void instantiateController_registerConfigChangeListener() {
verify(mShellController, times(1)).addConfigurationChangeListener(any());
}
@Test
public void testAddBubble() {
mBubbleController.updateBubble(mBubbleEntry);

View File

@@ -38,6 +38,7 @@ import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.common.TaskStackListenerImpl;
import com.android.wm.shell.draganddrop.DragAndDropController;
import com.android.wm.shell.onehanded.OneHandedController;
import com.android.wm.shell.sysui.ShellController;
import java.util.Optional;
@@ -48,6 +49,7 @@ public class TestableBubbleController extends BubbleController {
// Let's assume surfaces can be synchronized immediately.
TestableBubbleController(Context context,
ShellController shellController,
BubbleData data,
FloatingContentCoordinator floatingContentCoordinator,
BubbleDataRepository dataRepository,
@@ -67,11 +69,12 @@ public class TestableBubbleController extends BubbleController {
Handler shellMainHandler,
TaskViewTransitions taskViewTransitions,
SyncTransactionQueue syncQueue) {
super(context, data, Runnable::run, floatingContentCoordinator, dataRepository,
statusBarService, windowManager, windowManagerShellWrapper, userManager,
launcherApps, bubbleLogger, taskStackListener, shellTaskOrganizer, positioner,
displayController, oneHandedOptional, dragAndDropController, shellMainExecutor,
shellMainHandler, new SyncExecutor(), taskViewTransitions, syncQueue);
super(context, shellController, data, Runnable::run, floatingContentCoordinator,
dataRepository, statusBarService, windowManager, windowManagerShellWrapper,
userManager, launcherApps, bubbleLogger, taskStackListener, shellTaskOrganizer,
positioner, displayController, oneHandedOptional, dragAndDropController,
shellMainExecutor, shellMainHandler, new SyncExecutor(), taskViewTransitions,
syncQueue);
setInflateSynchronously(true);
initialize();
}

View File

@@ -45,6 +45,7 @@ import com.android.wm.shell.onehanded.OneHandedEventCallback;
import com.android.wm.shell.onehanded.OneHandedTransitionCallback;
import com.android.wm.shell.pip.Pip;
import com.android.wm.shell.splitscreen.SplitScreen;
import com.android.wm.shell.sysui.ShellInterface;
import org.junit.Before;
import org.junit.Test;
@@ -65,6 +66,7 @@ import java.util.Optional;
public class WMShellTest extends SysuiTestCase {
WMShell mWMShell;
@Mock ShellInterface mShellInterface;
@Mock CommandQueue mCommandQueue;
@Mock ConfigurationController mConfigurationController;
@Mock KeyguardStateController mKeyguardStateController;
@@ -88,12 +90,12 @@ public class WMShellTest extends SysuiTestCase {
public void setUp() {
MockitoAnnotations.initMocks(this);
mWMShell = new WMShell(mContext, Optional.of(mPip),
mWMShell = new WMShell(mContext, mShellInterface, Optional.of(mPip),
Optional.of(mSplitScreen), Optional.of(mOneHanded), Optional.of(mHideDisplayCutout),
Optional.of(mShellCommandHandler), Optional.of(mCompatUI),
Optional.of(mDragAndDrop),
mCommandQueue, mConfigurationController, mKeyguardStateController,
mKeyguardUpdateMonitor, mNavigationModeController, mScreenLifecycle, mSysUiState,
mKeyguardUpdateMonitor, mScreenLifecycle, mSysUiState,
mProtoTracer, mWakefulnessLifecycle, mUserInfoController, mSysUiMainExecutor);
}
@@ -122,14 +124,6 @@ public class WMShellTest extends SysuiTestCase {
verify(mOneHanded).registerEventCallback(any(OneHandedEventCallback.class));
}
@Test
public void initHideDisplayCutout_registersCallbacks() {
mWMShell.initHideDisplayCutout(mHideDisplayCutout);
verify(mConfigurationController).addCallback(
any(ConfigurationController.ConfigurationListener.class));
}
@Test
public void initCompatUI_registersCallbacks() {
mWMShell.initCompatUi(mCompatUI);