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

Commit a12ea56b authored by Jorim Jaggi's avatar Jorim Jaggi Committed by Tiger Huang
Browse files

Window Manager Flag Migration (3/n)

Adds fake control which is an InsetsSourceControl without a leash in it.

Fake control will be sent to the client when bars are shown transiently.
So the client thinks it still have the control over the bars, but moving
the bars won't take effect.

InsetsController.show still works and dispatches the modified state to
the server. The server can then listen to that state change, and abort
transient showing mode, start a new animation, and send over the new
control with an actual leash to the client.

Bug: 118118435
Test: atest InsetsSourceProviderTest
            InsetsStateControllerTest
            WindowStateTests
Change-Id: I8db5942e9f951e2652d4a3a34c9fde2efe5b9858
parent 8f0ecddf
Loading
Loading
Loading
Loading
+6 −3
Original line number Diff line number Diff line
@@ -26,7 +26,6 @@ import android.annotation.Nullable;
import android.graphics.Insets;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.os.UidProto.Sync;
import android.util.ArraySet;
import android.util.SparseArray;
import android.util.SparseIntArray;
@@ -40,7 +39,6 @@ import android.view.WindowManager.LayoutParams;
import com.android.internal.annotations.VisibleForTesting;

import java.util.ArrayList;
import java.util.function.Function;
import java.util.function.Supplier;

/**
@@ -238,7 +236,12 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll
            addTranslationToMatrix(side, offset, mTmpMatrix, mTmpFrame);

            state.getSource(source.getType()).setFrame(mTmpFrame);
            surfaceParams.add(new SurfaceParams(leash, 1f, mTmpMatrix, null, 0, 0f, inset != 0));

            // If the system is controlling the insets source, the leash can be null.
            if (leash != null) {
                surfaceParams.add(new SurfaceParams(leash, 1f /* alpha */, mTmpMatrix,
                        null /* windowCrop */, 0 /* layer */, 0f /* cornerRadius*/, inset != 0));
            }
        }
    }

