diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java index 8e24e0b516cb5..f3749220d4e1a 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java @@ -377,12 +377,10 @@ public class StartingSurfaceDrawer { final int taskId = startingWindowInfo.taskInfo.taskId; final TaskSnapshotWindow surface = TaskSnapshotWindow.create(startingWindowInfo, appToken, snapshot, mMainExecutor, () -> removeWindowSynced(taskId) /* clearWindow */); - mMainExecutor.execute(() -> { - mMainExecutor.executeDelayed(() -> removeWindowSynced(taskId), REMOVE_WHEN_TIMEOUT); - final StartingWindowRecord tView = - new StartingWindowRecord(null/* decorView */, surface); - mStartingWindowRecords.put(taskId, tView); - }); + mMainExecutor.executeDelayed(() -> removeWindowSynced(taskId), REMOVE_WHEN_TIMEOUT); + final StartingWindowRecord tView = + new StartingWindowRecord(null/* decorView */, surface); + mStartingWindowRecords.put(taskId, tView); } /** @@ -392,42 +390,40 @@ public class StartingSurfaceDrawer { if (DEBUG_SPLASH_SCREEN || DEBUG_TASK_SNAPSHOT) { Slog.d(TAG, "Task start finish, remove starting surface for task " + taskId); } - mMainExecutor.execute(() -> removeWindowSynced(taskId)); + removeWindowSynced(taskId); } protected void postAddWindow(int taskId, IBinder appToken, - View view, WindowManager wm, WindowManager.LayoutParams params) { - mMainExecutor.execute(() -> { - boolean shouldSaveView = true; - try { - wm.addView(view, params); - } catch (WindowManager.BadTokenException e) { - // ignore - Slog.w(TAG, appToken + " already running, starting window not displayed. " - + e.getMessage()); + View view, WindowManager wm, WindowManager.LayoutParams params) { + boolean shouldSaveView = true; + try { + wm.addView(view, params); + } catch (WindowManager.BadTokenException e) { + // ignore + Slog.w(TAG, appToken + " already running, starting window not displayed. " + + e.getMessage()); + shouldSaveView = false; + } catch (RuntimeException e) { + // don't crash if something else bad happens, for example a + // failure loading resources because we are loading from an app + // on external storage that has been unmounted. + Slog.w(TAG, appToken + " failed creating starting window", e); + shouldSaveView = false; + } finally { + if (view != null && view.getParent() == null) { + Slog.w(TAG, "view not successfully added to wm, removing view"); + wm.removeViewImmediate(view); shouldSaveView = false; - } catch (RuntimeException e) { - // don't crash if something else bad happens, for example a - // failure loading resources because we are loading from an app - // on external storage that has been unmounted. - Slog.w(TAG, appToken + " failed creating starting window", e); - shouldSaveView = false; - } finally { - if (view != null && view.getParent() == null) { - Slog.w(TAG, "view not successfully added to wm, removing view"); - wm.removeViewImmediate(view); - shouldSaveView = false; - } } + } - if (shouldSaveView) { - removeWindowSynced(taskId); - mMainExecutor.executeDelayed(() -> removeWindowSynced(taskId), REMOVE_WHEN_TIMEOUT); - final StartingWindowRecord tView = - new StartingWindowRecord(view, null /* TaskSnapshotWindow */); - mStartingWindowRecords.put(taskId, tView); - } - }); + if (shouldSaveView) { + removeWindowSynced(taskId); + mMainExecutor.executeDelayed(() -> removeWindowSynced(taskId), REMOVE_WHEN_TIMEOUT); + final StartingWindowRecord tView = + new StartingWindowRecord(view, null /* TaskSnapshotWindow */); + mStartingWindowRecords.put(taskId, tView); + } } protected void removeWindowSynced(int taskId) { @@ -445,7 +441,7 @@ public class StartingSurfaceDrawer { if (DEBUG_TASK_SNAPSHOT) { Slog.v(TAG, "Removing task snapshot window for " + taskId); } - record.mTaskSnapshotWindow.remove(mMainExecutor); + record.mTaskSnapshotWindow.remove(); } mStartingWindowRecords.remove(taskId); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java index b5e18960ff5ce..a6f44efd76458 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java @@ -82,6 +82,7 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.policy.DecorView; import com.android.internal.view.BaseIWindow; import com.android.wm.shell.common.ShellExecutor; +import com.android.wm.shell.common.annotations.ExternalThread; /** * This class represents a starting window that shows a snapshot. @@ -121,6 +122,7 @@ public class TaskSnapshotWindow { private final Window mWindow; private final Surface mSurface; private final Runnable mClearWindowHandler; + private final ShellExecutor mMainExecutor; private SurfaceControl mSurfaceControl; private SurfaceControl mChildSurfaceControl; private final IWindowSession mSession; @@ -213,7 +215,7 @@ public class TaskSnapshotWindow { final TaskSnapshotWindow snapshotSurface = new TaskSnapshotWindow( surfaceControl, snapshot, layoutParams.getTitle(), taskDescription, appearance, windowFlags, windowPrivateFlags, taskBounds, orientation, activityType, - topWindowInsetsState, clearWindowHandler); + topWindowInsetsState, clearWindowHandler, mainExecutor); final Window window = snapshotSurface.mWindow; final InsetsState mTmpInsetsState = new InsetsState(); @@ -229,7 +231,7 @@ public class TaskSnapshotWindow { } catch (RemoteException e) { snapshotSurface.clearWindowSynced(); } - window.setOuter(snapshotSurface, mainExecutor); + window.setOuter(snapshotSurface); try { session.relayout(window, layoutParams, -1, -1, View.VISIBLE, 0, -1, tmpFrames, tmpMergedConfiguration, surfaceControl, mTmpInsetsState, @@ -249,7 +251,8 @@ public class TaskSnapshotWindow { TaskSnapshot snapshot, CharSequence title, TaskDescription taskDescription, int appearance, int windowFlags, int windowPrivateFlags, Rect taskBounds, int currentOrientation, int activityType, InsetsState topWindowInsetsState, - Runnable clearWindowHandler) { + Runnable clearWindowHandler, ShellExecutor mainExecutor) { + mMainExecutor = mainExecutor; mSurface = new Surface(); mSession = WindowManagerGlobal.getWindowSession(); mWindow = new Window(); @@ -286,28 +289,26 @@ public class TaskSnapshotWindow { mSystemBarBackgroundPainter.drawNavigationBarBackground(c); } - void remove(ShellExecutor mainExecutor) { + void remove() { final long now = SystemClock.uptimeMillis(); if (mSizeMismatch && now - mShownTime < SIZE_MISMATCH_MINIMUM_TIME_MS // Show the latest content as soon as possible for unlocking to home. && mActivityType != ACTIVITY_TYPE_HOME) { final long delayTime = mShownTime + SIZE_MISMATCH_MINIMUM_TIME_MS - now; - mainExecutor.executeDelayed(() -> remove(mainExecutor), delayTime); + mMainExecutor.executeDelayed(() -> remove(), delayTime); if (DEBUG) { Slog.d(TAG, "Defer removing snapshot surface in " + delayTime); } return; } - mainExecutor.execute(() -> { - try { - if (DEBUG) { - Slog.d(TAG, "Removing snapshot surface, mHasDrawn: " + mHasDrawn); - } - mSession.remove(mWindow); - } catch (RemoteException e) { - // nothing + try { + if (DEBUG) { + Slog.d(TAG, "Removing snapshot surface, mHasDrawn: " + mHasDrawn); } - }); + mSession.remove(mWindow); + } catch (RemoteException e) { + // nothing + } } /** @@ -497,13 +498,12 @@ public class TaskSnapshotWindow { } } + @ExternalThread static class Window extends BaseIWindow { private TaskSnapshotWindow mOuter; - private ShellExecutor mMainExecutor; - public void setOuter(TaskSnapshotWindow outer, ShellExecutor mainExecutor) { + public void setOuter(TaskSnapshotWindow outer) { mOuter = outer; - mMainExecutor = mainExecutor; } @Override @@ -511,22 +511,20 @@ public class TaskSnapshotWindow { MergedConfiguration mergedConfiguration, boolean forceLayout, boolean alwaysConsumeSystemBars, int displayId) { if (mOuter != null) { - if (mergedConfiguration != null - && mOuter.mOrientationOnCreation - != mergedConfiguration.getMergedConfiguration().orientation) { - // The orientation of the screen is changing. We better remove the snapshot ASAP - // as we are going to wait on the new window in any case to unfreeze the screen, - // and the starting window is not needed anymore. - mMainExecutor.execute(() -> { + mOuter.mMainExecutor.execute(() -> { + if (mergedConfiguration != null + && mOuter.mOrientationOnCreation + != mergedConfiguration.getMergedConfiguration().orientation) { + // The orientation of the screen is changing. We better remove the snapshot + // ASAP as we are going to wait on the new window in any case to unfreeze + // the screen, and the starting window is not needed anymore. mOuter.clearWindowSynced(); - }); - } else if (reportDraw) { - mMainExecutor.execute(() -> { + } else if (reportDraw) { if (mOuter.mHasDrawn) { mOuter.reportDrawn(); } - }); - } + } + }); } } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitions.java new file mode 100644 index 0000000000000..85bbf74d56b98 --- /dev/null +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitions.java @@ -0,0 +1,40 @@ +/* + * 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.annotation.NonNull; +import android.window.IRemoteTransition; +import android.window.TransitionFilter; + +import com.android.wm.shell.common.annotations.ExternalThread; + +/** + * Interface to manage remote transitions. + */ +@ExternalThread +public interface RemoteTransitions { + /** + * Registers a remote transition. + */ + void registerRemote(@NonNull TransitionFilter filter, + @NonNull IRemoteTransition remoteTransition); + + /** + * Unregisters a remote transition. + */ + void unregisterRemote(@NonNull IRemoteTransition remoteTransition); +} 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 2ab4e0bdd76f1..0e171f6b41a35 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 @@ -67,6 +67,7 @@ public class Transitions { private final ShellExecutor mAnimExecutor; private final TransitionPlayerImpl mPlayerImpl; private final RemoteTransitionHandler mRemoteTransitionHandler; + private final RemoteTransitionImpl mImpl = new RemoteTransitionImpl(); /** List of possible handlers. Ordered by specificity (eg. tapped back to front). */ private final ArrayList mHandlers = new ArrayList<>(); @@ -78,6 +79,10 @@ 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 ShellExecutor mainExecutor, @NonNull ShellExecutor animExecutor) { mOrganizer = organizer; @@ -101,8 +106,20 @@ public class Transitions { /** Create an empty/non-registering transitions object for system-ui tests. */ @VisibleForTesting - public static Transitions createEmptyForTesting() { - return new Transitions(); + public static RemoteTransitions createEmptyForTesting() { + return new RemoteTransitions() { + @Override + public void registerRemote(@androidx.annotation.NonNull TransitionFilter filter, + @androidx.annotation.NonNull IRemoteTransition remoteTransition) { + // Do nothing + } + + @Override + public void unregisterRemote( + @androidx.annotation.NonNull IRemoteTransition remoteTransition) { + // Do nothing + } + }; } /** Register this transition handler with Core */ @@ -134,16 +151,14 @@ public class Transitions { } /** Register a remote transition to be used when `filter` matches an incoming transition */ - @ExternalThread public void registerRemote(@NonNull TransitionFilter filter, @NonNull IRemoteTransition remoteTransition) { - mMainExecutor.execute(() -> mRemoteTransitionHandler.addFiltered(filter, remoteTransition)); + mRemoteTransitionHandler.addFiltered(filter, remoteTransition); } /** Unregisters a remote transition and all associated filters */ - @ExternalThread public void unregisterRemote(@NonNull IRemoteTransition remoteTransition) { - mMainExecutor.execute(() -> mRemoteTransitionHandler.removeFiltered(remoteTransition)); + mRemoteTransitionHandler.removeFiltered(remoteTransition); } /** @return true if the transition was triggered by opening something vs closing something */ @@ -361,4 +376,22 @@ public class Transitions { mMainExecutor.execute(() -> Transitions.this.requestStartTransition(iBinder, request)); } } + + @ExternalThread + private class RemoteTransitionImpl implements RemoteTransitions { + @Override + public void registerRemote(@NonNull TransitionFilter filter, + @NonNull IRemoteTransition remoteTransition) { + mMainExecutor.execute(() -> { + Transitions.this.registerRemote(filter, remoteTransition); + }); + } + + @Override + public void unregisterRemote(@NonNull IRemoteTransition remoteTransition) { + mMainExecutor.execute(() -> { + Transitions.this.unregisterRemote(remoteTransition); + }); + } + } } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/TaskSnapshotWindowTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/TaskSnapshotWindowTest.java index 414a0a778d937..27e5f51d88b85 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/TaskSnapshotWindowTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/TaskSnapshotWindowTest.java @@ -47,6 +47,7 @@ import android.window.TaskSnapshot; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; +import com.android.wm.shell.TestShellExecutor; import com.android.wm.shell.startingsurface.TaskSnapshotWindow; import org.junit.Test; @@ -83,7 +84,7 @@ public class TaskSnapshotWindowTest { createTaskDescription(Color.WHITE, Color.RED, Color.BLUE), 0 /* appearance */, windowFlags /* windowFlags */, 0 /* privateWindowFlags */, taskBounds, ORIENTATION_PORTRAIT, ACTIVITY_TYPE_STANDARD, new InsetsState(), - null /* clearWindow */); + null /* clearWindow */, new TestShellExecutor()); } private TaskSnapshot createTaskSnapshot(int width, int height, Point taskSize, diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java index 062410abb689b..ffb8446f3e21a 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java @@ -33,7 +33,7 @@ import com.android.wm.shell.legacysplitscreen.LegacySplitScreen; 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.transition.Transitions; +import com.android.wm.shell.transition.RemoteTransitions; import java.util.Optional; @@ -86,7 +86,7 @@ public interface SysUIComponent { Builder setShellCommandHandler(Optional shellDump); @BindsInstance - Builder setTransitions(Transitions t); + Builder setTransitions(RemoteTransitions t); SysUIComponent build(); } diff --git a/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java index 60b665f0a51a7..84dd25963a15f 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java @@ -27,7 +27,7 @@ import com.android.wm.shell.legacysplitscreen.LegacySplitScreen; 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.transition.Transitions; +import com.android.wm.shell.transition.RemoteTransitions; import java.util.Optional; @@ -55,16 +55,12 @@ public interface WMComponent { getShellInit().init(); } - // Gets the Shell init instance @WMSingleton ShellInit getShellInit(); - // Gets the Shell dump instance @WMSingleton Optional getShellCommandHandler(); - // TODO(b/162923491): We currently pass the instances through to SysUI, but that may change - // depending on the threading mechanism we go with @WMSingleton Optional getOneHanded(); @@ -89,7 +85,6 @@ public interface WMComponent { @WMSingleton Optional getTaskViewFactory(); - /** Gets transitions */ @WMSingleton - Transitions getTransitions(); + RemoteTransitions getTransitions(); } diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java index a9f76f61c5379..01a8c1c89f840 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java +++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java @@ -101,7 +101,7 @@ 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.splitscreen.SplitScreen; -import com.android.wm.shell.transition.Transitions; +import com.android.wm.shell.transition.RemoteTransitions; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -149,7 +149,7 @@ public class OverviewProxyService extends CurrentUserTracker implements private final ScreenshotHelper mScreenshotHelper; private final Optional mOneHandedOptional; private final CommandQueue mCommandQueue; - private final Transitions mShellTransitions; + private final RemoteTransitions mShellTransitions; private Region mActiveNavBarRegion; @@ -799,7 +799,7 @@ public class OverviewProxyService extends CurrentUserTracker implements Optional> statusBarOptionalLazy, Optional oneHandedOptional, BroadcastDispatcher broadcastDispatcher, - Transitions shellTransitions) { + RemoteTransitions shellTransitions) { super(broadcastDispatcher); mContext = context; mPipOptional = pipOptional; diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java index b7aa907c6180d..36506bf5715cc 100644 --- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java +++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java @@ -75,6 +75,7 @@ import com.android.wm.shell.sizecompatui.SizeCompatUI; import com.android.wm.shell.sizecompatui.SizeCompatUIController; import com.android.wm.shell.splitscreen.SplitScreen; import com.android.wm.shell.splitscreen.SplitScreenController; +import com.android.wm.shell.transition.RemoteTransitions; import com.android.wm.shell.transition.Transitions; import java.util.Optional; @@ -386,6 +387,12 @@ public abstract class WMShellBaseModule { return new FullscreenTaskListener(syncQueue); } + @WMSingleton + @Provides + static RemoteTransitions provideRemoteTransitions(Transitions transitions) { + return Transitions.asRemoteTransitions(transitions); + } + @WMSingleton @Provides static Transitions provideTransitions(ShellTaskOrganizer organizer, TransactionPool pool, diff --git a/packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.java b/packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.java index 451c78fd1202c..6d2b8e415e969 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.java @@ -43,7 +43,7 @@ import com.android.systemui.statusbar.phone.StatusBar; import com.android.wm.shell.legacysplitscreen.LegacySplitScreen; import com.android.wm.shell.pip.Pip; import com.android.wm.shell.splitscreen.SplitScreen; -import com.android.wm.shell.transition.Transitions; +import com.android.wm.shell.transition.RemoteTransitions; import org.junit.Before; import org.junit.Test; @@ -78,7 +78,7 @@ public class OverviewProxyServiceTest extends SysuiTestCase { @Mock private Optional mMockOneHandedOptional; @Mock private PackageManager mPackageManager; @Mock private SysUiState mMockSysUiState; - @Mock private Transitions mMockTransitions; + @Mock private RemoteTransitions mMockTransitions; @Before public void setUp() throws RemoteException {