Merge "Use rotation transition to handle display config change" into sc-v2-dev

This commit is contained in:
Riddle Hsu
2021-09-27 02:38:56 +00:00
committed by Android (Google) Code Review
9 changed files with 82 additions and 32 deletions

View File

@@ -141,8 +141,9 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler {
static boolean isRotationSeamless(@NonNull TransitionInfo info,
DisplayController displayController) {
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS,
"Display is rotating, check if it should be seamless.");
"Display is changing, check if it should be seamless.");
boolean checkedDisplayLayout = false;
boolean hasTask = false;
for (int i = info.getChanges().size() - 1; i >= 0; --i) {
final TransitionInfo.Change change = info.getChanges().get(i);
@@ -166,6 +167,7 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler {
return false;
}
} else if (change.getTaskInfo() != null) {
hasTask = true;
// We only enable seamless rotation if all the visible task windows requested it.
if (change.getRotationAnimation() != ROTATION_ANIMATION_SEAMLESS) {
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS,
@@ -209,8 +211,12 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler {
}
}
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " Rotation IS seamless.");
return true;
// ROTATION_ANIMATION_SEAMLESS can only be requested by task.
if (hasTask) {
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " Rotation IS seamless.");
return true;
}
return false;
}
/**
@@ -280,7 +286,6 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler {
final TransitionInfo.Change change = info.getChanges().get(i);
if (info.getType() == TRANSIT_CHANGE && change.getMode() == TRANSIT_CHANGE
&& (change.getEndRotation() != change.getStartRotation())
&& (change.getFlags() & FLAG_IS_DISPLAY) != 0) {
boolean isSeamless = isRotationSeamless(info, mDisplayController);
final int anim = getRotationAnimation(info);

View File

@@ -186,11 +186,11 @@ class ScreenRotationAnimation {
t.setAlpha(mBackColorSurface, 1);
t.show(mBackColorSurface);
t.setLayer(mAnimLeash, SCREEN_FREEZE_LAYER_BASE);
t.setPosition(mAnimLeash, 0, 0);
t.setAlpha(mAnimLeash, 1);
t.show(mAnimLeash);
t.setLayer(mScreenshotLayer, SCREEN_FREEZE_LAYER_BASE);
t.setBuffer(mScreenshotLayer, buffer);
t.setColorSpace(mScreenshotLayer, screenshotBuffer.getColorSpace());
t.show(mScreenshotLayer);

View File

@@ -583,6 +583,13 @@ public class ShellTransitionTests {
.setRotate(ROTATION_ANIMATION_SEAMLESS).build())
.build();
assertFalse(DefaultTransitionHandler.isRotationSeamless(seamlessButAlert, displays));
// Not seamless if there is no changed task.
final TransitionInfo noTask = new TransitionInfoBuilder(TRANSIT_CHANGE)
.addChange(new ChangeBuilder(TRANSIT_CHANGE).setFlags(FLAG_IS_DISPLAY)
.setRotate().build())
.build();
assertFalse(DefaultTransitionHandler.isRotationSeamless(noTask, displays));
}
class TransitionInfoBuilder {

View File

@@ -5943,6 +5943,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
}
void startFreezingScreen(int overrideOriginalDisplayRotation) {
if (mAtmService.getTransitionController().isShellTransitionsEnabled()) {
return;
}
ProtoLog.i(WM_DEBUG_ORIENTATION,
"Set freezing of %s: visible=%b freezing=%b visibleRequested=%b. %s",
appToken, isVisible(), mFreezingScreen, mVisibleRequested,
@@ -8443,9 +8446,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
if (shouldRelaunchLocked(changes, mTmpConfig) || forceNewConfig) {
// Aha, the activity isn't handling the change, so DIE DIE DIE.
configChangeFlags |= changes;
if (!mAtmService.getTransitionController().isShellTransitionsEnabled()) {
startFreezingScreenLocked(globalChanges);
}
startFreezingScreenLocked(globalChanges);
forceNewConfig = false;
// Do not preserve window if it is freezing screen because the original window won't be
// able to update drawn state that causes freeze timeout.

View File

@@ -76,6 +76,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG;
import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
import static android.view.WindowManager.TRANSIT_CHANGE;
import static android.view.WindowManager.TRANSIT_OPEN;
import static android.view.WindowManager.TRANSIT_TO_FRONT;
import static android.window.DisplayAreaOrganizer.FEATURE_ROOT;
@@ -1389,11 +1390,16 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
final Configuration currentDisplayConfig = getConfiguration();
mTmpConfiguration.setTo(currentDisplayConfig);
computeScreenConfiguration(mTmpConfiguration);
configChanged |= currentDisplayConfig.diff(mTmpConfiguration) != 0;
final int changes = currentDisplayConfig.diff(mTmpConfiguration);
configChanged |= changes != 0;
if (configChanged) {
mWaitingForConfig = true;
mWmService.startFreezingDisplay(0 /* exitAnim */, 0 /* enterAnim */, this);
if (mAtmService.getTransitionController().isShellTransitionsEnabled()) {
requestChangeTransitionIfNeeded(changes);
} else {
mWmService.startFreezingDisplay(0 /* exitAnim */, 0 /* enterAnim */, this);
}
sendNewConfiguration();
}
@@ -3165,6 +3171,24 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
return mScreenRotationAnimation;
}
/**
* Requests to start a transition for the display configuration change. The given changes must
* be non-zero. This method is no-op if the display has been collected.
*/
void requestChangeTransitionIfNeeded(@ActivityInfo.Config int changes) {
final TransitionController controller = mAtmService.getTransitionController();
if (controller.isCollecting()) {
if (!controller.isCollecting(this)) {
controller.collect(this);
}
return;
}
final Transition t = controller.requestTransitionIfNeeded(TRANSIT_CHANGE, this);
if (t != null) {
t.setKnownConfigChanges(this, changes);
}
}
/** If the display is in transition, there should be a screenshot covering it. */
@Override
boolean inTransition() {
@@ -5724,6 +5748,9 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
}
mWmService.mDisplayNotificationController.dispatchDisplayChanged(
this, getConfiguration());
if (isReady() && mAtmService.getTransitionController().isShellTransitionsEnabled()) {
requestChangeTransitionIfNeeded(changes);
}
}
return changes;
}

