Merge "2/2 Making bouncer shift on double tap when user chooser is visible" into tm-qpr-dev am: 2a8b3b47a4

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/18950670

Change-Id: Id0760eb365ec9b4722de17cfde0e17c9323ec0d9
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Michał Brzeziński
2022-06-24 15:19:08 +00:00
committed by Automerger Merge Worker
3 changed files with 240 additions and 170 deletions

View File

@@ -102,12 +102,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>
<!-- The actual amount of translation that is applied to the bouncer 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 mode. Note that it will always translate from side of the screen to the other in one-handed or user switcher mode. Note that it will
the side of the screen to the other (it will "jump" closer to the destination while the always translate from the side of the screen to the other (it will "jump" closer to the
opacity is zero), but this controls how much motion will actually be applied to it while destination while the opacity is zero), but this controls how much motion will actually be
animating. Larger values will cause it to move "faster" while fading out/in. --> applied to it while animating. Larger values will cause it to move "faster" while
<dimen name="one_handed_bouncer_move_animation_translation">120dp</dimen> fading out/in. -->
<dimen name="security_shift_animation_translation">120dp</dimen>
<dimen name="bouncer_user_switcher_header_text_size">20sp</dimen> <dimen name="bouncer_user_switcher_header_text_size">20sp</dimen>

View File

