summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Ming-Shin Lu <lumark@google.com> 2021-01-29 16:45:23 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2021-01-29 16:45:23 +0000
commit07d71cf8ee8788a313ec12431bce27b87b9e96ea (patch)
tree0411d34592e7984abbd6bfb841401c4d61f544e3
parent2d1e90b508971e3cfa52727d595442bb7cef802a (diff)
parent0f536fa99489c5cfd2d266e94798b19540e2cd12 (diff)
Merge "Better IME transition while switching app with recents (6/N)" into sc-dev
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java9
-rw-r--r--services/core/java/com/android/server/wm/InsetsStateController.java12
-rw-r--r--services/core/java/com/android/server/wm/WindowContainer.java10
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java33
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java27
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java23
6 files changed, 106 insertions, 8 deletions
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 73bcf47979fe..0aaa1a1752bf 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -4107,8 +4107,15 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
* Callbacks when the given type of {@link WindowContainer} animation finished running in the
* hierarchy.
*/
- void onWindowAnimationFinished(int type) {
+ void onWindowAnimationFinished(@NonNull WindowContainer wc, int type) {
if (type == ANIMATION_TYPE_APP_TRANSITION || type == ANIMATION_TYPE_RECENTS) {
+ // Unfreeze the insets state of the frozen target when the animation finished if exists.
+ final Task task = wc.asTask();
+ if (task != null) {
+ task.forAllWindows(w -> {
+ w.clearFrozenInsetsState();
+ }, true /* traverseTopToBottom */);
+ }
removeImeSurfaceImmediately();
}
}
diff --git a/services/core/java/com/android/server/wm/InsetsStateController.java b/services/core/java/com/android/server/wm/InsetsStateController.java
index 398049fb97c3..267f67759a24 100644
--- a/services/core/java/com/android/server/wm/InsetsStateController.java
+++ b/services/core/java/com/android/server/wm/InsetsStateController.java
@@ -74,7 +74,7 @@ class InsetsStateController {
private final ArraySet<InsetsControlTarget> mPendingControlChanged = new ArraySet<>();
private final Consumer<WindowState> mDispatchInsetsChanged = w -> {
- if (w.isVisible()) {
+ if (w.isReadyToDispatchInsetsState()) {
w.notifyInsetsChanged();
}
};
@@ -117,7 +117,8 @@ class InsetsStateController {
final @InternalInsetsType int type = provider != null
? provider.getSource().getType() : ITYPE_INVALID;
return getInsetsForTarget(type, target.getWindowingMode(), target.isAlwaysOnTop(),
- isAboveIme(target));
+ isAboveIme(target),
+ target.getFrozenInsetsState() != null ? target.getFrozenInsetsState() : mState);
}
InsetsState getInsetsForWindowMetrics(@NonNull WindowManager.LayoutParams attrs) {
@@ -132,7 +133,7 @@ class InsetsStateController {
final @WindowingMode int windowingMode = token != null
? token.getWindowingMode() : WINDOWING_MODE_UNDEFINED;
final boolean alwaysOnTop = token != null && token.isAlwaysOnTop();
- return getInsetsForTarget(type, windowingMode, alwaysOnTop, isAboveIme(token));
+ return getInsetsForTarget(type, windowingMode, alwaysOnTop, isAboveIme(token), mState);
}
private boolean isAboveIme(WindowContainer target) {
@@ -180,9 +181,8 @@ class InsetsStateController {
* @see #getInsetsForWindowMetrics
*/
private InsetsState getInsetsForTarget(@InternalInsetsType int type,
- @WindowingMode int windowingMode, boolean isAlwaysOnTop, boolean aboveIme) {
- InsetsState state = mState;
-
+ @WindowingMode int windowingMode, boolean isAlwaysOnTop, boolean aboveIme,
+ @NonNull InsetsState state) {
if (type != ITYPE_INVALID) {
state = new InsetsState(state);
state.removeSource(type);
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 03fca1137e47..dd4ee877c05b 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -2684,6 +2684,14 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
@Nullable ArrayList<WindowContainer> sources) {
final Task task = asTask();
if (task != null && !enter && !task.isHomeOrRecentsRootTask()) {
+ if (AppTransition.isClosingTransitOld(transit)) {
+ // Freezes the insets state when the window is in app exiting transition, to
+ // ensure the exiting window won't receive unexpected insets changes from the
+ // next window.
+ task.forAllWindows(w -> {
+ w.freezeInsetsState();
+ }, true /* traverseTopToBottom */);
+ }
mDisplayContent.showImeScreenshot();
}
final Pair<AnimationAdapter, AnimationAdapter> adapters = getAnimationAdapter(lp,
@@ -2831,7 +2839,7 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
}
mSurfaceAnimationSources.clear();
if (mDisplayContent != null) {
- mDisplayContent.onWindowAnimationFinished(type);
+ mDisplayContent.onWindowAnimationFinished(this, type);
}
}
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 9f3188be7623..9a7823e35a01 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -713,6 +713,12 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
private @Nullable InsetsSourceProvider mControllableInsetProvider;
private final InsetsState mRequestedInsetsState = new InsetsState();
+ /**
+ * Freeze the insets state in some cases that not necessarily keeps up-to-date to the client.
+ * (e.g app exiting transition)
+ */
+ private InsetsState mFrozenInsetsState;
+
@Nullable InsetsSourceProvider mPendingPositionChanged;
private static final float DEFAULT_DIM_AMOUNT_DEAD_WINDOW = 0.5f;
@@ -758,6 +764,33 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
}
}
+ /**
+ * Set a freeze state for the window to ignore dispatching its insets state to the client.
+ *
+ * Used to keep the insets state for some use cases. (e.g. app exiting transition)
+ */
+ void freezeInsetsState() {
+ if (mFrozenInsetsState == null) {
+ mFrozenInsetsState = new InsetsState(getInsetsState(), true /* copySources */);
+ }
+ }
+
+ void clearFrozenInsetsState() {
+ mFrozenInsetsState = null;
+ }
+
+ InsetsState getFrozenInsetsState() {
+ return mFrozenInsetsState;
+ }
+
+ /**
+ * Check if the insets state of the window is ready to dispatch to the client when invoking
+ * {@link InsetsStateController#notifyInsetsChanged}.
+ */
+ boolean isReadyToDispatchInsetsState() {
+ return isVisible() && mFrozenInsetsState == null;
+ }
+
void seamlesslyRotateIfAllowed(Transaction transaction, @Rotation int oldRotation,
@Rotation int rotation, boolean requested) {
// Invisible windows and the wallpaper do not participate in the seamless rotation animation
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
index b0b8afd6c3a4..df5b48a038f3 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
@@ -22,6 +22,8 @@ import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
+import static android.view.WindowManager.TRANSIT_CLOSE;
+import static android.view.WindowManager.TRANSIT_OLD_TASK_CLOSE;
import static android.view.WindowManager.TRANSIT_OLD_TASK_OPEN;
import static android.view.WindowManager.TRANSIT_OPEN;
import static android.window.DisplayAreaOrganizer.FEATURE_DEFAULT_TASK_CONTAINER;
@@ -978,6 +980,31 @@ public class WindowContainerTests extends WindowTestsBase {
assertEquals(200, listener.mConfiguration.densityDpi);
}
+ @Test
+ public void testFreezeInsetsStateWhenAppTransition() {
+ final Task stack = createTaskStackOnDisplay(mDisplayContent);
+ final Task task = createTaskInStack(stack, 0 /* userId */);
+ final ActivityRecord activity = createActivityRecord(mDisplayContent, task);
+ final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, activity, "win");
+ task.getDisplayContent().prepareAppTransition(TRANSIT_CLOSE);
+ spyOn(win);
+ doReturn(true).when(task).okToAnimate();
+ ArrayList<WindowContainer> sources = new ArrayList<>();
+ sources.add(activity);
+
+ // Simulate the task applying the exit transition, verify the main window of the task
+ // will be set the frozen insets state.
+ task.applyAnimation(null, TRANSIT_OLD_TASK_CLOSE, false /* enter */,
+ false /* isVoiceInteraction */, sources);
+ verify(win).freezeInsetsState();
+
+ // Simulate the task transition finished, verify the frozen insets state of the window
+ // will be reset.
+ task.onAnimationFinished(ANIMATION_TYPE_APP_TRANSITION,
+ task.mSurfaceAnimator.getAnimation());
+ verify(win).clearFrozenInsetsState();
+ }
+
/* Used so we can gain access to some protected members of the {@link WindowContainer} class */
private static class TestWindowContainer extends WindowContainer<TestWindowContainer> {
private final int mLayer;
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 263aa194a108..3231f8b6551a 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
@@ -810,4 +810,27 @@ public class WindowStateTests extends WindowTestsBase {
WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
assertFalse(sameTokenWindow.needsRelativeLayeringToIme());
}
+
+ @Test
+ public void testSetFreezeInsetsState() {
+ final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
+ spyOn(app);
+ doReturn(true).when(app).isVisible();
+
+ // Set freezing the insets state to make the window ignore to dispatch insets changed.
+ final InsetsState expectedState = new InsetsState(app.getInsetsState(),
+ true /* copySources */);
+ app.freezeInsetsState();
+ assertEquals(expectedState, app.getFrozenInsetsState());
+ assertFalse(app.isReadyToDispatchInsetsState());
+ assertEquals(expectedState, app.getInsetsState());
+ mDisplayContent.getInsetsStateController().notifyInsetsChanged();
+ verify(app, never()).notifyInsetsChanged();
+
+ // Unfreeze the insets state to make the window can dispatch insets changed.
+ app.clearFrozenInsetsState();
+ assertTrue(app.isReadyToDispatchInsetsState());
+ mDisplayContent.getInsetsStateController().notifyInsetsChanged();
+ verify(app).notifyInsetsChanged();
+ }
}