Merge changes I244b3cb8,I194673d6

* changes:
  Fixed rotation: rotate wallpaper
  Fixed rotation: home and recents animation
This commit is contained in:
Vadim Caen
2020-02-19 18:04:31 +00:00
committed by Android (Google) Code Review
5 changed files with 190 additions and 6 deletions

View File

@@ -16,7 +16,6 @@
package com.android.server.wm;
import static android.app.ActivityTaskManager.INVALID_STACK_ID;
import static android.app.ActivityTaskManager.INVALID_TASK_ID;
import static android.app.ActivityTaskManager.SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
@@ -84,9 +83,6 @@ import static android.view.WindowManager.TRANSIT_ACTIVITY_OPEN;
import static android.view.WindowManager.TRANSIT_TASK_OPEN;
import static android.view.WindowManager.TRANSIT_TASK_TO_FRONT;
import static com.android.server.wm.DisplayContentProto.FOCUSED_ROOT_TASK_ID;
import static com.android.server.wm.DisplayContentProto.RESUMED_ACTIVITY;
import static com.android.server.wm.DisplayContentProto.SINGLE_TASK_INSTANCE;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
@@ -105,12 +101,15 @@ import static com.android.server.wm.DisplayContentProto.DISPLAY_INFO;
import static com.android.server.wm.DisplayContentProto.DOCKED_STACK_DIVIDER_CONTROLLER;
import static com.android.server.wm.DisplayContentProto.DPI;
import static com.android.server.wm.DisplayContentProto.FOCUSED_APP;
import static com.android.server.wm.DisplayContentProto.FOCUSED_ROOT_TASK_ID;
import static com.android.server.wm.DisplayContentProto.ID;
import static com.android.server.wm.DisplayContentProto.OPENING_APPS;
import static com.android.server.wm.DisplayContentProto.OVERLAY_WINDOWS;
import static com.android.server.wm.DisplayContentProto.RESUMED_ACTIVITY;
import static com.android.server.wm.DisplayContentProto.ROOT_DISPLAY_AREA;
import static com.android.server.wm.DisplayContentProto.ROTATION;
import static com.android.server.wm.DisplayContentProto.SCREEN_ROTATION_ANIMATION;
import static com.android.server.wm.DisplayContentProto.SINGLE_TASK_INSTANCE;
import static com.android.server.wm.DisplayContentProto.TASKS;
import static com.android.server.wm.DisplayContentProto.WINDOW_CONTAINER;
import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
@@ -1552,6 +1551,20 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
token.applyFixedRotationTransform(info, displayFrames, mTmpConfiguration);
}
/**
* If the provided {@link ActivityRecord} can be displayed in an orientation different from the
* display's, it will be rotated to match its requested orientation.
*
* @see #rotationForActivityInDifferentOrientation(ActivityRecord).
* @see WindowToken#applyFixedRotationTransform(DisplayInfo, DisplayFrames, Configuration)
*/
void rotateInDifferentOrientationIfNeeded(ActivityRecord activityRecord) {
int rotation = rotationForActivityInDifferentOrientation(activityRecord);
if (rotation != NO_ROTATION) {
startFixedRotationTransform(activityRecord, rotation);
}
}
/**
* Update rotation of the display.
*

View File

@@ -34,6 +34,7 @@ import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_RECENTS;
import static com.android.server.wm.WindowManagerInternal.AppTransitionListener;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.app.ActivityManager.TaskSnapshot;
import android.app.WindowConfiguration;
import android.graphics.Point;
@@ -423,6 +424,11 @@ public class RecentsAnimationController implements DeathRecipient {
mService.mWindowPlacerLocked.performSurfacePlacement();
// If the target 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.
mDisplayContent.rotateInDifferentOrientationIfNeeded(mTargetActivityRecord);
// Notify that the animation has started
if (mStatusBar != null) {
mStatusBar.onRecentsAnimationStateChanged(true /* running */);
@@ -695,6 +701,9 @@ public class RecentsAnimationController implements DeathRecipient {
mDisplayContent.mAppTransition.notifyAppTransitionFinishedLocked(
mTargetActivityRecord.token);
}
if (mTargetActivityRecord.hasFixedRotationTransform()) {
mTargetActivityRecord.clearFixedRotationTransform();
}
}
// Notify that the animation has ended
@@ -828,6 +837,19 @@ public class RecentsAnimationController implements DeathRecipient {
return task != null && isAnimatingTask(task) && !isTargetApp(windowState.mActivityRecord);
}
/**
* If the animation target ActivityRecord has a fixed rotation ({@link
* WindowToken#hasFixedRotationTransform()}, the provided wallpaper will be rotated accordingly.
*
* This avoids any screen rotation animation when animating to the Recents view.
*/
void applyFixedRotationTransformIfNeeded(@NonNull WindowToken wallpaper) {
if (mTargetActivityRecord == null) {
return;
}
wallpaper.applyFixedRotationTransform(mTargetActivityRecord);
}
@VisibleForTesting
class TaskAnimationAdapter implements AnimationAdapter {

View File

@@ -122,10 +122,37 @@ class WallpaperWindowToken extends WindowToken {
mDisplayContent.setLayoutNeeded();
}
final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo();
final WallpaperController wallpaperController = mDisplayContent.mWallpaperController;
if (visible) {
final WindowState wallpaperTarget = wallpaperController.getWallpaperTarget();
final RecentsAnimationController recentsAnimationController =
mWmService.getRecentsAnimationController();
if (wallpaperTarget != null
&& recentsAnimationController != null
&& recentsAnimationController.isAnimatingTask(wallpaperTarget.getTask())) {
// If the Recents animation is running, and the wallpaper target is the animating
// task we want the wallpaper to be rotated in the same orientation as the
// RecentsAnimation's target (e.g the launcher)
recentsAnimationController.applyFixedRotationTransformIfNeeded(this);
} else if (wallpaperTarget != null
&& wallpaperTarget.mToken.hasFixedRotationTransform()) {
// If the wallpaper target has a fixed rotation, we want the wallpaper to follow its
// rotation
applyFixedRotationTransform(wallpaperTarget.mToken);
} else if (hasFixedRotationTransform()) {
clearFixedRotationTransform();
}
}
DisplayInfo displayInfo = getFixedRotationTransformDisplayInfo();
if (displayInfo == null) {
displayInfo = mDisplayContent.getDisplayInfo();
}
final int dw = displayInfo.logicalWidth;
final int dh = displayInfo.logicalHeight;
final WallpaperController wallpaperController = mDisplayContent.mWallpaperController;
for (int wallpaperNdx = mChildren.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) {
final WindowState wallpaper = mChildren.get(wallpaperNdx);

View File

@@ -377,6 +377,19 @@ class WindowToken extends WindowContainer<WindowState> {
onConfigurationChanged(getParent().getConfiguration());
}
/**
* Copies the {@link FixedRotationTransformState} (if any) from the other WindowToken to this
* one.
*/
void applyFixedRotationTransform(WindowToken other) {
final FixedRotationTransformState fixedRotationState = other.mFixedRotationTransformState;
if (fixedRotationState != null) {
applyFixedRotationTransform(fixedRotationState.mDisplayInfo,
fixedRotationState.mDisplayFrames,
fixedRotationState.mRotatedOverrideConfiguration);
}
}
/** Clears the transformation and continue updating the orientation change of display. */
void clearFixedRotationTransform() {
if (mFixedRotationTransformState == null) {

View File

@@ -20,7 +20,9 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
import static android.view.WindowManager.TRANSIT_ACTIVITY_CLOSE;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.atLeast;
@@ -53,6 +55,8 @@ import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import android.app.ActivityManager.TaskSnapshot;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.os.Binder;
import android.os.IBinder;
import android.os.IInterface;
@@ -65,12 +69,16 @@ import androidx.test.filters.SmallTest;
import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
import com.google.common.truth.Truth;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.util.ArrayList;
/**
* Build/Install/Run:
* atest WmTests:RecentsAnimationControllerTest
@@ -330,6 +338,107 @@ public class RecentsAnimationControllerTest extends WindowTestsBase {
assertTrue(activity.shouldAnimate(TRANSIT_ACTIVITY_CLOSE));
}
@Test
public void testRecentViewInFixedPortraitWhenTopAppInLandscape() {
mWm.mIsFixedRotationTransformEnabled = true;
mWm.setRecentsAnimationController(mController);
final ActivityStack homeStack = mDisplayContent.getOrCreateStack(
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, ON_TOP);
final ActivityRecord homeAppWindow =
new ActivityTestsBase.ActivityBuilder(mWm.mAtmService)
.setStack(homeStack)
.setCreateTask(true)
.build();
final ActivityRecord appWindow = createActivityRecord(mDisplayContent,
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
final WindowState win0 = createWindow(null, TYPE_BASE_APPLICATION, appWindow, "win1");
appWindow.addWindow(win0);
final ActivityRecord landActivity = createActivityRecord(mDisplayContent,
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
landActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
final WindowState win1 = createWindow(null, TYPE_BASE_APPLICATION, landActivity, "win1");
landActivity.addWindow(win1);
assertEquals(landActivity.getTask().getTopVisibleActivity(), landActivity);
assertEquals(landActivity.findMainWindow(), win1);
// Ensure that the display is in Landscape
landActivity.onDescendantOrientationChanged(landActivity.token, landActivity);
assertEquals(Configuration.ORIENTATION_LANDSCAPE,
mDisplayContent.getConfiguration().orientation);
mController.initialize(ACTIVITY_TYPE_HOME, new SparseBooleanArray(), homeAppWindow);
// Check that the home app is in portrait
assertEquals(Configuration.ORIENTATION_PORTRAIT,
homeAppWindow.getConfiguration().orientation);
}
@Test
public void testWallpaperHasFixedRotationApplied() {
mWm.mIsFixedRotationTransformEnabled = true;
mWm.setRecentsAnimationController(mController);
// Create a portrait home stack, a wallpaper and a landscape application displayed on top.
// Home stack
final ActivityStack homeStack = mDisplayContent.getOrCreateStack(
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, ON_TOP);
final ActivityRecord homeActivity =
new ActivityTestsBase.ActivityBuilder(mWm.mAtmService)
.setStack(homeStack)
.setCreateTask(true)
.build();
homeActivity.setOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
final WindowState homeWindow = createWindow(null, TYPE_BASE_APPLICATION, homeActivity,
"homeWindow");
homeActivity.addWindow(homeWindow);
homeWindow.getAttrs().flags |= FLAG_SHOW_WALLPAPER;
// Landscape application
final ActivityRecord activity = createActivityRecord(mDisplayContent,
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
final WindowState applicationWindow = createWindow(null, TYPE_BASE_APPLICATION, activity,
"applicationWindow");
activity.addWindow(applicationWindow);
activity.setOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
// Wallpaper
final WallpaperWindowToken wallpaperWindowToken = new WallpaperWindowToken(mWm,
mock(IBinder.class), true, mDisplayContent, true /* ownerCanManageAppTokens */);
final WindowState wallpaperWindow = createWindow(null, TYPE_WALLPAPER, wallpaperWindowToken,
"wallpaperWindow");
// Make sure the landscape activity is on top and the display is in landscape
activity.moveFocusableActivityToTop("test");
mDisplayContent.getConfiguration().windowConfiguration.setRotation(
mDisplayContent.getRotation());
spyOn(mDisplayContent.mWallpaperController);
doReturn(true).when(mDisplayContent.mWallpaperController).isWallpaperVisible();
// Start the recents animation
mController
.initialize(ACTIVITY_TYPE_HOME, new SparseBooleanArray(), homeActivity);
mDisplayContent.mWallpaperController.adjustWallpaperWindows();
// Check preconditions
ArrayList<WallpaperWindowToken> wallpapers = new ArrayList<>(1);
mDisplayContent.forAllWallpaperWindows(wallpapers::add);
Truth.assertThat(wallpapers).hasSize(1);
Truth.assertThat(wallpapers.get(0).getTopChild()).isEqualTo(wallpaperWindow);
// Actual check
assertEquals(Configuration.ORIENTATION_PORTRAIT,
wallpapers.get(0).getConfiguration().orientation);
}
private static void verifyNoMoreInteractionsExceptAsBinder(IInterface binder) {
verify(binder, atLeast(0)).asBinder();
verifyNoMoreInteractions(binder);