View File

@@ -22,7 +22,6 @@ import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_CROSSFA
import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_JUMPCUT;
import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_ROTATE;
import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS;
import static android.view.WindowManager.TRANSIT_CHANGE;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION;
import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.LID_OPEN;
@@ -492,12 +491,6 @@ public class DisplayRotation {
recentsAnimationController.cancelAnimationForDisplayChange();
}
final Transition t = (useShellTransitions
&& !mService.mAtmService.getTransitionController().isCollecting())
? mService.mAtmService.getTransitionController().createTransition(TRANSIT_CHANGE)
: null;
mService.mAtmService.getTransitionController().collect(mDisplayContent);
ProtoLog.v(WM_DEBUG_ORIENTATION,
"Display id=%d rotation changed to %d from %d, lastOrientation=%d",
displayId, rotation, oldRotation, lastOrientation);
@@ -511,11 +504,10 @@ public class DisplayRotation {
mDisplayContent.setLayoutNeeded();
if (useShellTransitions) {
if (t != null) {
// This created its own transition, so send a start request.
mService.mAtmService.getTransitionController().requestStartTransition(
t, null /* trigger */, null /* remote */);
} else {
final boolean wasInTransition = mDisplayContent.inTransition();
mDisplayContent.requestChangeTransitionIfNeeded(
ActivityInfo.CONFIG_WINDOW_CONFIGURATION);
if (wasInTransition) {
// Use remote-rotation infra since the transition has already been requested
// TODO(shell-transitions): Remove this once lifecycle management can cover all
// rotation cases.

View File

@@ -58,6 +58,7 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.content.pm.ActivityInfo;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.Binder;
@@ -269,6 +270,18 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
mChanges.get(wc).mExistenceChanged = true;
}
/**
* Specifies configuration change explicitly for the window container, so it can be chosen as
* transition target. This is usually used with transition mode
* {@link android.view.WindowManager#TRANSIT_CHANGE}.
*/
void setKnownConfigChanges(WindowContainer<?> wc, @ActivityInfo.Config int changes) {
final ChangeInfo changeInfo = mChanges.get(wc);
if (changeInfo != null) {
changeInfo.mKnownConfigChanges = changes;
}
}
private void sendRemoteCallback(@Nullable IRemoteCallback callback) {
if (callback == null) return;
mController.mAtm.mH.sendMessage(PooledLambda.obtainMessage(cb -> {
@@ -1218,6 +1231,7 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
final Rect mAbsoluteBounds = new Rect();
boolean mShowWallpaper;
int mRotation = ROTATION_UNDEFINED;
@ActivityInfo.Config int mKnownConfigChanges;
ChangeInfo(@NonNull WindowContainer origState) {
mVisible = origState.isVisibleRequested();
@@ -1240,6 +1254,7 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
final boolean currVisible = newState.isVisibleRequested();
if (currVisible == mVisible && !mVisible) return false;
return currVisible != mVisible
|| mKnownConfigChanges != 0
// if mWindowingMode is 0, this container wasn't attached at collect time, so
// assume no change in windowing-mode.
|| (mWindowingMode != 0 && newState.getWindowingMode() != mWindowingMode)

View File

@@ -71,15 +71,7 @@ class TransitionController {
final Lock mRunningLock = new Lock();
private final IBinder.DeathRecipient mTransitionPlayerDeath = () -> {
// clean-up/finish any playing transitions.
for (int i = 0; i < mPlayingTransitions.size(); ++i) {
mPlayingTransitions.get(i).cleanUpOnFailure();
}
mPlayingTransitions.clear();
mTransitionPlayer = null;
mRunningLock.doNotifyLocked();
};
private final IBinder.DeathRecipient mTransitionPlayerDeath;
/** The transition currently being constructed (collecting participants). */
private Transition mCollectingTransition = null;
@@ -90,6 +82,17 @@ class TransitionController {
TransitionController(ActivityTaskManagerService atm) {
mAtm = atm;
mStatusBar = LocalServices.getService(StatusBarManagerInternal.class);
mTransitionPlayerDeath = () -> {
synchronized (mAtm.mGlobalLock) {
// Clean-up/finish any playing transitions.
for (int i = 0; i < mPlayingTransitions.size(); ++i) {
mPlayingTransitions.get(i).cleanUpOnFailure();
}
mPlayingTransitions.clear();
mTransitionPlayer = null;
mRunningLock.doNotifyLocked();
}
};
}
/** @see #createTransition(int, int) */

View File

@@ -327,7 +327,7 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
if (transition != null) {
// First check if we have a display rotation transition and if so, update it.
final DisplayContent dc = DisplayRotation.getDisplayFromTransition(transition);
if (dc != null && transition.mChanges.get(dc).mRotation != dc.getRotation()) {
if (dc != null && transition.mChanges.get(dc).hasChanged(dc)) {
// Go through all tasks and collect them before the rotation
// TODO(shell-transitions): move collect() to onConfigurationChange once
// wallpaper handling is synchronized.