Prevent timeout of async rotation by invisible windows
This avoids a delay to re-show the bars when an async window is removed during rotation (e.g. volume panel) since shell transition disables the usages of setOrientationChanging. This is also a step to be able to completely remove get/setOrientationChanging in the future. Also simplify prepareSurfaceLocked: - showRobustly always returns true, so the corresponding "else" can be removed. - isParentWindowHidden is already checked in isOnScreen. Bug: 270123439 Test: TransitionTests#testDisplayRotationChange Change-Id: I53bae0d937d63e4b600aed3a005a3f8c7d5b68b5
This commit is contained in:
@@ -217,6 +217,34 @@ class AsyncRotationController extends FadeAnimationController implements Consume
|
||||
if (DEBUG) Slog.d(TAG, "Requested to sync draw transaction");
|
||||
}
|
||||
|
||||
/**
|
||||
* If an async window is not requested to redraw or its surface is removed, then complete its
|
||||
* operation directly to avoid waiting until timeout.
|
||||
*/
|
||||
void updateTargetWindows() {
|
||||
if (mTransitionOp == OP_LEGACY || !mIsStartTransactionCommitted) return;
|
||||
for (int i = mTargetWindowTokens.size() - 1; i >= 0; i--) {
|
||||
final Operation op = mTargetWindowTokens.valueAt(i);
|
||||
if (op.mIsCompletionPending || op.mAction == Operation.ACTION_SEAMLESS) {
|
||||
// Skip completed target. And seamless windows use the signal from blast sync.
|
||||
continue;
|
||||
}
|
||||
final WindowToken token = mTargetWindowTokens.keyAt(i);
|
||||
int readyCount = 0;
|
||||
final int childCount = token.getChildCount();
|
||||
for (int j = childCount - 1; j >= 0; j--) {
|
||||
final WindowState w = token.getChildAt(j);
|
||||
// If the token no longer contains pending drawn windows, then it is ready.
|
||||
if (w.isDrawn() || !w.mWinAnimator.getShown()) {
|
||||
readyCount++;
|
||||
}
|
||||
}
|
||||
if (readyCount == childCount) {
|
||||
mDisplayContent.finishAsyncRotation(token);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Lets the window fit in new rotation naturally. */
|
||||
private void finishOp(WindowToken windowToken) {
|
||||
final Operation op = mTargetWindowTokens.remove(windowToken);
|
||||
|
||||
@@ -4761,6 +4761,9 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
|
||||
|
||||
void updateWindowsForAnimator() {
|
||||
forAllWindows(mUpdateWindowsForAnimator, true /* traverseTopToBottom */);
|
||||
if (mAsyncRotationController != null) {
|
||||
mAsyncRotationController.updateTargetWindows();
|
||||
}
|
||||
}
|
||||
|
||||
boolean isInputMethodClientFocus(int uid, int pid) {
|
||||
|
||||
@@ -32,7 +32,6 @@ import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
|
||||
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
|
||||
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
|
||||
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_WINDOW_ANIMATION;
|
||||
import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
|
||||
import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
|
||||
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG;
|
||||
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
|
||||
@@ -424,7 +423,7 @@ class WindowStateAnimator {
|
||||
|
||||
computeShownFrameLocked();
|
||||
|
||||
if (w.isParentWindowHidden() || !w.isOnScreen()) {
|
||||
if (!w.isOnScreen()) {
|
||||
hide(t, "prepareSurfaceLocked");
|
||||
mWallpaperControllerLocked.hideWallpapers(w);
|
||||
|
||||
@@ -449,30 +448,23 @@ class WindowStateAnimator {
|
||||
|
||||
if (prepared && mDrawState == HAS_DRAWN) {
|
||||
if (mLastHidden) {
|
||||
if (showSurfaceRobustlyLocked(t)) {
|
||||
mAnimator.requestRemovalOfReplacedWindows(w);
|
||||
mLastHidden = false;
|
||||
final DisplayContent displayContent = w.getDisplayContent();
|
||||
if (!displayContent.getLastHasContent()) {
|
||||
// This draw means the difference between unique content and mirroring.
|
||||
// Run another pass through performLayout to set mHasContent in the
|
||||
// LogicalDisplay.
|
||||
displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_ANIM;
|
||||
if (DEBUG_LAYOUT_REPEATS) {
|
||||
mService.mWindowPlacerLocked.debugLayoutRepeats(
|
||||
"showSurfaceRobustlyLocked " + w,
|
||||
displayContent.pendingLayoutChanges);
|
||||
}
|
||||
mSurfaceController.showRobustly(t);
|
||||
mAnimator.requestRemovalOfReplacedWindows(w);
|
||||
mLastHidden = false;
|
||||
final DisplayContent displayContent = w.getDisplayContent();
|
||||
if (!displayContent.getLastHasContent()) {
|
||||
// This draw means the difference between unique content and mirroring.
|
||||
// Run another pass through performLayout to set mHasContent in the
|
||||
// LogicalDisplay.
|
||||
displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_ANIM;
|
||||
if (DEBUG_LAYOUT_REPEATS) {
|
||||
mService.mWindowPlacerLocked.debugLayoutRepeats(
|
||||
"showSurfaceRobustlyLocked " + w,
|
||||
displayContent.pendingLayoutChanges);
|
||||
}
|
||||
} else {
|
||||
w.setOrientationChanging(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (mWin.isAnimating(TRANSITION | PARENTS)) {
|
||||
ProtoLog.v(WM_DEBUG_ANIM, "prepareSurface: No changes in animation for %s", this);
|
||||
}
|
||||
}
|
||||
|
||||
if (w.getOrientationChanging()) {
|
||||
@@ -511,22 +503,6 @@ class WindowStateAnimator {
|
||||
mSurfaceController.setColorSpaceAgnostic(mWin.getPendingTransaction(), agnostic);
|
||||
}
|
||||
|
||||
/**
|
||||
* Have the surface flinger show a surface, robustly dealing with
|
||||
* error conditions. In particular, if there is not enough memory
|
||||
* to show the surface, then we will try to get rid of other surfaces
|
||||
* in order to succeed.
|
||||
*
|
||||
* @return Returns true if the surface was successfully shown.
|
||||
*/
|
||||
private boolean showSurfaceRobustlyLocked(SurfaceControl.Transaction t) {
|
||||
boolean shown = mSurfaceController.showRobustly(t);
|
||||
if (!shown)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void applyEnterAnimationLocked() {
|
||||
// If we are the new part of a window replacement transition and we have requested
|
||||
// not to animate, we instead want to make it seamless, so we don't want to apply
|
||||
|
||||
@@ -245,13 +245,13 @@ class WindowSurfaceController {
|
||||
t.setColorSpaceAgnostic(mSurfaceControl, agnostic);
|
||||
}
|
||||
|
||||
boolean showRobustly(SurfaceControl.Transaction t) {
|
||||
void showRobustly(SurfaceControl.Transaction t) {
|
||||
ProtoLog.i(WM_SHOW_TRANSACTIONS, "SURFACE SHOW (performLayout): %s", title);
|
||||
if (DEBUG_VISIBILITY) Slog.v(TAG, "Showing " + this
|
||||
+ " during relayout");
|
||||
|
||||
if (mSurfaceShown) {
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
setShown(true);
|
||||
@@ -262,7 +262,6 @@ class WindowSurfaceController {
|
||||
dc.mDisplayId, 1 /* request shown */,
|
||||
String.valueOf(dc.mWallpaperController.getWallpaperTarget()));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean clearWindowContentFrameStats() {
|
||||
|
||||
@@ -1018,6 +1018,10 @@ public class TransitionTests extends WindowTestsBase {
|
||||
|
||||
@Test
|
||||
public void testDisplayRotationChange() {
|
||||
final DisplayPolicy displayPolicy = mDisplayContent.getDisplayPolicy();
|
||||
spyOn(displayPolicy);
|
||||
// Simulate gesture navigation (non-movable) so it is not seamless.
|
||||
doReturn(false).when(displayPolicy).navigationBarCanMove();
|
||||
final Task task = createActivityRecord(mDisplayContent).getTask();
|
||||
final WindowState statusBar = createWindow(null, TYPE_STATUS_BAR, "statusBar");
|
||||
final WindowState navBar = createWindow(null, TYPE_NAVIGATION_BAR, "navBar");
|
||||
@@ -1072,7 +1076,8 @@ public class TransitionTests extends WindowTestsBase {
|
||||
|
||||
// Navigation bar finishes drawing after the start transaction, so its fade-in animation
|
||||
// can execute directly.
|
||||
asyncRotationController.handleFinishDrawing(navBar, mMockT);
|
||||
navBar.mWinAnimator.mDrawState = WindowStateAnimator.HAS_DRAWN;
|
||||
asyncRotationController.updateTargetWindows();
|
||||
assertFalse(asyncRotationController.isTargetToken(navBar.mToken));
|
||||
assertNull(mDisplayContent.getAsyncRotationController());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user