Add tap target for when udfps is unavailable

tapping on the target will bring up the bouncer since UDFPS is
unavailable

Test: manual
Bug: 172050991
Change-Id: I8fafa2da174aec905ae0d9c4c19aff8907a4c67e
This commit is contained in:
Beverly
2020-11-23 16:07:25 -05:00
parent 2388cd528c
commit c0d931d3da
8 changed files with 332 additions and 3 deletions

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 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.
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="#33FFFFFF" />
</shape>

View File

@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ 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.
-->
<com.android.keyguard.DisabledUdfpsView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:systemui="http://schemas.android.com/apk/res-auto"
android:id="@+id/disabled_udfps_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/circle_white"
/>

View File

@@ -1,4 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ 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.
-->
<com.android.systemui.biometrics.UdfpsView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:systemui="http://schemas.android.com/apk/res-auto"

View File

@@ -0,0 +1,155 @@
/*
* 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 static android.hardware.biometrics.BiometricSourceType.FINGERPRINT;
import android.hardware.biometrics.BiometricSourceType;
import android.view.View;
import androidx.annotation.NonNull;
import com.android.systemui.Dumpable;
import com.android.systemui.biometrics.AuthController;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.util.ViewController;
import java.io.FileDescriptor;
import java.io.PrintWriter;
/**
* Controls when to show the DisabledUdfpsView to unlock the device on the lockscreen.
* If the device is not authenticated, the bouncer will show.
*
* This tap target will only show when:
* - User has UDFPS enrolled
* - UDFPS is currently unavailable see {@link KeyguardUpdateMonitor#shouldListenForUdfps}
*/
@SysUISingleton
public class DisabledUdfpsController extends ViewController<DisabledUdfpsView> implements Dumpable {
@NonNull private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
@NonNull private final KeyguardViewController mKeyguardViewController;
@NonNull private final StatusBarStateController mStatusBarStateController;
private boolean mIsDozing;
private boolean mIsBouncerShowing;
private boolean mIsKeyguardShowing;
private boolean mRunningFPS;
private boolean mAuthenticated;
private boolean mShowButton;
public DisabledUdfpsController(
@NonNull DisabledUdfpsView view,
@NonNull StatusBarStateController statusBarStateController,
@NonNull KeyguardUpdateMonitor keyguardUpdateMonitor,
@NonNull AuthController authController,
@NonNull KeyguardViewController keyguardViewController
) {
super(view);
mView.setOnClickListener(mOnClickListener);
mView.setSensorProperties(authController.getUdfpsProps().get(0));
mStatusBarStateController = statusBarStateController;
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
mKeyguardViewController = keyguardViewController;
}
@Override
protected void onViewAttached() {
mKeyguardUpdateMonitor.registerCallback(mKeyguardUpdateMonitorCallback);
mIsBouncerShowing = mKeyguardViewController.isBouncerShowing();
mStatusBarStateController.addCallback(mStatusBarStateListener);
mIsKeyguardShowing = mStatusBarStateController.getState() == StatusBarState.KEYGUARD;
mIsDozing = mStatusBarStateController.isDozing();
mAuthenticated = false;
}
@Override
protected void onViewDetached() {
mKeyguardUpdateMonitor.removeCallback(mKeyguardUpdateMonitorCallback);
mStatusBarStateController.removeCallback(mStatusBarStateListener);
}
private void updateButtonVisibility() {
mShowButton = !mAuthenticated && !mIsDozing && mIsKeyguardShowing
&& !mIsBouncerShowing && !mRunningFPS;
if (mShowButton) {
mView.setVisibility(View.VISIBLE);
} else {
mView.setVisibility(View.INVISIBLE);
}
}
@Override
public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String[] args) {
pw.println("DisabledUdfpsController state:");
pw.println(" mShowBouncerButton: " + mShowButton);
pw.println(" mIsDozing: " + mIsDozing);
pw.println(" mIsKeyguardShowing: " + mIsKeyguardShowing);
pw.println(" mIsBouncerShowing: " + mIsBouncerShowing);
pw.println(" mRunningFPS: " + mRunningFPS);
pw.println(" mAuthenticated: " + mAuthenticated);
}
private final View.OnClickListener mOnClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
mKeyguardViewController.showBouncer(/* scrim */ true);
}
};
private StatusBarStateController.StateListener mStatusBarStateListener =
new StatusBarStateController.StateListener() {
@Override
public void onStateChanged(int newState) {
mIsKeyguardShowing = newState == StatusBarState.KEYGUARD;
updateButtonVisibility();
}
@Override
public void onDozingChanged(boolean isDozing) {
mIsDozing = isDozing;
updateButtonVisibility();
}
};
private final KeyguardUpdateMonitorCallback mKeyguardUpdateMonitorCallback =
new KeyguardUpdateMonitorCallback() {
@Override
public void onKeyguardBouncerChanged(boolean bouncer) {
mIsBouncerShowing = bouncer;
updateButtonVisibility();
}
@Override
public void onBiometricRunningStateChanged(boolean running,
BiometricSourceType biometricSourceType) {
mRunningFPS = running && biometricSourceType == FINGERPRINT;
updateButtonVisibility();
}
@Override
public void onUserUnlocked() {
mAuthenticated = true;
updateButtonVisibility();
}
};
}

View File

