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

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

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

Mirror state back to server

In case the client does some local visibility modification to the
leash, the server needs to be informed for a couple of reasons:

- Dispatching state to other apps
- Updating accessibility services
- Updating SystemUI/IME system

For that we send the state back whenever we modified it and send
it via IWindowSession.insetsModified. The server ensures that
visibility state is only updated if we have a match for the
controlling app, and then updates the visibility state and
dispatches it to other apps.

We also invert mHidden to mVisible in InsetsSourceConsumer as it
was really really confusing.

Bug: 118118435
Change-Id: I92f187bf892a5f26b8b007ed7e6fbf4d2c7b13e6
parent 89000d06
Loading
Loading
Loading
Loading
+6 −0
Original line number Original line Diff line number Diff line
@@ -250,4 +250,10 @@ interface IWindowSession {
     */
     */
    void updateTapExcludeRegion(IWindow window, int regionId, int left, int top, int width,
    void updateTapExcludeRegion(IWindow window, int regionId, int left, int top, int width,
            int height);
            int height);

    /**
     * Called when the client has changed the local insets state, and now the server should reflect
     * that new state.
     */
    void insetsModified(IWindow window, in InsetsState state);
}
}
+31 −0
Original line number Original line Diff line number Diff line
@@ -19,7 +19,9 @@ package android.view;
import android.annotation.NonNull;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.Nullable;
import android.graphics.Rect;
import android.graphics.Rect;
import android.os.RemoteException;
import android.util.ArraySet;
import android.util.ArraySet;
import android.util.Log;
import android.util.SparseArray;
import android.util.SparseArray;
import android.view.SurfaceControl.Transaction;
import android.view.SurfaceControl.Transaction;
import android.view.WindowInsets.Type.InsetType;
import android.view.WindowInsets.Type.InsetType;
@@ -36,7 +38,11 @@ import java.util.ArrayList;
 */
 */
public class InsetsController implements WindowInsetsController {
public class InsetsController implements WindowInsetsController {


    private final String TAG = "InsetsControllerImpl";

    private final InsetsState mState = new InsetsState();
    private final InsetsState mState = new InsetsState();
    private final InsetsState mTmpState = new InsetsState();

    private final Rect mFrame = new Rect();
    private final Rect mFrame = new Rect();
    private final SparseArray<InsetsSourceConsumer> mSourceConsumers = new SparseArray<>();
    private final SparseArray<InsetsSourceConsumer> mSourceConsumers = new SparseArray<>();
    private final ViewRootImpl mViewRoot;
    private final ViewRootImpl mViewRoot;
@@ -61,8 +67,12 @@ public class InsetsController implements WindowInsetsController {
            return false;
            return false;
        }
        }
        mState.set(state);
        mState.set(state);
        mTmpState.set(state, true /* copySources */);
        applyLocalVisibilityOverride();
        applyLocalVisibilityOverride();
        mViewRoot.notifyInsetsChanged();
        mViewRoot.notifyInsetsChanged();
        if (!mState.equals(mTmpState)) {
            sendStateToWindowManager();
        }
        return true;
        return true;
    }
    }


