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 =
|
public static final String POWER_BUTTON_VERY_LONG_PRESS =
|
||||||
"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
|
* Keys we no longer back up under the current schema, but want to continue to
|
||||||
* process when restoring historical backup datasets.
|
* process when restoring historical backup datasets.
|
||||||
|
|||||||
@@ -4203,4 +4203,6 @@
|
|||||||
<java-symbol type="bool" name="config_telephony5gNonStandalone" />
|
<java-symbol type="bool" name="config_telephony5gNonStandalone" />
|
||||||
|
|
||||||
<java-symbol type="bool" name="config_voice_data_sms_auto_fallback" />
|
<java-symbol type="bool" name="config_voice_data_sms_auto_fallback" />
|
||||||
|
|
||||||
|
<java-symbol type="bool" name="config_enableOneHandedKeyguard" />
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -147,5 +147,10 @@ public class GlobalSettingsValidators {
|
|||||||
VALIDATORS.put(Global.DEVELOPMENT_SETTINGS_ENABLED, BOOLEAN_VALIDATOR);
|
VALIDATORS.put(Global.DEVELOPMENT_SETTINGS_ENABLED, BOOLEAN_VALIDATOR);
|
||||||
VALIDATORS.put(Global.NOTIFICATION_FEEDBACK_ENABLED, BOOLEAN_VALIDATOR);
|
VALIDATORS.put(Global.NOTIFICATION_FEEDBACK_ENABLED, BOOLEAN_VALIDATOR);
|
||||||
VALIDATORS.put(Global.RESTRICTED_NETWORKING_MODE, 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_REMOVING_INVISIBLE_PROFILES_TIMEOUT_MILLIS,
|
||||||
Settings.Global.EUICC_SWITCH_SLOT_TIMEOUT_MILLIS,
|
Settings.Global.EUICC_SWITCH_SLOT_TIMEOUT_MILLIS,
|
||||||
Settings.Global.FANCY_IME_ANIMATIONS,
|
Settings.Global.FANCY_IME_ANIMATIONS,
|
||||||
|
Settings.Global.ONE_HANDED_KEYGUARD_SIDE,
|
||||||
Settings.Global.FORCE_ALLOW_ON_EXTERNAL,
|
Settings.Global.FORCE_ALLOW_ON_EXTERNAL,
|
||||||
Settings.Global.FORCED_APP_STANDBY_ENABLED,
|
Settings.Global.FORCED_APP_STANDBY_ENABLED,
|
||||||
Settings.Global.FORCED_APP_STANDBY_FOR_SMALL_BATTERY_ENABLED,
|
Settings.Global.FORCED_APP_STANDBY_FOR_SMALL_BATTERY_ENABLED,
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
<include
|
<include
|
||||||
style="@style/BouncerSecurityContainer"
|
style="@style/BouncerSecurityContainer"
|
||||||
layout="@layout/keyguard_host_view"
|
layout="@layout/keyguard_host_view"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content" />
|
android:layout_height="wrap_content" />
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
|
||||||
|
|||||||
@@ -41,13 +41,14 @@
|
|||||||
android:layout_gravity="center">
|
android:layout_gravity="center">
|
||||||
<com.android.keyguard.KeyguardSecurityViewFlipper
|
<com.android.keyguard.KeyguardSecurityViewFlipper
|
||||||
android:id="@+id/view_flipper"
|
android:id="@+id/view_flipper"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="wrap_content"
|
||||||
android:clipChildren="false"
|
android:clipChildren="false"
|
||||||
android:clipToPadding="false"
|
android:clipToPadding="false"
|
||||||
android:paddingTop="@dimen/keyguard_security_view_top_margin"
|
android:paddingTop="@dimen/keyguard_security_view_top_margin"
|
||||||
android:paddingStart="@dimen/keyguard_security_view_lateral_margin"
|
android:paddingStart="@dimen/keyguard_security_view_lateral_margin"
|
||||||
android:paddingEnd="@dimen/keyguard_security_view_lateral_margin"
|
android:paddingEnd="@dimen/keyguard_security_view_lateral_margin"
|
||||||
|
android:layout_gravity="center"
|
||||||
android:gravity="center">
|
android:gravity="center">
|
||||||
</com.android.keyguard.KeyguardSecurityViewFlipper>
|
</com.android.keyguard.KeyguardSecurityViewFlipper>
|
||||||
</com.android.keyguard.KeyguardSecurityContainer>
|
</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] -->
|
<!-- Allow the menu hard key to be disabled in LockScreen on some devices [DO NOT TRANSLATE] -->
|
||||||
<bool name="config_disableMenuKeyInLockScreen">false</bool>
|
<bool name="config_disableMenuKeyInLockScreen">false</bool>
|
||||||
|
<bool name="can_use_one_handed_bouncer">false</bool>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -29,12 +29,17 @@ import android.app.AlertDialog;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.Insets;
|
import android.graphics.Insets;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
|
import android.provider.Settings;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.util.MathUtils;
|
import android.util.MathUtils;
|
||||||
import android.util.TypedValue;
|
import android.util.TypedValue;
|
||||||
|
import android.view.Gravity;
|
||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
|
import android.view.OrientationEventListener;
|
||||||
import android.view.VelocityTracker;
|
import android.view.VelocityTracker;
|
||||||
|
import android.view.View;
|
||||||
import android.view.ViewConfiguration;
|
import android.view.ViewConfiguration;
|
||||||
|
import android.view.ViewPropertyAnimator;
|
||||||
import android.view.WindowInsets;
|
import android.view.WindowInsets;
|
||||||
import android.view.WindowInsetsAnimation;
|
import android.view.WindowInsetsAnimation;
|
||||||
import android.view.WindowInsetsAnimationControlListener;
|
import android.view.WindowInsetsAnimationControlListener;
|
||||||
@@ -55,6 +60,7 @@ import com.android.internal.widget.LockPatternUtils;
|
|||||||
import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
|
import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
|
||||||
import com.android.systemui.Interpolators;
|
import com.android.systemui.Interpolators;
|
||||||
import com.android.systemui.R;
|
import com.android.systemui.R;
|
||||||
|
import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -99,6 +105,12 @@ public class KeyguardSecurityContainer extends FrameLayout {
|
|||||||
private boolean mDisappearAnimRunning;
|
private boolean mDisappearAnimRunning;
|
||||||
private SwipeListener mSwipeListener;
|
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 =
|
private final WindowInsetsAnimation.Callback mWindowInsetsAnimationCallback =
|
||||||
new WindowInsetsAnimation.Callback(DISPATCH_MODE_STOP) {
|
new WindowInsetsAnimation.Callback(DISPATCH_MODE_STOP) {
|
||||||
|
|
||||||
@@ -157,16 +169,20 @@ public class KeyguardSecurityContainer extends FrameLayout {
|
|||||||
// Used to notify the container when something interesting happens.
|
// Used to notify the container when something interesting happens.
|
||||||
public interface SecurityCallback {
|
public interface SecurityCallback {
|
||||||
boolean dismiss(boolean authenticated, int targetUserId, boolean bypassSecondaryLockScreen);
|
boolean dismiss(boolean authenticated, int targetUserId, boolean bypassSecondaryLockScreen);
|
||||||
|
|
||||||
void userActivity();
|
void userActivity();
|
||||||
|
|
||||||
void onSecurityModeChanged(SecurityMode securityMode, boolean needsInput);
|
void onSecurityModeChanged(SecurityMode securityMode, boolean needsInput);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param strongAuth wheher the user has authenticated with strong authentication like
|
* @param strongAuth wheher the user has authenticated with strong authentication like
|
||||||
* pattern, password or PIN but not by trust agents or fingerprint
|
* 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.
|
* @param targetUserId a user that needs to be the foreground user at the finish completion.
|
||||||
*/
|
*/
|
||||||
void finish(boolean strongAuth, int targetUserId);
|
void finish(boolean strongAuth, int targetUserId);
|
||||||
|
|
||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
void onCancelClicked();
|
void onCancelClicked();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -224,12 +240,136 @@ public class KeyguardSecurityContainer extends FrameLayout {
|
|||||||
super(context, attrs, defStyle);
|
super(context, attrs, defStyle);
|
||||||
mSpringAnimation = new SpringAnimation(this, DynamicAnimation.Y);
|
mSpringAnimation = new SpringAnimation(this, DynamicAnimation.Y);
|
||||||
mViewConfiguration = ViewConfiguration.get(context);
|
mViewConfiguration = ViewConfiguration.get(context);
|
||||||
|
|
||||||
|
mOrientationEventListener = new OrientationEventListener(context) {
|
||||||
|
@Override
|
||||||
|
public void onOrientationChanged(int orientation) {
|
||||||
|
updateLayoutForSecurityMode(mSecurityMode);
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
void onResume(SecurityMode securityMode, boolean faceAuthEnabled) {
|
void onResume(SecurityMode securityMode, boolean faceAuthEnabled) {
|
||||||
|
mSecurityMode = securityMode;
|
||||||
mSecurityViewFlipper.setWindowInsetsAnimationCallback(mWindowInsetsAnimationCallback);
|
mSecurityViewFlipper.setWindowInsetsAnimationCallback(mWindowInsetsAnimationCallback);
|
||||||
updateBiometricRetry(securityMode, faceAuthEnabled);
|
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() {
|
public void onPause() {
|
||||||
@@ -238,6 +378,7 @@ public class KeyguardSecurityContainer extends FrameLayout {
|
|||||||
mAlertDialog = null;
|
mAlertDialog = null;
|
||||||
}
|
}
|
||||||
mSecurityViewFlipper.setWindowInsetsAnimationCallback(null);
|
mSecurityViewFlipper.setWindowInsetsAnimationCallback(null);
|
||||||
|
mOrientationEventListener.disable();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -319,19 +460,44 @@ public class KeyguardSecurityContainer extends FrameLayout {
|
|||||||
if (mSwipeListener != null) {
|
if (mSwipeListener != null) {
|
||||||
mSwipeListener.onSwipeUp();
|
mSwipeListener.onSwipeUp();
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if (!mIsDragging) {
|
||||||
|
handleTap(event);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
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) {
|
void setSwipeListener(SwipeListener swipeListener) {
|
||||||
mSwipeListener = swipeListener;
|
mSwipeListener = swipeListener;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void startSpringAnimation(float startVelocity) {
|
private void startSpringAnimation(float startVelocity) {
|
||||||
mSpringAnimation
|
mSpringAnimation
|
||||||
.setStartVelocity(startVelocity)
|
.setStartVelocity(startVelocity)
|
||||||
.animateToFinalPosition(0);
|
.animateToFinalPosition(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void startDisappearAnimation(SecurityMode securitySelection) {
|
public void startDisappearAnimation(SecurityMode securitySelection) {
|
||||||
@@ -441,18 +607,17 @@ public class KeyguardSecurityContainer extends FrameLayout {
|
|||||||
return insets.inset(0, 0, 0, inset);
|
return insets.inset(0, 0, 0, inset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void showDialog(String title, String message) {
|
private void showDialog(String title, String message) {
|
||||||
if (mAlertDialog != null) {
|
if (mAlertDialog != null) {
|
||||||
mAlertDialog.dismiss();
|
mAlertDialog.dismiss();
|
||||||
}
|
}
|
||||||
|
|
||||||
mAlertDialog = new AlertDialog.Builder(mContext)
|
mAlertDialog = new AlertDialog.Builder(mContext)
|
||||||
.setTitle(title)
|
.setTitle(title)
|
||||||
.setMessage(message)
|
.setMessage(message)
|
||||||
.setCancelable(false)
|
.setCancelable(false)
|
||||||
.setNeutralButton(R.string.ok, null)
|
.setNeutralButton(R.string.ok, null)
|
||||||
.create();
|
.create();
|
||||||
if (!(mContext instanceof Activity)) {
|
if (!(mContext instanceof Activity)) {
|
||||||
mAlertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
|
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) {
|
void showAlmostAtWipeDialog(int attempts, int remaining, int userType) {
|
||||||
String message = null;
|
String message = null;
|
||||||
switch (userType) {
|
switch (userType) {
|
||||||
|
|||||||
@@ -404,6 +404,7 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
|
|||||||
if (newView != null) {
|
if (newView != null) {
|
||||||
newView.onResume(KeyguardSecurityView.VIEW_REVEALED);
|
newView.onResume(KeyguardSecurityView.VIEW_REVEALED);
|
||||||
mSecurityViewFlipperController.show(newView);
|
mSecurityViewFlipperController.show(newView);
|
||||||
|
mView.updateLayoutForSecurityMode(securityMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
mSecurityCallback.onSecurityModeChanged(
|
mSecurityCallback.onSecurityModeChanged(
|
||||||
|
|||||||
@@ -92,4 +92,13 @@ public class KeyguardSecurityModel {
|
|||||||
throw new IllegalStateException("Unknown security quality:" + security);
|
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.AndroidTestingRunner;
|
||||||
import android.testing.TestableLooper;
|
import android.testing.TestableLooper;
|
||||||
|
import android.testing.TestableResources;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
import android.view.WindowInsetsController;
|
import android.view.WindowInsetsController;
|
||||||
|
import android.widget.FrameLayout;
|
||||||
|
|
||||||
import androidx.test.filters.SmallTest;
|
import androidx.test.filters.SmallTest;
|
||||||
|
|
||||||
import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
|
import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
|
||||||
|
import com.android.systemui.R;
|
||||||
import com.android.systemui.SysuiTestCase;
|
import com.android.systemui.SysuiTestCase;
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
@@ -45,12 +50,21 @@ import org.mockito.junit.MockitoRule;
|
|||||||
@RunWith(AndroidTestingRunner.class)
|
@RunWith(AndroidTestingRunner.class)
|
||||||
@TestableLooper.RunWithLooper()
|
@TestableLooper.RunWithLooper()
|
||||||
public class KeyguardSecurityContainerTest extends SysuiTestCase {
|
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
|
@Rule
|
||||||
public MockitoRule mRule = MockitoJUnit.rule();
|
public MockitoRule mRule = MockitoJUnit.rule();
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
private WindowInsetsController mWindowInsetsController;
|
private WindowInsetsController mWindowInsetsController;
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
private KeyguardSecurityViewFlipper mSecurityViewFlipper;
|
private KeyguardSecurityViewFlipper mSecurityViewFlipper;
|
||||||
|
|
||||||
@@ -58,9 +72,18 @@ public class KeyguardSecurityContainerTest extends SysuiTestCase {
|
|||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setup() {
|
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.getWindowInsetsController()).thenReturn(mWindowInsetsController);
|
||||||
|
when(mSecurityViewFlipper.getLayoutParams()).thenReturn(securityViewFlipperLayoutParams);
|
||||||
mKeyguardSecurityContainer = new KeyguardSecurityContainer(getContext());
|
mKeyguardSecurityContainer = new KeyguardSecurityContainer(getContext());
|
||||||
mKeyguardSecurityContainer.mSecurityViewFlipper = mSecurityViewFlipper;
|
mKeyguardSecurityContainer.mSecurityViewFlipper = mSecurityViewFlipper;
|
||||||
|
mKeyguardSecurityContainer.addView(mSecurityViewFlipper, new ViewGroup.LayoutParams(
|
||||||
|
ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -69,4 +92,75 @@ public class KeyguardSecurityContainerTest extends SysuiTestCase {
|
|||||||
verify(mWindowInsetsController).controlWindowInsetsAnimation(eq(ime()), anyLong(), any(),
|
verify(mWindowInsetsController).controlWindowInsetsAnimation(eq(ime()), anyLong(), any(),
|
||||||
any(), 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