Merge "Prevent timeout of async rotation by invisible windows" into udc-dev

This commit is contained in:
Riddle Hsu
2023-02-22 09:41:54 +00:00
committed by Android (Google) Code Review
5 changed files with 53 additions and 42 deletions

View File

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

View File

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

View File

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

View File

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

View File

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