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 Original line Diff line number Diff line
@@ -105,6 +105,13 @@
         screen. -->
         screen. -->
    <item name="half_opened_bouncer_height_ratio" type="dimen" format="float">0.0</item>
    <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
    <!-- 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
         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
         always translate from the side of the screen to the other (it will "jump" closer to the
+25 −0
Original line number Original line Diff line number Diff line
@@ -10,9 +10,34 @@
        motion:duration="0"
        motion:duration="0"
        motion:autoTransition="none"/>
        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 -->
    <!-- No changes to default layout -->
    <ConstraintSet android:id="@+id/single_constraints"/>
    <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">
    <ConstraintSet android:id="@+id/split_constraints">


        <Constraint
        <Constraint
+26 −1
Original line number Original line Diff line number Diff line
@@ -28,9 +28,33 @@
        motion:duration="0"
        motion:duration="0"
        motion:autoTransition="none" />
        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 -->
    <!-- No changes to default layout -->
    <ConstraintSet android:id="@+id/single_constraints"/>
    <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">
    <ConstraintSet android:id="@+id/split_constraints">


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


    </ConstraintSet>
    </ConstraintSet>

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


import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
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_APPEAR;
import static com.android.internal.jank.InteractionJankMonitor.CUJ_LOCKSCREEN_PIN_DISAPPEAR;
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 mDisappearAnimationUtils;
    private final DisappearAnimationUtils mDisappearAnimationUtilsLocked;
    private final DisappearAnimationUtils mDisappearAnimationUtilsLocked;
    @Nullable private MotionLayout mContainerMotionLayout;
    @Nullable private MotionLayout mContainerMotionLayout;
    // TODO (b/293252410) - usage of mContainerConstraintLayout should be removed
    //  when the flag is enabled/removed
    @Nullable private ConstraintLayout mContainerConstraintLayout;
    @Nullable private ConstraintLayout mContainerConstraintLayout;
    private int mDisappearYTranslation;
    private int mDisappearYTranslation;
    private View[][] mViews;
    private View[][] mViews;
@@ -59,7 +62,7 @@ public class KeyguardPINView extends KeyguardPinBasedInputView {
    private int mYTransOffset;
    private int mYTransOffset;
    private View mBouncerMessageArea;
    private View mBouncerMessageArea;
    private boolean mAlreadyUsingSplitBouncer = false;
    private boolean mAlreadyUsingSplitBouncer = false;
    private boolean mIsLockScreenLandscapeEnabled = false;
    private boolean mIsSmallLockScreenLandscapeEnabled = false;
    @DevicePostureInt private int mLastDevicePosture = DEVICE_POSTURE_UNKNOWN;
    @DevicePostureInt private int mLastDevicePosture = DEVICE_POSTURE_UNKNOWN;
    public static final long ANIMATION_DURATION = 650;
    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
    /** Use motion layout (new bouncer implementation) if LOCKSCREEN_ENABLE_LANDSCAPE flag is
     *  enabled, instead of constraint layout (old bouncer implementation) */
     *  enabled, instead of constraint layout (old bouncer implementation) */
    public void setIsLockScreenLandscapeEnabled(boolean isLockScreenLandscapeEnabled) {
    public void setIsLockScreenLandscapeEnabled(boolean isLockScreenLandscapeEnabled) {
        mIsLockScreenLandscapeEnabled = isLockScreenLandscapeEnabled;
        mIsSmallLockScreenLandscapeEnabled = isLockScreenLandscapeEnabled;
        findContainerLayout();
        findContainerLayout();
    }
    }


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


        if (mIsLockScreenLandscapeEnabled) {
        if (mIsSmallLockScreenLandscapeEnabled) {
            boolean useSplitBouncerAfterFold =
            boolean useSplitBouncerAfterFold =
                    mLastDevicePosture == DEVICE_POSTURE_CLOSED
                    mLastDevicePosture == DEVICE_POSTURE_CLOSED
                    && getResources().getConfiguration().orientation == ORIENTATION_LANDSCAPE
                    && 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...
        // Update the guideline based on the device posture...
        float halfOpenPercentage =
        float halfOpenPercentage =
                mContext.getResources().getFloat(R.dimen.half_opened_bouncer_height_ratio);
                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();
        ConstraintSet cs = new ConstraintSet();
        cs.clone(mContainerConstraintLayout);
        cs.clone(mContainerConstraintLayout);
        cs.setGuidelinePercent(R.id.pin_pad_top_guideline,
        cs.setGuidelinePercent(R.id.pin_pad_top_guideline,
                mLastDevicePosture == DEVICE_POSTURE_HALF_OPENED ? halfOpenPercentage : 0.0f);
                mLastDevicePosture == DEVICE_POSTURE_HALF_OPENED ? halfOpenPercentage : 0.0f);
        cs.applyTo(mContainerConstraintLayout);
        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).
    /** 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. */
     *  Only called when flag LANDSCAPE_ENABLE_LOCKSCREEN is enabled. */
    @Override
    @Override
    protected void updateConstraints(boolean useSplitBouncer) {
    protected void updateConstraints(boolean useSplitBouncer) {
        if (!mIsSmallLockScreenLandscapeEnabled) return;

        mAlreadyUsingSplitBouncer = useSplitBouncer;
        mAlreadyUsingSplitBouncer = useSplitBouncer;

        if (useSplitBouncer) {
        if (useSplitBouncer) {
            mContainerMotionLayout.jumpToState(R.id.split_constraints);
            mContainerMotionLayout.jumpToState(R.id.split_constraints);
            mContainerMotionLayout.setMaxWidth(Integer.MAX_VALUE);
            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 {
            } else {
                mContainerMotionLayout.jumpToState(R.id.single_constraints);
                mContainerMotionLayout.jumpToState(R.id.single_constraints);
            }
            mContainerMotionLayout.setMaxWidth(getResources()
            mContainerMotionLayout.setMaxWidth(getResources()
                    .getDimensionPixelSize(R.dimen.keyguard_security_width));
                    .getDimensionPixelSize(R.dimen.keyguard_security_width));
        }
        }
+55 −16
Original line number Original line Diff line number Diff line
@@ -16,6 +16,7 @@
package com.android.keyguard;
package com.android.keyguard;


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


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


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


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


    private void updateMargins() {
    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...
        // Update the guideline based on the device posture...
        float halfOpenPercentage =
        float halfOpenPercentage =
                mContext.getResources().getFloat(R.dimen.half_opened_bouncer_height_ratio);
                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();
        ConstraintSet cs = new ConstraintSet();
        cs.clone(mContainerConstraintLayout);
        cs.clone(mContainerConstraintLayout);
        cs.setGuidelinePercent(R.id.pattern_top_guideline,
        cs.setGuidelinePercent(R.id.pattern_top_guideline,
                mLastDevicePosture == DEVICE_POSTURE_HALF_OPENED ? halfOpenPercentage : 0.0f);
                mLastDevicePosture == DEVICE_POSTURE_HALF_OPENED ? halfOpenPercentage : 0.0f);
        cs.applyTo(mContainerConstraintLayout);
        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
    @Override
    protected void updateConstraints(boolean useSplitBouncer) {
    protected void updateConstraints(boolean useSplitBouncer) {
        if (!mIsSmallLockScreenLandscapeEnabled) return;

        mAlreadyUsingSplitBouncer = useSplitBouncer;
        mAlreadyUsingSplitBouncer = useSplitBouncer;

        if (useSplitBouncer) {
        if (useSplitBouncer) {
            mContainerMotionLayout.jumpToState(R.id.split_constraints);
            mContainerMotionLayout.jumpToState(R.id.split_constraints);
            mContainerMotionLayout.setMaxWidth(Integer.MAX_VALUE);
            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 {
            } else {
                mContainerMotionLayout.jumpToState(R.id.single_constraints);
                mContainerMotionLayout.jumpToState(R.id.single_constraints);
            }
            mContainerMotionLayout.setMaxWidth(getResources()
            mContainerMotionLayout.setMaxWidth(getResources()
                    .getDimensionPixelSize(R.dimen.biometric_auth_pattern_view_max_size));
                    .getDimensionPixelSize(R.dimen.biometric_auth_pattern_view_max_size));
        }
        }
Loading