Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 07d71cf8 authored by Ming-Shin Lu's avatar Ming-Shin Lu Committed by Android (Google) Code Review
Browse files

Merge "Better IME transition while switching app with recents (6/N)" into sc-dev

parents 2d1e90b5 0f536fa9
Loading
Loading
Loading
Loading
+8 −1
Original line number Diff line number Diff line
@@ -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();
        }
    }
+6 −6
Original line number Diff line number Diff line
@@ -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);
+9 −1
Original line number Diff line number Diff line
@@ -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);
        }
    }

+33 −0
Original line number Diff line number Diff line
@@ -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
+27 −0
Original line number Diff line number Diff line
@@ -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;
Loading