Merge "Update the bouncer to be able to move to either side of a wide screen." into sc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
69b9601cf5
@@ -14614,6 +14614,29 @@ public final class Settings {
|
||||
public static final String POWER_BUTTON_VERY_LONG_PRESS =
|
||||
"power_button_very_long_press";
|
||||
|
||||
|
||||
/**
|
||||
* Keyguard should be on the left hand side of the screen, for wide screen layouts.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static final int ONE_HANDED_KEYGUARD_SIDE_LEFT = 0;
|
||||
|
||||
/**
|
||||
* Keyguard should be on the right hand side of the screen, for wide screen layouts.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static final int ONE_HANDED_KEYGUARD_SIDE_RIGHT = 1;
|
||||
/**
|
||||
* In one handed mode, which side the keyguard should be on. Allowable values are one of
|
||||
* the ONE_HANDED_KEYGUARD_SIDE_* constants.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@Readable
|
||||
public static final String ONE_HANDED_KEYGUARD_SIDE = "one_handed_keyguard_side";
|
||||
|
||||
/**
|
||||
* Keys we no longer back up under the current schema, but want to continue to
|
||||
* process when restoring historical backup datasets.
|
||||
|
||||
@@ -4203,4 +4203,6 @@
|
||||
<java-symbol type="bool" name="config_telephony5gNonStandalone" />
|
||||
|
||||
<java-symbol type="bool" name="config_voice_data_sms_auto_fallback" />
|
||||
|
||||
<java-symbol type="bool" name="config_enableOneHandedKeyguard" />
|
||||
</resources>
|
||||
|
||||
@@ -147,5 +147,10 @@ public class GlobalSettingsValidators {
|
||||
VALIDATORS.put(Global.DEVELOPMENT_SETTINGS_ENABLED, BOOLEAN_VALIDATOR);
|
||||
VALIDATORS.put(Global.NOTIFICATION_FEEDBACK_ENABLED, BOOLEAN_VALIDATOR);
|
||||
VALIDATORS.put(Global.RESTRICTED_NETWORKING_MODE, BOOLEAN_VALIDATOR);
|
||||
VALIDATORS.put(
|
||||
Global.ONE_HANDED_KEYGUARD_SIDE,
|
||||
new InclusiveIntegerRangeValidator(
|
||||
/* first= */Global.ONE_HANDED_KEYGUARD_SIDE_LEFT,
|
||||
/* last= */Global.ONE_HANDED_KEYGUARD_SIDE_RIGHT));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -283,6 +283,7 @@ public class SettingsBackupTest {
|
||||
Settings.Global.EUICC_REMOVING_INVISIBLE_PROFILES_TIMEOUT_MILLIS,
|
||||
Settings.Global.EUICC_SWITCH_SLOT_TIMEOUT_MILLIS,
|
||||
Settings.Global.FANCY_IME_ANIMATIONS,
|
||||
Settings.Global.ONE_HANDED_KEYGUARD_SIDE,
|
||||
Settings.Global.FORCE_ALLOW_ON_EXTERNAL,
|
||||
Settings.Global.FORCED_APP_STANDBY_ENABLED,
|
||||
Settings.Global.FORCED_APP_STANDBY_FOR_SMALL_BATTERY_ENABLED,
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
<include
|
||||
style="@style/BouncerSecurityContainer"
|
||||
layout="@layout/keyguard_host_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
</FrameLayout>
|
||||
|
||||
|
||||
@@ -41,13 +41,14 @@
|
||||
android:layout_gravity="center">
|
||||
<com.android.keyguard.KeyguardSecurityViewFlipper
|
||||
android:id="@+id/view_flipper"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:clipChildren="false"
|
||||
android:clipToPadding="false"
|
||||
android:paddingTop="@dimen/keyguard_security_view_top_margin"
|
||||
android:paddingStart="@dimen/keyguard_security_view_lateral_margin"
|
||||
android:paddingEnd="@dimen/keyguard_security_view_lateral_margin"
|
||||
android:layout_gravity="center"
|
||||
android:gravity="center">
|
||||
</com.android.keyguard.KeyguardSecurityViewFlipper>
|
||||
</com.android.keyguard.KeyguardSecurityContainer>
|
||||
|
||||
20
packages/SystemUI/res-keyguard/values-sw600dp-land/bools.xml
Normal file
20
packages/SystemUI/res-keyguard/values-sw600dp-land/bools.xml
Normal file
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (C) 2021 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.
|
||||
-->
|
||||
|
||||
<resources>
|
||||
<bool name="can_use_one_handed_bouncer">true</bool>
|
||||
</resources>
|
||||
@@ -22,4 +22,5 @@
|
||||
|
||||
<!-- Allow the menu hard key to be disabled in LockScreen on some devices [DO NOT TRANSLATE] -->
|
||||
<bool name="config_disableMenuKeyInLockScreen">false</bool>
|
||||
<bool name="can_use_one_handed_bouncer">false</bool>
|
||||
</resources>
|
||||
|
||||
@@ -29,12 +29,17 @@ import android.app.AlertDialog;
|
||||
import android.content.Context;
|
||||
import android.graphics.Insets;
|
||||
import android.graphics.Rect;
|
||||
import android.provider.Settings;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.MathUtils;
|
||||
import android.util.TypedValue;
|
||||
import android.view.Gravity;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.OrientationEventListener;
|
||||
import android.view.VelocityTracker;
|
||||
import android.view.View;
|
||||
import android.view.ViewConfiguration;
|
||||
import android.view.ViewPropertyAnimator;
|
||||
import android.view.WindowInsets;
|
||||
import android.view.WindowInsetsAnimation;
|
||||
import android.view.WindowInsetsAnimationControlListener;
|
||||
@@ -55,6 +60,7 @@ import com.android.internal.widget.LockPatternUtils;
|
||||
import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
|
||||
import com.android.systemui.Interpolators;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -99,6 +105,12 @@ public class KeyguardSecurityContainer extends FrameLayout {
|
||||
private boolean mDisappearAnimRunning;
|
||||
private SwipeListener mSwipeListener;
|
||||
|
||||
private boolean mIsSecurityViewLeftAligned = true;
|
||||
private boolean mOneHandedMode = false;
|
||||
private SecurityMode mSecurityMode = SecurityMode.Invalid;
|
||||
private ViewPropertyAnimator mRunningOneHandedAnimator;
|
||||
private final OrientationEventListener mOrientationEventListener;
|
||||
|
||||
private final WindowInsetsAnimation.Callback mWindowInsetsAnimationCallback =
|
||||
new WindowInsetsAnimation.Callback(DISPATCH_MODE_STOP) {
|
||||
|
||||
@@ -157,16 +169,20 @@ public class KeyguardSecurityContainer extends FrameLayout {
|
||||
// Used to notify the container when something interesting happens.
|
||||
public interface SecurityCallback {
|
||||
boolean dismiss(boolean authenticated, int targetUserId, boolean bypassSecondaryLockScreen);
|
||||
|
||||
void userActivity();
|
||||
|
||||
void onSecurityModeChanged(SecurityMode securityMode, boolean needsInput);
|
||||
|
||||
/**
|
||||
* @param strongAuth wheher the user has authenticated with strong authentication like
|
||||
* pattern, password or PIN but not by trust agents or fingerprint
|
||||
* @param strongAuth wheher the user has authenticated with strong authentication like
|
||||
* pattern, password or PIN but not by trust agents or fingerprint
|
||||
* @param targetUserId a user that needs to be the foreground user at the finish completion.
|
||||
*/
|
||||
void finish(boolean strongAuth, int targetUserId);
|
||||
|
||||
void reset();
|
||||
|
||||
void onCancelClicked();
|
||||
}
|
||||
|
||||
@@ -224,12 +240,136 @@ public class KeyguardSecurityContainer extends FrameLayout {
|
||||
super(context, attrs, defStyle);
|
||||
mSpringAnimation = new SpringAnimation(this, DynamicAnimation.Y);
|
||||
mViewConfiguration = ViewConfiguration.get(context);
|
||||
|
||||
mOrientationEventListener = new OrientationEventListener(context) {
|
||||
@Override
|
||||
public void onOrientationChanged(int orientation) {
|
||||
updateLayoutForSecurityMode(mSecurityMode);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void onResume(SecurityMode securityMode, boolean faceAuthEnabled) {
|
||||
mSecurityMode = securityMode;
|
||||
mSecurityViewFlipper.setWindowInsetsAnimationCallback(mWindowInsetsAnimationCallback);
|
||||
updateBiometricRetry(securityMode, faceAuthEnabled);
|
||||
|
||||
updateLayoutForSecurityMode(securityMode);
|
||||
mOrientationEventListener.enable();
|
||||
}
|
||||
|
||||
void updateLayoutForSecurityMode(SecurityMode securityMode) {
|
||||
mSecurityMode = securityMode;
|
||||
mOneHandedMode = canUseOneHandedBouncer();
|
||||
|
||||
if (mOneHandedMode) {
|
||||
mIsSecurityViewLeftAligned = isOneHandedKeyguardLeftAligned(mContext);
|
||||
}
|
||||
|
||||
updateSecurityViewGravity();
|
||||
updateSecurityViewLocation(false);
|
||||
}
|
||||
|
||||
/** Return whether the one-handed keyguard should be enabled. */
|
||||
private boolean canUseOneHandedBouncer() {
|
||||
// Is it enabled?
|
||||
if (!getResources().getBoolean(
|
||||
com.android.internal.R.bool.config_enableOneHandedKeyguard)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!KeyguardSecurityModel.isSecurityViewOneHanded(mSecurityMode)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return getResources().getBoolean(R.bool.can_use_one_handed_bouncer);
|
||||
}
|
||||
|
||||
/** Read whether the one-handed keyguard should be on the left/right from settings. */
|
||||
private boolean isOneHandedKeyguardLeftAligned(Context context) {
|
||||
try {
|
||||
return Settings.Global.getInt(context.getContentResolver(),
|
||||
Settings.Global.ONE_HANDED_KEYGUARD_SIDE)
|
||||
== Settings.Global.ONE_HANDED_KEYGUARD_SIDE_LEFT;
|
||||
} catch (Settings.SettingNotFoundException ex) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private void updateSecurityViewGravity() {
|
||||
View securityView = findKeyguardSecurityView();
|
||||
|
||||
if (securityView == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) securityView.getLayoutParams();
|
||||
|
||||
if (mOneHandedMode) {
|
||||
lp.gravity = Gravity.LEFT | Gravity.BOTTOM;
|
||||
} else {
|
||||
lp.gravity = Gravity.CENTER_HORIZONTAL;
|
||||
}
|
||||
|
||||
securityView.setLayoutParams(lp);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 .
|
||||
*/
|
||||
private void updateSecurityViewLocation(boolean animate) {
|
||||
View securityView = findKeyguardSecurityView();
|
||||
|
||||
if (securityView == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mOneHandedMode) {
|
||||
securityView.setTranslationX(0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (mRunningOneHandedAnimator != null) {
|
||||
mRunningOneHandedAnimator.cancel();
|
||||
mRunningOneHandedAnimator = null;
|
||||
}
|
||||
|
||||
int targetTranslation = mIsSecurityViewLeftAligned ? 0 : (int) (getMeasuredWidth() / 2f);
|
||||
|
||||
if (animate) {
|
||||
mRunningOneHandedAnimator = securityView.animate().translationX(targetTranslation);
|
||||
mRunningOneHandedAnimator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
|
||||
mRunningOneHandedAnimator.setListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
mRunningOneHandedAnimator = null;
|
||||
}
|
||||
});
|
||||
|
||||
mRunningOneHandedAnimator.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
|
||||
mRunningOneHandedAnimator.start();
|
||||
} else {
|
||||
securityView.setTranslationX(targetTranslation);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private KeyguardSecurityViewFlipper findKeyguardSecurityView() {
|
||||
for (int i = 0; i < getChildCount(); i++) {
|
||||
View child = getChildAt(i);
|
||||
|
||||
if (isKeyguardSecurityView(child)) {
|
||||
return (KeyguardSecurityViewFlipper) child;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean isKeyguardSecurityView(View view) {
|
||||
return view instanceof KeyguardSecurityViewFlipper;
|
||||
}
|
||||
|
||||
public void onPause() {
|
||||
@@ -238,6 +378,7 @@ public class KeyguardSecurityContainer extends FrameLayout {
|
||||
mAlertDialog = null;
|
||||
}
|
||||
mSecurityViewFlipper.setWindowInsetsAnimationCallback(null);
|
||||
mOrientationEventListener.disable();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -319,19 +460,44 @@ public class KeyguardSecurityContainer extends FrameLayout {
|
||||
if (mSwipeListener != null) {
|
||||
mSwipeListener.onSwipeUp();
|
||||
}
|
||||
} else {
|
||||
if (!mIsDragging) {
|
||||
handleTap(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void handleTap(MotionEvent event) {
|
||||
// If we're using a fullscreen security mode, skip
|
||||
if (!mOneHandedMode) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Did the tap hit the "other" side of the bouncer?
|
||||
if ((mIsSecurityViewLeftAligned && (event.getX() > getWidth() / 2f))
|
||||
|| (!mIsSecurityViewLeftAligned && (event.getX() < getWidth() / 2f))) {
|
||||
mIsSecurityViewLeftAligned = !mIsSecurityViewLeftAligned;
|
||||
|
||||
Settings.Global.putInt(
|
||||
mContext.getContentResolver(),
|
||||
Settings.Global.ONE_HANDED_KEYGUARD_SIDE,
|
||||
mIsSecurityViewLeftAligned ? Settings.Global.ONE_HANDED_KEYGUARD_SIDE_LEFT
|
||||
: Settings.Global.ONE_HANDED_KEYGUARD_SIDE_RIGHT);
|
||||
|
||||
updateSecurityViewLocation(true);
|
||||
}
|
||||
}
|
||||
|
||||
void setSwipeListener(SwipeListener swipeListener) {
|
||||
mSwipeListener = swipeListener;
|
||||
}
|
||||
|
||||
private void startSpringAnimation(float startVelocity) {
|
||||
mSpringAnimation
|
||||
.setStartVelocity(startVelocity)
|
||||
.animateToFinalPosition(0);
|
||||
.setStartVelocity(startVelocity)
|
||||
.animateToFinalPosition(0);
|
||||
}
|
||||
|
||||
public void startDisappearAnimation(SecurityMode securitySelection) {
|
||||
@@ -441,18 +607,17 @@ public class KeyguardSecurityContainer extends FrameLayout {
|
||||
return insets.inset(0, 0, 0, inset);
|
||||
}
|
||||
|
||||
|
||||
private void showDialog(String title, String message) {
|
||||
if (mAlertDialog != null) {
|
||||
mAlertDialog.dismiss();
|
||||
}
|
||||
|
||||
mAlertDialog = new AlertDialog.Builder(mContext)
|
||||
.setTitle(title)
|
||||
.setMessage(message)
|
||||
.setCancelable(false)
|
||||
.setNeutralButton(R.string.ok, null)
|
||||
.create();
|
||||
.setTitle(title)
|
||||
.setMessage(message)
|
||||
.setCancelable(false)
|
||||
.setNeutralButton(R.string.ok, null)
|
||||
.create();
|
||||
if (!(mContext instanceof Activity)) {
|
||||
mAlertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
|
||||
}
|
||||
@@ -490,6 +655,44 @@ public class KeyguardSecurityContainer extends FrameLayout {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
int maxHeight = 0;
|
||||
int maxWidth = 0;
|
||||
int childState = 0;
|
||||
|
||||
int halfWidthMeasureSpec = MeasureSpec.makeMeasureSpec(
|
||||
MeasureSpec.getSize(widthMeasureSpec) / 2,
|
||||
MeasureSpec.getMode(widthMeasureSpec));
|
||||
|
||||
for (int i = 0; i < getChildCount(); i++) {
|
||||
final View view = getChildAt(i);
|
||||
if (view.getVisibility() != GONE) {
|
||||
if (mOneHandedMode && isKeyguardSecurityView(view)) {
|
||||
measureChildWithMargins(view, halfWidthMeasureSpec, 0,
|
||||
heightMeasureSpec, 0);
|
||||
} else {
|
||||
measureChildWithMargins(view, widthMeasureSpec, 0,
|
||||
heightMeasureSpec, 0);
|
||||
}
|
||||
final LayoutParams lp = (LayoutParams) view.getLayoutParams();
|
||||
maxWidth = Math.max(maxWidth,
|
||||
view.getMeasuredWidth() + lp.leftMargin + lp.rightMargin);
|
||||
maxHeight = Math.max(maxHeight,
|
||||
view.getMeasuredHeight() + lp.topMargin + lp.bottomMargin);
|
||||
childState = combineMeasuredStates(childState, view.getMeasuredState());
|
||||
}
|
||||
}
|
||||
|
||||
// Check against our minimum height and width
|
||||
maxHeight = Math.max(maxHeight, getSuggestedMinimumHeight());
|
||||
maxWidth = Math.max(maxWidth, getSuggestedMinimumWidth());
|
||||
|
||||
setMeasuredDimension(resolveSizeAndState(maxWidth, widthMeasureSpec, childState),
|
||||
resolveSizeAndState(maxHeight, heightMeasureSpec,
|
||||
childState << MEASURED_HEIGHT_STATE_SHIFT));
|
||||
}
|
||||
|
||||
void showAlmostAtWipeDialog(int attempts, int remaining, int userType) {
|
||||
String message = null;
|
||||
switch (userType) {
|
||||
|
||||
@@ -404,6 +404,7 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
|
||||
if (newView != null) {
|
||||
newView.onResume(KeyguardSecurityView.VIEW_REVEALED);
|
||||
mSecurityViewFlipperController.show(newView);
|
||||
mView.updateLayoutForSecurityMode(securityMode);
|
||||
}
|
||||
|
||||
mSecurityCallback.onSecurityModeChanged(
|
||||
|
||||
@@ -92,4 +92,13 @@ public class KeyguardSecurityModel {
|
||||
throw new IllegalStateException("Unknown security quality:" + security);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the given security view should be used in a "one handed" way. This can be
|
||||
* used to change how the security view is drawn (e.g. take up less of the screen, and align to
|
||||
* one side).
|
||||
*/
|
||||
public static boolean isSecurityViewOneHanded(SecurityMode securityMode) {
|
||||
return securityMode == SecurityMode.Pattern || securityMode == SecurityMode.PIN;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,11 +26,16 @@ import static org.mockito.Mockito.when;
|
||||
|
||||
import android.testing.AndroidTestingRunner;
|
||||
import android.testing.TestableLooper;
|
||||
import android.testing.TestableResources;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.WindowInsetsController;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.SysuiTestCase;
|
||||
|
||||
import org.junit.Before;
|
||||
@@ -45,12 +50,21 @@ import org.mockito.junit.MockitoRule;
|
||||
@RunWith(AndroidTestingRunner.class)
|
||||
@TestableLooper.RunWithLooper()
|
||||
public class KeyguardSecurityContainerTest extends SysuiTestCase {
|
||||
private static final int SCREEN_WIDTH = 1600;
|
||||
private static final int FAKE_MEASURE_SPEC =
|
||||
View.MeasureSpec.makeMeasureSpec(SCREEN_WIDTH, View.MeasureSpec.EXACTLY);
|
||||
|
||||
private static final SecurityMode ONE_HANDED_SECURITY_MODE = SecurityMode.PIN;
|
||||
private static final SecurityMode TWO_HANDED_SECURITY_MODE = SecurityMode.Password;
|
||||
|
||||
|
||||
|
||||
@Rule
|
||||
public MockitoRule mRule = MockitoJUnit.rule();
|
||||
|
||||
@Mock
|
||||
private WindowInsetsController mWindowInsetsController;
|
||||
|
||||
@Mock
|
||||
private KeyguardSecurityViewFlipper mSecurityViewFlipper;
|
||||
|
||||
@@ -58,9 +72,18 @@ public class KeyguardSecurityContainerTest extends SysuiTestCase {
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
// Needed here, otherwise when mKeyguardSecurityContainer is created below, it'll cache
|
||||
// the real references (rather than the TestableResources that this call creates).
|
||||
mContext.ensureTestableResources();
|
||||
FrameLayout.LayoutParams securityViewFlipperLayoutParams = new FrameLayout.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
|
||||
|
||||
when(mSecurityViewFlipper.getWindowInsetsController()).thenReturn(mWindowInsetsController);
|
||||
when(mSecurityViewFlipper.getLayoutParams()).thenReturn(securityViewFlipperLayoutParams);
|
||||
mKeyguardSecurityContainer = new KeyguardSecurityContainer(getContext());
|
||||
mKeyguardSecurityContainer.mSecurityViewFlipper = mSecurityViewFlipper;
|
||||
mKeyguardSecurityContainer.addView(mSecurityViewFlipper, new ViewGroup.LayoutParams(
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -69,4 +92,75 @@ public class KeyguardSecurityContainerTest extends SysuiTestCase {
|
||||
verify(mWindowInsetsController).controlWindowInsetsAnimation(eq(ime()), anyLong(), any(),
|
||||
any(), any());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onMeasure_usesFullWidthWithoutOneHandedMode() {
|
||||
setUpKeyguard(
|
||||
/* deviceConfigCanUseOneHandedKeyguard= */false,
|
||||
/* sysuiResourceCanUseOneHandedKeyguard= */ false,
|
||||
ONE_HANDED_SECURITY_MODE);
|
||||
|
||||
mKeyguardSecurityContainer.onMeasure(FAKE_MEASURE_SPEC, FAKE_MEASURE_SPEC);
|
||||
|
||||
verify(mSecurityViewFlipper).measure(FAKE_MEASURE_SPEC, FAKE_MEASURE_SPEC);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onMeasure_usesFullWidthWithDeviceFlagDisabled() {
|
||||
setUpKeyguard(
|
||||
/* deviceConfigCanUseOneHandedKeyguard= */false,
|
||||
/* sysuiResourceCanUseOneHandedKeyguard= */ true,
|
||||
ONE_HANDED_SECURITY_MODE);
|
||||
|
||||
mKeyguardSecurityContainer.onMeasure(FAKE_MEASURE_SPEC, FAKE_MEASURE_SPEC);
|
||||
verify(mSecurityViewFlipper).measure(FAKE_MEASURE_SPEC, FAKE_MEASURE_SPEC);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onMeasure_usesFullWidthWithSysUIFlagDisabled() {
|
||||
setUpKeyguard(
|
||||
/* deviceConfigCanUseOneHandedKeyguard= */true,
|
||||
/* sysuiResourceCanUseOneHandedKeyguard= */ false,
|
||||
ONE_HANDED_SECURITY_MODE);
|
||||
|
||||
mKeyguardSecurityContainer.onMeasure(FAKE_MEASURE_SPEC, FAKE_MEASURE_SPEC);
|
||||
verify(mSecurityViewFlipper).measure(FAKE_MEASURE_SPEC, FAKE_MEASURE_SPEC);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onMeasure_usesHalfWidthWithFlagsEnabled() {
|
||||
setUpKeyguard(
|
||||
/* deviceConfigCanUseOneHandedKeyguard= */true,
|
||||
/* sysuiResourceCanUseOneHandedKeyguard= */ true,
|
||||
ONE_HANDED_SECURITY_MODE);
|
||||
|
||||
int halfWidthMeasureSpec =
|
||||
View.MeasureSpec.makeMeasureSpec(SCREEN_WIDTH / 2, View.MeasureSpec.EXACTLY);
|
||||
mKeyguardSecurityContainer.onMeasure(FAKE_MEASURE_SPEC, FAKE_MEASURE_SPEC);
|
||||
|
||||
verify(mSecurityViewFlipper).measure(halfWidthMeasureSpec, FAKE_MEASURE_SPEC);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onMeasure_usesFullWidthForFullScreenIme() {
|
||||
setUpKeyguard(
|
||||
/* deviceConfigCanUseOneHandedKeyguard= */true,
|
||||
/* sysuiResourceCanUseOneHandedKeyguard= */ true,
|
||||
TWO_HANDED_SECURITY_MODE);
|
||||
|
||||
mKeyguardSecurityContainer.onMeasure(FAKE_MEASURE_SPEC, FAKE_MEASURE_SPEC);
|
||||
verify(mSecurityViewFlipper).measure(FAKE_MEASURE_SPEC, FAKE_MEASURE_SPEC);
|
||||
}
|
||||
|
||||
private void setUpKeyguard(
|
||||
boolean deviceConfigCanUseOneHandedKeyguard,
|
||||
boolean sysuiResourceCanUseOneHandedKeyguard,
|
||||
SecurityMode securityMode) {
|
||||
TestableResources testableResources = mContext.getOrCreateTestableResources();
|
||||
testableResources.addOverride(com.android.internal.R.bool.config_enableOneHandedKeyguard,
|
||||
deviceConfigCanUseOneHandedKeyguard);
|
||||
testableResources.addOverride(R.bool.can_use_one_handed_bouncer,
|
||||
sysuiResourceCanUseOneHandedKeyguard);
|
||||
mKeyguardSecurityContainer.updateLayoutForSecurityMode(securityMode);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user