Remove ShellInit/ShellCommandHandler interfaces to SysUI

- SysUI now calls init/commands/dump via the ShellController interface
- Move ShellInit/ShellCommandHandler into the sysui package since it's
  only called on sysui startup

Test: atest WMShellUnitTests
Test: atest SystemUITests
Bug: 238217847
Change-Id: I7b05dbab7648cb8a8c6f9381b0b5f545ed3398f1
This commit is contained in:
Winson Chung
2022-07-20 22:23:24 +00:00
parent 531b63c1a6
commit 98f15cc9ea
13 changed files with 128 additions and 184 deletions

View File

@@ -1,39 +0,0 @@
/*
* Copyright (C) 2019 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;
import com.android.wm.shell.common.annotations.ExternalThread;
import java.io.PrintWriter;
/**
* An entry point into the shell for dumping shell internal state and running adb commands.
*
* Use with {@code adb shell dumpsys activity service SystemUIService WMShell ...}.
*/
@ExternalThread
public interface ShellCommandHandler {
/**
* Dumps the shell state.
*/
void dump(PrintWriter pw);
/**
* Handles a shell command.
*/
boolean handleCommand(final String[] args, PrintWriter pw);
}

View File

@@ -1,30 +0,0 @@
/*
* Copyright (C) 2019 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;
import com.android.wm.shell.common.annotations.ExternalThread;
/**
* An entry point into the shell for initializing shell internal state.
*/
@ExternalThread
public interface ShellInit {
/**
* Initializes the shell state.
*/
void init();
}

View File

