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

Commit d27f922e authored by Tiger Huang's avatar Tiger Huang Committed by Automerger Merge Worker
Browse files

Merge "Only create InsetsSourceConsumer for InsetsSourceControl" into...

Merge "Only create InsetsSourceConsumer for InsetsSourceControl" into udc-qpr-dev am: 5143e36b am: 216e1fe6

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/24151848



Change-Id: Ia36d6fda7247fbeb628e565d506502226f098ea8
Signed-off-by: default avatarAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
parents 9bb258d8 216e1fe6
Loading
Loading
Loading
Loading
+32 −33
Original line number Diff line number Diff line
@@ -69,6 +69,7 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.graphics.SfVsyncFrameCallbackProvider;
import com.android.internal.inputmethod.ImeTracing;
import com.android.internal.inputmethod.SoftInputShowHideReason;
import com.android.internal.util.function.TriFunction;

import java.io.PrintWriter;
import java.lang.annotation.Retention;
@@ -77,7 +78,6 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.function.BiFunction;

/**
 * Implements {@link WindowInsetsController} on the client.
@@ -627,7 +627,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
    private final InsetsState mLastDispatchedState = new InsetsState();

    private final Rect mFrame = new Rect();
    private final BiFunction<InsetsController, InsetsSource, InsetsSourceConsumer> mConsumerCreator;
    private final TriFunction<InsetsController, Integer, Integer, InsetsSourceConsumer>
            mConsumerCreator;
    private final SparseArray<InsetsSourceConsumer> mSourceConsumers = new SparseArray<>();
    private final InsetsSourceConsumer mImeSourceConsumer;
    private final Host mHost;
@@ -695,13 +696,6 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation

                    // Don't change the indexes of the sources while traversing. Remove it later.
                    mPendingRemoveIndexes.add(index1);

                    // Remove the consumer as well except the IME one. IME consumer should always
                    // be there since we need to communicate with InputMethodManager no matter we
                    // have the source or not.
                    if (source1.getType() != ime()) {
                        mSourceConsumers.remove(source1.getId());
                    }
                }

                @Override
@@ -756,12 +750,12 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
            };

    public InsetsController(Host host) {
        this(host, (controller, source) -> {
            if (source.getType() == ime()) {
                return new ImeInsetsSourceConsumer(source.getId(), controller.mState,
        this(host, (controller, id, type) -> {
            if (type == ime()) {
                return new ImeInsetsSourceConsumer(id, controller.mState,
                        Transaction::new, controller);
            } else {
                return new InsetsSourceConsumer(source.getId(), source.getType(), controller.mState,
                return new InsetsSourceConsumer(id, type, controller.mState,
                        Transaction::new, controller);
            }
        }, host.getHandler());
@@ -769,7 +763,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation

    @VisibleForTesting
    public InsetsController(Host host,
            BiFunction<InsetsController, InsetsSource, InsetsSourceConsumer> consumerCreator,
            TriFunction<InsetsController, Integer, Integer, InsetsSourceConsumer> consumerCreator,
            Handler handler) {
        mHost = host;
        mConsumerCreator = consumerCreator;
@@ -821,7 +815,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
        };

        // Make mImeSourceConsumer always non-null.
        mImeSourceConsumer = getSourceConsumer(new InsetsSource(ID_IME, ime()));
        mImeSourceConsumer = getSourceConsumer(ID_IME, ime());
    }

    @VisibleForTesting
@@ -898,7 +892,12 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
                    cancelledUserAnimationTypes[0] |= type;
                }
            }
            getSourceConsumer(source).updateSource(source, animationType);
            final InsetsSourceConsumer consumer = mSourceConsumers.get(source.getId());
            if (consumer != null) {
                consumer.updateSource(source, animationType);
            } else {
                mState.addSource(source);
            }
            existingTypes |= type;
            if (source.isVisible()) {
                visibleTypes |= type;
@@ -1002,8 +1001,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation

        @InsetsType int controllableTypes = 0;
        int consumedControlCount = 0;
        final int[] showTypes = new int[1];
        final int[] hideTypes = new int[1];
        final @InsetsType int[] showTypes = new int[1];
        final @InsetsType int[] hideTypes = new int[1];

        // Ensure to update all existing source consumers
        for (int i = mSourceConsumers.size() - 1; i >= 0; i--) {
@@ -1019,15 +1018,12 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
            consumer.setControl(control, showTypes, hideTypes);
        }

        // Ensure to create source consumers if not available yet.
        if (consumedControlCount != mTmpControlArray.size()) {
            // Whoops! The server sent us some controls without sending corresponding sources.
            for (int i = mTmpControlArray.size() - 1; i >= 0; i--) {
                final InsetsSourceControl control = mTmpControlArray.valueAt(i);
                final InsetsSourceConsumer consumer = mSourceConsumers.get(control.getId());
                if (consumer == null) {
                    control.release(SurfaceControl::release);
                    Log.e(TAG, control + " has no consumer.");
                }
                getSourceConsumer(control.getId(), control.getType())
                        .setControl(control, showTypes, hideTypes);
            }
        }

@@ -1592,6 +1588,11 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
        if (type == ime()) {
            abortPendingImeControlRequest();
        }
        if (consumer.getType() != ime()) {
            // IME consumer should always be there since we need to communicate with
            // InputMethodManager no matter we have the control or not.
            mSourceConsumers.remove(consumer.getId());
        }
    }

    private void cancelAnimation(InsetsAnimationControlRunner control, boolean invokeCallback) {
@@ -1645,21 +1646,20 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
    }

    @VisibleForTesting
    public @NonNull InsetsSourceConsumer getSourceConsumer(InsetsSource source) {
        final int sourceId = source.getId();
        InsetsSourceConsumer consumer = mSourceConsumers.get(sourceId);
    public @NonNull InsetsSourceConsumer getSourceConsumer(int id, int type) {
        InsetsSourceConsumer consumer = mSourceConsumers.get(id);
        if (consumer != null) {
            return consumer;
        }
        if (source.getType() == ime() && mImeSourceConsumer != null) {
        if (type == ime() && mImeSourceConsumer != null) {
            // WindowInsets.Type.ime() should be only provided by one source.
            mSourceConsumers.remove(mImeSourceConsumer.getId());
            consumer = mImeSourceConsumer;
            consumer.setId(sourceId);
            consumer.setId(id);
        } else {
            consumer = mConsumerCreator.apply(this, source);
            consumer = mConsumerCreator.apply(this, id, type);
        }
        mSourceConsumers.put(sourceId, consumer);
        mSourceConsumers.put(id, consumer);
        return consumer;
    }

@@ -1668,8 +1668,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
        return mImeSourceConsumer;
    }

    @VisibleForTesting
    public void notifyVisibilityChanged() {
    void notifyVisibilityChanged() {
        mHost.notifyInsetsChanged();
    }

+6 −3
Original line number Diff line number Diff line
@@ -149,9 +149,12 @@ public class InsetsSourceConsumer {
            // Check if we need to restore server visibility.
            final InsetsSource localSource = mState.peekSource(mId);
            final InsetsSource serverSource = mController.getLastDispatchedState().peekSource(mId);
            if (localSource != null && serverSource != null
                    && localSource.isVisible() != serverSource.isVisible()) {
                localSource.setVisible(serverSource.isVisible());
            final boolean localVisible = localSource != null && localSource.isVisible();
            final boolean serverVisible = serverSource != null && serverSource.isVisible();
            if (localSource != null) {
                localSource.setVisible(serverVisible);
            }
            if (localVisible != serverVisible) {
                mController.notifyVisibilityChanged();
            }
        } else {
+15 −14
Original line number Diff line number Diff line
@@ -131,10 +131,10 @@ public class InsetsControllerTest {
            mTestClock = new OffsettableClock();
            mTestHandler = new TestHandler(null, mTestClock);
            mTestHost = spy(new TestHost(mViewRoot));
            mController = new InsetsController(mTestHost, (controller, source) -> {
                if (source.getType() == ime()) {
                    return new InsetsSourceConsumer(source.getId(), source.getType(),
                            controller.getState(), Transaction::new, controller) {
            mController = new InsetsController(mTestHost, (controller, id, type) -> {
                if (type == ime()) {
                    return new InsetsSourceConsumer(id, type, controller.getState(),
                            Transaction::new, controller) {

                        private boolean mImeRequestedShow;

@@ -150,8 +150,8 @@ public class InsetsControllerTest {
                        }
                    };
                } else {
                    return new InsetsSourceConsumer(source.getId(), source.getType(),
                            controller.getState(), Transaction::new, controller);
                    return new InsetsSourceConsumer(id, type, controller.getState(),
                            Transaction::new, controller);
                }
            }, mTestHandler);
            final Rect rect = new Rect(5, 5, 5, 5);
@@ -182,7 +182,8 @@ public class InsetsControllerTest {
    @Test
    public void testControlsChanged() {
        mController.onControlsChanged(createSingletonControl(ID_STATUS_BAR, statusBars()));
        assertNotNull(mController.getSourceConsumer(mStatusSource).getControl().getLeash());
        assertNotNull(
                mController.getSourceConsumer(ID_STATUS_BAR, statusBars()).getControl().getLeash());
        mController.addOnControllableInsetsChangedListener(
                ((controller, typeMask) -> assertEquals(statusBars(), typeMask)));
    }
@@ -194,7 +195,7 @@ public class InsetsControllerTest {
        mController.addOnControllableInsetsChangedListener(listener);
        mController.onControlsChanged(createSingletonControl(ID_STATUS_BAR, statusBars()));
        mController.onControlsChanged(new InsetsSourceControl[0]);
        assertNull(mController.getSourceConsumer(mStatusSource).getControl());
        assertNull(mController.getSourceConsumer(ID_STATUS_BAR, statusBars()).getControl());
        InOrder inOrder = Mockito.inOrder(listener);
        inOrder.verify(listener).onControllableInsetsChanged(eq(mController), eq(0));
        inOrder.verify(listener).onControllableInsetsChanged(eq(mController), eq(statusBars()));
@@ -254,7 +255,7 @@ public class InsetsControllerTest {
        // only the original thread that created view hierarchy can touch its views
        InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
            mController.setSystemDrivenInsetsAnimationLoggingListener(loggingListener);
            mController.getSourceConsumer(mImeSource).onWindowFocusGained(true);
            mController.getSourceConsumer(ID_IME, ime()).onWindowFocusGained(true);
            // since there is no focused view, forcefully make IME visible.
            mController.show(WindowInsets.Type.ime(), true /* fromIme */, null /* statsToken */);
            // When using the animation thread, this must not invoke onReady()
