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

Commit 281be883 authored by Ming-Shin Lu's avatar Ming-Shin Lu Committed by Android (Google) Code Review
Browse files

Merge "Improve IME hiding animation when uncloked by password" into sc-dev

parents e0519c10 4a550b3a
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -185,8 +185,8 @@ public abstract class KeyguardAbsKeyInputViewController<T extends KeyguardAbsKey
            if (timeoutMs == 0) {
                mMessageAreaController.setMessage(mView.getWrongPasswordStringId());
            }
            mView.resetPasswordText(true /* animate */, false /* announce deletion if no match */);
        }
        mView.resetPasswordText(true /* animate */, !matched /* announce deletion if no match */);
    }

    protected void verifyPasswordAndUnlock() {
+13 −1
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ import com.android.internal.jank.InteractionJankMonitor;
 * A Base class for all Keyguard password/pattern/pin related inputs.
 */
public abstract class KeyguardInputView extends LinearLayout {
    private Runnable mOnFinishImeAnimationRunnable;

    public KeyguardInputView(Context context) {
        super(context);
@@ -47,7 +48,8 @@ public abstract class KeyguardInputView extends LinearLayout {

    abstract CharSequence getTitle();

    void animateForIme(float interpolatedFraction) {
    void animateForIme(float interpolatedFraction, boolean appearingAnim) {
        return;
    }

    boolean disallowInterceptTouch(MotionEvent event) {
@@ -85,4 +87,14 @@ public abstract class KeyguardInputView extends LinearLayout {
        };
    }

    public void setOnFinishImeAnimationRunnable(Runnable onFinishImeAnimationRunnable) {
        mOnFinishImeAnimationRunnable = onFinishImeAnimationRunnable;
    }

    public void runOnFinishImeAnimationRunnable() {
        if (mOnFinishImeAnimationRunnable != null) {
            mOnFinishImeAnimationRunnable.run();
            mOnFinishImeAnimationRunnable = null;
        }
    }
}
+70 −2
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package com.android.keyguard;

import static android.view.WindowInsets.Type.ime;

import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_DEVICE_ADMIN;
import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_NONE;
import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_PREPARE_FOR_UPDATE;
@@ -23,15 +25,25 @@ import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_RESTART;
import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_TIMEOUT;
import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_USER_REQUEST;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Insets;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.WindowInsetsAnimationControlListener;
import android.view.WindowInsetsAnimationController;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.android.internal.widget.LockscreenCredential;
import com.android.internal.widget.TextViewInputDisabler;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
/**
 * Displays an alphanumeric (latin-1) key entry for the user to enter
@@ -41,6 +53,8 @@ public class KeyguardPasswordView extends KeyguardAbsKeyInputView {

    private final int mDisappearYTranslation;

    private static final long IME_DISAPPEAR_DURATION_MS = 125;

    // A delay constant to be used in a workaround for the situation where InputMethodManagerService
    // is not switched to the new user yet.
    // TODO: Remove this by ensuring such a race condition never happens.
@@ -150,9 +164,63 @@ public class KeyguardPasswordView extends KeyguardAbsKeyInputView {
    }

    @Override
    public void animateForIme(float interpolatedFraction) {
    public boolean startDisappearAnimation(Runnable finishRunnable) {
        getWindowInsetsController().controlWindowInsetsAnimation(ime(),
                100,
                Interpolators.LINEAR, null, new WindowInsetsAnimationControlListener() {

                    @Override
                    public void onReady(@NonNull WindowInsetsAnimationController controller,
                            int types) {
                        ValueAnimator anim = ValueAnimator.ofFloat(1f, 0f);
                        anim.addUpdateListener(animation -> {
                            if (controller.isCancelled()) {
                                return;
                            }
                            Insets shownInsets = controller.getShownStateInsets();
                            Insets insets = Insets.add(shownInsets, Insets.of(0, 0, 0,
                                    (int) (-shownInsets.bottom / 4
                                            * anim.getAnimatedFraction())));
                            controller.setInsetsAndAlpha(insets,
                                    (float) animation.getAnimatedValue(),
                                    anim.getAnimatedFraction());
                        });
                        anim.addListener(new AnimatorListenerAdapter() {
                            @Override
                            public void onAnimationStart(Animator animation) {
                            }

                            @Override
                            public void onAnimationEnd(Animator animation) {
                                controller.finish(false);
                                runOnFinishImeAnimationRunnable();
                                finishRunnable.run();
                            }
                        });
                        anim.setInterpolator(Interpolators.FAST_OUT_LINEAR_IN);
                        anim.start();
                    }

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

                    @Override
                    public void onCancelled(
                            @Nullable WindowInsetsAnimationController controller) {
                    }
                });
        return true;
    }


    @Override
    public void animateForIme(float interpolatedFraction, boolean appearingAnim) {
        animate().cancel();
        setAlpha(Math.max(interpolatedFraction, getAlpha()));
        setAlpha(appearingAnim
                ? Math.max(interpolatedFraction, getAlpha())
                : 1 - interpolatedFraction);
    }

    @Override
+16 −6
Original line number Diff line number Diff line
@@ -189,23 +189,22 @@ public class KeyguardPasswordViewController
            return;
        }
        if (wasDisabled) {
            mInputMethodManager.showSoftInput(mPasswordEntry, InputMethodManager.SHOW_IMPLICIT);
            showInput();
        }
    }

    @Override
    public void onResume(int reason) {
        super.onResume(reason);

        mPasswordEntry.requestFocus();
        if (reason != KeyguardSecurityView.SCREEN_ON || mShowImeAtScreenOn) {
            showInput();
        }
    }

    private void showInput() {
        mPasswordEntry.post(() -> {
            if (mPasswordEntry.isFocused() && mView.isShown()) {
        mView.post(() -> {
            if (mView.isShown()) {
                mPasswordEntry.requestFocus();
                mInputMethodManager.showSoftInput(
                        mPasswordEntry, InputMethodManager.SHOW_IMPLICIT);
            }
@@ -214,7 +213,18 @@ public class KeyguardPasswordViewController

    @Override
    public void onPause() {
        if (!mPasswordEntry.isVisibleToUser()) {
            // Reset all states directly and then hide IME when the screen turned off.
            super.onPause();
        } else {
            // In order not to break the IME hide animation by resetting states too early after
            // the password checked, make sure resetting states after the IME hiding animation
            // finished.
            mView.setOnFinishImeAnimationRunnable(() -> {
                mPasswordEntry.clearFocus();
                super.onPause();
            });
        }
        mInputMethodManager.hideSoftInputFromWindow(mView.getWindowToken(), 0);
    }

+27 −80
Original line number Diff line number Diff line
@@ -23,11 +23,9 @@ import static java.lang.Integer.max;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.graphics.Insets;
import android.graphics.Rect;
import android.provider.Settings;
import android.util.AttributeSet;
@@ -42,12 +40,9 @@ import android.view.ViewConfiguration;
import android.view.ViewPropertyAnimator;
import android.view.WindowInsets;
import android.view.WindowInsetsAnimation;
import android.view.WindowInsetsAnimationControlListener;
import android.view.WindowInsetsAnimationController;
import android.view.WindowManager;
import android.widget.FrameLayout;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import androidx.dynamicanimation.animation.DynamicAnimation;
@@ -130,6 +125,9 @@ public class KeyguardSecurityContainer extends FrameLayout {
                        WindowInsetsAnimation.Bounds bounds) {
                    if (!mDisappearAnimRunning) {
                        beginJankInstrument(InteractionJankMonitor.CUJ_LOCKSCREEN_PASSWORD_APPEAR);
                    } else {
                        beginJankInstrument(
                                InteractionJankMonitor.CUJ_LOCKSCREEN_PASSWORD_DISAPPEAR);
                    }
                    mSecurityViewFlipper.getBoundsOnScreen(mFinalBounds);
                    return bounds;
@@ -138,10 +136,12 @@ public class KeyguardSecurityContainer extends FrameLayout {
                @Override
                public WindowInsets onProgress(WindowInsets windowInsets,
                        List<WindowInsetsAnimation> list) {
                    if (mDisappearAnimRunning) {
                        mSecurityViewFlipper.setTranslationY(
                                mInitialBounds.bottom - mFinalBounds.bottom);
                    } else {
                    float start = mDisappearAnimRunning
                            ? -(mFinalBounds.bottom - mInitialBounds.bottom)
                            : mInitialBounds.bottom - mFinalBounds.bottom;
                    float end = mDisappearAnimRunning
                            ? -((mFinalBounds.bottom - mInitialBounds.bottom) * 0.75f)
                            : 0f;
                    int translationY = 0;
                    float interpolatedFraction = 1f;
                    for (WindowInsetsAnimation animation : list) {
@@ -151,12 +151,13 @@ public class KeyguardSecurityContainer extends FrameLayout {
                        interpolatedFraction = animation.getInterpolatedFraction();

                        final int paddingBottom = (int) MathUtils.lerp(
                                    mInitialBounds.bottom - mFinalBounds.bottom, 0,
                                start, end,
                                interpolatedFraction);
                        translationY += paddingBottom;
                    }
                        mSecurityViewFlipper.animateForIme(translationY, interpolatedFraction);
                    }
                    mSecurityViewFlipper.animateForIme(translationY, interpolatedFraction,
                            !mDisappearAnimRunning);

                    return windowInsets;
                }

@@ -164,7 +165,10 @@ public class KeyguardSecurityContainer extends FrameLayout {
                public void onEnd(WindowInsetsAnimation animation) {
                    if (!mDisappearAnimRunning) {
                        endJankInstrument(InteractionJankMonitor.CUJ_LOCKSCREEN_PASSWORD_APPEAR);
                        mSecurityViewFlipper.animateForIme(0, /* interpolatedFraction */ 1f);
                        mSecurityViewFlipper.animateForIme(0, /* interpolatedFraction */ 1f,
                                true /* appearingAnim */);
                    } else {
                        endJankInstrument(InteractionJankMonitor.CUJ_LOCKSCREEN_PASSWORD_DISAPPEAR);
                    }
                }
            };
