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

Commit 8ca2881e authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Automerger Merge Worker
Browse files

Merge "Defer updating InsetsSource.mFrame while animating" into rvc-dev am: d3a0b895

Change-Id: I2b4b14ca96521757989d79b684478a8c3f39e0af
parents 8629cfaf d3a0b895
Loading
Loading
Loading
Loading
+24 −6
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package android.view;

import static android.view.InsetsState.ITYPE_IME;
import static android.view.InsetsState.toInternalType;
import static android.view.InsetsState.toPublicType;
import static android.view.WindowInsets.Type.all;
import static android.view.WindowInsets.Type.ime;
@@ -26,8 +27,6 @@ import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_BEHAVIOR_CONT
import android.animation.AnimationHandler;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
import android.animation.TypeEvaluator;
import android.animation.ValueAnimator;
import android.annotation.IntDef;
@@ -38,11 +37,9 @@ import android.graphics.Rect;
import android.os.CancellationSignal;
import android.os.Handler;
import android.os.RemoteException;
import android.renderscript.Sampler.Value;
import android.util.ArraySet;
import android.util.Log;
import android.util.Pair;
import android.util.Property;
import android.util.SparseArray;
import android.view.InsetsSourceConsumer.ShowResult;
import android.view.InsetsState.InternalInsetsType;
@@ -467,7 +464,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
        if (!localStateChanged && mLastDispachedState.equals(state)) {
            return false;
        }
        mState.set(state);
        updateState(state);
        mLastDispachedState.set(state, true /* copySources */);
        applyLocalVisibilityOverride();
        if (localStateChanged) {
@@ -479,6 +476,20 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
        return true;
    }

    private void updateState(InsetsState newState) {
        mState.setDisplayFrame(newState.getDisplayFrame());
        for (int i = newState.getSourcesCount() - 1; i >= 0; i--) {
            InsetsSource source = newState.sourceAt(i);
            getSourceConsumer(source.getType()).updateSource(source);
        }
        for (int i = mState.getSourcesCount() - 1; i >= 0; i--) {
            InsetsSource source = mState.sourceAt(i);
            if (newState.peekSource(source.getType()) == null) {
                mState.removeSource(source.getType());
            }
        }
    }

    /**
     * @see InsetsState#calculateInsets
     */
