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

Commit cfd6f3b4 authored by Jorim Jaggi's avatar Jorim Jaggi
Browse files

A brave new world for window insets (7/n)

Ensure that the client visibility state affects other subsystems,
like accessibility as well as input.

Test: WindowStateTest
Bug: 118118435
Change-Id: I8a50a0b82dc76e578861967197350eaa3867f837
parent 22b99b47
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -250,7 +250,7 @@ public class InsetsState implements Parcelable {
        }
    }

    static String typeToString(int type) {
    public static String typeToString(int type) {
        switch (type) {
            case TYPE_TOP_BAR:
                return "TYPE_TOP_BAR";
+14 −13
Original line number Diff line number Diff line
@@ -18,7 +18,6 @@ package com.android.server.wm;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.graphics.Point;
import android.graphics.Rect;
import android.util.proto.ProtoOutputStream;
import android.view.InsetsState;
@@ -28,6 +27,7 @@ import android.view.InsetsSource;
import android.view.InsetsSourceControl;

import com.android.internal.util.function.TriConsumer;
import com.android.internal.util.function.pooled.PooledLambda;
import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;

import java.io.PrintWriter;
@@ -106,8 +106,8 @@ class InsetsSourceProvider {
            mTmpRect.inset(mWin.mGivenContentInsets);
        }
        mSource.setFrame(mTmpRect);
        setServerVisible(mWin.isVisible() && !mWin.mGivenInsetsPending);

        setServerVisible(mWin.wouldBeVisibleIfPolicyIgnored() && mWin.mPolicyVisibility
                && !mWin.mGivenInsetsPending);
    }

    void updateControlForTarget(@Nullable WindowState target) {
@@ -115,15 +115,15 @@ class InsetsSourceProvider {
            return;
        }
        if (target == null) {
            revokeControl();
            // Cancelling the animation will invoke onAnimationCancelled, resetting all the fields.
            mWin.cancelAnimation();
            return;
        }
        mAdapter = new ControlAdapter();
        mWin.startAnimation(mDisplayContent.getPendingTransaction(), mAdapter,
                false /* TODO hidden */);
                !mClientVisible /* hidden */);
        mControllingWin = target;
        mControl = new InsetsSourceControl(mSource.getType(), mAdapter.mCapturedLeash);
        setClientVisible(InsetsState.getDefaultVisibly(mSource.getType()));
    }

    boolean onInsetsModified(WindowState caller, InsetsSource modifiedSource) {
@@ -135,7 +135,12 @@ class InsetsSourceProvider {
    }

    private void setClientVisible(boolean clientVisible) {
        if (mClientVisible == clientVisible) {
            return;
        }
        mClientVisible = clientVisible;
        mDisplayContent.mWmService.mH.sendMessage(PooledLambda.obtainMessage(
                DisplayContent::layoutAndAssignWindowLayersIfNeeded, mDisplayContent));
        updateVisibility();
    }

@@ -152,13 +157,8 @@ class InsetsSourceProvider {
        return mControl;
    }

    void revokeControl() {
        if (mControllingWin != null) {

            // Cancelling the animation will invoke onAnimationCancelled, resetting all the fields.
            mWin.cancelAnimation();
        }
        setClientVisible(InsetsState.getDefaultVisibly(mSource.getType()));
    boolean isClientVisible() {
        return mClientVisible;
    }

    private class ControlAdapter implements AnimationAdapter {
@@ -186,6 +186,7 @@ class InsetsSourceProvider {
        public void onAnimationCancelled(SurfaceControl animationLeash) {
            if (mAdapter == this) {
                mStateController.notifyControlRevoked(mControllingWin, InsetsSourceProvider.this);
                setClientVisible(InsetsState.getDefaultVisibly(mSource.getType()));
                mControl = null;
                mControllingWin = null;
                mAdapter = null;
+6 −0
Original line number Diff line number Diff line
@@ -218,5 +218,11 @@ class InsetsStateController {
    void dump(String prefix, PrintWriter pw) {
        pw.println(prefix + "WindowInsetsStateController");
        mState.dump(prefix + "  ", pw);
        pw.println(prefix + "  " + "Control map:");
        for (int i = mTypeWinControlMap.size() - 1; i >= 0; i--) {
            pw.print(prefix + "  ");
            pw.println(InsetsState.typeToString(mTypeWinControlMap.keyAt(i)) + " -> "
                    + mTypeWinControlMap.valueAt(i));
        }
    }
}
+6 −3
Original line number Diff line number Diff line
@@ -1373,12 +1373,15 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP

    @Override
    boolean isVisible() {
        return wouldBeVisibleIfPolicyIgnored() && mPolicyVisibility;
        return wouldBeVisibleIfPolicyIgnored() && mPolicyVisibility
                // If we don't have a provider, this window isn't used as a window generating
                // insets, so nobody can hide it over the inset APIs.
                && (mInsetProvider == null || mInsetProvider.isClientVisible());
    }

    /**
     * @return True if the window would be visible if we'd ignore policy visibility, false
     *         otherwise.
     * @return {@code true} if the window would be visible if we'd ignore policy visibility,
     *         {@code false} otherwise.
     */
    boolean wouldBeVisibleIfPolicyIgnored() {
        return mHasSurface && !isParentWindowHidden()
+17 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package com.android.server.wm;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.hardware.camera2.params.OutputConfiguration.ROTATION_90;
import static android.view.InsetsState.TYPE_TOP_BAR;
import static android.view.Surface.ROTATION_0;
import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
@@ -31,6 +32,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVE
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;

import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
@@ -56,6 +58,7 @@ import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
import android.util.Size;
import android.view.DisplayCutout;
import android.view.InsetsSource;
import android.view.SurfaceControl;
import android.view.WindowManager;

@@ -325,6 +328,20 @@ public class WindowStateTests extends WindowTestsBase {
        assertFalse(app.canAffectSystemUiFlags());
    }

    @Test
    public void testVisibleWithInsetsProvider() throws Exception {
        final WindowState topBar = createWindow(null, TYPE_STATUS_BAR, "topBar");
        final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
        topBar.mHasSurface = true;
        assertTrue(topBar.isVisible());
        mDisplayContent.getInsetsStateController().getSourceProvider(TYPE_TOP_BAR)
                .setWindow(topBar, null);
        mDisplayContent.getInsetsStateController().onBarControllingWindowChanged(app);
        mDisplayContent.getInsetsStateController().getSourceProvider(TYPE_TOP_BAR)
                .onInsetsModified(app, new InsetsSource(TYPE_TOP_BAR));
        assertFalse(topBar.isVisible());
    }

    @Test
    public void testIsSelfOrAncestorWindowAnimating() {
        final WindowState root = createWindow(null, TYPE_APPLICATION, "root");