@@ -29,10 +29,8 @@ import com.android.internal.logging.UiEventLogger;
import com.android.launcher3.icons.IconProvider;
import com.android.wm.shell.RootDisplayAreaOrganizer;
import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
import com.android.wm.shell.ShellCommandHandler;
import com.android.wm.shell.ShellCommandHandlerImpl;
import com.android.wm.shell.ShellInit;
import com.android.wm.shell.ShellInitImpl;
import com.android.wm.shell.sysui.ShellCommandHandler;
import com.android.wm.shell.sysui.ShellInit;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.TaskViewFactory;
import com.android.wm.shell.TaskViewFactoryController;
@@ -624,13 +622,9 @@ public abstract class WMShellBaseModule {
@WMSingleton
@Provides
static ShellInit provideShellInit(ShellInitImpl impl) {
return impl.asShellInit();
}
@WMSingleton
@Provides
static ShellInitImpl provideShellInitImpl(DisplayController displayController,
static ShellInit provideShellInitImpl(
ShellController shellController,
DisplayController displayController,
DisplayImeController displayImeController,
DisplayInsetsController displayInsetsController,
DragAndDropController dragAndDropController,
@@ -648,7 +642,8 @@ public abstract class WMShellBaseModule {
Transitions transitions,
StartingWindowController startingWindow,
@ShellMainThread ShellExecutor mainExecutor) {
return new ShellInitImpl(displayController,
return new ShellInit(shellController,
displayController,
displayImeController,
displayInsetsController,
dragAndDropController,
@@ -668,19 +663,10 @@ public abstract class WMShellBaseModule {
mainExecutor);
}
/**
* Note, this is only optional because we currently pass this to the SysUI component scope and
* for non-primary users, we may inject a null-optional for that dependency.
*/
@WMSingleton
@Provides
static Optional<ShellCommandHandler> provideShellCommandHandler(ShellCommandHandlerImpl impl) {
return Optional.of(impl.asShellCommandHandler());
}
@WMSingleton
@Provides
static ShellCommandHandlerImpl provideShellCommandHandlerImpl(
static ShellCommandHandler provideShellCommandHandlerImpl(
ShellController shellController,
ShellTaskOrganizer shellTaskOrganizer,
KidsModeTaskOrganizer kidsModeTaskOrganizer,
Optional<SplitScreenController> splitScreenOptional,
@@ -689,9 +675,9 @@ public abstract class WMShellBaseModule {
Optional<HideDisplayCutoutController> hideDisplayCutout,
Optional<RecentTasksController> recentTasksOptional,
@ShellMainThread ShellExecutor mainExecutor) {
return new ShellCommandHandlerImpl(shellTaskOrganizer, kidsModeTaskOrganizer,
splitScreenOptional, pipOptional, oneHandedOptional, hideDisplayCutout,
recentTasksOptional, mainExecutor);
return new ShellCommandHandler(shellController, shellTaskOrganizer,
kidsModeTaskOrganizer, splitScreenOptional, pipOptional, oneHandedOptional,
hideDisplayCutout, recentTasksOptional, mainExecutor);
}
@WMSingleton

View File

@@ -14,10 +14,11 @@
* limitations under the License.
*/
package com.android.wm.shell;
package com.android.wm.shell.sysui;
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT;
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;
@@ -34,8 +35,8 @@ import java.util.Optional;
*
* Use with {@code adb shell dumpsys activity service SystemUIService WMShell ...}.
*/
public final class ShellCommandHandlerImpl {
private static final String TAG = ShellCommandHandlerImpl.class.getSimpleName();
public final class ShellCommandHandler {
private static final String TAG = ShellCommandHandler.class.getSimpleName();
private final Optional<SplitScreenController> mSplitScreenOptional;
private final Optional<Pip> mPipOptional;
@@ -45,9 +46,9 @@ public final class ShellCommandHandlerImpl {
private final ShellTaskOrganizer mShellTaskOrganizer;
private final KidsModeTaskOrganizer mKidsModeTaskOrganizer;
private final ShellExecutor mMainExecutor;
private final HandlerImpl mImpl = new HandlerImpl();
public ShellCommandHandlerImpl(
public ShellCommandHandler(
ShellController shellController,
ShellTaskOrganizer shellTaskOrganizer,
KidsModeTaskOrganizer kidsModeTaskOrganizer,
Optional<SplitScreenController> splitScreenOptional,
@@ -64,14 +65,12 @@ public final class ShellCommandHandlerImpl {
mOneHandedOptional = oneHandedOptional;
mHideDisplayCutout = hideDisplayCutout;
mMainExecutor = mainExecutor;
}
public ShellCommandHandler asShellCommandHandler() {
return mImpl;
// TODO(238217847): To be removed once the command handler dependencies are inverted
shellController.setShellCommandHandler(this);
}
/** Dumps WM Shell internal state. */
private void dump(PrintWriter pw) {
public void dump(PrintWriter pw) {
mShellTaskOrganizer.dump(pw, "");
pw.println();
pw.println();
@@ -91,7 +90,7 @@ public final class ShellCommandHandlerImpl {
/** Returns {@code true} if command was found and executed. */
private boolean handleCommand(final String[] args, PrintWriter pw) {
public boolean handleCommand(final String[] args, PrintWriter pw) {
if (args.length < 2) {
// Argument at position 0 is "WMShell".
return false;
@@ -164,28 +163,4 @@ public final class ShellCommandHandlerImpl {
pw.println(" Sets the position of the side-stage.");
return true;
}
private class HandlerImpl implements ShellCommandHandler {
@Override
public void dump(PrintWriter pw) {
try {
mMainExecutor.executeBlocking(() -> ShellCommandHandlerImpl.this.dump(pw));
} catch (InterruptedException e) {
throw new RuntimeException("Failed to dump the Shell in 2s", e);
}
}
@Override
public boolean handleCommand(String[] args, PrintWriter pw) {
try {
boolean[] result = new boolean[1];
mMainExecutor.executeBlocking(() -> {
result[0] = ShellCommandHandlerImpl.this.handleCommand(args, pw);
});
return result[0];
} catch (InterruptedException e) {
throw new RuntimeException("Failed to handle Shell command in 2s", e);
}
}
}
}

View File

@@ -47,6 +47,9 @@ public class ShellController {
private final ShellExecutor mMainExecutor;
private final ShellInterfaceImpl mImpl = new ShellInterfaceImpl();
private ShellInit mShellInit;
private ShellCommandHandler mShellCommandHandler;
private final CopyOnWriteArrayList<ConfigurationChangeListener> mConfigChangeListeners =
new CopyOnWriteArrayList<>();
private final CopyOnWriteArrayList<KeyguardChangeListener> mKeyguardChangeListeners =
@@ -65,6 +68,24 @@ public class ShellController {
return mImpl;
}
/**
* Sets the init handler to call back to.
* TODO(238217847): This is only exposed this way until we can remove the dependencies from the
* init handler to other classes.
*/
public void setShellInit(ShellInit shellInit) {
mShellInit = shellInit;
}
/**
* 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.
@@ -164,6 +185,38 @@ public class ShellController {
*/
@ExternalThread
private class ShellInterfaceImpl implements ShellInterface {
@Override
public void onInit() {
try {
mMainExecutor.executeBlocking(() -> mShellInit.init());
} catch (InterruptedException e) {
throw new RuntimeException("Failed to initialize the Shell in 2s", e);
}
}
@Override
public void dump(PrintWriter pw) {
try {
mMainExecutor.executeBlocking(() -> mShellCommandHandler.dump(pw));
} catch (InterruptedException e) {
throw new RuntimeException("Failed to dump the Shell in 2s", e);
}
}
@Override
public boolean handleCommand(String[] args, PrintWriter pw) {
try {
boolean[] result = new boolean[1];
mMainExecutor.executeBlocking(() -> {
result[0] = mShellCommandHandler.handleCommand(args, pw);
});
return result[0];
} catch (InterruptedException e) {
throw new RuntimeException("Failed to handle Shell command in 2s", e);
}
}
@Override
public void onConfigurationChanged(Configuration newConfiguration) {
mMainExecutor.execute(() ->

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.android.wm.shell;
package com.android.wm.shell.sysui;
import static com.android.wm.shell.ShellTaskOrganizer.TASK_LISTENER_TYPE_FULLSCREEN;
import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_INIT;
@@ -26,13 +26,13 @@ import android.util.Pair;
import androidx.annotation.VisibleForTesting;
import com.android.internal.protolog.common.ProtoLog;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.activityembedding.ActivityEmbeddingController;
import com.android.wm.shell.bubbles.BubbleController;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.DisplayImeController;
import com.android.wm.shell.common.DisplayInsetsController;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.annotations.ExternalThread;
import com.android.wm.shell.draganddrop.DragAndDropController;
import com.android.wm.shell.freeform.FreeformTaskListener;
import com.android.wm.shell.fullscreen.FullscreenTaskListener;
@@ -53,8 +53,8 @@ import java.util.Optional;
* The entry point implementation into the shell for initializing shell internal state. Classes
* which need to setup on start should inject an instance of this class and add an init callback.
*/
public class ShellInitImpl {
private static final String TAG = ShellInitImpl.class.getSimpleName();
public class ShellInit {
private static final String TAG = ShellInit.class.getSimpleName();
private final DisplayController mDisplayController;
private final DisplayImeController mDisplayImeController;
@@ -75,12 +75,12 @@ public class ShellInitImpl {
private final Optional<RecentTasksController> mRecentTasks;
private final Optional<ActivityEmbeddingController> mActivityEmbeddingOptional;
private final InitImpl mImpl = new InitImpl();
// An ordered list of init callbacks to be made once shell is first started
private final ArrayList<Pair<String, Runnable>> mInitCallbacks = new ArrayList<>();
private boolean mHasInitialized;
public ShellInitImpl(
public ShellInit(
ShellController shellController,
DisplayController displayController,
DisplayImeController displayImeController,
DisplayInsetsController displayInsetsController,
@@ -117,10 +117,8 @@ public class ShellInitImpl {
mTransitions = transitions;
mMainExecutor = mainExecutor;
mStartingWindow = startingWindow;
}
public ShellInit asShellInit() {
return mImpl;
// TODO(238217847): To be removed once the init dependencies are inverted
shellController.setShellInit(this);
}
private void legacyInit() {
@@ -210,16 +208,4 @@ public class ShellInitImpl {
mHasInitialized = true;
}
@ExternalThread
private class InitImpl implements ShellInit {
@Override
public void init() {
try {
mMainExecutor.executeBlocking(ShellInitImpl.this::init);
} catch (InterruptedException e) {
throw new RuntimeException("Failed to initialize the Shell in 2s", e);
}
}
}
}

View File

@@ -18,14 +18,31 @@ package com.android.wm.shell.sysui;
import android.content.res.Configuration;
import java.io.PrintWriter;
/**
* 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 {
/**
* Initializes the shell state.
*/
default void onInit() {}
/**
* Dumps the shell state.
*/
default void dump(PrintWriter pw) {}
/**
* Handles a shell command.
*/
default boolean handleCommand(final String[] args, PrintWriter pw) {
return false;
}
/**
* Notifies the Shell that the configuration has changed.
*/

View File

@@ -38,6 +38,8 @@ 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.startingsurface.StartingWindowController;
import com.android.wm.shell.sysui.ShellController;
import com.android.wm.shell.sysui.ShellInit;
import com.android.wm.shell.transition.Transitions;
import com.android.wm.shell.unfold.UnfoldAnimationController;
import com.android.wm.shell.unfold.UnfoldTransitionHandler;
@@ -54,8 +56,9 @@ import java.util.Optional;
@SmallTest
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper(setAsMainLooper = true)
public class ShellInitImplTest extends ShellTestCase {
public class ShellInitTest extends ShellTestCase {
@Mock private ShellController mShellController;
@Mock private DisplayController mDisplayController;
@Mock private DisplayImeController mDisplayImeController;
@Mock private DisplayInsetsController mDisplayInsetsController;
@@ -75,12 +78,12 @@ public class ShellInitImplTest extends ShellTestCase {
@Mock private StartingWindowController mStartingWindow;
@Mock private ShellExecutor mMainExecutor;
private ShellInitImpl mImpl;
private ShellInit mImpl;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mImpl = new ShellInitImpl(mDisplayController, mDisplayImeController,
mImpl = new ShellInit(mShellController, mDisplayController, mDisplayImeController,
mDisplayInsetsController, mDragAndDropController, mShellTaskOrganizer,
mKidsModeTaskOrganizer, mBubblesOptional, mSplitScreenOptional,
mPipTouchHandlerOptional, mFullscreenTaskListener, mUnfoldAnimationController,

View File

@@ -96,7 +96,6 @@ public abstract class SystemUIInitializer {
.setSplitScreen(mWMComponent.getSplitScreen())
.setOneHanded(mWMComponent.getOneHanded())
.setBubbles(mWMComponent.getBubbles())
.setShellCommandHandler(mWMComponent.getShellCommandHandler())
.setTaskViewFactory(mWMComponent.getTaskViewFactory())
.setTransitions(mWMComponent.getTransitions())
.setStartingSurface(mWMComponent.getStartingSurface())
@@ -112,7 +111,6 @@ public abstract class SystemUIInitializer {
.setSplitScreen(Optional.ofNullable(null))
.setOneHanded(Optional.ofNullable(null))
.setBubbles(Optional.ofNullable(null))
.setShellCommandHandler(Optional.ofNullable(null))
.setTaskViewFactory(Optional.ofNullable(null))
.setTransitions(new ShellTransitions() {})
.setDisplayAreaHelper(Optional.ofNullable(null))

View File

@@ -37,7 +37,6 @@ import com.android.systemui.unfold.FoldStateLoggingProvider;
import com.android.systemui.unfold.SysUIUnfoldComponent;
import com.android.systemui.unfold.UnfoldLatencyTracker;
import com.android.systemui.unfold.util.NaturalRotationUnfoldProgressProvider;
import com.android.wm.shell.ShellCommandHandler;
import com.android.wm.shell.TaskViewFactory;
import com.android.wm.shell.back.BackAnimation;
import com.android.wm.shell.bubbles.Bubbles;
@@ -95,9 +94,6 @@ public interface SysUIComponent {
@BindsInstance
Builder setTaskViewFactory(Optional<TaskViewFactory> t);
@BindsInstance
Builder setShellCommandHandler(Optional<ShellCommandHandler> shellDump);
@BindsInstance
Builder setTransitions(ShellTransitions t);

View File

@@ -23,8 +23,8 @@ import androidx.annotation.Nullable;
import com.android.systemui.SystemUIInitializerFactory;
import com.android.systemui.tv.TvWMComponent;
import com.android.wm.shell.ShellCommandHandler;
import com.android.wm.shell.ShellInit;
import com.android.wm.shell.sysui.ShellCommandHandler;
import com.android.wm.shell.sysui.ShellInit;
import com.android.wm.shell.TaskViewFactory;
import com.android.wm.shell.back.BackAnimation;
import com.android.wm.shell.bubbles.Bubbles;
@@ -75,17 +75,24 @@ public interface WMComponent {
* Initializes all the WMShell components before starting any of the SystemUI components.
*/
default void init() {
getShellInit().init();
// TODO(238217847): To be removed once the dependencies are inverted and ShellController can
// inject these classes directly, otherwise, it's currently needed to ensure that these
// classes are created and set on the controller before onInit() is called
getShellInit();
getShellCommandHandler();
getShell().onInit();
}
@WMSingleton
ShellInterface getShell();
// TODO(238217847): To be removed once ShellController can inject ShellInit directly
@WMSingleton
ShellInit getShellInit();
// TODO(238217847): To be removed once ShellController can inject ShellCommandHandler directly
@WMSingleton
Optional<ShellCommandHandler> getShellCommandHandler();
@WMSingleton
ShellInterface getShell();
ShellCommandHandler getShellCommandHandler();
@WMSingleton
Optional<OneHanded> getOneHanded();

View File

@@ -54,7 +54,6 @@ import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.statusbar.policy.UserInfoController;
import com.android.systemui.tracing.ProtoTracer;
import com.android.systemui.tracing.nano.SystemUiTraceProto;
import com.android.wm.shell.ShellCommandHandler;
import com.android.wm.shell.nano.WmShellTraceProto;
import com.android.wm.shell.onehanded.OneHanded;
import com.android.wm.shell.onehanded.OneHandedEventCallback;
@@ -107,7 +106,6 @@ public final class WMShell extends CoreStartable
private final Optional<Pip> mPipOptional;
private final Optional<SplitScreen> mSplitScreenOptional;
private final Optional<OneHanded> mOneHandedOptional;
private final Optional<ShellCommandHandler> mShellCommandHandler;
private final CommandQueue mCommandQueue;
private final ConfigurationController mConfigurationController;
@@ -130,7 +128,6 @@ public final class WMShell extends CoreStartable
Optional<Pip> pipOptional,
Optional<SplitScreen> splitScreenOptional,
Optional<OneHanded> oneHandedOptional,
Optional<ShellCommandHandler> shellCommandHandler,
CommandQueue commandQueue,
ConfigurationController configurationController,
KeyguardStateController keyguardStateController,
@@ -154,7 +151,6 @@ public final class WMShell extends CoreStartable
mOneHandedOptional = oneHandedOptional;
mWakefulnessLifecycle = wakefulnessLifecycle;
mProtoTracer = protoTracer;
mShellCommandHandler = shellCommandHandler;
mUserInfoController = userInfoController;
mSysUiMainExecutor = sysUiMainExecutor;
}
@@ -325,8 +321,7 @@ public final class WMShell extends CoreStartable
@Override
public void dump(PrintWriter pw, String[] args) {
// Handle commands if provided
if (mShellCommandHandler.isPresent()
&& mShellCommandHandler.get().handleCommand(args, pw)) {
if (mShell.handleCommand(args, pw)) {
return;
}
// Handle logging commands if provided
@@ -334,8 +329,7 @@ public final class WMShell extends CoreStartable
return;
}
// Dump WMShell stuff here if no commands were handled
mShellCommandHandler.ifPresent(
shellCommandHandler -> shellCommandHandler.dump(pw));
mShell.dump(pw);
}
@Override

View File

@@ -33,7 +33,6 @@ import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.statusbar.policy.UserInfoController;
import com.android.systemui.tracing.ProtoTracer;
import com.android.wm.shell.ShellCommandHandler;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.onehanded.OneHanded;
import com.android.wm.shell.onehanded.OneHandedEventCallback;
@@ -73,7 +72,6 @@ public class WMShellTest extends SysuiTestCase {
@Mock OneHanded mOneHanded;
@Mock WakefulnessLifecycle mWakefulnessLifecycle;
@Mock ProtoTracer mProtoTracer;
@Mock ShellCommandHandler mShellCommandHandler;
@Mock UserInfoController mUserInfoController;
@Mock ShellExecutor mSysUiMainExecutor;
@@ -82,10 +80,10 @@ public class WMShellTest extends SysuiTestCase {
MockitoAnnotations.initMocks(this);
mWMShell = new WMShell(mContext, mShellInterface, Optional.of(mPip),
Optional.of(mSplitScreen), Optional.of(mOneHanded),
Optional.of(mShellCommandHandler), mCommandQueue, mConfigurationController,
mKeyguardStateController, mKeyguardUpdateMonitor, mScreenLifecycle, mSysUiState,
mProtoTracer, mWakefulnessLifecycle, mUserInfoController, mSysUiMainExecutor);
Optional.of(mSplitScreen), Optional.of(mOneHanded), mCommandQueue,
mConfigurationController, mKeyguardStateController, mKeyguardUpdateMonitor,
mScreenLifecycle, mSysUiState, mProtoTracer, mWakefulnessLifecycle,
mUserInfoController, mSysUiMainExecutor);
}
@Test