diff options
| author | 2023-08-28 16:26:05 +0000 | |
|---|---|---|
| committer | 2023-09-18 12:54:05 +0000 | |
| commit | 461f259ffaa5e6d71cb6f1d7b16b1fccafa1cb35 (patch) | |
| tree | 8636b340f7fad1fe910ded2b929181b977ddd3f2 | |
| parent | 3544524bad816c0344cbfe65282ff1f45a0cccb2 (diff) | |
Pattern bouncer refactor: motion layout - change constraints on rotate
- refactored Pattern bouncer into a single motion layout
- transition between landscape or portrait constrains on rotate
why are we doing this?
- to add support for landscape bouncers on small screens
"Split" bouncer constraints (https://hsv.googleplex.com/5351602346000384) will be used on small landscape screens only
"Single" bouncer constraints (https://hsv.googleplex.com/6007067992129536) are used otherwise, such as for large screen port/land and small screens port - this is the same as the previous behaviour.
Use of "split or single" bouncer constraints is not strictly related to device orientation.
Flag:
WHEN FLAG OFF - old portrait layout always used
WHEN FLAG ON - new layout uses, constraints updated to match current orientation (once per rotate, once on device posture change, and once after inflate)
Bug: 293252410
Bug: 296567469
Bug: 297863911
Test: KeyguardPatternViewControllerTest
Change-Id: If57b60482377eaf9ac3131fff9a136c92af67da0
6 files changed, 244 insertions, 18 deletions
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_pattern_motion_layout.xml b/packages/SystemUI/res-keyguard/layout/keyguard_pattern_motion_layout.xml new file mode 100644 index 000000000000..b562d7b5ee48 --- /dev/null +++ b/packages/SystemUI/res-keyguard/layout/keyguard_pattern_motion_layout.xml @@ -0,0 +1,109 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +** +** Copyright 2023, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License") +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<!-- This file is needed when flag lockscreen.enable_landscape is on + Required for landscape lockscreen on small screens. --> +<com.android.keyguard.KeyguardPatternView + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:androidprv="http://schemas.android.com/apk/res-auto" + android:id="@+id/keyguard_pattern_view" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_gravity="center_horizontal|bottom" + android:clipChildren="false" + android:clipToPadding="false" + android:orientation="vertical"> + + <!-- Layout here is visually identical to the previous keyguard_pattern_view. + I.E., 'constraints here effectively the same as the previous linear layout' --> + <androidx.constraintlayout.motion.widget.MotionLayout + android:id="@+id/pattern_container" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_gravity="center_horizontal" + android:clipChildren="false" + android:clipToPadding="false" + android:layoutDirection="ltr" + android:orientation="vertical" + android:maxWidth = "@dimen/biometric_auth_pattern_view_max_size" + androidprv:layoutDescription="@xml/keyguard_pattern_scene"> + + <!-- Guideline need to align pattern right of centre, + when on small screen landscape layout --> + <androidx.constraintlayout.widget.Guideline + android:id="@+id/pattern_center_guideline" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:orientation="vertical" + androidprv:layout_constraintGuide_percent="0.5" /> + + <LinearLayout + android:id="@+id/keyguard_bouncer_message_container" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:clipChildren="false" + android:clipToPadding="false" + android:layoutDirection="ltr" + android:orientation="vertical" + androidprv:layout_constraintTop_toTopOf="parent"> + + <include layout="@layout/keyguard_bouncer_message_area" /> + + <com.android.systemui.bouncer.ui.BouncerMessageView + android:id="@+id/bouncer_message_view" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical" /> + + </LinearLayout> + + <androidx.constraintlayout.widget.Guideline + android:id="@+id/pattern_top_guideline" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:orientation="horizontal" + androidprv:layout_constraintGuide_percent="0" /> + + <com.android.internal.widget.LockPatternView + android:id="@+id/lockPatternView" + android:layout_width="0dp" + android:layout_height="0dp" + android:layout_marginBottom="8dp" + androidprv:layout_constraintVertical_bias="1.0" + androidprv:layout_constraintDimensionRatio="1.0" + androidprv:layout_constraintStart_toStartOf="parent" + androidprv:layout_constraintBottom_toTopOf="@+id/keyguard_selector_fade_container" + androidprv:layout_constraintEnd_toEndOf="parent" + androidprv:layout_constraintVertical_chainStyle="packed" + androidprv:layout_constraintTop_toBottomOf="@id/pattern_top_guideline"/> + + <include + android:id="@+id/keyguard_selector_fade_container" + layout="@layout/keyguard_eca" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginBottom="@dimen/keyguard_eca_bottom_margin" + android:layout_marginTop="@dimen/keyguard_eca_top_margin" + android:orientation="vertical" + androidprv:layout_constraintBottom_toBottomOf="parent" + androidprv:layout_constraintTop_toBottomOf="@+id/lockPatternView" /> + + </androidx.constraintlayout.motion.widget.MotionLayout> + +</com.android.keyguard.KeyguardPatternView>
\ No newline at end of file diff --git a/packages/SystemUI/res-keyguard/xml/keyguard_pattern_scene.xml b/packages/SystemUI/res-keyguard/xml/keyguard_pattern_scene.xml new file mode 100644 index 000000000000..6112411402c4 --- /dev/null +++ b/packages/SystemUI/res-keyguard/xml/keyguard_pattern_scene.xml @@ -0,0 +1,47 @@ +<?xml version="1.0" encoding="utf-8"?> +<MotionScene + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:motion="http://schemas.android.com/apk/res-auto" + xmlns:androidprv="http://schemas.android.com/apk/res-auto"> + + <Transition + motion:constraintSetStart="@id/single_constraints" + motion:constraintSetEnd="@+id/split_constraints" + motion:duration="0" + motion:autoTransition="none"/> + + <!-- No changes to default layout --> + <ConstraintSet android:id="@+id/single_constraints"/> + + <ConstraintSet android:id="@+id/split_constraints"> + + <Constraint + android:id="@+id/keyguard_bouncer_message_container" + android:layout_width="0dp" + android:layout_height="wrap_content" + androidprv:layout_constraintEnd_toStartOf="@+id/pattern_center_guideline" + androidprv:layout_constraintStart_toStartOf="parent" + androidprv:layout_constraintTop_toTopOf="parent" /> + <Constraint + android:id="@+id/lockPatternView" + android:layout_width="0dp" + android:layout_height="0dp" + androidprv:layout_constraintDimensionRatio="1.0" + androidprv:layout_constraintVertical_bias="0.5" + androidprv:layout_constraintBottom_toBottomOf="parent" + androidprv:layout_constraintEnd_toEndOf="parent" + androidprv:layout_constraintStart_toStartOf="@+id/pattern_center_guideline" + androidprv:layout_constraintTop_toTopOf="parent" + android:layout_marginBottom="0dp" /> + <Constraint + android:id="@+id/keyguard_selector_fade_container" + android:layout_width="0dp" + android:layout_height="wrap_content" + androidprv:layout_constraintBottom_toBottomOf="parent" + androidprv:layout_constraintEnd_toStartOf="@+id/pattern_center_guideline" + androidprv:layout_constraintStart_toStartOf="parent" + android:layout_marginBottom="@dimen/keyguard_eca_bottom_margin" + android:layout_marginTop="@dimen/keyguard_eca_top_margin" /> + + </ConstraintSet> +</MotionScene>
\ No newline at end of file diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java index 2bdf46e1309d..56706b5a7135 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java @@ -15,9 +15,13 @@ */ package com.android.keyguard; +import static android.content.res.Configuration.ORIENTATION_LANDSCAPE; + +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_UNKNOWN; +import android.annotation.Nullable; import android.content.Context; import android.content.res.Configuration; import android.graphics.Rect; @@ -29,6 +33,7 @@ import android.view.View; import android.view.animation.AnimationUtils; import android.view.animation.Interpolator; +import androidx.constraintlayout.motion.widget.MotionLayout; import androidx.constraintlayout.widget.ConstraintLayout; import androidx.constraintlayout.widget.ConstraintSet; @@ -75,7 +80,10 @@ public class KeyguardPatternView extends KeyguardInputView BouncerKeyguardMessageArea mSecurityMessageDisplay; private View mEcaView; - private ConstraintLayout mContainer; + @Nullable private MotionLayout mContainerMotionLayout; + @Nullable private ConstraintLayout mContainerConstraintLayout; + private boolean mAlreadyUsingSplitBouncer = false; + private boolean mIsLockScreenLandscapeEnabled = false; @DevicePostureInt private int mLastDevicePosture = DEVICE_POSTURE_UNKNOWN; public KeyguardPatternView(Context context) { @@ -98,16 +106,44 @@ public class KeyguardPatternView extends KeyguardInputView mContext, android.R.interpolator.fast_out_linear_in)); } + /** + * 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; + findContainerLayout(); + } + + private void findContainerLayout() { + if (mIsLockScreenLandscapeEnabled) { + mContainerMotionLayout = findViewById(R.id.pattern_container); + } else { + mContainerConstraintLayout = findViewById(R.id.pattern_container); + } + } + @Override protected void onConfigurationChanged(Configuration newConfig) { updateMargins(); } void onDevicePostureChanged(@DevicePostureInt int posture) { - if (mLastDevicePosture != posture) { - mLastDevicePosture = posture; - updateMargins(); + if (mLastDevicePosture == posture) return; + mLastDevicePosture = posture; + + if (mIsLockScreenLandscapeEnabled) { + boolean useSplitBouncerAfterFold = + mLastDevicePosture == DEVICE_POSTURE_CLOSED + && getResources().getConfiguration().orientation == ORIENTATION_LANDSCAPE + && getResources().getBoolean(R.bool.update_bouncer_constraints); + + if (mAlreadyUsingSplitBouncer != useSplitBouncerAfterFold) { + updateConstraints(useSplitBouncerAfterFold); + } } + + updateMargins(); } private void updateMargins() { @@ -115,12 +151,36 @@ public class KeyguardPatternView extends KeyguardInputView float halfOpenPercentage = mContext.getResources().getFloat(R.dimen.half_opened_bouncer_height_ratio); - ConstraintSet cs = new ConstraintSet(); - cs.clone(mContainer); - cs.setGuidelinePercent(R.id.pattern_top_guideline, - mLastDevicePosture == DEVICE_POSTURE_HALF_OPENED - ? halfOpenPercentage : 0.0f); - cs.applyTo(mContainer); + 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); + } + } + + /** + * Updates the keyguard view's constraints (single or split constraints). + * Split constraints are only used for small landscape screens. + * Only called when flag LANDSCAPE_ENABLE_LOCKSCREEN is enabled. + */ + @Override + protected void updateConstraints(boolean useSplitBouncer) { + mAlreadyUsingSplitBouncer = useSplitBouncer; + if (useSplitBouncer) { + mContainerMotionLayout.jumpToState(R.id.split_constraints); + mContainerMotionLayout.setMaxWidth(Integer.MAX_VALUE); + } else { + mContainerMotionLayout.jumpToState(R.id.single_constraints); + mContainerMotionLayout.setMaxWidth(getResources() + .getDimensionPixelSize(R.dimen.biometric_auth_pattern_view_max_size)); + } } @Override @@ -130,7 +190,6 @@ public class KeyguardPatternView extends KeyguardInputView mLockPatternView = findViewById(R.id.lockPatternView); mEcaView = findViewById(R.id.keyguard_selector_fade_container); - mContainer = findViewById(R.id.pattern_container); } @Override @@ -209,7 +268,7 @@ public class KeyguardPatternView extends KeyguardInputView getAnimationListener(InteractionJankMonitor.CUJ_LOCKSCREEN_PATTERN_DISAPPEAR)); DisappearAnimationUtils disappearAnimationUtils = needsSlowUnlockTransition - ? mDisappearAnimationUtilsLocked : mDisappearAnimationUtils; + ? mDisappearAnimationUtilsLocked : mDisappearAnimationUtils; disappearAnimationUtils.startAnimation2d(mLockPatternView.getCellStates(), () -> { enableClipping(true); @@ -220,7 +279,7 @@ public class KeyguardPatternView extends KeyguardInputView if (!TextUtils.isEmpty(mSecurityMessageDisplay.getText())) { mDisappearAnimationUtils.createAnimation(mSecurityMessageDisplay, 0, (long) (200 * durationMultiplier), - - mDisappearAnimationUtils.getStartTranslation() * 3, + -mDisappearAnimationUtils.getStartTranslation() * 3, false /* appearing */, mDisappearAnimationUtils.getInterpolator(), null /* finishRunnable */); @@ -229,9 +288,16 @@ public class KeyguardPatternView extends KeyguardInputView } private void enableClipping(boolean enable) { - setClipChildren(enable); - mContainer.setClipToPadding(enable); - mContainer.setClipChildren(enable); + if (mContainerConstraintLayout != null) { + setClipChildren(enable); + mContainerConstraintLayout.setClipToPadding(enable); + mContainerConstraintLayout.setClipChildren(enable); + } + if (mContainerMotionLayout != null) { + setClipChildren(enable); + mContainerMotionLayout.setClipToPadding(enable); + mContainerMotionLayout.setClipChildren(enable); + } } @Override diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java index a30b4479fe95..98312b11e9d6 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java @@ -18,6 +18,7 @@ package com.android.keyguard; import static com.android.internal.util.LatencyTracker.ACTION_CHECK_CREDENTIAL; import static com.android.internal.util.LatencyTracker.ACTION_CHECK_CREDENTIAL_UNLOCKED; +import static com.android.systemui.flags.Flags.LOCKSCREEN_ENABLE_LANDSCAPE; import android.content.res.ColorStateList; import android.os.AsyncTask; @@ -205,6 +206,8 @@ public class KeyguardPatternViewController mLatencyTracker = latencyTracker; mFalsingCollector = falsingCollector; mEmergencyButtonController = emergencyButtonController; + view.setIsLockScreenLandscapeEnabled( + featureFlags.isEnabled(LOCKSCREEN_ENABLE_LANDSCAPE)); mLockPatternView = mView.findViewById(R.id.lockPatternView); mPostureController = postureController; } diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipperController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipperController.java index 5528837f153c..f18504c28609 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipperController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipperController.java @@ -155,7 +155,7 @@ public class KeyguardSecurityViewFlipperController private int getLayoutIdFor(SecurityMode securityMode) { // TODO (b/297863911, b/297864907) - implement motion layout for other bouncers switch (securityMode) { - case Pattern: return R.layout.keyguard_pattern_view; + case Pattern: return R.layout.keyguard_pattern_motion_layout; case PIN: return R.layout.keyguard_pin_motion_layout; case Password: return R.layout.keyguard_password_motion_layout; case SimPin: return R.layout.keyguard_sim_pin_view; diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPatternViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPatternViewControllerTest.kt index 93048a5787b2..0ef9f4533015 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPatternViewControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPatternViewControllerTest.kt @@ -94,9 +94,10 @@ class KeyguardPatternViewControllerTest : SysuiTestCase() { .thenReturn(mKeyguardMessageAreaController) fakeFeatureFlags = FakeFeatureFlags() fakeFeatureFlags.set(Flags.REVAMPED_BOUNCER_MESSAGES, false) + fakeFeatureFlags.set(Flags.LOCKSCREEN_ENABLE_LANDSCAPE, false) mKeyguardPatternView = View.inflate(mContext, R.layout.keyguard_pattern_view, null) as KeyguardPatternView - + mKeyguardPatternView.setIsLockScreenLandscapeEnabled(false) mKeyguardPatternViewController = KeyguardPatternViewController( mKeyguardPatternView, |