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

Commit 792903f9 authored by axfordjc's avatar axfordjc Committed by Jonathon Axford
Browse files

Bouncer half fold animation for pin/pattern

- previously, guideline height was set in code causing pin/pattern to jump between sizes
- now, with the new use of motion layout, a transition to 'half folded constraints' is used
- half_folded_single_constraints is the same as single_constraints but the emergency button has a smaller bottom margin and the guideline is lowered causing the pin/pattern to shrink
- note, the final size/layout of pin/pattern after the half-fold animation is not identical to previous behaviour. But, this is ok or even an improvement - anyhow, it can be easily tweaked.

Guarded by flag "lockscreen.enable_landscape" (b/293252410)

Bug: 293252410
Fixes: 299106220

Test: PattenBouncerFoldableUIScreenshotTest, PattenBouncerFoldableScreen, PinBouncerFoldableUIScreenshotTest, PinBouncerFoldableScreen
Change-Id: I7094cb592d2d1a81ebb9055bef60d03358ac5f85
parent 2e75d1bb
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -105,6 +105,13 @@
         screen. -->
    <item name="half_opened_bouncer_height_ratio" type="dimen" format="float">0.0</item>

    <!-- Proportion of the screen height to use to set the maximum height of the bouncer to when
     the device is in the DEVICE_POSTURE_HALF_OPENED posture.

     This value is only used when motion layout bouncer is used - when flag
     landscape.enable_lockscreen (b/293252410) is on -->
    <item name="motion_layout_half_fold_bouncer_height_ratio" type="dimen" format="float">0.55</item>

    <!-- The actual amount of translation that is applied to the security when it animates from one
         side of the screen to the other in one-handed or user switcher mode. Note that it will
         always translate from the side of the screen to the other (it will "jump" closer to the
+25 −0
Original line number Diff line number Diff line
@@ -10,9 +10,34 @@
        motion:duration="0"
        motion:autoTransition="none"/>

    <Transition
        motion:constraintSetStart="@id/single_constraints"
        motion:constraintSetEnd="@+id/half_folded_single_constraints"
        motion:duration="@integer/material_motion_duration_short_1"
        motion:autoTransition="none"/>

    <!-- No changes to default layout -->
    <ConstraintSet android:id="@+id/single_constraints"/>

    <ConstraintSet android:id="@+id/half_folded_single_constraints">

        <Constraint
            android:id="@+id/pattern_top_guideline"
            androidprv:layout_constraintGuide_percent=
                "@dimen/motion_layout_half_fold_bouncer_height_ratio"/>

        <Constraint
            android:id="@+id/keyguard_selector_fade_container"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="0dp"
            android:layout_marginTop="@dimen/keyguard_eca_top_margin"
            android:orientation="vertical"
            androidprv:layout_constraintBottom_toBottomOf="parent"
            androidprv:layout_constraintTop_toBottomOf="@+id/flow1"/>

    </ConstraintSet>

    <ConstraintSet android:id="@+id/split_constraints">

        <Constraint
+26 −1
Original line number Diff line number Diff line
@@ -28,9 +28,33 @@
        motion:duration="0"
        motion:autoTransition="none" />

    <Transition
        motion:constraintSetStart="@id/single_constraints"
        motion:constraintSetEnd="@+id/half_folded_single_constraints"
        motion:duration="@integer/material_motion_duration_short_1" />

    <!-- No changes to default layout -->
    <ConstraintSet android:id="@+id/single_constraints"/>

    <ConstraintSet android:id="@+id/half_folded_single_constraints">

        <Constraint
            android:id="@+id/pin_pad_top_guideline"
            androidprv:layout_constraintGuide_percent=
                "@dimen/motion_layout_half_fold_bouncer_height_ratio"/>

        <Constraint
            android:id="@+id/keyguard_selector_fade_container"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="0dp"
            android:layout_marginTop="@dimen/keyguard_eca_top_margin"
            android:orientation="vertical"
            androidprv:layout_constraintBottom_toBottomOf="parent"
            androidprv:layout_constraintTop_toBottomOf="@+id/flow1"/>

    </ConstraintSet>

    <ConstraintSet android:id="@+id/split_constraints">

        <Constraint
@@ -68,4 +92,5 @@
            android:layout_marginTop="@dimen/keyguard_eca_top_margin" />

    </ConstraintSet>

</MotionScene>
 No newline at end of file
+55 −16
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.keyguard;

import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;

import static com.android.internal.jank.InteractionJankMonitor.CUJ_LOCKSCREEN_PIN_APPEAR;
import static com.android.internal.jank.InteractionJankMonitor.CUJ_LOCKSCREEN_PIN_DISAPPEAR;
@@ -52,6 +53,8 @@ public class KeyguardPINView extends KeyguardPinBasedInputView {
    private final DisappearAnimationUtils mDisappearAnimationUtils;
    private final DisappearAnimationUtils mDisappearAnimationUtilsLocked;
    @Nullable private MotionLayout mContainerMotionLayout;
    // TODO (b/293252410) - usage of mContainerConstraintLayout should be removed
    //  when the flag is enabled/removed
    @Nullable private ConstraintLayout mContainerConstraintLayout;
    private int mDisappearYTranslation;
    private View[][] mViews;
@@ -59,7 +62,7 @@ public class KeyguardPINView extends KeyguardPinBasedInputView {
    private int mYTransOffset;
    private View mBouncerMessageArea;
    private boolean mAlreadyUsingSplitBouncer = false;
    private boolean mIsLockScreenLandscapeEnabled = false;
    private boolean mIsSmallLockScreenLandscapeEnabled = false;
    @DevicePostureInt private int mLastDevicePosture = DEVICE_POSTURE_UNKNOWN;
    public static final long ANIMATION_DURATION = 650;

@@ -87,12 +90,12 @@ public class KeyguardPINView extends KeyguardPinBasedInputView {
    /** Use motion layout (new bouncer implementation) if LOCKSCREEN_ENABLE_LANDSCAPE flag is
     *  enabled, instead of constraint layout (old bouncer implementation) */
    public void setIsLockScreenLandscapeEnabled(boolean isLockScreenLandscapeEnabled) {
        mIsLockScreenLandscapeEnabled = isLockScreenLandscapeEnabled;
        mIsSmallLockScreenLandscapeEnabled = isLockScreenLandscapeEnabled;
        findContainerLayout();
    }

    private void findContainerLayout() {
        if (mIsLockScreenLandscapeEnabled) {
        if (mIsSmallLockScreenLandscapeEnabled) {
            mContainerMotionLayout = findViewById(R.id.pin_container);
        } else {
            mContainerConstraintLayout = findViewById(R.id.pin_container);
@@ -109,7 +112,7 @@ public class KeyguardPINView extends KeyguardPinBasedInputView {
        if (mLastDevicePosture == posture) return;
        mLastDevicePosture = posture;

        if (mIsLockScreenLandscapeEnabled) {
        if (mIsSmallLockScreenLandscapeEnabled) {
            boolean useSplitBouncerAfterFold =
                    mLastDevicePosture == DEVICE_POSTURE_CLOSED
                    && getResources().getConfiguration().orientation == ORIENTATION_LANDSCAPE
@@ -166,22 +169,46 @@ public class KeyguardPINView extends KeyguardPinBasedInputView {
            }
        }

        if (mIsSmallLockScreenLandscapeEnabled) {
            updateHalfFoldedConstraints();
        } else {
            updateHalfFoldedGuideline();
        }
    }

    private void updateHalfFoldedConstraints() {
        // Update the constraints based on the device posture...
        if (mAlreadyUsingSplitBouncer) return;

        boolean shouldCollapsePin =
                mLastDevicePosture == DEVICE_POSTURE_HALF_OPENED
                        && mContext.getResources().getConfiguration().orientation
                        == ORIENTATION_PORTRAIT;

        int expectedMotionLayoutState = shouldCollapsePin
                ? R.id.half_folded_single_constraints
                : R.id.single_constraints;

        transitionToMotionLayoutState(expectedMotionLayoutState);
    }

    // TODO (b/293252410) - this method can be removed when the flag is enabled/removed
    private void updateHalfFoldedGuideline() {
        // Update the guideline based on the device posture...
        float halfOpenPercentage =
                mContext.getResources().getFloat(R.dimen.half_opened_bouncer_height_ratio);

        if (mIsLockScreenLandscapeEnabled) {
            ConstraintSet cs = mContainerMotionLayout.getConstraintSet(R.id.single_constraints);
            cs.setGuidelinePercent(R.id.pin_pad_top_guideline,
                    mLastDevicePosture == DEVICE_POSTURE_HALF_OPENED ? halfOpenPercentage : 0.0f);
            cs.applyTo(mContainerMotionLayout);
        } else {
        ConstraintSet cs = new ConstraintSet();
        cs.clone(mContainerConstraintLayout);
        cs.setGuidelinePercent(R.id.pin_pad_top_guideline,
                mLastDevicePosture == DEVICE_POSTURE_HALF_OPENED ? halfOpenPercentage : 0.0f);
        cs.applyTo(mContainerConstraintLayout);
    }

    private void transitionToMotionLayoutState(int state) {
        if (mContainerMotionLayout.getCurrentState() != state) {
            mContainerMotionLayout.transitionToState(state);
        }
    }

    /** Updates the keyguard view's constraints (single or split constraints).
@@ -189,12 +216,24 @@ public class KeyguardPINView extends KeyguardPinBasedInputView {
     *  Only called when flag LANDSCAPE_ENABLE_LOCKSCREEN is enabled. */
    @Override
    protected void updateConstraints(boolean useSplitBouncer) {
        if (!mIsSmallLockScreenLandscapeEnabled) return;

        mAlreadyUsingSplitBouncer = useSplitBouncer;

        if (useSplitBouncer) {
            mContainerMotionLayout.jumpToState(R.id.split_constraints);
            mContainerMotionLayout.setMaxWidth(Integer.MAX_VALUE);
        } else {
            boolean useHalfFoldedConstraints =
                    mLastDevicePosture == DEVICE_POSTURE_HALF_OPENED
                            && mContext.getResources().getConfiguration().orientation
                            == ORIENTATION_PORTRAIT;

            if (useHalfFoldedConstraints) {
                mContainerMotionLayout.jumpToState(R.id.half_folded_single_constraints);
            } else {
                mContainerMotionLayout.jumpToState(R.id.single_constraints);
            }
            mContainerMotionLayout.setMaxWidth(getResources()
                    .getDimensionPixelSize(R.dimen.keyguard_security_width));
        }
+55 −16
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@
package com.android.keyguard;

import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;

import static com.android.systemui.statusbar.policy.DevicePostureController.DEVICE_POSTURE_CLOSED;
import static com.android.systemui.statusbar.policy.DevicePostureController.DEVICE_POSTURE_HALF_OPENED;
@@ -81,9 +82,11 @@ public class KeyguardPatternView extends KeyguardInputView
    BouncerKeyguardMessageArea mSecurityMessageDisplay;
    private View mEcaView;
    @Nullable private MotionLayout mContainerMotionLayout;
    // TODO (b/293252410) - usage of mContainerConstraintLayout should be removed
    //  when the flag is enabled/removed
    @Nullable private ConstraintLayout mContainerConstraintLayout;
    private boolean mAlreadyUsingSplitBouncer = false;
    private boolean mIsLockScreenLandscapeEnabled = false;
    private boolean mIsSmallLockScreenLandscapeEnabled = false;
    @DevicePostureInt private int mLastDevicePosture = DEVICE_POSTURE_UNKNOWN;

    public KeyguardPatternView(Context context) {
@@ -111,12 +114,12 @@ public class KeyguardPatternView extends KeyguardInputView
     * enabled, instead of constraint layout (old bouncer implementation)
     */
    public void setIsLockScreenLandscapeEnabled(boolean isLockScreenLandscapeEnabled) {
        mIsLockScreenLandscapeEnabled = isLockScreenLandscapeEnabled;
        mIsSmallLockScreenLandscapeEnabled = isLockScreenLandscapeEnabled;
        findContainerLayout();
    }

    private void findContainerLayout() {
        if (mIsLockScreenLandscapeEnabled) {
        if (mIsSmallLockScreenLandscapeEnabled) {
            mContainerMotionLayout = findViewById(R.id.pattern_container);
        } else {
            mContainerConstraintLayout = findViewById(R.id.pattern_container);
@@ -132,7 +135,7 @@ public class KeyguardPatternView extends KeyguardInputView
        if (mLastDevicePosture == posture) return;
        mLastDevicePosture = posture;

        if (mIsLockScreenLandscapeEnabled) {
        if (mIsSmallLockScreenLandscapeEnabled) {
            boolean useSplitBouncerAfterFold =
                    mLastDevicePosture == DEVICE_POSTURE_CLOSED
                    && getResources().getConfiguration().orientation == ORIENTATION_LANDSCAPE
@@ -147,22 +150,46 @@ public class KeyguardPatternView extends KeyguardInputView
    }

    private void updateMargins() {
        if (mIsSmallLockScreenLandscapeEnabled) {
            updateHalfFoldedConstraints();
        } else {
            updateHalfFoldedGuideline();
        }
    }

    private void updateHalfFoldedConstraints() {
        // Update the constraints based on the device posture...
        if (mAlreadyUsingSplitBouncer) return;

        boolean shouldCollapsePattern =
                mLastDevicePosture == DEVICE_POSTURE_HALF_OPENED
                        && mContext.getResources().getConfiguration().orientation
                        == ORIENTATION_PORTRAIT;

        int expectedMotionLayoutState = shouldCollapsePattern
                ? R.id.half_folded_single_constraints
                : R.id.single_constraints;

        transitionToMotionLayoutState(expectedMotionLayoutState);
    }

    // TODO (b/293252410) - this method can be removed when the flag is enabled/removed
    private void updateHalfFoldedGuideline() {
        // Update the guideline based on the device posture...
        float halfOpenPercentage =
                mContext.getResources().getFloat(R.dimen.half_opened_bouncer_height_ratio);

        if (mIsLockScreenLandscapeEnabled) {
            ConstraintSet cs = mContainerMotionLayout.getConstraintSet(R.id.single_constraints);
            cs.setGuidelinePercent(R.id.pattern_top_guideline,
                    mLastDevicePosture == DEVICE_POSTURE_HALF_OPENED ? halfOpenPercentage : 0.0f);
            cs.applyTo(mContainerMotionLayout);
        } else {
        ConstraintSet cs = new ConstraintSet();
        cs.clone(mContainerConstraintLayout);
        cs.setGuidelinePercent(R.id.pattern_top_guideline,
                mLastDevicePosture == DEVICE_POSTURE_HALF_OPENED ? halfOpenPercentage : 0.0f);
        cs.applyTo(mContainerConstraintLayout);
    }

    private void transitionToMotionLayoutState(int state) {
        if (mContainerMotionLayout.getCurrentState() != state) {
            mContainerMotionLayout.transitionToState(state);
        }
    }

    /**
@@ -172,12 +199,24 @@ public class KeyguardPatternView extends KeyguardInputView
     */
    @Override
    protected void updateConstraints(boolean useSplitBouncer) {
        if (!mIsSmallLockScreenLandscapeEnabled) return;

        mAlreadyUsingSplitBouncer = useSplitBouncer;

        if (useSplitBouncer) {
            mContainerMotionLayout.jumpToState(R.id.split_constraints);
            mContainerMotionLayout.setMaxWidth(Integer.MAX_VALUE);
        } else {
            boolean useHalfFoldedConstraints =
                    mLastDevicePosture == DEVICE_POSTURE_HALF_OPENED
                            && mContext.getResources().getConfiguration().orientation
                            == ORIENTATION_PORTRAIT;

            if (useHalfFoldedConstraints) {
                mContainerMotionLayout.jumpToState(R.id.half_folded_single_constraints);
            } else {
                mContainerMotionLayout.jumpToState(R.id.single_constraints);
            }
            mContainerMotionLayout.setMaxWidth(getResources()
                    .getDimensionPixelSize(R.dimen.biometric_auth_pattern_view_max_size));
        }
Loading