@@ -163,6 +173,27 @@ public class InsetsController implements WindowInsetsController {
    @VisibleForTesting
    @VisibleForTesting
    public void notifyVisibilityChanged() {
    public void notifyVisibilityChanged() {
        mViewRoot.notifyInsetsChanged();
        mViewRoot.notifyInsetsChanged();
        sendStateToWindowManager();
    }

    /**
     * Sends the local visibility state back to window manager.
     */
    private void sendStateToWindowManager() {
        InsetsState tmpState = new InsetsState();
        for (int i = mSourceConsumers.size() - 1; i >= 0; i--) {
            final InsetsSourceConsumer consumer = mSourceConsumers.valueAt(i);
            if (consumer.getControl() != null) {
                tmpState.addSource(mState.getSource(consumer.getType()));
            }
        }

        // TODO: Put this on a dispatcher thread.
        try {
            mViewRoot.mWindowSession.insetsModified(mViewRoot.mWindow, tmpState);
        } catch (RemoteException e) {
            Log.e(TAG, "Failed to call insetsModified", e);
        }
    }
    }


    void dump(String prefix, PrintWriter pw) {
    void dump(String prefix, PrintWriter pw) {
+4 −0
Original line number Original line Diff line number Diff line
@@ -65,6 +65,10 @@ public class InsetsSource implements Parcelable {
        return mFrame;
        return mFrame;
    }
    }


    public boolean isVisible() {
        return mVisible;
    }

    /**
    /**
     * Calculates the insets this source will cause to a client window.
     * Calculates the insets this source will cause to a client window.
     *
     *
+20 −14
Original line number Original line Diff line number Diff line
@@ -35,7 +35,7 @@ public class InsetsSourceConsumer {
    private final InsetsState mState;
    private final InsetsState mState;
    private final InsetsController mController;
    private final InsetsController mController;
    private @Nullable InsetsSourceControl mSourceControl;
    private @Nullable InsetsSourceControl mSourceControl;
    private boolean mHidden;
    private boolean mVisible;


    public InsetsSourceConsumer(@InternalInsetType int type, InsetsState state,
    public InsetsSourceConsumer(@InternalInsetType int type, InsetsState state,
            Supplier<Transaction> transactionSupplier, InsetsController controller) {
            Supplier<Transaction> transactionSupplier, InsetsController controller) {
@@ -43,6 +43,7 @@ public class InsetsSourceConsumer {
        mState = state;
        mState = state;
        mTransactionSupplier = transactionSupplier;
        mTransactionSupplier = transactionSupplier;
        mController = controller;
        mController = controller;
        mVisible = InsetsState.getDefaultVisibly(type);
    }
    }


    public void setControl(@Nullable InsetsSourceControl control) {
    public void setControl(@Nullable InsetsSourceControl control) {
@@ -51,9 +52,10 @@ public class InsetsSourceConsumer {
        }
        }
        mSourceControl = control;
        mSourceControl = control;
        applyHiddenToControl();
        applyHiddenToControl();
        applyLocalVisibilityOverride();
        if (applyLocalVisibilityOverride()) {
            mController.notifyVisibilityChanged();
            mController.notifyVisibilityChanged();
        }
        }
    }


    @VisibleForTesting
    @VisibleForTesting
    public InsetsSourceControl getControl() {
    public InsetsSourceControl getControl() {
@@ -66,28 +68,32 @@ public class InsetsSourceConsumer {


    @VisibleForTesting
    @VisibleForTesting
    public void show() {
    public void show() {
        setHidden(false);
        setVisible(true);
    }
    }


    @VisibleForTesting
    @VisibleForTesting
    public void hide() {
    public void hide() {
        setHidden(true);
        setVisible(false);
    }
    }


    void applyLocalVisibilityOverride() {
    boolean applyLocalVisibilityOverride() {


        // If we don't have control, we are not able to change the visibility.
        // If we don't have control, we are not able to change the visibility.
        if (mSourceControl == null) {
        if (mSourceControl == null) {
            return;
            return false;
        }
        if (mState.getSource(mType).isVisible() == mVisible) {
            return false;
        }
        }
        mState.getSource(mType).setVisible(!mHidden);
        mState.getSource(mType).setVisible(mVisible);
        return true;
    }
    }


    private void setHidden(boolean hidden) {
    private void setVisible(boolean visible) {
        if (mHidden == hidden) {
        if (mVisible == visible) {
            return;
            return;
        }
        }
        mHidden = hidden;
        mVisible = visible;
        applyHiddenToControl();
        applyHiddenToControl();
        applyLocalVisibilityOverride();
        applyLocalVisibilityOverride();
        mController.notifyVisibilityChanged();
        mController.notifyVisibilityChanged();
@@ -100,10 +106,10 @@ public class InsetsSourceConsumer {


        // TODO: Animation
        // TODO: Animation
        final Transaction t = mTransactionSupplier.get();
        final Transaction t = mTransactionSupplier.get();
        if (mHidden) {
        if (mVisible) {
            t.hide(mSourceControl.getLeash());
        } else {
            t.show(mSourceControl.getLeash());
            t.show(mSourceControl.getLeash());
        } else {
            t.hide(mSourceControl.getLeash());
        }
        }
        t.apply();
        t.apply();
    }
    }
+27 −0
Original line number Original line Diff line number Diff line
@@ -32,6 +32,7 @@ import android.view.WindowInsets.Type.InsetType;
import java.io.PrintWriter;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;


/**
/**
 * Holder for state of system windows that cause window insets for all other windows in the system.
 * Holder for state of system windows that cause window insets for all other windows in the system.
@@ -200,6 +201,18 @@ public class InsetsState implements Parcelable {
        }
        }
    }
    }


    public void addSource(InsetsSource source) {
        mSources.put(source.getType(), source);
    }

    public int getSourcesCount() {
        return mSources.size();
    }

    public InsetsSource sourceAt(int index) {
        return mSources.valueAt(index);
    }

    public static @InternalInsetType ArraySet<Integer> toInternalType(@InsetType int insetTypes) {
    public static @InternalInsetType ArraySet<Integer> toInternalType(@InsetType int insetTypes) {
        final ArraySet<Integer> result = new ArraySet<>();
        final ArraySet<Integer> result = new ArraySet<>();
        if ((insetTypes & Type.TOP_BAR) != 0) {
        if ((insetTypes & Type.TOP_BAR) != 0) {
@@ -216,6 +229,20 @@ public class InsetsState implements Parcelable {
        return result;
        return result;
    }
    }


    public static boolean getDefaultVisibly(@InsetType int type) {
        switch (type) {
            case TYPE_TOP_BAR:
            case TYPE_SIDE_BAR_1:
            case TYPE_SIDE_BAR_2:
            case TYPE_SIDE_BAR_3:
                return true;
            case TYPE_IME:
                return false;
            default:
                return true;
        }
    }

    public void dump(String prefix, PrintWriter pw) {
    public void dump(String prefix, PrintWriter pw) {
        pw.println(prefix + "InsetsState");
        pw.println(prefix + "InsetsState");
        for (int i = mSources.size() - 1; i >= 0; i--) {
        for (int i = mSources.size() - 1; i >= 0; i--) {
Loading