Restrict ime adjustment to maintain primary split visibility
This does a few things.
1. Fixes the logic around restricting the amount of adjustment. Its
supposed to make sure that at-least 1/3 of the primary split is
visible.
2. Fixes an issue where windowcontainertransactions weren't applying
configuration updates to tiles specifically
3. Includes configuration changes among the things that will send
onTaskInfoChanged updates to task-organizers. Previously, the
changes were actually applied late.
- The reported changes are restricted to only configs that
task organizers can set.
4. To adapt to config changes being reported, divider code needed
to be changed.
Bug: 151181674
Test: Using various snaps of split, open ime in secondary and
verify that primary remains visible.
Change-Id: I7001bd29872a15950f91ab2407848fde8c3f1d02
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
index d7eab3a..d58cc73 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
@@ -273,10 +273,12 @@
}
// Update all the adjusted-for-ime states
- mView.setAdjustedForIme(mTargetShown, mTargetShown
- ? DisplayImeController.ANIMATION_DURATION_SHOW_MS
- : DisplayImeController.ANIMATION_DURATION_HIDE_MS);
- setAdjustedForIme(mTargetShown);
+ if (!mPaused) {
+ mView.setAdjustedForIme(mTargetShown, mTargetShown
+ ? DisplayImeController.ANIMATION_DURATION_SHOW_MS
+ : DisplayImeController.ANIMATION_DURATION_HIDE_MS);
+ }
+ setAdjustedForIme(mTargetShown && !mPaused);
}
@Override
@@ -390,6 +392,9 @@
mTargetPrimaryDim = mTargetSecondaryDim = 0.f;
updateImeAdjustState();
startAsyncAnimation();
+ if (mAnimation != null) {
+ mAnimation.end();
+ }
});
}
@@ -605,15 +610,17 @@
+ mHomeStackResizable + "->" + homeStackResizable + " split:" + inSplitMode());
}
WindowContainerTransaction wct = new WindowContainerTransaction();
+ final boolean minimizedChanged = mMinimized != minimized;
// Update minimized state
- if (mMinimized != minimized) {
+ if (minimizedChanged) {
mMinimized = minimized;
}
// Always set this because we could be entering split when mMinimized is already true
wct.setFocusable(mSplits.mPrimary.token, !mMinimized);
// Update home-stack resizability
- if (mHomeStackResizable != homeStackResizable) {
+ final boolean homeResizableChanged = mHomeStackResizable != homeStackResizable;
+ if (homeResizableChanged) {
mHomeStackResizable = homeStackResizable;
if (inSplitMode()) {
WindowManagerProxy.applyHomeTasksMinimized(
@@ -629,7 +636,10 @@
if (mMinimized) {
mImePositionProcessor.pause(displayId);
}
- mView.setMinimizedDockStack(minimized, getAnimDuration(), homeStackResizable);
+ if (minimizedChanged || homeResizableChanged) {
+ // This conflicts with IME adjustment, so only call it when things change.
+ mView.setMinimizedDockStack(minimized, getAnimDuration(), homeStackResizable);
+ }
if (!mMinimized) {
// afterwards so it can end any animations started in view
mImePositionProcessor.resume(displayId);
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/SplitDisplayLayout.java b/packages/SystemUI/src/com/android/systemui/stackdivider/SplitDisplayLayout.java
index 271faed..deead34 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/SplitDisplayLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/SplitDisplayLayout.java
@@ -191,13 +191,24 @@
final int currDividerWidth =
(int) (dividerWidthInactive * shownFraction + dividerWidth * (1.f - shownFraction));
+ // Calculate the highest we can move the bottom of the top stack to keep 30% visible.
final int minTopStackBottom = displayStableRect.top
+ (int) ((mPrimary.bottom - displayStableRect.top) * ADJUSTED_STACK_FRACTION_MIN);
- final int minImeTop = minTopStackBottom + currDividerWidth;
-
- // Calculate an offset which shifts the stacks up by the height of the IME, but still
- // leaves at least 30% of the top stack visible.
- final int yOffset = Math.max(0, dl.height() - Math.max(currImeTop, minImeTop));
+ // Based on that, calculate the maximum amount we'll allow the ime to shift things.
+ final int maxOffset = mPrimary.bottom - minTopStackBottom;
+ // Calculate how much we would shift things without limits (basically the height of ime).
+ final int desiredOffset = hiddenTop - shownTop;
+ // Calculate an "adjustedTop" which is the currImeTop but restricted by our constraints.
+ // We want an effect where the adjustment only occurs during the "highest" portion of the
+ // ime animation. This is done by shifting the adjustment values by the difference in
+ // offsets (effectively playing the whole adjustment animation some fixed amount of pixels
+ // below the ime top).
+ final int topCorrection = Math.max(0, desiredOffset - maxOffset);
+ final int adjustedTop = currImeTop + topCorrection;
+ // The actual yOffset is the distance between adjustedTop and the bottom of the display.
+ // Since our adjustedTop values are playing "below" the ime, we clamp at 0 so we only
+ // see adjustment upward.
+ final int yOffset = Math.max(0, dl.height() - adjustedTop);
// TOP
// Reduce the offset by an additional small amount to squish the divider bar.
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/SplitScreenTaskOrganizer.java b/packages/SystemUI/src/com/android/systemui/stackdivider/SplitScreenTaskOrganizer.java
index 48ea4ae..f1bb27a 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/SplitScreenTaskOrganizer.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/SplitScreenTaskOrganizer.java
@@ -30,7 +30,6 @@
import android.util.Log;
import android.view.Display;
import android.view.ITaskOrganizer;
-import android.view.IWindowContainer;
import android.view.SurfaceControl;
import android.view.SurfaceSession;
@@ -108,6 +107,8 @@
* presentations based on the contents of the split regions.
*/
private void handleTaskInfoChanged(RunningTaskInfo info) {
+ final boolean secondaryWasHomeOrRecents = mSecondary.topActivityType == ACTIVITY_TYPE_HOME
+ || mSecondary.topActivityType == ACTIVITY_TYPE_RECENTS;
final boolean primaryWasEmpty = mPrimary.topActivityType == ACTIVITY_TYPE_UNDEFINED;
final boolean secondaryWasEmpty = mSecondary.topActivityType == ACTIVITY_TYPE_UNDEFINED;
if (info.token.asBinder() == mPrimary.token.asBinder()) {
@@ -117,9 +118,16 @@
}
final boolean primaryIsEmpty = mPrimary.topActivityType == ACTIVITY_TYPE_UNDEFINED;
final boolean secondaryIsEmpty = mSecondary.topActivityType == ACTIVITY_TYPE_UNDEFINED;
+ final boolean secondaryIsHomeOrRecents = mSecondary.topActivityType == ACTIVITY_TYPE_HOME
+ || mSecondary.topActivityType == ACTIVITY_TYPE_RECENTS;
if (DEBUG) {
Log.d(TAG, "onTaskInfoChanged " + mPrimary + " " + mSecondary);
}
+ if (primaryIsEmpty == primaryWasEmpty && secondaryWasEmpty == secondaryIsEmpty
+ && secondaryWasHomeOrRecents == secondaryIsHomeOrRecents) {
+ // No relevant changes
+ return;
+ }
if (primaryIsEmpty || secondaryIsEmpty) {
// At-least one of the splits is empty which means we are currently transitioning
// into or out-of split-screen mode.
@@ -146,8 +154,7 @@
}
mDivider.startEnterSplit();
}
- } else if (mSecondary.topActivityType == ACTIVITY_TYPE_HOME
- || mSecondary.topActivityType == ACTIVITY_TYPE_RECENTS) {
+ } else if (secondaryIsHomeOrRecents) {
// Both splits are populated but the secondary split has a home/recents stack on top,
// so enter minimized mode.
mDivider.ensureMinimizedSplit();