Merge changes Ic966923a,I92c6dfac,Id370d798 into rvc-dev am: 33cf9d091c
Change-Id: If325c31e261487a7adaf3ee99c4655ab15f88df0
This commit is contained in:
@@ -494,10 +494,14 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
|
|||||||
* The launching activity which is using fixed rotation transformation.
|
* The launching activity which is using fixed rotation transformation.
|
||||||
*
|
*
|
||||||
* @see #handleTopActivityLaunchingInDifferentOrientation
|
* @see #handleTopActivityLaunchingInDifferentOrientation
|
||||||
|
* @see #setFixedRotationLaunchingApp
|
||||||
* @see DisplayRotation#shouldRotateSeamlessly
|
* @see DisplayRotation#shouldRotateSeamlessly
|
||||||
*/
|
*/
|
||||||
ActivityRecord mFixedRotationLaunchingApp;
|
ActivityRecord mFixedRotationLaunchingApp;
|
||||||
|
|
||||||
|
final FixedRotationTransitionListener mFixedRotationTransitionListener =
|
||||||
|
new FixedRotationTransitionListener();
|
||||||
|
|
||||||
/** Windows added since {@link #mCurrentFocus} was set to null. Used for ANR blaming. */
|
/** Windows added since {@link #mCurrentFocus} was set to null. Used for ANR blaming. */
|
||||||
final ArrayList<WindowState> mWinAddedSinceNullFocus = new ArrayList<>();
|
final ArrayList<WindowState> mWinAddedSinceNullFocus = new ArrayList<>();
|
||||||
|
|
||||||
@@ -928,6 +932,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
|
|||||||
|
|
||||||
mAppTransition = new AppTransition(mWmService.mContext, mWmService, this);
|
mAppTransition = new AppTransition(mWmService.mContext, mWmService, this);
|
||||||
mAppTransition.registerListenerLocked(mWmService.mActivityManagerAppTransitionNotifier);
|
mAppTransition.registerListenerLocked(mWmService.mActivityManagerAppTransitionNotifier);
|
||||||
|
mAppTransition.registerListenerLocked(mFixedRotationTransitionListener);
|
||||||
mAppTransitionController = new AppTransitionController(mWmService, this);
|
mAppTransitionController = new AppTransitionController(mWmService, this);
|
||||||
mUnknownAppVisibilityController = new UnknownAppVisibilityController(mWmService, this);
|
mUnknownAppVisibilityController = new UnknownAppVisibilityController(mWmService, this);
|
||||||
|
|
||||||
@@ -1266,6 +1271,12 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
|
|||||||
if (configUpdated) {
|
if (configUpdated) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The display configuration doesn't change. If there is a launching transformed app, that
|
||||||
|
// means its request to change display configuration has been discarded, then it should
|
||||||
|
// respect to the current configuration of display.
|
||||||
|
clearFixedRotationLaunchingApp();
|
||||||
|
|
||||||
// Something changed (E.g. device rotation), but no configuration update is needed.
|
// Something changed (E.g. device rotation), but no configuration update is needed.
|
||||||
// E.g. changing device rotation by 180 degrees. Go ahead and perform surface placement to
|
// E.g. changing device rotation by 180 degrees. Go ahead and perform surface placement to
|
||||||
// unfreeze the display since we froze it when the rotation was updated in
|
// unfreeze the display since we froze it when the rotation was updated in
|
||||||
@@ -1383,7 +1394,6 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
|
|||||||
orientationSource != null ? orientationSource.asActivityRecord() : null;
|
orientationSource != null ? orientationSource.asActivityRecord() : null;
|
||||||
// Currently there is no use case from non-activity.
|
// Currently there is no use case from non-activity.
|
||||||
if (r != null && handleTopActivityLaunchingInDifferentOrientation(r)) {
|
if (r != null && handleTopActivityLaunchingInDifferentOrientation(r)) {
|
||||||
mFixedRotationLaunchingApp = r;
|
|
||||||
// Display orientation should be deferred until the top fixed rotation is finished.
|
// Display orientation should be deferred until the top fixed rotation is finished.
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -1448,47 +1458,66 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
startFixedRotationTransform(r, rotation);
|
setFixedRotationLaunchingApp(r, rotation);
|
||||||
mAppTransition.registerListenerLocked(new WindowManagerInternal.AppTransitionListener() {
|
|
||||||
void done() {
|
|
||||||
r.finishFixedRotationTransform();
|
|
||||||
mAppTransition.unregisterListener(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onAppTransitionFinishedLocked(IBinder token) {
|
|
||||||
if (token == r.token) {
|
|
||||||
done();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onAppTransitionCancelledLocked(int transit) {
|
|
||||||
done();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onAppTransitionTimeoutLocked() {
|
|
||||||
done();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return {@code true} if the display orientation will be changed. */
|
/**
|
||||||
boolean continueUpdateOrientationForDiffOrienLaunchingApp(WindowToken token) {
|
* Sets the provided record to {@link mFixedRotationLaunchingApp} if possible to apply fixed
|
||||||
if (token != mFixedRotationLaunchingApp) {
|
* rotation transform to it and indicate that the display may be rotated after it is launched.
|
||||||
return false;
|
*/
|
||||||
|
void setFixedRotationLaunchingApp(@NonNull ActivityRecord r, @Surface.Rotation int rotation) {
|
||||||
|
final WindowToken prevRotatedLaunchingApp = mFixedRotationLaunchingApp;
|
||||||
|
if (prevRotatedLaunchingApp != null
|
||||||
|
&& prevRotatedLaunchingApp.getWindowConfiguration().getRotation() == rotation
|
||||||
|
// It is animating so we can expect there will have a transition callback.
|
||||||
|
&& prevRotatedLaunchingApp.isAnimating(TRANSITION | PARENTS)) {
|
||||||
|
// It may be the case that multiple activities launch consecutively. Because their
|
||||||
|
// rotation are the same, the transformed state can be shared to avoid duplicating
|
||||||
|
// the heavy operations. This also benefits that the states of multiple activities
|
||||||
|
// are handled together.
|
||||||
|
r.linkFixedRotationTransform(prevRotatedLaunchingApp);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!r.hasFixedRotationTransform()) {
|
||||||
|
startFixedRotationTransform(r, rotation);
|
||||||
|
}
|
||||||
|
mFixedRotationLaunchingApp = r;
|
||||||
|
if (prevRotatedLaunchingApp != null) {
|
||||||
|
prevRotatedLaunchingApp.finishFixedRotationTransform();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Continue updating the orientation change of display if it was deferred by a top activity
|
||||||
|
* launched in a different orientation.
|
||||||
|
*/
|
||||||
|
void continueUpdateOrientationForDiffOrienLaunchingApp() {
|
||||||
|
if (mFixedRotationLaunchingApp == null) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
// Update directly because the app which will change the orientation of display is ready.
|
// Update directly because the app which will change the orientation of display is ready.
|
||||||
if (mDisplayRotation.updateOrientation(getOrientation(), false /* forceUpdate */)) {
|
if (mDisplayRotation.updateOrientation(getOrientation(), false /* forceUpdate */)) {
|
||||||
sendNewConfiguration();
|
sendNewConfiguration();
|
||||||
return true;
|
return;
|
||||||
}
|
}
|
||||||
// The display won't rotate (e.g. the orientation from sensor has updated again before
|
// The orientation of display is not changed.
|
||||||
// applying rotation to display), so clear it to stop using seamless rotation.
|
clearFixedRotationLaunchingApp();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears the {@link mFixedRotationLaunchingApp} without applying rotation to display. It is
|
||||||
|
* used when the display won't rotate (e.g. the orientation from sensor has updated again before
|
||||||
|
* applying rotation to display) but the launching app has been transformed. So the record need
|
||||||
|
* to be cleared and restored to stop using seamless rotation and rotated configuration.
|
||||||
|
*/
|
||||||
|
private void clearFixedRotationLaunchingApp() {
|
||||||
|
if (mFixedRotationLaunchingApp == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mFixedRotationLaunchingApp.finishFixedRotationTransform();
|
||||||
mFixedRotationLaunchingApp = null;
|
mFixedRotationLaunchingApp = null;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void startFixedRotationTransform(WindowToken token, int rotation) {
|
private void startFixedRotationTransform(WindowToken token, int rotation) {
|
||||||
@@ -2858,6 +2887,9 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
|
|||||||
pw.print(" mLastStatusBarVisibility=0x");
|
pw.print(" mLastStatusBarVisibility=0x");
|
||||||
pw.println(Integer.toHexString(mLastStatusBarVisibility));
|
pw.println(Integer.toHexString(mLastStatusBarVisibility));
|
||||||
}
|
}
|
||||||
|
if (mFixedRotationLaunchingApp != null) {
|
||||||
|
pw.println(" mFixedRotationLaunchingApp=" + mFixedRotationLaunchingApp);
|
||||||
|
}
|
||||||
|
|
||||||
pw.println();
|
pw.println();
|
||||||
mWallpaperController.dump(pw, " ");
|
mWallpaperController.dump(pw, " ");
|
||||||
@@ -5184,7 +5216,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
|
|||||||
final int currRotation = currOverrideConfig.windowConfiguration.getRotation();
|
final int currRotation = currOverrideConfig.windowConfiguration.getRotation();
|
||||||
final int overrideRotation = overrideConfiguration.windowConfiguration.getRotation();
|
final int overrideRotation = overrideConfiguration.windowConfiguration.getRotation();
|
||||||
if (currRotation != ROTATION_UNDEFINED && currRotation != overrideRotation) {
|
if (currRotation != ROTATION_UNDEFINED && currRotation != overrideRotation) {
|
||||||
applyRotationAndClearFixedRotation(currRotation, overrideRotation);
|
applyRotationAndFinishFixedRotation(currRotation, overrideRotation);
|
||||||
}
|
}
|
||||||
mCurrentOverrideConfigurationChanges = currOverrideConfig.diff(overrideConfiguration);
|
mCurrentOverrideConfigurationChanges = currOverrideConfig.diff(overrideConfiguration);
|
||||||
super.onRequestedOverrideConfigurationChanged(overrideConfiguration);
|
super.onRequestedOverrideConfigurationChanged(overrideConfiguration);
|
||||||
@@ -5200,7 +5232,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
|
|||||||
* fixed rotation transform also needs to be cleared to make sure the rotated activity fits
|
* fixed rotation transform also needs to be cleared to make sure the rotated activity fits
|
||||||
* the display naturally.
|
* the display naturally.
|
||||||
*/
|
*/
|
||||||
private void applyRotationAndClearFixedRotation(int oldRotation, int newRotation) {
|
private void applyRotationAndFinishFixedRotation(int oldRotation, int newRotation) {
|
||||||
if (mFixedRotationLaunchingApp == null) {
|
if (mFixedRotationLaunchingApp == null) {
|
||||||
applyRotation(oldRotation, newRotation);
|
applyRotation(oldRotation, newRotation);
|
||||||
return;
|
return;
|
||||||
@@ -5219,7 +5251,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
mFixedRotationLaunchingApp.clearFixedRotationTransform(
|
mFixedRotationLaunchingApp.finishFixedRotationTransform(
|
||||||
() -> applyRotation(oldRotation, newRotation));
|
() -> applyRotation(oldRotation, newRotation));
|
||||||
mFixedRotationLaunchingApp = null;
|
mFixedRotationLaunchingApp = null;
|
||||||
}
|
}
|
||||||
@@ -5494,6 +5526,75 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** The entry for proceeding to handle {@link #mFixedRotationLaunchingApp}. */
|
||||||
|
class FixedRotationTransitionListener extends WindowManagerInternal.AppTransitionListener {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The animating activity which shows the recents task list. It is set between
|
||||||
|
* {@link RecentsAnimationController#initialize} and
|
||||||
|
* {@link RecentsAnimationController#cancelAnimation}.
|
||||||
|
*/
|
||||||
|
private ActivityRecord mAnimatingRecents;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the recents activity has a fixed orientation which is different from the current top
|
||||||
|
* activity, it will be rotated before being shown so we avoid a screen rotation animation
|
||||||
|
* when showing the Recents view.
|
||||||
|
*/
|
||||||
|
void onStartRecentsAnimation(@NonNull ActivityRecord r) {
|
||||||
|
mAnimatingRecents = r;
|
||||||
|
rotateInDifferentOrientationIfNeeded(r);
|
||||||
|
if (r.hasFixedRotationTransform()) {
|
||||||
|
// Set the record so we can recognize it to continue to update display orientation
|
||||||
|
// if the recents activity becomes the top later.
|
||||||
|
setFixedRotationLaunchingApp(r, r.getWindowConfiguration().getRotation());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If {@link #mAnimatingRecents} still has fixed rotation, it should be moved to top so we
|
||||||
|
* don't clear {@link #mFixedRotationLaunchingApp} that will be handled by transition.
|
||||||
|
*/
|
||||||
|
void onFinishRecentsAnimation() {
|
||||||
|
final ActivityRecord animatingRecents = mAnimatingRecents;
|
||||||
|
mAnimatingRecents = null;
|
||||||
|
if (animatingRecents != null && animatingRecents == mFixedRotationLaunchingApp
|
||||||
|
&& !animatingRecents.hasFixedRotationTransform()) {
|
||||||
|
// The recents activity won't be the top, such as giving up the swipe up gesture
|
||||||
|
// and return to the original top.
|
||||||
|
mFixedRotationLaunchingApp = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAppTransitionFinishedLocked(IBinder token) {
|
||||||
|
final ActivityRecord r = getActivityRecord(token);
|
||||||
|
// Ignore the animating recents so the fixed rotation transform won't be switched twice
|
||||||
|
// by finishing the recents animation and moving it to top. That also avoids flickering
|
||||||
|
// due to wait for previous activity to be paused if it supports PiP that ignores the
|
||||||
|
// effect of resume-while-pausing.
|
||||||
|
if (r == null || r == mAnimatingRecents) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (mFixedRotationLaunchingApp != null
|
||||||
|
&& mFixedRotationLaunchingApp.hasFixedRotationTransform(r)) {
|
||||||
|
continueUpdateOrientationForDiffOrienLaunchingApp();
|
||||||
|
} else {
|
||||||
|
r.finishFixedRotationTransform();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAppTransitionCancelledLocked(int transit) {
|
||||||
|
continueUpdateOrientationForDiffOrienLaunchingApp();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAppTransitionTimeoutLocked() {
|
||||||
|
continueUpdateOrientationForDiffOrienLaunchingApp();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class RemoteInsetsControlTarget implements InsetsControlTarget {
|
class RemoteInsetsControlTarget implements InsetsControlTarget {
|
||||||
private final IDisplayWindowInsetsController mRemoteInsetsController;
|
private final IDisplayWindowInsetsController mRemoteInsetsController;
|
||||||
|
|
||||||
|
|||||||
@@ -411,10 +411,7 @@ public class RecentsAnimationController implements DeathRecipient {
|
|||||||
|
|
||||||
mService.mWindowPlacerLocked.performSurfacePlacement();
|
mService.mWindowPlacerLocked.performSurfacePlacement();
|
||||||
|
|
||||||
// If the target activity has a fixed orientation which is different from the current top
|
mDisplayContent.mFixedRotationTransitionListener.onStartRecentsAnimation(targetActivity);
|
||||||
// activity, it will be rotated before being shown so we avoid a screen rotation
|
|
||||||
// animation when showing the Recents view.
|
|
||||||
mDisplayContent.rotateInDifferentOrientationIfNeeded(mTargetActivityRecord);
|
|
||||||
|
|
||||||
// Notify that the animation has started
|
// Notify that the animation has started
|
||||||
if (mStatusBar != null) {
|
if (mStatusBar != null) {
|
||||||
@@ -736,11 +733,13 @@ public class RecentsAnimationController implements DeathRecipient {
|
|||||||
if (reorderMode == REORDER_MOVE_TO_TOP || reorderMode == REORDER_KEEP_IN_PLACE) {
|
if (reorderMode == REORDER_MOVE_TO_TOP || reorderMode == REORDER_KEEP_IN_PLACE) {
|
||||||
mDisplayContent.mAppTransition.notifyAppTransitionFinishedLocked(
|
mDisplayContent.mAppTransition.notifyAppTransitionFinishedLocked(
|
||||||
mTargetActivityRecord.token);
|
mTargetActivityRecord.token);
|
||||||
}
|
} else {
|
||||||
if (mTargetActivityRecord.hasFixedRotationTransform()) {
|
// The target activity will be moved to original position (non-top). Since it won't
|
||||||
|
// affect display orientation, just finish the transform.
|
||||||
mTargetActivityRecord.finishFixedRotationTransform();
|
mTargetActivityRecord.finishFixedRotationTransform();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
mDisplayContent.mFixedRotationTransitionListener.onFinishRecentsAnimation();
|
||||||
|
|
||||||
// Notify that the animation has ended
|
// Notify that the animation has ended
|
||||||
if (mStatusBar != null) {
|
if (mStatusBar != null) {
|
||||||
|
|||||||
@@ -119,7 +119,6 @@ class WindowToken extends WindowContainer<WindowState> {
|
|||||||
* rotated by the given rotated display info, frames and insets.
|
* rotated by the given rotated display info, frames and insets.
|
||||||
*/
|
*/
|
||||||
private static class FixedRotationTransformState {
|
private static class FixedRotationTransformState {
|
||||||
final WindowToken mOwner;
|
|
||||||
final DisplayInfo mDisplayInfo;
|
final DisplayInfo mDisplayInfo;
|
||||||
final DisplayFrames mDisplayFrames;
|
final DisplayFrames mDisplayFrames;
|
||||||
final InsetsState mInsetsState;
|
final InsetsState mInsetsState;
|
||||||
@@ -133,10 +132,9 @@ class WindowToken extends WindowContainer<WindowState> {
|
|||||||
final ArrayList<WindowContainer<?>> mRotatedContainers = new ArrayList<>(3);
|
final ArrayList<WindowContainer<?>> mRotatedContainers = new ArrayList<>(3);
|
||||||
boolean mIsTransforming = true;
|
boolean mIsTransforming = true;
|
||||||
|
|
||||||
FixedRotationTransformState(WindowToken owner, DisplayInfo rotatedDisplayInfo,
|
FixedRotationTransformState(DisplayInfo rotatedDisplayInfo,
|
||||||
DisplayFrames rotatedDisplayFrames, InsetsState rotatedInsetsState,
|
DisplayFrames rotatedDisplayFrames, InsetsState rotatedInsetsState,
|
||||||
Configuration rotatedConfig, int currentRotation) {
|
Configuration rotatedConfig, int currentRotation) {
|
||||||
mOwner = owner;
|
|
||||||
mDisplayInfo = rotatedDisplayInfo;
|
mDisplayInfo = rotatedDisplayInfo;
|
||||||
mDisplayFrames = rotatedDisplayFrames;
|
mDisplayFrames = rotatedDisplayFrames;
|
||||||
mInsetsState = rotatedInsetsState;
|
mInsetsState = rotatedInsetsState;
|
||||||
@@ -482,6 +480,14 @@ class WindowToken extends WindowContainer<WindowState> {
|
|||||||
return mFixedRotationTransformState != null;
|
return mFixedRotationTransformState != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Returns {@code true} if the given token shares the same transform. */
|
||||||
|
boolean hasFixedRotationTransform(WindowToken token) {
|
||||||
|
if (mFixedRotationTransformState == null || token == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return this == token || mFixedRotationTransformState == token.mFixedRotationTransformState;
|
||||||
|
}
|
||||||
|
|
||||||
boolean isFinishingFixedRotationTransform() {
|
boolean isFinishingFixedRotationTransform() {
|
||||||
return mFixedRotationTransformState != null
|
return mFixedRotationTransformState != null
|
||||||
&& !mFixedRotationTransformState.mIsTransforming;
|
&& !mFixedRotationTransformState.mIsTransforming;
|
||||||
@@ -520,15 +526,14 @@ class WindowToken extends WindowContainer<WindowState> {
|
|||||||
final InsetsState insetsState = new InsetsState();
|
final InsetsState insetsState = new InsetsState();
|
||||||
mDisplayContent.getDisplayPolicy().simulateLayoutDisplay(displayFrames, insetsState,
|
mDisplayContent.getDisplayPolicy().simulateLayoutDisplay(displayFrames, insetsState,
|
||||||
mDisplayContent.getConfiguration().uiMode);
|
mDisplayContent.getConfiguration().uiMode);
|
||||||
mFixedRotationTransformState = new FixedRotationTransformState(this, info, displayFrames,
|
mFixedRotationTransformState = new FixedRotationTransformState(info, displayFrames,
|
||||||
insetsState, new Configuration(config), mDisplayContent.getRotation());
|
insetsState, new Configuration(config), mDisplayContent.getRotation());
|
||||||
onConfigurationChanged(getParent().getConfiguration());
|
onConfigurationChanged(getParent().getConfiguration());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reuses the {@link FixedRotationTransformState} (if any) from the other WindowToken to this
|
* Reuses the {@link FixedRotationTransformState} (if any) from the other WindowToken to this
|
||||||
* one. This takes the same effect as {@link #applyFixedRotationTransform}, but the linked state
|
* one. This takes the same effect as {@link #applyFixedRotationTransform}.
|
||||||
* can only be cleared by the state owner.
|
|
||||||
*/
|
*/
|
||||||
void linkFixedRotationTransform(WindowToken other) {
|
void linkFixedRotationTransform(WindowToken other) {
|
||||||
if (mFixedRotationTransformState != null) {
|
if (mFixedRotationTransformState != null) {
|
||||||
@@ -543,28 +548,15 @@ class WindowToken extends WindowContainer<WindowState> {
|
|||||||
onConfigurationChanged(getParent().getConfiguration());
|
onConfigurationChanged(getParent().getConfiguration());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Finishes the transform and continue updating the orientation change of display. Only the
|
|
||||||
* state owner can finish the transform state.
|
|
||||||
*/
|
|
||||||
void finishFixedRotationTransform() {
|
void finishFixedRotationTransform() {
|
||||||
if (mFixedRotationTransformState == null || mFixedRotationTransformState.mOwner != this) {
|
finishFixedRotationTransform(null /* applyDisplayRotation */);
|
||||||
return;
|
|
||||||
}
|
|
||||||
final boolean changed =
|
|
||||||
mDisplayContent.continueUpdateOrientationForDiffOrienLaunchingApp(this);
|
|
||||||
// If it is not the launching app or the display is not rotated, make sure the transform is
|
|
||||||
// cleared and the configuration is restored from parent.
|
|
||||||
if (!changed) {
|
|
||||||
clearFixedRotationTransform(null /* applyDisplayRotation */);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clears the transform and apply display rotation if the action is given. If the display will
|
* Finishes the transform and apply display rotation if the action is given. If the display will
|
||||||
* not rotate, the transformed containers are restored to their original states.
|
* not rotate, the transformed containers are restored to their original states.
|
||||||
*/
|
*/
|
||||||
void clearFixedRotationTransform(Runnable applyDisplayRotation) {
|
void finishFixedRotationTransform(Runnable applyDisplayRotation) {
|
||||||
final FixedRotationTransformState state = mFixedRotationTransformState;
|
final FixedRotationTransformState state = mFixedRotationTransformState;
|
||||||
if (state == null) {
|
if (state == null) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -66,6 +66,7 @@ import static org.junit.Assert.assertNull;
|
|||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
import static org.mockito.ArgumentMatchers.anyInt;
|
import static org.mockito.ArgumentMatchers.anyInt;
|
||||||
import static org.mockito.ArgumentMatchers.anyString;
|
import static org.mockito.ArgumentMatchers.anyString;
|
||||||
|
import static org.mockito.Mockito.clearInvocations;
|
||||||
import static org.mockito.Mockito.never;
|
import static org.mockito.Mockito.never;
|
||||||
|
|
||||||
import android.app.ActivityOptions;
|
import android.app.ActivityOptions;
|
||||||
@@ -1402,6 +1403,7 @@ public class ActivityRecordTests extends ActivityTestsBase {
|
|||||||
final DisplayInfo rotatedInfo = mActivity.getFixedRotationTransformDisplayInfo();
|
final DisplayInfo rotatedInfo = mActivity.getFixedRotationTransformDisplayInfo();
|
||||||
mActivity.finishFixedRotationTransform();
|
mActivity.finishFixedRotationTransform();
|
||||||
final ScreenRotationAnimation rotationAnim = display.getRotationAnimation();
|
final ScreenRotationAnimation rotationAnim = display.getRotationAnimation();
|
||||||
|
assertNotNull(rotationAnim);
|
||||||
rotationAnim.setRotation(display.getPendingTransaction(), originalRotation);
|
rotationAnim.setRotation(display.getPendingTransaction(), originalRotation);
|
||||||
|
|
||||||
// Because the display doesn't rotate, the rotated activity needs to cancel the fixed
|
// Because the display doesn't rotate, the rotated activity needs to cancel the fixed
|
||||||
@@ -1409,8 +1411,18 @@ public class ActivityRecordTests extends ActivityTestsBase {
|
|||||||
verify(mActivity).onCancelFixedRotationTransform(rotatedInfo.rotation);
|
verify(mActivity).onCancelFixedRotationTransform(rotatedInfo.rotation);
|
||||||
assertTrue(mActivity.isFreezingScreen());
|
assertTrue(mActivity.isFreezingScreen());
|
||||||
assertFalse(displayRotation.isRotatingSeamlessly());
|
assertFalse(displayRotation.isRotatingSeamlessly());
|
||||||
assertNotNull(rotationAnim);
|
|
||||||
assertTrue(rotationAnim.isRotating());
|
assertTrue(rotationAnim.isRotating());
|
||||||
|
|
||||||
|
// 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();
|
||||||
|
clearInvocations(mActivity);
|
||||||
|
display.mFixedRotationLaunchingApp = mActivity;
|
||||||
|
display.sendNewConfiguration();
|
||||||
|
|
||||||
|
assertNull(display.mFixedRotationLaunchingApp);
|
||||||
|
assertFalse(mActivity.hasFixedRotationTransform());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -790,9 +790,7 @@ public class DisplayContentTests extends WindowTestsBase {
|
|||||||
final DisplayContent dc = createNewDisplay();
|
final DisplayContent dc = createNewDisplay();
|
||||||
dc.getDisplayRotation().setFixedToUserRotation(
|
dc.getDisplayRotation().setFixedToUserRotation(
|
||||||
IWindowManager.FIXED_TO_USER_ROTATION_DISABLED);
|
IWindowManager.FIXED_TO_USER_ROTATION_DISABLED);
|
||||||
final int newOrientation = dc.getLastOrientation() == SCREEN_ORIENTATION_LANDSCAPE
|
final int newOrientation = getRotatedOrientation(dc);
|
||||||
? SCREEN_ORIENTATION_PORTRAIT
|
|
||||||
: SCREEN_ORIENTATION_LANDSCAPE;
|
|
||||||
|
|
||||||
final ActivityStack stack =
|
final ActivityStack stack =
|
||||||
new ActivityTestsBase.StackBuilder(mWm.mAtmService.mRootWindowContainer)
|
new ActivityTestsBase.StackBuilder(mWm.mAtmService.mRootWindowContainer)
|
||||||
@@ -812,9 +810,7 @@ public class DisplayContentTests extends WindowTestsBase {
|
|||||||
final DisplayContent dc = createNewDisplay();
|
final DisplayContent dc = createNewDisplay();
|
||||||
dc.getDisplayRotation().setFixedToUserRotation(
|
dc.getDisplayRotation().setFixedToUserRotation(
|
||||||
IWindowManager.FIXED_TO_USER_ROTATION_ENABLED);
|
IWindowManager.FIXED_TO_USER_ROTATION_ENABLED);
|
||||||
final int newOrientation = dc.getLastOrientation() == SCREEN_ORIENTATION_LANDSCAPE
|
final int newOrientation = getRotatedOrientation(dc);
|
||||||
? SCREEN_ORIENTATION_PORTRAIT
|
|
||||||
: SCREEN_ORIENTATION_LANDSCAPE;
|
|
||||||
|
|
||||||
final ActivityStack stack =
|
final ActivityStack stack =
|
||||||
new ActivityTestsBase.StackBuilder(mWm.mAtmService.mRootWindowContainer)
|
new ActivityTestsBase.StackBuilder(mWm.mAtmService.mRootWindowContainer)
|
||||||
@@ -1083,7 +1079,8 @@ public class DisplayContentTests extends WindowTestsBase {
|
|||||||
mDisplayContent.prepareAppTransition(WindowManager.TRANSIT_ACTIVITY_OPEN,
|
mDisplayContent.prepareAppTransition(WindowManager.TRANSIT_ACTIVITY_OPEN,
|
||||||
false /* alwaysKeepCurrent */);
|
false /* alwaysKeepCurrent */);
|
||||||
mDisplayContent.mOpeningApps.add(app);
|
mDisplayContent.mOpeningApps.add(app);
|
||||||
app.setRequestedOrientation(SCREEN_ORIENTATION_LANDSCAPE);
|
final int newOrientation = getRotatedOrientation(mDisplayContent);
|
||||||
|
app.setRequestedOrientation(newOrientation);
|
||||||
|
|
||||||
assertTrue(app.isFixedRotationTransforming());
|
assertTrue(app.isFixedRotationTransforming());
|
||||||
assertTrue(mDisplayContent.getDisplayRotation().shouldRotateSeamlessly(
|
assertTrue(mDisplayContent.getDisplayRotation().shouldRotateSeamlessly(
|
||||||
@@ -1124,12 +1121,25 @@ public class DisplayContentTests extends WindowTestsBase {
|
|||||||
mWallpaperWindow.mToken.onAnimationLeashCreated(t, null /* leash */);
|
mWallpaperWindow.mToken.onAnimationLeashCreated(t, null /* leash */);
|
||||||
verify(t, never()).setPosition(any(), eq(0), eq(0));
|
verify(t, never()).setPosition(any(), eq(0), eq(0));
|
||||||
|
|
||||||
|
// Launch another activity before the transition is finished.
|
||||||
|
final ActivityRecord app2 = new ActivityTestsBase.StackBuilder(mWm.mRoot)
|
||||||
|
.setDisplay(mDisplayContent).build().getTopMostActivity();
|
||||||
|
mDisplayContent.prepareAppTransition(WindowManager.TRANSIT_ACTIVITY_OPEN,
|
||||||
|
false /* alwaysKeepCurrent */);
|
||||||
|
mDisplayContent.mOpeningApps.add(app2);
|
||||||
|
app2.setRequestedOrientation(newOrientation);
|
||||||
|
|
||||||
|
// The activity should share the same transform state as the existing one.
|
||||||
|
assertTrue(app.hasFixedRotationTransform(app2));
|
||||||
|
|
||||||
|
// The display should be rotated after the launch is finished.
|
||||||
mDisplayContent.mAppTransition.notifyAppTransitionFinishedLocked(app.token);
|
mDisplayContent.mAppTransition.notifyAppTransitionFinishedLocked(app.token);
|
||||||
|
|
||||||
// The animation in old rotation should be cancelled.
|
// The animation in old rotation should be cancelled.
|
||||||
assertFalse(closingApp.isAnimating());
|
assertFalse(closingApp.isAnimating());
|
||||||
// The display should be rotated after the launch is finished.
|
// The fixed rotation should be cleared and the new rotation is applied to display.
|
||||||
assertFalse(app.hasFixedRotationTransform());
|
assertFalse(app.hasFixedRotationTransform());
|
||||||
|
assertFalse(app2.hasFixedRotationTransform());
|
||||||
assertEquals(config90.orientation, mDisplayContent.getConfiguration().orientation);
|
assertEquals(config90.orientation, mDisplayContent.getConfiguration().orientation);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1292,6 +1302,12 @@ public class DisplayContentTests extends WindowTestsBase {
|
|||||||
assertThat("topToBottom", actualWindows, is(reverseList(expectedWindowsBottomToTop)));
|
assertThat("topToBottom", actualWindows, is(reverseList(expectedWindowsBottomToTop)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static int getRotatedOrientation(DisplayContent dc) {
|
||||||
|
return dc.getLastOrientation() == SCREEN_ORIENTATION_LANDSCAPE
|
||||||
|
? SCREEN_ORIENTATION_PORTRAIT
|
||||||
|
: SCREEN_ORIENTATION_LANDSCAPE;
|
||||||
|
}
|
||||||
|
|
||||||
private static List<WindowState> reverseList(List<WindowState> list) {
|
private static List<WindowState> reverseList(List<WindowState> list) {
|
||||||
final ArrayList<WindowState> result = new ArrayList<>(list);
|
final ArrayList<WindowState> result = new ArrayList<>(list);
|
||||||
Collections.reverse(result);
|
Collections.reverse(result);
|
||||||
|
|||||||
@@ -344,9 +344,17 @@ public class RecentsAnimationControllerTest extends WindowTestsBase {
|
|||||||
|
|
||||||
mController.initialize(ACTIVITY_TYPE_HOME, new SparseBooleanArray(), homeActivity);
|
mController.initialize(ACTIVITY_TYPE_HOME, new SparseBooleanArray(), homeActivity);
|
||||||
|
|
||||||
|
assertEquals(homeActivity, mDefaultDisplay.mFixedRotationLaunchingApp);
|
||||||
|
|
||||||
// Check that the home app is in portrait
|
// Check that the home app is in portrait
|
||||||
assertEquals(Configuration.ORIENTATION_PORTRAIT,
|
assertEquals(Configuration.ORIENTATION_PORTRAIT,
|
||||||
homeActivity.getConfiguration().orientation);
|
homeActivity.getConfiguration().orientation);
|
||||||
|
|
||||||
|
// Home activity won't become top (return to landActivity), so its fixed rotation and the
|
||||||
|
// top rotated record should be cleared.
|
||||||
|
mController.cleanupAnimation(REORDER_MOVE_TO_ORIGINAL_POSITION);
|
||||||
|
assertFalse(homeActivity.hasFixedRotationTransform());
|
||||||
|
assertNull(mDefaultDisplay.mFixedRotationLaunchingApp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -401,12 +409,16 @@ public class RecentsAnimationControllerTest extends WindowTestsBase {
|
|||||||
assertEquals(Configuration.ORIENTATION_PORTRAIT,
|
assertEquals(Configuration.ORIENTATION_PORTRAIT,
|
||||||
wallpapers.get(0).getConfiguration().orientation);
|
wallpapers.get(0).getConfiguration().orientation);
|
||||||
|
|
||||||
// Wallpaper's transform state is controlled by home, so the invocation should be no-op.
|
mController.cleanupAnimation(REORDER_MOVE_TO_TOP);
|
||||||
wallpaperWindowToken.finishFixedRotationTransform();
|
// The transform state should keep because we expect to listen the signal from the
|
||||||
assertTrue(wallpaperWindowToken.hasFixedRotationTransform());
|
// transition executed by moving the task to front.
|
||||||
|
assertTrue(homeActivity.hasFixedRotationTransform());
|
||||||
|
assertEquals(homeActivity, mDefaultDisplay.mFixedRotationLaunchingApp);
|
||||||
|
|
||||||
|
mDefaultDisplay.mFixedRotationTransitionListener.onAppTransitionFinishedLocked(
|
||||||
|
homeActivity.token);
|
||||||
// Wallpaper's transform state should be cleared with home.
|
// Wallpaper's transform state should be cleared with home.
|
||||||
homeActivity.finishFixedRotationTransform();
|
assertFalse(homeActivity.hasFixedRotationTransform());
|
||||||
assertFalse(wallpaperWindowToken.hasFixedRotationTransform());
|
assertFalse(wallpaperWindowToken.hasFixedRotationTransform());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -136,7 +136,7 @@ public class WindowTokenTests extends WindowTestsBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testClearFixedRotationTransform() {
|
public void testFinishFixedRotationTransform() {
|
||||||
final WindowToken appToken = mAppWindow.mToken;
|
final WindowToken appToken = mAppWindow.mToken;
|
||||||
final WindowToken wallpaperToken = mWallpaperWindow.mToken;
|
final WindowToken wallpaperToken = mWallpaperWindow.mToken;
|
||||||
final Configuration config = new Configuration(mDisplayContent.getConfiguration());
|
final Configuration config = new Configuration(mDisplayContent.getConfiguration());
|
||||||
@@ -152,7 +152,7 @@ public class WindowTokenTests extends WindowTestsBase {
|
|||||||
assertEquals(targetRotation, wallpaperToken.getWindowConfiguration().getRotation());
|
assertEquals(targetRotation, wallpaperToken.getWindowConfiguration().getRotation());
|
||||||
|
|
||||||
// The display doesn't rotate, the transformation will be canceled.
|
// The display doesn't rotate, the transformation will be canceled.
|
||||||
mAppWindow.mToken.clearFixedRotationTransform(null /* applyDisplayRotation */);
|
mAppWindow.mToken.finishFixedRotationTransform();
|
||||||
|
|
||||||
// The window tokens should restore to the original rotation.
|
// The window tokens should restore to the original rotation.
|
||||||
assertEquals(originalRotation, appToken.getWindowConfiguration().getRotation());
|
assertEquals(originalRotation, appToken.getWindowConfiguration().getRotation());
|
||||||
|
|||||||
Reference in New Issue
Block a user