Merge "Remove KeyguardHostView" into tm-qpr-dev
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<!--
|
<!--
|
||||||
**
|
**
|
||||||
** Copyright 2012, The Android Open Source Project
|
** Copyright 2023, The Android Open Source Project
|
||||||
**
|
**
|
||||||
** Licensed under the Apache License, Version 2.0 (the "License")
|
** Licensed under the Apache License, Version 2.0 (the "License")
|
||||||
** you may not use this file except in compliance with the License.
|
** you may not use this file except in compliance with the License.
|
||||||
@@ -17,12 +17,10 @@
|
|||||||
*/
|
*/
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<!-- This is the host view that generally contains two sub views: the widget view
|
<com.android.keyguard.KeyguardSecurityContainer
|
||||||
and the security view. -->
|
|
||||||
<com.android.keyguard.KeyguardHostView
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:androidprv="http://schemas.android.com/apk/res-auto"
|
xmlns:androidprv="http://schemas.android.com/apk/res-auto"
|
||||||
android:id="@+id/keyguard_host_view"
|
android:id="@+id/keyguard_security_container"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:clipChildren="false"
|
android:clipChildren="false"
|
||||||
@@ -30,27 +28,15 @@
|
|||||||
android:paddingTop="@dimen/keyguard_lock_padding"
|
android:paddingTop="@dimen/keyguard_lock_padding"
|
||||||
android:importantForAccessibility="yes"> <!-- Needed because TYPE_WINDOW_STATE_CHANGED is sent
|
android:importantForAccessibility="yes"> <!-- Needed because TYPE_WINDOW_STATE_CHANGED is sent
|
||||||
from this view when bouncer is shown -->
|
from this view when bouncer is shown -->
|
||||||
|
<com.android.keyguard.KeyguardSecurityViewFlipper
|
||||||
<com.android.keyguard.KeyguardSecurityContainer
|
android:id="@+id/view_flipper"
|
||||||
android:id="@+id/keyguard_security_container"
|
android:layout_width="wrap_content"
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:clipChildren="false"
|
android:clipChildren="false"
|
||||||
android:clipToPadding="false"
|
android:clipToPadding="false"
|
||||||
android:padding="0dp"
|
android:paddingTop="@dimen/keyguard_security_view_top_margin"
|
||||||
android:fitsSystemWindows="true"
|
android:layout_gravity="center"
|
||||||
android:layout_gravity="center">
|
android:gravity="center">
|
||||||
<com.android.keyguard.KeyguardSecurityViewFlipper
|
</com.android.keyguard.KeyguardSecurityViewFlipper>
|
||||||
android:id="@+id/view_flipper"
|
</com.android.keyguard.KeyguardSecurityContainer>
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:clipChildren="false"
|
|
||||||
android:clipToPadding="false"
|
|
||||||
android:paddingTop="@dimen/keyguard_security_view_top_margin"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:gravity="center">
|
|
||||||
</com.android.keyguard.KeyguardSecurityViewFlipper>
|
|
||||||
</com.android.keyguard.KeyguardSecurityContainer>
|
|
||||||
|
|
||||||
</com.android.keyguard.KeyguardHostView>
|
|
||||||
|
|
||||||
@@ -1,78 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2007 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.android.keyguard;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.graphics.Canvas;
|
|
||||||
import android.util.AttributeSet;
|
|
||||||
import android.view.MotionEvent;
|
|
||||||
import android.widget.FrameLayout;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Base class for keyguard view. {@link #reset} is where you should
|
|
||||||
* reset the state of your view. Use the {@link KeyguardViewCallback} via
|
|
||||||
* {@link #getCallback()} to send information back (such as poking the wake lock,
|
|
||||||
* or finishing the keyguard).
|
|
||||||
*
|
|
||||||
* Handles intercepting of media keys that still work when the keyguard is
|
|
||||||
* showing.
|
|
||||||
*/
|
|
||||||
public class KeyguardHostView extends FrameLayout {
|
|
||||||
|
|
||||||
protected ViewMediatorCallback mViewMediatorCallback;
|
|
||||||
private boolean mIsInteractable;
|
|
||||||
|
|
||||||
public KeyguardHostView(Context context) {
|
|
||||||
this(context, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public KeyguardHostView(Context context, AttributeSet attrs) {
|
|
||||||
super(context, attrs);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void dispatchDraw(Canvas canvas) {
|
|
||||||
super.dispatchDraw(canvas);
|
|
||||||
if (mViewMediatorCallback != null) {
|
|
||||||
mViewMediatorCallback.keyguardDoneDrawing();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setViewMediatorCallback(ViewMediatorCallback viewMediatorCallback) {
|
|
||||||
mViewMediatorCallback = viewMediatorCallback;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Set true if the view can be interacted with */
|
|
||||||
public void setInteractable(boolean isInteractable) {
|
|
||||||
mIsInteractable = isInteractable;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Make sure to disallow touches while transitioning the bouncer, otherwise
|
|
||||||
* it can remain interactable even when barely visible.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean onInterceptTouchEvent(MotionEvent ev) {
|
|
||||||
return !mIsInteractable;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** True to consume any events that are sent to it */
|
|
||||||
@Override
|
|
||||||
public boolean onTouchEvent(MotionEvent ev) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,535 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2020 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.android.keyguard;
|
|
||||||
|
|
||||||
import android.app.ActivityManager;
|
|
||||||
import android.content.res.ColorStateList;
|
|
||||||
import android.content.res.Resources;
|
|
||||||
import android.media.AudioManager;
|
|
||||||
import android.os.SystemClock;
|
|
||||||
import android.telephony.TelephonyManager;
|
|
||||||
import android.util.Log;
|
|
||||||
import android.util.MathUtils;
|
|
||||||
import android.view.KeyEvent;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.View.OnKeyListener;
|
|
||||||
import android.view.ViewTreeObserver;
|
|
||||||
import android.widget.FrameLayout;
|
|
||||||
import android.window.OnBackAnimationCallback;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
|
|
||||||
import com.android.keyguard.KeyguardSecurityContainer.SecurityCallback;
|
|
||||||
import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
|
|
||||||
import com.android.keyguard.dagger.KeyguardBouncerScope;
|
|
||||||
import com.android.settingslib.Utils;
|
|
||||||
import com.android.systemui.R;
|
|
||||||
import com.android.systemui.plugins.ActivityStarter;
|
|
||||||
import com.android.systemui.util.ViewController;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
|
||||||
|
|
||||||
/** Controller for a {@link KeyguardHostView}. */
|
|
||||||
@KeyguardBouncerScope
|
|
||||||
public class KeyguardHostViewController extends ViewController<KeyguardHostView> {
|
|
||||||
private static final String TAG = "KeyguardViewBase";
|
|
||||||
public static final boolean DEBUG = KeyguardConstants.DEBUG;
|
|
||||||
// Whether the volume keys should be handled by keyguard. If true, then
|
|
||||||
// they will be handled here for specific media types such as music, otherwise
|
|
||||||
// the audio service will bring up the volume dialog.
|
|
||||||
private static final boolean KEYGUARD_MANAGES_VOLUME = false;
|
|
||||||
|
|
||||||
private static final String ENABLE_MENU_KEY_FILE = "/data/local/enable_menu_key";
|
|
||||||
|
|
||||||
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
|
|
||||||
private final KeyguardSecurityContainerController mKeyguardSecurityContainerController;
|
|
||||||
private final TelephonyManager mTelephonyManager;
|
|
||||||
private final ViewMediatorCallback mViewMediatorCallback;
|
|
||||||
private final AudioManager mAudioManager;
|
|
||||||
|
|
||||||
private ActivityStarter.OnDismissAction mDismissAction;
|
|
||||||
private Runnable mCancelAction;
|
|
||||||
private int mTranslationY;
|
|
||||||
|
|
||||||
private final KeyguardUpdateMonitorCallback mUpdateCallback =
|
|
||||||
new KeyguardUpdateMonitorCallback() {
|
|
||||||
@Override
|
|
||||||
public void onTrustGrantedForCurrentUser(
|
|
||||||
boolean dismissKeyguard,
|
|
||||||
boolean newlyUnlocked,
|
|
||||||
TrustGrantFlags flags,
|
|
||||||
String message
|
|
||||||
) {
|
|
||||||
if (dismissKeyguard) {
|
|
||||||
if (!mView.isVisibleToUser()) {
|
|
||||||
// The trust agent dismissed the keyguard without the user proving
|
|
||||||
// that they are present (by swiping up to show the bouncer). That's
|
|
||||||
// fine if the user proved presence via some other way to the trust
|
|
||||||
// agent.
|
|
||||||
Log.i(TAG, "TrustAgent dismissed Keyguard.");
|
|
||||||
}
|
|
||||||
mSecurityCallback.dismiss(
|
|
||||||
false /* authenticated */,
|
|
||||||
KeyguardUpdateMonitor.getCurrentUser(),
|
|
||||||
/* bypassSecondaryLockScreen */ false,
|
|
||||||
SecurityMode.Invalid
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
if (flags.isInitiatedByUser() || flags.dismissKeyguardRequested()) {
|
|
||||||
mViewMediatorCallback.playTrustedSound();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private final SecurityCallback mSecurityCallback = new SecurityCallback() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean dismiss(boolean authenticated, int targetUserId,
|
|
||||||
boolean bypassSecondaryLockScreen, SecurityMode expectedSecurityMode) {
|
|
||||||
return mKeyguardSecurityContainerController.showNextSecurityScreenOrFinish(
|
|
||||||
authenticated, targetUserId, bypassSecondaryLockScreen, expectedSecurityMode);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void userActivity() {
|
|
||||||
mViewMediatorCallback.userActivity();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onSecurityModeChanged(SecurityMode securityMode, boolean needsInput) {
|
|
||||||
mViewMediatorCallback.setNeedsInput(needsInput);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Authentication has happened and it's time to dismiss keyguard. This function
|
|
||||||
* should clean up and inform KeyguardViewMediator.
|
|
||||||
*
|
|
||||||
* @param strongAuth whether 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 dismissal
|
|
||||||
* completion.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void finish(boolean strongAuth, int targetUserId) {
|
|
||||||
// If there's a pending runnable because the user interacted with a widget
|
|
||||||
// and we're leaving keyguard, then run it.
|
|
||||||
boolean deferKeyguardDone = false;
|
|
||||||
if (mDismissAction != null) {
|
|
||||||
deferKeyguardDone = mDismissAction.onDismiss();
|
|
||||||
mDismissAction = null;
|
|
||||||
mCancelAction = null;
|
|
||||||
}
|
|
||||||
if (mViewMediatorCallback != null) {
|
|
||||||
if (deferKeyguardDone) {
|
|
||||||
mViewMediatorCallback.keyguardDonePending(strongAuth, targetUserId);
|
|
||||||
} else {
|
|
||||||
mViewMediatorCallback.keyguardDone(strongAuth, targetUserId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void reset() {
|
|
||||||
mViewMediatorCallback.resetKeyguard();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCancelClicked() {
|
|
||||||
mViewMediatorCallback.onCancelClicked();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private OnKeyListener mOnKeyListener = (v, keyCode, event) -> interceptMediaKey(event);
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
public KeyguardHostViewController(KeyguardHostView view,
|
|
||||||
KeyguardUpdateMonitor keyguardUpdateMonitor,
|
|
||||||
AudioManager audioManager,
|
|
||||||
TelephonyManager telephonyManager,
|
|
||||||
ViewMediatorCallback viewMediatorCallback,
|
|
||||||
KeyguardSecurityContainerController.Factory
|
|
||||||
keyguardSecurityContainerControllerFactory) {
|
|
||||||
super(view);
|
|
||||||
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
|
|
||||||
mAudioManager = audioManager;
|
|
||||||
mTelephonyManager = telephonyManager;
|
|
||||||
mViewMediatorCallback = viewMediatorCallback;
|
|
||||||
mKeyguardSecurityContainerController = keyguardSecurityContainerControllerFactory.create(
|
|
||||||
mSecurityCallback);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Initialize the Controller. */
|
|
||||||
public void onInit() {
|
|
||||||
mKeyguardSecurityContainerController.init();
|
|
||||||
updateResources();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onViewAttached() {
|
|
||||||
mView.setViewMediatorCallback(mViewMediatorCallback);
|
|
||||||
// Update ViewMediator with the current input method requirements
|
|
||||||
mViewMediatorCallback.setNeedsInput(mKeyguardSecurityContainerController.needsInput());
|
|
||||||
mKeyguardUpdateMonitor.registerCallback(mUpdateCallback);
|
|
||||||
mView.setOnKeyListener(mOnKeyListener);
|
|
||||||
mKeyguardSecurityContainerController.showPrimarySecurityScreen(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onViewDetached() {
|
|
||||||
mKeyguardUpdateMonitor.removeCallback(mUpdateCallback);
|
|
||||||
mView.setOnKeyListener(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Called before this view is being removed. */
|
|
||||||
public void cleanUp() {
|
|
||||||
mKeyguardSecurityContainerController.onPause();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void resetSecurityContainer() {
|
|
||||||
mKeyguardSecurityContainerController.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dismisses the keyguard by going to the next screen or making it gone.
|
|
||||||
* @param targetUserId a user that needs to be the foreground user at the dismissal completion.
|
|
||||||
* @return True if the keyguard is done.
|
|
||||||
*/
|
|
||||||
public boolean dismiss(int targetUserId) {
|
|
||||||
return mSecurityCallback.dismiss(false, targetUserId, false,
|
|
||||||
getCurrentSecurityMode());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when the Keyguard is actively shown on the screen.
|
|
||||||
*/
|
|
||||||
public void onResume() {
|
|
||||||
if (DEBUG) Log.d(TAG, "screen on, instance " + Integer.toHexString(hashCode()));
|
|
||||||
mKeyguardSecurityContainerController.onResume(KeyguardSecurityView.SCREEN_ON);
|
|
||||||
mView.requestFocus();
|
|
||||||
}
|
|
||||||
|
|
||||||
public CharSequence getAccessibilityTitleForCurrentMode() {
|
|
||||||
return mKeyguardSecurityContainerController.getTitle();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Starts the animation when the Keyguard gets shown.
|
|
||||||
*/
|
|
||||||
public void appear(int statusBarHeight) {
|
|
||||||
// We might still be collapsed and the view didn't have time to layout yet or still
|
|
||||||
// be small, let's wait on the predraw to do the animation in that case.
|
|
||||||
if (mView.getHeight() != 0 && mView.getHeight() != statusBarHeight) {
|
|
||||||
mKeyguardSecurityContainerController.startAppearAnimation();
|
|
||||||
} else {
|
|
||||||
mView.getViewTreeObserver().addOnPreDrawListener(
|
|
||||||
new ViewTreeObserver.OnPreDrawListener() {
|
|
||||||
@Override
|
|
||||||
public boolean onPreDraw() {
|
|
||||||
mView.getViewTreeObserver().removeOnPreDrawListener(this);
|
|
||||||
mKeyguardSecurityContainerController.startAppearAnimation();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
mView.requestLayout();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show a string explaining why the security view needs to be solved.
|
|
||||||
*
|
|
||||||
* @param reason a flag indicating which string should be shown, see
|
|
||||||
* {@link KeyguardSecurityView#PROMPT_REASON_NONE},
|
|
||||||
* {@link KeyguardSecurityView#PROMPT_REASON_RESTART},
|
|
||||||
* {@link KeyguardSecurityView#PROMPT_REASON_TIMEOUT}, and
|
|
||||||
* {@link KeyguardSecurityView#PROMPT_REASON_PREPARE_FOR_UPDATE}.
|
|
||||||
*/
|
|
||||||
public void showPromptReason(int reason) {
|
|
||||||
mKeyguardSecurityContainerController.showPromptReason(reason);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void showMessage(CharSequence message, ColorStateList colorState) {
|
|
||||||
mKeyguardSecurityContainerController.showMessage(message, colorState);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void showErrorMessage(CharSequence customMessage) {
|
|
||||||
showMessage(customMessage, Utils.getColorError(mView.getContext()));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets an action to run when keyguard finishes.
|
|
||||||
*
|
|
||||||
* @param action
|
|
||||||
*/
|
|
||||||
public void setOnDismissAction(ActivityStarter.OnDismissAction action, Runnable cancelAction) {
|
|
||||||
if (mCancelAction != null) {
|
|
||||||
mCancelAction.run();
|
|
||||||
mCancelAction = null;
|
|
||||||
}
|
|
||||||
mDismissAction = action;
|
|
||||||
mCancelAction = cancelAction;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void cancelDismissAction() {
|
|
||||||
setOnDismissAction(null, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void startDisappearAnimation(Runnable finishRunnable) {
|
|
||||||
if (!mKeyguardSecurityContainerController.startDisappearAnimation(finishRunnable)
|
|
||||||
&& finishRunnable != null) {
|
|
||||||
finishRunnable.run();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when the Keyguard is not actively shown anymore on the screen.
|
|
||||||
*/
|
|
||||||
public void onPause() {
|
|
||||||
if (DEBUG) {
|
|
||||||
Log.d(TAG, String.format("screen off, instance %s at %s",
|
|
||||||
Integer.toHexString(hashCode()), SystemClock.uptimeMillis()));
|
|
||||||
}
|
|
||||||
mKeyguardSecurityContainerController.showPrimarySecurityScreen(true);
|
|
||||||
mKeyguardSecurityContainerController.onPause();
|
|
||||||
mView.clearFocus();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when the view needs to be shown.
|
|
||||||
*/
|
|
||||||
public void showPrimarySecurityScreen() {
|
|
||||||
if (DEBUG) Log.d(TAG, "show()");
|
|
||||||
mKeyguardSecurityContainerController.showPrimarySecurityScreen(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fades and translates in/out the security screen.
|
|
||||||
* Fades in as expansion approaches 0.
|
|
||||||
* Animation duration is between 0.33f and 0.67f of panel expansion fraction.
|
|
||||||
* @param fraction amount of the screen that should show.
|
|
||||||
*/
|
|
||||||
public void setExpansion(float fraction) {
|
|
||||||
float scaledFraction = BouncerPanelExpansionCalculator.showBouncerProgress(fraction);
|
|
||||||
mView.setAlpha(MathUtils.constrain(1 - scaledFraction, 0f, 1f));
|
|
||||||
mView.setTranslationY(scaledFraction * mTranslationY);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* When bouncer was visible and is starting to become hidden.
|
|
||||||
*/
|
|
||||||
public void onStartingToHide() {
|
|
||||||
mKeyguardSecurityContainerController.onStartingToHide();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Called when bouncer visibility changes. */
|
|
||||||
public void onBouncerVisibilityChanged(@View.Visibility int visibility) {
|
|
||||||
mKeyguardSecurityContainerController.onBouncerVisibilityChanged(visibility);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean hasDismissActions() {
|
|
||||||
return mDismissAction != null || mCancelAction != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SecurityMode getCurrentSecurityMode() {
|
|
||||||
return mKeyguardSecurityContainerController.getCurrentSecurityMode();
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getTop() {
|
|
||||||
int top = mView.getTop();
|
|
||||||
// The password view has an extra top padding that should be ignored.
|
|
||||||
if (getCurrentSecurityMode() == SecurityMode.Password) {
|
|
||||||
View messageArea = mView.findViewById(R.id.keyguard_message_area);
|
|
||||||
top += messageArea.getTop();
|
|
||||||
}
|
|
||||||
return top;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean handleBackKey() {
|
|
||||||
SecurityMode securityMode = mKeyguardSecurityContainerController.getCurrentSecurityMode();
|
|
||||||
if (securityMode != SecurityMode.None) {
|
|
||||||
mKeyguardSecurityContainerController.dismiss(
|
|
||||||
false, KeyguardUpdateMonitor.getCurrentUser(), securityMode);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* In general, we enable unlocking the insecure keyguard with the menu key. However, there are
|
|
||||||
* some cases where we wish to disable it, notably when the menu button placement or technology
|
|
||||||
* is prone to false positives.
|
|
||||||
*
|
|
||||||
* @return true if the menu key should be enabled
|
|
||||||
*/
|
|
||||||
public boolean shouldEnableMenuKey() {
|
|
||||||
final Resources res = mView.getResources();
|
|
||||||
final boolean configDisabled = res.getBoolean(R.bool.config_disableMenuKeyInLockScreen);
|
|
||||||
final boolean isTestHarness = ActivityManager.isRunningInTestHarness();
|
|
||||||
final boolean fileOverride = (new File(ENABLE_MENU_KEY_FILE)).exists();
|
|
||||||
return !configDisabled || isTestHarness || fileOverride;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return true if the current bouncer is password
|
|
||||||
*/
|
|
||||||
public boolean dispatchBackKeyEventPreIme() {
|
|
||||||
if (mKeyguardSecurityContainerController.getCurrentSecurityMode()
|
|
||||||
== SecurityMode.Password) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the {@link OnBackAnimationCallback} to animate this view during a back gesture.
|
|
||||||
*/
|
|
||||||
@NonNull
|
|
||||||
public OnBackAnimationCallback getBackCallback() {
|
|
||||||
return mKeyguardSecurityContainerController.getBackCallback();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Allows the media keys to work when the keyguard is showing.
|
|
||||||
* The media keys should be of no interest to the actual keyguard view(s),
|
|
||||||
* so intercepting them here should not be of any harm.
|
|
||||||
* @param event The key event
|
|
||||||
* @return whether the event was consumed as a media key.
|
|
||||||
*/
|
|
||||||
public boolean interceptMediaKey(KeyEvent event) {
|
|
||||||
int keyCode = event.getKeyCode();
|
|
||||||
if (event.getAction() == KeyEvent.ACTION_DOWN) {
|
|
||||||
switch (keyCode) {
|
|
||||||
case KeyEvent.KEYCODE_MEDIA_PLAY:
|
|
||||||
case KeyEvent.KEYCODE_MEDIA_PAUSE:
|
|
||||||
case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
|
|
||||||
/* Suppress PLAY/PAUSE toggle when phone is ringing or
|
|
||||||
* in-call to avoid music playback */
|
|
||||||
if (mTelephonyManager != null &&
|
|
||||||
mTelephonyManager.getCallState() != TelephonyManager.CALL_STATE_IDLE) {
|
|
||||||
return true; // suppress key event
|
|
||||||
}
|
|
||||||
case KeyEvent.KEYCODE_MUTE:
|
|
||||||
case KeyEvent.KEYCODE_HEADSETHOOK:
|
|
||||||
case KeyEvent.KEYCODE_MEDIA_STOP:
|
|
||||||
case KeyEvent.KEYCODE_MEDIA_NEXT:
|
|
||||||
case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
|
|
||||||
case KeyEvent.KEYCODE_MEDIA_REWIND:
|
|
||||||
case KeyEvent.KEYCODE_MEDIA_RECORD:
|
|
||||||
case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
|
|
||||||
case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: {
|
|
||||||
handleMediaKeyEvent(event);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
case KeyEvent.KEYCODE_VOLUME_UP:
|
|
||||||
case KeyEvent.KEYCODE_VOLUME_DOWN:
|
|
||||||
case KeyEvent.KEYCODE_VOLUME_MUTE: {
|
|
||||||
if (KEYGUARD_MANAGES_VOLUME) {
|
|
||||||
// Volume buttons should only function for music (local or remote).
|
|
||||||
// TODO: Actually handle MUTE.
|
|
||||||
mAudioManager.adjustSuggestedStreamVolume(
|
|
||||||
keyCode == KeyEvent.KEYCODE_VOLUME_UP
|
|
||||||
? AudioManager.ADJUST_RAISE
|
|
||||||
: AudioManager.ADJUST_LOWER /* direction */,
|
|
||||||
AudioManager.STREAM_MUSIC /* stream */, 0 /* flags */);
|
|
||||||
// Don't execute default volume behavior
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (event.getAction() == KeyEvent.ACTION_UP) {
|
|
||||||
switch (keyCode) {
|
|
||||||
case KeyEvent.KEYCODE_MUTE:
|
|
||||||
case KeyEvent.KEYCODE_HEADSETHOOK:
|
|
||||||
case KeyEvent.KEYCODE_MEDIA_PLAY:
|
|
||||||
case KeyEvent.KEYCODE_MEDIA_PAUSE:
|
|
||||||
case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
|
|
||||||
case KeyEvent.KEYCODE_MEDIA_STOP:
|
|
||||||
case KeyEvent.KEYCODE_MEDIA_NEXT:
|
|
||||||
case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
|
|
||||||
case KeyEvent.KEYCODE_MEDIA_REWIND:
|
|
||||||
case KeyEvent.KEYCODE_MEDIA_RECORD:
|
|
||||||
case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
|
|
||||||
case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: {
|
|
||||||
handleMediaKeyEvent(event);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void handleMediaKeyEvent(KeyEvent keyEvent) {
|
|
||||||
mAudioManager.dispatchMediaKeyEvent(keyEvent);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void finish(boolean strongAuth, int currentUser) {
|
|
||||||
mSecurityCallback.finish(strongAuth, currentUser);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Apply keyguard configuration from the currently active resources. This can be called when the
|
|
||||||
* device configuration changes, to re-apply some resources that are qualified on the device
|
|
||||||
* configuration.
|
|
||||||
*/
|
|
||||||
public void updateResources() {
|
|
||||||
int gravity;
|
|
||||||
|
|
||||||
Resources resources = mView.getResources();
|
|
||||||
|
|
||||||
if (resources.getBoolean(R.bool.can_use_one_handed_bouncer)) {
|
|
||||||
gravity = resources.getInteger(
|
|
||||||
R.integer.keyguard_host_view_one_handed_gravity);
|
|
||||||
} else {
|
|
||||||
gravity = resources.getInteger(R.integer.keyguard_host_view_gravity);
|
|
||||||
}
|
|
||||||
|
|
||||||
mTranslationY = resources
|
|
||||||
.getDimensionPixelSize(R.dimen.keyguard_host_view_translation_y);
|
|
||||||
// Android SysUI uses a FrameLayout as the top-level, but Auto uses RelativeLayout.
|
|
||||||
// We're just changing the gravity here though (which can't be applied to RelativeLayout),
|
|
||||||
// so only attempt the update if mView is inside a FrameLayout.
|
|
||||||
if (mView.getLayoutParams() instanceof FrameLayout.LayoutParams) {
|
|
||||||
FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) mView.getLayoutParams();
|
|
||||||
if (lp.gravity != gravity) {
|
|
||||||
lp.gravity = gravity;
|
|
||||||
mView.setLayoutParams(lp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mKeyguardSecurityContainerController != null) {
|
|
||||||
mKeyguardSecurityContainerController.updateResources();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Update keyguard position based on a tapped X coordinate. */
|
|
||||||
public void updateKeyguardPosition(float x) {
|
|
||||||
if (mKeyguardSecurityContainerController != null) {
|
|
||||||
mKeyguardSecurityContainerController.updateKeyguardPosition(x);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Set true if the view can be interacted with */
|
|
||||||
public void setInteractable(boolean isInteractable) {
|
|
||||||
mView.setInteractable(isInteractable);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -51,26 +51,7 @@ public abstract class KeyguardInputViewController<T extends KeyguardInputView>
|
|||||||
// The following is used to ignore callbacks from SecurityViews that are no longer current
|
// The following is used to ignore callbacks from SecurityViews that are no longer current
|
||||||
// (e.g. face unlock). This avoids unwanted asynchronous events from messing with the
|
// (e.g. face unlock). This avoids unwanted asynchronous events from messing with the
|
||||||
// state for the current security method.
|
// state for the current security method.
|
||||||
private KeyguardSecurityCallback mNullCallback = new KeyguardSecurityCallback() {
|
private KeyguardSecurityCallback mNullCallback = new KeyguardSecurityCallback() {};
|
||||||
@Override
|
|
||||||
public void userActivity() { }
|
|
||||||
@Override
|
|
||||||
public void reportUnlockAttempt(int userId, boolean success, int timeoutMs) { }
|
|
||||||
@Override
|
|
||||||
public boolean isVerifyUnlockOnly() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public void dismiss(boolean securityVerified, int targetUserId,
|
|
||||||
SecurityMode expectedSecurityMode) { }
|
|
||||||
@Override
|
|
||||||
public void dismiss(boolean authenticated, int targetId,
|
|
||||||
boolean bypassSecondaryLockScreen, SecurityMode expectedSecurityMode) { }
|
|
||||||
@Override
|
|
||||||
public void onUserInput() { }
|
|
||||||
@Override
|
|
||||||
public void reset() {}
|
|
||||||
};
|
|
||||||
|
|
||||||
protected KeyguardInputViewController(T view, SecurityMode securityMode,
|
protected KeyguardInputViewController(T view, SecurityMode securityMode,
|
||||||
KeyguardSecurityCallback keyguardSecurityCallback,
|
KeyguardSecurityCallback keyguardSecurityCallback,
|
||||||
|
|||||||
@@ -25,7 +25,9 @@ public interface KeyguardSecurityCallback {
|
|||||||
* @param targetUserId a user that needs to be the foreground user at the dismissal completion.
|
* @param targetUserId a user that needs to be the foreground user at the dismissal completion.
|
||||||
* @param expectedSecurityMode The security mode that is invoking this dismiss.
|
* @param expectedSecurityMode The security mode that is invoking this dismiss.
|
||||||
*/
|
*/
|
||||||
void dismiss(boolean securityVerified, int targetUserId, SecurityMode expectedSecurityMode);
|
default void dismiss(boolean securityVerified, int targetUserId,
|
||||||
|
SecurityMode expectedSecurityMode) {
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dismiss the given security screen.
|
* Dismiss the given security screen.
|
||||||
@@ -35,19 +37,26 @@ public interface KeyguardSecurityCallback {
|
|||||||
* if any, during this dismissal.
|
* if any, during this dismissal.
|
||||||
* @param expectedSecurityMode The security mode that is invoking this dismiss.
|
* @param expectedSecurityMode The security mode that is invoking this dismiss.
|
||||||
*/
|
*/
|
||||||
void dismiss(boolean securityVerified, int targetUserId, boolean bypassSecondaryLockScreen,
|
default boolean dismiss(boolean securityVerified, int targetUserId,
|
||||||
SecurityMode expectedSecurityMode);
|
boolean bypassSecondaryLockScreen,
|
||||||
|
SecurityMode expectedSecurityMode) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manually report user activity to keep the device awake.
|
* Manually report user activity to keep the device awake.
|
||||||
*/
|
*/
|
||||||
void userActivity();
|
default void userActivity() {
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if keyguard is in "verify credentials" mode.
|
* Checks if keyguard is in "verify credentials" mode.
|
||||||
|
*
|
||||||
* @return true if user has been asked to verify security.
|
* @return true if user has been asked to verify security.
|
||||||
*/
|
*/
|
||||||
boolean isVerifyUnlockOnly();
|
default boolean isVerifyUnlockOnly() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Call to report an unlock attempt.
|
* Call to report an unlock attempt.
|
||||||
@@ -56,12 +65,14 @@ public interface KeyguardSecurityCallback {
|
|||||||
* @param timeoutMs timeout in milliseconds to wait before reattempting an unlock.
|
* @param timeoutMs timeout in milliseconds to wait before reattempting an unlock.
|
||||||
* Only nonzero if 'success' is false
|
* Only nonzero if 'success' is false
|
||||||
*/
|
*/
|
||||||
void reportUnlockAttempt(int userId, boolean success, int timeoutMs);
|
default void reportUnlockAttempt(int userId, boolean success, int timeoutMs) {
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resets the keyguard view.
|
* Resets the keyguard view.
|
||||||
*/
|
*/
|
||||||
void reset();
|
default void reset() {
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Call when cancel button is pressed in bouncer.
|
* Call when cancel button is pressed in bouncer.
|
||||||
@@ -73,5 +84,19 @@ public interface KeyguardSecurityCallback {
|
|||||||
/**
|
/**
|
||||||
* Invoked whenever users are typing their password or drawing a pattern.
|
* Invoked whenever users are typing their password or drawing a pattern.
|
||||||
*/
|
*/
|
||||||
void onUserInput();
|
default void onUserInput() {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dismisses keyguard and go to unlocked state.
|
||||||
|
*/
|
||||||
|
default void finish(boolean strongAuth, int targetUserId) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies that security mode has changed.
|
||||||
|
*/
|
||||||
|
default void onSecurityModeChanged(SecurityMode securityMode, boolean needsInput) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ import android.content.res.Configuration;
|
|||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.BlendMode;
|
import android.graphics.BlendMode;
|
||||||
|
import android.graphics.Canvas;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.graphics.drawable.BitmapDrawable;
|
import android.graphics.drawable.BitmapDrawable;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
@@ -164,6 +165,8 @@ public class KeyguardSecurityContainer extends ConstraintLayout {
|
|||||||
private boolean mDisappearAnimRunning;
|
private boolean mDisappearAnimRunning;
|
||||||
private SwipeListener mSwipeListener;
|
private SwipeListener mSwipeListener;
|
||||||
private ViewMode mViewMode = new DefaultViewMode();
|
private ViewMode mViewMode = new DefaultViewMode();
|
||||||
|
private boolean mIsInteractable;
|
||||||
|
protected ViewMediatorCallback mViewMediatorCallback;
|
||||||
/*
|
/*
|
||||||
* Using MODE_UNINITIALIZED to mean the view mode is set to DefaultViewMode, but init() has not
|
* Using MODE_UNINITIALIZED to mean the view mode is set to DefaultViewMode, but init() has not
|
||||||
* yet been called on it. This will happen when the ViewController is initialized.
|
* yet been called on it. This will happen when the ViewController is initialized.
|
||||||
@@ -265,31 +268,6 @@ public class KeyguardSecurityContainer extends ConstraintLayout {
|
|||||||
return mBackCallback;
|
return mBackCallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Used to notify the container when something interesting happens.
|
|
||||||
public interface SecurityCallback {
|
|
||||||
/**
|
|
||||||
* Potentially dismiss the current security screen, after validating that all device
|
|
||||||
* security has been unlocked. Otherwise show the next screen.
|
|
||||||
*/
|
|
||||||
boolean dismiss(boolean authenticated, int targetUserId, boolean bypassSecondaryLockScreen,
|
|
||||||
SecurityMode expectedSecurityMode);
|
|
||||||
|
|
||||||
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 targetUserId a user that needs to be the foreground user at the finish completion.
|
|
||||||
*/
|
|
||||||
void finish(boolean strongAuth, int targetUserId);
|
|
||||||
|
|
||||||
void reset();
|
|
||||||
|
|
||||||
void onCancelClicked();
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface SwipeListener {
|
public interface SwipeListener {
|
||||||
void onSwipeUp();
|
void onSwipeUp();
|
||||||
}
|
}
|
||||||
@@ -342,7 +320,7 @@ public class KeyguardSecurityContainer extends ConstraintLayout {
|
|||||||
|
|
||||||
public KeyguardSecurityContainer(Context context, AttributeSet attrs, int defStyle) {
|
public KeyguardSecurityContainer(Context context, AttributeSet attrs, int defStyle) {
|
||||||
super(context, attrs, defStyle);
|
super(context, attrs, defStyle);
|
||||||
mSpringAnimation = new SpringAnimation(this, DynamicAnimation.Y);
|
mSpringAnimation = new SpringAnimation(this, DynamicAnimation.TRANSLATION_Y);
|
||||||
mViewConfiguration = ViewConfiguration.get(context);
|
mViewConfiguration = ViewConfiguration.get(context);
|
||||||
mDoubleTapDetector = new GestureDetector(context, new DoubleTapListener());
|
mDoubleTapDetector = new GestureDetector(context, new DoubleTapListener());
|
||||||
}
|
}
|
||||||
@@ -445,6 +423,11 @@ public class KeyguardSecurityContainer extends ConstraintLayout {
|
|||||||
mViewMode.reset();
|
mViewMode.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Set true if the view can be interacted with */
|
||||||
|
public void setInteractable(boolean isInteractable) {
|
||||||
|
mIsInteractable = isInteractable;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean shouldDelayChildPressedState() {
|
public boolean shouldDelayChildPressedState() {
|
||||||
return true;
|
return true;
|
||||||
@@ -452,6 +435,10 @@ public class KeyguardSecurityContainer extends ConstraintLayout {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onInterceptTouchEvent(MotionEvent event) {
|
public boolean onInterceptTouchEvent(MotionEvent event) {
|
||||||
|
if (!mIsInteractable) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
boolean result = mMotionEventListeners.stream().anyMatch(
|
boolean result = mMotionEventListeners.stream().anyMatch(
|
||||||
listener -> listener.onInterceptTouchEvent(event))
|
listener -> listener.onInterceptTouchEvent(event))
|
||||||
|| super.onInterceptTouchEvent(event);
|
|| super.onInterceptTouchEvent(event);
|
||||||
@@ -639,6 +626,18 @@ public class KeyguardSecurityContainer extends ConstraintLayout {
|
|||||||
return insets.inset(0, 0, 0, inset);
|
return insets.inset(0, 0, 0, inset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void dispatchDraw(Canvas canvas) {
|
||||||
|
super.dispatchDraw(canvas);
|
||||||
|
if (mViewMediatorCallback != null) {
|
||||||
|
mViewMediatorCallback.keyguardDoneDrawing();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setViewMediatorCallback(ViewMediatorCallback viewMediatorCallback) {
|
||||||
|
mViewMediatorCallback = viewMediatorCallback;
|
||||||
|
}
|
||||||
|
|
||||||
private void showDialog(String title, String message) {
|
private void showDialog(String title, String message) {
|
||||||
if (mAlertDialog != null) {
|
if (mAlertDialog != null) {
|
||||||
mAlertDialog.dismiss();
|
mAlertDialog.dismiss();
|
||||||
|
|||||||
@@ -29,17 +29,26 @@ import static com.android.keyguard.KeyguardSecurityContainer.USER_TYPE_SECONDARY
|
|||||||
import static com.android.keyguard.KeyguardSecurityContainer.USER_TYPE_WORK_PROFILE;
|
import static com.android.keyguard.KeyguardSecurityContainer.USER_TYPE_WORK_PROFILE;
|
||||||
import static com.android.systemui.DejankUtils.whitelistIpcs;
|
import static com.android.systemui.DejankUtils.whitelistIpcs;
|
||||||
|
|
||||||
|
import android.app.ActivityManager;
|
||||||
import android.app.admin.DevicePolicyManager;
|
import android.app.admin.DevicePolicyManager;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.res.ColorStateList;
|
import android.content.res.ColorStateList;
|
||||||
import android.content.res.Configuration;
|
import android.content.res.Configuration;
|
||||||
|
import android.content.res.Resources;
|
||||||
import android.hardware.biometrics.BiometricSourceType;
|
import android.hardware.biometrics.BiometricSourceType;
|
||||||
|
import android.media.AudioManager;
|
||||||
import android.metrics.LogMaker;
|
import android.metrics.LogMaker;
|
||||||
|
import android.os.SystemClock;
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
|
import android.telephony.TelephonyManager;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
import android.util.MathUtils;
|
||||||
import android.util.Slog;
|
import android.util.Slog;
|
||||||
|
import android.view.KeyEvent;
|
||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
import android.view.ViewTreeObserver;
|
||||||
|
import android.widget.FrameLayout;
|
||||||
import android.window.OnBackAnimationCallback;
|
import android.window.OnBackAnimationCallback;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
@@ -53,7 +62,6 @@ import com.android.internal.logging.nano.MetricsProto;
|
|||||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||||
import com.android.internal.widget.LockPatternUtils;
|
import com.android.internal.widget.LockPatternUtils;
|
||||||
import com.android.keyguard.KeyguardSecurityContainer.BouncerUiEvent;
|
import com.android.keyguard.KeyguardSecurityContainer.BouncerUiEvent;
|
||||||
import com.android.keyguard.KeyguardSecurityContainer.SecurityCallback;
|
|
||||||
import com.android.keyguard.KeyguardSecurityContainer.SwipeListener;
|
import com.android.keyguard.KeyguardSecurityContainer.SwipeListener;
|
||||||
import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
|
import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
|
||||||
import com.android.keyguard.dagger.KeyguardBouncerScope;
|
import com.android.keyguard.dagger.KeyguardBouncerScope;
|
||||||
@@ -67,6 +75,7 @@ import com.android.systemui.classifier.FalsingCollector;
|
|||||||
import com.android.systemui.flags.FeatureFlags;
|
import com.android.systemui.flags.FeatureFlags;
|
||||||
import com.android.systemui.flags.Flags;
|
import com.android.systemui.flags.Flags;
|
||||||
import com.android.systemui.log.SessionTracker;
|
import com.android.systemui.log.SessionTracker;
|
||||||
|
import com.android.systemui.plugins.ActivityStarter;
|
||||||
import com.android.systemui.plugins.FalsingManager;
|
import com.android.systemui.plugins.FalsingManager;
|
||||||
import com.android.systemui.shared.system.SysUiStatsLog;
|
import com.android.systemui.shared.system.SysUiStatsLog;
|
||||||
import com.android.systemui.statusbar.policy.ConfigurationController;
|
import com.android.systemui.statusbar.policy.ConfigurationController;
|
||||||
@@ -75,6 +84,7 @@ import com.android.systemui.statusbar.policy.UserSwitcherController;
|
|||||||
import com.android.systemui.util.ViewController;
|
import com.android.systemui.util.ViewController;
|
||||||
import com.android.systemui.util.settings.GlobalSettings;
|
import com.android.systemui.util.settings.GlobalSettings;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
@@ -95,7 +105,6 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
|
|||||||
private final UiEventLogger mUiEventLogger;
|
private final UiEventLogger mUiEventLogger;
|
||||||
private final KeyguardStateController mKeyguardStateController;
|
private final KeyguardStateController mKeyguardStateController;
|
||||||
private final KeyguardSecurityViewFlipperController mSecurityViewFlipperController;
|
private final KeyguardSecurityViewFlipperController mSecurityViewFlipperController;
|
||||||
private final SecurityCallback mSecurityCallback;
|
|
||||||
private final ConfigurationController mConfigurationController;
|
private final ConfigurationController mConfigurationController;
|
||||||
private final FalsingCollector mFalsingCollector;
|
private final FalsingCollector mFalsingCollector;
|
||||||
private final FalsingManager mFalsingManager;
|
private final FalsingManager mFalsingManager;
|
||||||
@@ -105,6 +114,20 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
|
|||||||
private final SessionTracker mSessionTracker;
|
private final SessionTracker mSessionTracker;
|
||||||
private final Optional<SideFpsController> mSideFpsController;
|
private final Optional<SideFpsController> mSideFpsController;
|
||||||
private final FalsingA11yDelegate mFalsingA11yDelegate;
|
private final FalsingA11yDelegate mFalsingA11yDelegate;
|
||||||
|
private int mTranslationY;
|
||||||
|
// Whether the volume keys should be handled by keyguard. If true, then
|
||||||
|
// they will be handled here for specific media types such as music, otherwise
|
||||||
|
// the audio service will bring up the volume dialog.
|
||||||
|
private static final boolean KEYGUARD_MANAGES_VOLUME = false;
|
||||||
|
|
||||||
|
private static final String ENABLE_MENU_KEY_FILE = "/data/local/enable_menu_key";
|
||||||
|
|
||||||
|
private final TelephonyManager mTelephonyManager;
|
||||||
|
private final ViewMediatorCallback mViewMediatorCallback;
|
||||||
|
private final AudioManager mAudioManager;
|
||||||
|
private View.OnKeyListener mOnKeyListener = (v, keyCode, event) -> interceptMediaKey(event);
|
||||||
|
private ActivityStarter.OnDismissAction mDismissAction;
|
||||||
|
private Runnable mCancelAction;
|
||||||
|
|
||||||
private int mLastOrientation = Configuration.ORIENTATION_UNDEFINED;
|
private int mLastOrientation = Configuration.ORIENTATION_UNDEFINED;
|
||||||
|
|
||||||
@@ -149,11 +172,6 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
|
|||||||
};
|
};
|
||||||
|
|
||||||
private KeyguardSecurityCallback mKeyguardSecurityCallback = new KeyguardSecurityCallback() {
|
private KeyguardSecurityCallback mKeyguardSecurityCallback = new KeyguardSecurityCallback() {
|
||||||
public void userActivity() {
|
|
||||||
if (mSecurityCallback != null) {
|
|
||||||
mSecurityCallback.userActivity();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onUserInput() {
|
public void onUserInput() {
|
||||||
@@ -168,16 +186,23 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void dismiss(boolean authenticated, int targetId,
|
public boolean dismiss(boolean authenticated, int targetId,
|
||||||
boolean bypassSecondaryLockScreen, SecurityMode expectedSecurityMode) {
|
boolean bypassSecondaryLockScreen, SecurityMode expectedSecurityMode) {
|
||||||
mSecurityCallback.dismiss(authenticated, targetId, bypassSecondaryLockScreen,
|
return showNextSecurityScreenOrFinish(
|
||||||
expectedSecurityMode);
|
authenticated, targetId, bypassSecondaryLockScreen, expectedSecurityMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void userActivity() {
|
||||||
|
mViewMediatorCallback.userActivity();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean isVerifyUnlockOnly() {
|
public boolean isVerifyUnlockOnly() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
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.isSidedSecurityMode()) {
|
if (mView.isSidedSecurityMode()) {
|
||||||
@@ -214,12 +239,47 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
|
|||||||
: BouncerUiEvent.BOUNCER_PASSWORD_FAILURE, getSessionId());
|
: BouncerUiEvent.BOUNCER_PASSWORD_FAILURE, getSessionId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void reset() {
|
public void reset() {
|
||||||
mSecurityCallback.reset();
|
mViewMediatorCallback.resetKeyguard();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void onCancelClicked() {
|
public void onCancelClicked() {
|
||||||
mSecurityCallback.onCancelClicked();
|
mViewMediatorCallback.onCancelClicked();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Authentication has happened and it's time to dismiss keyguard. This function
|
||||||
|
* should clean up and inform KeyguardViewMediator.
|
||||||
|
*
|
||||||
|
* @param strongAuth whether 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 dismissal
|
||||||
|
* completion.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void finish(boolean strongAuth, int targetUserId) {
|
||||||
|
// If there's a pending runnable because the user interacted with a widget
|
||||||
|
// and we're leaving keyguard, then run it.
|
||||||
|
boolean deferKeyguardDone = false;
|
||||||
|
if (mDismissAction != null) {
|
||||||
|
deferKeyguardDone = mDismissAction.onDismiss();
|
||||||
|
mDismissAction = null;
|
||||||
|
mCancelAction = null;
|
||||||
|
}
|
||||||
|
if (mViewMediatorCallback != null) {
|
||||||
|
if (deferKeyguardDone) {
|
||||||
|
mViewMediatorCallback.keyguardDonePending(strongAuth, targetUserId);
|
||||||
|
} else {
|
||||||
|
mViewMediatorCallback.keyguardDone(strongAuth, targetUserId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSecurityModeChanged(SecurityMode securityMode, boolean needsInput) {
|
||||||
|
mViewMediatorCallback.setNeedsInput(needsInput);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -262,6 +322,34 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
|
|||||||
private boolean mBouncerVisible = false;
|
private boolean mBouncerVisible = false;
|
||||||
private final KeyguardUpdateMonitorCallback mKeyguardUpdateMonitorCallback =
|
private final KeyguardUpdateMonitorCallback mKeyguardUpdateMonitorCallback =
|
||||||
new KeyguardUpdateMonitorCallback() {
|
new KeyguardUpdateMonitorCallback() {
|
||||||
|
@Override
|
||||||
|
public void onTrustGrantedForCurrentUser(
|
||||||
|
boolean dismissKeyguard,
|
||||||
|
boolean newlyUnlocked,
|
||||||
|
TrustGrantFlags flags,
|
||||||
|
String message
|
||||||
|
) {
|
||||||
|
if (dismissKeyguard) {
|
||||||
|
if (!mView.isVisibleToUser()) {
|
||||||
|
// The trust agent dismissed the keyguard without the user proving
|
||||||
|
// that they are present (by swiping up to show the bouncer). That's
|
||||||
|
// fine if the user proved presence via some other way to the trust
|
||||||
|
// agent.
|
||||||
|
Log.i(TAG, "TrustAgent dismissed Keyguard.");
|
||||||
|
}
|
||||||
|
mKeyguardSecurityCallback.dismiss(
|
||||||
|
false /* authenticated */,
|
||||||
|
KeyguardUpdateMonitor.getCurrentUser(),
|
||||||
|
/* bypassSecondaryLockScreen */ false,
|
||||||
|
SecurityMode.Invalid
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
if (flags.isInitiatedByUser() || flags.dismissKeyguardRequested()) {
|
||||||
|
mViewMediatorCallback.playTrustedSound();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDevicePolicyManagerStateChanged() {
|
public void onDevicePolicyManagerStateChanged() {
|
||||||
showPrimarySecurityScreen(false);
|
showPrimarySecurityScreen(false);
|
||||||
@@ -281,7 +369,8 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private KeyguardSecurityContainerController(KeyguardSecurityContainer view,
|
@Inject
|
||||||
|
public KeyguardSecurityContainerController(KeyguardSecurityContainer view,
|
||||||
AdminSecondaryLockScreenController.Factory adminSecondaryLockScreenControllerFactory,
|
AdminSecondaryLockScreenController.Factory adminSecondaryLockScreenControllerFactory,
|
||||||
LockPatternUtils lockPatternUtils,
|
LockPatternUtils lockPatternUtils,
|
||||||
KeyguardUpdateMonitor keyguardUpdateMonitor,
|
KeyguardUpdateMonitor keyguardUpdateMonitor,
|
||||||
@@ -289,7 +378,6 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
|
|||||||
MetricsLogger metricsLogger,
|
MetricsLogger metricsLogger,
|
||||||
UiEventLogger uiEventLogger,
|
UiEventLogger uiEventLogger,
|
||||||
KeyguardStateController keyguardStateController,
|
KeyguardStateController keyguardStateController,
|
||||||
SecurityCallback securityCallback,
|
|
||||||
KeyguardSecurityViewFlipperController securityViewFlipperController,
|
KeyguardSecurityViewFlipperController securityViewFlipperController,
|
||||||
ConfigurationController configurationController,
|
ConfigurationController configurationController,
|
||||||
FalsingCollector falsingCollector,
|
FalsingCollector falsingCollector,
|
||||||
@@ -299,7 +387,11 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
|
|||||||
GlobalSettings globalSettings,
|
GlobalSettings globalSettings,
|
||||||
SessionTracker sessionTracker,
|
SessionTracker sessionTracker,
|
||||||
Optional<SideFpsController> sideFpsController,
|
Optional<SideFpsController> sideFpsController,
|
||||||
FalsingA11yDelegate falsingA11yDelegate) {
|
FalsingA11yDelegate falsingA11yDelegate,
|
||||||
|
TelephonyManager telephonyManager,
|
||||||
|
ViewMediatorCallback viewMediatorCallback,
|
||||||
|
AudioManager audioManager
|
||||||
|
) {
|
||||||
super(view);
|
super(view);
|
||||||
mLockPatternUtils = lockPatternUtils;
|
mLockPatternUtils = lockPatternUtils;
|
||||||
mUpdateMonitor = keyguardUpdateMonitor;
|
mUpdateMonitor = keyguardUpdateMonitor;
|
||||||
@@ -307,7 +399,6 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
|
|||||||
mMetricsLogger = metricsLogger;
|
mMetricsLogger = metricsLogger;
|
||||||
mUiEventLogger = uiEventLogger;
|
mUiEventLogger = uiEventLogger;
|
||||||
mKeyguardStateController = keyguardStateController;
|
mKeyguardStateController = keyguardStateController;
|
||||||
mSecurityCallback = securityCallback;
|
|
||||||
mSecurityViewFlipperController = securityViewFlipperController;
|
mSecurityViewFlipperController = securityViewFlipperController;
|
||||||
mAdminSecondaryLockScreenController = adminSecondaryLockScreenControllerFactory.create(
|
mAdminSecondaryLockScreenController = adminSecondaryLockScreenControllerFactory.create(
|
||||||
mKeyguardSecurityCallback);
|
mKeyguardSecurityCallback);
|
||||||
@@ -321,11 +412,15 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
|
|||||||
mSessionTracker = sessionTracker;
|
mSessionTracker = sessionTracker;
|
||||||
mSideFpsController = sideFpsController;
|
mSideFpsController = sideFpsController;
|
||||||
mFalsingA11yDelegate = falsingA11yDelegate;
|
mFalsingA11yDelegate = falsingA11yDelegate;
|
||||||
|
mTelephonyManager = telephonyManager;
|
||||||
|
mViewMediatorCallback = viewMediatorCallback;
|
||||||
|
mAudioManager = audioManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onInit() {
|
public void onInit() {
|
||||||
mSecurityViewFlipperController.init();
|
mSecurityViewFlipperController.init();
|
||||||
|
updateResources();
|
||||||
configureMode();
|
configureMode();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -336,6 +431,11 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
|
|||||||
mView.addMotionEventListener(mGlobalTouchListener);
|
mView.addMotionEventListener(mGlobalTouchListener);
|
||||||
mConfigurationController.addCallback(mConfigurationListener);
|
mConfigurationController.addCallback(mConfigurationListener);
|
||||||
mUserSwitcherController.addUserSwitchCallback(mUserSwitchCallback);
|
mUserSwitcherController.addUserSwitchCallback(mUserSwitchCallback);
|
||||||
|
mView.setViewMediatorCallback(mViewMediatorCallback);
|
||||||
|
// Update ViewMediator with the current input method requirements
|
||||||
|
mViewMediatorCallback.setNeedsInput(needsInput());
|
||||||
|
mView.setOnKeyListener(mOnKeyListener);
|
||||||
|
showPrimarySecurityScreen(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -348,6 +448,11 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
|
|||||||
|
|
||||||
/** */
|
/** */
|
||||||
public void onPause() {
|
public void onPause() {
|
||||||
|
if (DEBUG) {
|
||||||
|
Log.d(TAG, String.format("screen off, instance %s at %s",
|
||||||
|
Integer.toHexString(hashCode()), SystemClock.uptimeMillis()));
|
||||||
|
}
|
||||||
|
showPrimarySecurityScreen(true);
|
||||||
mAdminSecondaryLockScreenController.hide();
|
mAdminSecondaryLockScreenController.hide();
|
||||||
if (mCurrentSecurityMode != SecurityMode.None) {
|
if (mCurrentSecurityMode != SecurityMode.None) {
|
||||||
getCurrentSecurityController().onPause();
|
getCurrentSecurityController().onPause();
|
||||||
@@ -356,6 +461,7 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
|
|||||||
// It might happen that onStartingToHide is not called when the device is locked while on
|
// It might happen that onStartingToHide is not called when the device is locked while on
|
||||||
// bouncer.
|
// bouncer.
|
||||||
setBouncerVisible(false);
|
setBouncerVisible(false);
|
||||||
|
mView.clearFocus();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateSideFpsVisibility() {
|
private void updateSideFpsVisibility() {
|
||||||
@@ -391,12 +497,22 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
|
|||||||
* @param turningOff true if the device is being turned off
|
* @param turningOff true if the device is being turned off
|
||||||
*/
|
*/
|
||||||
public void showPrimarySecurityScreen(boolean turningOff) {
|
public void showPrimarySecurityScreen(boolean turningOff) {
|
||||||
|
if (DEBUG) Log.d(TAG, "show()");
|
||||||
SecurityMode securityMode = whitelistIpcs(() -> mSecurityModel.getSecurityMode(
|
SecurityMode securityMode = whitelistIpcs(() -> mSecurityModel.getSecurityMode(
|
||||||
KeyguardUpdateMonitor.getCurrentUser()));
|
KeyguardUpdateMonitor.getCurrentUser()));
|
||||||
if (DEBUG) Log.v(TAG, "showPrimarySecurityScreen(turningOff=" + turningOff + ")");
|
if (DEBUG) Log.v(TAG, "showPrimarySecurityScreen(turningOff=" + turningOff + ")");
|
||||||
showSecurityScreen(securityMode);
|
showSecurityScreen(securityMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show a string explaining why the security view needs to be solved.
|
||||||
|
*
|
||||||
|
* @param reason a flag indicating which string should be shown, see
|
||||||
|
* {@link KeyguardSecurityView#PROMPT_REASON_NONE},
|
||||||
|
* {@link KeyguardSecurityView#PROMPT_REASON_RESTART},
|
||||||
|
* {@link KeyguardSecurityView#PROMPT_REASON_TIMEOUT}, and
|
||||||
|
* {@link KeyguardSecurityView#PROMPT_REASON_PREPARE_FOR_UPDATE}.
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void showPromptReason(int reason) {
|
public void showPromptReason(int reason) {
|
||||||
if (mCurrentSecurityMode != SecurityMode.None) {
|
if (mCurrentSecurityMode != SecurityMode.None) {
|
||||||
@@ -413,8 +529,32 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public SecurityMode getCurrentSecurityMode() {
|
/**
|
||||||
return mCurrentSecurityMode;
|
* Sets an action to run when keyguard finishes.
|
||||||
|
*
|
||||||
|
* @param action callback to be invoked when keyguard disappear animation completes.
|
||||||
|
*/
|
||||||
|
public void setOnDismissAction(ActivityStarter.OnDismissAction action, Runnable cancelAction) {
|
||||||
|
if (mCancelAction != null) {
|
||||||
|
mCancelAction.run();
|
||||||
|
mCancelAction = null;
|
||||||
|
}
|
||||||
|
mDismissAction = action;
|
||||||
|
mCancelAction = cancelAction;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return whether dismiss action or cancel action has been set.
|
||||||
|
*/
|
||||||
|
public boolean hasDismissActions() {
|
||||||
|
return mDismissAction != null || mCancelAction != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove any dismiss action or cancel action that was set.
|
||||||
|
*/
|
||||||
|
public void cancelDismissAction() {
|
||||||
|
setOnDismissAction(null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -426,17 +566,64 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
|
|||||||
mKeyguardSecurityCallback.dismiss(authenticated, targetUserId, expectedSecurityMode);
|
mKeyguardSecurityCallback.dismiss(authenticated, targetUserId, expectedSecurityMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dismisses the keyguard by going to the next screen or making it gone.
|
||||||
|
* @param targetUserId a user that needs to be the foreground user at the dismissal completion.
|
||||||
|
* @return True if the keyguard is done.
|
||||||
|
*/
|
||||||
|
public boolean dismiss(int targetUserId) {
|
||||||
|
return mKeyguardSecurityCallback.dismiss(false, targetUserId, false,
|
||||||
|
getCurrentSecurityMode());
|
||||||
|
}
|
||||||
|
|
||||||
|
public SecurityMode getCurrentSecurityMode() {
|
||||||
|
return mCurrentSecurityMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the top of the corresponding view.
|
||||||
|
*/
|
||||||
|
public int getTop() {
|
||||||
|
int top = mView.getTop();
|
||||||
|
// The password view has an extra top padding that should be ignored.
|
||||||
|
if (getCurrentSecurityMode() == SecurityMode.Password) {
|
||||||
|
View messageArea = mView.findViewById(R.id.keyguard_message_area);
|
||||||
|
top += messageArea.getTop();
|
||||||
|
}
|
||||||
|
return top;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Set true if the view can be interacted with */
|
||||||
|
public void setInteractable(boolean isInteractable) {
|
||||||
|
mView.setInteractable(isInteractable);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dismiss keyguard due to a user unlock event.
|
||||||
|
*/
|
||||||
|
public void finish(boolean strongAuth, int currentUser) {
|
||||||
|
mKeyguardSecurityCallback.finish(strongAuth, currentUser);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the text of the KeyguardMessageArea.
|
||||||
|
*/
|
||||||
|
public CharSequence getTitle() {
|
||||||
|
return mView.getTitle();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets the state of the views.
|
||||||
|
*/
|
||||||
public void reset() {
|
public void reset() {
|
||||||
mView.reset();
|
mView.reset();
|
||||||
mSecurityViewFlipperController.reset();
|
mSecurityViewFlipperController.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
public CharSequence getTitle() {
|
|
||||||
return mView.getTitle();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onResume(int reason) {
|
public void onResume(int reason) {
|
||||||
|
if (DEBUG) Log.d(TAG, "screen on, instance " + Integer.toHexString(hashCode()));
|
||||||
|
mView.requestFocus();
|
||||||
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.isSidedSecurityMode()) {
|
if (mView.isSidedSecurityMode()) {
|
||||||
@@ -454,6 +641,30 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
|
|||||||
mKeyguardStateController.isFaceAuthEnabled());
|
mKeyguardStateController.isFaceAuthEnabled());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the bouncer and start appear animations.
|
||||||
|
*
|
||||||
|
* @param statusBarHeight
|
||||||
|
*/
|
||||||
|
public void appear(int statusBarHeight) {
|
||||||
|
// We might still be collapsed and the view didn't have time to layout yet or still
|
||||||
|
// be small, let's wait on the predraw to do the animation in that case.
|
||||||
|
if (mView.getHeight() != 0 && mView.getHeight() != statusBarHeight) {
|
||||||
|
startAppearAnimation();
|
||||||
|
} else {
|
||||||
|
mView.getViewTreeObserver().addOnPreDrawListener(
|
||||||
|
new ViewTreeObserver.OnPreDrawListener() {
|
||||||
|
@Override
|
||||||
|
public boolean onPreDraw() {
|
||||||
|
mView.getViewTreeObserver().removeOnPreDrawListener(this);
|
||||||
|
startAppearAnimation();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
mView.requestLayout();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void startAppearAnimation() {
|
public void startAppearAnimation() {
|
||||||
if (mCurrentSecurityMode != SecurityMode.None) {
|
if (mCurrentSecurityMode != SecurityMode.None) {
|
||||||
mView.setAlpha(1f);
|
mView.setAlpha(1f);
|
||||||
@@ -465,9 +676,13 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
|
|||||||
public boolean startDisappearAnimation(Runnable onFinishRunnable) {
|
public boolean startDisappearAnimation(Runnable onFinishRunnable) {
|
||||||
if (mCurrentSecurityMode != SecurityMode.None) {
|
if (mCurrentSecurityMode != SecurityMode.None) {
|
||||||
mView.startDisappearAnimation(mCurrentSecurityMode);
|
mView.startDisappearAnimation(mCurrentSecurityMode);
|
||||||
return getCurrentSecurityController().startDisappearAnimation(onFinishRunnable);
|
boolean animating = getCurrentSecurityController().startDisappearAnimation(
|
||||||
|
onFinishRunnable);
|
||||||
|
if (!animating && onFinishRunnable != null) {
|
||||||
|
onFinishRunnable.run();
|
||||||
|
}
|
||||||
|
return animating;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -583,7 +798,7 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
|
|||||||
mUiEventLogger.log(uiEvent, getSessionId());
|
mUiEventLogger.log(uiEvent, getSessionId());
|
||||||
}
|
}
|
||||||
if (finish) {
|
if (finish) {
|
||||||
mSecurityCallback.finish(strongAuth, targetUserId);
|
mKeyguardSecurityCallback.finish(strongAuth, targetUserId);
|
||||||
}
|
}
|
||||||
return finish;
|
return finish;
|
||||||
}
|
}
|
||||||
@@ -596,10 +811,113 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
|
|||||||
* @return the {@link OnBackAnimationCallback} to animate this view during a back gesture.
|
* @return the {@link OnBackAnimationCallback} to animate this view during a back gesture.
|
||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
OnBackAnimationCallback getBackCallback() {
|
public OnBackAnimationCallback getBackCallback() {
|
||||||
return mView.getBackCallback();
|
return mView.getBackCallback();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return whether we should dispatch the back key event before Ime.
|
||||||
|
*/
|
||||||
|
public boolean dispatchBackKeyEventPreIme() {
|
||||||
|
return getCurrentSecurityMode() == SecurityMode.Password;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows the media keys to work when the keyguard is showing.
|
||||||
|
* The media keys should be of no interest to the actual keyguard view(s),
|
||||||
|
* so intercepting them here should not be of any harm.
|
||||||
|
* @param event The key event
|
||||||
|
* @return whether the event was consumed as a media key.
|
||||||
|
*/
|
||||||
|
public boolean interceptMediaKey(KeyEvent event) {
|
||||||
|
int keyCode = event.getKeyCode();
|
||||||
|
if (event.getAction() == KeyEvent.ACTION_DOWN) {
|
||||||
|
switch (keyCode) {
|
||||||
|
case KeyEvent.KEYCODE_MEDIA_PLAY:
|
||||||
|
case KeyEvent.KEYCODE_MEDIA_PAUSE:
|
||||||
|
case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
|
||||||
|
/* Suppress PLAY/PAUSE toggle when phone is ringing or
|
||||||
|
* in-call to avoid music playback */
|
||||||
|
if (mTelephonyManager != null
|
||||||
|
&& mTelephonyManager.getCallState()
|
||||||
|
!= TelephonyManager.CALL_STATE_IDLE) {
|
||||||
|
return true; // suppress key event
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
case KeyEvent.KEYCODE_MUTE:
|
||||||
|
case KeyEvent.KEYCODE_HEADSETHOOK:
|
||||||
|
case KeyEvent.KEYCODE_MEDIA_STOP:
|
||||||
|
case KeyEvent.KEYCODE_MEDIA_NEXT:
|
||||||
|
case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
|
||||||
|
case KeyEvent.KEYCODE_MEDIA_REWIND:
|
||||||
|
case KeyEvent.KEYCODE_MEDIA_RECORD:
|
||||||
|
case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
|
||||||
|
case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: {
|
||||||
|
handleMediaKeyEvent(event);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
case KeyEvent.KEYCODE_VOLUME_UP:
|
||||||
|
case KeyEvent.KEYCODE_VOLUME_DOWN:
|
||||||
|
case KeyEvent.KEYCODE_VOLUME_MUTE: {
|
||||||
|
if (KEYGUARD_MANAGES_VOLUME) {
|
||||||
|
// Volume buttons should only function for music (local or remote).
|
||||||
|
// TODO: Actually handle MUTE.
|
||||||
|
mAudioManager.adjustSuggestedStreamVolume(
|
||||||
|
keyCode == KeyEvent.KEYCODE_VOLUME_UP
|
||||||
|
? AudioManager.ADJUST_RAISE
|
||||||
|
: AudioManager.ADJUST_LOWER /* direction */,
|
||||||
|
AudioManager.STREAM_MUSIC /* stream */, 0 /* flags */);
|
||||||
|
// Don't execute default volume behavior
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (event.getAction() == KeyEvent.ACTION_UP) {
|
||||||
|
switch (keyCode) {
|
||||||
|
case KeyEvent.KEYCODE_MUTE:
|
||||||
|
case KeyEvent.KEYCODE_HEADSETHOOK:
|
||||||
|
case KeyEvent.KEYCODE_MEDIA_PLAY:
|
||||||
|
case KeyEvent.KEYCODE_MEDIA_PAUSE:
|
||||||
|
case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
|
||||||
|
case KeyEvent.KEYCODE_MEDIA_STOP:
|
||||||
|
case KeyEvent.KEYCODE_MEDIA_NEXT:
|
||||||
|
case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
|
||||||
|
case KeyEvent.KEYCODE_MEDIA_REWIND:
|
||||||
|
case KeyEvent.KEYCODE_MEDIA_RECORD:
|
||||||
|
case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
|
||||||
|
case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: {
|
||||||
|
handleMediaKeyEvent(event);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void handleMediaKeyEvent(KeyEvent keyEvent) {
|
||||||
|
mAudioManager.dispatchMediaKeyEvent(keyEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* In general, we enable unlocking the insecure keyguard with the menu key. However, there are
|
||||||
|
* some cases where we wish to disable it, notably when the menu button placement or technology
|
||||||
|
* is prone to false positives.
|
||||||
|
*
|
||||||
|
* @return true if the menu key should be enabled
|
||||||
|
*/
|
||||||
|
public boolean shouldEnableMenuKey() {
|
||||||
|
final Resources res = mView.getResources();
|
||||||
|
final boolean configDisabled = res.getBoolean(R.bool.config_disableMenuKeyInLockScreen);
|
||||||
|
final boolean isTestHarness = ActivityManager.isRunningInTestHarness();
|
||||||
|
final boolean fileOverride = (new File(ENABLE_MENU_KEY_FILE)).exists();
|
||||||
|
return !configDisabled || isTestHarness || fileOverride;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Switches to the given security view unless it's already being shown, in which case
|
* Switches to the given security view unless it's already being shown, in which case
|
||||||
* this is a no-op.
|
* this is a no-op.
|
||||||
@@ -628,7 +946,7 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
|
|||||||
configureMode();
|
configureMode();
|
||||||
}
|
}
|
||||||
|
|
||||||
mSecurityCallback.onSecurityModeChanged(
|
mKeyguardSecurityCallback.onSecurityModeChanged(
|
||||||
securityMode, newView != null && newView.needsInput());
|
securityMode, newView != null && newView.needsInput());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -726,6 +1044,30 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
|
|||||||
* configuration.
|
* configuration.
|
||||||
*/
|
*/
|
||||||
public void updateResources() {
|
public void updateResources() {
|
||||||
|
int gravity;
|
||||||
|
|
||||||
|
Resources resources = mView.getResources();
|
||||||
|
|
||||||
|
if (resources.getBoolean(R.bool.can_use_one_handed_bouncer)) {
|
||||||
|
gravity = resources.getInteger(
|
||||||
|
R.integer.keyguard_host_view_one_handed_gravity);
|
||||||
|
} else {
|
||||||
|
gravity = resources.getInteger(R.integer.keyguard_host_view_gravity);
|
||||||
|
}
|
||||||
|
|
||||||
|
mTranslationY = resources
|
||||||
|
.getDimensionPixelSize(R.dimen.keyguard_host_view_translation_y);
|
||||||
|
// Android SysUI uses a FrameLayout as the top-level, but Auto uses RelativeLayout.
|
||||||
|
// We're just changing the gravity here though (which can't be applied to RelativeLayout),
|
||||||
|
// so only attempt the update if mView is inside a FrameLayout.
|
||||||
|
if (mView.getLayoutParams() instanceof FrameLayout.LayoutParams) {
|
||||||
|
FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) mView.getLayoutParams();
|
||||||
|
if (lp.gravity != gravity) {
|
||||||
|
lp.gravity = gravity;
|
||||||
|
mView.setLayoutParams(lp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int newOrientation = getResources().getConfiguration().orientation;
|
int newOrientation = getResources().getConfiguration().orientation;
|
||||||
if (newOrientation != mLastOrientation) {
|
if (newOrientation != mLastOrientation) {
|
||||||
mLastOrientation = newOrientation;
|
mLastOrientation = newOrientation;
|
||||||
@@ -759,77 +1101,15 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
|
|||||||
mKeyguardSecurityCallback);
|
mKeyguardSecurityCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
static class Factory {
|
/**
|
||||||
|
* Fades and translates in/out the security screen.
|
||||||
private final KeyguardSecurityContainer mView;
|
* Fades in as expansion approaches 0.
|
||||||
private final AdminSecondaryLockScreenController.Factory
|
* Animation duration is between 0.33f and 0.67f of panel expansion fraction.
|
||||||
mAdminSecondaryLockScreenControllerFactory;
|
* @param fraction amount of the screen that should show.
|
||||||
private final LockPatternUtils mLockPatternUtils;
|
*/
|
||||||
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
|
public void setExpansion(float fraction) {
|
||||||
private final KeyguardSecurityModel mKeyguardSecurityModel;
|
float scaledFraction = BouncerPanelExpansionCalculator.showBouncerProgress(fraction);
|
||||||
private final MetricsLogger mMetricsLogger;
|
mView.setAlpha(MathUtils.constrain(1 - scaledFraction, 0f, 1f));
|
||||||
private final UiEventLogger mUiEventLogger;
|
mView.setTranslationY(scaledFraction * mTranslationY);
|
||||||
private final KeyguardStateController mKeyguardStateController;
|
|
||||||
private final KeyguardSecurityViewFlipperController mSecurityViewFlipperController;
|
|
||||||
private final ConfigurationController mConfigurationController;
|
|
||||||
private final FalsingCollector mFalsingCollector;
|
|
||||||
private final FalsingManager mFalsingManager;
|
|
||||||
private final GlobalSettings mGlobalSettings;
|
|
||||||
private final FeatureFlags mFeatureFlags;
|
|
||||||
private final UserSwitcherController mUserSwitcherController;
|
|
||||||
private final SessionTracker mSessionTracker;
|
|
||||||
private final Optional<SideFpsController> mSidefpsController;
|
|
||||||
private final FalsingA11yDelegate mFalsingA11yDelegate;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
Factory(KeyguardSecurityContainer view,
|
|
||||||
AdminSecondaryLockScreenController.Factory
|
|
||||||
adminSecondaryLockScreenControllerFactory,
|
|
||||||
LockPatternUtils lockPatternUtils,
|
|
||||||
KeyguardUpdateMonitor keyguardUpdateMonitor,
|
|
||||||
KeyguardSecurityModel keyguardSecurityModel,
|
|
||||||
MetricsLogger metricsLogger,
|
|
||||||
UiEventLogger uiEventLogger,
|
|
||||||
KeyguardStateController keyguardStateController,
|
|
||||||
KeyguardSecurityViewFlipperController securityViewFlipperController,
|
|
||||||
ConfigurationController configurationController,
|
|
||||||
FalsingCollector falsingCollector,
|
|
||||||
FalsingManager falsingManager,
|
|
||||||
UserSwitcherController userSwitcherController,
|
|
||||||
FeatureFlags featureFlags,
|
|
||||||
GlobalSettings globalSettings,
|
|
||||||
SessionTracker sessionTracker,
|
|
||||||
Optional<SideFpsController> sidefpsController,
|
|
||||||
FalsingA11yDelegate falsingA11yDelegate) {
|
|
||||||
mView = view;
|
|
||||||
mAdminSecondaryLockScreenControllerFactory = adminSecondaryLockScreenControllerFactory;
|
|
||||||
mLockPatternUtils = lockPatternUtils;
|
|
||||||
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
|
|
||||||
mKeyguardSecurityModel = keyguardSecurityModel;
|
|
||||||
mMetricsLogger = metricsLogger;
|
|
||||||
mUiEventLogger = uiEventLogger;
|
|
||||||
mKeyguardStateController = keyguardStateController;
|
|
||||||
mSecurityViewFlipperController = securityViewFlipperController;
|
|
||||||
mConfigurationController = configurationController;
|
|
||||||
mFalsingCollector = falsingCollector;
|
|
||||||
mFalsingManager = falsingManager;
|
|
||||||
mFeatureFlags = featureFlags;
|
|
||||||
mGlobalSettings = globalSettings;
|
|
||||||
mUserSwitcherController = userSwitcherController;
|
|
||||||
mSessionTracker = sessionTracker;
|
|
||||||
mSidefpsController = sidefpsController;
|
|
||||||
mFalsingA11yDelegate = falsingA11yDelegate;
|
|
||||||
}
|
|
||||||
|
|
||||||
public KeyguardSecurityContainerController create(
|
|
||||||
SecurityCallback securityCallback) {
|
|
||||||
return new KeyguardSecurityContainerController(mView,
|
|
||||||
mAdminSecondaryLockScreenControllerFactory, mLockPatternUtils,
|
|
||||||
mKeyguardUpdateMonitor, mKeyguardSecurityModel, mMetricsLogger, mUiEventLogger,
|
|
||||||
mKeyguardStateController, securityCallback, mSecurityViewFlipperController,
|
|
||||||
mConfigurationController, mFalsingCollector, mFalsingManager,
|
|
||||||
mUserSwitcherController, mFeatureFlags, mGlobalSettings, mSessionTracker,
|
|
||||||
mSidefpsController, mFalsingA11yDelegate);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3747,7 +3747,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: use these callbacks elsewhere in place of the existing notifyScreen*()
|
// TODO: use these callbacks elsewhere in place of the existing notifyScreen*()
|
||||||
// (KeyguardViewMediator, KeyguardHostView)
|
// (KeyguardViewMediator, KeyguardSecurityContainer)
|
||||||
/**
|
/**
|
||||||
* Dispatch wakeup events to:
|
* Dispatch wakeup events to:
|
||||||
* - update biometric listening states
|
* - update biometric listening states
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ package com.android.keyguard.dagger;
|
|||||||
|
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
import com.android.keyguard.KeyguardHostViewController;
|
import com.android.keyguard.KeyguardSecurityContainerController;
|
||||||
import com.android.systemui.dagger.qualifiers.RootView;
|
import com.android.systemui.dagger.qualifiers.RootView;
|
||||||
import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerInteractor;
|
import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerInteractor;
|
||||||
|
|
||||||
@@ -37,6 +37,6 @@ public interface KeyguardBouncerComponent {
|
|||||||
KeyguardBouncerComponent create(@BindsInstance @RootView ViewGroup bouncerContainer);
|
KeyguardBouncerComponent create(@BindsInstance @RootView ViewGroup bouncerContainer);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns a {@link KeyguardHostViewController}. */
|
/** Returns a {@link KeyguardSecurityContainerController}. */
|
||||||
KeyguardHostViewController getKeyguardHostViewController();
|
KeyguardSecurityContainerController getSecurityContainerController();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ import android.hardware.fingerprint.FingerprintManager;
|
|||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
import com.android.keyguard.KeyguardHostView;
|
|
||||||
import com.android.keyguard.KeyguardSecurityContainer;
|
import com.android.keyguard.KeyguardSecurityContainer;
|
||||||
import com.android.keyguard.KeyguardSecurityViewFlipper;
|
import com.android.keyguard.KeyguardSecurityViewFlipper;
|
||||||
import com.android.systemui.R;
|
import com.android.systemui.R;
|
||||||
@@ -47,19 +46,13 @@ public interface KeyguardBouncerModule {
|
|||||||
/** */
|
/** */
|
||||||
@Provides
|
@Provides
|
||||||
@KeyguardBouncerScope
|
@KeyguardBouncerScope
|
||||||
static KeyguardHostView providesKeyguardHostView(@RootView ViewGroup rootView,
|
static KeyguardSecurityContainer providesKeyguardSecurityContainer(@RootView ViewGroup rootView,
|
||||||
LayoutInflater layoutInflater) {
|
LayoutInflater layoutInflater) {
|
||||||
KeyguardHostView hostView = (KeyguardHostView) layoutInflater.inflate(
|
KeyguardSecurityContainer securityContainer =
|
||||||
R.layout.keyguard_host_view, rootView, false);
|
(KeyguardSecurityContainer) layoutInflater.inflate(
|
||||||
rootView.addView(hostView);
|
R.layout.keyguard_security_container_view, rootView, false);
|
||||||
return hostView;
|
rootView.addView(securityContainer);
|
||||||
}
|
return securityContainer;
|
||||||
|
|
||||||
/** */
|
|
||||||
@Provides
|
|
||||||
@KeyguardBouncerScope
|
|
||||||
static KeyguardSecurityContainer providesKeyguardSecurityContainer(KeyguardHostView hostView) {
|
|
||||||
return hostView.findViewById(R.id.keyguard_security_container);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** */
|
/** */
|
||||||
|
|||||||
@@ -23,10 +23,12 @@ import android.window.OnBackAnimationCallback
|
|||||||
import androidx.lifecycle.Lifecycle
|
import androidx.lifecycle.Lifecycle
|
||||||
import androidx.lifecycle.repeatOnLifecycle
|
import androidx.lifecycle.repeatOnLifecycle
|
||||||
import com.android.internal.policy.SystemBarUtils
|
import com.android.internal.policy.SystemBarUtils
|
||||||
import com.android.keyguard.KeyguardHostViewController
|
import com.android.keyguard.KeyguardSecurityContainerController
|
||||||
import com.android.keyguard.KeyguardSecurityModel
|
import com.android.keyguard.KeyguardSecurityModel
|
||||||
|
import com.android.keyguard.KeyguardSecurityView
|
||||||
import com.android.keyguard.KeyguardUpdateMonitor
|
import com.android.keyguard.KeyguardUpdateMonitor
|
||||||
import com.android.keyguard.dagger.KeyguardBouncerComponent
|
import com.android.keyguard.dagger.KeyguardBouncerComponent
|
||||||
|
import com.android.settingslib.Utils
|
||||||
import com.android.systemui.keyguard.data.BouncerViewDelegate
|
import com.android.systemui.keyguard.data.BouncerViewDelegate
|
||||||
import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.EXPANSION_VISIBLE
|
import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.EXPANSION_VISIBLE
|
||||||
import com.android.systemui.keyguard.ui.viewmodel.KeyguardBouncerViewModel
|
import com.android.systemui.keyguard.ui.viewmodel.KeyguardBouncerViewModel
|
||||||
@@ -44,52 +46,54 @@ object KeyguardBouncerViewBinder {
|
|||||||
viewModel: KeyguardBouncerViewModel,
|
viewModel: KeyguardBouncerViewModel,
|
||||||
componentFactory: KeyguardBouncerComponent.Factory
|
componentFactory: KeyguardBouncerComponent.Factory
|
||||||
) {
|
) {
|
||||||
// Builds the KeyguardHostViewController from bouncer view group.
|
// Builds the KeyguardSecurityContainerController from bouncer view group.
|
||||||
val hostViewController: KeyguardHostViewController =
|
val securityContainerController: KeyguardSecurityContainerController =
|
||||||
componentFactory.create(view).keyguardHostViewController
|
componentFactory.create(view).securityContainerController
|
||||||
hostViewController.init()
|
securityContainerController.init()
|
||||||
val delegate =
|
val delegate =
|
||||||
object : BouncerViewDelegate {
|
object : BouncerViewDelegate {
|
||||||
override fun isFullScreenBouncer(): Boolean {
|
override fun isFullScreenBouncer(): Boolean {
|
||||||
val mode = hostViewController.currentSecurityMode
|
val mode = securityContainerController.currentSecurityMode
|
||||||
return mode == KeyguardSecurityModel.SecurityMode.SimPin ||
|
return mode == KeyguardSecurityModel.SecurityMode.SimPin ||
|
||||||
mode == KeyguardSecurityModel.SecurityMode.SimPuk
|
mode == KeyguardSecurityModel.SecurityMode.SimPuk
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getBackCallback(): OnBackAnimationCallback {
|
override fun getBackCallback(): OnBackAnimationCallback {
|
||||||
return hostViewController.backCallback
|
return securityContainerController.backCallback
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun shouldDismissOnMenuPressed(): Boolean {
|
override fun shouldDismissOnMenuPressed(): Boolean {
|
||||||
return hostViewController.shouldEnableMenuKey()
|
return securityContainerController.shouldEnableMenuKey()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun interceptMediaKey(event: KeyEvent?): Boolean {
|
override fun interceptMediaKey(event: KeyEvent?): Boolean {
|
||||||
return hostViewController.interceptMediaKey(event)
|
return securityContainerController.interceptMediaKey(event)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun dispatchBackKeyEventPreIme(): Boolean {
|
override fun dispatchBackKeyEventPreIme(): Boolean {
|
||||||
return hostViewController.dispatchBackKeyEventPreIme()
|
return securityContainerController.dispatchBackKeyEventPreIme()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun showNextSecurityScreenOrFinish(): Boolean {
|
override fun showNextSecurityScreenOrFinish(): Boolean {
|
||||||
return hostViewController.dismiss(KeyguardUpdateMonitor.getCurrentUser())
|
return securityContainerController.dismiss(
|
||||||
|
KeyguardUpdateMonitor.getCurrentUser()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun resume() {
|
override fun resume() {
|
||||||
hostViewController.showPrimarySecurityScreen()
|
securityContainerController.showPrimarySecurityScreen(/* isTurningOff= */ false)
|
||||||
hostViewController.onResume()
|
securityContainerController.onResume(KeyguardSecurityView.SCREEN_ON)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setDismissAction(
|
override fun setDismissAction(
|
||||||
onDismissAction: ActivityStarter.OnDismissAction?,
|
onDismissAction: ActivityStarter.OnDismissAction?,
|
||||||
cancelAction: Runnable?
|
cancelAction: Runnable?
|
||||||
) {
|
) {
|
||||||
hostViewController.setOnDismissAction(onDismissAction, cancelAction)
|
securityContainerController.setOnDismissAction(onDismissAction, cancelAction)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun willDismissWithActions(): Boolean {
|
override fun willDismissWithActions(): Boolean {
|
||||||
return hostViewController.hasDismissActions()
|
return securityContainerController.hasDismissActions()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
view.repeatWhenAttached {
|
view.repeatWhenAttached {
|
||||||
@@ -98,39 +102,46 @@ object KeyguardBouncerViewBinder {
|
|||||||
viewModel.setBouncerViewDelegate(delegate)
|
viewModel.setBouncerViewDelegate(delegate)
|
||||||
launch {
|
launch {
|
||||||
viewModel.show.collect {
|
viewModel.show.collect {
|
||||||
hostViewController.showPromptReason(it.promptReason)
|
securityContainerController.showPromptReason(it.promptReason)
|
||||||
it.errorMessage?.let { errorMessage ->
|
it.errorMessage?.let { errorMessage ->
|
||||||
hostViewController.showErrorMessage(errorMessage)
|
securityContainerController.showMessage(
|
||||||
|
errorMessage,
|
||||||
|
Utils.getColorError(view.context)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
hostViewController.showPrimarySecurityScreen()
|
securityContainerController.showPrimarySecurityScreen(
|
||||||
hostViewController.appear(
|
/* turningOff= */ false
|
||||||
|
)
|
||||||
|
securityContainerController.appear(
|
||||||
SystemBarUtils.getStatusBarHeight(view.context)
|
SystemBarUtils.getStatusBarHeight(view.context)
|
||||||
)
|
)
|
||||||
hostViewController.onResume()
|
securityContainerController.onResume(KeyguardSecurityView.SCREEN_ON)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
launch {
|
launch {
|
||||||
viewModel.hide.collect {
|
viewModel.hide.collect {
|
||||||
hostViewController.cancelDismissAction()
|
securityContainerController.cancelDismissAction()
|
||||||
hostViewController.cleanUp()
|
securityContainerController.onPause()
|
||||||
hostViewController.resetSecurityContainer()
|
securityContainerController.reset()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
launch {
|
launch {
|
||||||
viewModel.startingToHide.collect { hostViewController.onStartingToHide() }
|
viewModel.startingToHide.collect {
|
||||||
|
securityContainerController.onStartingToHide()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
launch {
|
launch {
|
||||||
viewModel.startDisappearAnimation.collect {
|
viewModel.startDisappearAnimation.collect {
|
||||||
hostViewController.startDisappearAnimation(it)
|
securityContainerController.startDisappearAnimation(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
launch {
|
launch {
|
||||||
viewModel.bouncerExpansionAmount.collect { expansion ->
|
viewModel.bouncerExpansionAmount.collect { expansion ->
|
||||||
hostViewController.setExpansion(expansion)
|
securityContainerController.setExpansion(expansion)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,10 +149,8 @@ object KeyguardBouncerViewBinder {
|
|||||||
viewModel.bouncerExpansionAmount
|
viewModel.bouncerExpansionAmount
|
||||||
.filter { it == EXPANSION_VISIBLE }
|
.filter { it == EXPANSION_VISIBLE }
|
||||||
.collect {
|
.collect {
|
||||||
hostViewController.onResume()
|
securityContainerController.onResume(KeyguardSecurityView.SCREEN_ON)
|
||||||
view.announceForAccessibility(
|
view.announceForAccessibility(securityContainerController.title)
|
||||||
hostViewController.accessibilityTitleForCurrentMode
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,13 +158,13 @@ object KeyguardBouncerViewBinder {
|
|||||||
viewModel.isBouncerVisible.collect { isVisible ->
|
viewModel.isBouncerVisible.collect { isVisible ->
|
||||||
val visibility = if (isVisible) View.VISIBLE else View.INVISIBLE
|
val visibility = if (isVisible) View.VISIBLE else View.INVISIBLE
|
||||||
view.visibility = visibility
|
view.visibility = visibility
|
||||||
hostViewController.onBouncerVisibilityChanged(visibility)
|
securityContainerController.onBouncerVisibilityChanged(visibility)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
launch {
|
launch {
|
||||||
viewModel.isInteractable.collect { isInteractable ->
|
viewModel.isInteractable.collect { isInteractable ->
|
||||||
hostViewController.setInteractable(isInteractable)
|
securityContainerController.setInteractable(isInteractable)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,33 +173,36 @@ object KeyguardBouncerViewBinder {
|
|||||||
.filter { !it }
|
.filter { !it }
|
||||||
.collect {
|
.collect {
|
||||||
// Remove existing input for security reasons.
|
// Remove existing input for security reasons.
|
||||||
hostViewController.resetSecurityContainer()
|
securityContainerController.reset()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
launch {
|
launch {
|
||||||
viewModel.keyguardPosition.collect { position ->
|
viewModel.keyguardPosition.collect { position ->
|
||||||
hostViewController.updateKeyguardPosition(position)
|
securityContainerController.updateKeyguardPosition(position)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
launch {
|
launch {
|
||||||
viewModel.updateResources.collect {
|
viewModel.updateResources.collect {
|
||||||
hostViewController.updateResources()
|
securityContainerController.updateResources()
|
||||||
viewModel.notifyUpdateResources()
|
viewModel.notifyUpdateResources()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
launch {
|
launch {
|
||||||
viewModel.bouncerShowMessage.collect {
|
viewModel.bouncerShowMessage.collect {
|
||||||
hostViewController.showMessage(it.message, it.colorStateList)
|
securityContainerController.showMessage(it.message, it.colorStateList)
|
||||||
viewModel.onMessageShown()
|
viewModel.onMessageShown()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
launch {
|
launch {
|
||||||
viewModel.keyguardAuthenticated.collect {
|
viewModel.keyguardAuthenticated.collect {
|
||||||
hostViewController.finish(it, KeyguardUpdateMonitor.getCurrentUser())
|
securityContainerController.finish(
|
||||||
|
it,
|
||||||
|
KeyguardUpdateMonitor.getCurrentUser()
|
||||||
|
)
|
||||||
viewModel.notifyKeyguardAuthenticated()
|
viewModel.notifyKeyguardAuthenticated()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -204,7 +216,7 @@ object KeyguardBouncerViewBinder {
|
|||||||
launch {
|
launch {
|
||||||
viewModel.screenTurnedOff.collect {
|
viewModel.screenTurnedOff.collect {
|
||||||
if (view.visibility == View.VISIBLE) {
|
if (view.visibility == View.VISIBLE) {
|
||||||
hostViewController.onPause()
|
securityContainerController.onPause()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,186 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2018 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.android.keyguard;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
import static org.junit.Assert.assertFalse;
|
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
|
||||||
import static org.mockito.Mockito.inOrder;
|
|
||||||
import static org.mockito.Mockito.mock;
|
|
||||||
import static org.mockito.Mockito.verify;
|
|
||||||
import static org.mockito.Mockito.when;
|
|
||||||
|
|
||||||
import android.media.AudioManager;
|
|
||||||
import android.telephony.TelephonyManager;
|
|
||||||
import android.test.suitebuilder.annotation.SmallTest;
|
|
||||||
import android.testing.AndroidTestingRunner;
|
|
||||||
import android.testing.TestableLooper;
|
|
||||||
import android.testing.TestableResources;
|
|
||||||
import android.view.Gravity;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.FrameLayout;
|
|
||||||
|
|
||||||
import com.android.systemui.R;
|
|
||||||
import com.android.systemui.SysuiTestCase;
|
|
||||||
import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
|
|
||||||
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Rule;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
import org.mockito.InOrder;
|
|
||||||
import org.mockito.Mock;
|
|
||||||
import org.mockito.junit.MockitoJUnit;
|
|
||||||
import org.mockito.junit.MockitoRule;
|
|
||||||
|
|
||||||
@SmallTest
|
|
||||||
@RunWith(AndroidTestingRunner.class)
|
|
||||||
@TestableLooper.RunWithLooper
|
|
||||||
public class KeyguardHostViewControllerTest extends SysuiTestCase {
|
|
||||||
@Mock
|
|
||||||
private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
|
|
||||||
|
|
||||||
private KeyguardHostView mKeyguardHostView;
|
|
||||||
@Mock
|
|
||||||
private AudioManager mAudioManager;
|
|
||||||
@Mock
|
|
||||||
private TelephonyManager mTelephonyManager;
|
|
||||||
@Mock
|
|
||||||
private ViewMediatorCallback mViewMediatorCallback;
|
|
||||||
@Mock
|
|
||||||
KeyguardSecurityContainerController.Factory mKeyguardSecurityContainerControllerFactory;
|
|
||||||
@Mock
|
|
||||||
private KeyguardSecurityContainerController mKeyguardSecurityContainerController;
|
|
||||||
|
|
||||||
@Rule
|
|
||||||
public MockitoRule mMockitoRule = MockitoJUnit.rule();
|
|
||||||
|
|
||||||
private TestableResources mTestableResources;
|
|
||||||
private KeyguardHostViewController mKeyguardHostViewController;
|
|
||||||
|
|
||||||
@Before
|
|
||||||
public void setup() {
|
|
||||||
mTestableResources = mContext.getOrCreateTestableResources();
|
|
||||||
|
|
||||||
mKeyguardHostView = new KeyguardHostView(mContext);
|
|
||||||
|
|
||||||
// Explicitly disable one handed keyguard.
|
|
||||||
mTestableResources.addOverride(
|
|
||||||
R.bool.can_use_one_handed_bouncer, false);
|
|
||||||
|
|
||||||
when(mKeyguardSecurityContainerControllerFactory.create(any(
|
|
||||||
KeyguardSecurityContainer.SecurityCallback.class)))
|
|
||||||
.thenReturn(mKeyguardSecurityContainerController);
|
|
||||||
mKeyguardHostViewController = new KeyguardHostViewController(
|
|
||||||
mKeyguardHostView, mKeyguardUpdateMonitor, mAudioManager, mTelephonyManager,
|
|
||||||
mViewMediatorCallback, mKeyguardSecurityContainerControllerFactory);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testHasDismissActions() {
|
|
||||||
assertFalse("Action not set yet", mKeyguardHostViewController.hasDismissActions());
|
|
||||||
mKeyguardHostViewController.setOnDismissAction(mock(OnDismissAction.class),
|
|
||||||
null /* cancelAction */);
|
|
||||||
assertTrue("Action should exist", mKeyguardHostViewController.hasDismissActions());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testOnStartingToHide() {
|
|
||||||
mKeyguardHostViewController.onStartingToHide();
|
|
||||||
verify(mKeyguardSecurityContainerController).onStartingToHide();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void onBouncerVisible_propagatesToKeyguardSecurityContainerController() {
|
|
||||||
mKeyguardHostViewController.onBouncerVisibilityChanged(ViewGroup.VISIBLE);
|
|
||||||
mKeyguardHostViewController.onBouncerVisibilityChanged(ViewGroup.INVISIBLE);
|
|
||||||
|
|
||||||
InOrder order = inOrder(mKeyguardSecurityContainerController);
|
|
||||||
order.verify(mKeyguardSecurityContainerController).onBouncerVisibilityChanged(View.VISIBLE);
|
|
||||||
order.verify(mKeyguardSecurityContainerController).onBouncerVisibilityChanged(
|
|
||||||
View.INVISIBLE);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testGravityReappliedOnConfigurationChange() {
|
|
||||||
FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(
|
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT);
|
|
||||||
mKeyguardHostView.setLayoutParams(lp);
|
|
||||||
|
|
||||||
// Set initial gravity
|
|
||||||
mTestableResources.addOverride(R.integer.keyguard_host_view_gravity,
|
|
||||||
Gravity.CENTER);
|
|
||||||
|
|
||||||
// Kick off the initial pass...
|
|
||||||
mKeyguardHostViewController.init();
|
|
||||||
assertEquals(
|
|
||||||
((FrameLayout.LayoutParams) mKeyguardHostView.getLayoutParams()).gravity,
|
|
||||||
Gravity.CENTER);
|
|
||||||
|
|
||||||
// Now simulate a config change
|
|
||||||
mTestableResources.addOverride(R.integer.keyguard_host_view_gravity,
|
|
||||||
Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM);
|
|
||||||
|
|
||||||
mKeyguardHostViewController.updateResources();
|
|
||||||
assertEquals(
|
|
||||||
((FrameLayout.LayoutParams) mKeyguardHostView.getLayoutParams()).gravity,
|
|
||||||
Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testGravityUsesOneHandGravityWhenApplicable() {
|
|
||||||
FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(
|
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT);
|
|
||||||
mKeyguardHostView.setLayoutParams(lp);
|
|
||||||
|
|
||||||
mTestableResources.addOverride(
|
|
||||||
R.integer.keyguard_host_view_gravity,
|
|
||||||
Gravity.CENTER);
|
|
||||||
mTestableResources.addOverride(
|
|
||||||
R.integer.keyguard_host_view_one_handed_gravity,
|
|
||||||
Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM);
|
|
||||||
|
|
||||||
// Start disabled.
|
|
||||||
mTestableResources.addOverride(
|
|
||||||
R.bool.can_use_one_handed_bouncer, false);
|
|
||||||
|
|
||||||
mKeyguardHostViewController.init();
|
|
||||||
assertEquals(
|
|
||||||
((FrameLayout.LayoutParams) mKeyguardHostView.getLayoutParams()).gravity,
|
|
||||||
Gravity.CENTER);
|
|
||||||
|
|
||||||
// And enable
|
|
||||||
mTestableResources.addOverride(
|
|
||||||
R.bool.can_use_one_handed_bouncer, true);
|
|
||||||
|
|
||||||
mKeyguardHostViewController.updateResources();
|
|
||||||
assertEquals(
|
|
||||||
((FrameLayout.LayoutParams) mKeyguardHostView.getLayoutParams()).gravity,
|
|
||||||
Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testUpdateKeyguardPositionDelegatesToSecurityContainer() {
|
|
||||||
mKeyguardHostViewController.updateKeyguardPosition(1.0f);
|
|
||||||
|
|
||||||
verify(mKeyguardSecurityContainerController).updateKeyguardPosition(1.0f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -23,12 +23,17 @@ 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 junit.framework.Assert.assertFalse;
|
||||||
|
import static junit.framework.Assert.assertTrue;
|
||||||
|
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||||
import static org.mockito.ArgumentMatchers.anyInt;
|
import static org.mockito.ArgumentMatchers.anyInt;
|
||||||
import static org.mockito.ArgumentMatchers.anyLong;
|
import static org.mockito.ArgumentMatchers.anyLong;
|
||||||
|
import static org.mockito.ArgumentMatchers.argThat;
|
||||||
import static org.mockito.ArgumentMatchers.eq;
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
import static org.mockito.Mockito.atLeastOnce;
|
import static org.mockito.Mockito.atLeastOnce;
|
||||||
|
import static org.mockito.Mockito.clearInvocations;
|
||||||
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.reset;
|
||||||
@@ -39,12 +44,17 @@ import static org.mockito.Mockito.when;
|
|||||||
import android.content.res.Configuration;
|
import android.content.res.Configuration;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.hardware.biometrics.BiometricSourceType;
|
import android.hardware.biometrics.BiometricSourceType;
|
||||||
|
import android.media.AudioManager;
|
||||||
|
import android.telephony.TelephonyManager;
|
||||||
import android.testing.AndroidTestingRunner;
|
import android.testing.AndroidTestingRunner;
|
||||||
import android.testing.TestableLooper;
|
import android.testing.TestableLooper;
|
||||||
|
import android.testing.TestableResources;
|
||||||
|
import android.view.Gravity;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.WindowInsetsController;
|
import android.view.WindowInsetsController;
|
||||||
|
import android.widget.FrameLayout;
|
||||||
|
|
||||||
import androidx.test.filters.SmallTest;
|
import androidx.test.filters.SmallTest;
|
||||||
|
|
||||||
@@ -60,6 +70,7 @@ import com.android.systemui.classifier.FalsingA11yDelegate;
|
|||||||
import com.android.systemui.classifier.FalsingCollector;
|
import com.android.systemui.classifier.FalsingCollector;
|
||||||
import com.android.systemui.flags.FeatureFlags;
|
import com.android.systemui.flags.FeatureFlags;
|
||||||
import com.android.systemui.log.SessionTracker;
|
import com.android.systemui.log.SessionTracker;
|
||||||
|
import com.android.systemui.plugins.ActivityStarter;
|
||||||
import com.android.systemui.plugins.FalsingManager;
|
import com.android.systemui.plugins.FalsingManager;
|
||||||
import com.android.systemui.statusbar.policy.ConfigurationController;
|
import com.android.systemui.statusbar.policy.ConfigurationController;
|
||||||
import com.android.systemui.statusbar.policy.KeyguardStateController;
|
import com.android.systemui.statusbar.policy.KeyguardStateController;
|
||||||
@@ -71,6 +82,7 @@ import org.junit.Rule;
|
|||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.mockito.ArgumentCaptor;
|
import org.mockito.ArgumentCaptor;
|
||||||
|
import org.mockito.ArgumentMatcher;
|
||||||
import org.mockito.Captor;
|
import org.mockito.Captor;
|
||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import org.mockito.junit.MockitoJUnit;
|
import org.mockito.junit.MockitoJUnit;
|
||||||
@@ -108,8 +120,6 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase {
|
|||||||
@Mock
|
@Mock
|
||||||
private KeyguardInputViewController mInputViewController;
|
private KeyguardInputViewController mInputViewController;
|
||||||
@Mock
|
@Mock
|
||||||
private KeyguardSecurityContainer.SecurityCallback mSecurityCallback;
|
|
||||||
@Mock
|
|
||||||
private WindowInsetsController mWindowInsetsController;
|
private WindowInsetsController mWindowInsetsController;
|
||||||
@Mock
|
@Mock
|
||||||
private KeyguardSecurityViewFlipper mSecurityViewFlipper;
|
private KeyguardSecurityViewFlipper mSecurityViewFlipper;
|
||||||
@@ -126,8 +136,6 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase {
|
|||||||
@Mock
|
@Mock
|
||||||
private EmergencyButtonController mEmergencyButtonController;
|
private EmergencyButtonController mEmergencyButtonController;
|
||||||
@Mock
|
@Mock
|
||||||
private Resources mResources;
|
|
||||||
@Mock
|
|
||||||
private FalsingCollector mFalsingCollector;
|
private FalsingCollector mFalsingCollector;
|
||||||
@Mock
|
@Mock
|
||||||
private FalsingManager mFalsingManager;
|
private FalsingManager mFalsingManager;
|
||||||
@@ -147,6 +155,12 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase {
|
|||||||
private KeyguardPasswordViewController mKeyguardPasswordViewControllerMock;
|
private KeyguardPasswordViewController mKeyguardPasswordViewControllerMock;
|
||||||
@Mock
|
@Mock
|
||||||
private FalsingA11yDelegate mFalsingA11yDelegate;
|
private FalsingA11yDelegate mFalsingA11yDelegate;
|
||||||
|
@Mock
|
||||||
|
private TelephonyManager mTelephonyManager;
|
||||||
|
@Mock
|
||||||
|
private ViewMediatorCallback mViewMediatorCallback;
|
||||||
|
@Mock
|
||||||
|
private AudioManager mAudioManager;
|
||||||
|
|
||||||
@Captor
|
@Captor
|
||||||
private ArgumentCaptor<KeyguardUpdateMonitorCallback> mKeyguardUpdateMonitorCallback;
|
private ArgumentCaptor<KeyguardUpdateMonitorCallback> mKeyguardUpdateMonitorCallback;
|
||||||
@@ -158,18 +172,25 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase {
|
|||||||
private KeyguardSecurityContainerController mKeyguardSecurityContainerController;
|
private KeyguardSecurityContainerController mKeyguardSecurityContainerController;
|
||||||
private KeyguardPasswordViewController mKeyguardPasswordViewController;
|
private KeyguardPasswordViewController mKeyguardPasswordViewController;
|
||||||
private KeyguardPasswordView mKeyguardPasswordView;
|
private KeyguardPasswordView mKeyguardPasswordView;
|
||||||
|
private TestableResources mTestableResources;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setup() {
|
public void setup() {
|
||||||
mConfiguration = new Configuration();
|
mConfiguration = new Configuration();
|
||||||
mConfiguration.setToDefaults(); // Defaults to ORIENTATION_UNDEFINED.
|
mConfiguration.setToDefaults(); // Defaults to ORIENTATION_UNDEFINED.
|
||||||
|
mTestableResources = mContext.getOrCreateTestableResources();
|
||||||
|
|
||||||
when(mResources.getConfiguration()).thenReturn(mConfiguration);
|
|
||||||
when(mView.getContext()).thenReturn(mContext);
|
when(mView.getContext()).thenReturn(mContext);
|
||||||
when(mView.getResources()).thenReturn(mResources);
|
when(mView.getResources()).thenReturn(mContext.getResources());
|
||||||
|
FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(/* width= */ 0, /* height= */
|
||||||
|
0);
|
||||||
|
lp.gravity = 0;
|
||||||
|
when(mView.getLayoutParams()).thenReturn(lp);
|
||||||
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);
|
||||||
|
when(mKeyguardSecurityViewFlipperController.getSecurityView(any(SecurityMode.class),
|
||||||
|
any(KeyguardSecurityCallback.class))).thenReturn(mInputViewController);
|
||||||
mKeyguardPasswordView = spy((KeyguardPasswordView) LayoutInflater.from(mContext).inflate(
|
mKeyguardPasswordView = spy((KeyguardPasswordView) LayoutInflater.from(mContext).inflate(
|
||||||
R.layout.keyguard_password_view, null));
|
R.layout.keyguard_password_view, null));
|
||||||
when(mKeyguardPasswordView.getRootView()).thenReturn(mSecurityViewFlipper);
|
when(mKeyguardPasswordView.getRootView()).thenReturn(mSecurityViewFlipper);
|
||||||
@@ -178,20 +199,21 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase {
|
|||||||
when(mKeyguardMessageAreaControllerFactory.create(any(KeyguardMessageArea.class)))
|
when(mKeyguardMessageAreaControllerFactory.create(any(KeyguardMessageArea.class)))
|
||||||
.thenReturn(mKeyguardMessageAreaController);
|
.thenReturn(mKeyguardMessageAreaController);
|
||||||
when(mKeyguardPasswordView.getWindowInsetsController()).thenReturn(mWindowInsetsController);
|
when(mKeyguardPasswordView.getWindowInsetsController()).thenReturn(mWindowInsetsController);
|
||||||
|
when(mKeyguardSecurityModel.getSecurityMode(anyInt())).thenReturn(SecurityMode.PIN);
|
||||||
mKeyguardPasswordViewController = new KeyguardPasswordViewController(
|
mKeyguardPasswordViewController = new KeyguardPasswordViewController(
|
||||||
(KeyguardPasswordView) mKeyguardPasswordView, mKeyguardUpdateMonitor,
|
(KeyguardPasswordView) mKeyguardPasswordView, mKeyguardUpdateMonitor,
|
||||||
SecurityMode.Password, mLockPatternUtils, null,
|
SecurityMode.Password, mLockPatternUtils, null,
|
||||||
mKeyguardMessageAreaControllerFactory, null, null, mEmergencyButtonController,
|
mKeyguardMessageAreaControllerFactory, null, null, mEmergencyButtonController,
|
||||||
null, mock(Resources.class), null, mKeyguardViewController);
|
null, mock(Resources.class), null, mKeyguardViewController);
|
||||||
|
|
||||||
mKeyguardSecurityContainerController = new KeyguardSecurityContainerController.Factory(
|
mKeyguardSecurityContainerController = new KeyguardSecurityContainerController(
|
||||||
mView, mAdminSecondaryLockScreenControllerFactory, mLockPatternUtils,
|
mView, mAdminSecondaryLockScreenControllerFactory, mLockPatternUtils,
|
||||||
mKeyguardUpdateMonitor, mKeyguardSecurityModel, mMetricsLogger, mUiEventLogger,
|
mKeyguardUpdateMonitor, mKeyguardSecurityModel, mMetricsLogger, mUiEventLogger,
|
||||||
mKeyguardStateController, mKeyguardSecurityViewFlipperController,
|
mKeyguardStateController, mKeyguardSecurityViewFlipperController,
|
||||||
mConfigurationController, mFalsingCollector, mFalsingManager,
|
mConfigurationController, mFalsingCollector, mFalsingManager,
|
||||||
mUserSwitcherController, mFeatureFlags, mGlobalSettings,
|
mUserSwitcherController, mFeatureFlags, mGlobalSettings,
|
||||||
mSessionTracker, Optional.of(mSideFpsController), mFalsingA11yDelegate).create(
|
mSessionTracker, Optional.of(mSideFpsController), mFalsingA11yDelegate,
|
||||||
mSecurityCallback);
|
mTelephonyManager, mViewMediatorCallback, mAudioManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -243,7 +265,8 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase {
|
|||||||
eq(mFalsingA11yDelegate));
|
eq(mFalsingA11yDelegate));
|
||||||
|
|
||||||
// Update rotation. Should trigger update
|
// Update rotation. Should trigger update
|
||||||
mConfiguration.orientation = Configuration.ORIENTATION_LANDSCAPE;
|
mTestableResources.getResources().getConfiguration().orientation =
|
||||||
|
Configuration.ORIENTATION_LANDSCAPE;
|
||||||
|
|
||||||
mKeyguardSecurityContainerController.updateResources();
|
mKeyguardSecurityContainerController.updateResources();
|
||||||
verify(mView).initMode(eq(MODE_DEFAULT), eq(mGlobalSettings), eq(mFalsingManager),
|
verify(mView).initMode(eq(MODE_DEFAULT), eq(mGlobalSettings), eq(mFalsingManager),
|
||||||
@@ -277,7 +300,7 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void showSecurityScreen_oneHandedMode_flagDisabled_noOneHandedMode() {
|
public void showSecurityScreen_oneHandedMode_flagDisabled_noOneHandedMode() {
|
||||||
when(mResources.getBoolean(R.bool.can_use_one_handed_bouncer)).thenReturn(false);
|
mTestableResources.addOverride(R.bool.can_use_one_handed_bouncer, false);
|
||||||
when(mKeyguardSecurityViewFlipperController.getSecurityView(
|
when(mKeyguardSecurityViewFlipperController.getSecurityView(
|
||||||
eq(SecurityMode.Pattern), any(KeyguardSecurityCallback.class)))
|
eq(SecurityMode.Pattern), any(KeyguardSecurityCallback.class)))
|
||||||
.thenReturn((KeyguardInputViewController) mKeyguardPasswordViewController);
|
.thenReturn((KeyguardInputViewController) mKeyguardPasswordViewController);
|
||||||
@@ -291,7 +314,7 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void showSecurityScreen_oneHandedMode_flagEnabled_oneHandedMode() {
|
public void showSecurityScreen_oneHandedMode_flagEnabled_oneHandedMode() {
|
||||||
when(mResources.getBoolean(R.bool.can_use_one_handed_bouncer)).thenReturn(true);
|
mTestableResources.addOverride(R.bool.can_use_one_handed_bouncer, true);
|
||||||
when(mKeyguardSecurityViewFlipperController.getSecurityView(
|
when(mKeyguardSecurityViewFlipperController.getSecurityView(
|
||||||
eq(SecurityMode.Pattern), any(KeyguardSecurityCallback.class)))
|
eq(SecurityMode.Pattern), any(KeyguardSecurityCallback.class)))
|
||||||
.thenReturn((KeyguardInputViewController) mKeyguardPasswordViewController);
|
.thenReturn((KeyguardInputViewController) mKeyguardPasswordViewController);
|
||||||
@@ -305,7 +328,7 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void showSecurityScreen_twoHandedMode_flagEnabled_noOneHandedMode() {
|
public void showSecurityScreen_twoHandedMode_flagEnabled_noOneHandedMode() {
|
||||||
when(mResources.getBoolean(R.bool.can_use_one_handed_bouncer)).thenReturn(true);
|
mTestableResources.addOverride(R.bool.can_use_one_handed_bouncer, true);
|
||||||
setupGetSecurityView();
|
setupGetSecurityView();
|
||||||
|
|
||||||
mKeyguardSecurityContainerController.showSecurityScreen(SecurityMode.Password);
|
mKeyguardSecurityContainerController.showSecurityScreen(SecurityMode.Password);
|
||||||
@@ -482,7 +505,9 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase {
|
|||||||
SecurityMode.SimPin);
|
SecurityMode.SimPin);
|
||||||
|
|
||||||
// THEN the next security method of PIN is set, and the keyguard is not marked as done
|
// THEN the next security method of PIN is set, and the keyguard is not marked as done
|
||||||
verify(mSecurityCallback, never()).finish(anyBoolean(), anyInt());
|
|
||||||
|
verify(mViewMediatorCallback, never()).keyguardDonePending(anyBoolean(), anyInt());
|
||||||
|
verify(mViewMediatorCallback, never()).keyguardDone(anyBoolean(), anyInt());
|
||||||
assertThat(mKeyguardSecurityContainerController.getCurrentSecurityMode())
|
assertThat(mKeyguardSecurityContainerController.getCurrentSecurityMode())
|
||||||
.isEqualTo(SecurityMode.PIN);
|
.isEqualTo(SecurityMode.PIN);
|
||||||
}
|
}
|
||||||
@@ -556,17 +581,19 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void onDensityorFontScaleChanged() {
|
public void onDensityOrFontScaleChanged() {
|
||||||
ArgumentCaptor<ConfigurationController.ConfigurationListener>
|
ArgumentCaptor<ConfigurationController.ConfigurationListener>
|
||||||
configurationListenerArgumentCaptor = ArgumentCaptor.forClass(
|
configurationListenerArgumentCaptor = ArgumentCaptor.forClass(
|
||||||
ConfigurationController.ConfigurationListener.class);
|
ConfigurationController.ConfigurationListener.class);
|
||||||
mKeyguardSecurityContainerController.onViewAttached();
|
mKeyguardSecurityContainerController.onViewAttached();
|
||||||
verify(mConfigurationController).addCallback(configurationListenerArgumentCaptor.capture());
|
verify(mConfigurationController).addCallback(configurationListenerArgumentCaptor.capture());
|
||||||
|
clearInvocations(mKeyguardSecurityViewFlipperController);
|
||||||
|
|
||||||
configurationListenerArgumentCaptor.getValue().onDensityOrFontScaleChanged();
|
configurationListenerArgumentCaptor.getValue().onDensityOrFontScaleChanged();
|
||||||
|
|
||||||
verify(mView).onDensityOrFontScaleChanged();
|
verify(mView).onDensityOrFontScaleChanged();
|
||||||
verify(mKeyguardSecurityViewFlipperController).clearViews();
|
verify(mKeyguardSecurityViewFlipperController).clearViews();
|
||||||
verify(mKeyguardSecurityViewFlipperController).getSecurityView(any(SecurityMode.class),
|
verify(mKeyguardSecurityViewFlipperController).getSecurityView(eq(SecurityMode.PIN),
|
||||||
any(KeyguardSecurityCallback.class));
|
any(KeyguardSecurityCallback.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -577,11 +604,13 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase {
|
|||||||
ConfigurationController.ConfigurationListener.class);
|
ConfigurationController.ConfigurationListener.class);
|
||||||
mKeyguardSecurityContainerController.onViewAttached();
|
mKeyguardSecurityContainerController.onViewAttached();
|
||||||
verify(mConfigurationController).addCallback(configurationListenerArgumentCaptor.capture());
|
verify(mConfigurationController).addCallback(configurationListenerArgumentCaptor.capture());
|
||||||
|
clearInvocations(mKeyguardSecurityViewFlipperController);
|
||||||
|
|
||||||
configurationListenerArgumentCaptor.getValue().onThemeChanged();
|
configurationListenerArgumentCaptor.getValue().onThemeChanged();
|
||||||
|
|
||||||
verify(mView).reloadColors();
|
verify(mView).reloadColors();
|
||||||
verify(mKeyguardSecurityViewFlipperController).clearViews();
|
verify(mKeyguardSecurityViewFlipperController).clearViews();
|
||||||
verify(mKeyguardSecurityViewFlipperController).getSecurityView(any(SecurityMode.class),
|
verify(mKeyguardSecurityViewFlipperController).getSecurityView(eq(SecurityMode.PIN),
|
||||||
any(KeyguardSecurityCallback.class));
|
any(KeyguardSecurityCallback.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -592,14 +621,90 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase {
|
|||||||
ConfigurationController.ConfigurationListener.class);
|
ConfigurationController.ConfigurationListener.class);
|
||||||
mKeyguardSecurityContainerController.onViewAttached();
|
mKeyguardSecurityContainerController.onViewAttached();
|
||||||
verify(mConfigurationController).addCallback(configurationListenerArgumentCaptor.capture());
|
verify(mConfigurationController).addCallback(configurationListenerArgumentCaptor.capture());
|
||||||
|
clearInvocations(mKeyguardSecurityViewFlipperController);
|
||||||
|
|
||||||
configurationListenerArgumentCaptor.getValue().onUiModeChanged();
|
configurationListenerArgumentCaptor.getValue().onUiModeChanged();
|
||||||
|
|
||||||
verify(mView).reloadColors();
|
verify(mView).reloadColors();
|
||||||
verify(mKeyguardSecurityViewFlipperController).clearViews();
|
verify(mKeyguardSecurityViewFlipperController).clearViews();
|
||||||
verify(mKeyguardSecurityViewFlipperController).getSecurityView(any(SecurityMode.class),
|
verify(mKeyguardSecurityViewFlipperController).getSecurityView(eq(SecurityMode.PIN),
|
||||||
any(KeyguardSecurityCallback.class));
|
any(KeyguardSecurityCallback.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testHasDismissActions() {
|
||||||
|
assertFalse("Action not set yet", mKeyguardSecurityContainerController.hasDismissActions());
|
||||||
|
mKeyguardSecurityContainerController.setOnDismissAction(mock(
|
||||||
|
ActivityStarter.OnDismissAction.class),
|
||||||
|
null /* cancelAction */);
|
||||||
|
assertTrue("Action should exist", mKeyguardSecurityContainerController.hasDismissActions());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testOnStartingToHide() {
|
||||||
|
mKeyguardSecurityContainerController.onStartingToHide();
|
||||||
|
verify(mInputViewController).onStartingToHide();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGravityReappliedOnConfigurationChange() {
|
||||||
|
// Set initial gravity
|
||||||
|
mTestableResources.addOverride(R.integer.keyguard_host_view_gravity,
|
||||||
|
Gravity.CENTER);
|
||||||
|
|
||||||
|
// Kick off the initial pass...
|
||||||
|
mKeyguardSecurityContainerController.onInit();
|
||||||
|
verify(mView).setLayoutParams(argThat(
|
||||||
|
(ArgumentMatcher<FrameLayout.LayoutParams>) argument ->
|
||||||
|
argument.gravity == Gravity.CENTER));
|
||||||
|
clearInvocations(mView);
|
||||||
|
|
||||||
|
// Now simulate a config change
|
||||||
|
mTestableResources.addOverride(R.integer.keyguard_host_view_gravity,
|
||||||
|
Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM);
|
||||||
|
|
||||||
|
mKeyguardSecurityContainerController.updateResources();
|
||||||
|
verify(mView).setLayoutParams(argThat(
|
||||||
|
(ArgumentMatcher<FrameLayout.LayoutParams>) argument ->
|
||||||
|
argument.gravity == (Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGravityUsesOneHandGravityWhenApplicable() {
|
||||||
|
mTestableResources.addOverride(
|
||||||
|
R.integer.keyguard_host_view_gravity,
|
||||||
|
Gravity.CENTER);
|
||||||
|
mTestableResources.addOverride(
|
||||||
|
R.integer.keyguard_host_view_one_handed_gravity,
|
||||||
|
Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM);
|
||||||
|
|
||||||
|
// Start disabled.
|
||||||
|
mTestableResources.addOverride(
|
||||||
|
R.bool.can_use_one_handed_bouncer, false);
|
||||||
|
|
||||||
|
mKeyguardSecurityContainerController.onInit();
|
||||||
|
verify(mView).setLayoutParams(argThat(
|
||||||
|
(ArgumentMatcher<FrameLayout.LayoutParams>) argument ->
|
||||||
|
argument.gravity == Gravity.CENTER));
|
||||||
|
clearInvocations(mView);
|
||||||
|
|
||||||
|
// And enable
|
||||||
|
mTestableResources.addOverride(
|
||||||
|
R.bool.can_use_one_handed_bouncer, true);
|
||||||
|
|
||||||
|
mKeyguardSecurityContainerController.updateResources();
|
||||||
|
verify(mView).setLayoutParams(argThat(
|
||||||
|
(ArgumentMatcher<FrameLayout.LayoutParams>) argument ->
|
||||||
|
argument.gravity == (Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUpdateKeyguardPositionDelegatesToSecurityContainer() {
|
||||||
|
mKeyguardSecurityContainerController.updateKeyguardPosition(1.0f);
|
||||||
|
verify(mView).updatePositionByTouchX(1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private KeyguardSecurityContainer.SwipeListener getRegisteredSwipeListener() {
|
private KeyguardSecurityContainer.SwipeListener getRegisteredSwipeListener() {
|
||||||
mKeyguardSecurityContainerController.onViewAttached();
|
mKeyguardSecurityContainerController.onViewAttached();
|
||||||
verify(mView).setSwipeListener(mSwipeListenerArgumentCaptor.capture());
|
verify(mView).setSwipeListener(mSwipeListenerArgumentCaptor.capture());
|
||||||
@@ -625,7 +730,7 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void setSideFpsHintEnabledFromResources(boolean enabled) {
|
private void setSideFpsHintEnabledFromResources(boolean enabled) {
|
||||||
when(mResources.getBoolean(R.bool.config_show_sidefps_hint_on_bouncer)).thenReturn(
|
mTestableResources.addOverride(R.bool.config_show_sidefps_hint_on_bouncer,
|
||||||
enabled);
|
enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ import android.testing.TestableLooper.RunWithLooper
|
|||||||
import android.view.MotionEvent
|
import android.view.MotionEvent
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.test.filters.SmallTest
|
import androidx.test.filters.SmallTest
|
||||||
import com.android.keyguard.KeyguardHostViewController
|
import com.android.keyguard.KeyguardSecurityContainerController
|
||||||
import com.android.keyguard.LockIconViewController
|
import com.android.keyguard.LockIconViewController
|
||||||
import com.android.keyguard.dagger.KeyguardBouncerComponent
|
import com.android.keyguard.dagger.KeyguardBouncerComponent
|
||||||
import com.android.systemui.R
|
import com.android.systemui.R
|
||||||
@@ -106,7 +106,7 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() {
|
|||||||
private lateinit var alternateBouncerInteractor: AlternateBouncerInteractor
|
private lateinit var alternateBouncerInteractor: AlternateBouncerInteractor
|
||||||
@Mock lateinit var keyguardBouncerComponentFactory: KeyguardBouncerComponent.Factory
|
@Mock lateinit var keyguardBouncerComponentFactory: KeyguardBouncerComponent.Factory
|
||||||
@Mock lateinit var keyguardBouncerComponent: KeyguardBouncerComponent
|
@Mock lateinit var keyguardBouncerComponent: KeyguardBouncerComponent
|
||||||
@Mock lateinit var keyguardHostViewController: KeyguardHostViewController
|
@Mock lateinit var keyguardSecurityContainerController: KeyguardSecurityContainerController
|
||||||
@Mock lateinit var keyguardTransitionInteractor: KeyguardTransitionInteractor
|
@Mock lateinit var keyguardTransitionInteractor: KeyguardTransitionInteractor
|
||||||
|
|
||||||
private lateinit var interactionEventHandlerCaptor: ArgumentCaptor<InteractionEventHandler>
|
private lateinit var interactionEventHandlerCaptor: ArgumentCaptor<InteractionEventHandler>
|
||||||
@@ -122,8 +122,8 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() {
|
|||||||
.thenReturn(mock(ViewGroup::class.java))
|
.thenReturn(mock(ViewGroup::class.java))
|
||||||
whenever(keyguardBouncerComponentFactory.create(any(ViewGroup::class.java)))
|
whenever(keyguardBouncerComponentFactory.create(any(ViewGroup::class.java)))
|
||||||
.thenReturn(keyguardBouncerComponent)
|
.thenReturn(keyguardBouncerComponent)
|
||||||
whenever(keyguardBouncerComponent.keyguardHostViewController)
|
whenever(keyguardBouncerComponent.securityContainerController)
|
||||||
.thenReturn(keyguardHostViewController)
|
.thenReturn(keyguardSecurityContainerController)
|
||||||
underTest = NotificationShadeWindowViewController(
|
underTest = NotificationShadeWindowViewController(
|
||||||
lockscreenShadeTransitionController,
|
lockscreenShadeTransitionController,
|
||||||
FalsingCollectorFake(),
|
FalsingCollectorFake(),
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ import android.view.ViewGroup;
|
|||||||
|
|
||||||
import androidx.test.filters.SmallTest;
|
import androidx.test.filters.SmallTest;
|
||||||
|
|
||||||
import com.android.keyguard.KeyguardHostViewController;
|
import com.android.keyguard.KeyguardSecurityContainerController;
|
||||||
import com.android.keyguard.LockIconViewController;
|
import com.android.keyguard.LockIconViewController;
|
||||||
import com.android.keyguard.dagger.KeyguardBouncerComponent;
|
import com.android.keyguard.dagger.KeyguardBouncerComponent;
|
||||||
import com.android.systemui.R;
|
import com.android.systemui.R;
|
||||||
@@ -97,7 +97,7 @@ public class NotificationShadeWindowViewTest extends SysuiTestCase {
|
|||||||
@Mock private KeyguardBouncerViewModel mKeyguardBouncerViewModel;
|
@Mock private KeyguardBouncerViewModel mKeyguardBouncerViewModel;
|
||||||
@Mock private KeyguardBouncerComponent.Factory mKeyguardBouncerComponentFactory;
|
@Mock private KeyguardBouncerComponent.Factory mKeyguardBouncerComponentFactory;
|
||||||
@Mock private KeyguardBouncerComponent mKeyguardBouncerComponent;
|
@Mock private KeyguardBouncerComponent mKeyguardBouncerComponent;
|
||||||
@Mock private KeyguardHostViewController mKeyguardHostViewController;
|
@Mock private KeyguardSecurityContainerController mKeyguardSecurityContainerController;
|
||||||
@Mock private NotificationInsetsController mNotificationInsetsController;
|
@Mock private NotificationInsetsController mNotificationInsetsController;
|
||||||
@Mock private AlternateBouncerInteractor mAlternateBouncerInteractor;
|
@Mock private AlternateBouncerInteractor mAlternateBouncerInteractor;
|
||||||
@Mock private KeyguardTransitionInteractor mKeyguardTransitionInteractor;
|
@Mock private KeyguardTransitionInteractor mKeyguardTransitionInteractor;
|
||||||
@@ -117,8 +117,8 @@ public class NotificationShadeWindowViewTest extends SysuiTestCase {
|
|||||||
when(mView.findViewById(R.id.keyguard_bouncer_container)).thenReturn(mock(ViewGroup.class));
|
when(mView.findViewById(R.id.keyguard_bouncer_container)).thenReturn(mock(ViewGroup.class));
|
||||||
when(mKeyguardBouncerComponentFactory.create(any(ViewGroup.class))).thenReturn(
|
when(mKeyguardBouncerComponentFactory.create(any(ViewGroup.class))).thenReturn(
|
||||||
mKeyguardBouncerComponent);
|
mKeyguardBouncerComponent);
|
||||||
when(mKeyguardBouncerComponent.getKeyguardHostViewController()).thenReturn(
|
when(mKeyguardBouncerComponent.getSecurityContainerController()).thenReturn(
|
||||||
mKeyguardHostViewController);
|
mKeyguardSecurityContainerController);
|
||||||
|
|
||||||
when(mStatusBarStateController.isDozing()).thenReturn(false);
|
when(mStatusBarStateController.isDozing()).thenReturn(false);
|
||||||
mDependency.injectTestDependency(ShadeController.class, mShadeController);
|
mDependency.injectTestDependency(ShadeController.class, mShadeController);
|
||||||
|
|||||||
Reference in New Issue
Block a user