@@ -271,7 +272,7 @@ public class InsetsControllerTest {
        prepareControls();

        InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
            mController.getSourceConsumer(mImeSource).onWindowFocusGained(true);
            mController.getSourceConsumer(ID_IME, ime()).onWindowFocusGained(true);
            // since there is no focused view, forcefully make IME visible.
            mController.show(WindowInsets.Type.ime(), true /* fromIme */, null /* statsToken */);
            mController.show(all());
@@ -284,7 +285,7 @@ public class InsetsControllerTest {
            mController.hide(all());
            mController.cancelExistingAnimations();
            assertEquals(0, mController.getRequestedVisibleTypes() & types);
            mController.getSourceConsumer(mImeSource).onWindowFocusLost();
            mController.getSourceConsumer(ID_IME, ime()).onWindowFocusLost();
        });
        InstrumentationRegistry.getInstrumentation().waitForIdleSync();
    }
@@ -294,14 +295,14 @@ public class InsetsControllerTest {
        InsetsSourceControl ime = createControl(ID_IME, ime());
        mController.onControlsChanged(new InsetsSourceControl[] { ime });
        InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
            mController.getSourceConsumer(mImeSource).onWindowFocusGained(true);
            mController.getSourceConsumer(ID_IME, ime()).onWindowFocusGained(true);
            mController.show(WindowInsets.Type.ime(), true /* fromIme */, null /* statsToken */);
            mController.cancelExistingAnimations();
            assertTrue(isRequestedVisible(mController, ime()));
            mController.hide(ime(), true /* fromIme */, null /* statsToken */);
            mController.cancelExistingAnimations();
            assertFalse(isRequestedVisible(mController, ime()));
            mController.getSourceConsumer(mImeSource).onWindowFocusLost();
            mController.getSourceConsumer(ID_IME, ime()).onWindowFocusLost();
        });
        InstrumentationRegistry.getInstrumentation().waitForIdleSync();
    }
