diff options
| author | 2020-03-31 21:41:18 +0800 | |
|---|---|---|
| committer | 2020-04-03 14:59:12 +0000 | |
| commit | 839b5f55f9d985b1abfac608df7928d713b51ce5 (patch) | |
| tree | 0eac1da87cd290b542c472f8dd9e01dc6de294b1 | |
| parent | 07217a0dacee26bee0e8933d81dfee877999ced0 (diff) | |
Do not remove window if IWindow#resized is failed
Even DeadObjectException is thrown, it is not equivalent to the
window is died (transaction failed by small size data will be
DeadObjectException). Sometimes it may be caused by the binder
buffer of process is temporarily full. If the window is removed
directly but the process is still alive, the application client
and window manager are out of sync. Especially if the window is
important system window, e.g. status bar, notification shade,
navigation bar, which might need to reboot to recover. Ideally,
if the process is really dead, there should be a binderDied
callback that also removes the window.
The original purpose of the removal is to avoid display frozen
(e.g. rotation) always timeout which is caused by resetting
WindowState#mOrientationChanging in each layout traversal. Now
the window states are still updated as "resized" has reported,
so it won't block unfreeze display.
Bug: 151814107
Bug: 147448299
Test: atest WindowStateTests#testReportResizedWithRemoteException
Test: Hard code to throw RemoteException for a specified window
and rotate the display.
Change-Id: Id295456cc99ab9af30aa5fad2eedada6afb862a2
4 files changed, 58 insertions, 31 deletions
diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json index a871047a0602..852af47dacea 100644 --- a/data/etc/services.core.protolog.json +++ b/data/etc/services.core.protolog.json @@ -25,6 +25,12 @@ "group": "WM_DEBUG_REMOTE_ANIMATIONS", "at": "com\/android\/server\/wm\/RemoteAnimationController.java" }, + "-2101985723": { + "message": "Failed looking up window session=%s callers=%s", + "level": "WARN", + "group": "WM_ERROR", + "at": "com\/android\/server\/wm\/WindowManagerService.java" + }, "-2072089308": { "message": "Attempted to add window with token that is a sub-window: %s. Aborting.", "level": "WARN", @@ -301,12 +307,6 @@ "group": "WM_DEBUG_ADD_REMOVE", "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-1455600136": { - "message": "Attempted to add Dream window with unknown token %s. Aborting.", - "level": "WARN", - "group": "WM_ERROR", - "at": "com\/android\/server\/wm\/WindowManagerService.java" - }, "-1443029505": { "message": "SAFE MODE ENABLED (menu=%d s=%d dpad=%d trackball=%d)", "level": "INFO", @@ -385,12 +385,6 @@ "group": "WM_DEBUG_RESIZE", "at": "com\/android\/server\/wm\/WindowState.java" }, - "-1263554915": { - "message": "Attempted to add Dream window with bad token %s. Aborting.", - "level": "WARN", - "group": "WM_ERROR", - "at": "com\/android\/server\/wm\/WindowManagerService.java" - }, "-1263316010": { "message": "Computed rotation=%s (%d) for display id=%d based on lastOrientation=%s (%d) and oldRotation=%s (%d)", "level": "VERBOSE", @@ -673,12 +667,6 @@ "group": "WM_DEBUG_SCREEN_ON", "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "-747671114": { - "message": "Failed looking up window callers=%s", - "level": "WARN", - "group": "WM_ERROR", - "at": "com\/android\/server\/wm\/WindowManagerService.java" - }, "-714291355": { "message": "Losing delayed focus: %s", "level": "INFO", diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index b1f22f8623d6..56bb19f6e26c 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -5321,7 +5321,8 @@ public class WindowManagerService extends IWindowManager.Stub throw new IllegalArgumentException( "Requested window " + client + " does not exist"); } - ProtoLog.w(WM_ERROR, "Failed looking up window callers=%s", Debug.getCallers(3)); + ProtoLog.w(WM_ERROR, "Failed looking up window session=%s callers=%s", session, + Debug.getCallers(3)); return null; } if (session != null && win.mSession != session) { @@ -5329,7 +5330,8 @@ public class WindowManagerService extends IWindowManager.Stub throw new IllegalArgumentException("Requested window " + client + " is in session " + win.mSession + ", not " + session); } - ProtoLog.w(WM_ERROR, "Failed looking up window callers=%s", Debug.getCallers(3)); + ProtoLog.w(WM_ERROR, "Failed looking up window session=%s callers=%s", session, + Debug.getCallers(3)); return null; } diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 016277c0c37d..c3a740791caf 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -3440,13 +3440,23 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP getMergedConfiguration(mLastReportedConfiguration); mLastConfigReportedToClient = true; + final boolean reportOrientation = mReportOrientationChanged; + // Always reset these states first, so if {@link IWindow#resized} fails, this + // window won't be added to {@link WindowManagerService#mResizingWindows} and set + // {@link #mOrientationChanging} to true again by {@link #updateResizingWindowIfNeeded} + // that may cause WINDOW_FREEZE_TIMEOUT because resizing the client keeps failing. + mReportOrientationChanged = false; + mDragResizingChangeReported = true; + mWinAnimator.mSurfaceResized = false; + mWindowFrames.resetInsetsChanged(); + final Rect frame = mWindowFrames.mCompatFrame; final Rect contentInsets = mWindowFrames.mLastContentInsets; final Rect visibleInsets = mWindowFrames.mLastVisibleInsets; final Rect stableInsets = mWindowFrames.mLastStableInsets; final MergedConfiguration mergedConfiguration = mLastReportedConfiguration; final boolean reportDraw = mWinAnimator.mDrawState == DRAW_PENDING; - final boolean forceRelayout = mReportOrientationChanged || isDragResizeChanged(); + final boolean forceRelayout = reportOrientation || isDragResizeChanged(); final int displayId = getDisplayId(); final DisplayCutout displayCutout = getWmDisplayCutout().getDisplayCutout(); @@ -3455,25 +3465,17 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP mergedConfiguration, getBackdropFrame(frame), forceRelayout, getDisplayContent().getDisplayPolicy().areSystemBarsForcedShownLw(this), displayId, new DisplayCutout.ParcelableWrapper(displayCutout)); - mDragResizingChangeReported = true; if (mWmService.mAccessibilityController != null) { mWmService.mAccessibilityController.onSomeWindowResizedOrMovedLocked(displayId); } updateLocationInParentDisplayIfNeeded(); - - mWindowFrames.resetInsetsChanged(); - mWinAnimator.mSurfaceResized = false; - mReportOrientationChanged = false; } catch (RemoteException e) { + // Cancel orientation change of this window to avoid blocking unfreeze display. setOrientationChanging(false); mLastFreezeDuration = (int)(SystemClock.elapsedRealtime() - mWmService.mDisplayFreezeTime); - // We are assuming the hosting process is dead or in a zombie state. - Slog.w(TAG, "Failed to report 'resized' to the client of " + this - + ", removing this window."); - mWmService.mPendingRemove.add(this); - mWmService.mWindowPlacerLocked.requestTraversal(); + Slog.w(TAG, "Failed to report 'resized' to " + this + " due to " + e); } Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); } diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java index e95ccab38960..aac10052b894 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java @@ -40,6 +40,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.doThrow; import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock; import static com.android.dx.mockito.inline.extended.ExtendedMockito.never; import static com.android.dx.mockito.inline.extended.ExtendedMockito.reset; @@ -47,6 +48,8 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy; import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; +import static com.google.common.truth.Truth.assertThat; + import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.not; import static org.junit.Assert.assertEquals; @@ -55,6 +58,7 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.anyString; @@ -65,6 +69,7 @@ import android.graphics.Insets; import android.graphics.Matrix; import android.graphics.PixelFormat; import android.graphics.Rect; +import android.os.RemoteException; import android.platform.test.annotations.Presubmit; import android.util.Size; import android.view.DisplayCutout; @@ -570,6 +575,36 @@ public class WindowStateTests extends WindowTestsBase { } @Test + public void testReportResizedWithRemoteException() { + final WindowState win = mChildAppWindowAbove; + makeWindowVisible(win, win.getParentWindow()); + win.mLayoutSeq = win.getDisplayContent().mLayoutSeq; + win.updateResizingWindowIfNeeded(); + + assertThat(mWm.mResizingWindows).contains(win); + assertTrue(win.getOrientationChanging()); + + mWm.mResizingWindows.remove(win); + spyOn(win.mClient); + try { + doThrow(new RemoteException("test")).when(win.mClient).resized(any() /* frame */, + any() /* contentInsets */, any() /* visibleInsets */, any() /* stableInsets */, + anyBoolean() /* reportDraw */, any() /* mergedConfig */, + any() /* backDropFrame */, anyBoolean() /* forceLayout */, + anyBoolean() /* alwaysConsumeSystemBars */, anyInt() /* displayId */, + any() /* displayCutout */); + } catch (RemoteException ignored) { + } + win.reportResized(); + win.updateResizingWindowIfNeeded(); + + // Even "resized" throws remote exception, it is still considered as reported. So the window + // shouldn't be resized again (which may block unfreeze in real case). + assertThat(mWm.mResizingWindows).doesNotContain(win); + assertFalse(win.getOrientationChanging()); + } + + @Test public void testGetTransformationMatrix() { final int PARENT_WINDOW_OFFSET = 1; final int DISPLAY_IN_PARENT_WINDOW_OFFSET = 2; |