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 (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. */ /** Lets the window fit in new rotation naturally. */
private void finishOp(WindowToken windowToken) { private void finishOp(WindowToken windowToken) {
final Operation op = mTargetWindowTokens.remove(windowToken); final Operation op = mTargetWindowTokens.remove(windowToken);

View File

@@ -4761,6 +4761,9 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
void updateWindowsForAnimator() { void updateWindowsForAnimator() {
forAllWindows(mUpdateWindowsForAnimator, true /* traverseTopToBottom */); forAllWindows(mUpdateWindowsForAnimator, true /* traverseTopToBottom */);
if (mAsyncRotationController != null) {
mAsyncRotationController.updateTargetWindows();
}
} }
boolean isInputMethodClientFocus(int uid, int pid) { 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_ANIM;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 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.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.WindowContainer.AnimationFlags.TRANSITION;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
@@ -424,7 +423,7 @@ class WindowStateAnimator {
computeShownFrameLocked(); computeShownFrameLocked();
if (w.isParentWindowHidden() || !w.isOnScreen()) { if (!w.isOnScreen()) {
hide(t, "prepareSurfaceLocked"); hide(t, "prepareSurfaceLocked");
mWallpaperControllerLocked.hideWallpapers(w); mWallpaperControllerLocked.hideWallpapers(w);
@@ -449,30 +448,23 @@ class WindowStateAnimator {
if (prepared && mDrawState == HAS_DRAWN) { if (prepared && mDrawState == HAS_DRAWN) {
if (mLastHidden) { if (mLastHidden) {
if (showSurfaceRobustlyLocked(t)) { mSurfaceController.showRobustly(t);
mAnimator.requestRemovalOfReplacedWindows(w); mAnimator.requestRemovalOfReplacedWindows(w);
mLastHidden = false; mLastHidden = false;
final DisplayContent displayContent = w.getDisplayContent(); final DisplayContent displayContent = w.getDisplayContent();
if (!displayContent.getLastHasContent()) { if (!displayContent.getLastHasContent()) {
// This draw means the difference between unique content and mirroring. // This draw means the difference between unique content and mirroring.
// Run another pass through performLayout to set mHasContent in the // Run another pass through performLayout to set mHasContent in the
// LogicalDisplay. // LogicalDisplay.
displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_ANIM; displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_ANIM;
if (DEBUG_LAYOUT_REPEATS) { if (DEBUG_LAYOUT_REPEATS) {
mService.mWindowPlacerLocked.debugLayoutRepeats( mService.mWindowPlacerLocked.debugLayoutRepeats(
"showSurfaceRobustlyLocked " + w, "showSurfaceRobustlyLocked " + w,
displayContent.pendingLayoutChanges); 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()) { if (w.getOrientationChanging()) {
@@ -511,22 +503,6 @@ class WindowStateAnimator {
mSurfaceController.setColorSpaceAgnostic(mWin.getPendingTransaction(), agnostic); 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() { void applyEnterAnimationLocked() {
// If we are the new part of a window replacement transition and we have requested // 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 // 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); t.setColorSpaceAgnostic(mSurfaceControl, agnostic);
} }
boolean showRobustly(SurfaceControl.Transaction t) { void showRobustly(SurfaceControl.Transaction t) {
ProtoLog.i(WM_SHOW_TRANSACTIONS, "SURFACE SHOW (performLayout): %s", title); ProtoLog.i(WM_SHOW_TRANSACTIONS, "SURFACE SHOW (performLayout): %s", title);
if (DEBUG_VISIBILITY) Slog.v(TAG, "Showing " + this if (DEBUG_VISIBILITY) Slog.v(TAG, "Showing " + this
+ " during relayout"); + " during relayout");
if (mSurfaceShown) { if (mSurfaceShown) {
return true; return;
} }
setShown(true); setShown(true);
@@ -262,7 +262,6 @@ class WindowSurfaceController {
dc.mDisplayId, 1 /* request shown */, dc.mDisplayId, 1 /* request shown */,
String.valueOf(dc.mWallpaperController.getWallpaperTarget())); String.valueOf(dc.mWallpaperController.getWallpaperTarget()));
} }
return true;
} }
boolean clearWindowContentFrameStats() { boolean clearWindowContentFrameStats() {

View File

@@ -1018,6 +1018,10 @@ public class TransitionTests extends WindowTestsBase {
@Test @Test
public void testDisplayRotationChange() { 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 Task task = createActivityRecord(mDisplayContent).getTask();
final WindowState statusBar = createWindow(null, TYPE_STATUS_BAR, "statusBar"); final WindowState statusBar = createWindow(null, TYPE_STATUS_BAR, "statusBar");
final WindowState navBar = createWindow(null, TYPE_NAVIGATION_BAR, "navBar"); 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 // Navigation bar finishes drawing after the start transaction, so its fade-in animation
// can execute directly. // can execute directly.
asyncRotationController.handleFinishDrawing(navBar, mMockT); navBar.mWinAnimator.mDrawState = WindowStateAnimator.HAS_DRAWN;
asyncRotationController.updateTargetWindows();
assertFalse(asyncRotationController.isTargetToken(navBar.mToken)); assertFalse(asyncRotationController.isTargetToken(navBar.mToken));
assertNull(mDisplayContent.getAsyncRotationController()); assertNull(mDisplayContent.getAsyncRotationController());
} }