@@ -858,8 +869,15 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
            control.cancel();
        }
        for (int i = mRunningAnimations.size() - 1; i >= 0; i--) {
            if (mRunningAnimations.get(i).runner == control) {
            RunningAnimation runningAnimation = mRunningAnimations.get(i);
            if (runningAnimation.runner == control) {
                mRunningAnimations.remove(i);
                ArraySet<Integer> types = toInternalType(control.getTypes());
                for (int j = types.size() - 1; j >= 0; j--) {
                    if (getSourceConsumer(types.valueAt(j)).notifyAnimationFinished()) {
                        mViewRoot.notifyInsetsChanged();
                    }
                }
                break;
            }
        }
+36 −0
Original line number Diff line number Diff line
@@ -16,11 +16,13 @@

package android.view;

import static android.view.InsetsController.ANIMATION_TYPE_NONE;
import static android.view.InsetsController.AnimationType;
import static android.view.InsetsState.toPublicType;

import android.annotation.IntDef;
import android.annotation.Nullable;
import android.graphics.Rect;
import android.view.InsetsState.InternalInsetsType;
import android.view.SurfaceControl.Transaction;
import android.view.WindowInsets.Type.InsetsType;
@@ -64,6 +66,8 @@ public class InsetsSourceConsumer {
    private final Supplier<Transaction> mTransactionSupplier;
    private @Nullable InsetsSourceControl mSourceControl;
    private boolean mHasWindowFocus;
    private Rect mPendingFrame;
    private Rect mPendingVisibleFrame;

    public InsetsSourceConsumer(@InternalInsetsType int type, InsetsState state,
            Supplier<Transaction> transactionSupplier, InsetsController controller) {
@@ -215,6 +219,38 @@ public class InsetsSourceConsumer {
        // no-op for types that always return ShowResult#SHOW_IMMEDIATELY.
    }

    void updateSource(InsetsSource newSource) {
        InsetsSource source = mState.peekSource(mType);
        if (source == null || mController.getAnimationType(mType) == ANIMATION_TYPE_NONE
                || source.getFrame().equals(newSource.getFrame())) {
            mState.addSource(newSource);
            return;
        }

        // Frame is changing while animating. Keep note of the new frame but keep existing frame
        // until animaition is finished.
        newSource = new InsetsSource(newSource);
        mPendingFrame = new Rect(newSource.getFrame());
        mPendingVisibleFrame = newSource.getVisibleFrame() != null
                ? new Rect(newSource.getVisibleFrame())
                : null;
        newSource.setFrame(source.getFrame());
        newSource.setVisibleFrame(source.getVisibleFrame());
        mState.addSource(newSource);
    }

    boolean notifyAnimationFinished() {
        if (mPendingFrame != null) {
            InsetsSource source = mState.getSource(mType);
            source.setFrame(mPendingFrame);
            source.setVisibleFrame(mPendingVisibleFrame);
            mPendingFrame = null;
            mPendingVisibleFrame = null;
            return true;
        }
        return false;
    }

    /**
     * Sets requested visibility from the client, regardless of whether we are able to control it at
     * the moment.
+27 −0
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
@@ -638,6 +639,32 @@ public class InsetsControllerTest {
        });
    }

    @Test
    public void testFrameUpdateDuringAnimation() {
        InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {

            mController.onControlsChanged(createSingletonControl(ITYPE_IME));

            // Pretend IME is calling
            mController.show(ime(), true /* fromIme */);

            InsetsState copy = new InsetsState(mController.getState(), true /* copySources */);
            copy.getSource(ITYPE_IME).setFrame(0, 1, 2, 3);
            copy.getSource(ITYPE_IME).setVisibleFrame(new Rect(4, 5, 6, 7));
            mController.onStateChanged(copy);
            assertNotEquals(new Rect(0, 1, 2, 3),
                    mController.getState().getSource(ITYPE_IME).getFrame());
            assertNotEquals(new Rect(4, 5, 6, 7),
                    mController.getState().getSource(ITYPE_IME).getVisibleFrame());
            mController.cancelExistingAnimation();
            assertEquals(new Rect(0, 1, 2, 3),
                    mController.getState().getSource(ITYPE_IME).getFrame());
            assertEquals(new Rect(4, 5, 6, 7),
                    mController.getState().getSource(ITYPE_IME).getVisibleFrame());
        });
        InstrumentationRegistry.getInstrumentation().waitForIdleSync();
    }

    private void waitUntilNextFrame() throws Exception {
        final CountDownLatch latch = new CountDownLatch(1);
        Choreographer.getMainThreadInstance().postCallback(Choreographer.CALLBACK_COMMIT,
+37 −54
Original line number Diff line number Diff line
@@ -18,7 +18,6 @@ package com.google.android.test.windowinsetstests;

import static android.view.WindowInsets.Type.ime;
import static android.view.WindowInsetsAnimation.Callback.DISPATCH_MODE_STOP;

import static java.lang.Math.max;
import static java.lang.Math.min;

@@ -31,6 +30,7 @@ import android.content.Context;
import android.graphics.Insets;
import android.os.Bundle;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
@@ -44,11 +44,11 @@ import android.view.WindowInsetsController.OnControllableInsetsChangedListener;
import android.view.animation.LinearInterpolator;
import android.widget.LinearLayout;

import androidx.appcompat.app.AppCompatActivity;

import java.util.ArrayList;
import java.util.List;

import androidx.appcompat.app.AppCompatActivity;

public class WindowInsetsActivity extends AppCompatActivity {

    private View mRoot;
@@ -191,28 +191,9 @@ public class WindowInsetsActivity extends AppCompatActivity {
                mTransitions.forEach(it -> it.onFinish(animation));
            }
        });
    }

    @Override
    public void onResume() {
        super.onResume();
        // TODO: move this to onCreate once setDecorFitsSystemWindows can be safely called there.
        getWindow().getDecorView().post(() -> getWindow().setDecorFitsSystemWindows(false));
    }

    @Override
    public void onAttachedToWindow() {
        super.onAttachedToWindow();
        getWindow().getInsetsController().addOnControllableInsetsChangedListener(
                new OnControllableInsetsChangedListener() {

                    boolean hasControl = false;
                    @Override
                    public void onControllableInsetsChanged(WindowInsetsController controller,
                            int types) {
                        if ((types & ime()) != 0 && !hasControl) {
                            hasControl = true;
                            controller.controlWindowInsetsAnimation(ime(), -1,
        findViewById(R.id.floating_action_button).setOnClickListener(
                v -> v.getWindowInsetsController().controlWindowInsetsAnimation(ime(), -1,
                new LinearInterpolator(), null /* cancellationSignal */,
                new WindowInsetsAnimationControlListener() {
                    @Override
@@ -237,18 +218,20 @@ public class WindowInsetsActivity extends AppCompatActivity {
                    }

                    @Override
                                        public void onFinished(
                                                WindowInsetsAnimationController controller) {
                    public void onCancelled(WindowInsetsAnimationController controller) {
                    }

                    @Override
                                        public void onCancelled(
                                                WindowInsetsAnimationController controller) {
                                        }
                                    });
                    public void onFinished(WindowInsetsAnimationController controller) {
                    }
                }));
    }
                });

    @Override
    public void onResume() {
        super.onResume();
        // TODO: move this to onCreate once setDecorFitsSystemWindows can be safely called there.
        getWindow().getDecorView().post(() -> getWindow().setDecorFitsSystemWindows(false));
    }

    static class Transition {