1/2 Making bouncer shift on double tap when user chooser is visible

This change makes bouncer/security swap sides with multi user view without proper animation. Adding animation will come in follow up CL.
The main change is extracting double tap and shift logic to SidedSecurityMode superclass so both "one handed mode" and "multi user mode" can inherit from it and behave in a similar way.

Bug: 220872694
Test: KeyguardSecurityContainerTest
Test: open bouncer with user chooser on the side, double tap on the other side of the bouncer, see views swap positions
Change-Id: Ic7e32412edd4c25dde709db0544e60ec9ab951e5
This commit is contained in:
Michal Brzezinski
2022-06-15 11:34:05 -04:00
parent 1e09b6dbc2
commit fd8aa55ee3
7 changed files with 215 additions and 115 deletions

View File

@@ -29,7 +29,7 @@ import java.lang.annotation.RetentionPolicy;
/**
* Interface that decides whether a touch on the phone was accidental. i.e. Pocket Dialing.
*
* {@see com.android.systemui.classifier.FalsingManagerImpl}
* {@see com.android.systemui.classifier.BrightLineFalsingManager}
*/
@ProvidesInterface(version = FalsingManager.VERSION)
public interface FalsingManager {

View File

@@ -375,10 +375,23 @@ public class KeyguardSecurityContainer extends FrameLayout {
mViewMode.updatePositionByTouchX(x);
}
/** Returns whether the inner SecurityViewFlipper is left-aligned when in one-handed mode. */
public boolean isOneHandedModeLeftAligned() {
return mCurrentMode == MODE_ONE_HANDED
&& ((OneHandedViewMode) mViewMode).isLeftAligned();
public boolean isSidedSecurityMode() {
return mViewMode instanceof SidedSecurityMode;
}
/** Returns whether the inner SecurityViewFlipper is left-aligned when in sided mode. */
public boolean isSecurityLeftAligned() {
return mViewMode instanceof SidedSecurityMode
&& ((SidedSecurityMode) mViewMode).isLeftAligned();
}
/**
* Returns whether the touch happened on the other side of security (like bouncer) when in
* sided mode.
*/
public boolean isTouchOnTheOtherSideOfSecurity(MotionEvent ev) {
return mViewMode instanceof SidedSecurityMode
&& ((SidedSecurityMode) mViewMode).isTouchOnTheOtherSideOfSecurity(ev);
}
public void onPause() {
@@ -437,12 +450,15 @@ public class KeyguardSecurityContainer extends FrameLayout {
@Override
public boolean onTouchEvent(MotionEvent event) {
final int action = event.getActionMasked();
mDoubleTapDetector.onTouchEvent(event);
boolean result = mMotionEventListeners.stream()
.anyMatch(listener -> listener.onTouchEvent(event))
|| super.onTouchEvent(event);
// double tap detector should be called after listeners handle touches as listeners are
// helping with ignoring falsing. Otherwise falsing will be activated for some double taps
mDoubleTapDetector.onTouchEvent(event);
switch (action) {
case MotionEvent.ACTION_MOVE:
mVelocityTracker.addMovement(event);
@@ -487,11 +503,16 @@ public class KeyguardSecurityContainer extends FrameLayout {
private class DoubleTapListener extends GestureDetector.SimpleOnGestureListener {
@Override
public boolean onDoubleTap(MotionEvent e) {
if (!mIsDragging) {
mViewMode.handleDoubleTap(e);
}
return handleDoubleTap(e);
}
}
@VisibleForTesting boolean handleDoubleTap(MotionEvent e) {
if (!mIsDragging) {
mViewMode.handleDoubleTap(e);
return true;
}
return false;
}
void addMotionEventListener(Gefingerpoken listener) {
@@ -770,6 +791,70 @@ public class KeyguardSecurityContainer extends FrameLayout {
default void onDestroy() {};
}
/**
* Base class for modes which support having on left/right side of the screen, used for large
* screen devices
*/
abstract static class SidedSecurityMode implements ViewMode {
private ViewGroup mView;
private GlobalSettings mGlobalSettings;
private int mDefaultSideSetting;
public void init(ViewGroup v, GlobalSettings globalSettings, boolean leftAlignedByDefault) {
mView = v;
mGlobalSettings = globalSettings;
mDefaultSideSetting =
leftAlignedByDefault ? Settings.Global.ONE_HANDED_KEYGUARD_SIDE_LEFT
: Settings.Global.ONE_HANDED_KEYGUARD_SIDE_RIGHT;
}
/**
* Determine if a double tap on this view is on the other side. If so, will animate
* positions and record the preference to always show on this side.
*/
@Override
public void handleDoubleTap(MotionEvent event) {
boolean currentlyLeftAligned = isLeftAligned();
// Did the tap hit the "other" side of the bouncer?
if (isTouchOnTheOtherSideOfSecurity(event, currentlyLeftAligned)) {
boolean willBeLeftAligned = !currentlyLeftAligned;
updateSideSetting(willBeLeftAligned);
int keyguardState = willBeLeftAligned
? SysUiStatsLog.KEYGUARD_BOUNCER_STATE_CHANGED__STATE__SWITCH_LEFT
: SysUiStatsLog.KEYGUARD_BOUNCER_STATE_CHANGED__STATE__SWITCH_RIGHT;
SysUiStatsLog.write(SysUiStatsLog.KEYGUARD_BOUNCER_STATE_CHANGED, keyguardState);
updateSecurityViewLocation(willBeLeftAligned, /* animate= */ true);
}
}
private boolean isTouchOnTheOtherSideOfSecurity(MotionEvent ev, boolean leftAligned) {
float x = ev.getX();
return (leftAligned && (x > mView.getWidth() / 2f))
|| (!leftAligned && (x < mView.getWidth() / 2f));
}
public boolean isTouchOnTheOtherSideOfSecurity(MotionEvent ev) {
return isTouchOnTheOtherSideOfSecurity(ev, isLeftAligned());
}
protected abstract void updateSecurityViewLocation(boolean leftAlign, boolean animate);
boolean isLeftAligned() {
return mGlobalSettings.getInt(Settings.Global.ONE_HANDED_KEYGUARD_SIDE,
mDefaultSideSetting)
== Settings.Global.ONE_HANDED_KEYGUARD_SIDE_LEFT;
}
protected void updateSideSetting(boolean leftAligned) {
mGlobalSettings.putInt(
Settings.Global.ONE_HANDED_KEYGUARD_SIDE,
leftAligned ? Settings.Global.ONE_HANDED_KEYGUARD_SIDE_LEFT
: Settings.Global.ONE_HANDED_KEYGUARD_SIDE_RIGHT);
}
}
/**
* Default bouncer is centered within the space
*/
@@ -802,7 +887,7 @@ public class KeyguardSecurityContainer extends FrameLayout {
* User switcher mode will display both the current user icon as well as
* a user switcher, in both portrait and landscape modes.
*/
static class UserSwitcherViewMode implements ViewMode {
static class UserSwitcherViewMode extends SidedSecurityMode {
private ViewGroup mView;
private ViewGroup mUserSwitcherViewGroup;
private KeyguardSecurityViewFlipper mViewFlipper;
@@ -819,6 +904,7 @@ public class KeyguardSecurityContainer extends FrameLayout {
@NonNull KeyguardSecurityViewFlipper viewFlipper,
@NonNull FalsingManager falsingManager,
@NonNull UserSwitcherController userSwitcherController) {
init(v, globalSettings, /* leftAlignedByDefault= */false);
mView = v;
mViewFlipper = viewFlipper;
mFalsingManager = falsingManager;
@@ -1030,6 +1116,10 @@ public class KeyguardSecurityContainer extends FrameLayout {
@Override
public void updateSecurityViewLocation() {
updateSecurityViewLocation(isLeftAligned(), /* animate= */false);
}
public void updateSecurityViewLocation(boolean leftAlign, boolean animate) {
int yTrans = mResources.getDimensionPixelSize(R.dimen.bouncer_user_switcher_y_trans);
if (mResources.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
@@ -1039,8 +1129,12 @@ public class KeyguardSecurityContainer extends FrameLayout {
mUserSwitcherViewGroup.setTranslationY(yTrans);
mViewFlipper.setTranslationY(-yTrans);
} else {
updateViewGravity(mViewFlipper, Gravity.RIGHT | Gravity.BOTTOM);
updateViewGravity(mUserSwitcherViewGroup, Gravity.LEFT | Gravity.CENTER_VERTICAL);
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
// on the device
@@ -1060,20 +1154,19 @@ public class KeyguardSecurityContainer extends FrameLayout {
* Logic to enabled one-handed bouncer mode. Supports animating the bouncer
* between alternate sides of the display.
*/
static class OneHandedViewMode implements ViewMode {
static class OneHandedViewMode extends SidedSecurityMode {
@Nullable private ValueAnimator mRunningOneHandedAnimator;
private ViewGroup mView;
private KeyguardSecurityViewFlipper mViewFlipper;
private GlobalSettings mGlobalSettings;
@Override
public void init(@NonNull ViewGroup v, @NonNull GlobalSettings globalSettings,
@NonNull KeyguardSecurityViewFlipper viewFlipper,
@NonNull FalsingManager falsingManager,
@NonNull UserSwitcherController userSwitcherController) {
init(v, globalSettings, /* leftAlignedByDefault= */true);
mView = v;
mViewFlipper = viewFlipper;
mGlobalSettings = globalSettings;
updateSecurityViewGravity();
updateSecurityViewLocation(isLeftAligned(), /* animate= */false);
@@ -1107,43 +1200,6 @@ public class KeyguardSecurityContainer extends FrameLayout {
updateSecurityViewLocation(isTouchOnLeft, /* animate= */false);
}
boolean isLeftAligned() {
return mGlobalSettings.getInt(Settings.Global.ONE_HANDED_KEYGUARD_SIDE,
Settings.Global.ONE_HANDED_KEYGUARD_SIDE_LEFT)
== Settings.Global.ONE_HANDED_KEYGUARD_SIDE_LEFT;
}
private void updateSideSetting(boolean leftAligned) {
mGlobalSettings.putInt(
Settings.Global.ONE_HANDED_KEYGUARD_SIDE,
leftAligned ? Settings.Global.ONE_HANDED_KEYGUARD_SIDE_LEFT
: Settings.Global.ONE_HANDED_KEYGUARD_SIDE_RIGHT);
}
/**
* Determine if a double tap on this view is on the other side. If so, will animate
* positions and record the preference to always show on this side.
*/
@Override
public void handleDoubleTap(MotionEvent event) {
float x = event.getX();
boolean currentlyLeftAligned = isLeftAligned();
// Did the tap hit the "other" side of the bouncer?
if ((currentlyLeftAligned && (x > mView.getWidth() / 2f))
|| (!currentlyLeftAligned && (x < mView.getWidth() / 2f))) {
boolean willBeLeftAligned = !currentlyLeftAligned;
updateSideSetting(willBeLeftAligned);
int keyguardState = willBeLeftAligned
? SysUiStatsLog.KEYGUARD_BOUNCER_STATE_CHANGED__STATE__SWITCH_LEFT
: SysUiStatsLog.KEYGUARD_BOUNCER_STATE_CHANGED__STATE__SWITCH_RIGHT;
SysUiStatsLog.write(SysUiStatsLog.KEYGUARD_BOUNCER_STATE_CHANGED, keyguardState);
updateSecurityViewLocation(willBeLeftAligned, true /* animate */);
}
}
@Override
public void updateSecurityViewLocation() {
updateSecurityViewLocation(isLeftAligned(), /* animate= */false);
@@ -1151,10 +1207,10 @@ public class KeyguardSecurityContainer extends FrameLayout {
/**
* Moves the inner security view to the correct location (in one handed mode) with
* animation. This is triggered when the user taps on the side of the screen that is not
* currently occupied by the security view.
* animation. This is triggered when the user double taps on the side of the screen that is
* not currently occupied by the security view.
*/
private void updateSecurityViewLocation(boolean leftAlign, boolean animate) {
protected void updateSecurityViewLocation(boolean leftAlign, boolean animate) {
if (mRunningOneHandedAnimator != null) {
mRunningOneHandedAnimator.cancel();
mRunningOneHandedAnimator = null;

View File

@@ -116,12 +116,8 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
// If we're in one handed mode, the user can tap on the opposite side of the screen
// to move the bouncer across. In that case, inhibit the falsing (otherwise the taps
// to move the bouncer to each screen side can end up closing it instead).
if (mView.getMode() == KeyguardSecurityContainer.MODE_ONE_HANDED) {
boolean isLeftAligned = mView.isOneHandedModeLeftAligned();
if ((isLeftAligned && ev.getX() > mView.getWidth() / 2f)
|| (!isLeftAligned && ev.getX() <= mView.getWidth() / 2f)) {
mFalsingCollector.avoidGesture();
}
if (mView.isTouchOnTheOtherSideOfSecurity(ev)) {
mFalsingCollector.avoidGesture();
}
if (mTouchDown != null) {
@@ -169,8 +165,8 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
public void reportUnlockAttempt(int userId, boolean success, int timeoutMs) {
int bouncerSide = SysUiStatsLog.KEYGUARD_BOUNCER_PASSWORD_ENTERED__SIDE__DEFAULT;
if (mView.getMode() == KeyguardSecurityContainer.MODE_ONE_HANDED) {
bouncerSide = mView.isOneHandedModeLeftAligned()
if (mView.isSidedSecurityMode()) {
bouncerSide = mView.isSecurityLeftAligned()
? SysUiStatsLog.KEYGUARD_BOUNCER_PASSWORD_ENTERED__SIDE__LEFT
: SysUiStatsLog.KEYGUARD_BOUNCER_PASSWORD_ENTERED__SIDE__RIGHT;
}
@@ -367,8 +363,8 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
public void onResume(int reason) {
if (mCurrentSecurityMode != SecurityMode.None) {
int state = SysUiStatsLog.KEYGUARD_BOUNCER_STATE_CHANGED__STATE__SHOWN;
if (mView.getMode() == KeyguardSecurityContainer.MODE_ONE_HANDED) {
state = mView.isOneHandedModeLeftAligned()
if (mView.isSidedSecurityMode()) {
state = mView.isSecurityLeftAligned()
? SysUiStatsLog.KEYGUARD_BOUNCER_STATE_CHANGED__STATE__SHOWN_LEFT
: SysUiStatsLog.KEYGUARD_BOUNCER_STATE_CHANGED__STATE__SHOWN_RIGHT;
}

View File

@@ -1647,7 +1647,6 @@ public class NotificationPanelViewController extends PanelViewController {
setQsExpansionEnabled();
}
@Override
public void resetViews(boolean animate) {
mIsLaunchTransitionFinished = false;
mBlockTouches = false;

View File

@@ -1163,8 +1163,6 @@ public abstract class PanelViewController {
mTouchDisabled ? "T" : "f"));
}
public abstract void resetViews(boolean animate);
public void setHeadsUpManager(HeadsUpManagerPhone headsUpManager) {
mHeadsUpManager = headsUpManager;
}

View File

@@ -27,7 +27,6 @@ import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -68,8 +67,6 @@ import org.mockito.junit.MockitoRule;
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper()
public class KeyguardSecurityContainerControllerTest extends SysuiTestCase {
private static final int VIEW_WIDTH = 1600;
@Rule
public MockitoRule mRule = MockitoJUnit.rule();
@@ -141,7 +138,6 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase {
when(mResources.getConfiguration()).thenReturn(mConfiguration);
when(mView.getContext()).thenReturn(mContext);
when(mView.getResources()).thenReturn(mResources);
when(mView.getWidth()).thenReturn(VIEW_WIDTH);
when(mAdminSecondaryLockScreenControllerFactory.create(any(KeyguardSecurityCallback.class)))
.thenReturn(mAdminSecondaryLockScreenController);
when(mSecurityViewFlipper.getWindowInsetsController()).thenReturn(mWindowInsetsController);
@@ -212,49 +208,26 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase {
mUserSwitcherController);
}
private void touchDownLeftSide() {
private void touchDown() {
mKeyguardSecurityContainerController.mGlobalTouchListener.onTouchEvent(
MotionEvent.obtain(
/* downTime= */0,
/* eventTime= */0,
MotionEvent.ACTION_DOWN,
/* x= */VIEW_WIDTH / 3f,
/* y= */0,
/* metaState= */0));
}
private void touchDownRightSide() {
mKeyguardSecurityContainerController.mGlobalTouchListener.onTouchEvent(
MotionEvent.obtain(
/* downTime= */0,
/* eventTime= */0,
MotionEvent.ACTION_DOWN,
/* x= */(VIEW_WIDTH / 3f) * 2,
/* x= */0,
/* y= */0,
/* metaState= */0));
}
@Test
public void onInterceptTap_inhibitsFalsingInOneHandedMode() {
when(mView.getMode()).thenReturn(MODE_ONE_HANDED);
when(mView.isOneHandedModeLeftAligned()).thenReturn(true);
public void onInterceptTap_inhibitsFalsingInSidedSecurityMode() {
touchDownLeftSide();
when(mView.isTouchOnTheOtherSideOfSecurity(any())).thenReturn(false);
touchDown();
verify(mFalsingCollector, never()).avoidGesture();
// Now on the right.
touchDownRightSide();
verify(mFalsingCollector).avoidGesture();
// Move and re-test
reset(mFalsingCollector);
when(mView.isOneHandedModeLeftAligned()).thenReturn(false);
// On the right...
touchDownRightSide();
verify(mFalsingCollector, never()).avoidGesture();
touchDownLeftSide();
when(mView.isTouchOnTheOtherSideOfSecurity(any())).thenReturn(true);
touchDown();
verify(mFalsingCollector).avoidGesture();
}

View File

@@ -16,6 +16,9 @@
package com.android.keyguard;
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_RIGHT;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.WindowInsets.Type.ime;
import static android.view.WindowInsets.Type.systemBars;
@@ -25,7 +28,9 @@ import static com.android.keyguard.KeyguardSecurityContainer.MODE_ONE_HANDED;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
@@ -34,10 +39,10 @@ import static org.mockito.Mockito.when;
import android.content.pm.UserInfo;
import android.content.res.Configuration;
import android.graphics.Insets;
import android.provider.Settings;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowInsets;
@@ -70,6 +75,9 @@ import java.util.ArrayList;
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper()
public class KeyguardSecurityContainerTest extends SysuiTestCase {
private static final int VIEW_WIDTH = 1600;
private int mScreenWidth;
private int mFakeMeasureSpec;
@@ -212,14 +220,12 @@ public class KeyguardSecurityContainerTest extends SysuiTestCase {
mKeyguardSecurityContainer.updatePositionByTouchX(
mKeyguardSecurityContainer.getWidth() - 1f);
verify(mGlobalSettings).putInt(Settings.Global.ONE_HANDED_KEYGUARD_SIDE,
Settings.Global.ONE_HANDED_KEYGUARD_SIDE_RIGHT);
verify(mGlobalSettings).putInt(ONE_HANDED_KEYGUARD_SIDE, ONE_HANDED_KEYGUARD_SIDE_RIGHT);
verify(mSecurityViewFlipper).setTranslationX(
mKeyguardSecurityContainer.getWidth() - mSecurityViewFlipper.getWidth());
mKeyguardSecurityContainer.updatePositionByTouchX(1f);
verify(mGlobalSettings).putInt(Settings.Global.ONE_HANDED_KEYGUARD_SIDE,
Settings.Global.ONE_HANDED_KEYGUARD_SIDE_LEFT);
verify(mGlobalSettings).putInt(ONE_HANDED_KEYGUARD_SIDE, ONE_HANDED_KEYGUARD_SIDE_LEFT);
verify(mSecurityViewFlipper).setTranslationX(0.0f);
}
@@ -253,10 +259,7 @@ public class KeyguardSecurityContainerTest extends SysuiTestCase {
// THEN views are oriented side by side
verify(mSecurityViewFlipper).setLayoutParams(mLayoutCaptor.capture());
assertThat(mLayoutCaptor.getValue().gravity).isEqualTo(Gravity.RIGHT | Gravity.BOTTOM);
ViewGroup userSwitcher = mKeyguardSecurityContainer.findViewById(
R.id.keyguard_bouncer_user_switcher);
assertThat(((FrameLayout.LayoutParams) userSwitcher.getLayoutParams()).gravity)
.isEqualTo(Gravity.LEFT | Gravity.CENTER_VERTICAL);
assertUserSwitcherGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL);
}
@Test
@@ -276,10 +279,7 @@ public class KeyguardSecurityContainerTest extends SysuiTestCase {
// THEN views are both centered horizontally
verify(mSecurityViewFlipper).setLayoutParams(mLayoutCaptor.capture());
assertThat(mLayoutCaptor.getValue().gravity).isEqualTo(Gravity.CENTER_HORIZONTAL);
ViewGroup userSwitcher = mKeyguardSecurityContainer.findViewById(
R.id.keyguard_bouncer_user_switcher);
assertThat(((FrameLayout.LayoutParams) userSwitcher.getLayoutParams()).gravity)
.isEqualTo(Gravity.CENTER_HORIZONTAL);
assertUserSwitcherGravity(Gravity.CENTER_HORIZONTAL);
}
@Test
@@ -310,7 +310,85 @@ public class KeyguardSecurityContainerTest extends SysuiTestCase {
assertThat(anchor.isClickable()).isTrue();
}
@Test
public void testTouchesAreRecognizedAsBeingOnTheOtherSideOfSecurity() {
setupUserSwitcher();
setViewWidth(VIEW_WIDTH);
assertThat(mKeyguardSecurityContainer.isTouchOnTheOtherSideOfSecurity(
touchEventLeftSide())).isTrue();
assertThat(mKeyguardSecurityContainer.isTouchOnTheOtherSideOfSecurity(
touchEventRightSide())).isFalse();
mKeyguardSecurityContainer.handleDoubleTap(touchEventLeftSide());
// settings should be updated, we need to keep the mock updated as well
when(mGlobalSettings.getInt(any(), anyInt())).thenReturn(ONE_HANDED_KEYGUARD_SIDE_LEFT);
assertThat(mKeyguardSecurityContainer.isTouchOnTheOtherSideOfSecurity(
touchEventLeftSide())).isFalse();
assertThat(mKeyguardSecurityContainer.isTouchOnTheOtherSideOfSecurity(
touchEventRightSide())).isTrue();
}
@Test
public void testSecuritySwitchesSidesInLandscapeUserSwitcherMode() {
Configuration config = new Configuration();
config.orientation = Configuration.ORIENTATION_LANDSCAPE;
when(getContext().getResources().getConfiguration()).thenReturn(config);
setupUserSwitcher();
// check default position
assertSecurityGravity(Gravity.RIGHT | Gravity.BOTTOM);
assertUserSwitcherGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL);
reset(mSecurityViewFlipper);
when(mSecurityViewFlipper.getLayoutParams()).thenReturn(mSecurityViewFlipperLayoutParams);
// change setting so configuration change triggers position change
when(mGlobalSettings.getInt(any(), anyInt())).thenReturn(ONE_HANDED_KEYGUARD_SIDE_LEFT);
mKeyguardSecurityContainer.onConfigurationChanged(new Configuration());
// check position after switching
assertSecurityGravity(Gravity.LEFT | Gravity.BOTTOM);
assertUserSwitcherGravity(Gravity.RIGHT | Gravity.CENTER_VERTICAL);
}
private void assertUserSwitcherGravity(@Gravity.GravityFlags int gravity) {
ViewGroup userSwitcher = mKeyguardSecurityContainer.findViewById(
R.id.keyguard_bouncer_user_switcher);
assertThat(((FrameLayout.LayoutParams) userSwitcher.getLayoutParams()).gravity)
.isEqualTo(gravity);
}
private void assertSecurityGravity(@Gravity.GravityFlags int gravity) {
verify(mSecurityViewFlipper, atLeastOnce()).setLayoutParams(mLayoutCaptor.capture());
assertThat(mLayoutCaptor.getValue().gravity).isEqualTo(gravity);
}
private void setViewWidth(int width) {
mKeyguardSecurityContainer.setRight(width);
mKeyguardSecurityContainer.setLeft(0);
}
private MotionEvent touchEventLeftSide() {
return MotionEvent.obtain(
/* downTime= */0,
/* eventTime= */0,
MotionEvent.ACTION_DOWN,
/* x= */VIEW_WIDTH / 3f,
/* y= */0,
/* metaState= */0);
}
private MotionEvent touchEventRightSide() {
return MotionEvent.obtain(
/* downTime= */0,
/* eventTime= */0,
MotionEvent.ACTION_DOWN,
/* x= */(VIEW_WIDTH / 3f) * 2,
/* y= */0,
/* metaState= */0);
}
private void setupUserSwitcher() {
when(mGlobalSettings.getInt(any(), anyInt())).thenReturn(ONE_HANDED_KEYGUARD_SIDE_RIGHT);
mKeyguardSecurityContainer.initMode(KeyguardSecurityContainer.MODE_USER_SWITCHER,
mGlobalSettings, mFalsingManager, mUserSwitcherController);
}