From e1a31c94832efa679c7630e30fa092f1bfe12685 Mon Sep 17 00:00:00 2001 From: Evan Rosky Date: Thu, 18 Jun 2020 16:46:47 -0700 Subject: [PATCH] Don't use sync transactions if not needed Some common operations (like setting focusability) don't need to be sync. In fact, sync is causing problems because it causes other simultaneous operations (like transition animations) to put some of their operations on the sync transaction instead of pending. For example, leash-reparent would go on pending, but activity hide would go on sync. Additionally, the divider kept re-updating the app bounds even when they didn't change. This added to the likelihood that transactions would get mixed-up. Bug: 158767094 Test: In split-screen landscape, quickly open/close apps in secondary split and look for flickers. Change-Id: I0151e013347e9b30d58a52e8bd6b1401defee572 --- .../systemui/stackdivider/Divider.java | 12 ++- .../stackdivider/DividerImeController.java | 81 ++++++++++--------- 2 files changed, 54 insertions(+), 39 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java index fab120e470e52..a25103e48580a 100644 --- a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java +++ b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java @@ -387,6 +387,7 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks, } // Always set this because we could be entering split when mMinimized is already true wct.setFocusable(mSplits.mPrimary.token, !mMinimized); + boolean onlyFocusable = true; // Update home-stack resizability final boolean homeResizableChanged = mHomeStackResizable != homeStackResizable; @@ -395,6 +396,7 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks, if (isDividerVisible()) { WindowManagerProxy.applyHomeTasksMinimized( mSplitLayout, mSplits.mSecondary.token, wct); + onlyFocusable = false; } } @@ -416,7 +418,15 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks, } } updateTouchable(); - mWindowManagerProxy.applySyncTransaction(wct); + if (onlyFocusable) { + // If we are only setting focusability, a sync transaction isn't necessary (in fact it + // can interrupt other animations), so see if it can be submitted on pending instead. + if (!mSplits.mDivider.getWmProxy().queueSyncTransactionIfWaiting(wct)) { + WindowOrganizer.applyTransaction(wct); + } + } else { + mWindowManagerProxy.applySyncTransaction(wct); + } } void setAdjustedForIme(boolean adjustedForIme) { diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerImeController.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerImeController.java index aea87f2d1971f..6e296e2ce0d39 100644 --- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerImeController.java +++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerImeController.java @@ -29,6 +29,7 @@ import android.view.SurfaceControl; import android.window.TaskOrganizer; import android.window.WindowContainerToken; import android.window.WindowContainerTransaction; +import android.window.WindowOrganizer; import androidx.annotation.Nullable; @@ -173,47 +174,51 @@ class DividerImeController implements DisplayImeController.ImePositionProcessor } private void updateImeAdjustState() { - // Reposition the server's secondary split position so that it evaluates - // insets properly. - WindowContainerTransaction wct = new WindowContainerTransaction(); - final SplitDisplayLayout splitLayout = getLayout(); - if (mTargetAdjusted) { - splitLayout.updateAdjustedBounds(mShownTop, mHiddenTop, mShownTop); - wct.setBounds(mSplits.mSecondary.token, splitLayout.mAdjustedSecondary); - // "Freeze" the configuration size so that the app doesn't get a config - // or relaunch. This is required because normally nav-bar contributes - // to configuration bounds (via nondecorframe). - Rect adjustAppBounds = new Rect(mSplits.mSecondary.configuration - .windowConfiguration.getAppBounds()); - adjustAppBounds.offset(0, splitLayout.mAdjustedSecondary.top - - splitLayout.mSecondary.top); - wct.setAppBounds(mSplits.mSecondary.token, adjustAppBounds); - wct.setScreenSizeDp(mSplits.mSecondary.token, - mSplits.mSecondary.configuration.screenWidthDp, - mSplits.mSecondary.configuration.screenHeightDp); + if (mAdjusted != mTargetAdjusted) { + // Reposition the server's secondary split position so that it evaluates + // insets properly. + WindowContainerTransaction wct = new WindowContainerTransaction(); + final SplitDisplayLayout splitLayout = getLayout(); + if (mTargetAdjusted) { + splitLayout.updateAdjustedBounds(mShownTop, mHiddenTop, mShownTop); + wct.setBounds(mSplits.mSecondary.token, splitLayout.mAdjustedSecondary); + // "Freeze" the configuration size so that the app doesn't get a config + // or relaunch. This is required because normally nav-bar contributes + // to configuration bounds (via nondecorframe). + Rect adjustAppBounds = new Rect(mSplits.mSecondary.configuration + .windowConfiguration.getAppBounds()); + adjustAppBounds.offset(0, splitLayout.mAdjustedSecondary.top + - splitLayout.mSecondary.top); + wct.setAppBounds(mSplits.mSecondary.token, adjustAppBounds); + wct.setScreenSizeDp(mSplits.mSecondary.token, + mSplits.mSecondary.configuration.screenWidthDp, + mSplits.mSecondary.configuration.screenHeightDp); - wct.setBounds(mSplits.mPrimary.token, splitLayout.mAdjustedPrimary); - adjustAppBounds = new Rect(mSplits.mPrimary.configuration - .windowConfiguration.getAppBounds()); - adjustAppBounds.offset(0, splitLayout.mAdjustedPrimary.top - - splitLayout.mPrimary.top); - wct.setAppBounds(mSplits.mPrimary.token, adjustAppBounds); - wct.setScreenSizeDp(mSplits.mPrimary.token, - mSplits.mPrimary.configuration.screenWidthDp, - mSplits.mPrimary.configuration.screenHeightDp); - } else { - wct.setBounds(mSplits.mSecondary.token, splitLayout.mSecondary); - wct.setAppBounds(mSplits.mSecondary.token, null); - wct.setScreenSizeDp(mSplits.mSecondary.token, - SCREEN_WIDTH_DP_UNDEFINED, SCREEN_HEIGHT_DP_UNDEFINED); - wct.setBounds(mSplits.mPrimary.token, splitLayout.mPrimary); - wct.setAppBounds(mSplits.mPrimary.token, null); - wct.setScreenSizeDp(mSplits.mPrimary.token, - SCREEN_WIDTH_DP_UNDEFINED, SCREEN_HEIGHT_DP_UNDEFINED); + wct.setBounds(mSplits.mPrimary.token, splitLayout.mAdjustedPrimary); + adjustAppBounds = new Rect(mSplits.mPrimary.configuration + .windowConfiguration.getAppBounds()); + adjustAppBounds.offset(0, splitLayout.mAdjustedPrimary.top + - splitLayout.mPrimary.top); + wct.setAppBounds(mSplits.mPrimary.token, adjustAppBounds); + wct.setScreenSizeDp(mSplits.mPrimary.token, + mSplits.mPrimary.configuration.screenWidthDp, + mSplits.mPrimary.configuration.screenHeightDp); + } else { + wct.setBounds(mSplits.mSecondary.token, splitLayout.mSecondary); + wct.setAppBounds(mSplits.mSecondary.token, null); + wct.setScreenSizeDp(mSplits.mSecondary.token, + SCREEN_WIDTH_DP_UNDEFINED, SCREEN_HEIGHT_DP_UNDEFINED); + wct.setBounds(mSplits.mPrimary.token, splitLayout.mPrimary); + wct.setAppBounds(mSplits.mPrimary.token, null); + wct.setScreenSizeDp(mSplits.mPrimary.token, + SCREEN_WIDTH_DP_UNDEFINED, SCREEN_HEIGHT_DP_UNDEFINED); + } + + if (!mSplits.mDivider.getWmProxy().queueSyncTransactionIfWaiting(wct)) { + WindowOrganizer.applyTransaction(wct); + } } - mSplits.mDivider.getWmProxy().applySyncTransaction(wct); - // Update all the adjusted-for-ime states if (!mPaused) { final DividerView view = getView();