diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInitImpl.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInitImpl.java index 9abda68fbfd7c..6f4550c2a89e0 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInitImpl.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInitImpl.java @@ -26,7 +26,7 @@ import com.android.wm.shell.draganddrop.DragAndDropController; import com.android.wm.shell.legacysplitscreen.LegacySplitScreenController; import com.android.wm.shell.pip.phone.PipTouchHandler; import com.android.wm.shell.splitscreen.SplitScreenController; -import com.android.wm.shell.startingsurface.StartingSurface; +import com.android.wm.shell.startingsurface.StartingWindowController; import com.android.wm.shell.transition.Transitions; import java.util.Optional; @@ -47,7 +47,7 @@ public class ShellInitImpl { private final FullscreenTaskListener mFullscreenTaskListener; private final ShellExecutor mMainExecutor; private final Transitions mTransitions; - private final Optional mStartingSurfaceOptional; + private final StartingWindowController mStartingWindow; private final InitImpl mImpl = new InitImpl(); @@ -57,10 +57,10 @@ public class ShellInitImpl { Optional legacySplitScreenOptional, Optional splitScreenOptional, Optional appPairsOptional, - Optional startingSurfaceOptional, Optional pipTouchHandlerOptional, FullscreenTaskListener fullscreenTaskListener, Transitions transitions, + StartingWindowController startingWindow, ShellExecutor mainExecutor) { mDisplayImeController = displayImeController; mDragAndDropController = dragAndDropController; @@ -72,7 +72,7 @@ public class ShellInitImpl { mPipTouchHandlerOptional = pipTouchHandlerOptional; mTransitions = transitions; mMainExecutor = mainExecutor; - mStartingSurfaceOptional = startingSurfaceOptional; + mStartingWindow = startingWindow; } public ShellInit asShellInit() { @@ -83,10 +83,10 @@ public class ShellInitImpl { // Start listening for display changes mDisplayImeController.startMonitorDisplays(); + // Setup the shell organizer mShellTaskOrganizer.addListenerForType( mFullscreenTaskListener, TASK_LISTENER_TYPE_FULLSCREEN); - mStartingSurfaceOptional.ifPresent(mShellTaskOrganizer::initStartingSurface); - // Register the shell organizer + mShellTaskOrganizer.initStartingWindow(mStartingWindow); mShellTaskOrganizer.registerOrganizer(); mAppPairsOptional.ifPresent(AppPairsController::onOrganizerRegistered); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java index fcb53cd890b72..94d13eab4299d 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java @@ -48,7 +48,7 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.protolog.common.ProtoLog; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.sizecompatui.SizeCompatUIController; -import com.android.wm.shell.startingsurface.StartingSurface; +import com.android.wm.shell.startingsurface.StartingWindowController; import java.io.PrintWriter; import java.util.ArrayList; @@ -133,7 +133,7 @@ public class ShellTaskOrganizer extends TaskOrganizer { private final ArraySet mLocusIdListeners = new ArraySet<>(); private final Object mLock = new Object(); - private StartingSurface mStartingSurface; + private StartingWindowController mStartingWindow; /** * In charge of showing size compat UI. Can be {@code null} if device doesn't support size @@ -184,8 +184,8 @@ public class ShellTaskOrganizer extends TaskOrganizer { /** * @hide */ - public void initStartingSurface(StartingSurface startingSurface) { - mStartingSurface = startingSurface; + public void initStartingWindow(StartingWindowController startingWindow) { + mStartingWindow = startingWindow; } /** @@ -302,23 +302,23 @@ public class ShellTaskOrganizer extends TaskOrganizer { @Override public void addStartingWindow(StartingWindowInfo info, IBinder appToken) { - if (mStartingSurface != null) { - mStartingSurface.addStartingWindow(info, appToken); + if (mStartingWindow != null) { + mStartingWindow.addStartingWindow(info, appToken); } } @Override public void removeStartingWindow(int taskId, SurfaceControl leash, Rect frame, boolean playRevealAnimation) { - if (mStartingSurface != null) { - mStartingSurface.removeStartingWindow(taskId, leash, frame, playRevealAnimation); + if (mStartingWindow != null) { + mStartingWindow.removeStartingWindow(taskId, leash, frame, playRevealAnimation); } } @Override public void copySplashScreenView(int taskId) { - if (mStartingSurface != null) { - mStartingSurface.copySplashScreenView(taskId); + if (mStartingWindow != null) { + mStartingWindow.copySplashScreenView(taskId); } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java index aab2334f82555..9a09ca43d1d7f 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java @@ -235,7 +235,7 @@ public class DragAndDropPolicy { mStarter.startShortcut(packageName, id, stage, position, opts, user); } else { mStarter.startIntent(intent.getParcelableExtra(EXTRA_PENDING_INTENT), - mContext, null, stage, position, opts); + null, stage, position, opts); } } @@ -295,7 +295,7 @@ public class DragAndDropPolicy { @Nullable Bundle options); void startShortcut(String packageName, String shortcutId, @StageType int stage, @StagePosition int position, @Nullable Bundle options, UserHandle user); - void startIntent(PendingIntent intent, Context context, Intent fillInIntent, + void startIntent(PendingIntent intent, Intent fillInIntent, @StageType int stage, @StagePosition int position, @Nullable Bundle options); void enterSplitScreen(int taskId, boolean leftOrTop); @@ -337,9 +337,8 @@ public class DragAndDropPolicy { } @Override - public void startIntent(PendingIntent intent, Context context, - @Nullable Intent fillInIntent, int stage, int position, - @Nullable Bundle options) { + public void startIntent(PendingIntent intent, @Nullable Intent fillInIntent, int stage, + int position, @Nullable Bundle options) { try { intent.send(mContext, 0, fillInIntent, null, null, null, options); } catch (PendingIntent.CanceledException e) { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/IOneHanded.aidl b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/IOneHanded.aidl new file mode 100644 index 0000000000000..008b5087d7da2 --- /dev/null +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/IOneHanded.aidl @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2021 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.onehanded; + +/** + * Interface that is exposed to remote callers to manipulate the OneHanded feature. + */ +interface IOneHanded { + + /** + * Enters one handed mode. + */ + oneway void startOneHanded() = 1; + + /** + * Exits one handed mode. + */ + oneway void stopOneHanded() = 2; +} diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHanded.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHanded.java index 4f31c370108d1..a7e9a0135de0e 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHanded.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHanded.java @@ -26,6 +26,14 @@ import com.android.wm.shell.onehanded.OneHandedGestureHandler.OneHandedGestureEv */ @ExternalThread public interface OneHanded { + + /** + * Returns a binder that can be passed to an external process to manipulate OneHanded. + */ + default IOneHanded createExternalInterface() { + return null; + } + /** * Return one handed settings enabled or not. */ diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java index 5fc7c987899f5..8022c1b6e047a 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java @@ -18,6 +18,10 @@ package com.android.wm.shell.onehanded; import static android.os.UserHandle.USER_CURRENT; +import static com.android.wm.shell.common.ExecutorUtils.executeRemoteCallWithTaskPermission; + +import android.Manifest; +import android.annotation.BinderThread; import android.content.ComponentName; import android.content.Context; import android.content.om.IOverlayManager; @@ -43,6 +47,8 @@ import com.android.internal.logging.UiEventLogger; import com.android.wm.shell.R; import com.android.wm.shell.common.DisplayChangeController; import com.android.wm.shell.common.DisplayController; +import com.android.wm.shell.common.ExecutorUtils; +import com.android.wm.shell.common.RemoteCallable; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.TaskStackListenerCallback; import com.android.wm.shell.common.TaskStackListenerImpl; @@ -54,7 +60,7 @@ import java.io.PrintWriter; /** * Manages and manipulates the one handed states, transitions, and gesture for phones. */ -public class OneHandedController { +public class OneHandedController implements RemoteCallable { private static final String TAG = "OneHandedController"; private static final String ONE_HANDED_MODE_OFFSET_PERCENTAGE = @@ -239,6 +245,16 @@ public class OneHandedController { return mImpl; } + @Override + public Context getContext() { + return mContext; + } + + @Override + public ShellExecutor getRemoteCallExecutor() { + return mMainExecutor; + } + /** * Set one handed enabled or disabled when user update settings */ @@ -567,8 +583,22 @@ public class OneHandedController { } } + /** + * The interface for calls from outside the Shell, within the host process. + */ @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 boolean isOneHandedEnabled() { // This is volatile so return directly @@ -637,4 +667,39 @@ public class OneHandedController { }); } } + + /** + * The interface for calls from outside the host process. + */ + @BinderThread + private static class IOneHandedImpl extends IOneHanded.Stub { + private OneHandedController mController; + + IOneHandedImpl(OneHandedController controller) { + mController = controller; + } + + /** + * Invalidates this instance, preventing future calls from updating the controller. + */ + void invalidate() { + mController = null; + } + + @Override + public void startOneHanded() { + executeRemoteCallWithTaskPermission(mController, "startOneHanded", + (controller) -> { + controller.startOneHanded(); + }); + } + + @Override + public void stopOneHanded() { + executeRemoteCallWithTaskPermission(mController, "stopOneHanded", + (controller) -> { + controller.stopOneHanded(); + }); + } + } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ISplitScreen.aidl b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ISplitScreen.aidl new file mode 100644 index 0000000000000..0c46eaba18aee --- /dev/null +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ISplitScreen.aidl @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.wm.shell.splitscreen; + +import android.app.PendingIntent; +import android.content.Intent; +import android.os.Bundle; +import android.os.UserHandle; + +import com.android.wm.shell.splitscreen.ISplitScreenListener; + +/** + * Interface that is exposed to remote callers to manipulate the splitscreen feature. + */ +interface ISplitScreen { + + /** + * Registers a split screen listener. + */ + oneway void registerSplitScreenListener(in ISplitScreenListener listener) = 1; + + /** + * Unregisters a split screen listener. + */ + oneway void unregisterSplitScreenListener(in ISplitScreenListener listener) = 2; + + /** + * Hides the side-stage if it is currently visible. + */ + oneway void setSideStageVisibility(boolean visible) = 3; + + /** + * Removes a task from the side stage. + */ + oneway void removeFromSideStage(int taskId) = 4; + + /** + * Removes the split-screen stages. + */ + oneway void exitSplitScreen() = 5; + + /** + * @param exitSplitScreenOnHide if to exit split-screen if both stages are not visible. + */ + oneway void exitSplitScreenOnHide(boolean exitSplitScreenOnHide) = 6; + + /** + * Starts a task in a stage. + */ + oneway void startTask(int taskId, int stage, int position, in Bundle options) = 7; + + /** + * Starts a shortcut in a stage. + */ + oneway void startShortcut(String packageName, String shortcutId, int stage, int position, + in Bundle options, in UserHandle user) = 8; + + /** + * Starts an activity in a stage. + */ + oneway void startIntent(in PendingIntent intent, in Intent fillInIntent, int stage, + int position, in Bundle options) = 9; +} diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISplitScreenListener.aidl b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ISplitScreenListener.aidl similarity index 84% rename from packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISplitScreenListener.aidl rename to libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ISplitScreenListener.aidl index 54242bece2b64..faab4c2009cf9 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISplitScreenListener.aidl +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ISplitScreenListener.aidl @@ -14,12 +14,20 @@ * limitations under the License. */ -package com.android.systemui.shared.recents; +package com.android.wm.shell.splitscreen; /** * Listener interface that Launcher attaches to SystemUI to get split-screen callbacks. */ oneway interface ISplitScreenListener { + + /** + * Called when the stage position changes. + */ void onStagePositionChanged(int stage, int position); + + /** + * Called when a task changes stages. + */ void onTaskStageChanged(int taskId, int stage, boolean visible); -} +} \ No newline at end of file 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 25a84bd464840..340b55d7f4465 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 @@ -35,7 +35,7 @@ import com.android.wm.shell.draganddrop.DragAndDropPolicy; * TODO: Figure out which of these are actually needed outside of the Shell */ @ExternalThread -public interface SplitScreen extends DragAndDropPolicy.Starter { +public interface SplitScreen { /** * Stage position isn't specified normally meaning to use what ever it is currently set to. */ @@ -89,35 +89,10 @@ public interface SplitScreen extends DragAndDropPolicy.Starter { void onTaskStageChanged(int taskId, @StageType int stage, boolean visible); } - /** @return {@code true} if split-screen is currently visible. */ - boolean isSplitScreenVisible(); - /** Moves a task in the side-stage of split-screen. */ - boolean moveToSideStage(int taskId, @StagePosition int sideStagePosition); - /** Moves a task in the side-stage of split-screen. */ - boolean moveToSideStage(ActivityManager.RunningTaskInfo task, - @StagePosition int sideStagePosition); - /** Removes a task from the side-stage of split-screen. */ - boolean removeFromSideStage(int taskId); - /** Sets the position of the side-stage. */ - void setSideStagePosition(@StagePosition int sideStagePosition); - /** Hides the side-stage if it is currently visible. */ - void setSideStageVisibility(boolean visible); - - /** Removes the split-screen stages. */ - void exitSplitScreen(); - /** @param exitSplitScreenOnHide if to exit split-screen if both stages are not visible. */ - void exitSplitScreenOnHide(boolean exitSplitScreenOnHide); - /** Gets the stage bounds. */ - void getStageBounds(Rect outTopOrLeftBounds, Rect outBottomOrRightBounds); - - void registerSplitScreenListener(SplitScreenListener listener); - void unregisterSplitScreenListener(SplitScreenListener listener); - - void startTask(int taskId, - @StageType int stage, @StagePosition int position, @Nullable Bundle options); - void startShortcut(String packageName, String shortcutId, @StageType int stage, - @StagePosition int position, @Nullable Bundle options, UserHandle user); - void startIntent(PendingIntent intent, Context context, - @Nullable Intent fillInIntent, @StageType int stage, - @StagePosition int position, @Nullable Bundle options); + /** + * Returns a binder that can be passed to an external process to manipulate SplitScreen. + */ + default ISplitScreen createExternalInterface() { + return null; + } } 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 bb6f6f259a1ea..d4362efe462d2 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 @@ -18,6 +18,7 @@ package com.android.wm.shell.splitscreen; import static android.view.Display.DEFAULT_DISPLAY; +import static com.android.wm.shell.common.ExecutorUtils.executeRemoteCallWithTaskPermission; import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_POSITION_BOTTOM_OR_RIGHT; import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_POSITION_TOP_OR_LEFT; import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_POSITION_UNDEFINED; @@ -34,19 +35,24 @@ import android.content.Intent; import android.content.pm.LauncherApps; import android.graphics.Rect; import android.os.Bundle; +import android.os.IBinder; import android.os.RemoteException; import android.os.UserHandle; import android.util.Slog; +import androidx.annotation.BinderThread; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.android.wm.shell.RootTaskDisplayAreaOrganizer; import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.common.DisplayImeController; +import com.android.wm.shell.common.RemoteCallable; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.SyncTransactionQueue; +import com.android.wm.shell.common.annotations.ExternalThread; import com.android.wm.shell.draganddrop.DragAndDropPolicy; +import com.android.wm.shell.splitscreen.ISplitScreenListener; import java.io.PrintWriter; @@ -55,7 +61,8 @@ import java.io.PrintWriter; * {@link SplitScreen}. * @see StageCoordinator */ -public class SplitScreenController implements DragAndDropPolicy.Starter { +public class SplitScreenController implements DragAndDropPolicy.Starter, + RemoteCallable { private static final String TAG = SplitScreenController.class.getSimpleName(); private final ShellTaskOrganizer mTaskOrganizer; @@ -84,6 +91,16 @@ public class SplitScreenController implements DragAndDropPolicy.Starter { return mImpl; } + @Override + public Context getContext() { + return mContext; + } + + @Override + public ShellExecutor getRemoteCallExecutor() { + return mMainExecutor; + } + public void onOrganizerRegistered() { if (mStageCoordinator == null) { // TODO: Multi-display @@ -172,13 +189,13 @@ public class SplitScreenController implements DragAndDropPolicy.Starter { } } - public void startIntent(PendingIntent intent, Context context, - Intent fillInIntent, @SplitScreen.StageType int stage, - @SplitScreen.StagePosition int position, @Nullable Bundle options) { + public void startIntent(PendingIntent intent, Intent fillInIntent, + @SplitScreen.StageType int stage, @SplitScreen.StagePosition int position, + @Nullable Bundle options) { options = resolveStartStage(stage, position, options); try { - intent.send(context, 0, fillInIntent, null, null, null, options); + intent.send(mContext, 0, fillInIntent, null, null, null, options); } catch (PendingIntent.CanceledException e) { Slog.e(TAG, "Failed to launch activity", e); } @@ -242,121 +259,170 @@ public class SplitScreenController implements DragAndDropPolicy.Starter { } } + /** + * The interface for calls from outside the Shell, within the host process. + */ + @ExternalThread private class SplitScreenImpl implements SplitScreen { + private ISplitScreenImpl mISplitScreen; + @Override - public boolean isSplitScreenVisible() { - return mMainExecutor.executeBlockingForResult(() -> { - return SplitScreenController.this.isSplitScreenVisible(); - }, Boolean.class); + public ISplitScreen createExternalInterface() { + if (mISplitScreen != null) { + mISplitScreen.invalidate(); + } + mISplitScreen = new ISplitScreenImpl(SplitScreenController.this); + return mISplitScreen; + } + } + + /** + * The interface for calls from outside the host process. + */ + @BinderThread + private static class ISplitScreenImpl extends ISplitScreen.Stub { + private SplitScreenController mController; + private ISplitScreenListener mListener; + private final SplitScreen.SplitScreenListener mSplitScreenListener = + new SplitScreen.SplitScreenListener() { + @Override + public void onStagePositionChanged(int stage, int position) { + try { + if (mListener != null) { + mListener.onStagePositionChanged(stage, position); + } + } catch (RemoteException e) { + Slog.e(TAG, "onStagePositionChanged", e); + } + } + + @Override + public void onTaskStageChanged(int taskId, int stage, boolean visible) { + try { + if (mListener != null) { + mListener.onTaskStageChanged(taskId, stage, visible); + } + } catch (RemoteException e) { + Slog.e(TAG, "onTaskStageChanged", e); + } + } + }; + private final IBinder.DeathRecipient mListenerDeathRecipient = + new IBinder.DeathRecipient() { + @Override + @BinderThread + public void binderDied() { + final SplitScreenController controller = mController; + controller.getRemoteCallExecutor().execute(() -> { + mListener = null; + controller.unregisterSplitScreenListener(mSplitScreenListener); + }); + } + }; + + public ISplitScreenImpl(SplitScreenController controller) { + mController = controller; + } + + /** + * Invalidates this instance, preventing future calls from updating the controller. + */ + void invalidate() { + mController = null; } @Override - public boolean moveToSideStage(int taskId, int sideStagePosition) { - return mMainExecutor.executeBlockingForResult(() -> { - return SplitScreenController.this.moveToSideStage(taskId, sideStagePosition); - }, Boolean.class); + public void registerSplitScreenListener(ISplitScreenListener listener) { + executeRemoteCallWithTaskPermission(mController, "registerSplitScreenListener", + (controller) -> { + if (mListener != null) { + mListener.asBinder().unlinkToDeath(mListenerDeathRecipient, + 0 /* flags */); + } + if (listener != null) { + try { + listener.asBinder().linkToDeath(mListenerDeathRecipient, + 0 /* flags */); + } catch (RemoteException e) { + Slog.e(TAG, "Failed to link to death"); + return; + } + } + mListener = listener; + controller.registerSplitScreenListener(mSplitScreenListener); + }); } @Override - public boolean moveToSideStage(ActivityManager.RunningTaskInfo task, - int sideStagePosition) { - return mMainExecutor.executeBlockingForResult(() -> { - return SplitScreenController.this.moveToSideStage(task, sideStagePosition); - }, Boolean.class); - } - - @Override - public boolean removeFromSideStage(int taskId) { - return mMainExecutor.executeBlockingForResult(() -> { - return SplitScreenController.this.removeFromSideStage(taskId); - }, Boolean.class); - } - - @Override - public void setSideStagePosition(int sideStagePosition) { - mMainExecutor.execute(() -> { - SplitScreenController.this.setSideStagePosition(sideStagePosition); - }); - } - - @Override - public void setSideStageVisibility(boolean visible) { - mMainExecutor.execute(() -> { - SplitScreenController.this.setSideStageVisibility(visible); - }); - } - - @Override - public void enterSplitScreen(int taskId, boolean leftOrTop) { - mMainExecutor.execute(() -> { - SplitScreenController.this.enterSplitScreen(taskId, leftOrTop); - }); + public void unregisterSplitScreenListener(ISplitScreenListener listener) { + executeRemoteCallWithTaskPermission(mController, "unregisterSplitScreenListener", + (controller) -> { + if (mListener != null) { + mListener.asBinder().unlinkToDeath(mListenerDeathRecipient, + 0 /* flags */); + } + mListener = null; + controller.unregisterSplitScreenListener(mSplitScreenListener); + }); } @Override public void exitSplitScreen() { - mMainExecutor.execute(() -> { - SplitScreenController.this.exitSplitScreen(); - }); + executeRemoteCallWithTaskPermission(mController, "exitSplitScreen", + (controller) -> { + controller.exitSplitScreen(); + }); } @Override public void exitSplitScreenOnHide(boolean exitSplitScreenOnHide) { - mMainExecutor.execute(() -> { - SplitScreenController.this.exitSplitScreenOnHide(exitSplitScreenOnHide); - }); + executeRemoteCallWithTaskPermission(mController, "exitSplitScreenOnHide", + (controller) -> { + controller.exitSplitScreenOnHide(exitSplitScreenOnHide); + }); } @Override - public void getStageBounds(Rect outTopOrLeftBounds, Rect outBottomOrRightBounds) { - try { - mMainExecutor.executeBlocking(() -> { - SplitScreenController.this.getStageBounds(outTopOrLeftBounds, - outBottomOrRightBounds); - }); - } catch (InterruptedException e) { - Slog.e(TAG, "Failed to get stage bounds in 2s"); - } + public void setSideStageVisibility(boolean visible) { + executeRemoteCallWithTaskPermission(mController, "setSideStageVisibility", + (controller) -> { + controller.setSideStageVisibility(visible); + }); } @Override - public void registerSplitScreenListener(SplitScreenListener listener) { - mMainExecutor.execute(() -> { - SplitScreenController.this.registerSplitScreenListener(listener); - }); - } - - @Override - public void unregisterSplitScreenListener(SplitScreenListener listener) { - mMainExecutor.execute(() -> { - SplitScreenController.this.unregisterSplitScreenListener(listener); - }); + public void removeFromSideStage(int taskId) { + executeRemoteCallWithTaskPermission(mController, "removeFromSideStage", + (controller) -> { + controller.removeFromSideStage(taskId); + }); } @Override public void startTask(int taskId, int stage, int position, @Nullable Bundle options) { - mMainExecutor.execute(() -> { - SplitScreenController.this.startTask(taskId, stage, position, options); - }); + executeRemoteCallWithTaskPermission(mController, "startTask", + (controller) -> { + controller.startTask(taskId, stage, position, options); + }); } @Override public void startShortcut(String packageName, String shortcutId, int stage, int position, @Nullable Bundle options, UserHandle user) { - mMainExecutor.execute(() -> { - SplitScreenController.this.startShortcut(packageName, shortcutId, stage, position, - options, user); - }); + executeRemoteCallWithTaskPermission(mController, "startShortcut", + (controller) -> { + controller.startShortcut(packageName, shortcutId, stage, position, + options, user); + }); } @Override - public void startIntent(PendingIntent intent, Context context, Intent fillInIntent, - int stage, int position, @Nullable Bundle options) { - mMainExecutor.execute(() -> { - SplitScreenController.this.startIntent(intent, context, fillInIntent, stage, - position, options); - }); + public void startIntent(PendingIntent intent, Intent fillInIntent, int stage, int position, + @Nullable Bundle options) { + executeRemoteCallWithTaskPermission(mController, "startIntent", + (controller) -> { + controller.startIntent(intent, fillInIntent, stage, position, options); + }); } } - } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/IStartingWindow.aidl b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/IStartingWindow.aidl new file mode 100644 index 0000000000000..546c406ef4533 --- /dev/null +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/IStartingWindow.aidl @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2021 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.startingsurface; + +import com.android.wm.shell.startingsurface.IStartingWindowListener; + +/** + * Interface that is exposed to remote callers to manipulate starting windows. + */ +interface IStartingWindow { + /** + * Sets listener to get task launching callbacks. + */ + oneway void setStartingWindowListener(IStartingWindowListener listener) = 43; +} diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IStartingWindowListener.aidl b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/IStartingWindowListener.aidl similarity index 90% rename from packages/SystemUI/shared/src/com/android/systemui/shared/recents/IStartingWindowListener.aidl rename to libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/IStartingWindowListener.aidl index eb3e60cec5c55..f562c8fc4f859 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IStartingWindowListener.aidl +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/IStartingWindowListener.aidl @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 The Android Open Source Project + * Copyright (C) 2021 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. @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.systemui.shared.recents; +package com.android.wm.shell.startingsurface; /** * Listener interface that Launcher attaches to SystemUI to get 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 f258286f2d176..079d689738523 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 @@ -16,35 +16,15 @@ package com.android.wm.shell.startingsurface; -import android.graphics.Rect; -import android.os.IBinder; -import android.view.SurfaceControl; -import android.window.StartingWindowInfo; - -import java.util.function.BiConsumer; /** * Interface to engage starting window feature. */ public interface StartingSurface { - /** - * Called when a task need a starting window. - */ - void addStartingWindow(StartingWindowInfo windowInfo, IBinder appToken); - /** - * Called when the content of a task is ready to show, starting window can be removed. - */ - void removeStartingWindow(int taskId, SurfaceControl leash, Rect frame, - boolean playRevealAnimation); - /** - * Called when the Task wants to copy the splash screen. - * @param taskId - */ - void copySplashScreenView(int taskId); /** - * Registers the starting window listener. - * - * @param listener The callback when need a starting window. + * Returns a binder that can be passed to an external process to manipulate starting windows. */ - void setStartingWindowListener(BiConsumer listener); + default IStartingWindow createExternalInterface() { + return null; + } } 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 a694e525a7615..b6ca869896908 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 @@ -25,6 +25,8 @@ import static android.window.StartingWindowInfo.TYPE_PARAMETER_NEW_TASK; import static android.window.StartingWindowInfo.TYPE_PARAMETER_PROCESS_RUNNING; import static android.window.StartingWindowInfo.TYPE_PARAMETER_TASK_SWITCH; +import static com.android.wm.shell.common.ExecutorUtils.executeRemoteCallWithTaskPermission; + import android.app.ActivityManager.RunningTaskInfo; import android.app.ActivityTaskManager; import android.content.Context; @@ -37,6 +39,9 @@ import android.window.StartingWindowInfo; import android.window.TaskOrganizer; import android.window.TaskSnapshot; +import androidx.annotation.BinderThread; + +import com.android.wm.shell.common.RemoteCallable; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.TransactionPool; @@ -58,7 +63,7 @@ import java.util.function.BiConsumer; * constructor to keep everything synchronized. * @hide */ -public class StartingWindowController { +public class StartingWindowController implements RemoteCallable { private static final String TAG = StartingWindowController.class.getSimpleName(); static final boolean DEBUG_SPLASH_SCREEN = false; static final boolean DEBUG_TASK_SNAPSHOT = false; @@ -68,17 +73,17 @@ public class StartingWindowController { private BiConsumer mTaskLaunchingCallback; private final StartingSurfaceImpl mImpl = new StartingSurfaceImpl(); + private final Context mContext; private final ShellExecutor mSplashScreenExecutor; // For Car Launcher public StartingWindowController(Context context, ShellExecutor splashScreenExecutor) { - mStartingSurfaceDrawer = new StartingSurfaceDrawer(context, splashScreenExecutor, - new TransactionPool()); - mSplashScreenExecutor = splashScreenExecutor; + this(context, splashScreenExecutor, new TransactionPool()); } public StartingWindowController(Context context, ShellExecutor splashScreenExecutor, TransactionPool pool) { + mContext = context; mStartingSurfaceDrawer = new StartingSurfaceDrawer(context, splashScreenExecutor, pool); mSplashScreenExecutor = splashScreenExecutor; } @@ -90,6 +95,16 @@ public class StartingWindowController { return mImpl; } + @Override + public Context getContext() { + return mContext; + } + + @Override + public ShellExecutor getRemoteCallExecutor() { + return mSplashScreenExecutor; + } + private static class StartingTypeChecker { TaskSnapshot mSnapshot; @@ -188,59 +203,121 @@ public class StartingWindowController { /** * Called when a task need a starting window. */ - void addStartingWindow(StartingWindowInfo windowInfo, IBinder appToken) { - final int suggestionType = mStartingTypeChecker.estimateStartingWindowType(windowInfo); - final RunningTaskInfo runningTaskInfo = windowInfo.taskInfo; - if (mTaskLaunchingCallback != null) { - mTaskLaunchingCallback.accept(runningTaskInfo.taskId, suggestionType); - } - if (suggestionType == STARTING_WINDOW_TYPE_SPLASH_SCREEN) { - mStartingSurfaceDrawer.addSplashScreenStartingWindow(windowInfo, appToken); - } else if (suggestionType == STARTING_WINDOW_TYPE_SNAPSHOT) { - final TaskSnapshot snapshot = mStartingTypeChecker.mSnapshot; - mStartingSurfaceDrawer.makeTaskSnapshotWindow(windowInfo, appToken, snapshot); - } - // If prefer don't show, then don't show! + public void addStartingWindow(StartingWindowInfo windowInfo, IBinder appToken) { + mSplashScreenExecutor.execute(() -> { + final int suggestionType = mStartingTypeChecker.estimateStartingWindowType(windowInfo); + final RunningTaskInfo runningTaskInfo = windowInfo.taskInfo; + if (mTaskLaunchingCallback != null) { + mTaskLaunchingCallback.accept(runningTaskInfo.taskId, suggestionType); + } + if (suggestionType == STARTING_WINDOW_TYPE_SPLASH_SCREEN) { + mStartingSurfaceDrawer.addSplashScreenStartingWindow(windowInfo, appToken); + } else if (suggestionType == STARTING_WINDOW_TYPE_SNAPSHOT) { + final TaskSnapshot snapshot = mStartingTypeChecker.mSnapshot; + mStartingSurfaceDrawer.makeTaskSnapshotWindow(windowInfo, appToken, snapshot); + } + // If prefer don't show, then don't show! + }); } - void copySplashScreenView(int taskId) { - mStartingSurfaceDrawer.copySplashScreenView(taskId); + public void copySplashScreenView(int taskId) { + mSplashScreenExecutor.execute(() -> { + mStartingSurfaceDrawer.copySplashScreenView(taskId); + }); } /** * Called when the content of a task is ready to show, starting window can be removed. */ - void removeStartingWindow(int taskId, SurfaceControl leash, Rect frame, + public void removeStartingWindow(int taskId, SurfaceControl leash, Rect frame, boolean playRevealAnimation) { - mStartingSurfaceDrawer.removeStartingWindow(taskId, leash, frame, playRevealAnimation); + mSplashScreenExecutor.execute(() -> { + mStartingSurfaceDrawer.removeStartingWindow(taskId, leash, frame, playRevealAnimation); + }); } + /** + * The interface for calls from outside the Shell, within the host process. + */ private class StartingSurfaceImpl implements StartingSurface { + private IStartingWindowImpl mIStartingWindow; @Override - public void addStartingWindow(StartingWindowInfo windowInfo, IBinder appToken) { - mSplashScreenExecutor.execute(() -> - StartingWindowController.this.addStartingWindow(windowInfo, appToken)); + public IStartingWindowImpl createExternalInterface() { + if (mIStartingWindow != null) { + mIStartingWindow.invalidate(); + } + mIStartingWindow = new IStartingWindowImpl(StartingWindowController.this); + return mIStartingWindow; + } + } + + /** + * The interface for calls from outside the host process. + */ + @BinderThread + private static class IStartingWindowImpl extends IStartingWindow.Stub { + private StartingWindowController mController; + private IStartingWindowListener mListener; + private final BiConsumer mStartingWindowListener = + this::notifyIStartingWindowListener; + private final IBinder.DeathRecipient mListenerDeathRecipient = + new IBinder.DeathRecipient() { + @Override + @BinderThread + public void binderDied() { + final StartingWindowController controller = mController; + controller.getRemoteCallExecutor().execute(() -> { + mListener = null; + controller.setStartingWindowListener(null); + }); + } + }; + + public IStartingWindowImpl(StartingWindowController controller) { + mController = controller; + } + + /** + * Invalidates this instance, preventing future calls from updating the controller. + */ + void invalidate() { + mController = null; } @Override - public void removeStartingWindow(int taskId, SurfaceControl leash, Rect frame, - boolean playRevealAnimation) { - mSplashScreenExecutor.execute(() -> - StartingWindowController.this.removeStartingWindow(taskId, leash, frame, - playRevealAnimation)); + public void setStartingWindowListener(IStartingWindowListener listener) { + executeRemoteCallWithTaskPermission(mController, "setStartingWindowListener", + (controller) -> { + if (mListener != null) { + // Reset the old death recipient + mListener.asBinder().unlinkToDeath(mListenerDeathRecipient, + 0 /* flags */); + } + if (listener != null) { + try { + listener.asBinder().linkToDeath(mListenerDeathRecipient, + 0 /* flags */); + } catch (RemoteException e) { + Slog.e(TAG, "Failed to link to death"); + return; + } + } + mListener = listener; + controller.setStartingWindowListener(mStartingWindowListener); + }); } - @Override - public void copySplashScreenView(int taskId) { - mSplashScreenExecutor.execute(() -> - StartingWindowController.this.copySplashScreenView(taskId)); - } + private void notifyIStartingWindowListener(int taskId, int supportedType) { + if (mListener == null) { + return; + } - @Override - public void setStartingWindowListener(BiConsumer listener) { - mSplashScreenExecutor.execute(() -> - StartingWindowController.this.setStartingWindowListener(listener)); + try { + mListener.onTaskLaunching(taskId, supportedType); + } catch (RemoteException e) { + Slog.e(TAG, "Failed to notify task launching", e); + } } } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/IShellTransitions.aidl b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/IShellTransitions.aidl new file mode 100644 index 0000000000000..dffc700a36900 --- /dev/null +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/IShellTransitions.aidl @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2021 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.transition; + +import android.window.IRemoteTransition; +import android.window.TransitionFilter; + +/** + * Interface that is exposed to remote callers to manipulate the transitions feature. + */ +interface IShellTransitions { + + /** + * Registers a remote transition handler. + */ + oneway void registerRemote(in TransitionFilter filter, + in IRemoteTransition remoteTransition) = 1; + + /** + * Unregisters a remote transition handler. + */ + oneway void unregisterRemote(in IRemoteTransition remoteTransition) = 2; +} diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitionHandler.java index ac93a17b4014d..9667f4b6a8c54 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitionHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitionHandler.java @@ -16,6 +16,8 @@ package com.android.wm.shell.transition; +import static com.android.wm.shell.common.ExecutorUtils.executeRemoteCallWithTaskPermission; + import android.annotation.NonNull; import android.annotation.Nullable; import android.os.IBinder; @@ -23,6 +25,7 @@ import android.os.RemoteException; import android.util.ArrayMap; import android.util.Log; import android.util.Pair; +import android.util.Slog; import android.view.SurfaceControl; import android.window.IRemoteTransition; import android.window.IRemoteTransitionFinishedCallback; @@ -31,6 +34,8 @@ import android.window.TransitionInfo; import android.window.TransitionRequestInfo; import android.window.WindowContainerTransaction; +import androidx.annotation.BinderThread; + import com.android.internal.protolog.common.ProtoLog; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.protolog.ShellProtoLogGroup; @@ -42,6 +47,8 @@ import java.util.ArrayList; * if the request includes a specific remote. */ public class RemoteTransitionHandler implements Transitions.TransitionHandler { + private static final String TAG = "RemoteTransitionHandler"; + private final ShellExecutor mMainExecutor; /** Includes remotes explicitly requested by, eg, ActivityOptions */ @@ -51,15 +58,33 @@ public class RemoteTransitionHandler implements Transitions.TransitionHandler { private final ArrayList> mFilters = new ArrayList<>(); + private final IBinder.DeathRecipient mTransitionDeathRecipient = + new IBinder.DeathRecipient() { + @Override + @BinderThread + public void binderDied() { + mMainExecutor.execute(() -> { + mFilters.clear(); + }); + } + }; + RemoteTransitionHandler(@NonNull ShellExecutor mainExecutor) { mMainExecutor = mainExecutor; } void addFiltered(TransitionFilter filter, IRemoteTransition remote) { + try { + remote.asBinder().linkToDeath(mTransitionDeathRecipient, 0 /* flags */); + } catch (RemoteException e) { + Slog.e(TAG, "Failed to link to death"); + return; + } mFilters.add(new Pair<>(filter, remote)); } void removeFiltered(IRemoteTransition remote) { + remote.asBinder().unlinkToDeath(mTransitionDeathRecipient, 0 /* flags */); for (int i = mFilters.size() - 1; i >= 0; --i) { if (mFilters.get(i).second == remote) { mFilters.remove(i); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/ShellTransitions.java similarity index 83% rename from libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitions.java rename to libs/WindowManager/Shell/src/com/android/wm/shell/transition/ShellTransitions.java index 85bbf74d56b98..bc42c6e2f12c0 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitions.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/ShellTransitions.java @@ -26,7 +26,15 @@ import com.android.wm.shell.common.annotations.ExternalThread; * Interface to manage remote transitions. */ @ExternalThread -public interface RemoteTransitions { +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 677db10d07a78..ca1b53d4d46bb 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 @@ -23,6 +23,8 @@ import static android.view.WindowManager.TRANSIT_TO_BACK; import static android.view.WindowManager.TRANSIT_TO_FRONT; import static android.window.TransitionInfo.FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT; +import static com.android.wm.shell.common.ExecutorUtils.executeRemoteCallWithTaskPermission; + import android.annotation.NonNull; import android.annotation.Nullable; import android.content.ContentResolver; @@ -51,6 +53,7 @@ import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.protolog.common.ProtoLog; import com.android.wm.shell.ShellTaskOrganizer; +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; @@ -60,7 +63,7 @@ import java.util.ArrayList; import java.util.Arrays; /** Plays transition animations */ -public class Transitions { +public class Transitions implements RemoteCallable { static final String TAG = "ShellTransitions"; /** Set to {@code true} to enable shell transitions. */ @@ -73,7 +76,7 @@ public class Transitions { private final ShellExecutor mAnimExecutor; private final TransitionPlayerImpl mPlayerImpl; private final RemoteTransitionHandler mRemoteTransitionHandler; - private final RemoteTransitionImpl mImpl = new RemoteTransitionImpl(); + private final ShellTransitionImpl mImpl = new ShellTransitionImpl(); /** List of possible handlers. Ordered by specificity (eg. tapped back to front). */ private final ArrayList mHandlers = new ArrayList<>(); @@ -87,10 +90,6 @@ public class Transitions { /** Keeps track of currently tracked transitions and all the animations associated with each */ private final ArrayMap mActiveTransitions = new ArrayMap<>(); - public static RemoteTransitions asRemoteTransitions(Transitions transitions) { - return transitions.mImpl; - } - public Transitions(@NonNull WindowOrganizer organizer, @NonNull TransactionPool pool, @NonNull Context context, @NonNull ShellExecutor mainExecutor, @NonNull ShellExecutor animExecutor) { @@ -126,6 +125,20 @@ public class Transitions { mRemoteTransitionHandler = null; } + public ShellTransitions asRemoteTransitions() { + return mImpl; + } + + @Override + public Context getContext() { + return mContext; + } + + @Override + public ShellExecutor getRemoteCallExecutor() { + return mMainExecutor; + } + private void dispatchAnimScaleSetting(float scale) { for (int i = mHandlers.size() - 1; i >= 0; --i) { mHandlers.get(i).setAnimScaleSetting(scale); @@ -134,8 +147,8 @@ public class Transitions { /** Create an empty/non-registering transitions object for system-ui tests. */ @VisibleForTesting - public static RemoteTransitions createEmptyForTesting() { - return new RemoteTransitions() { + public static ShellTransitions createEmptyForTesting() { + return new ShellTransitions() { @Override public void registerRemote(@androidx.annotation.NonNull TransitionFilter filter, @androidx.annotation.NonNull IRemoteTransition remoteTransition) { @@ -426,24 +439,74 @@ public class Transitions { } } + /** + * The interface for calls from outside the Shell, within the host process. + */ @ExternalThread - private class RemoteTransitionImpl implements RemoteTransitions { + 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 IRemoteTransition remoteTransition) { mMainExecutor.execute(() -> { - Transitions.this.registerRemote(filter, remoteTransition); + mRemoteTransitionHandler.addFiltered(filter, remoteTransition); }); } @Override public void unregisterRemote(@NonNull IRemoteTransition remoteTransition) { mMainExecutor.execute(() -> { - Transitions.this.unregisterRemote(remoteTransition); + mRemoteTransitionHandler.removeFiltered(remoteTransition); }); } } + /** + * The interface for calls from outside the host process. + */ + @BinderThread + private static class IShellTransitionsImpl extends IShellTransitions.Stub { + private Transitions mTransitions; + + IShellTransitionsImpl(Transitions transitions) { + mTransitions = transitions; + } + + /** + * Invalidates this instance, preventing future calls from updating the controller. + */ + void invalidate() { + mTransitions = null; + } + + @Override + public void registerRemote(@NonNull TransitionFilter filter, + @NonNull IRemoteTransition remoteTransition) { + executeRemoteCallWithTaskPermission(mTransitions, "registerRemote", + (transitions) -> { + transitions.mRemoteTransitionHandler.addFiltered(filter, remoteTransition); + }); + } + + @Override + public void unregisterRemote(@NonNull IRemoteTransition remoteTransition) { + executeRemoteCallWithTaskPermission(mTransitions, "unregisterRemote", + (transitions) -> { + transitions.mRemoteTransitionHandler.removeFiltered(remoteTransition); + }); + } + } + private class SettingsObserver extends ContentObserver { SettingsObserver() { diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropPolicyTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropPolicyTest.java index c1c4c6dd08d75..2f2bbba11646e 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropPolicyTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropPolicyTest.java @@ -205,7 +205,7 @@ public class DragAndDropPolicyTest { mPolicy.getTargets(mInsets), TYPE_FULLSCREEN); mPolicy.handleDrop(filterTargetByType(targets, TYPE_FULLSCREEN), mActivityClipData); - verify(mSplitScreenStarter).startIntent(any(), any(), any(), + verify(mSplitScreenStarter).startIntent(any(), any(), eq(STAGE_TYPE_UNDEFINED), eq(STAGE_POSITION_UNDEFINED), any()); } @@ -217,12 +217,12 @@ public class DragAndDropPolicyTest { mPolicy.getTargets(mInsets), TYPE_FULLSCREEN, TYPE_SPLIT_LEFT, TYPE_SPLIT_RIGHT); mPolicy.handleDrop(filterTargetByType(targets, TYPE_FULLSCREEN), mActivityClipData); - verify(mSplitScreenStarter).startIntent(any(), any(), any(), + verify(mSplitScreenStarter).startIntent(any(), any(), eq(STAGE_TYPE_UNDEFINED), eq(STAGE_POSITION_UNDEFINED), any()); reset(mSplitScreenStarter); mPolicy.handleDrop(filterTargetByType(targets, TYPE_SPLIT_RIGHT), mActivityClipData); - verify(mSplitScreenStarter).startIntent(any(), any(), any(), + verify(mSplitScreenStarter).startIntent(any(), any(), eq(STAGE_TYPE_SIDE), eq(STAGE_POSITION_BOTTOM_OR_RIGHT), any()); } @@ -234,12 +234,12 @@ public class DragAndDropPolicyTest { mPolicy.getTargets(mInsets), TYPE_FULLSCREEN, TYPE_SPLIT_TOP, TYPE_SPLIT_BOTTOM); mPolicy.handleDrop(filterTargetByType(targets, TYPE_FULLSCREEN), mActivityClipData); - verify(mSplitScreenStarter).startIntent(any(), any(), any(), + verify(mSplitScreenStarter).startIntent(any(), any(), eq(STAGE_TYPE_UNDEFINED), eq(STAGE_POSITION_UNDEFINED), any()); reset(mSplitScreenStarter); mPolicy.handleDrop(filterTargetByType(targets, TYPE_SPLIT_BOTTOM), mActivityClipData); - verify(mSplitScreenStarter).startIntent(any(), any(), any(), + verify(mSplitScreenStarter).startIntent(any(), any(), eq(STAGE_TYPE_SIDE), eq(STAGE_POSITION_BOTTOM_OR_RIGHT), any()); } @@ -251,7 +251,7 @@ public class DragAndDropPolicyTest { mPolicy.getTargets(mInsets), TYPE_FULLSCREEN, TYPE_SPLIT_LEFT, TYPE_SPLIT_RIGHT); mPolicy.handleDrop(filterTargetByType(targets, TYPE_FULLSCREEN), mActivityClipData); - verify(mSplitScreenStarter).startIntent(any(), any(), any(), + verify(mSplitScreenStarter).startIntent(any(), any(), eq(STAGE_TYPE_UNDEFINED), eq(STAGE_POSITION_UNDEFINED), any()); } @@ -263,7 +263,7 @@ public class DragAndDropPolicyTest { mPolicy.getTargets(mInsets), TYPE_FULLSCREEN, TYPE_SPLIT_LEFT, TYPE_SPLIT_RIGHT); mPolicy.handleDrop(filterTargetByType(targets, TYPE_FULLSCREEN), mActivityClipData); - verify(mSplitScreenStarter).startIntent(any(), any(), any(), + verify(mSplitScreenStarter).startIntent(any(), any(), eq(STAGE_TYPE_UNDEFINED), eq(STAGE_POSITION_UNDEFINED), any()); } @@ -276,13 +276,13 @@ public class DragAndDropPolicyTest { mPolicy.getTargets(mInsets), TYPE_FULLSCREEN, TYPE_SPLIT_LEFT, TYPE_SPLIT_RIGHT); mPolicy.handleDrop(filterTargetByType(targets, TYPE_FULLSCREEN), mActivityClipData); - verify(mSplitScreenStarter).startIntent(any(), any(), any(), + verify(mSplitScreenStarter).startIntent(any(), any(), eq(STAGE_TYPE_UNDEFINED), eq(STAGE_POSITION_UNDEFINED), any()); reset(mSplitScreenStarter); // TODO(b/169894807): Just verify starting for the non-docked task until we have app pairs mPolicy.handleDrop(filterTargetByType(targets, TYPE_SPLIT_RIGHT), mActivityClipData); - verify(mSplitScreenStarter).startIntent(any(), any(), any(), + verify(mSplitScreenStarter).startIntent(any(), any(), eq(STAGE_TYPE_SIDE), eq(STAGE_POSITION_BOTTOM_OR_RIGHT), any()); } @@ -295,13 +295,13 @@ public class DragAndDropPolicyTest { mPolicy.getTargets(mInsets), TYPE_FULLSCREEN, TYPE_SPLIT_TOP, TYPE_SPLIT_BOTTOM); mPolicy.handleDrop(filterTargetByType(targets, TYPE_FULLSCREEN), mActivityClipData); - verify(mSplitScreenStarter).startIntent(any(), any(), any(), + verify(mSplitScreenStarter).startIntent(any(), any(), eq(STAGE_TYPE_UNDEFINED), eq(STAGE_POSITION_UNDEFINED), any()); reset(mSplitScreenStarter); // TODO(b/169894807): Just verify starting for the non-docked task until we have app pairs mPolicy.handleDrop(filterTargetByType(targets, TYPE_SPLIT_BOTTOM), mActivityClipData); - verify(mSplitScreenStarter).startIntent(any(), any(), any(), + verify(mSplitScreenStarter).startIntent(any(), any(), eq(STAGE_TYPE_SIDE), eq(STAGE_POSITION_BOTTOM_OR_RIGHT), any()); } diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl index 7cb8f86a9a947..2103de2ae85c0 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl @@ -16,8 +16,6 @@ package com.android.systemui.shared.recents; -import android.app.PendingIntent; -import android.content.Intent; import android.graphics.Bitmap; import android.graphics.Insets; import android.graphics.Rect; @@ -25,14 +23,11 @@ import android.os.Bundle; import android.os.UserHandle; import android.view.MotionEvent; -import com.android.systemui.shared.recents.ISplitScreenListener; -import com.android.systemui.shared.recents.IStartingWindowListener; import com.android.systemui.shared.recents.model.Task; import com.android.systemui.shared.system.RemoteTransitionCompat; /** * Temporary callbacks into SystemUI. - * Next id = 44 */ interface ISystemUiProxy { @@ -134,16 +129,6 @@ interface ISystemUiProxy { */ void onQuickSwitchToNewTask(int rotation) = 25; - /** - * Start the one-handed mode. - */ - void startOneHandedMode() = 26; - - /** - * Stop the one-handed mode. - */ - void stopOneHandedMode() = 27; - /** * Handle the provided image as if it was a screenshot. */ @@ -155,65 +140,5 @@ interface ISystemUiProxy { */ void expandNotificationPanel() = 29; - /** - * Registers a RemoteTransitionCompat that will handle transitions. This parameter bundles an - * IRemoteTransition and a filter that must pass for it. - */ - void registerRemoteTransition(in RemoteTransitionCompat remoteTransition) = 32; - - /** Unegisters a RemoteTransitionCompat that will handle transitions. */ - void unregisterRemoteTransition(in RemoteTransitionCompat remoteTransition) = 33; - -// SplitScreen APIs...copied from SplitScreen.java - /** - * Stage position isn't specified normally meaning to use what ever it is currently set to. - */ - //int STAGE_POSITION_UNDEFINED = -1; - /** - * Specifies that a stage is positioned at the top half of the screen if - * in portrait mode or at the left half of the screen if in landscape mode. - */ - //int STAGE_POSITION_TOP_OR_LEFT = 0; - /** - * Specifies that a stage is positioned at the bottom half of the screen if - * in portrait mode or at the right half of the screen if in landscape mode. - */ - //int STAGE_POSITION_BOTTOM_OR_RIGHT = 1; - - /** - * Stage type isn't specified normally meaning to use what ever the default is. - * E.g. exit split-screen and launch the app in fullscreen. - */ - //int STAGE_TYPE_UNDEFINED = -1; - /** - * The main stage type. - * @see MainStage - */ - //int STAGE_TYPE_MAIN = 0; - /** - * The side stage type. - * @see SideStage - */ - //int STAGE_TYPE_SIDE = 1; - - void registerSplitScreenListener(in ISplitScreenListener listener) = 34; - void unregisterSplitScreenListener(in ISplitScreenListener listener) = 35; - - /** Hides the side-stage if it is currently visible. */ - void setSideStageVisibility(in boolean visible) = 36; - /** Removes the split-screen stages. */ - void exitSplitScreen() = 37; - /** @param exitSplitScreenOnHide if to exit split-screen if both stages are not visible. */ - void exitSplitScreenOnHide(boolean exitSplitScreenOnHide) = 38; - void startTask(in int taskId, in int stage, in int position, in Bundle options) = 39; - void startShortcut(in String packageName, in String shortcutId, in int stage, in int position, - in Bundle options, in UserHandle user) = 40; - void startIntent( - in PendingIntent intent, in Intent fillInIntent, in int stage, in int position, - in Bundle options) = 41; - void removeFromSideStage(in int taskId) = 42; - /** - * Sets listener to get task launching callbacks. - */ - void setStartingWindowListener(IStartingWindowListener listener) = 43; + // Next id = 44 } 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 55a6d34d65728..41840afc49953 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,6 +43,16 @@ public class QuickStepContract { 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 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"; public static final String NAV_BAR_MODE_2BUTTON_OVERLAY = WindowManagerPolicyConstants.NAV_BAR_MODE_2BUTTON_OVERLAY; diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java index 8f79de5184196..ed3d5ec33b41e 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java @@ -34,7 +34,7 @@ import com.android.wm.shell.onehanded.OneHanded; import com.android.wm.shell.pip.Pip; import com.android.wm.shell.splitscreen.SplitScreen; import com.android.wm.shell.startingsurface.StartingSurface; -import com.android.wm.shell.transition.RemoteTransitions; +import com.android.wm.shell.transition.ShellTransitions; import java.util.Optional; @@ -87,7 +87,7 @@ public interface SysUIComponent { Builder setShellCommandHandler(Optional shellDump); @BindsInstance - Builder setTransitions(RemoteTransitions t); + Builder setTransitions(ShellTransitions t); @BindsInstance Builder setStartingSurface(Optional s); diff --git a/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java index 1b77d1c166394..bbd95b4d0c900 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java @@ -33,7 +33,7 @@ import com.android.wm.shell.onehanded.OneHanded; import com.android.wm.shell.pip.Pip; import com.android.wm.shell.splitscreen.SplitScreen; import com.android.wm.shell.startingsurface.StartingSurface; -import com.android.wm.shell.transition.RemoteTransitions; +import com.android.wm.shell.transition.ShellTransitions; import java.util.Optional; @@ -98,7 +98,7 @@ public interface WMComponent { Optional getTaskViewFactory(); @WMSingleton - RemoteTransitions getTransitions(); + ShellTransitions getTransitions(); @WMSingleton Optional getStartingSurface(); diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java index 3cc481b95b396..5a714f2ed3840 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java +++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java @@ -25,7 +25,11 @@ 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_INPUT_MONITOR; +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_WINDOW_CORNER_RADIUS; @@ -36,15 +40,12 @@ import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_T import android.annotation.FloatRange; import android.app.ActivityTaskManager; -import android.app.PendingIntent; -import android.app.PictureInPictureParams; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.ServiceConnection; -import android.content.pm.ActivityInfo; import android.graphics.Bitmap; import android.graphics.Insets; import android.graphics.Rect; @@ -58,14 +59,12 @@ import android.os.Looper; import android.os.PatternMatcher; import android.os.RemoteException; import android.os.UserHandle; -import android.util.ArraySet; import android.util.Log; import android.view.InputMonitor; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.Surface; import android.view.accessibility.AccessibilityManager; -import android.window.IRemoteTransition; import androidx.annotation.NonNull; @@ -84,14 +83,11 @@ import com.android.systemui.navigationbar.NavigationModeController; import com.android.systemui.recents.OverviewProxyService.OverviewProxyListener; import com.android.systemui.settings.CurrentUserTracker; import com.android.systemui.shared.recents.IOverviewProxy; -import com.android.systemui.shared.recents.ISplitScreenListener; -import com.android.systemui.shared.recents.IStartingWindowListener; import com.android.systemui.shared.recents.ISystemUiProxy; import com.android.systemui.shared.recents.model.Task; import com.android.systemui.shared.system.ActivityManagerWrapper; import com.android.systemui.shared.system.InputMonitorCompat; import com.android.systemui.shared.system.QuickStepContract; -import com.android.systemui.shared.system.RemoteTransitionCompat; import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.NotificationShadeWindowController; import com.android.systemui.statusbar.phone.StatusBar; @@ -103,7 +99,7 @@ import com.android.wm.shell.pip.Pip; import com.android.wm.shell.pip.PipAnimationController; import com.android.wm.shell.splitscreen.SplitScreen; import com.android.wm.shell.startingsurface.StartingSurface; -import com.android.wm.shell.transition.RemoteTransitions; +import com.android.wm.shell.transition.ShellTransitions; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -111,7 +107,6 @@ import java.util.ArrayList; import java.util.List; import java.util.Optional; import java.util.function.BiConsumer; -import java.util.function.Consumer; import javax.inject.Inject; @@ -151,7 +146,7 @@ public class OverviewProxyService extends CurrentUserTracker implements private final ScreenshotHelper mScreenshotHelper; private final Optional mOneHandedOptional; private final CommandQueue mCommandQueue; - private final RemoteTransitions mShellTransitions; + private final ShellTransitions mShellTransitions; private final Optional mStartingSurface; private Region mActiveNavBarRegion; @@ -168,8 +163,6 @@ public class OverviewProxyService extends CurrentUserTracker implements private float mWindowCornerRadius; private boolean mSupportsRoundedCornersOnWindows; private int mNavBarMode = NAV_BAR_MODE_3BUTTON; - private final ArraySet mRemoteTransitions = new ArraySet<>(); - private IStartingWindowListener mIStartingWindowListener; @VisibleForTesting public ISystemUiProxy mSysUiProxy = new ISystemUiProxy.Stub() { @@ -413,21 +406,6 @@ public class OverviewProxyService extends CurrentUserTracker implements } } - @Override - public void setStartingWindowListener(IStartingWindowListener listener) { - if (!verifyCaller("setStartingWindowListener")) { - return; - } - mIStartingWindowListener = listener; - final long token = Binder.clearCallingIdentity(); - try { - mStartingSurface.ifPresent(s -> - s.setStartingWindowListener(mStartingWindowListener)); - } finally { - Binder.restoreCallingIdentity(token); - } - } - @Override public void onQuickSwitchToNewTask(@Surface.Rotation int rotation) { if (!verifyCaller("onQuickSwitchToNewTask")) { @@ -441,32 +419,6 @@ public class OverviewProxyService extends CurrentUserTracker implements } } - @Override - public void startOneHandedMode() { - if (!verifyCaller("startOneHandedMode")) { - return; - } - final long token = Binder.clearCallingIdentity(); - try { - mOneHandedOptional.ifPresent(oneHanded -> oneHanded.startOneHanded()); - } finally { - Binder.restoreCallingIdentity(token); - } - } - - @Override - public void stopOneHandedMode() { - if (!verifyCaller("stopOneHandedMode")) { - return; - } - final long token = Binder.clearCallingIdentity(); - try { - mOneHandedOptional.ifPresent(oneHanded -> oneHanded.stopOneHanded()); - } finally { - Binder.restoreCallingIdentity(token); - } - } - @Override public void handleImageBundleAsScreenshot(Bundle screenImageBundle, Rect locationInScreen, Insets visibleInsets, Task.TaskKey task) { @@ -495,158 +447,6 @@ public class OverviewProxyService extends CurrentUserTracker implements } } - @Override - public void registerRemoteTransition(RemoteTransitionCompat remoteTransition) { - if (!verifyCaller("registerRemoteTransition")) return; - final long binderToken = Binder.clearCallingIdentity(); - try { - mRemoteTransitions.add(remoteTransition.getTransition()); - mShellTransitions.registerRemote( - remoteTransition.getFilter(), remoteTransition.getTransition()); - } finally { - Binder.restoreCallingIdentity(binderToken); - } - } - - @Override - public void unregisterRemoteTransition(RemoteTransitionCompat remoteTransition) { - if (!verifyCaller("registerRemoteTransition")) return; - final long binderToken = Binder.clearCallingIdentity(); - try { - mRemoteTransitions.remove(remoteTransition.getTransition()); - mShellTransitions.unregisterRemote(remoteTransition.getTransition()); - } finally { - Binder.restoreCallingIdentity(binderToken); - } - } - - @Override - public void registerSplitScreenListener(ISplitScreenListener listener) { - if (!verifyCaller("registerSplitScreenListener")) { - return; - } - mISplitScreenListener = listener; - final long token = Binder.clearCallingIdentity(); - try { - mSplitScreenOptional.ifPresent( - s -> s.registerSplitScreenListener(mSplitScreenListener)); - } finally { - Binder.restoreCallingIdentity(token); - } - } - - @Override - public void unregisterSplitScreenListener(ISplitScreenListener listener) { - if (!verifyCaller("unregisterSplitScreenListener")) { - return; - } - mISplitScreenListener = null; - final long token = Binder.clearCallingIdentity(); - try { - mSplitScreenOptional.ifPresent( - s -> s.unregisterSplitScreenListener(mSplitScreenListener)); - } finally { - Binder.restoreCallingIdentity(token); - } - } - - @Override - public void setSideStageVisibility(boolean visible) { - if (!verifyCaller("setSideStageVisibility")) { - return; - } - final long token = Binder.clearCallingIdentity(); - try { - mSplitScreenOptional.ifPresent(s -> s.setSideStageVisibility(visible)); - } finally { - Binder.restoreCallingIdentity(token); - } - } - - @Override - public void exitSplitScreen() { - if (!verifyCaller("exitSplitScreen")) { - return; - } - final long token = Binder.clearCallingIdentity(); - try { - mSplitScreenOptional.ifPresent(s -> s.exitSplitScreen()); - } finally { - Binder.restoreCallingIdentity(token); - } - } - - @Override - public void exitSplitScreenOnHide(boolean exitSplitScreenOnHide) { - if (!verifyCaller("exitSplitScreenOnHide")) { - return; - } - final long token = Binder.clearCallingIdentity(); - try { - mSplitScreenOptional.ifPresent(s -> s.exitSplitScreenOnHide(exitSplitScreenOnHide)); - } finally { - Binder.restoreCallingIdentity(token); - } - } - - @Override - public void startTask(int taskId, int stage, int position, Bundle options) { - if (!verifyCaller("startTask")) { - return; - } - final long token = Binder.clearCallingIdentity(); - try { - mSplitScreenOptional.ifPresent( - s -> s.startTask(taskId, stage, position, options)); - } finally { - Binder.restoreCallingIdentity(token); - } - } - - @Override - public void startShortcut(String packageName, String shortcutId, int stage, int position, - Bundle options, UserHandle user) { - if (!verifyCaller("startShortcut")) { - return; - } - final long token = Binder.clearCallingIdentity(); - try { - mSplitScreenOptional.ifPresent(s -> - s.startShortcut(packageName, shortcutId, stage, position, options, user)); - } finally { - Binder.restoreCallingIdentity(token); - } - } - - @Override - public void startIntent(PendingIntent intent, Intent fillInIntent, - int stage, int position, Bundle options) { - if (!verifyCaller("startIntent")) { - return; - } - final long token = Binder.clearCallingIdentity(); - try { - mSplitScreenOptional.ifPresent(s -> - s.startIntent(intent, mContext, fillInIntent, stage, position, options)); - } finally { - Binder.restoreCallingIdentity(token); - } - } - - @Override - public void removeFromSideStage(int taskId) { - if (!verifyCaller("removeFromSideStage")) { - return; - } - final long token = Binder.clearCallingIdentity(); - try { - mSplitScreenOptional.ifPresent( - s -> s.removeFromSideStage(taskId)); - } finally { - Binder.restoreCallingIdentity(token); - } - } - private boolean verifyCaller(String reason) { final int callerId = Binder.getCallingUserHandle().getIdentifier(); if (callerId != mCurrentBoundedUserId) { @@ -701,8 +501,20 @@ public class OverviewProxyService extends CurrentUserTracker implements 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, + 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())); + 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())); try { mOverviewProxy.onInitialize(params); @@ -744,39 +556,10 @@ public class OverviewProxyService extends CurrentUserTracker implements private final BiConsumer mSplitScreenBoundsChangeListener = this::notifySplitScreenBoundsChanged; - private final BiConsumer mStartingWindowListener = - this::notifyTaskLaunching; - // This is the death handler for the binder from the launcher service private final IBinder.DeathRecipient mOverviewServiceDeathRcpt = this::cleanupAfterDeath; - private ISplitScreenListener mISplitScreenListener; - private final SplitScreen.SplitScreenListener mSplitScreenListener = - new SplitScreen.SplitScreenListener() { - @Override - public void onStagePositionChanged(int stage, int position) { - try { - if (mISplitScreenListener != null) { - mISplitScreenListener.onStagePositionChanged(stage, position); - } - } catch (RemoteException e) { - Log.e(TAG_OPS, "onStagePositionChanged", e); - } - } - - @Override - public void onTaskStageChanged(int taskId, int stage, boolean visible) { - try { - if (mISplitScreenListener != null) { - mISplitScreenListener.onTaskStageChanged(taskId, stage, visible); - } - } catch (RemoteException e) { - Log.e(TAG_OPS, "onTaskStageChanged", e); - } - } - }; - @SuppressWarnings("OptionalUsedAsFieldOrParameterType") @Inject public OverviewProxyService(Context context, CommandQueue commandQueue, @@ -789,7 +572,7 @@ public class OverviewProxyService extends CurrentUserTracker implements Optional> statusBarOptionalLazy, Optional oneHandedOptional, BroadcastDispatcher broadcastDispatcher, - RemoteTransitions shellTransitions, + ShellTransitions shellTransitions, Optional startingSurface) { super(broadcastDispatcher); mContext = context; @@ -906,18 +689,6 @@ public class OverviewProxyService extends CurrentUserTracker implements } } - private void notifyTaskLaunching(int taskId, int supportedType) { - if (mIStartingWindowListener == null) { - return; - } - - try { - mIStartingWindowListener.onTaskLaunching(taskId, supportedType); - } catch (RemoteException e) { - Log.e(TAG_OPS, "Failed to call notifyTaskLaunching()", e); - } - } - private void onStatusBarStateChanged(boolean keyguardShowing, boolean keyguardOccluded, boolean bouncerShowing) { mSysUiState.setFlag(SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING, @@ -961,12 +732,6 @@ public class OverviewProxyService extends CurrentUserTracker implements // Clean up the minimized state if launcher dies mLegacySplitScreenOptional.ifPresent( splitScreen -> splitScreen.setMinimized(false)); - - // Clean up any registered remote transitions - for (int i = mRemoteTransitions.size() - 1; i >= 0; --i) { - mShellTransitions.unregisterRemote(mRemoteTransitions.valueAt(i)); - } - mRemoteTransitions.clear(); } public void startConnectionToCurrentUser() { diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java index c3ecb5c1f08b5..1d18750f1fdf7 100644 --- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java +++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java @@ -81,7 +81,7 @@ import com.android.wm.shell.splitscreen.SplitScreen; import com.android.wm.shell.splitscreen.SplitScreenController; import com.android.wm.shell.startingsurface.StartingSurface; import com.android.wm.shell.startingsurface.StartingWindowController; -import com.android.wm.shell.transition.RemoteTransitions; +import com.android.wm.shell.transition.ShellTransitions; import com.android.wm.shell.transition.Transitions; import java.util.Optional; @@ -399,8 +399,8 @@ public abstract class WMShellBaseModule { @WMSingleton @Provides - static RemoteTransitions provideRemoteTransitions(Transitions transitions) { - return Transitions.asRemoteTransitions(transitions); + static ShellTransitions provideRemoteTransitions(Transitions transitions) { + return transitions.asRemoteTransitions(); } @WMSingleton @@ -521,10 +521,10 @@ public abstract class WMShellBaseModule { Optional legacySplitScreenOptional, Optional splitScreenOptional, Optional appPairsOptional, - Optional startingSurface, Optional pipTouchHandlerOptional, FullscreenTaskListener fullscreenTaskListener, Transitions transitions, + StartingWindowController startingWindow, @ShellMainThread ShellExecutor mainExecutor) { return new ShellInitImpl(displayImeController, dragAndDropController, @@ -532,10 +532,10 @@ public abstract class WMShellBaseModule { legacySplitScreenOptional, splitScreenOptional, appPairsOptional, - startingSurface, pipTouchHandlerOptional, fullscreenTaskListener, transitions, + startingWindow, mainExecutor); }