@@ -522,63 +526,6 @@ public class KeyguardSecurityContainer extends FrameLayout {

    public void startDisappearAnimation(SecurityMode securitySelection) {
        mDisappearAnimRunning = true;
        if (securitySelection == SecurityMode.Password) {
            mSecurityViewFlipper.getWindowInsetsController().controlWindowInsetsAnimation(ime(),
                    IME_DISAPPEAR_DURATION_MS,
                    Interpolators.LINEAR, null, new WindowInsetsAnimationControlListener() {


                        @Override
                        public void onReady(@NonNull WindowInsetsAnimationController controller,
                                int types) {
                            ValueAnimator anim = ValueAnimator.ofFloat(1f, 0f);
                            anim.addUpdateListener(animation -> {
                                if (controller.isCancelled()) {
                                    return;
                                }
                                Insets shownInsets = controller.getShownStateInsets();
                                Insets insets = Insets.add(shownInsets, Insets.of(0, 0, 0,
                                        (int) (-shownInsets.bottom / 4
                                                * anim.getAnimatedFraction())));
                                controller.setInsetsAndAlpha(insets,
                                        (float) animation.getAnimatedValue(),
                                        anim.getAnimatedFraction());
                            });
                            anim.addListener(new AnimatorListenerAdapter() {
                                @Override
                                public void onAnimationStart(Animator animation) {
                                    beginJankInstrument(
                                            InteractionJankMonitor
                                                    .CUJ_LOCKSCREEN_PASSWORD_DISAPPEAR);
                                }

                                @Override
                                public void onAnimationEnd(Animator animation) {
                                    endJankInstrument(
                                            InteractionJankMonitor
                                                    .CUJ_LOCKSCREEN_PASSWORD_DISAPPEAR);
                                    controller.finish(false);
                                }
                            });
                            anim.setDuration(IME_DISAPPEAR_DURATION_MS);
                            anim.setInterpolator(Interpolators.FAST_OUT_LINEAR_IN);
                            anim.start();
                        }

                        @Override
                        public void onFinished(
                                @NonNull WindowInsetsAnimationController controller) {
                            mDisappearAnimRunning = false;
                        }

                        @Override
                        public void onCancelled(
                                @Nullable WindowInsetsAnimationController controller) {
                            cancelJankInstrument(
                                    InteractionJankMonitor.CUJ_LOCKSCREEN_PASSWORD_DISAPPEAR);
                        }
                    });
        }
    }

    private void beginJankInstrument(int cuj) {
Loading