diff --git a/libs/WindowManager/Shell/Android.bp b/libs/WindowManager/Shell/Android.bp index 9ee52ccaf3575..82573b2b9acc4 100644 --- a/libs/WindowManager/Shell/Android.bp +++ b/libs/WindowManager/Shell/Android.bp @@ -44,6 +44,7 @@ filegroup { srcs: [ "src/com/android/wm/shell/util/**/*.java", "src/com/android/wm/shell/common/split/SplitScreenConstants.java", + "src/com/android/wm/shell/sysui/ShellSharedConstants.java", ], path: "src", } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimation.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimation.java index 86f9d5b534f4d..8cbe44b15e422 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimation.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimation.java @@ -28,13 +28,6 @@ import com.android.wm.shell.common.annotations.ExternalThread; @ExternalThread public interface BackAnimation { - /** - * Returns a binder that can be passed to an external process to update back animations. - */ - default IBackAnimation createExternalInterface() { - return null; - } - /** * Called when a {@link MotionEvent} is generated by a back gesture. * diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java index 33ecdd88fad31..938189fc8a88a 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java @@ -21,6 +21,7 @@ import static android.view.RemoteAnimationTarget.MODE_OPENING; import static com.android.wm.shell.common.ExecutorUtils.executeRemoteCallWithTaskPermission; import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_BACK_PREVIEW; +import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_BACK_ANIMATION; import android.annotation.NonNull; import android.annotation.Nullable; @@ -57,10 +58,12 @@ import android.window.IOnBackInvokedCallback; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.protolog.common.ProtoLog; +import com.android.wm.shell.common.ExternalInterfaceBinder; import com.android.wm.shell.common.RemoteCallable; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.annotations.ShellBackgroundThread; import com.android.wm.shell.common.annotations.ShellMainThread; +import com.android.wm.shell.sysui.ShellController; import com.android.wm.shell.sysui.ShellInit; import java.util.concurrent.atomic.AtomicBoolean; @@ -105,6 +108,7 @@ public class BackAnimationController implements RemoteCallable controller.onBackToLauncherAnimationFinished()); } - void invalidate() { + @Override + public void invalidate() { mController = null; } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/ExternalInterfaceBinder.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/ExternalInterfaceBinder.java new file mode 100644 index 0000000000000..aa5b0cb628e1a --- /dev/null +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/ExternalInterfaceBinder.java @@ -0,0 +1,34 @@ +/* + * 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.common; + +import android.os.IBinder; + +/** + * An interface for binders which can be registered to be sent to other processes. + */ +public interface ExternalInterfaceBinder { + /** + * Invalidates this binder (detaches it from the controller it would call). + */ + void invalidate(); + + /** + * Returns the IBinder to send. + */ + IBinder asBinder(); +} diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java index 7d0c4bd19a434..28a19597bd370 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java @@ -261,13 +261,14 @@ public abstract class WMShellBaseModule { static Optional provideBackAnimationController( Context context, ShellInit shellInit, + ShellController shellController, @ShellMainThread ShellExecutor shellExecutor, @ShellBackgroundThread Handler backgroundHandler ) { if (BackAnimationController.IS_ENABLED) { return Optional.of( - new BackAnimationController(shellInit, shellExecutor, backgroundHandler, - context)); + new BackAnimationController(shellInit, shellController, shellExecutor, + backgroundHandler, context)); } return Optional.empty(); } @@ -471,6 +472,7 @@ public abstract class WMShellBaseModule { static Optional provideRecentTasksController( Context context, ShellInit shellInit, + ShellController shellController, ShellCommandHandler shellCommandHandler, TaskStackListenerImpl taskStackListener, ActivityTaskManager activityTaskManager, @@ -478,9 +480,9 @@ public abstract class WMShellBaseModule { @ShellMainThread ShellExecutor mainExecutor ) { return Optional.ofNullable( - RecentTasksController.create(context, shellInit, shellCommandHandler, - taskStackListener, activityTaskManager, desktopModeTaskRepository, - mainExecutor)); + RecentTasksController.create(context, shellInit, shellController, + shellCommandHandler, taskStackListener, activityTaskManager, + desktopModeTaskRepository, mainExecutor)); } // @@ -497,14 +499,15 @@ public abstract class WMShellBaseModule { @Provides static Transitions provideTransitions(Context context, ShellInit shellInit, + ShellController shellController, ShellTaskOrganizer organizer, TransactionPool pool, DisplayController displayController, @ShellMainThread ShellExecutor mainExecutor, @ShellMainThread Handler mainHandler, @ShellAnimationThread ShellExecutor animExecutor) { - return new Transitions(context, shellInit, organizer, pool, displayController, mainExecutor, - mainHandler, animExecutor); + return new Transitions(context, shellInit, shellController, organizer, pool, + displayController, mainExecutor, mainHandler, animExecutor); } @WMSingleton @@ -621,13 +624,15 @@ public abstract class WMShellBaseModule { @WMSingleton @Provides - static StartingWindowController provideStartingWindowController(Context context, + static StartingWindowController provideStartingWindowController( + Context context, ShellInit shellInit, + ShellController shellController, ShellTaskOrganizer shellTaskOrganizer, @ShellSplashscreenThread ShellExecutor splashScreenExecutor, StartingWindowTypeAlgorithm startingWindowTypeAlgorithm, IconProvider iconProvider, TransactionPool pool) { - return new StartingWindowController(context, shellInit, shellTaskOrganizer, + return new StartingWindowController(context, shellInit, shellController, shellTaskOrganizer, splashScreenExecutor, startingWindowTypeAlgorithm, iconProvider, pool); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java index 461d7dcf30ad3..1ec98d3e94f38 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java @@ -598,7 +598,9 @@ public abstract class WMShellModule { @WMSingleton @Provides @DynamicOverride - static DesktopModeController provideDesktopModeController(Context context, ShellInit shellInit, + static DesktopModeController provideDesktopModeController(Context context, + ShellInit shellInit, + ShellController shellController, ShellTaskOrganizer shellTaskOrganizer, RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer, Transitions transitions, @@ -606,7 +608,7 @@ public abstract class WMShellModule { @ShellMainThread Handler mainHandler, @ShellMainThread ShellExecutor mainExecutor ) { - return new DesktopModeController(context, shellInit, shellTaskOrganizer, + return new DesktopModeController(context, shellInit, shellController, shellTaskOrganizer, rootTaskDisplayAreaOrganizer, transitions, desktopModeTaskRepository, mainHandler, mainExecutor); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopMode.java b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopMode.java index ff3be38d09e1b..44a467ffcf3d4 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopMode.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopMode.java @@ -23,9 +23,4 @@ import com.android.wm.shell.common.annotations.ExternalThread; */ @ExternalThread public interface DesktopMode { - - /** Returns a binder that can be passed to an external process to manipulate DesktopMode. */ - default IDesktopMode createExternalInterface() { - return null; - } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeController.java index dc7ed15dbe3a1..b96facf4c46e6 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeController.java @@ -23,6 +23,7 @@ import static android.view.WindowManager.TRANSIT_OPEN; import static com.android.wm.shell.common.ExecutorUtils.executeRemoteCallWithTaskPermission; import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE; +import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_DESKTOP_MODE; import android.app.ActivityManager.RunningTaskInfo; import android.app.WindowConfiguration; @@ -48,10 +49,12 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.protolog.common.ProtoLog; import com.android.wm.shell.RootTaskDisplayAreaOrganizer; import com.android.wm.shell.ShellTaskOrganizer; +import com.android.wm.shell.common.ExternalInterfaceBinder; import com.android.wm.shell.common.RemoteCallable; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.annotations.ExternalThread; import com.android.wm.shell.common.annotations.ShellMainThread; +import com.android.wm.shell.sysui.ShellController; import com.android.wm.shell.sysui.ShellInit; import com.android.wm.shell.transition.Transitions; @@ -65,15 +68,18 @@ public class DesktopModeController implements RemoteCallable` -interface that the `Controller` implements and handles on the main Shell thread. +interface that the `Controller` implements and handles on the main Shell thread +(see [SysUI/Shell threading](threading.md)). In addition, because components accessible to SysUI injection are explicitly listed, you'll have to add an appropriate method in `WMComponent` to get the interface and update the `Builder` in `SysUIComponent` to take the interface so it can be injected in SysUI code. The binding between the two is done in `SystemUIFactory#init()` which will need to be updated as well. +Specifically, to support calling into a controller from an external process (like Launcher): +- Create an implementation of the external interface within the controller +- Have all incoming calls post to the main shell thread (inject @ShellMainThread Executor into the + controller if needed) +- Note that callbacks into SysUI should take an associated executor to call back on + ### Launcher accessible components Because Launcher is not a part of SystemUI and is a separate process, exposing controllers to Launcher requires a new AIDL interface to be created and implemented by the controller. The implementation of the stub interface in the controller otherwise behaves similar to the interface to SysUI where it posts the work to the main Shell thread. +Specifically, to support calling into a controller from an external process (like Launcher): +- Create an implementation of the interface binder's `Stub` class within the controller, have it + extend `ExternalInterfaceBinder` and implement `invalidate()` to ensure it doesn't hold long + references to the outer controller +- Make the controller implement `RemoteCallable`, and have all incoming calls use one of + the `ExecutorUtils.executeRemoteCallWithTaskPermission()` calls to verify the caller's identity + and ensure the call happens on the main shell thread and not the binder thread +- Inject `ShellController` and add the instance of the implementation as external interface +- In Launcher, update `TouchInteractionService` to pass the interface to `SystemUIProxy`, and then + call the SystemUIProxy method as needed in that code + ### Component initialization To initialize the component: - On the Shell side, you potentially need to do two things to initialize the component: @@ -64,8 +82,9 @@ adb logcat *:S WindowManagerShell ### General Do's & Dont's Do: -- Do add unit tests for all new components -- Do keep controllers simple and break them down as needed +- Add unit tests for all new components +- Keep controllers simple and break them down as needed +- Any SysUI callbacks should also take an associated executor to run the callback on Don't: - **Don't** do initialization in the constructor, only do initialization in the init callbacks. diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/floating/FloatingTasks.java b/libs/WindowManager/Shell/src/com/android/wm/shell/floating/FloatingTasks.java index 935666026bf42..f86d467360f9b 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/floating/FloatingTasks.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/floating/FloatingTasks.java @@ -33,9 +33,4 @@ public interface FloatingTasks { * - If there is a floating task for this intent, and it's not stashed, this stashes it. */ void showOrSetStashed(Intent intent); - - /** Returns a binder that can be passed to an external process to manipulate FloatingTasks. */ - default IFloatingTasks createExternalInterface() { - return null; - } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/floating/FloatingTasksController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/floating/FloatingTasksController.java index 67552991869b8..b3c09d32055bd 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/floating/FloatingTasksController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/floating/FloatingTasksController.java @@ -21,6 +21,7 @@ import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_M import static com.android.wm.shell.common.ExecutorUtils.executeRemoteCallWithTaskPermission; import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_FLOATING_APPS; +import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_FLOATING_TASKS; import android.annotation.Nullable; import android.content.Context; @@ -40,6 +41,7 @@ import com.android.internal.protolog.common.ProtoLog; import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.TaskViewTransitions; import com.android.wm.shell.bubbles.BubbleController; +import com.android.wm.shell.common.ExternalInterfaceBinder; import com.android.wm.shell.common.RemoteCallable; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.SyncTransactionQueue; @@ -136,11 +138,13 @@ public class FloatingTasksController implements RemoteCallable FloatingTasksController.this.showOrSetStashed(intent)); } - - @Override - public IFloatingTasks createExternalInterface() { - if (mIFloatingTasks != null) { - mIFloatingTasks.invalidate(); - } - mIFloatingTasks = new IFloatingTasksImpl(FloatingTasksController.this); - return mIFloatingTasks; - } } /** * The interface for calls from outside the host process. */ @BinderThread - private static class IFloatingTasksImpl extends IFloatingTasks.Stub { + private static class IFloatingTasksImpl extends IFloatingTasks.Stub + implements ExternalInterfaceBinder { private FloatingTasksController mController; IFloatingTasksImpl(FloatingTasksController controller) { @@ -443,7 +441,8 @@ public class FloatingTasksController implements RemoteCallable, mShellController.addConfigurationChangeListener(this); mShellController.addKeyguardChangeListener(this); mShellController.addUserChangeListener(this); + mShellController.addExternalInterface(KEY_EXTRA_SHELL_ONE_HANDED, + this::createExternalInterface, this); } public OneHanded asOneHanded() { return mImpl; } + private ExternalInterfaceBinder createExternalInterface() { + return new IOneHandedImpl(this); + } + @Override public Context getContext() { return mContext; @@ -709,17 +717,6 @@ public class OneHandedController implements RemoteCallable, */ @ExternalThread private class OneHandedImpl implements OneHanded { - private IOneHandedImpl mIOneHanded; - - @Override - public IOneHanded createExternalInterface() { - if (mIOneHanded != null) { - mIOneHanded.invalidate(); - } - mIOneHanded = new IOneHandedImpl(OneHandedController.this); - return mIOneHanded; - } - @Override public void startOneHanded() { mMainExecutor.execute(() -> { @@ -767,7 +764,7 @@ public class OneHandedController implements RemoteCallable, * The interface for calls from outside the host process. */ @BinderThread - private static class IOneHandedImpl extends IOneHanded.Stub { + private static class IOneHandedImpl extends IOneHanded.Stub implements ExternalInterfaceBinder { private OneHandedController mController; IOneHandedImpl(OneHandedController controller) { @@ -777,7 +774,8 @@ public class OneHandedController implements RemoteCallable, /** * Invalidates this instance, preventing future calls from updating the controller. */ - void invalidate() { + @Override + public void invalidate() { mController = null; } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/Pip.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/Pip.java index 72b9dd37ac7da..f34d2a827e69c 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/Pip.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/Pip.java @@ -27,14 +27,6 @@ import java.util.function.Consumer; */ @ExternalThread public interface Pip { - - /** - * Returns a binder that can be passed to an external process to manipulate PIP. - */ - default IPip createExternalInterface() { - return null; - } - /** * Expand PIP, it's possible that specific request to activate the window via Alt-tab. */ diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java index 3345b1b2d0e80..a918559d897e6 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java @@ -33,6 +33,7 @@ import static com.android.wm.shell.pip.PipAnimationController.TRANSITION_DIRECTI import static com.android.wm.shell.pip.PipAnimationController.TRANSITION_DIRECTION_TO_PIP; import static com.android.wm.shell.pip.PipAnimationController.TRANSITION_DIRECTION_USER_RESIZE; import static com.android.wm.shell.pip.PipAnimationController.isOutPipDirection; +import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_PIP; import android.app.ActivityManager; import android.app.ActivityTaskManager; @@ -68,6 +69,7 @@ import com.android.wm.shell.common.DisplayChangeController; import com.android.wm.shell.common.DisplayController; import com.android.wm.shell.common.DisplayInsetsController; import com.android.wm.shell.common.DisplayLayout; +import com.android.wm.shell.common.ExternalInterfaceBinder; import com.android.wm.shell.common.RemoteCallable; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.SingleInstanceRemoteListener; @@ -632,6 +634,12 @@ public class PipController implements PipTransitionController.PipTransitionCallb mShellController.addConfigurationChangeListener(this); mShellController.addKeyguardChangeListener(this); mShellController.addUserChangeListener(this); + mShellController.addExternalInterface(KEY_EXTRA_SHELL_PIP, + this::createExternalInterface, this); + } + + private ExternalInterfaceBinder createExternalInterface() { + return new IPipImpl(this); } @Override @@ -1040,17 +1048,6 @@ public class PipController implements PipTransitionController.PipTransitionCallb * The interface for calls from outside the Shell, within the host process. */ private class PipImpl implements Pip { - private IPipImpl mIPip; - - @Override - public IPip createExternalInterface() { - if (mIPip != null) { - mIPip.invalidate(); - } - mIPip = new IPipImpl(PipController.this); - return mIPip; - } - @Override public void expandPip() { mMainExecutor.execute(() -> { @@ -1098,7 +1095,7 @@ public class PipController implements PipTransitionController.PipTransitionCallb * The interface for calls from outside the host process. */ @BinderThread - private static class IPipImpl extends IPip.Stub { + private static class IPipImpl extends IPip.Stub implements ExternalInterfaceBinder { private PipController mController; private final SingleInstanceRemoteListener mListener; @@ -1129,7 +1126,8 @@ public class PipController implements PipTransitionController.PipTransitionCallb /** * Invalidates this instance, preventing future calls from updating the controller. */ - void invalidate() { + @Override + public void invalidate() { mController = null; } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasks.java b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasks.java index 2a625524b48b6..069066e4bd49d 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasks.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasks.java @@ -28,13 +28,6 @@ import java.util.function.Consumer; */ @ExternalThread public interface RecentTasks { - /** - * Returns a binder that can be passed to an external process to fetch recent tasks. - */ - default IRecentTasks createExternalInterface() { - return null; - } - /** * Gets the set of recent tasks. */ diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java index 02b5a35f653b5..08f3db65e62fa 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java @@ -20,6 +20,7 @@ import static android.app.ActivityTaskManager.INVALID_TASK_ID; import static android.content.pm.PackageManager.FEATURE_PC; import static com.android.wm.shell.common.ExecutorUtils.executeRemoteCallWithTaskPermission; +import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_RECENT_TASKS; import android.app.ActivityManager; import android.app.ActivityTaskManager; @@ -37,6 +38,7 @@ import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import com.android.internal.protolog.common.ProtoLog; +import com.android.wm.shell.common.ExternalInterfaceBinder; import com.android.wm.shell.common.RemoteCallable; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.SingleInstanceRemoteListener; @@ -48,6 +50,7 @@ import com.android.wm.shell.desktopmode.DesktopModeStatus; import com.android.wm.shell.desktopmode.DesktopModeTaskRepository; import com.android.wm.shell.protolog.ShellProtoLogGroup; import com.android.wm.shell.sysui.ShellCommandHandler; +import com.android.wm.shell.sysui.ShellController; import com.android.wm.shell.sysui.ShellInit; import com.android.wm.shell.util.GroupedRecentTaskInfo; import com.android.wm.shell.util.SplitBounds; @@ -69,11 +72,12 @@ public class RecentTasksController implements TaskStackListenerCallback, private static final String TAG = RecentTasksController.class.getSimpleName(); private final Context mContext; + private final ShellController mShellController; private final ShellCommandHandler mShellCommandHandler; private final Optional mDesktopModeTaskRepository; private final ShellExecutor mMainExecutor; private final TaskStackListenerImpl mTaskStackListener; - private final RecentTasks mImpl = new RecentTasksImpl(); + private final RecentTasksImpl mImpl = new RecentTasksImpl(); private final ActivityTaskManager mActivityTaskManager; private IRecentTasksListener mListener; private final boolean mIsDesktopMode; @@ -97,6 +101,7 @@ public class RecentTasksController implements TaskStackListenerCallback, public static RecentTasksController create( Context context, ShellInit shellInit, + ShellController shellController, ShellCommandHandler shellCommandHandler, TaskStackListenerImpl taskStackListener, ActivityTaskManager activityTaskManager, @@ -106,18 +111,20 @@ public class RecentTasksController implements TaskStackListenerCallback, if (!context.getResources().getBoolean(com.android.internal.R.bool.config_hasRecents)) { return null; } - return new RecentTasksController(context, shellInit, shellCommandHandler, taskStackListener, - activityTaskManager, desktopModeTaskRepository, mainExecutor); + return new RecentTasksController(context, shellInit, shellController, shellCommandHandler, + taskStackListener, activityTaskManager, desktopModeTaskRepository, mainExecutor); } RecentTasksController(Context context, ShellInit shellInit, + ShellController shellController, ShellCommandHandler shellCommandHandler, TaskStackListenerImpl taskStackListener, ActivityTaskManager activityTaskManager, Optional desktopModeTaskRepository, ShellExecutor mainExecutor) { mContext = context; + mShellController = shellController; mShellCommandHandler = shellCommandHandler; mActivityTaskManager = activityTaskManager; mIsDesktopMode = mContext.getPackageManager().hasSystemFeature(FEATURE_PC); @@ -131,7 +138,13 @@ public class RecentTasksController implements TaskStackListenerCallback, return mImpl; } + private ExternalInterfaceBinder createExternalInterface() { + return new IRecentTasksImpl(this); + } + private void onInit() { + mShellController.addExternalInterface(KEY_EXTRA_SHELL_RECENT_TASKS, + this::createExternalInterface, this); mShellCommandHandler.addDumpCallback(this::dump, this); mTaskStackListener.addListener(this); mDesktopModeTaskRepository.ifPresent(it -> it.addListener(this)); @@ -366,17 +379,6 @@ public class RecentTasksController implements TaskStackListenerCallback, */ @ExternalThread private class RecentTasksImpl implements RecentTasks { - private IRecentTasksImpl mIRecentTasks; - - @Override - public IRecentTasks createExternalInterface() { - if (mIRecentTasks != null) { - mIRecentTasks.invalidate(); - } - mIRecentTasks = new IRecentTasksImpl(RecentTasksController.this); - return mIRecentTasks; - } - @Override public void getRecentTasks(int maxNum, int flags, int userId, Executor executor, Consumer> callback) { @@ -393,7 +395,8 @@ public class RecentTasksController implements TaskStackListenerCallback, * The interface for calls from outside the host process. */ @BinderThread - private static class IRecentTasksImpl extends IRecentTasks.Stub { + private static class IRecentTasksImpl extends IRecentTasks.Stub + implements ExternalInterfaceBinder { private RecentTasksController mController; private final SingleInstanceRemoteListener mListener; @@ -424,7 +427,8 @@ public class RecentTasksController implements TaskStackListenerCallback, /** * Invalidates this instance, preventing future calls from updating the controller. */ - void invalidate() { + @Override + public void invalidate() { mController = null; } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java index e73b799b7a3d6..d86aadc996e32 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java @@ -70,13 +70,6 @@ public interface SplitScreen { /** Unregisters listener that gets split screen callback. */ void unregisterSplitScreenListener(@NonNull SplitScreenListener listener); - /** - * Returns a binder that can be passed to an external process to manipulate SplitScreen. - */ - default ISplitScreen createExternalInterface() { - return null; - } - /** Called when device waking up finished. */ void onFinishedWakingUp(); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java index d9c2871a1654d..c6a2b8312ebdd 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java @@ -29,6 +29,7 @@ import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSIT import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_UNDEFINED; import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_SIDE; import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_UNDEFINED; +import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_SPLIT_SCREEN; import static com.android.wm.shell.transition.Transitions.ENABLE_SHELL_TRANSITIONS; import android.app.ActivityManager; @@ -71,6 +72,7 @@ import com.android.wm.shell.ShellTaskOrganizer; 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.ExternalInterfaceBinder; import com.android.wm.shell.common.RemoteCallable; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.SingleInstanceRemoteListener; @@ -214,6 +216,10 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, return mImpl; } + private ExternalInterfaceBinder createExternalInterface() { + return new ISplitScreenImpl(this); + } + /** * This will be called after ShellTaskOrganizer has initialized/registered because of the * dependency order. @@ -224,6 +230,8 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, mShellCommandHandler.addCommandCallback("splitscreen", mSplitScreenShellCommandHandler, this); mShellController.addKeyguardChangeListener(this); + mShellController.addExternalInterface(KEY_EXTRA_SHELL_SPLIT_SCREEN, + this::createExternalInterface, this); if (mStageCoordinator == null) { // TODO: Multi-display mStageCoordinator = createStageCoordinator(); @@ -658,7 +666,6 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, */ @ExternalThread private class SplitScreenImpl implements SplitScreen { - private ISplitScreenImpl mISplitScreen; private final ArrayMap mExecutors = new ArrayMap<>(); private final SplitScreen.SplitScreenListener mListener = new SplitScreenListener() { @Override @@ -703,15 +710,6 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, } }; - @Override - public ISplitScreen createExternalInterface() { - if (mISplitScreen != null) { - mISplitScreen.invalidate(); - } - mISplitScreen = new ISplitScreenImpl(SplitScreenController.this); - return mISplitScreen; - } - @Override public void registerSplitScreenListener(SplitScreenListener listener, Executor executor) { if (mExecutors.containsKey(listener)) return; @@ -752,7 +750,8 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, * The interface for calls from outside the host process. */ @BinderThread - private static class ISplitScreenImpl extends ISplitScreen.Stub { + private static class ISplitScreenImpl extends ISplitScreen.Stub + implements ExternalInterfaceBinder { private SplitScreenController mController; private final SingleInstanceRemoteListener mListener; @@ -779,7 +778,8 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, /** * Invalidates this instance, preventing future calls from updating the controller. */ - void invalidate() { + @Override + public void invalidate() { mController = null; } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurface.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurface.java index 76105a39189b7..538bbec2aa2bb 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurface.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurface.java @@ -22,14 +22,6 @@ import android.graphics.Color; * Interface to engage starting window feature. */ public interface StartingSurface { - - /** - * Returns a binder that can be passed to an external process to manipulate starting windows. - */ - default IStartingWindow createExternalInterface() { - return null; - } - /** * Returns the background color for a starting window if existing. */ diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java index 379af21ac9568..0c23f109feaf1 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java @@ -23,6 +23,7 @@ import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_SOLID_COLOR import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_SPLASH_SCREEN; import static com.android.wm.shell.common.ExecutorUtils.executeRemoteCallWithTaskPermission; +import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_STARTING_WINDOW; import android.app.ActivityManager.RunningTaskInfo; import android.app.TaskInfo; @@ -43,10 +44,12 @@ import com.android.internal.annotations.GuardedBy; import com.android.internal.util.function.TriConsumer; import com.android.launcher3.icons.IconProvider; import com.android.wm.shell.ShellTaskOrganizer; +import com.android.wm.shell.common.ExternalInterfaceBinder; import com.android.wm.shell.common.RemoteCallable; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.SingleInstanceRemoteListener; import com.android.wm.shell.common.TransactionPool; +import com.android.wm.shell.sysui.ShellController; import com.android.wm.shell.sysui.ShellInit; /** @@ -76,6 +79,7 @@ public class StartingWindowController implements RemoteCallable mTaskLaunchingCallback; private final StartingSurfaceImpl mImpl = new StartingSurfaceImpl(); private final Context mContext; + private final ShellController mShellController; private final ShellTaskOrganizer mShellTaskOrganizer; private final ShellExecutor mSplashScreenExecutor; /** @@ -86,12 +90,14 @@ public class StartingWindowController implements RemoteCallable mListener; @@ -276,7 +278,8 @@ public class StartingWindowController implements RemoteCallable mUserChangeListeners = new CopyOnWriteArrayList<>(); + private ArrayMap> mExternalInterfaceSuppliers = + new ArrayMap<>(); + // References to the existing interfaces, to be invalidated when they are recreated + private ArrayMap mExternalInterfaces = new ArrayMap<>(); + private Configuration mLastConfiguration; @@ -67,6 +77,11 @@ public class ShellController { mShellInit = shellInit; mShellCommandHandler = shellCommandHandler; mMainExecutor = mainExecutor; + shellInit.addInitCallback(this::onInit, this); + } + + private void onInit() { + mShellCommandHandler.addDumpCallback(this::dump, this); } /** @@ -124,6 +139,47 @@ public class ShellController { mUserChangeListeners.remove(listener); } + /** + * Adds an interface that can be called from a remote process. This method takes a supplier + * because each binder reference is valid for a single process, and in multi-user mode, SysUI + * will request new binder instances for each instance of Launcher that it provides binders + * to. + * + * @param extra the key for the interface, {@see ShellSharedConstants} + * @param binderSupplier the supplier of the binder to pass to the external process + * @param callerInstance the instance of the caller, purely for logging + */ + public void addExternalInterface(String extra, Supplier binderSupplier, + Object callerInstance) { + ProtoLog.v(WM_SHELL_INIT, "Adding external interface from %s with key %s", + callerInstance.getClass().getSimpleName(), extra); + if (mExternalInterfaceSuppliers.containsKey(extra)) { + throw new IllegalArgumentException("Supplier with same key already exists: " + + extra); + } + mExternalInterfaceSuppliers.put(extra, binderSupplier); + } + + /** + * Updates the given bundle with the set of external interfaces, invalidating the old set of + * binders. + */ + private void createExternalInterfaces(Bundle output) { + // Invalidate the old binders + for (int i = 0; i < mExternalInterfaces.size(); i++) { + mExternalInterfaces.valueAt(i).invalidate(); + } + mExternalInterfaces.clear(); + + // Create new binders for each key + for (int i = 0; i < mExternalInterfaceSuppliers.size(); i++) { + final String key = mExternalInterfaceSuppliers.keyAt(i); + final ExternalInterfaceBinder b = mExternalInterfaceSuppliers.valueAt(i).get(); + mExternalInterfaces.put(key, b); + output.putBinder(key, b.asBinder()); + } + } + @VisibleForTesting void onConfigurationChanged(Configuration newConfig) { // The initial config is send on startup and doesn't trigger listener callbacks @@ -204,6 +260,14 @@ public class ShellController { pw.println(innerPrefix + "mLastConfiguration=" + mLastConfiguration); pw.println(innerPrefix + "mKeyguardChangeListeners=" + mKeyguardChangeListeners.size()); pw.println(innerPrefix + "mUserChangeListeners=" + mUserChangeListeners.size()); + + if (!mExternalInterfaces.isEmpty()) { + pw.println(innerPrefix + "mExternalInterfaces={"); + for (String key : mExternalInterfaces.keySet()) { + pw.println(innerPrefix + "\t" + key + ": " + mExternalInterfaces.get(key)); + } + pw.println(innerPrefix + "}"); + } } /** @@ -211,7 +275,6 @@ public class ShellController { */ @ExternalThread private class ShellInterfaceImpl implements ShellInterface { - @Override public void onInit() { try { @@ -221,28 +284,6 @@ public class ShellController { } } - @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(() -> @@ -274,5 +315,38 @@ public class ShellController { mMainExecutor.execute(() -> ShellController.this.onUserProfilesChanged(profiles)); } + + @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 createExternalInterfaces(Bundle bundle) { + try { + mMainExecutor.executeBlocking(() -> { + ShellController.this.createExternalInterfaces(bundle); + }); + } catch (InterruptedException e) { + throw new RuntimeException("Failed to get Shell command 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); + } + } } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/sysui/ShellInterface.java b/libs/WindowManager/Shell/src/com/android/wm/shell/sysui/ShellInterface.java index 2108c824ac6fc..bc5dd11ef54e0 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/sysui/ShellInterface.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/sysui/ShellInterface.java @@ -19,6 +19,7 @@ package com.android.wm.shell.sysui; import android.content.Context; import android.content.pm.UserInfo; import android.content.res.Configuration; +import android.os.Bundle; import androidx.annotation.NonNull; @@ -36,18 +37,6 @@ public interface ShellInterface { */ 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. */ @@ -74,4 +63,21 @@ public interface ShellInterface { * Notifies the Shell when a profile belonging to the user changes. */ default void onUserProfilesChanged(@NonNull List profiles) {} + + /** + * Handles a shell command. + */ + default boolean handleCommand(final String[] args, PrintWriter pw) { + return false; + } + + /** + * Updates the given {@param bundle} with the set of exposed interfaces. + */ + default void createExternalInterfaces(Bundle bundle) {} + + /** + * Dumps the shell state. + */ + default void dump(PrintWriter pw) {} } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/sysui/ShellSharedConstants.java b/libs/WindowManager/Shell/src/com/android/wm/shell/sysui/ShellSharedConstants.java new file mode 100644 index 0000000000000..bdda6a8e926b3 --- /dev/null +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/sysui/ShellSharedConstants.java @@ -0,0 +1,43 @@ +/* + * 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; + +/** + * General shell-related constants that are shared with users of the library. + */ +public class ShellSharedConstants { + // See IPip.aidl + public static final String KEY_EXTRA_SHELL_PIP = "extra_shell_pip"; + // See ISplitScreen.aidl + public static final String KEY_EXTRA_SHELL_SPLIT_SCREEN = "extra_shell_split_screen"; + // See IOneHanded.aidl + public static final String KEY_EXTRA_SHELL_ONE_HANDED = "extra_shell_one_handed"; + // See IShellTransitions.aidl + public static final String KEY_EXTRA_SHELL_SHELL_TRANSITIONS = + "extra_shell_shell_transitions"; + // See IStartingWindow.aidl + public static final String KEY_EXTRA_SHELL_STARTING_WINDOW = + "extra_shell_starting_window"; + // See IRecentTasks.aidl + public static final String KEY_EXTRA_SHELL_RECENT_TASKS = "extra_shell_recent_tasks"; + // See IBackAnimation.aidl + public static final String KEY_EXTRA_SHELL_BACK_ANIMATION = "extra_shell_back_animation"; + // See IFloatingTasks.aidl + public static final String KEY_EXTRA_SHELL_FLOATING_TASKS = "extra_shell_floating_tasks"; + // See IDesktopMode.aidl + public static final String KEY_EXTRA_SHELL_DESKTOP_MODE = "extra_shell_desktop_mode"; +} diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/ShellTransitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/ShellTransitions.java index b34049d4ec42e..da39017a03132 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/ShellTransitions.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/ShellTransitions.java @@ -27,14 +27,6 @@ import com.android.wm.shell.common.annotations.ExternalThread; */ @ExternalThread public interface ShellTransitions { - - /** - * Returns a binder that can be passed to an external process to manipulate remote transitions. - */ - default IShellTransitions createExternalInterface() { - return null; - } - /** * Registers a remote transition. */ diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java index f251e9ea0d048..d1bc7384d78c5 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java @@ -30,6 +30,7 @@ import static android.window.TransitionInfo.FLAG_IS_WALLPAPER; import static android.window.TransitionInfo.FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT; import static com.android.wm.shell.common.ExecutorUtils.executeRemoteCallWithTaskPermission; +import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_SHELL_TRANSITIONS; import android.annotation.NonNull; import android.annotation.Nullable; @@ -62,11 +63,13 @@ import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.protolog.common.ProtoLog; import com.android.wm.shell.common.DisplayController; +import com.android.wm.shell.common.ExternalInterfaceBinder; import com.android.wm.shell.common.RemoteCallable; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.TransactionPool; import com.android.wm.shell.common.annotations.ExternalThread; import com.android.wm.shell.protolog.ShellProtoLogGroup; +import com.android.wm.shell.sysui.ShellController; import com.android.wm.shell.sysui.ShellInit; import java.util.ArrayList; @@ -116,6 +119,7 @@ public class Transitions implements RemoteCallable { private final DefaultTransitionHandler mDefaultTransitionHandler; private final RemoteTransitionHandler mRemoteTransitionHandler; private final DisplayController mDisplayController; + private final ShellController mShellController; private final ShellTransitionImpl mImpl = new ShellTransitionImpl(); /** List of possible handlers. Ordered by specificity (eg. tapped back to front). */ @@ -143,6 +147,7 @@ public class Transitions implements RemoteCallable { public Transitions(@NonNull Context context, @NonNull ShellInit shellInit, + @NonNull ShellController shellController, @NonNull WindowOrganizer organizer, @NonNull TransactionPool pool, @NonNull DisplayController displayController, @@ -157,10 +162,14 @@ public class Transitions implements RemoteCallable { mDefaultTransitionHandler = new DefaultTransitionHandler(context, shellInit, displayController, pool, mainExecutor, mainHandler, animExecutor); mRemoteTransitionHandler = new RemoteTransitionHandler(mMainExecutor); + mShellController = shellController; shellInit.addInitCallback(this::onInit, this); } private void onInit() { + mShellController.addExternalInterface(KEY_EXTRA_SHELL_SHELL_TRANSITIONS, + this::createExternalInterface, this); + // The very last handler (0 in the list) should be the default one. mHandlers.add(mDefaultTransitionHandler); ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "addHandler: Default"); @@ -194,6 +203,10 @@ public class Transitions implements RemoteCallable { return mImpl; } + private ExternalInterfaceBinder createExternalInterface() { + return new IShellTransitionsImpl(this); + } + @Override public Context getContext() { return mContext; @@ -917,17 +930,6 @@ public class Transitions implements RemoteCallable { */ @ExternalThread private class ShellTransitionImpl implements ShellTransitions { - private IShellTransitionsImpl mIShellTransitions; - - @Override - public IShellTransitions createExternalInterface() { - if (mIShellTransitions != null) { - mIShellTransitions.invalidate(); - } - mIShellTransitions = new IShellTransitionsImpl(Transitions.this); - return mIShellTransitions; - } - @Override public void registerRemote(@NonNull TransitionFilter filter, @NonNull RemoteTransition remoteTransition) { @@ -948,7 +950,8 @@ public class Transitions implements RemoteCallable { * The interface for calls from outside the host process. */ @BinderThread - private static class IShellTransitionsImpl extends IShellTransitions.Stub { + private static class IShellTransitionsImpl extends IShellTransitions.Stub + implements ExternalInterfaceBinder { private Transitions mTransitions; IShellTransitionsImpl(Transitions transitions) { @@ -958,7 +961,8 @@ public class Transitions implements RemoteCallable { /** * Invalidates this instance, preventing future calls from updating the controller. */ - void invalidate() { + @Override + public void invalidate() { mTransitions = null; } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java index 90a377309edd4..077e9ca2e88c4 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java @@ -63,7 +63,9 @@ import androidx.test.platform.app.InstrumentationRegistry; import com.android.internal.util.test.FakeSettingsProvider; import com.android.wm.shell.ShellTestCase; import com.android.wm.shell.TestShellExecutor; +import com.android.wm.shell.sysui.ShellController; import com.android.wm.shell.sysui.ShellInit; +import com.android.wm.shell.sysui.ShellSharedConstants; import org.junit.Before; import org.junit.Ignore; @@ -102,6 +104,9 @@ public class BackAnimationControllerTest extends ShellTestCase { @Mock private IBackNaviAnimationController mIBackNaviAnimationController; + @Mock + private ShellController mShellController; + private BackAnimationController mController; private int mEventTime = 0; @@ -118,7 +123,7 @@ public class BackAnimationControllerTest extends ShellTestCase { ANIMATION_ENABLED); mTestableLooper = TestableLooper.get(this); mShellInit = spy(new ShellInit(mShellExecutor)); - mController = new BackAnimationController(mShellInit, + mController = new BackAnimationController(mShellInit, mShellController, mShellExecutor, new Handler(mTestableLooper.getLooper()), mTransaction, mActivityTaskManager, mContext, mContentResolver); @@ -174,6 +179,12 @@ public class BackAnimationControllerTest extends ShellTestCase { verify(mShellInit, times(1)).addInitCallback(any(), any()); } + @Test + public void instantiateController_addExternalInterface() { + verify(mShellController, times(1)).addExternalInterface( + eq(ShellSharedConstants.KEY_EXTRA_SHELL_BACK_ANIMATION), any(), any()); + } + @Test @Ignore("b/207481538") public void crossActivity_screenshotAttachedAndVisible() { @@ -250,7 +261,7 @@ public class BackAnimationControllerTest extends ShellTestCase { // Toggle the setting off Settings.Global.putString(mContentResolver, Settings.Global.ENABLE_BACK_ANIMATION, "0"); ShellInit shellInit = new ShellInit(mShellExecutor); - mController = new BackAnimationController(shellInit, + mController = new BackAnimationController(shellInit, mShellController, mShellExecutor, new Handler(mTestableLooper.getLooper()), mTransaction, mActivityTaskManager, mContext, mContentResolver); diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeControllerTest.java index dd23d97d91998..c850a3b3b7803 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeControllerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeControllerTest.java @@ -52,6 +52,7 @@ import com.android.wm.shell.ShellTestCase; import com.android.wm.shell.TestRunningTaskInfoBuilder; import com.android.wm.shell.TestShellExecutor; import com.android.wm.shell.common.ShellExecutor; +import com.android.wm.shell.sysui.ShellController; import com.android.wm.shell.sysui.ShellInit; import com.android.wm.shell.transition.Transitions; @@ -67,6 +68,8 @@ import org.mockito.Mockito; @RunWith(AndroidTestingRunner.class) public class DesktopModeControllerTest extends ShellTestCase { + @Mock + private ShellController mShellController; @Mock private ShellTaskOrganizer mShellTaskOrganizer; @Mock @@ -94,8 +97,8 @@ public class DesktopModeControllerTest extends ShellTestCase { mDesktopModeTaskRepository = new DesktopModeTaskRepository(); - mController = new DesktopModeController(mContext, mShellInit, mShellTaskOrganizer, - mRootTaskDisplayAreaOrganizer, mMockTransitions, + mController = new DesktopModeController(mContext, mShellInit, mShellController, + mShellTaskOrganizer, mRootTaskDisplayAreaOrganizer, mMockTransitions, mDesktopModeTaskRepository, mMockHandler, mExecutor); when(mShellTaskOrganizer.prepareClearFreeformForStandardTasks(anyInt())).thenReturn( diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/floating/FloatingTasksControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/floating/FloatingTasksControllerTest.java index a88c83779f254..d378a177650ad 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/floating/FloatingTasksControllerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/floating/FloatingTasksControllerTest.java @@ -52,6 +52,7 @@ import com.android.wm.shell.floating.views.FloatingTaskLayer; import com.android.wm.shell.sysui.ShellCommandHandler; import com.android.wm.shell.sysui.ShellController; import com.android.wm.shell.sysui.ShellInit; +import com.android.wm.shell.sysui.ShellSharedConstants; import org.junit.After; import org.junit.Before; @@ -168,6 +169,18 @@ public class FloatingTasksControllerTest extends ShellTestCase { } } + @Test + public void onInit_addExternalInterface() { + if (FLOATING_TASKS_ACTUALLY_ENABLED) { + createController(); + setUpTabletConfig(); + mController.onInit(); + + verify(mShellController, times(1)).addExternalInterface( + ShellSharedConstants.KEY_EXTRA_SHELL_FLOATING_TASKS, any(), any()); + } + } + // // Tests for floating layer, which is only available for tablets. // diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedControllerTest.java index cf8297eec0614..8ad3d2a726170 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedControllerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedControllerTest.java @@ -51,6 +51,7 @@ import com.android.wm.shell.common.TaskStackListenerImpl; import com.android.wm.shell.sysui.ShellCommandHandler; import com.android.wm.shell.sysui.ShellController; import com.android.wm.shell.sysui.ShellInit; +import com.android.wm.shell.sysui.ShellSharedConstants; import org.junit.Before; import org.junit.Test; @@ -175,6 +176,12 @@ public class OneHandedControllerTest extends OneHandedTestCase { verify(mMockShellController, times(1)).addUserChangeListener(any()); } + @Test + public void testControllerRegisteresExternalInterface() { + verify(mMockShellController, times(1)).addExternalInterface( + eq(ShellSharedConstants.KEY_EXTRA_SHELL_ONE_HANDED), any(), any()); + } + @Test public void testDefaultShouldNotInOneHanded() { // Assert default transition state is STATE_NONE diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipControllerTest.java index 1e08f1e557972..d06fb55a57693 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipControllerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipControllerTest.java @@ -20,6 +20,7 @@ import static android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE; import static org.junit.Assert.assertNull; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; @@ -61,6 +62,7 @@ import com.android.wm.shell.pip.PipTransitionState; import com.android.wm.shell.sysui.ShellCommandHandler; import com.android.wm.shell.sysui.ShellController; import com.android.wm.shell.sysui.ShellInit; +import com.android.wm.shell.sysui.ShellSharedConstants; import org.junit.Before; import org.junit.Test; @@ -151,6 +153,12 @@ public class PipControllerTest extends ShellTestCase { verify(mShellController, times(1)).addKeyguardChangeListener(any()); } + @Test + public void instantiatePipController_registerExternalInterface() { + verify(mShellController, times(1)).addExternalInterface( + eq(ShellSharedConstants.KEY_EXTRA_SHELL_PIP), any(), any()); + } + @Test public void instantiatePipController_registerUserChangeListener() { verify(mShellController, times(1)).addUserChangeListener(any()); diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentTasksControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentTasksControllerTest.java index b8aaaa76e3c7e..f6ac3ee0a8e45 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentTasksControllerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentTasksControllerTest.java @@ -28,6 +28,7 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.isA; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; @@ -57,7 +58,9 @@ import com.android.wm.shell.common.TaskStackListenerImpl; import com.android.wm.shell.desktopmode.DesktopModeStatus; import com.android.wm.shell.desktopmode.DesktopModeTaskRepository; import com.android.wm.shell.sysui.ShellCommandHandler; +import com.android.wm.shell.sysui.ShellController; import com.android.wm.shell.sysui.ShellInit; +import com.android.wm.shell.sysui.ShellSharedConstants; import com.android.wm.shell.util.GroupedRecentTaskInfo; import com.android.wm.shell.util.SplitBounds; @@ -84,6 +87,8 @@ public class RecentTasksControllerTest extends ShellTestCase { @Mock private TaskStackListenerImpl mTaskStackListener; @Mock + private ShellController mShellController; + @Mock private ShellCommandHandler mShellCommandHandler; @Mock private DesktopModeTaskRepository mDesktopModeTaskRepository; @@ -101,7 +106,7 @@ public class RecentTasksControllerTest extends ShellTestCase { when(mContext.getPackageManager()).thenReturn(mock(PackageManager.class)); mShellInit = spy(new ShellInit(mMainExecutor)); mRecentTasksController = spy(new RecentTasksController(mContext, mShellInit, - mShellCommandHandler, mTaskStackListener, mActivityTaskManager, + mShellController, mShellCommandHandler, mTaskStackListener, mActivityTaskManager, Optional.of(mDesktopModeTaskRepository), mMainExecutor)); mShellTaskOrganizer = new ShellTaskOrganizer(mShellInit, mShellCommandHandler, null /* sizeCompatUI */, Optional.empty(), Optional.of(mRecentTasksController), @@ -120,6 +125,12 @@ public class RecentTasksControllerTest extends ShellTestCase { isA(RecentTasksController.class)); } + @Test + public void instantiateController_addExternalInterface() { + verify(mShellController, times(1)).addExternalInterface( + eq(ShellSharedConstants.KEY_EXTRA_SHELL_RECENT_TASKS), any(), any()); + } + @Test public void testAddRemoveSplitNotifyChange() { ActivityManager.RecentTaskInfo t1 = makeTaskInfo(1); diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitScreenControllerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitScreenControllerTests.java index 5a68361c595c2..55883ab2ef70c 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitScreenControllerTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitScreenControllerTests.java @@ -58,6 +58,7 @@ import com.android.wm.shell.recents.RecentTasksController; import com.android.wm.shell.sysui.ShellCommandHandler; import com.android.wm.shell.sysui.ShellController; import com.android.wm.shell.sysui.ShellInit; +import com.android.wm.shell.sysui.ShellSharedConstants; import com.android.wm.shell.transition.Transitions; import org.junit.Before; @@ -132,6 +133,15 @@ public class SplitScreenControllerTests extends ShellTestCase { verify(mShellController, times(1)).addKeyguardChangeListener(any()); } + @Test + public void instantiateController_addExternalInterface() { + doReturn(mMainExecutor).when(mTaskOrganizer).getExecutor(); + when(mDisplayController.getDisplayLayout(anyInt())).thenReturn(new DisplayLayout()); + mSplitScreenController.onInit(); + verify(mShellController, times(1)).addExternalInterface( + eq(ShellSharedConstants.KEY_EXTRA_SHELL_SPLIT_SCREEN), any(), any()); + } + @Test public void testShouldAddMultipleTaskFlag_notInSplitScreen() { doReturn(false).when(mSplitScreenController).isSplitScreenVisible(); diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingWindowControllerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingWindowControllerTests.java index 35515e3bb6e88..90165d1cd1b2b 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingWindowControllerTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingWindowControllerTests.java @@ -21,6 +21,7 @@ import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -36,7 +37,9 @@ import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.ShellTestCase; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.TransactionPool; +import com.android.wm.shell.sysui.ShellController; import com.android.wm.shell.sysui.ShellInit; +import com.android.wm.shell.sysui.ShellSharedConstants; import org.junit.Before; import org.junit.Test; @@ -56,25 +59,34 @@ public class StartingWindowControllerTests extends ShellTestCase { private @Mock Context mContext; private @Mock DisplayManager mDisplayManager; - private @Mock ShellInit mShellInit; + private @Mock ShellController mShellController; private @Mock ShellTaskOrganizer mTaskOrganizer; private @Mock ShellExecutor mMainExecutor; private @Mock StartingWindowTypeAlgorithm mTypeAlgorithm; private @Mock IconProvider mIconProvider; private @Mock TransactionPool mTransactionPool; private StartingWindowController mController; + private ShellInit mShellInit; @Before public void setUp() { MockitoAnnotations.initMocks(this); doReturn(mock(Display.class)).when(mDisplayManager).getDisplay(anyInt()); doReturn(mDisplayManager).when(mContext).getSystemService(eq(DisplayManager.class)); - mController = new StartingWindowController(mContext, mShellInit, mTaskOrganizer, - mMainExecutor, mTypeAlgorithm, mIconProvider, mTransactionPool); + mShellInit = spy(new ShellInit(mMainExecutor)); + mController = new StartingWindowController(mContext, mShellInit, mShellController, + mTaskOrganizer, mMainExecutor, mTypeAlgorithm, mIconProvider, mTransactionPool); + mShellInit.init(); } @Test - public void instantiate_addInitCallback() { + public void instantiateController_addInitCallback() { verify(mShellInit, times(1)).addInitCallback(any(), any()); } + + @Test + public void instantiateController_addExternalInterface() { + verify(mShellController, times(1)).addExternalInterface( + eq(ShellSharedConstants.KEY_EXTRA_SHELL_STARTING_WINDOW), any(), any()); + } } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/sysui/ShellControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/sysui/ShellControllerTest.java index d6ddba9e927d3..fbc50c68eff9d 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/sysui/ShellControllerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/sysui/ShellControllerTest.java @@ -16,12 +16,16 @@ package com.android.wm.shell.sysui; +import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; import android.content.Context; import android.content.pm.UserInfo; import android.content.res.Configuration; +import android.os.Binder; +import android.os.Bundle; +import android.os.IBinder; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; @@ -30,6 +34,7 @@ import androidx.test.filters.SmallTest; import androidx.test.platform.app.InstrumentationRegistry; import com.android.wm.shell.ShellTestCase; +import com.android.wm.shell.common.ExternalInterfaceBinder; import com.android.wm.shell.common.ShellExecutor; import org.junit.After; @@ -49,6 +54,7 @@ import java.util.Locale; public class ShellControllerTest extends ShellTestCase { private static final int TEST_USER_ID = 100; + private static final String EXTRA_TEST_BINDER = "test_binder"; @Mock private ShellInit mShellInit; @@ -80,6 +86,47 @@ public class ShellControllerTest extends ShellTestCase { // Do nothing } + @Test + public void testAddExternalInterface_ensureCallback() { + Binder callback = new Binder(); + ExternalInterfaceBinder wrapper = new ExternalInterfaceBinder() { + @Override + public void invalidate() { + // Do nothing + } + + @Override + public IBinder asBinder() { + return callback; + } + }; + mController.addExternalInterface(EXTRA_TEST_BINDER, () -> wrapper, this); + + Bundle b = new Bundle(); + mController.asShell().createExternalInterfaces(b); + assertTrue(b.getIBinder(EXTRA_TEST_BINDER) == callback); + } + + @Test + public void testAddExternalInterface_disallowDuplicateKeys() { + Binder callback = new Binder(); + ExternalInterfaceBinder wrapper = new ExternalInterfaceBinder() { + @Override + public void invalidate() { + // Do nothing + } + + @Override + public IBinder asBinder() { + return callback; + } + }; + mController.addExternalInterface(EXTRA_TEST_BINDER, () -> wrapper, this); + assertThrows(IllegalArgumentException.class, () -> { + mController.addExternalInterface(EXTRA_TEST_BINDER, () -> wrapper, this); + }); + } + @Test public void testAddUserChangeListener_ensureCallback() { mController.addUserChangeListener(mUserChangeListener); diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java index db9136d8eacbe..c764741d4cd6a 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java @@ -87,7 +87,9 @@ 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.TransactionPool; +import com.android.wm.shell.sysui.ShellController; import com.android.wm.shell.sysui.ShellInit; +import com.android.wm.shell.sysui.ShellSharedConstants; import org.junit.Before; import org.junit.Test; @@ -124,11 +126,24 @@ public class ShellTransitionTests extends ShellTestCase { @Test public void instantiate_addInitCallback() { ShellInit shellInit = mock(ShellInit.class); - final Transitions t = new Transitions(mContext, shellInit, mOrganizer, mTransactionPool, - createTestDisplayController(), mMainExecutor, mMainHandler, mAnimExecutor); + final Transitions t = new Transitions(mContext, shellInit, mock(ShellController.class), + mOrganizer, mTransactionPool, createTestDisplayController(), mMainExecutor, + mMainHandler, mAnimExecutor); verify(shellInit, times(1)).addInitCallback(any(), eq(t)); } + @Test + public void instantiateController_addExternalInterface() { + ShellInit shellInit = new ShellInit(mMainExecutor); + ShellController shellController = mock(ShellController.class); + final Transitions t = new Transitions(mContext, shellInit, shellController, + mOrganizer, mTransactionPool, createTestDisplayController(), mMainExecutor, + mMainHandler, mAnimExecutor); + shellInit.init(); + verify(shellController, times(1)).addExternalInterface( + eq(ShellSharedConstants.KEY_EXTRA_SHELL_SHELL_TRANSITIONS), any(), any()); + } + @Test public void testBasicTransitionFlow() { Transitions transitions = createTestTransitions(); @@ -1063,8 +1078,9 @@ public class ShellTransitionTests extends ShellTestCase { private Transitions createTestTransitions() { ShellInit shellInit = new ShellInit(mMainExecutor); - final Transitions t = new Transitions(mContext, shellInit, mOrganizer, mTransactionPool, - createTestDisplayController(), mMainExecutor, mMainHandler, mAnimExecutor); + final Transitions t = new Transitions(mContext, shellInit, mock(ShellController.class), + mOrganizer, mTransactionPool, createTestDisplayController(), mMainExecutor, + mMainHandler, mAnimExecutor); shellInit.init(); return t; } diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java index 85278dd4b8837..f2742b7889b1e 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java @@ -43,27 +43,8 @@ public class QuickStepContract { public static final String KEY_EXTRA_SYSUI_PROXY = "extra_sysui_proxy"; public static final String KEY_EXTRA_WINDOW_CORNER_RADIUS = "extra_window_corner_radius"; public static final String KEY_EXTRA_SUPPORTS_WINDOW_CORNERS = "extra_supports_window_corners"; - // See IPip.aidl - public static final String KEY_EXTRA_SHELL_PIP = "extra_shell_pip"; - // See ISplitScreen.aidl - public static final String KEY_EXTRA_SHELL_SPLIT_SCREEN = "extra_shell_split_screen"; - // See IFloatingTasks.aidl - public static final String KEY_EXTRA_SHELL_FLOATING_TASKS = "extra_shell_floating_tasks"; - // See IOneHanded.aidl - public static final String KEY_EXTRA_SHELL_ONE_HANDED = "extra_shell_one_handed"; - // See IShellTransitions.aidl - public static final String KEY_EXTRA_SHELL_SHELL_TRANSITIONS = - "extra_shell_shell_transitions"; - // See IStartingWindow.aidl - public static final String KEY_EXTRA_SHELL_STARTING_WINDOW = - "extra_shell_starting_window"; // See ISysuiUnlockAnimationController.aidl public static final String KEY_EXTRA_UNLOCK_ANIMATION_CONTROLLER = "unlock_animation"; - // See IRecentTasks.aidl - public static final String KEY_EXTRA_RECENT_TASKS = "recent_tasks"; - public static final String KEY_EXTRA_SHELL_BACK_ANIMATION = "extra_shell_back_animation"; - // See IDesktopMode.aidl - public static final String KEY_EXTRA_SHELL_DESKTOP_MODE = "extra_shell_desktop_mode"; public static final String NAV_BAR_MODE_3BUTTON_OVERLAY = WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON_OVERLAY; diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java index 899e57d7d0ae2..66be00d8de66f 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java +++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java @@ -25,15 +25,6 @@ import static android.view.WindowManager.ScreenshotSource.SCREENSHOT_OVERVIEW; import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON; import static com.android.internal.accessibility.common.ShortcutConstants.CHOOSER_PACKAGE_NAME; -import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_RECENT_TASKS; -import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SHELL_BACK_ANIMATION; -import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SHELL_DESKTOP_MODE; -import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SHELL_FLOATING_TASKS; -import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SHELL_ONE_HANDED; -import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SHELL_PIP; -import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SHELL_SHELL_TRANSITIONS; -import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SHELL_SPLIT_SCREEN; -import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SHELL_STARTING_WINDOW; import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SUPPORTS_WINDOW_CORNERS; import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SYSUI_PROXY; import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_UNLOCK_ANIMATION_CONTROLLER; @@ -110,16 +101,7 @@ import com.android.systemui.statusbar.NotificationShadeWindowController; import com.android.systemui.statusbar.phone.CentralSurfaces; import com.android.systemui.statusbar.phone.StatusBarWindowCallback; import com.android.systemui.statusbar.policy.CallbackController; -import com.android.wm.shell.back.BackAnimation; -import com.android.wm.shell.desktopmode.DesktopMode; -import com.android.wm.shell.floating.FloatingTasks; -import com.android.wm.shell.onehanded.OneHanded; -import com.android.wm.shell.pip.Pip; -import com.android.wm.shell.pip.PipAnimationController; -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.transition.ShellTransitions; +import com.android.wm.shell.sysui.ShellInterface; import java.io.PrintWriter; import java.util.ArrayList; @@ -151,10 +133,8 @@ public class OverviewProxyService extends CurrentUserTracker implements private static final long MAX_BACKOFF_MILLIS = 10 * 60 * 1000; private final Context mContext; - private final Optional mPipOptional; + private final ShellInterface mShellInterface; private final Lazy> mCentralSurfacesOptionalLazy; - private final Optional mSplitScreenOptional; - private final Optional mFloatingTasksOptional; private SysUiState mSysUiState; private final Handler mHandler; private final Lazy mNavBarControllerLazy; @@ -164,14 +144,8 @@ public class OverviewProxyService extends CurrentUserTracker implements private final List mConnectionCallbacks = new ArrayList<>(); private final Intent mQuickStepIntent; private final ScreenshotHelper mScreenshotHelper; - private final Optional mOneHandedOptional; private final CommandQueue mCommandQueue; - private final ShellTransitions mShellTransitions; - private final Optional mStartingSurface; private final KeyguardUnlockAnimationController mSysuiUnlockAnimationController; - private final Optional mRecentTasks; - private final Optional mBackAnimation; - private final Optional mDesktopModeOptional; private final UiEventLogger mUiEventLogger; private Region mActiveNavBarRegion; @@ -456,36 +430,10 @@ public class OverviewProxyService extends CurrentUserTracker implements params.putBinder(KEY_EXTRA_SYSUI_PROXY, mSysUiProxy.asBinder()); params.putFloat(KEY_EXTRA_WINDOW_CORNER_RADIUS, mWindowCornerRadius); params.putBoolean(KEY_EXTRA_SUPPORTS_WINDOW_CORNERS, mSupportsRoundedCornersOnWindows); - - mPipOptional.ifPresent((pip) -> params.putBinder( - KEY_EXTRA_SHELL_PIP, - pip.createExternalInterface().asBinder())); - mSplitScreenOptional.ifPresent((splitscreen) -> params.putBinder( - KEY_EXTRA_SHELL_SPLIT_SCREEN, - splitscreen.createExternalInterface().asBinder())); - mFloatingTasksOptional.ifPresent(floatingTasks -> params.putBinder( - KEY_EXTRA_SHELL_FLOATING_TASKS, - floatingTasks.createExternalInterface().asBinder())); - mOneHandedOptional.ifPresent((onehanded) -> params.putBinder( - KEY_EXTRA_SHELL_ONE_HANDED, - onehanded.createExternalInterface().asBinder())); - params.putBinder(KEY_EXTRA_SHELL_SHELL_TRANSITIONS, - mShellTransitions.createExternalInterface().asBinder()); - mStartingSurface.ifPresent((startingwindow) -> params.putBinder( - KEY_EXTRA_SHELL_STARTING_WINDOW, - startingwindow.createExternalInterface().asBinder())); - params.putBinder( - KEY_EXTRA_UNLOCK_ANIMATION_CONTROLLER, + params.putBinder(KEY_EXTRA_UNLOCK_ANIMATION_CONTROLLER, mSysuiUnlockAnimationController.asBinder()); - mRecentTasks.ifPresent(recentTasks -> params.putBinder( - KEY_EXTRA_RECENT_TASKS, - recentTasks.createExternalInterface().asBinder())); - mBackAnimation.ifPresent((backAnimation) -> params.putBinder( - KEY_EXTRA_SHELL_BACK_ANIMATION, - backAnimation.createExternalInterface().asBinder())); - mDesktopModeOptional.ifPresent((desktopMode -> params.putBinder( - KEY_EXTRA_SHELL_DESKTOP_MODE, - desktopMode.createExternalInterface().asBinder()))); + // Add all the interfaces exposed by the shell + mShellInterface.createExternalInterfaces(params); try { Log.d(TAG_OPS, "OverviewProxyService connected, initializing overview proxy"); @@ -559,21 +507,14 @@ public class OverviewProxyService extends CurrentUserTracker implements @SuppressWarnings("OptionalUsedAsFieldOrParameterType") @Inject - public OverviewProxyService(Context context, CommandQueue commandQueue, + public OverviewProxyService(Context context, + CommandQueue commandQueue, + ShellInterface shellInterface, Lazy navBarControllerLazy, Lazy> centralSurfacesOptionalLazy, NavigationModeController navModeController, NotificationShadeWindowController statusBarWinController, SysUiState sysUiState, - Optional pipOptional, - Optional splitScreenOptional, - Optional floatingTasksOptional, - Optional oneHandedOptional, - Optional recentTasks, - Optional backAnimation, - Optional startingSurface, - Optional desktopModeOptional, BroadcastDispatcher broadcastDispatcher, - ShellTransitions shellTransitions, ScreenLifecycle screenLifecycle, UiEventLogger uiEventLogger, KeyguardUnlockAnimationController sysuiUnlockAnimationController, @@ -587,7 +528,7 @@ public class OverviewProxyService extends CurrentUserTracker implements } mContext = context; - mPipOptional = pipOptional; + mShellInterface = shellInterface; mCentralSurfacesOptionalLazy = centralSurfacesOptionalLazy; mHandler = new Handler(); mNavBarControllerLazy = navBarControllerLazy; @@ -602,11 +543,6 @@ public class OverviewProxyService extends CurrentUserTracker implements .supportsRoundedCornersOnWindows(mContext.getResources()); mSysUiState = sysUiState; mSysUiState.addCallback(this::notifySystemUiStateFlags); - mOneHandedOptional = oneHandedOptional; - mShellTransitions = shellTransitions; - mRecentTasks = recentTasks; - mBackAnimation = backAnimation; - mDesktopModeOptional = desktopModeOptional; mUiEventLogger = uiEventLogger; dumpManager.registerDumpable(getClass().getSimpleName(), this); @@ -636,9 +572,6 @@ public class OverviewProxyService extends CurrentUserTracker implements }); mCommandQueue = commandQueue; - mSplitScreenOptional = splitScreenOptional; - mFloatingTasksOptional = floatingTasksOptional; - // Listen for user setup startTracking(); @@ -647,7 +580,6 @@ public class OverviewProxyService extends CurrentUserTracker implements // Connect to the service updateEnabledState(); startConnectionToCurrentUser(); - mStartingSurface = startingSurface; mSysuiUnlockAnimationController = sysuiUnlockAnimationController; // Listen for assistant changes