@@ -0,0 +1,89 @@
/*
* 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.annotation.NonNull;
import android.content.Context;
import android.graphics.RectF;
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
import android.util.AttributeSet;
import android.view.Surface;
import android.widget.Button;
import android.widget.FrameLayout;
/**
* A full screen view with an oval target where the UDFPS sensor is.
* Controlled by {@link DisabledUdfpsController}.
*/
public class DisabledUdfpsView extends Button {
@NonNull private final RectF mSensorRect;
@NonNull private final Context mContext;
// Used to obtain the sensor location.
@NonNull private FingerprintSensorPropertiesInternal mSensorProps;
public DisabledUdfpsView(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
mSensorRect = new RectF();
}
public void setSensorProperties(@NonNull FingerprintSensorPropertiesInternal properties) {
mSensorProps = properties;
}
// The "h" and "w" are the display's height and width relative to its current rotation.
private void updateSensorRect(int h, int w) {
// mSensorProps coordinates assume portrait mode.
mSensorRect.set(mSensorProps.sensorLocationX - mSensorProps.sensorRadius,
mSensorProps.sensorLocationY - mSensorProps.sensorRadius,
mSensorProps.sensorLocationX + mSensorProps.sensorRadius,
mSensorProps.sensorLocationY + mSensorProps.sensorRadius);
// Transform mSensorRect if the device is in landscape mode.
switch (mContext.getDisplay().getRotation()) {
case Surface.ROTATION_90:
mSensorRect.set(mSensorRect.top, h - mSensorRect.right, mSensorRect.bottom,
h - mSensorRect.left);
break;
case Surface.ROTATION_270:
mSensorRect.set(w - mSensorRect.bottom, mSensorRect.left, w - mSensorRect.top,
mSensorRect.right);
break;
default:
// Do nothing to stay in portrait mode.
}
setX(mSensorRect.left);
setY(mSensorRect.top);
setLayoutParams(new FrameLayout.LayoutParams(
(int) (mSensorRect.right - mSensorRect.left),
(int) (mSensorRect.bottom - mSensorRect.top)));
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
// Always re-compute the layout regardless of whether "changed" is true. It is usually false
// when the device goes from landscape to seascape and vice versa, but mSensorRect and
// its dependencies need to be recalculated to stay at the same physical location on the
// screen.
final int w = getLayoutParams().width;
final int h = getLayoutParams().height;
updateSensorRect(h, w);
}
}

View File

@@ -1925,6 +1925,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
}
// TODO: Add support for multiple fingerprint sensors, b/173730729
updateUdfpsEnrolled(getCurrentUser());
boolean shouldListenForFingerprint =
isUdfpsEnrolled() ? shouldListenForUdfps() : shouldListenForFingerprint();
boolean runningOrRestarting = mFingerprintRunningState == BIOMETRIC_STATE_RUNNING
@@ -2137,7 +2138,6 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
}
if (DEBUG) Log.v(TAG, "startListeningForFingerprint()");
int userId = getCurrentUser();
updateUdfpsEnrolled(userId);
if (isUnlockWithFingerprintPossible(userId)) {
if (mFingerprintCancelSignal != null) {
mFingerprintCancelSignal.cancel();
@@ -2627,7 +2627,6 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
Assert.isMainThread();
if (DEBUG) Log.d(TAG, "handleKeyguardBouncerChanged(" + bouncerVisible + ")");
mBouncer = bouncerVisible == 1;
if (mBouncer) {
// If the bouncer is shown, always clear this flag. This can happen in the following
// situations: 1) Default camera with SHOW_WHEN_LOCKED is not chosen yet. 2) Secure

View File

@@ -413,6 +413,11 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
mCurrentDialog.onHelp(message);
}
@Nullable
public List<FingerprintSensorPropertiesInternal> getUdfpsProps() {
return mUdfpsProps;
}
private String getErrorString(int modality, int error, int vendorCode) {
switch (modality) {
case TYPE_FACE:

View File

@@ -68,6 +68,7 @@ import com.android.internal.jank.InteractionJankMonitor;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.util.LatencyTracker;
import com.android.keyguard.DisabledUdfpsController;
import com.android.keyguard.KeyguardClockSwitchController;
import com.android.keyguard.KeyguardStatusView;
import com.android.keyguard.KeyguardStatusViewController;
@@ -255,7 +256,25 @@ public class NotificationPanelViewController extends PanelViewController {
mFirstBypassAttempt = mKeyguardBypassController.getBypassEnabled();
mDelayShowingKeyguardStatusBar = false;
}
};
@Override
public void onKeyguardVisibilityChanged(boolean showing) {
if (mDisabledUdfpsController == null
&& mAuthController.getUdfpsRegion() != null
&& mAuthController.isUdfpsEnrolled(
KeyguardUpdateMonitor.getCurrentUser())) {
LayoutInflater.from(mView.getContext())
.inflate(R.layout.disabled_udfps_view, mView);
mDisabledUdfpsController = new DisabledUdfpsController(
mView.findViewById(R.id.disabled_udfps_view),
mStatusBarStateController,
mUpdateMonitor,
mAuthController,
mStatusBarKeyguardViewManager);
mDisabledUdfpsController.init();
}
}
};
private final InjectionInflationController mInjectionInflationController;
private final PowerManager mPowerManager;
@@ -283,6 +302,7 @@ public class NotificationPanelViewController extends PanelViewController {
private QS mQs;
private FrameLayout mQsFrame;
private KeyguardStatusViewController mKeyguardStatusViewController;
private DisabledUdfpsController mDisabledUdfpsController;
private View mQsNavbarScrim;
private NotificationsQuickSettingsContainer mNotificationContainerParent;
private boolean mAnimateNextPositionUpdate;
@@ -3041,6 +3061,9 @@ public class NotificationPanelViewController extends PanelViewController {
if (mKeyguardStatusBar != null) {
mKeyguardStatusBar.dump(fd, pw, args);
}
if (mDisabledUdfpsController != null) {
mDisabledUdfpsController.dump(fd, pw, args);
}
}
public boolean hasActiveClearableNotifications() {