Merge "Synchronize display change with the Shell" into tm-qpr-dev am: 343260adfa

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/18140347

Change-Id: I79ae5b123006a43140cb11dd5344483552440e75
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Nick Chameyev
2022-05-12 17:15:05 +00:00
committed by Automerger Merge Worker
21 changed files with 438 additions and 221 deletions

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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",
@@ -3397,12 +3403,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",
@@ -3499,6 +3499,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",
@@ -3523,6 +3529,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",
@@ -3865,6 +3877,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",

View File

@@ -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();
}
}
});

View File

@@ -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);
}
}

View File

@@ -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) {

View File

@@ -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;
}

View File

@@ -156,7 +156,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;
}

View File

@@ -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;
@@ -1318,7 +1319,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
if (displayId != DEFAULT_DISPLAY) {
return;
}
mDisplayController.addDisplayChangingController(this::onRotateDisplay);
mDisplayController.addDisplayChangingController(this::onDisplayChange);
}
@Override
@@ -1329,14 +1330,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();
}

View File

@@ -629,8 +629,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(

View File

@@ -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();
}

View File

@@ -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));

View File

@@ -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());
}
}
}

View File

@@ -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();
}
}

View File

@@ -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,13 +106,44 @@ 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 {
DeviceStateListener(Context context) {

View File

@@ -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);
}
}

View File

@@ -238,10 +238,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;
@@ -682,9 +682,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;
@@ -4266,12 +4266,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;
@@ -4303,17 +4304,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");
@@ -6112,24 +6113,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;

View File

@@ -1786,13 +1786,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.
@@ -1830,7 +1833,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();

View File

@@ -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);
}

View File

@@ -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.