diff options
| author | 2022-05-03 11:17:15 +0000 | |
|---|---|---|
| committer | 2022-05-10 09:50:34 +0000 | |
| commit | 0e1d4e23cb91ee650cdb161f2d6eca5d2df1aaad (patch) | |
| tree | d30f0429ea25513210b6268a22605a4ce4bee308 | |
| parent | c3565a503dc37bdc51d479bd07ae3fd77b8a87d3 (diff) | |
Synchronize display change with the Shell
This CL adds synchronization of applying of the window
container transaction with split-screen layout changes after
the display size change. This is needed for the unfold
animation to have the split screen layout ready
for the first frame of the unfold animation on foldable
devices.
The flow is similar to the display rotation synchonization,
now it is triggered on both physical display change and
rotation.
Bug: 204925795
Test: folding/unfolding, rotating with a split layout
when Shell transitions enabled/disabled
Change-Id: I30f391dae69cf38768daf49361660d87165f886d
21 files changed, 438 insertions, 221 deletions
diff --git a/core/java/android/view/IDisplayWindowRotationCallback.aidl b/core/java/android/view/IDisplayChangeWindowCallback.aidl index 1ffe2dde40f1..00a5b7b831ca 100644 --- a/core/java/android/view/IDisplayWindowRotationCallback.aidl +++ b/core/java/android/view/IDisplayChangeWindowCallback.aidl @@ -17,13 +17,15 @@ package android.view; import android.window.WindowContainerTransaction; +import android.window.DisplayAreaInfo; /** - * Interface to be invoked by the controller when it has finished preparing for a display rotation. + * Interface to be invoked by the controller when it has finished preparing for a display + * size change. * - * @see IDisplayWindowRotationController + * @see IDisplayChangeWindowController * @hide */ -interface IDisplayWindowRotationCallback { - void continueRotateDisplay(int targetRotation, in WindowContainerTransaction t); +interface IDisplayChangeWindowCallback { + void continueDisplayChange(in WindowContainerTransaction t); } diff --git a/core/java/android/view/IDisplayWindowRotationController.aidl b/core/java/android/view/IDisplayChangeWindowController.aidl index c1c7464c3168..8c0bb6a54528 100644 --- a/core/java/android/view/IDisplayWindowRotationController.aidl +++ b/core/java/android/view/IDisplayChangeWindowController.aidl @@ -16,11 +16,12 @@ package android.view; -import android.view.IDisplayWindowRotationCallback; +import android.view.IDisplayChangeWindowCallback; +import android.window.DisplayAreaInfo; /** - * Singular controller of a "remote" display rotation. When a display rotation is started, WM - * freezes the screen. It will then call into this controller and wait for a response via the + * Singular controller of a "remote" display change. When a display rotation or change is started, + * WM freezes the screen. It will then call into this controller and wait for a response via the * callback. * * This needs to provide configuration changes because those changes need to be applied in sync @@ -36,17 +37,18 @@ import android.view.IDisplayWindowRotationCallback; * * @hide */ -oneway interface IDisplayWindowRotationController { +oneway interface IDisplayChangeWindowController { /** - * Called when WM needs to know how to update tasks in response to a display rotation. - * If this isn't called, a timeout will continue the rotation in WM. + * Called when WM needs to know how to update tasks in response to a display change. + * If this isn't called, a timeout will continue the change in WM. * - * @param displayId the display that is rotating. - * @param fromRotation the rotation the display is rotating from. - * @param toRotation the rotation the display is rotating to. + * @param fromRotation the old rotation + * @param newRotation the new rotation + * @param newDisplayAreaInfo the new display area info after the change * @param callback A callback to be called when this has calculated updated configs. */ - void onRotateDisplay(int displayId, int fromRotation, int toRotation, - in IDisplayWindowRotationCallback callback); + void onDisplayChange(int displayId, int fromRotation, int toRotation, + in DisplayAreaInfo newDisplayAreaInfo, in IDisplayChangeWindowCallback callback); + } diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl index ee49d7bf5c28..ebdb79ce19e8 100644 --- a/core/java/android/view/IWindowManager.aidl +++ b/core/java/android/view/IWindowManager.aidl @@ -40,7 +40,7 @@ import android.view.ICrossWindowBlurEnabledListener; import android.view.IDisplayWindowInsetsController; import android.view.IDisplayWindowListener; import android.view.IDisplayFoldListener; -import android.view.IDisplayWindowRotationController; +import android.view.IDisplayChangeWindowController; import android.view.IOnKeyguardExitResult; import android.view.IPinnedTaskListener; import android.view.IScrollCaptureResponseListener; @@ -146,7 +146,7 @@ interface IWindowManager * controller is called after the display has "frozen" for a rotation and display rotation will * only continue once the controller has finished calculating associated configurations. */ - void setDisplayWindowRotationController(IDisplayWindowRotationController controller); + void setDisplayChangeWindowController(IDisplayChangeWindowController controller); /** * Adds a root container that a client shell can populate with its own windows (usually via diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json index 0d62d20d1176..558e4fa105d7 100644 --- a/data/etc/services.core.protolog.json +++ b/data/etc/services.core.protolog.json @@ -469,6 +469,12 @@ "group": "WM_DEBUG_ADD_REMOVE", "at": "com\/android\/server\/wm\/ResetTargetTaskHelper.java" }, + "-1635750891": { + "message": "Received remote change for Display[%d], applied: [%dx%d, rot = %d]", + "level": "VERBOSE", + "group": "WM_DEBUG_CONFIGURATION", + "at": "com\/android\/server\/wm\/RemoteDisplayChangeController.java" + }, "-1633115609": { "message": "Key dispatch not paused for screen off", "level": "VERBOSE", @@ -3391,12 +3397,6 @@ "group": "WM_DEBUG_BOOT", "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1246035185": { - "message": "stopFreezingDisplayLocked: Returning waitingForConfig=%b, waitingForRemoteRotation=%b, mAppsFreezingScreen=%d, mWindowsFreezingScreen=%d, mClientFreezingScreen=%b, mOpeningApps.size()=%d", - "level": "DEBUG", - "group": "WM_DEBUG_ORIENTATION", - "at": "com\/android\/server\/wm\/WindowManagerService.java" - }, "1252594551": { "message": "Window types in WindowContext and LayoutParams.type should match! Type from LayoutParams is %d, but type from WindowContext is %d", "level": "WARN", @@ -3493,6 +3493,12 @@ "group": "WM_DEBUG_ORIENTATION", "at": "com\/android\/server\/wm\/ScreenRotationAnimation.java" }, + "1360176455": { + "message": "stopFreezingDisplayLocked: Returning waitingForConfig=%b, waitingForRemoteDisplayChange=%b, mAppsFreezingScreen=%d, mWindowsFreezingScreen=%d, mClientFreezingScreen=%b, mOpeningApps.size()=%d", + "level": "DEBUG", + "group": "WM_DEBUG_ORIENTATION", + "at": "com\/android\/server\/wm\/WindowManagerService.java" + }, "1364126018": { "message": "Resumed activity; dropping state of: %s", "level": "INFO", @@ -3517,6 +3523,12 @@ "group": "WM_DEBUG_ORIENTATION", "at": "com\/android\/server\/wm\/TaskDisplayArea.java" }, + "1393721079": { + "message": "Starting remote display change: from [rot = %d], to [%dx%d, rot = %d]", + "level": "VERBOSE", + "group": "WM_DEBUG_CONFIGURATION", + "at": "com\/android\/server\/wm\/RemoteDisplayChangeController.java" + }, "1396893178": { "message": "createRootTask unknown displayId=%d", "level": "ERROR", @@ -3859,6 +3871,12 @@ "group": "WM_DEBUG_ORIENTATION", "at": "com\/android\/server\/wm\/WindowStateAnimator.java" }, + "1764619787": { + "message": "Remote change for Display[%d]: timeout reached", + "level": "VERBOSE", + "group": "WM_DEBUG_CONFIGURATION", + "at": "com\/android\/server\/wm\/RemoteDisplayChangeController.java" + }, "1774661765": { "message": "Devices still not ready after waiting %d milliseconds before attempting to detect safe mode.", "level": "WARN", diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java index f407bdcb8852..8cfeefe71b15 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java @@ -78,7 +78,6 @@ import android.view.View; import android.view.ViewGroup; import android.view.WindowInsets; import android.view.WindowManager; -import android.window.WindowContainerTransaction; import androidx.annotation.MainThread; import androidx.annotation.Nullable; @@ -89,7 +88,6 @@ import com.android.internal.statusbar.IStatusBarService; import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.TaskViewTransitions; import com.android.wm.shell.WindowManagerShellWrapper; -import com.android.wm.shell.common.DisplayChangeController; import com.android.wm.shell.common.DisplayController; import com.android.wm.shell.common.FloatingContentCoordinator; import com.android.wm.shell.common.ShellExecutor; @@ -423,17 +421,13 @@ public class BubbleController { }); mDisplayController.addDisplayChangingController( - new DisplayChangeController.OnDisplayChangingListener() { - @Override - public void onRotateDisplay(int displayId, int fromRotation, int toRotation, - WindowContainerTransaction t) { - // This is triggered right before the rotation is applied - if (fromRotation != toRotation) { - if (mStackView != null) { - // Layout listener set on stackView will update the positioner - // once the rotation is applied - mStackView.onOrientationChanged(); - } + (displayId, fromRotation, toRotation, newDisplayAreaInfo, t) -> { + // This is triggered right before the rotation is applied + if (fromRotation != toRotation) { + if (mStackView != null) { + // Layout listener set on stackView will update the positioner + // once the rotation is applied + mStackView.onOrientationChanged(); } } }); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayChangeController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayChangeController.java index c32733d4f73c..28c7367662a2 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayChangeController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayChangeController.java @@ -16,11 +16,13 @@ package com.android.wm.shell.common; +import android.annotation.Nullable; import android.os.RemoteException; import android.util.Slog; -import android.view.IDisplayWindowRotationCallback; -import android.view.IDisplayWindowRotationController; +import android.view.IDisplayChangeWindowCallback; +import android.view.IDisplayChangeWindowController; import android.view.IWindowManager; +import android.window.DisplayAreaInfo; import android.window.WindowContainerTransaction; import androidx.annotation.BinderThread; @@ -40,17 +42,17 @@ public class DisplayChangeController { private final ShellExecutor mMainExecutor; private final IWindowManager mWmService; - private final IDisplayWindowRotationController mControllerImpl; + private final IDisplayChangeWindowController mControllerImpl; - private final CopyOnWriteArrayList<OnDisplayChangingListener> mRotationListener = + private final CopyOnWriteArrayList<OnDisplayChangingListener> mDisplayChangeListener = new CopyOnWriteArrayList<>(); public DisplayChangeController(IWindowManager wmService, ShellExecutor mainExecutor) { mMainExecutor = mainExecutor; mWmService = wmService; - mControllerImpl = new DisplayWindowRotationControllerImpl(); + mControllerImpl = new DisplayChangeWindowControllerImpl(); try { - mWmService.setDisplayWindowRotationController(mControllerImpl); + mWmService.setDisplayChangeWindowController(mControllerImpl); } catch (RemoteException e) { throw new RuntimeException("Unable to register rotation controller"); } @@ -59,63 +61,64 @@ public class DisplayChangeController { /** * Adds a display rotation controller. */ - public void addRotationListener(OnDisplayChangingListener listener) { - mRotationListener.add(listener); + public void addDisplayChangeListener(OnDisplayChangingListener listener) { + mDisplayChangeListener.add(listener); } /** * Removes a display rotation controller. */ - public void removeRotationListener(OnDisplayChangingListener listener) { - mRotationListener.remove(listener); + public void removeDisplayChangeListener(OnDisplayChangingListener listener) { + mDisplayChangeListener.remove(listener); } - /** Query all listeners for changes that should happen on rotation. */ - public void dispatchOnRotateDisplay(WindowContainerTransaction outWct, int displayId, - final int fromRotation, final int toRotation) { - for (OnDisplayChangingListener c : mRotationListener) { - c.onRotateDisplay(displayId, fromRotation, toRotation, outWct); + /** Query all listeners for changes that should happen on display change. */ + public void dispatchOnDisplayChange(WindowContainerTransaction outWct, int displayId, + int fromRotation, int toRotation, DisplayAreaInfo newDisplayAreaInfo) { + for (OnDisplayChangingListener c : mDisplayChangeListener) { + c.onDisplayChange(displayId, fromRotation, toRotation, newDisplayAreaInfo, outWct); } } - private void onRotateDisplay(int displayId, final int fromRotation, final int toRotation, - IDisplayWindowRotationCallback callback) { + private void onDisplayChange(int displayId, int fromRotation, int toRotation, + DisplayAreaInfo newDisplayAreaInfo, IDisplayChangeWindowCallback callback) { WindowContainerTransaction t = new WindowContainerTransaction(); - dispatchOnRotateDisplay(t, displayId, fromRotation, toRotation); + dispatchOnDisplayChange(t, displayId, fromRotation, toRotation, newDisplayAreaInfo); try { - callback.continueRotateDisplay(toRotation, t); + callback.continueDisplayChange(t); } catch (RemoteException e) { - Slog.e(TAG, "Failed to continue rotation", e); + Slog.e(TAG, "Failed to continue handling display change", e); } } @BinderThread - private class DisplayWindowRotationControllerImpl - extends IDisplayWindowRotationController.Stub { + private class DisplayChangeWindowControllerImpl + extends IDisplayChangeWindowController.Stub { @Override - public void onRotateDisplay(int displayId, final int fromRotation, - final int toRotation, IDisplayWindowRotationCallback callback) { - mMainExecutor.execute(() -> { - DisplayChangeController.this.onRotateDisplay(displayId, fromRotation, toRotation, - callback); - }); + public void onDisplayChange(int displayId, int fromRotation, int toRotation, + DisplayAreaInfo newDisplayAreaInfo, IDisplayChangeWindowCallback callback) { + mMainExecutor.execute(() -> DisplayChangeController.this + .onDisplayChange(displayId, fromRotation, toRotation, + newDisplayAreaInfo, callback)); } } /** * Give a listener a chance to queue up configuration changes to execute as part of a - * display rotation. The contents of {@link #onRotateDisplay} must run synchronously. + * display rotation. The contents of {@link #onDisplayChange} must run synchronously. */ @ShellMainThread public interface OnDisplayChangingListener { /** - * Called before the display is rotated. Contents of this method must run synchronously. - * @param displayId Id of display that is rotating. - * @param fromRotation starting rotation of the display. - * @param toRotation target rotation of the display (after rotating). + * Called before the display size has changed. + * Contents of this method must run synchronously. + * @param displayId display id of the display that is under the change + * @param fromRotation rotation before the change + * @param toRotation rotation after the change + * @param newDisplayAreaInfo display area info after applying the update * @param t A task transaction to populate. */ - void onRotateDisplay(int displayId, int fromRotation, int toRotation, - WindowContainerTransaction t); + void onDisplayChange(int displayId, int fromRotation, int toRotation, + @Nullable DisplayAreaInfo newDisplayAreaInfo, WindowContainerTransaction t); } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayController.java index 4ba32e93fb3d..764936cceb01 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayController.java @@ -156,14 +156,14 @@ public class DisplayController { * Adds a display rotation controller. */ public void addDisplayChangingController(OnDisplayChangingListener controller) { - mChangeController.addRotationListener(controller); + mChangeController.addDisplayChangeListener(controller); } /** * Removes a display rotation controller. */ public void removeDisplayChangingController(OnDisplayChangingListener controller) { - mChangeController.removeRotationListener(controller); + mChangeController.removeDisplayChangeListener(controller); } private void onDisplayAdded(int displayId) { 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 179b725ab210..1d8ac2b576e9 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 @@ -39,6 +39,7 @@ import android.provider.Settings; import android.util.Slog; import android.view.WindowManager; import android.view.accessibility.AccessibilityManager; +import android.window.DisplayAreaInfo; import android.window.WindowContainerTransaction; import androidx.annotation.NonNull; @@ -659,11 +660,11 @@ public class OneHandedController implements RemoteCallable<OneHandedController>, } /** - * Handles rotation based on OnDisplayChangingListener callback + * Handles display change based on OnDisplayChangingListener callback */ @Override - public void onRotateDisplay(int displayId, int fromRotation, int toRotation, - WindowContainerTransaction wct) { + public void onDisplayChange(int displayId, int fromRotation, int toRotation, + DisplayAreaInfo newDisplayAreaInfo, WindowContainerTransaction wct) { if (!isInitialized()) { return; } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java index 492b5d959c46..9e9044c449e5 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java @@ -154,7 +154,7 @@ public class PipController implements PipTransitionController.PipTransitionCallb * Handler for display rotation changes. */ private final DisplayChangeController.OnDisplayChangingListener mRotationController = ( - int displayId, int fromRotation, int toRotation, WindowContainerTransaction t) -> { + displayId, fromRotation, toRotation, newDisplayAreaInfo, t) -> { if (mPipTransitionController.handleRotateDisplay(fromRotation, toRotation, t)) { return; } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java index 6274d6fa00ee..5ec078fb5efa 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java @@ -83,6 +83,7 @@ import android.view.RemoteAnimationTarget; import android.view.SurfaceControl; import android.view.SurfaceSession; import android.view.WindowManager; +import android.window.DisplayAreaInfo; import android.window.RemoteTransition; import android.window.TransitionInfo; import android.window.TransitionRequestInfo; @@ -1315,7 +1316,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, if (displayId != DEFAULT_DISPLAY) { return; } - mDisplayController.addDisplayChangingController(this::onRotateDisplay); + mDisplayController.addDisplayChangingController(this::onDisplayChange); } @Override @@ -1326,14 +1327,17 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, mDisplayLayout.set(mDisplayController.getDisplayLayout(displayId)); } - private void onRotateDisplay(int displayId, int fromRotation, int toRotation, - WindowContainerTransaction wct) { + private void onDisplayChange(int displayId, int fromRotation, int toRotation, + @Nullable DisplayAreaInfo newDisplayAreaInfo, WindowContainerTransaction wct) { if (!mMainStage.isActive()) return; // Only do this when shell transition if (!ENABLE_SHELL_TRANSITIONS) return; mDisplayLayout.rotateTo(mContext.getResources(), toRotation); mSplitLayout.rotateTo(toRotation, mDisplayLayout.stableInsets()); + if (newDisplayAreaInfo != null) { + mSplitLayout.updateConfiguration(newDisplayAreaInfo.configuration); + } updateWindowBounds(mSplitLayout, wct); updateUnfoldBounds(); } 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 98eee7ba33a0..165ea620323d 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 @@ -626,8 +626,9 @@ public class Transitions implements RemoteCallable<Transitions> { if (wct == null) { wct = new WindowContainerTransaction(); } - mDisplayController.getChangeController().dispatchOnRotateDisplay(wct, - change.getDisplayId(), change.getStartRotation(), change.getEndRotation()); + mDisplayController.getChangeController().dispatchOnDisplayChange(wct, + change.getDisplayId(), change.getStartRotation(), change.getEndRotation(), + null /* newDisplayAreaInfo */); } } active.mToken = mOrganizer.startTransition( diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/UnfoldTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/UnfoldTransitionHandler.java index af78f2d7d870..8e45e7d36b86 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/UnfoldTransitionHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/UnfoldTransitionHandler.java @@ -127,7 +127,8 @@ public class UnfoldTransitionHandler implements TransitionHandler, UnfoldListene @Override public WindowContainerTransaction handleRequest(@NonNull IBinder transition, @NonNull TransitionRequestInfo request) { - if (request.getType() == TRANSIT_CHANGE && request.getDisplayChange() != null) { + if (request.getType() == TRANSIT_CHANGE && request.getDisplayChange() != null + && request.getDisplayChange().isPhysicalDisplayChanged()) { mTransition = transition; return new WindowContainerTransaction(); } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedControllerTest.java index ecf1c5d41864..6a6db8aa3c04 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedControllerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedControllerTest.java @@ -345,8 +345,8 @@ public class OneHandedControllerTest extends OneHandedTestCase { when(mMockSettingsUitl.getSettingsSwipeToNotificationEnabled(any(), anyInt())).thenReturn( false); final WindowContainerTransaction handlerWCT = new WindowContainerTransaction(); - mSpiedOneHandedController.onRotateDisplay(mDisplay.getDisplayId(), Surface.ROTATION_0, - Surface.ROTATION_90, handlerWCT); + mSpiedOneHandedController.onDisplayChange(mDisplay.getDisplayId(), Surface.ROTATION_0, + Surface.ROTATION_90, null /* newDisplayAreaInfo */, handlerWCT); verify(mMockDisplayAreaOrganizer, atLeastOnce()).onRotateDisplay(eq(mContext), eq(Surface.ROTATION_90), any(WindowContainerTransaction.class)); @@ -358,8 +358,8 @@ public class OneHandedControllerTest extends OneHandedTestCase { when(mMockSettingsUitl.getSettingsSwipeToNotificationEnabled(any(), anyInt())).thenReturn( false); final WindowContainerTransaction handlerWCT = new WindowContainerTransaction(); - mSpiedOneHandedController.onRotateDisplay(mDisplay.getDisplayId(), Surface.ROTATION_0, - Surface.ROTATION_90, handlerWCT); + mSpiedOneHandedController.onDisplayChange(mDisplay.getDisplayId(), Surface.ROTATION_0, + Surface.ROTATION_90, null /* newDisplayAreaInfo */, handlerWCT); verify(mMockDisplayAreaOrganizer, never()).onRotateDisplay(eq(mContext), eq(Surface.ROTATION_90), any(WindowContainerTransaction.class)); @@ -371,8 +371,8 @@ public class OneHandedControllerTest extends OneHandedTestCase { when(mMockSettingsUitl.getSettingsSwipeToNotificationEnabled(any(), anyInt())).thenReturn( true); final WindowContainerTransaction handlerWCT = new WindowContainerTransaction(); - mSpiedOneHandedController.onRotateDisplay(mDisplay.getDisplayId(), Surface.ROTATION_0, - Surface.ROTATION_90, handlerWCT); + mSpiedOneHandedController.onDisplayChange(mDisplay.getDisplayId(), Surface.ROTATION_0, + Surface.ROTATION_90, null /* newDisplayAreaInfo */, handlerWCT); verify(mMockDisplayAreaOrganizer, never()).onRotateDisplay(eq(mContext), eq(Surface.ROTATION_90), any(WindowContainerTransaction.class)); @@ -384,8 +384,8 @@ public class OneHandedControllerTest extends OneHandedTestCase { when(mMockSettingsUitl.getSettingsSwipeToNotificationEnabled(any(), anyInt())).thenReturn( false); final WindowContainerTransaction handlerWCT = new WindowContainerTransaction(); - mSpiedOneHandedController.onRotateDisplay(mDisplay.getDisplayId(), Surface.ROTATION_0, - Surface.ROTATION_90, handlerWCT); + mSpiedOneHandedController.onDisplayChange(mDisplay.getDisplayId(), Surface.ROTATION_0, + Surface.ROTATION_90, null /* newDisplayAreaInfo */, handlerWCT); verify(mMockDisplayAreaOrganizer, atLeastOnce()).onRotateDisplay(eq(mContext), eq(Surface.ROTATION_90), any(WindowContainerTransaction.class)); diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 17ce26535e3a..da5e90dc01b5 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -556,7 +556,8 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp final FixedRotationTransitionListener mFixedRotationTransitionListener = new FixedRotationTransitionListener(); - private PhysicalDisplaySwitchTransitionLauncher mDisplaySwitchTransitionLauncher; + private final PhysicalDisplaySwitchTransitionLauncher mDisplaySwitchTransitionLauncher; + final RemoteDisplayChangeController mRemoteDisplayChangeController; /** Windows added since {@link #mCurrentFocus} was set to null. Used for ANR blaming. */ final ArrayList<WindowState> mWinAddedSinceNullFocus = new ArrayList<>(); @@ -1052,6 +1053,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp mUnknownAppVisibilityController = new UnknownAppVisibilityController(mWmService, this); mDisplaySwitchTransitionLauncher = new PhysicalDisplaySwitchTransitionLauncher(this, mTransitionController); + mRemoteDisplayChangeController = new RemoteDisplayChangeController(mWmService, mDisplayId); final InputChannel inputChannel = mWmService.mInputManager.monitorInput( "PointerEventDispatcher" + mDisplayId, mDisplayId); @@ -1433,7 +1435,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp if (!isReady()) { return; } - if (mDisplayRotation.isWaitingForRemoteRotation()) { + if (mRemoteDisplayChangeController.isWaitingForRemoteDisplayChange()) { return; } @@ -1533,8 +1535,8 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp config = new Configuration(); computeScreenConfiguration(config); } else if (!(mTransitionController.isCollecting(this) - // If waiting for a remote rotation, don't prematurely update configuration. - || mDisplayRotation.isWaitingForRemoteRotation())) { + // If waiting for a remote display change, don't prematurely update configuration. + || mRemoteDisplayChangeController.isWaitingForRemoteDisplayChange())) { // No obvious action we need to take, but if our current state mismatches the // activity manager's, update it, disregarding font scale, which should remain set // to the value of the previous configuration. @@ -1596,7 +1598,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp boolean isSyncFinished() { // Do not consider children because if they are requested to be synced, they should be // added to sync group explicitly. - return !mDisplayRotation.isWaitingForRemoteRotation(); + return !mRemoteDisplayChangeController.isWaitingForRemoteDisplayChange(); } /** @@ -1829,8 +1831,8 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp sendNewConfiguration(); return; } - if (mDisplayRotation.isWaitingForRemoteRotation()) { - // There is pending rotation change to apply. + if (mRemoteDisplayChangeController.isWaitingForRemoteDisplayChange()) { + // There is pending display change to apply. return; } // The orientation of display is not changed. @@ -2758,6 +2760,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp private void updateBaseDisplayMetricsIfNeeded() { // Get real display metrics without overrides from WM. mWmService.mDisplayManagerInternal.getNonOverrideDisplayInfo(mDisplayId, mDisplayInfo); + final int currentRotation = getRotation(); final int orientation = mDisplayInfo.rotation; final boolean rotated = (orientation == ROTATION_90 || orientation == ROTATION_270); final int newWidth = rotated ? mDisplayInfo.logicalHeight : mDisplayInfo.logicalWidth; @@ -2818,7 +2821,8 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp reconfigureDisplayLocked(); if (physicalDisplayChanged) { - mDisplaySwitchTransitionLauncher.onDisplayUpdated(); + mDisplaySwitchTransitionLauncher.onDisplayUpdated(currentRotation, getRotation(), + getDisplayAreaInfo()); } } } diff --git a/services/core/java/com/android/server/wm/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java index 03e1429f1bf1..86ed44e39425 100644 --- a/services/core/java/com/android/server/wm/DisplayRotation.java +++ b/services/core/java/com/android/server/wm/DisplayRotation.java @@ -51,14 +51,12 @@ import android.content.res.Resources; import android.database.ContentObserver; import android.hardware.power.Boost; import android.os.Handler; -import android.os.RemoteException; import android.os.SystemProperties; import android.os.UserHandle; import android.provider.Settings; import android.util.Slog; import android.util.TimeUtils; import android.util.proto.ProtoOutputStream; -import android.view.IDisplayWindowRotationCallback; import android.view.IWindowManager; import android.view.Surface; import android.window.TransitionRequestInfo; @@ -67,7 +65,6 @@ import android.window.WindowContainerTransaction; import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.protolog.common.ProtoLog; -import com.android.internal.util.function.pooled.PooledLambda; import com.android.server.LocalServices; import com.android.server.UiThread; import com.android.server.policy.WindowManagerPolicy; @@ -211,31 +208,6 @@ public class DisplayRotation { private boolean mDemoHdmiRotationLock; private boolean mDemoRotationLock; - private static final int REMOTE_ROTATION_TIMEOUT_MS = 800; - - private boolean mIsWaitingForRemoteRotation = false; - - private final Runnable mDisplayRotationHandlerTimeout = - new Runnable() { - @Override - public void run() { - continueRotation(mRotation, null /* transaction */); - } - }; - - private final IDisplayWindowRotationCallback mRemoteRotationCallback = - new IDisplayWindowRotationCallback.Stub() { - @Override - public void continueRotateDisplay(int targetRotation, - WindowContainerTransaction t) { - synchronized (mService.getWindowManagerLock()) { - mService.mH.sendMessage(PooledLambda.obtainMessage( - DisplayRotation::continueRotation, DisplayRotation.this, - targetRotation, t)); - } - } - }; - DisplayRotation(WindowManagerService service, DisplayContent displayContent) { this(service, displayContent, displayContent.getDisplayPolicy(), service.mDisplayWindowSettings, service.mContext, service.getWindowManagerLock()); @@ -511,6 +483,7 @@ public class DisplayRotation { final TransitionRequestInfo.DisplayChange change = wasCollecting ? null : new TransitionRequestInfo.DisplayChange(mDisplayContent.getDisplayId(), oldRotation, mRotation); + mDisplayContent.requestChangeTransitionIfNeeded( ActivityInfo.CONFIG_WINDOW_CONFIGURATION, change); if (wasCollecting) { @@ -554,61 +527,45 @@ public class DisplayRotation { return null; } - /** - * A Remote rotation is when we are waiting for some registered (remote) - * {@link IDisplayWindowRotationController} to calculate and return some hierarchy operations - * to perform in sync with the rotation. - */ - boolean isWaitingForRemoteRotation() { - return mIsWaitingForRemoteRotation; - } - private void startRemoteRotation(int fromRotation, int toRotation) { - if (mService.mDisplayRotationController == null) { - return; - } - mIsWaitingForRemoteRotation = true; - try { - mService.mDisplayRotationController.onRotateDisplay(mDisplayContent.getDisplayId(), - fromRotation, toRotation, mRemoteRotationCallback); - mService.mH.removeCallbacks(mDisplayRotationHandlerTimeout); - mService.mH.postDelayed(mDisplayRotationHandlerTimeout, REMOTE_ROTATION_TIMEOUT_MS); - } catch (RemoteException e) { - mIsWaitingForRemoteRotation = false; - return; - } + mDisplayContent.mRemoteDisplayChangeController.performRemoteDisplayChange( + fromRotation, toRotation, null /* newDisplayAreaInfo */, + (appliedChange, transaction) -> { + final int newRotation = appliedChange != null + ? appliedChange.toRotation + // Timeout occurred, use old rotation + : fromRotation; + continueRotation(newRotation, transaction); + } + ); } private void continueRotation(int targetRotation, WindowContainerTransaction t) { - synchronized (mService.mGlobalLock) { - if (targetRotation != mRotation || !mIsWaitingForRemoteRotation) { - // Drop it, this is either coming from an outdated remote rotation; or, we've - // already moved on. - return; - } - mService.mH.removeCallbacks(mDisplayRotationHandlerTimeout); - mIsWaitingForRemoteRotation = false; + if (targetRotation != mRotation) { + // Drop it, this is either coming from an outdated remote rotation; or, we've + // already moved on. + return; + } - if (mDisplayContent.mTransitionController.isShellTransitionsEnabled()) { - if (!mDisplayContent.mTransitionController.isCollecting()) { - throw new IllegalStateException("Trying to rotate outside a transition"); - } - mDisplayContent.mTransitionController.collect(mDisplayContent); - // Go through all tasks and collect them before the rotation - // TODO(shell-transitions): move collect() to onConfigurationChange once wallpaper - // handling is synchronized. - mDisplayContent.mTransitionController.collectForDisplayChange(mDisplayContent, - null /* use collecting transition */); + if (mDisplayContent.mTransitionController.isShellTransitionsEnabled()) { + if (!mDisplayContent.mTransitionController.isCollecting()) { + throw new IllegalStateException("Trying to rotate outside a transition"); } - mService.mAtmService.deferWindowLayout(); - try { - mDisplayContent.sendNewConfiguration(); - if (t != null) { - mService.mAtmService.mWindowOrganizerController.applyTransaction(t); - } - } finally { - mService.mAtmService.continueWindowLayout(); + mDisplayContent.mTransitionController.collect(mDisplayContent); + // Go through all tasks and collect them before the rotation + // TODO(shell-transitions): move collect() to onConfigurationChange once wallpaper + // handling is synchronized. + mDisplayContent.mTransitionController.collectForDisplayChange(mDisplayContent, + null /* use collecting transition */); + } + mService.mAtmService.deferWindowLayout(); + try { + mDisplayContent.sendNewConfiguration(); + if (t != null) { + mService.mAtmService.mWindowOrganizerController.applyTransaction(t); } + } finally { + mService.mAtmService.continueWindowLayout(); } } diff --git a/services/core/java/com/android/server/wm/PhysicalDisplaySwitchTransitionLauncher.java b/services/core/java/com/android/server/wm/PhysicalDisplaySwitchTransitionLauncher.java index 9c1d5601dad5..3e01f08994f8 100644 --- a/services/core/java/com/android/server/wm/PhysicalDisplaySwitchTransitionLauncher.java +++ b/services/core/java/com/android/server/wm/PhysicalDisplaySwitchTransitionLauncher.java @@ -22,17 +22,21 @@ import static com.android.internal.R.bool.config_unfoldTransitionEnabled; import static com.android.server.wm.ActivityTaskManagerService.POWER_MODE_REASON_CHANGE_DISPLAY; import android.animation.ValueAnimator; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.content.Context; import android.graphics.Rect; import android.hardware.devicestate.DeviceStateManager; import android.os.HandlerExecutor; +import android.window.DisplayAreaInfo; import android.window.TransitionRequestInfo; +import android.window.WindowContainerTransaction; public class PhysicalDisplaySwitchTransitionLauncher { private final DisplayContent mDisplayContent; + private final WindowManagerService mService; private final DeviceStateManager mDeviceStateManager; - private final Context mContext; private final TransitionController mTransitionController; private DeviceStateListener mDeviceStateListener; @@ -46,13 +50,13 @@ public class PhysicalDisplaySwitchTransitionLauncher { public PhysicalDisplaySwitchTransitionLauncher(DisplayContent displayContent, TransitionController transitionController) { mDisplayContent = displayContent; - mContext = mDisplayContent.mWmService.mContext; + mService = displayContent.mWmService; mTransitionController = transitionController; - mDeviceStateManager = mContext.getSystemService(DeviceStateManager.class); + mDeviceStateManager = mService.mContext.getSystemService(DeviceStateManager.class); if (mDeviceStateManager != null) { - mDeviceStateListener = new DeviceStateListener(mContext); + mDeviceStateListener = new DeviceStateListener(mService.mContext); mDeviceStateManager .registerCallback(new HandlerExecutor(mDisplayContent.mWmService.mH), mDeviceStateListener); @@ -74,7 +78,7 @@ public class PhysicalDisplaySwitchTransitionLauncher { if (!mDisplayContent.getLastHasContent()) return; boolean shouldRequestUnfoldTransition = !mIsFolded - && mContext.getResources().getBoolean(config_unfoldTransitionEnabled) + && mService.mContext.getResources().getBoolean(config_unfoldTransitionEnabled) && ValueAnimator.areAnimatorsEnabled(); if (!shouldRequestUnfoldTransition) { @@ -102,11 +106,42 @@ public class PhysicalDisplaySwitchTransitionLauncher { } } - public void onDisplayUpdated() { - if (mTransition != null) { - mTransition.setAllReady(); - mTransition = null; + /** + * Called when physical display is getting updated, this could happen e.g. on foldable + * devices when the physical underlying display is replaced. + * + * @param fromRotation rotation before the display change + * @param toRotation rotation after the display change + * @param newDisplayAreaInfo display area info after the display change + */ + public void onDisplayUpdated(int fromRotation, int toRotation, + @NonNull DisplayAreaInfo newDisplayAreaInfo) { + if (mTransition == null) return; + + final boolean started = mDisplayContent.mRemoteDisplayChangeController + .performRemoteDisplayChange(fromRotation, toRotation, newDisplayAreaInfo, + (appliedChange, transaction) -> continueDisplayUpdate(transaction)); + + if (!started) { + markTransitionAsReady(); + } + } + + private void continueDisplayUpdate(@Nullable WindowContainerTransaction transaction) { + if (mTransition == null) return; + + if (transaction != null) { + mService.mAtmService.mWindowOrganizerController.applyTransaction(transaction); } + + markTransitionAsReady(); + } + + private void markTransitionAsReady() { + if (mTransition == null) return; + + mTransition.setAllReady(); + mTransition = null; } class DeviceStateListener extends DeviceStateManager.FoldStateListener { diff --git a/services/core/java/com/android/server/wm/RemoteDisplayChangeController.java b/services/core/java/com/android/server/wm/RemoteDisplayChangeController.java new file mode 100644 index 000000000000..553384b06268 --- /dev/null +++ b/services/core/java/com/android/server/wm/RemoteDisplayChangeController.java @@ -0,0 +1,185 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.wm; + +import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_CONFIGURATION; + +import android.annotation.Nullable; +import android.os.RemoteException; +import android.view.IDisplayChangeWindowCallback; +import android.window.DisplayAreaInfo; +import android.window.WindowContainerTransaction; + +import com.android.internal.protolog.common.ProtoLog; +import com.android.internal.util.function.pooled.PooledLambda; + +import java.util.ArrayList; +import java.util.List; + +/** + * A helper class, a wrapper around {@link android.view.IDisplayChangeWindowController} to perform + * a synchronous display change in other parts (e.g. in the Shell) and continue the process + * in the system server. It handles timeouts and multiple requests. + * We have an instance of this controller for each display. + */ +public class RemoteDisplayChangeController { + + private static final int REMOTE_DISPLAY_CHANGE_TIMEOUT_MS = 800; + + private final WindowManagerService mService; + private final int mDisplayId; + + private boolean mIsWaitingForRemoteDisplayChange; + private final Runnable mTimeoutRunnable = () -> { + continueDisplayChange(null /* appliedChange */, null /* transaction */); + }; + + private final List<ContinueRemoteDisplayChangeCallback> mCallbacks = new ArrayList<>(); + + public RemoteDisplayChangeController(WindowManagerService service, int displayId) { + mService = service; + mDisplayId = displayId; + } + + /** + * A Remote change is when we are waiting for some registered (remote) + * {@link IDisplayChangeWindowController} to calculate and return some hierarchy operations + * to perform in sync with the display change. + */ + public boolean isWaitingForRemoteDisplayChange() { + return mIsWaitingForRemoteDisplayChange; + } + + /** + * Starts remote display change + * @param fromRotation rotation before the change + * @param toRotation rotation after the change + * @param newDisplayAreaInfo display area info after change + * @param callback that will be called after completing remote display change + * @return true if the change successfully started, false otherwise + */ + public boolean performRemoteDisplayChange( + int fromRotation, int toRotation, + @Nullable DisplayAreaInfo newDisplayAreaInfo, + ContinueRemoteDisplayChangeCallback callback) { + if (mService.mDisplayChangeController == null) { + return false; + } + mIsWaitingForRemoteDisplayChange = true; + mCallbacks.add(callback); + + if (newDisplayAreaInfo != null) { + ProtoLog.v(WM_DEBUG_CONFIGURATION, + "Starting remote display change: " + + "from [rot = %d], " + + "to [%dx%d, rot = %d]", + fromRotation, + newDisplayAreaInfo.configuration.windowConfiguration + .getMaxBounds().width(), + newDisplayAreaInfo.configuration.windowConfiguration + .getMaxBounds().height(), + toRotation); + } + + final RemoteDisplayChange change = new RemoteDisplayChange(fromRotation, toRotation, + newDisplayAreaInfo); + final IDisplayChangeWindowCallback remoteCallback = createCallback(change); + try { + mService.mDisplayChangeController.onDisplayChange(mDisplayId, fromRotation, toRotation, + newDisplayAreaInfo, remoteCallback); + + mService.mH.removeCallbacks(mTimeoutRunnable); + mService.mH.postDelayed(mTimeoutRunnable, REMOTE_DISPLAY_CHANGE_TIMEOUT_MS); + return true; + } catch (RemoteException e) { + mIsWaitingForRemoteDisplayChange = false; + return false; + } + } + + private void continueDisplayChange(@Nullable RemoteDisplayChange appliedChange, + @Nullable WindowContainerTransaction transaction) { + synchronized (mService.mGlobalLock) { + if (appliedChange != null) { + ProtoLog.v(WM_DEBUG_CONFIGURATION, + "Received remote change for Display[%d], applied: [%dx%d, rot = %d]", + mDisplayId, + appliedChange.displayAreaInfo != null ? appliedChange.displayAreaInfo + .configuration.windowConfiguration.getMaxBounds().width() : -1, + appliedChange.displayAreaInfo != null ? appliedChange.displayAreaInfo + .configuration.windowConfiguration.getMaxBounds().height() : -1, + appliedChange.toRotation); + } else { + ProtoLog.v(WM_DEBUG_CONFIGURATION, "Remote change for Display[%d]: timeout reached", + mDisplayId); + } + + mIsWaitingForRemoteDisplayChange = false; + + for (int i = 0; i < mCallbacks.size(); i++) { + ContinueRemoteDisplayChangeCallback callback = mCallbacks.get(i); + callback.onContinueRemoteDisplayChange(appliedChange, transaction); + } + } + } + + private IDisplayChangeWindowCallback createCallback(RemoteDisplayChange originalChange) { + return new IDisplayChangeWindowCallback.Stub() { + @Override + public void continueDisplayChange(WindowContainerTransaction t) { + synchronized (mService.mGlobalLock) { + mService.mH.removeCallbacks(mTimeoutRunnable); + mService.mH.sendMessage(PooledLambda.obtainMessage( + RemoteDisplayChangeController::continueDisplayChange, + RemoteDisplayChangeController.this, + originalChange, t)); + } + } + }; + } + + /** + * Data class that contains information about a remote display change + */ + public static class RemoteDisplayChange { + final int fromRotation; + final int toRotation; + @Nullable + final DisplayAreaInfo displayAreaInfo; + + public RemoteDisplayChange(int fromRotation, int toRotation, + @Nullable DisplayAreaInfo displayAreaInfo) { + this.fromRotation = fromRotation; + this.toRotation = toRotation; + this.displayAreaInfo = displayAreaInfo; + } + } + + /** + * Callback interface to handle continuation of the remote display change + */ + public interface ContinueRemoteDisplayChangeCallback { + /** + * This method is called when the remote display change has been applied + * @param appliedChange the change that was applied or null if there was + * an error during remote display change (e.g. timeout) + * @param transaction window changes collected by the remote display change + */ + void onContinueRemoteDisplayChange(@Nullable RemoteDisplayChange appliedChange, + @Nullable WindowContainerTransaction transaction); + } +} diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 42344dce08a7..254290b2fcd6 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -237,10 +237,10 @@ import android.view.DisplayInfo; import android.view.Gravity; import android.view.IAppTransitionAnimationSpecsFuture; import android.view.ICrossWindowBlurEnabledListener; +import android.view.IDisplayChangeWindowController; import android.view.IDisplayFoldListener; import android.view.IDisplayWindowInsetsController; import android.view.IDisplayWindowListener; -import android.view.IDisplayWindowRotationController; import android.view.IInputFilter; import android.view.IOnKeyguardExitResult; import android.view.IPinnedTaskListener; @@ -681,9 +681,9 @@ public class WindowManagerService extends IWindowManager.Stub final WallpaperVisibilityListeners mWallpaperVisibilityListeners = new WallpaperVisibilityListeners(); - IDisplayWindowRotationController mDisplayRotationController = null; - private final DeathRecipient mDisplayRotationControllerDeath = - () -> mDisplayRotationController = null; + IDisplayChangeWindowController mDisplayChangeController = null; + private final DeathRecipient mDisplayChangeControllerDeath = + () -> mDisplayChangeController = null; final DisplayWindowListenerController mDisplayNotificationController; final TaskSystemBarsListenerController mTaskSystemBarsListenerController; @@ -4256,12 +4256,13 @@ public class WindowManagerService extends IWindowManager.Stub .notifyOnActivityRotation(displayContent.mDisplayId); } - final boolean pendingRemoteRotation = rotationChanged - && (displayContent.getDisplayRotation().isWaitingForRemoteRotation() + final boolean pendingRemoteDisplayChange = rotationChanged + && (displayContent.mRemoteDisplayChangeController + .isWaitingForRemoteDisplayChange() || displayContent.mTransitionController.isCollecting()); // Even if alwaysSend, we are waiting for a transition or remote to provide - // rotated configuration, so we can't update configuration yet. - if (!pendingRemoteRotation) { + // updated configuration, so we can't update configuration yet. + if (!pendingRemoteDisplayChange) { if (!rotationChanged || forceRelayout) { displayContent.setLayoutNeeded(); layoutNeeded = true; @@ -4293,17 +4294,17 @@ public class WindowManagerService extends IWindowManager.Stub } @Override - public void setDisplayWindowRotationController(IDisplayWindowRotationController controller) { + public void setDisplayChangeWindowController(IDisplayChangeWindowController controller) { mAtmService.enforceTaskPermission("setDisplayWindowRotationController"); try { synchronized (mGlobalLock) { - if (mDisplayRotationController != null) { - mDisplayRotationController.asBinder().unlinkToDeath( - mDisplayRotationControllerDeath, 0); - mDisplayRotationController = null; + if (mDisplayChangeController != null) { + mDisplayChangeController.asBinder().unlinkToDeath( + mDisplayChangeControllerDeath, 0); + mDisplayChangeController = null; } - controller.asBinder().linkToDeath(mDisplayRotationControllerDeath, 0); - mDisplayRotationController = controller; + controller.asBinder().linkToDeath(mDisplayChangeControllerDeath, 0); + mDisplayChangeController = controller; } } catch (RemoteException e) { throw new RuntimeException("Unable to set rotation controller"); @@ -6102,24 +6103,24 @@ public class WindowManagerService extends IWindowManager.Stub final DisplayContent displayContent = mRoot.getDisplayContent(mFrozenDisplayId); final int numOpeningApps; final boolean waitingForConfig; - final boolean waitingForRemoteRotation; + final boolean waitingForRemoteDisplayChange; if (displayContent != null) { numOpeningApps = displayContent.mOpeningApps.size(); waitingForConfig = displayContent.mWaitingForConfig; - waitingForRemoteRotation = - displayContent.getDisplayRotation().isWaitingForRemoteRotation(); + waitingForRemoteDisplayChange = displayContent.mRemoteDisplayChangeController + .isWaitingForRemoteDisplayChange(); } else { - waitingForConfig = waitingForRemoteRotation = false; + waitingForConfig = waitingForRemoteDisplayChange = false; numOpeningApps = 0; } - if (waitingForConfig || waitingForRemoteRotation || mAppsFreezingScreen > 0 + if (waitingForConfig || waitingForRemoteDisplayChange || mAppsFreezingScreen > 0 || mWindowsFreezingScreen == WINDOWS_FREEZING_SCREENS_ACTIVE || mClientFreezingScreen || numOpeningApps > 0) { ProtoLog.d(WM_DEBUG_ORIENTATION, "stopFreezingDisplayLocked: Returning " - + "waitingForConfig=%b, waitingForRemoteRotation=%b, " + + "waitingForConfig=%b, waitingForRemoteDisplayChange=%b, " + "mAppsFreezingScreen=%d, mWindowsFreezingScreen=%d, " + "mClientFreezingScreen=%b, mOpeningApps.size()=%d", - waitingForConfig, waitingForRemoteRotation, + waitingForConfig, waitingForRemoteDisplayChange, mAppsFreezingScreen, mWindowsFreezingScreen, mClientFreezingScreen, numOpeningApps); return; diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java index 533540e2568d..51ffd1c59ce9 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java @@ -1787,13 +1787,16 @@ public class ActivityRecordTests extends WindowTestsBase { public void testActivityOnCancelFixedRotationTransform() { final ActivityRecord activity = createActivityWithTask(); final DisplayRotation displayRotation = activity.mDisplayContent.getDisplayRotation(); + final RemoteDisplayChangeController remoteDisplayChangeController = activity + .mDisplayContent.mRemoteDisplayChangeController; spyOn(displayRotation); + spyOn(remoteDisplayChangeController); final DisplayContent display = activity.mDisplayContent; final int originalRotation = display.getRotation(); // Make {@link DisplayContent#sendNewConfiguration} not apply rotation immediately. - doReturn(true).when(displayRotation).isWaitingForRemoteRotation(); + doReturn(true).when(remoteDisplayChangeController).isWaitingForRemoteDisplayChange(); doReturn((originalRotation + 1) % 4).when(displayRotation).rotationForOrientation( anyInt() /* orientation */, anyInt() /* lastRotation */); // Set to visible so the activity can freeze the screen. @@ -1831,7 +1834,7 @@ public class ActivityRecordTests extends WindowTestsBase { // Simulate the remote rotation has completed and the configuration doesn't change, then // the rotated activity should also be restored by clearing the transform. displayRotation.updateRotationUnchecked(true /* forceUpdate */); - doReturn(false).when(displayRotation).isWaitingForRemoteRotation(); + doReturn(false).when(remoteDisplayChangeController).isWaitingForRemoteDisplayChange(); clearInvocations(activity); display.setFixedRotationLaunchingAppUnchecked(activity); display.sendNewConfiguration(); diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java index 89dfffb532ea..2938f1b3e8a2 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java @@ -124,8 +124,8 @@ import android.view.ContentRecordingSession; import android.view.DisplayCutout; import android.view.DisplayInfo; import android.view.Gravity; -import android.view.IDisplayWindowRotationCallback; -import android.view.IDisplayWindowRotationController; +import android.view.IDisplayChangeWindowCallback; +import android.view.IDisplayChangeWindowController; import android.view.ISystemGestureExclusionListener; import android.view.IWindowManager; import android.view.InsetsState; @@ -136,6 +136,7 @@ import android.view.SurfaceControl; import android.view.SurfaceControl.Transaction; import android.view.View; import android.view.WindowManager; +import android.window.DisplayAreaInfo; import android.window.IDisplayAreaOrganizer; import android.window.WindowContainerToken; @@ -1801,15 +1802,16 @@ public class DisplayContentTests extends WindowTestsBase { return true; }).when(dc).updateDisplayOverrideConfigurationLocked(); final boolean[] called = new boolean[1]; - mWm.mDisplayRotationController = - new IDisplayWindowRotationController.Stub() { + mWm.mDisplayChangeController = + new IDisplayChangeWindowController.Stub() { @Override - public void onRotateDisplay(int displayId, int fromRotation, int toRotation, - IDisplayWindowRotationCallback callback) { + public void onDisplayChange(int displayId, int fromRotation, int toRotation, + DisplayAreaInfo newDisplayAreaInfo, + IDisplayChangeWindowCallback callback) throws RemoteException { called[0] = true; try { - callback.continueRotateDisplay(toRotation, null); + callback.continueDisplayChange(null); } catch (RemoteException e) { assertTrue(false); } @@ -1843,13 +1845,14 @@ public class DisplayContentTests extends WindowTestsBase { // Rotate 180 degree so the display doesn't have configuration change. This condition is // used for the later verification of stop-freezing (without setting mWaitingForConfig). doReturn((dr.getRotation() + 2) % 4).when(dr).rotationForOrientation(anyInt(), anyInt()); - mWm.mDisplayRotationController = - new IDisplayWindowRotationController.Stub() { + mWm.mDisplayChangeController = + new IDisplayChangeWindowController.Stub() { @Override - public void onRotateDisplay(int displayId, int fromRotation, int toRotation, - IDisplayWindowRotationCallback callback) { + public void onDisplayChange(int displayId, int fromRotation, int toRotation, + DisplayAreaInfo newDisplayAreaInfo, + IDisplayChangeWindowCallback callback) throws RemoteException { try { - callback.continueRotateDisplay(toRotation, null); + callback.continueDisplayChange(null); } catch (RemoteException e) { assertTrue(false); } diff --git a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java index 16adffdba6c3..d9d819b5f00f 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java @@ -821,8 +821,11 @@ public class TransitionTests extends WindowTestsBase { player.onTransactionReady(mDisplayContent.getSyncTransaction()); final DisplayRotation displayRotation = mDisplayContent.getDisplayRotation(); + final RemoteDisplayChangeController displayChangeController = mDisplayContent + .mRemoteDisplayChangeController; spyOn(displayRotation); - doReturn(true).when(displayRotation).isWaitingForRemoteRotation(); + spyOn(displayChangeController); + doReturn(true).when(displayChangeController).isWaitingForRemoteDisplayChange(); doReturn(prevRotation + 1).when(displayRotation).rotationForOrientation( anyInt() /* orientation */, anyInt() /* lastRotation */); // Rotation update is skipped while the recents animation is running. |