Loading apct-tests/perftests/inputmethod/src/android/inputmethod/ImePerfTest.java +1 −0 Original line number Diff line number Diff line Loading @@ -92,6 +92,7 @@ public class ImePerfTest extends ImePerfTestBase "IMMS.applyImeVisibility", "applyPostLayoutPolicy", "applyWindowSurfaceChanges", "ISC.onPreLayout", "ISC.onPostLayout" }; Loading core/java/android/view/inputmethod/flags.aconfig +6 −0 Original line number Diff line number Diff line Loading @@ -219,3 +219,9 @@ flag { bug: "139872425" } flag { name: "set_server_visibility_onprelayout" namespace: "input_method" description: "Set server visibility before performLayout to avoid additional window layout traversal." bug: "427863960" } services/core/java/com/android/server/wm/DisplayContent.java +4 −0 Original line number Diff line number Diff line Loading @@ -5072,6 +5072,10 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp setLayoutNeeded(); } if (android.view.inputmethod.Flags.setServerVisibilityOnprelayout()) { mInsetsStateController.onPreLayout(); } // Perform a layout, if needed. performLayout(true /* initial */, false /* updateInputWindows */); pendingLayoutChanges = 0; Loading services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java +46 −13 Original line number Diff line number Diff line Loading @@ -71,6 +71,12 @@ final class ImeInsetsSourceProvider extends InsetsSourceProvider { */ private boolean mServerVisible; /** * The server visibility of the source provider's window before the latest * {@link #onPreLayout} call. */ private boolean mServerVisiblePreLayout; /** * When the IME is not ready, it has givenInsetsPending. However, this could happen again, * after it became serverVisible. This flag indicates is used to determine if it is Loading @@ -92,18 +98,31 @@ final class ImeInsetsSourceProvider extends InsetsSourceProvider { } @Override void onPostLayout() { void onPreLayout() { if (!android.view.inputmethod.Flags.setServerVisibilityOnprelayout()) { return; } mServerVisiblePreLayout = mServerVisible; super.onPreLayout(); mLastDrawn = mWin != null && mWin.isDrawn(); } @Override boolean onPostLayout() { final boolean wasSourceVisible = mSource.isVisible(); super.onPostLayout(); if (wasSourceVisible != mSource.isVisible()) { final boolean controlDispatched = super.onPostLayout(); if (!android.view.inputmethod.Flags.setServerVisibilityOnprelayout() && wasSourceVisible != mSource.isVisible()) { // TODO(b/427863960): Remove this and set the server visibility in onPreLayout // If the IME visibility has changed, a traversal needs to apply. mDisplayContent.setLayoutNeeded(); } final boolean givenInsetsPending = mWin != null && mWin.mGivenInsetsPending; if (!android.view.inputmethod.Flags.setServerVisibilityOnprelayout()) { mLastDrawn = mWin != null && mWin.isDrawn(); } // isLeashReadyForDispatching (used to dispatch the leash of the control) is // depending on mGivenInsetsReady. Therefore, triggering notifyControlChanged here // again, so that the control with leash can be eventually dispatched Loading @@ -115,10 +134,14 @@ final class ImeInsetsSourceProvider extends InsetsSourceProvider { mGivenInsetsReady = true; ImeTracker.forLogging().onProgress(mStatsToken, ImeTracker.PHASE_WM_POST_LAYOUT_NOTIFY_CONTROLS_CHANGED); if (!controlDispatched) { mStateController.notifyControlChanged(mControlTarget, this); } setImeShowing(true); } else if (wasSourceVisible && isServerVisible() && mGivenInsetsReady && givenInsetsPending) { return true; } else if (((!android.view.inputmethod.Flags.setServerVisibilityOnprelayout() && wasSourceVisible) || mServerVisiblePreLayout) && isServerVisible() && mGivenInsetsReady && givenInsetsPending) { // If the server visibility didn't change (still visible), and mGivenInsetsReady // is set, we won't call into notifyControlChanged. Therefore, we can reset the // statsToken, if available. Loading @@ -127,12 +150,22 @@ final class ImeInsetsSourceProvider extends InsetsSourceProvider { ImeTracker.forLogging().onCancelled(mStatsToken, ImeTracker.PHASE_WM_POST_LAYOUT_NOTIFY_CONTROLS_CHANGED); mStatsToken = null; } else if (isImeShowing() && !isServerVisible()) { } else if (!isServerVisible()) { if (isImeShowing()) { ProtoLog.d(WM_DEBUG_IME, "onPostLayout: setImeShowing(false) was: true, controlTarget=%s", mControlTarget); setImeShowing(false); } if (android.view.inputmethod.Flags.setServerVisibilityOnprelayout() && mControlTarget != null && mServerVisiblePreLayout && !controlDispatched) { // If the server visibility changed (not visible anymore), we need to dispatch // the control. mStateController.notifyControlChanged(mControlTarget, this); return true; } } return controlDispatched; } @Nullable Loading services/core/java/com/android/server/wm/InsetsSourceProvider.java +34 −9 Original line number Diff line number Diff line Loading @@ -362,28 +362,53 @@ class InsetsSourceProvider { } /** * Called when a layout pass has occurred. * Called before a layout pass will occur. */ void onPostLayout() { void onPreLayout() { if (!android.view.inputmethod.Flags.setServerVisibilityOnprelayout()) { return; } if (mWin == null) { return; } setServerVisible(isSurfaceVisible()); } /** * Called after a layout pass has occurred. * * @return {@code true} if {@link InsetsStateController#notifyControlChanged} was called or * was scheduled to be called within this method, else {@code false}. */ boolean onPostLayout() { if (mWin == null) { return false; } final boolean serverVisibleChanged; if (!android.view.inputmethod.Flags.setServerVisibilityOnprelayout()) { final boolean isServerVisible = isSurfaceVisible(); final boolean serverVisibleChanged = mServerVisible != isServerVisible; serverVisibleChanged = mServerVisible != isServerVisible; setServerVisible(isServerVisible); } else { serverVisibleChanged = false; } if (mControl != null && mControlTarget != null) { final boolean positionChanged = updateInsetsControlPosition(mWin); if (!(positionChanged || mHasPendingPosition) if (positionChanged || mHasPendingPosition) { return true; } // The insets hint would be updated while changing the position. Here updates it // for the possible change of the bounds or the server visibility. && (updateInsetsHint(mControl) || serverVisibleChanged)) { // for the possible change of the bounds. if (updateInsetsHint(mControl) || serverVisibleChanged) { // Only call notifyControlChanged here when the position hasn't been or won't be // changed. Otherwise, it has been called or scheduled to be called during // updateInsetsControlPosition. mStateController.notifyControlChanged(mControlTarget, this); return true; } } return false; } /** Loading Loading
apct-tests/perftests/inputmethod/src/android/inputmethod/ImePerfTest.java +1 −0 Original line number Diff line number Diff line Loading @@ -92,6 +92,7 @@ public class ImePerfTest extends ImePerfTestBase "IMMS.applyImeVisibility", "applyPostLayoutPolicy", "applyWindowSurfaceChanges", "ISC.onPreLayout", "ISC.onPostLayout" }; Loading
core/java/android/view/inputmethod/flags.aconfig +6 −0 Original line number Diff line number Diff line Loading @@ -219,3 +219,9 @@ flag { bug: "139872425" } flag { name: "set_server_visibility_onprelayout" namespace: "input_method" description: "Set server visibility before performLayout to avoid additional window layout traversal." bug: "427863960" }
services/core/java/com/android/server/wm/DisplayContent.java +4 −0 Original line number Diff line number Diff line Loading @@ -5072,6 +5072,10 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp setLayoutNeeded(); } if (android.view.inputmethod.Flags.setServerVisibilityOnprelayout()) { mInsetsStateController.onPreLayout(); } // Perform a layout, if needed. performLayout(true /* initial */, false /* updateInputWindows */); pendingLayoutChanges = 0; Loading
services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java +46 −13 Original line number Diff line number Diff line Loading @@ -71,6 +71,12 @@ final class ImeInsetsSourceProvider extends InsetsSourceProvider { */ private boolean mServerVisible; /** * The server visibility of the source provider's window before the latest * {@link #onPreLayout} call. */ private boolean mServerVisiblePreLayout; /** * When the IME is not ready, it has givenInsetsPending. However, this could happen again, * after it became serverVisible. This flag indicates is used to determine if it is Loading @@ -92,18 +98,31 @@ final class ImeInsetsSourceProvider extends InsetsSourceProvider { } @Override void onPostLayout() { void onPreLayout() { if (!android.view.inputmethod.Flags.setServerVisibilityOnprelayout()) { return; } mServerVisiblePreLayout = mServerVisible; super.onPreLayout(); mLastDrawn = mWin != null && mWin.isDrawn(); } @Override boolean onPostLayout() { final boolean wasSourceVisible = mSource.isVisible(); super.onPostLayout(); if (wasSourceVisible != mSource.isVisible()) { final boolean controlDispatched = super.onPostLayout(); if (!android.view.inputmethod.Flags.setServerVisibilityOnprelayout() && wasSourceVisible != mSource.isVisible()) { // TODO(b/427863960): Remove this and set the server visibility in onPreLayout // If the IME visibility has changed, a traversal needs to apply. mDisplayContent.setLayoutNeeded(); } final boolean givenInsetsPending = mWin != null && mWin.mGivenInsetsPending; if (!android.view.inputmethod.Flags.setServerVisibilityOnprelayout()) { mLastDrawn = mWin != null && mWin.isDrawn(); } // isLeashReadyForDispatching (used to dispatch the leash of the control) is // depending on mGivenInsetsReady. Therefore, triggering notifyControlChanged here // again, so that the control with leash can be eventually dispatched Loading @@ -115,10 +134,14 @@ final class ImeInsetsSourceProvider extends InsetsSourceProvider { mGivenInsetsReady = true; ImeTracker.forLogging().onProgress(mStatsToken, ImeTracker.PHASE_WM_POST_LAYOUT_NOTIFY_CONTROLS_CHANGED); if (!controlDispatched) { mStateController.notifyControlChanged(mControlTarget, this); } setImeShowing(true); } else if (wasSourceVisible && isServerVisible() && mGivenInsetsReady && givenInsetsPending) { return true; } else if (((!android.view.inputmethod.Flags.setServerVisibilityOnprelayout() && wasSourceVisible) || mServerVisiblePreLayout) && isServerVisible() && mGivenInsetsReady && givenInsetsPending) { // If the server visibility didn't change (still visible), and mGivenInsetsReady // is set, we won't call into notifyControlChanged. Therefore, we can reset the // statsToken, if available. Loading @@ -127,12 +150,22 @@ final class ImeInsetsSourceProvider extends InsetsSourceProvider { ImeTracker.forLogging().onCancelled(mStatsToken, ImeTracker.PHASE_WM_POST_LAYOUT_NOTIFY_CONTROLS_CHANGED); mStatsToken = null; } else if (isImeShowing() && !isServerVisible()) { } else if (!isServerVisible()) { if (isImeShowing()) { ProtoLog.d(WM_DEBUG_IME, "onPostLayout: setImeShowing(false) was: true, controlTarget=%s", mControlTarget); setImeShowing(false); } if (android.view.inputmethod.Flags.setServerVisibilityOnprelayout() && mControlTarget != null && mServerVisiblePreLayout && !controlDispatched) { // If the server visibility changed (not visible anymore), we need to dispatch // the control. mStateController.notifyControlChanged(mControlTarget, this); return true; } } return controlDispatched; } @Nullable Loading
services/core/java/com/android/server/wm/InsetsSourceProvider.java +34 −9 Original line number Diff line number Diff line Loading @@ -362,28 +362,53 @@ class InsetsSourceProvider { } /** * Called when a layout pass has occurred. * Called before a layout pass will occur. */ void onPostLayout() { void onPreLayout() { if (!android.view.inputmethod.Flags.setServerVisibilityOnprelayout()) { return; } if (mWin == null) { return; } setServerVisible(isSurfaceVisible()); } /** * Called after a layout pass has occurred. * * @return {@code true} if {@link InsetsStateController#notifyControlChanged} was called or * was scheduled to be called within this method, else {@code false}. */ boolean onPostLayout() { if (mWin == null) { return false; } final boolean serverVisibleChanged; if (!android.view.inputmethod.Flags.setServerVisibilityOnprelayout()) { final boolean isServerVisible = isSurfaceVisible(); final boolean serverVisibleChanged = mServerVisible != isServerVisible; serverVisibleChanged = mServerVisible != isServerVisible; setServerVisible(isServerVisible); } else { serverVisibleChanged = false; } if (mControl != null && mControlTarget != null) { final boolean positionChanged = updateInsetsControlPosition(mWin); if (!(positionChanged || mHasPendingPosition) if (positionChanged || mHasPendingPosition) { return true; } // The insets hint would be updated while changing the position. Here updates it // for the possible change of the bounds or the server visibility. && (updateInsetsHint(mControl) || serverVisibleChanged)) { // for the possible change of the bounds. if (updateInsetsHint(mControl) || serverVisibleChanged) { // Only call notifyControlChanged here when the position hasn't been or won't be // changed. Otherwise, it has been called or scheduled to be called during // updateInsetsControlPosition. mStateController.notifyControlChanged(mControlTarget, this); return true; } } return false; } /** Loading