@@ -94,6 +94,7 @@ import com.android.systemui.util.settings.GlobalSettings;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.function.Consumer;
public class KeyguardSecurityContainer extends FrameLayout { public class KeyguardSecurityContainer extends FrameLayout {
static final int USER_TYPE_PRIMARY = 1; static final int USER_TYPE_PRIMARY = 1;
@@ -128,12 +129,12 @@ public class KeyguardSecurityContainer extends FrameLayout {
private static final long IME_DISAPPEAR_DURATION_MS = 125; private static final long IME_DISAPPEAR_DURATION_MS = 125;
// The duration of the animation to switch bouncer sides. // The duration of the animation to switch security sides.
private static final long BOUNCER_HANDEDNESS_ANIMATION_DURATION_MS = 500; private static final long SECURITY_SHIFT_ANIMATION_DURATION_MS = 500;
// How much of the switch sides animation should be dedicated to fading the bouncer out. The // How much of the switch sides animation should be dedicated to fading the security out. The
// remainder will fade it back in again. // remainder will fade it back in again.
private static final float BOUNCER_HANDEDNESS_ANIMATION_FADE_OUT_PROPORTION = 0.2f; private static final float SECURITY_SHIFT_ANIMATION_FADE_OUT_PROPORTION = 0.2f;
@VisibleForTesting @VisibleForTesting
KeyguardSecurityViewFlipper mSecurityViewFlipper; KeyguardSecurityViewFlipper mSecurityViewFlipper;
@@ -796,12 +797,16 @@ public class KeyguardSecurityContainer extends FrameLayout {
* screen devices * screen devices
*/ */
abstract static class SidedSecurityMode implements ViewMode { abstract static class SidedSecurityMode implements ViewMode {
@Nullable private ValueAnimator mRunningSecurityShiftAnimator;
private KeyguardSecurityViewFlipper mViewFlipper;
private ViewGroup mView; private ViewGroup mView;
private GlobalSettings mGlobalSettings; private GlobalSettings mGlobalSettings;
private int mDefaultSideSetting; private int mDefaultSideSetting;
public void init(ViewGroup v, GlobalSettings globalSettings, boolean leftAlignedByDefault) { public void init(ViewGroup v, KeyguardSecurityViewFlipper viewFlipper,
GlobalSettings globalSettings, boolean leftAlignedByDefault) {
mView = v; mView = v;
mViewFlipper = viewFlipper;
mGlobalSettings = globalSettings; mGlobalSettings = globalSettings;
mDefaultSideSetting = mDefaultSideSetting =
leftAlignedByDefault ? Settings.Global.ONE_HANDED_KEYGUARD_SIDE_LEFT leftAlignedByDefault ? Settings.Global.ONE_HANDED_KEYGUARD_SIDE_LEFT
@@ -841,6 +846,127 @@ public class KeyguardSecurityContainer extends FrameLayout {
protected abstract void updateSecurityViewLocation(boolean leftAlign, boolean animate); protected abstract void updateSecurityViewLocation(boolean leftAlign, boolean animate);
protected void translateSecurityViewLocation(boolean leftAlign, boolean animate) {
translateSecurityViewLocation(leftAlign, animate, i -> {});
}
/**
* Moves the inner security view to the correct location with animation. This is triggered
* when the user double taps on the side of the screen that is not currently occupied by
* the security view.
*/
protected void translateSecurityViewLocation(boolean leftAlign, boolean animate,
Consumer<Float> securityAlphaListener) {
if (mRunningSecurityShiftAnimator != null) {
mRunningSecurityShiftAnimator.cancel();
mRunningSecurityShiftAnimator = null;
}
int targetTranslation = leftAlign
? 0 : mView.getMeasuredWidth() - mViewFlipper.getWidth();
if (animate) {
// This animation is a bit fun to implement. The bouncer needs to move, and fade
// in/out at the same time. The issue is, the bouncer should only move a short
// amount (120dp or so), but obviously needs to go from one side of the screen to
// the other. This needs a pretty custom animation.
//
// This works as follows. It uses a ValueAnimation to simply drive the animation
// progress. This animator is responsible for both the translation of the bouncer,
// and the current fade. It will fade the bouncer out while also moving it along the
// 120dp path. Once the bouncer is fully faded out though, it will "snap" the
// bouncer closer to its destination, then fade it back in again. The effect is that
// the bouncer will move from 0 -> X while fading out, then
// (destination - X) -> destination while fading back in again.
// TODO(b/208250221): Make this animation properly abortable.
Interpolator positionInterpolator = AnimationUtils.loadInterpolator(
mView.getContext(), android.R.interpolator.fast_out_extra_slow_in);
Interpolator fadeOutInterpolator = Interpolators.FAST_OUT_LINEAR_IN;
Interpolator fadeInInterpolator = Interpolators.LINEAR_OUT_SLOW_IN;
mRunningSecurityShiftAnimator = ValueAnimator.ofFloat(0.0f, 1.0f);
mRunningSecurityShiftAnimator.setDuration(SECURITY_SHIFT_ANIMATION_DURATION_MS);
mRunningSecurityShiftAnimator.setInterpolator(Interpolators.LINEAR);
int initialTranslation = (int) mViewFlipper.getTranslationX();
int totalTranslation = (int) mView.getResources().getDimension(
R.dimen.security_shift_animation_translation);
final boolean shouldRestoreLayerType = mViewFlipper.hasOverlappingRendering()
&& mViewFlipper.getLayerType() != View.LAYER_TYPE_HARDWARE;
if (shouldRestoreLayerType) {
mViewFlipper.setLayerType(View.LAYER_TYPE_HARDWARE, /* paint= */null);
}
float initialAlpha = mViewFlipper.getAlpha();
mRunningSecurityShiftAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
mRunningSecurityShiftAnimator = null;
}
});
mRunningSecurityShiftAnimator.addUpdateListener(animation -> {
float switchPoint = SECURITY_SHIFT_ANIMATION_FADE_OUT_PROPORTION;
boolean isFadingOut = animation.getAnimatedFraction() < switchPoint;
int currentTranslation = (int) (positionInterpolator.getInterpolation(
animation.getAnimatedFraction()) * totalTranslation);
int translationRemaining = totalTranslation - currentTranslation;
// Flip the sign if we're going from right to left.
if (leftAlign) {
currentTranslation = -currentTranslation;
translationRemaining = -translationRemaining;
}
float opacity;
if (isFadingOut) {
// The bouncer fades out over the first X%.
float fadeOutFraction = MathUtils.constrainedMap(
/* rangeMin= */1.0f,
/* rangeMax= */0.0f,
/* valueMin= */0.0f,
/* valueMax= */switchPoint,
animation.getAnimatedFraction());
opacity = fadeOutInterpolator.getInterpolation(fadeOutFraction);
// When fading out, the alpha needs to start from the initial opacity of the
// view flipper, otherwise we get a weird bit of jank as it ramps back to
// 100%.
mViewFlipper.setAlpha(opacity * initialAlpha);
// Animate away from the source.
mViewFlipper.setTranslationX(initialTranslation + currentTranslation);
} else {
// And in again over the remaining (100-X)%.
float fadeInFraction = MathUtils.constrainedMap(
/* rangeMin= */0.0f,
/* rangeMax= */1.0f,
/* valueMin= */switchPoint,
/* valueMax= */1.0f,
animation.getAnimatedFraction());
opacity = fadeInInterpolator.getInterpolation(fadeInFraction);
mViewFlipper.setAlpha(opacity);
// Fading back in, animate towards the destination.
mViewFlipper.setTranslationX(targetTranslation - translationRemaining);
}
securityAlphaListener.accept(opacity);
if (animation.getAnimatedFraction() == 1.0f && shouldRestoreLayerType) {
mViewFlipper.setLayerType(View.LAYER_TYPE_NONE, /* paint= */null);
}
});
mRunningSecurityShiftAnimator.start();
} else {
mViewFlipper.setTranslationX(targetTranslation);
}
}
boolean isLeftAligned() { boolean isLeftAligned() {
return mGlobalSettings.getInt(Settings.Global.ONE_HANDED_KEYGUARD_SIDE, return mGlobalSettings.getInt(Settings.Global.ONE_HANDED_KEYGUARD_SIDE,
mDefaultSideSetting) mDefaultSideSetting)
@@ -899,12 +1025,15 @@ public class KeyguardSecurityContainer extends FrameLayout {
private UserSwitcherController.UserSwitchCallback mUserSwitchCallback = private UserSwitcherController.UserSwitchCallback mUserSwitchCallback =
this::setupUserSwitcher; this::setupUserSwitcher;
private float mAnimationLastAlpha = 1f;
private boolean mAnimationWaitsToShift = true;
@Override @Override
public void init(@NonNull ViewGroup v, @NonNull GlobalSettings globalSettings, public void init(@NonNull ViewGroup v, @NonNull GlobalSettings globalSettings,
@NonNull KeyguardSecurityViewFlipper viewFlipper, @NonNull KeyguardSecurityViewFlipper viewFlipper,
@NonNull FalsingManager falsingManager, @NonNull FalsingManager falsingManager,
@NonNull UserSwitcherController userSwitcherController) { @NonNull UserSwitcherController userSwitcherController) {
init(v, globalSettings, /* leftAlignedByDefault= */false); init(v, viewFlipper, globalSettings, /* leftAlignedByDefault= */false);
mView = v; mView = v;
mViewFlipper = viewFlipper; mViewFlipper = viewFlipper;
mFalsingManager = falsingManager; mFalsingManager = falsingManager;
@@ -918,9 +1047,7 @@ public class KeyguardSecurityContainer extends FrameLayout {
true); true);
mUserSwitcherViewGroup = mView.findViewById(R.id.keyguard_bouncer_user_switcher); mUserSwitcherViewGroup = mView.findViewById(R.id.keyguard_bouncer_user_switcher);
} }
updateSecurityViewLocation(); updateSecurityViewLocation();
mUserSwitcher = mView.findViewById(R.id.user_switcher_header); mUserSwitcher = mView.findViewById(R.id.user_switcher_header);
setupUserSwitcher(); setupUserSwitcher();
mUserSwitcherController.addUserSwitchCallback(mUserSwitchCallback); mUserSwitcherController.addUserSwitchCallback(mUserSwitchCallback);
@@ -1120,22 +1247,61 @@ public class KeyguardSecurityContainer extends FrameLayout {
} }
public void updateSecurityViewLocation(boolean leftAlign, boolean animate) { public void updateSecurityViewLocation(boolean leftAlign, boolean animate) {
int yTrans = mResources.getDimensionPixelSize(R.dimen.bouncer_user_switcher_y_trans); setYTranslation();
setGravity();
setXTranslation(leftAlign, animate);
}
private void setXTranslation(boolean leftAlign, boolean animate) {
if (mResources.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) { if (mResources.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
updateViewGravity(mViewFlipper, Gravity.CENTER_HORIZONTAL); mUserSwitcherViewGroup.setTranslationX(0);
updateViewGravity(mUserSwitcherViewGroup, Gravity.CENTER_HORIZONTAL); mViewFlipper.setTranslationX(0);
} else {
int switcherTargetTranslation = leftAlign
? mView.getMeasuredWidth() - mViewFlipper.getWidth() : 0;
if (animate) {
mAnimationWaitsToShift = true;
mAnimationLastAlpha = 1f;
translateSecurityViewLocation(leftAlign, animate, securityAlpha -> {
// During the animation security view fades out - alpha goes from 1 to
// (almost) 0 - and then fades in - alpha grows back to 1.
// If new alpha is bigger than previous one it means we're at inflection
// point and alpha is zero or almost zero. That's when we want to do
// translation of user switcher, so that it's not visible to the user.
boolean fullyFadeOut = securityAlpha == 0.0f
|| securityAlpha > mAnimationLastAlpha;
if (fullyFadeOut && mAnimationWaitsToShift) {
mUserSwitcherViewGroup.setTranslationX(switcherTargetTranslation);
mAnimationWaitsToShift = false;
}
mUserSwitcherViewGroup.setAlpha(securityAlpha);
mAnimationLastAlpha = securityAlpha;
});
} else {
translateSecurityViewLocation(leftAlign, animate);
mUserSwitcherViewGroup.setTranslationX(switcherTargetTranslation);
}
}
}
private void setGravity() {
if (mResources.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
updateViewGravity(mUserSwitcherViewGroup, Gravity.CENTER_HORIZONTAL);
updateViewGravity(mViewFlipper, Gravity.CENTER_HORIZONTAL);
} else {
// horizontal gravity is the same because we translate these views anyway
updateViewGravity(mViewFlipper, Gravity.LEFT | Gravity.BOTTOM);
updateViewGravity(mUserSwitcherViewGroup, Gravity.LEFT | Gravity.CENTER_VERTICAL);
}
}
private void setYTranslation() {
int yTrans = mResources.getDimensionPixelSize(R.dimen.bouncer_user_switcher_y_trans);
if (mResources.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
mUserSwitcherViewGroup.setTranslationY(yTrans); mUserSwitcherViewGroup.setTranslationY(yTrans);
mViewFlipper.setTranslationY(-yTrans); mViewFlipper.setTranslationY(-yTrans);
} else { } else {
int securityHorizontalGravity = leftAlign ? Gravity.LEFT : Gravity.RIGHT;
int userSwitcherHorizontalGravity =
securityHorizontalGravity == Gravity.LEFT ? Gravity.RIGHT : Gravity.LEFT;
updateViewGravity(mViewFlipper, securityHorizontalGravity | Gravity.BOTTOM);
updateViewGravity(mUserSwitcherViewGroup,
userSwitcherHorizontalGravity | Gravity.CENTER_VERTICAL);
// Attempt to reposition a bit higher to make up for this frame being a bit lower // Attempt to reposition a bit higher to make up for this frame being a bit lower
// on the device // on the device
mUserSwitcherViewGroup.setTranslationY(-yTrans); mUserSwitcherViewGroup.setTranslationY(-yTrans);
@@ -1155,7 +1321,6 @@ public class KeyguardSecurityContainer extends FrameLayout {
* between alternate sides of the display. * between alternate sides of the display.
*/ */
static class OneHandedViewMode extends SidedSecurityMode { static class OneHandedViewMode extends SidedSecurityMode {
@Nullable private ValueAnimator mRunningOneHandedAnimator;
private ViewGroup mView; private ViewGroup mView;
private KeyguardSecurityViewFlipper mViewFlipper; private KeyguardSecurityViewFlipper mViewFlipper;
@@ -1164,7 +1329,7 @@ public class KeyguardSecurityContainer extends FrameLayout {
@NonNull KeyguardSecurityViewFlipper viewFlipper, @NonNull KeyguardSecurityViewFlipper viewFlipper,
@NonNull FalsingManager falsingManager, @NonNull FalsingManager falsingManager,
@NonNull UserSwitcherController userSwitcherController) { @NonNull UserSwitcherController userSwitcherController) {
init(v, globalSettings, /* leftAlignedByDefault= */true); init(v, viewFlipper, globalSettings, /* leftAlignedByDefault= */true);
mView = v; mView = v;
mViewFlipper = viewFlipper; mViewFlipper = viewFlipper;
@@ -1205,117 +1370,8 @@ public class KeyguardSecurityContainer extends FrameLayout {
updateSecurityViewLocation(isLeftAligned(), /* animate= */false); updateSecurityViewLocation(isLeftAligned(), /* animate= */false);
} }
/**
* Moves the inner security view to the correct location (in one handed mode) with
* animation. This is triggered when the user double taps on the side of the screen that is
* not currently occupied by the security view.
*/
protected void updateSecurityViewLocation(boolean leftAlign, boolean animate) { protected void updateSecurityViewLocation(boolean leftAlign, boolean animate) {
if (mRunningOneHandedAnimator != null) { translateSecurityViewLocation(leftAlign, animate);
mRunningOneHandedAnimator.cancel();
mRunningOneHandedAnimator = null;
}
int targetTranslation = leftAlign
? 0 : (int) (mView.getMeasuredWidth() - mViewFlipper.getWidth());
if (animate) {
// This animation is a bit fun to implement. The bouncer needs to move, and fade
// in/out at the same time. The issue is, the bouncer should only move a short
// amount (120dp or so), but obviously needs to go from one side of the screen to
// the other. This needs a pretty custom animation.
//
// This works as follows. It uses a ValueAnimation to simply drive the animation
// progress. This animator is responsible for both the translation of the bouncer,
// and the current fade. It will fade the bouncer out while also moving it along the
// 120dp path. Once the bouncer is fully faded out though, it will "snap" the
// bouncer closer to its destination, then fade it back in again. The effect is that
// the bouncer will move from 0 -> X while fading out, then
// (destination - X) -> destination while fading back in again.
// TODO(b/208250221): Make this animation properly abortable.
Interpolator positionInterpolator = AnimationUtils.loadInterpolator(
mView.getContext(), android.R.interpolator.fast_out_extra_slow_in);
Interpolator fadeOutInterpolator = Interpolators.FAST_OUT_LINEAR_IN;
Interpolator fadeInInterpolator = Interpolators.LINEAR_OUT_SLOW_IN;
mRunningOneHandedAnimator = ValueAnimator.ofFloat(0.0f, 1.0f);
mRunningOneHandedAnimator.setDuration(BOUNCER_HANDEDNESS_ANIMATION_DURATION_MS);
mRunningOneHandedAnimator.setInterpolator(Interpolators.LINEAR);
int initialTranslation = (int) mViewFlipper.getTranslationX();
int totalTranslation = (int) mView.getResources().getDimension(
R.dimen.one_handed_bouncer_move_animation_translation);
final boolean shouldRestoreLayerType = mViewFlipper.hasOverlappingRendering()
&& mViewFlipper.getLayerType() != View.LAYER_TYPE_HARDWARE;
if (shouldRestoreLayerType) {
mViewFlipper.setLayerType(View.LAYER_TYPE_HARDWARE, /* paint= */null);
}
float initialAlpha = mViewFlipper.getAlpha();
mRunningOneHandedAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
mRunningOneHandedAnimator = null;
}
});
mRunningOneHandedAnimator.addUpdateListener(animation -> {
float switchPoint = BOUNCER_HANDEDNESS_ANIMATION_FADE_OUT_PROPORTION;
boolean isFadingOut = animation.getAnimatedFraction() < switchPoint;
int currentTranslation = (int) (positionInterpolator.getInterpolation(
animation.getAnimatedFraction()) * totalTranslation);
int translationRemaining = totalTranslation - currentTranslation;
// Flip the sign if we're going from right to left.
if (leftAlign) {
currentTranslation = -currentTranslation;
translationRemaining = -translationRemaining;
}
if (isFadingOut) {
// The bouncer fades out over the first X%.
float fadeOutFraction = MathUtils.constrainedMap(
/* rangeMin= */1.0f,
/* rangeMax= */0.0f,
/* valueMin= */0.0f,
/* valueMax= */switchPoint,
animation.getAnimatedFraction());
float opacity = fadeOutInterpolator.getInterpolation(fadeOutFraction);
// When fading out, the alpha needs to start from the initial opacity of the
// view flipper, otherwise we get a weird bit of jank as it ramps back to
// 100%.
mViewFlipper.setAlpha(opacity * initialAlpha);
// Animate away from the source.
mViewFlipper.setTranslationX(initialTranslation + currentTranslation);
} else {
// And in again over the remaining (100-X)%.
float fadeInFraction = MathUtils.constrainedMap(
/* rangeMin= */0.0f,
/* rangeMax= */1.0f,
/* valueMin= */switchPoint,
/* valueMax= */1.0f,
animation.getAnimatedFraction());
float opacity = fadeInInterpolator.getInterpolation(fadeInFraction);
mViewFlipper.setAlpha(opacity);
// Fading back in, animate towards the destination.
mViewFlipper.setTranslationX(targetTranslation - translationRemaining);
}
if (animation.getAnimatedFraction() == 1.0f && shouldRestoreLayerType) {
mViewFlipper.setLayerType(View.LAYER_TYPE_NONE, /* paint= */null);
}
});
mRunningOneHandedAnimator.start();
} else {
mViewFlipper.setTranslationX(targetTranslation);
}
} }
} }
} }

View File

@@ -16,6 +16,8 @@
package com.android.keyguard; package com.android.keyguard;
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
import static android.provider.Settings.Global.ONE_HANDED_KEYGUARD_SIDE; import static android.provider.Settings.Global.ONE_HANDED_KEYGUARD_SIDE;
import static android.provider.Settings.Global.ONE_HANDED_KEYGUARD_SIDE_LEFT; import static android.provider.Settings.Global.ONE_HANDED_KEYGUARD_SIDE_LEFT;
import static android.provider.Settings.Global.ONE_HANDED_KEYGUARD_SIDE_RIGHT; import static android.provider.Settings.Global.ONE_HANDED_KEYGUARD_SIDE_RIGHT;
@@ -46,7 +48,6 @@ import android.view.MotionEvent;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.WindowInsets; import android.view.WindowInsets;
import android.view.WindowInsetsController;
import android.widget.FrameLayout; import android.widget.FrameLayout;
import androidx.test.filters.SmallTest; import androidx.test.filters.SmallTest;
@@ -84,8 +85,6 @@ public class KeyguardSecurityContainerTest extends SysuiTestCase {
@Rule @Rule
public MockitoRule mRule = MockitoJUnit.rule(); public MockitoRule mRule = MockitoJUnit.rule();
@Mock
private WindowInsetsController mWindowInsetsController;
@Mock @Mock
private KeyguardSecurityViewFlipper mSecurityViewFlipper; private KeyguardSecurityViewFlipper mSecurityViewFlipper;
@Mock @Mock
@@ -110,7 +109,6 @@ public class KeyguardSecurityContainerTest extends SysuiTestCase {
mSecurityViewFlipperLayoutParams = new FrameLayout.LayoutParams( mSecurityViewFlipperLayoutParams = new FrameLayout.LayoutParams(
MATCH_PARENT, MATCH_PARENT); MATCH_PARENT, MATCH_PARENT);
when(mSecurityViewFlipper.getWindowInsetsController()).thenReturn(mWindowInsetsController);
when(mSecurityViewFlipper.getLayoutParams()).thenReturn(mSecurityViewFlipperLayoutParams); when(mSecurityViewFlipper.getLayoutParams()).thenReturn(mSecurityViewFlipperLayoutParams);
mKeyguardSecurityContainer = new KeyguardSecurityContainer(getContext()); mKeyguardSecurityContainer = new KeyguardSecurityContainer(getContext());
mKeyguardSecurityContainer.mSecurityViewFlipper = mSecurityViewFlipper; mKeyguardSecurityContainer.mSecurityViewFlipper = mSecurityViewFlipper;
@@ -221,7 +219,7 @@ public class KeyguardSecurityContainerTest extends SysuiTestCase {
mKeyguardSecurityContainer.getWidth() - 1f); mKeyguardSecurityContainer.getWidth() - 1f);
verify(mGlobalSettings).putInt(ONE_HANDED_KEYGUARD_SIDE, ONE_HANDED_KEYGUARD_SIDE_RIGHT); verify(mGlobalSettings).putInt(ONE_HANDED_KEYGUARD_SIDE, ONE_HANDED_KEYGUARD_SIDE_RIGHT);
verify(mSecurityViewFlipper).setTranslationX( assertSecurityTranslationX(
mKeyguardSecurityContainer.getWidth() - mSecurityViewFlipper.getWidth()); mKeyguardSecurityContainer.getWidth() - mSecurityViewFlipper.getWidth());
mKeyguardSecurityContainer.updatePositionByTouchX(1f); mKeyguardSecurityContainer.updatePositionByTouchX(1f);
@@ -243,43 +241,43 @@ public class KeyguardSecurityContainerTest extends SysuiTestCase {
} }
@Test @Test
public void testUserSwitcherModeViewGravityLandscape() { public void testUserSwitcherModeViewPositionLandscape() {
// GIVEN one user has been setup and in landscape // GIVEN one user has been setup and in landscape
when(mUserSwitcherController.getUsers()).thenReturn(buildUserRecords(1)); when(mUserSwitcherController.getUsers()).thenReturn(buildUserRecords(1));
Configuration config = new Configuration(); Configuration landscapeConfig = configuration(ORIENTATION_LANDSCAPE);
config.orientation = Configuration.ORIENTATION_LANDSCAPE; when(getContext().getResources().getConfiguration()).thenReturn(landscapeConfig);
when(getContext().getResources().getConfiguration()).thenReturn(config);
// WHEN UserSwitcherViewMode is initialized and config has changed // WHEN UserSwitcherViewMode is initialized and config has changed
setupUserSwitcher(); setupUserSwitcher();
reset(mSecurityViewFlipper); mKeyguardSecurityContainer.onConfigurationChanged(landscapeConfig);
when(mSecurityViewFlipper.getLayoutParams()).thenReturn(mSecurityViewFlipperLayoutParams);
mKeyguardSecurityContainer.onConfigurationChanged(config);
// THEN views are oriented side by side // THEN views are oriented side by side
verify(mSecurityViewFlipper).setLayoutParams(mLayoutCaptor.capture()); assertSecurityGravity(Gravity.LEFT | Gravity.BOTTOM);
assertThat(mLayoutCaptor.getValue().gravity).isEqualTo(Gravity.RIGHT | Gravity.BOTTOM);
assertUserSwitcherGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL); assertUserSwitcherGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL);
assertSecurityTranslationX(
mKeyguardSecurityContainer.getWidth() - mSecurityViewFlipper.getWidth());
assertUserSwitcherTranslationX(0f);
} }
@Test @Test
public void testUserSwitcherModeViewGravityPortrait() { public void testUserSwitcherModeViewGravityPortrait() {
// GIVEN one user has been setup and in landscape // GIVEN one user has been setup and in landscape
when(mUserSwitcherController.getUsers()).thenReturn(buildUserRecords(1)); when(mUserSwitcherController.getUsers()).thenReturn(buildUserRecords(1));
Configuration config = new Configuration(); Configuration portraitConfig = configuration(ORIENTATION_PORTRAIT);
config.orientation = Configuration.ORIENTATION_PORTRAIT; when(getContext().getResources().getConfiguration()).thenReturn(portraitConfig);
when(getContext().getResources().getConfiguration()).thenReturn(config);
// WHEN UserSwitcherViewMode is initialized and config has changed // WHEN UserSwitcherViewMode is initialized and config has changed
setupUserSwitcher(); setupUserSwitcher();
reset(mSecurityViewFlipper); reset(mSecurityViewFlipper);
when(mSecurityViewFlipper.getLayoutParams()).thenReturn(mSecurityViewFlipperLayoutParams); when(mSecurityViewFlipper.getLayoutParams()).thenReturn(mSecurityViewFlipperLayoutParams);
mKeyguardSecurityContainer.onConfigurationChanged(config); mKeyguardSecurityContainer.onConfigurationChanged(portraitConfig);
// THEN views are both centered horizontally // THEN views are both centered horizontally
verify(mSecurityViewFlipper).setLayoutParams(mLayoutCaptor.capture()); assertSecurityGravity(Gravity.CENTER_HORIZONTAL);
assertThat(mLayoutCaptor.getValue().gravity).isEqualTo(Gravity.CENTER_HORIZONTAL);
assertUserSwitcherGravity(Gravity.CENTER_HORIZONTAL); assertUserSwitcherGravity(Gravity.CENTER_HORIZONTAL);
assertSecurityTranslationX(0);
assertUserSwitcherTranslationX(0);
} }
@Test @Test
@@ -315,14 +313,16 @@ public class KeyguardSecurityContainerTest extends SysuiTestCase {
setupUserSwitcher(); setupUserSwitcher();
setViewWidth(VIEW_WIDTH); setViewWidth(VIEW_WIDTH);
// security is on the right side by default
assertThat(mKeyguardSecurityContainer.isTouchOnTheOtherSideOfSecurity( assertThat(mKeyguardSecurityContainer.isTouchOnTheOtherSideOfSecurity(
touchEventLeftSide())).isTrue(); touchEventLeftSide())).isTrue();
assertThat(mKeyguardSecurityContainer.isTouchOnTheOtherSideOfSecurity( assertThat(mKeyguardSecurityContainer.isTouchOnTheOtherSideOfSecurity(
touchEventRightSide())).isFalse(); touchEventRightSide())).isFalse();
mKeyguardSecurityContainer.handleDoubleTap(touchEventLeftSide()); // move security to the left side
// settings should be updated, we need to keep the mock updated as well
when(mGlobalSettings.getInt(any(), anyInt())).thenReturn(ONE_HANDED_KEYGUARD_SIDE_LEFT); when(mGlobalSettings.getInt(any(), anyInt())).thenReturn(ONE_HANDED_KEYGUARD_SIDE_LEFT);
mKeyguardSecurityContainer.onConfigurationChanged(new Configuration());
assertThat(mKeyguardSecurityContainer.isTouchOnTheOtherSideOfSecurity( assertThat(mKeyguardSecurityContainer.isTouchOnTheOtherSideOfSecurity(
touchEventLeftSide())).isFalse(); touchEventLeftSide())).isFalse();
assertThat(mKeyguardSecurityContainer.isTouchOnTheOtherSideOfSecurity( assertThat(mKeyguardSecurityContainer.isTouchOnTheOtherSideOfSecurity(
@@ -331,23 +331,33 @@ public class KeyguardSecurityContainerTest extends SysuiTestCase {
@Test @Test
public void testSecuritySwitchesSidesInLandscapeUserSwitcherMode() { public void testSecuritySwitchesSidesInLandscapeUserSwitcherMode() {
Configuration config = new Configuration(); when(getContext().getResources().getConfiguration())
config.orientation = Configuration.ORIENTATION_LANDSCAPE; .thenReturn(configuration(ORIENTATION_LANDSCAPE));
when(getContext().getResources().getConfiguration()).thenReturn(config);
setupUserSwitcher(); setupUserSwitcher();
// check default position
assertSecurityGravity(Gravity.RIGHT | Gravity.BOTTOM);
assertUserSwitcherGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL);
reset(mSecurityViewFlipper); // switch sides
when(mSecurityViewFlipper.getLayoutParams()).thenReturn(mSecurityViewFlipperLayoutParams);
// change setting so configuration change triggers position change
when(mGlobalSettings.getInt(any(), anyInt())).thenReturn(ONE_HANDED_KEYGUARD_SIDE_LEFT); when(mGlobalSettings.getInt(any(), anyInt())).thenReturn(ONE_HANDED_KEYGUARD_SIDE_LEFT);
mKeyguardSecurityContainer.onConfigurationChanged(new Configuration()); mKeyguardSecurityContainer.onConfigurationChanged(new Configuration());
// check position after switching assertSecurityTranslationX(0);
assertSecurityGravity(Gravity.LEFT | Gravity.BOTTOM); assertUserSwitcherTranslationX(
assertUserSwitcherGravity(Gravity.RIGHT | Gravity.CENTER_VERTICAL); mKeyguardSecurityContainer.getWidth() - mSecurityViewFlipper.getWidth());
}
private Configuration configuration(@Configuration.Orientation int orientation) {
Configuration config = new Configuration();
config.orientation = orientation;
return config;
}
private void assertSecurityTranslationX(float translation) {
verify(mSecurityViewFlipper).setTranslationX(translation);
}
private void assertUserSwitcherTranslationX(float translation) {
ViewGroup userSwitcher = mKeyguardSecurityContainer.findViewById(
R.id.keyguard_bouncer_user_switcher);
assertThat(userSwitcher.getTranslationX()).isEqualTo(translation);
} }
private void assertUserSwitcherGravity(@Gravity.GravityFlags int gravity) { private void assertUserSwitcherGravity(@Gravity.GravityFlags int gravity) {
@@ -391,6 +401,9 @@ public class KeyguardSecurityContainerTest extends SysuiTestCase {
when(mGlobalSettings.getInt(any(), anyInt())).thenReturn(ONE_HANDED_KEYGUARD_SIDE_RIGHT); when(mGlobalSettings.getInt(any(), anyInt())).thenReturn(ONE_HANDED_KEYGUARD_SIDE_RIGHT);
mKeyguardSecurityContainer.initMode(KeyguardSecurityContainer.MODE_USER_SWITCHER, mKeyguardSecurityContainer.initMode(KeyguardSecurityContainer.MODE_USER_SWITCHER,
mGlobalSettings, mFalsingManager, mUserSwitcherController); mGlobalSettings, mFalsingManager, mUserSwitcherController);
// reset mSecurityViewFlipper so setup doesn't influence test verifications
reset(mSecurityViewFlipper);
when(mSecurityViewFlipper.getLayoutParams()).thenReturn(mSecurityViewFlipperLayoutParams);
} }
private ArrayList<UserRecord> buildUserRecords(int count) { private ArrayList<UserRecord> buildUserRecords(int count) {