+1 −1
Original line number Diff line number Diff line
@@ -167,7 +167,7 @@ public class InsetsSourceConsumer {
    }

    private void applyHiddenToControl() {
        if (mSourceControl == null) {
        if (mSourceControl == null || mSourceControl.getLeash() == null) {
            return;
        }

+10 −3
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package android.view;

import android.annotation.Nullable;
import android.graphics.Point;
import android.os.Parcel;
import android.os.Parcelable;
@@ -28,10 +29,10 @@ import android.view.InsetsState.InternalInsetType;
public class InsetsSourceControl implements Parcelable {

    private final @InternalInsetType int mType;
    private final SurfaceControl mLeash;
    private final @Nullable SurfaceControl mLeash;
    private final Point mSurfacePosition;

    public InsetsSourceControl(@InternalInsetType int type, SurfaceControl leash,
    public InsetsSourceControl(@InternalInsetType int type, @Nullable SurfaceControl leash,
            Point surfacePosition) {
        mType = type;
        mLeash = leash;
@@ -42,7 +43,13 @@ public class InsetsSourceControl implements Parcelable {
        return mType;
    }

    public SurfaceControl getLeash() {
    /**
     * Gets the leash for controlling insets source. If the system is controlling the insets source,
     * for example, transient bars, the client will receive fake controls without leash in it.
     *
     * @return the leash.
     */
    public @Nullable SurfaceControl getLeash() {
        return mLeash;
    }

+24 −3
Original line number Diff line number Diff line
@@ -51,8 +51,11 @@ class InsetsSourceProvider {
    private final @NonNull InsetsSource mSource;
    private final DisplayContent mDisplayContent;
    private final InsetsStateController mStateController;
    private final InsetsSourceControl mFakeControl;
    private @Nullable InsetsSourceControl mControl;
    private @Nullable InsetsControlTarget mControlTarget;
    private @Nullable InsetsControlTarget mFakeControlTarget;

    private @Nullable ControlAdapter mAdapter;
    private WindowState mWin;
    private TriConsumer<DisplayFrames, WindowState, Rect> mFrameProvider;
@@ -73,6 +76,8 @@ class InsetsSourceProvider {
        mSource = source;
        mDisplayContent = displayContent;
        mStateController = stateController;
        mFakeControl = new InsetsSourceControl(source.getType(), null /* leash */,
                new Point());

        final int type = source.getType();
        if (type == TYPE_TOP_BAR || type == TYPE_NAVIGATION_BAR) {
@@ -150,6 +155,16 @@ class InsetsSourceProvider {
                && !mWin.mGivenInsetsPending);
    }

    /**
     * @see InsetsStateController#onControlFakeTargetChanged(int, InsetsControlTarget)
     */
    void updateControlForFakeTarget(@Nullable InsetsControlTarget fakeTarget) {
        if (fakeTarget == mFakeControlTarget) {
            return;
        }
        mFakeControlTarget = fakeTarget;
    }

    void updateControlForTarget(@Nullable InsetsControlTarget target, boolean force) {
        if (mWin == null) {
            mControlTarget = target;
@@ -199,9 +214,15 @@ class InsetsSourceProvider {
        mSource.setVisible(mServerVisible && mClientVisible);
    }

    InsetsSourceControl getControl() {
    InsetsSourceControl getControl(InsetsControlTarget target) {
        if (target == mControlTarget) {
            return mControl;
        }
        if (target == mFakeControlTarget) {
            return mFakeControl;
        }
        return null;
    }

    boolean isClientVisible() {
        return sNewInsetsMode == NEW_INSETS_MODE_NONE || mClientVisible;
@@ -257,5 +278,5 @@ class InsetsSourceProvider {
        @Override
        public void writeToProto(ProtoOutputStream proto) {
        }
    };
    }
}
+53 −8
Original line number Diff line number Diff line
@@ -20,6 +20,8 @@ import static android.view.InsetsState.InternalInsetType;
import static android.view.InsetsState.TYPE_IME;
import static android.view.InsetsState.TYPE_NAVIGATION_BAR;
import static android.view.InsetsState.TYPE_TOP_BAR;
import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL;
import static android.view.ViewRootImpl.sNewInsetsMode;

import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -47,6 +49,10 @@ class InsetsStateController {
    private final ArrayMap<InsetsControlTarget, ArrayList<Integer>> mControlTargetTypeMap =
            new ArrayMap<>();
    private final SparseArray<InsetsControlTarget> mTypeControlTargetMap = new SparseArray<>();

    /** @see #onControlFakeTargetChanged */
    private final SparseArray<InsetsControlTarget> mTypeFakeControlTargetMap = new SparseArray<>();

    private final ArraySet<InsetsControlTarget> mPendingControlChanged = new ArraySet<>();

    private final Consumer<WindowState> mDispatchInsetsChanged = w -> {
@@ -93,7 +99,7 @@ class InsetsStateController {
        final int size = controlled.size();
        final InsetsSourceControl[] result = new InsetsSourceControl[size];
        for (int i = 0; i < size; i++) {
            result[i] = mProviders.get(controlled.get(i)).getControl();
            result[i] = mProviders.get(controlled.get(i)).getControl(target);
        }
        return result;
    }
@@ -157,7 +163,8 @@ class InsetsStateController {

    void notifyControlRevoked(@NonNull InsetsControlTarget previousControlTarget,
            InsetsSourceProvider provider) {
        removeFromControlMaps(previousControlTarget, provider.getSource().getType());
        removeFromControlMaps(previousControlTarget, provider.getSource().getType(),
                false /* fake */);
    }

    private void onControlChanged(@InternalInsetType int type,
@@ -175,17 +182,47 @@ class InsetsStateController {
        }
        provider.updateControlForTarget(target, false /* force */);
        if (previous != null) {
            removeFromControlMaps(previous, type);
            removeFromControlMaps(previous, type, false /* fake */);
            mPendingControlChanged.add(previous);
        }
        if (target != null) {
            addToControlMaps(target, type);
            addToControlMaps(target, type, false /* fake */);
            mPendingControlChanged.add(target);
        }
    }

    /**
     * The fake target saved here will be used to pretend to the app that it's still under control
     * of the bars while it's not really, but we still need to find out the apps intentions around
     * showing/hiding. For example, when the transient bars are showing, and the fake target
     * requests to show system bars, the transient state will be aborted.
     */
    void onControlFakeTargetChanged(@InternalInsetType  int type,
            @Nullable InsetsControlTarget fakeTarget) {
        if (sNewInsetsMode != NEW_INSETS_MODE_FULL) {
            return;
        }
        final InsetsControlTarget previous = mTypeFakeControlTargetMap.get(type);
        if (fakeTarget == previous) {
            return;
        }
        final InsetsSourceProvider provider = mProviders.get(type);
        if (provider == null) {
            return;
        }
        provider.updateControlForFakeTarget(fakeTarget);
        if (previous != null) {
            removeFromControlMaps(previous, type, true /* fake */);
            mPendingControlChanged.add(previous);
        }
        if (fakeTarget != null) {
            addToControlMaps(fakeTarget, type, true /* fake */);
            mPendingControlChanged.add(fakeTarget);
        }
    }

    private void removeFromControlMaps(@NonNull InsetsControlTarget target,
            @InternalInsetType int type) {
            @InternalInsetType int type, boolean fake) {
        final ArrayList<Integer> array = mControlTargetTypeMap.get(target);
        if (array == null) {
            return;
@@ -194,16 +231,24 @@ class InsetsStateController {
        if (array.isEmpty()) {
            mControlTargetTypeMap.remove(target);
        }
        if (fake) {
            mTypeFakeControlTargetMap.remove(type);
        } else {
            mTypeControlTargetMap.remove(type);
        }
    }

    private void addToControlMaps(@NonNull InsetsControlTarget target,
            @InternalInsetType int type) {
            @InternalInsetType int type, boolean fake) {
        final ArrayList<Integer> array = mControlTargetTypeMap.computeIfAbsent(target,
                key -> new ArrayList<>());
        array.add(type);
        if (fake) {
            mTypeFakeControlTargetMap.put(type, target);
        } else {
            mTypeControlTargetMap.put(type, target);
        }
    }

    void notifyControlChanged(InsetsControlTarget target) {
        mPendingControlChanged.add(target);
Loading