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

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

Change-Id: I60e2b2aa80586971f0b5219e582be6833fc3b45a
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Michał Brzeziński
2022-06-22 17:16:22 +00:00
committed by Automerger Merge Worker
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. * 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) @ProvidesInterface(version = FalsingManager.VERSION)
public interface FalsingManager { public interface FalsingManager {

View File

@@ -375,10 +375,23 @@ public class KeyguardSecurityContainer extends FrameLayout {
mViewMode.updatePositionByTouchX(x); mViewMode.updatePositionByTouchX(x);
} }
/** Returns whether the inner SecurityViewFlipper is left-aligned when in one-handed mode. */ public boolean isSidedSecurityMode() {
public boolean isOneHandedModeLeftAligned() { return mViewMode instanceof SidedSecurityMode;
return mCurrentMode == MODE_ONE_HANDED }
&& ((OneHandedViewMode) mViewMode).isLeftAligned();
/** 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() { public void onPause() {
@@ -437,12 +450,15 @@ public class KeyguardSecurityContainer extends FrameLayout {
@Override @Override
public boolean onTouchEvent(MotionEvent event) { public boolean onTouchEvent(MotionEvent event) {
final int action = event.getActionMasked(); final int action = event.getActionMasked();
mDoubleTapDetector.onTouchEvent(event);
boolean result = mMotionEventListeners.stream() boolean result = mMotionEventListeners.stream()
.anyMatch(listener -> listener.onTouchEvent(event)) .anyMatch(listener -> listener.onTouchEvent(event))
|| super.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) { switch (action) {
case MotionEvent.ACTION_MOVE: case MotionEvent.ACTION_MOVE:
mVelocityTracker.addMovement(event); mVelocityTracker.addMovement(event);
@@ -487,11 +503,16 @@ public class KeyguardSecurityContainer extends FrameLayout {
private class DoubleTapListener extends GestureDetector.SimpleOnGestureListener { private class DoubleTapListener extends GestureDetector.SimpleOnGestureListener {
@Override @Override
public boolean onDoubleTap(MotionEvent e) { public boolean onDoubleTap(MotionEvent e) {
if (!mIsDragging) { return handleDoubleTap(e);
mViewMode.handleDoubleTap(e); }
} }
@VisibleForTesting boolean handleDoubleTap(MotionEvent e) {
if (!mIsDragging) {
mViewMode.handleDoubleTap(e);
return true; return true;
} }
return false;
} }
void addMotionEventListener(Gefingerpoken listener) { void addMotionEventListener(Gefingerpoken listener) {
@@ -770,6 +791,70 @@ public class KeyguardSecurityContainer extends FrameLayout {
default void onDestroy() {}; 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 * 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 * User switcher mode will display both the current user icon as well as
* a user switcher, in both portrait and landscape modes. * a user switcher, in both portrait and landscape modes.
*/ */
static class UserSwitcherViewMode implements ViewMode { static class UserSwitcherViewMode extends SidedSecurityMode {
private ViewGroup mView; private ViewGroup mView;
private ViewGroup mUserSwitcherViewGroup; private ViewGroup mUserSwitcherViewGroup;
private KeyguardSecurityViewFlipper mViewFlipper; private KeyguardSecurityViewFlipper mViewFlipper;
@@ -819,6 +904,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= */false);
mView = v; mView = v;
mViewFlipper = viewFlipper; mViewFlipper = viewFlipper;
mFalsingManager = falsingManager; mFalsingManager = falsingManager;
@@ -1030,6 +1116,10 @@ public class KeyguardSecurityContainer extends FrameLayout {
@Override @Override
public void updateSecurityViewLocation() { 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); int yTrans = mResources.getDimensionPixelSize(R.dimen.bouncer_user_switcher_y_trans);
if (mResources.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) { if (mResources.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
@@ -1039,8 +1129,12 @@ public class KeyguardSecurityContainer extends FrameLayout {
mUserSwitcherViewGroup.setTranslationY(yTrans); mUserSwitcherViewGroup.setTranslationY(yTrans);
mViewFlipper.setTranslationY(-yTrans); mViewFlipper.setTranslationY(-yTrans);
} else { } else {
updateViewGravity(mViewFlipper, Gravity.RIGHT | Gravity.BOTTOM); int securityHorizontalGravity = leftAlign ? Gravity.LEFT : Gravity.RIGHT;
updateViewGravity(mUserSwitcherViewGroup, Gravity.LEFT | Gravity.CENTER_VERTICAL); 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
@@ -1060,20 +1154,19 @@ public class KeyguardSecurityContainer extends FrameLayout {
* Logic to enabled one-handed bouncer mode. Supports animating the bouncer * Logic to enabled one-handed bouncer mode. Supports animating the bouncer
* between alternate sides of the display. * between alternate sides of the display.
*/ */
static class OneHandedViewMode implements ViewMode { static class OneHandedViewMode extends SidedSecurityMode {
@Nullable private ValueAnimator mRunningOneHandedAnimator; @Nullable private ValueAnimator mRunningOneHandedAnimator;
private ViewGroup mView; private ViewGroup mView;
private KeyguardSecurityViewFlipper mViewFlipper; private KeyguardSecurityViewFlipper mViewFlipper;
private GlobalSettings mGlobalSettings;
@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= */true);
mView = v; mView = v;
mViewFlipper = viewFlipper; mViewFlipper = viewFlipper;
mGlobalSettings = globalSettings;
updateSecurityViewGravity(); updateSecurityViewGravity();
updateSecurityViewLocation(isLeftAligned(), /* animate= */false); updateSecurityViewLocation(isLeftAligned(), /* animate= */false);
@@ -1107,43 +1200,6 @@ public class KeyguardSecurityContainer extends FrameLayout {
updateSecurityViewLocation(isTouchOnLeft, /* animate= */false); 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 @Override
public void updateSecurityViewLocation() { public void updateSecurityViewLocation() {
updateSecurityViewLocation(isLeftAligned(), /* animate= */false); 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 * 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 * animation. This is triggered when the user double taps on the side of the screen that is
* currently occupied by the security view. * not currently occupied by the security view.
*/ */
private void updateSecurityViewLocation(boolean leftAlign, boolean animate) { protected void updateSecurityViewLocation(boolean leftAlign, boolean animate) {
if (mRunningOneHandedAnimator != null) { if (mRunningOneHandedAnimator != null) {
mRunningOneHandedAnimator.cancel(); mRunningOneHandedAnimator.cancel();
mRunningOneHandedAnimator = null; 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 // 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 across. In that case, inhibit the falsing (otherwise the taps
// to move the bouncer to each screen side can end up closing it instead). // to move the bouncer to each screen side can end up closing it instead).
if (mView.getMode() == KeyguardSecurityContainer.MODE_ONE_HANDED) { if (mView.isTouchOnTheOtherSideOfSecurity(ev)) {
boolean isLeftAligned = mView.isOneHandedModeLeftAligned(); mFalsingCollector.avoidGesture();
if ((isLeftAligned && ev.getX() > mView.getWidth() / 2f)
|| (!isLeftAligned && ev.getX() <= mView.getWidth() / 2f)) {
mFalsingCollector.avoidGesture();
}
} }
if (mTouchDown != null) { if (mTouchDown != null) {
@@ -169,8 +165,8 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
public void reportUnlockAttempt(int userId, boolean success, int timeoutMs) { public void reportUnlockAttempt(int userId, boolean success, int timeoutMs) {
int bouncerSide = SysUiStatsLog.KEYGUARD_BOUNCER_PASSWORD_ENTERED__SIDE__DEFAULT; int bouncerSide = SysUiStatsLog.KEYGUARD_BOUNCER_PASSWORD_ENTERED__SIDE__DEFAULT;
if (mView.getMode() == KeyguardSecurityContainer.MODE_ONE_HANDED) { if (mView.isSidedSecurityMode()) {
bouncerSide = mView.isOneHandedModeLeftAligned() bouncerSide = mView.isSecurityLeftAligned()
? SysUiStatsLog.KEYGUARD_BOUNCER_PASSWORD_ENTERED__SIDE__LEFT ? SysUiStatsLog.KEYGUARD_BOUNCER_PASSWORD_ENTERED__SIDE__LEFT
: SysUiStatsLog.KEYGUARD_BOUNCER_PASSWORD_ENTERED__SIDE__RIGHT; : SysUiStatsLog.KEYGUARD_BOUNCER_PASSWORD_ENTERED__SIDE__RIGHT;
} }
@@ -367,8 +363,8 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
public void onResume(int reason) { public void onResume(int reason) {
if (mCurrentSecurityMode != SecurityMode.None) { if (mCurrentSecurityMode != SecurityMode.None) {
int state = SysUiStatsLog.KEYGUARD_BOUNCER_STATE_CHANGED__STATE__SHOWN; int state = SysUiStatsLog.KEYGUARD_BOUNCER_STATE_CHANGED__STATE__SHOWN;
if (mView.getMode() == KeyguardSecurityContainer.MODE_ONE_HANDED) { if (mView.isSidedSecurityMode()) {
state = mView.isOneHandedModeLeftAligned() state = mView.isSecurityLeftAligned()
? SysUiStatsLog.KEYGUARD_BOUNCER_STATE_CHANGED__STATE__SHOWN_LEFT ? SysUiStatsLog.KEYGUARD_BOUNCER_STATE_CHANGED__STATE__SHOWN_LEFT
: SysUiStatsLog.KEYGUARD_BOUNCER_STATE_CHANGED__STATE__SHOWN_RIGHT; : SysUiStatsLog.KEYGUARD_BOUNCER_STATE_CHANGED__STATE__SHOWN_RIGHT;
} }

View File

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

View File

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

View File

@@ -16,6 +16,9 @@
package com.android.keyguard; 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.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.WindowInsets.Type.ime; import static android.view.WindowInsets.Type.ime;
import static android.view.WindowInsets.Type.systemBars; 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 com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.never; import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset; import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
@@ -34,10 +39,10 @@ import static org.mockito.Mockito.when;
import android.content.pm.UserInfo; import android.content.pm.UserInfo;
import android.content.res.Configuration; import android.content.res.Configuration;
import android.graphics.Insets; import android.graphics.Insets;
import android.provider.Settings;
import android.testing.AndroidTestingRunner; import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper; import android.testing.TestableLooper;
import android.view.Gravity; import android.view.Gravity;
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;
@@ -70,6 +75,9 @@ import java.util.ArrayList;
@RunWith(AndroidTestingRunner.class) @RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper() @TestableLooper.RunWithLooper()
public class KeyguardSecurityContainerTest extends SysuiTestCase { public class KeyguardSecurityContainerTest extends SysuiTestCase {
private static final int VIEW_WIDTH = 1600;
private int mScreenWidth; private int mScreenWidth;
private int mFakeMeasureSpec; private int mFakeMeasureSpec;
@@ -212,14 +220,12 @@ public class KeyguardSecurityContainerTest extends SysuiTestCase {
mKeyguardSecurityContainer.updatePositionByTouchX( mKeyguardSecurityContainer.updatePositionByTouchX(
mKeyguardSecurityContainer.getWidth() - 1f); mKeyguardSecurityContainer.getWidth() - 1f);
verify(mGlobalSettings).putInt(Settings.Global.ONE_HANDED_KEYGUARD_SIDE, verify(mGlobalSettings).putInt(ONE_HANDED_KEYGUARD_SIDE, ONE_HANDED_KEYGUARD_SIDE_RIGHT);
Settings.Global.ONE_HANDED_KEYGUARD_SIDE_RIGHT);
verify(mSecurityViewFlipper).setTranslationX( verify(mSecurityViewFlipper).setTranslationX(
mKeyguardSecurityContainer.getWidth() - mSecurityViewFlipper.getWidth()); mKeyguardSecurityContainer.getWidth() - mSecurityViewFlipper.getWidth());
mKeyguardSecurityContainer.updatePositionByTouchX(1f); mKeyguardSecurityContainer.updatePositionByTouchX(1f);
verify(mGlobalSettings).putInt(Settings.Global.ONE_HANDED_KEYGUARD_SIDE, verify(mGlobalSettings).putInt(ONE_HANDED_KEYGUARD_SIDE, ONE_HANDED_KEYGUARD_SIDE_LEFT);
Settings.Global.ONE_HANDED_KEYGUARD_SIDE_LEFT);
verify(mSecurityViewFlipper).setTranslationX(0.0f); verify(mSecurityViewFlipper).setTranslationX(0.0f);
} }
@@ -253,10 +259,7 @@ public class KeyguardSecurityContainerTest extends SysuiTestCase {
// THEN views are oriented side by side // THEN views are oriented side by side
verify(mSecurityViewFlipper).setLayoutParams(mLayoutCaptor.capture()); verify(mSecurityViewFlipper).setLayoutParams(mLayoutCaptor.capture());
assertThat(mLayoutCaptor.getValue().gravity).isEqualTo(Gravity.RIGHT | Gravity.BOTTOM); assertThat(mLayoutCaptor.getValue().gravity).isEqualTo(Gravity.RIGHT | Gravity.BOTTOM);
ViewGroup userSwitcher = mKeyguardSecurityContainer.findViewById( assertUserSwitcherGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL);
R.id.keyguard_bouncer_user_switcher);
assertThat(((FrameLayout.LayoutParams) userSwitcher.getLayoutParams()).gravity)
.isEqualTo(Gravity.LEFT | Gravity.CENTER_VERTICAL);
} }
@Test @Test
@@ -276,10 +279,7 @@ public class KeyguardSecurityContainerTest extends SysuiTestCase {
// THEN views are both centered horizontally // THEN views are both centered horizontally
verify(mSecurityViewFlipper).setLayoutParams(mLayoutCaptor.capture()); verify(mSecurityViewFlipper).setLayoutParams(mLayoutCaptor.capture());
assertThat(mLayoutCaptor.getValue().gravity).isEqualTo(Gravity.CENTER_HORIZONTAL); assertThat(mLayoutCaptor.getValue().gravity).isEqualTo(Gravity.CENTER_HORIZONTAL);
ViewGroup userSwitcher = mKeyguardSecurityContainer.findViewById( assertUserSwitcherGravity(Gravity.CENTER_HORIZONTAL);
R.id.keyguard_bouncer_user_switcher);
assertThat(((FrameLayout.LayoutParams) userSwitcher.getLayoutParams()).gravity)
.isEqualTo(Gravity.CENTER_HORIZONTAL);
} }
@Test @Test
@@ -310,7 +310,85 @@ public class KeyguardSecurityContainerTest extends SysuiTestCase {
assertThat(anchor.isClickable()).isTrue(); 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() { private void setupUserSwitcher() {
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);
} }