@@ -914,7 +915,7 @@ public class InsetsControllerTest {
            // Simulate IME insets is not controllable
            mController.onControlsChanged(new InsetsSourceControl[0]);
            final InsetsSourceConsumer imeInsetsConsumer =
                    mController.getSourceConsumer(mImeSource);
                    mController.getSourceConsumer(ID_IME, ime());
            assertNull(imeInsetsConsumer.getControl());

            // Verify IME requested visibility should be updated to IME consumer from controller.
+5 −7
Original line number Diff line number Diff line
@@ -219,10 +219,10 @@ public class InsetsSourceConsumerTest {
        InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
            InsetsState state = new InsetsState();
            ViewRootInsetsControllerHost host = new ViewRootInsetsControllerHost(mViewRoot);
            InsetsController insetsController = new InsetsController(host, (controller, source) -> {
                if (source.getType() == ime()) {
            InsetsController insetsController = new InsetsController(host, (ic, id, type) -> {
                if (type == ime()) {
                    return new InsetsSourceConsumer(ID_IME, ime(), state,
                            () -> mMockTransaction, controller) {
                            () -> mMockTransaction, ic) {
                        @Override
                        public int requestShow(boolean fromController,
                                ImeTracker.Token statsToken) {
@@ -230,11 +230,9 @@ public class InsetsSourceConsumerTest {
                        }
                    };
                }
                return new InsetsSourceConsumer(source.getId(), source.getType(),
                        controller.getState(), Transaction::new, controller);
                return new InsetsSourceConsumer(id, type, ic.getState(), Transaction::new, ic);
            }, host.getHandler());
            InsetsSource imeSource = new InsetsSource(ID_IME, ime());
            InsetsSourceConsumer imeConsumer = insetsController.getSourceConsumer(imeSource);
            InsetsSourceConsumer imeConsumer = insetsController.getSourceConsumer(ID_IME, ime());

            // Initial IME insets source control with its leash.
            imeConsumer.setControl(new InsetsSourceControl(ID_IME, ime(), mLeash,