Merge "Pass detailed reason to UdfpsView, split animation logic"
This commit is contained in:
@@ -22,7 +22,9 @@ package android.hardware.fingerprint;
|
||||
oneway interface IUdfpsOverlayController {
|
||||
const int REASON_UNKNOWN = 0;
|
||||
const int REASON_ENROLL = 1;
|
||||
const int REASON_AUTH = 2;
|
||||
const int REASON_AUTH_BP = 2; // BiometricPrompt
|
||||
const int REASON_AUTH_FPM_KEYGUARD = 3; // FingerprintManager usage from Keyguard
|
||||
const int REASON_AUTH_FPM_OTHER = 4; // Other FingerprintManager usage
|
||||
|
||||
// Shows the overlay.
|
||||
void showUdfpsOverlay(int sensorId, int reason);
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.systemui.biometrics;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.drawable.Drawable;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.android.systemui.R;
|
||||
|
||||
/**
|
||||
* Abstract base class for animations that should be drawn when the finger is not touching the
|
||||
* sensor area.
|
||||
*/
|
||||
public abstract class UdfpsAnimation extends Drawable {
|
||||
abstract void updateColor();
|
||||
|
||||
@NonNull protected final Context mContext;
|
||||
@NonNull protected final Drawable mFingerprintDrawable;
|
||||
|
||||
public UdfpsAnimation(@NonNull Context context) {
|
||||
mContext = context;
|
||||
mFingerprintDrawable = context.getResources().getDrawable(R.drawable.ic_fingerprint, null);
|
||||
}
|
||||
|
||||
public void onSensorRectUpdated(@NonNull RectF sensorRect) {
|
||||
int margin = (int) (sensorRect.bottom - sensorRect.top) / 5;
|
||||
mFingerprintDrawable.setBounds(
|
||||
(int) sensorRect.left + margin,
|
||||
(int) sensorRect.top + margin,
|
||||
(int) sensorRect.right - margin,
|
||||
(int) sensorRect.bottom - margin);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.systemui.biometrics;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.ColorFilter;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.RectF;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.systemui.R;
|
||||
|
||||
/**
|
||||
* UDFPS animations that should be shown when enrolling.
|
||||
*/
|
||||
public class UdfpsAnimationEnroll extends UdfpsAnimation {
|
||||
private static final String TAG = "UdfpsAnimationEnroll";
|
||||
|
||||
@Nullable private RectF mSensorRect;
|
||||
@NonNull private final Paint mSensorPaint;
|
||||
|
||||
UdfpsAnimationEnroll(@NonNull Context context) {
|
||||
super(context);
|
||||
|
||||
mSensorPaint = new Paint(0 /* flags */);
|
||||
mSensorPaint.setAntiAlias(true);
|
||||
mSensorPaint.setColor(Color.WHITE);
|
||||
mSensorPaint.setShadowLayer(UdfpsView.SENSOR_SHADOW_RADIUS, 0, 0, Color.BLACK);
|
||||
mSensorPaint.setStyle(Paint.Style.FILL);
|
||||
}
|
||||
|
||||
@Override
|
||||
void updateColor() {
|
||||
mFingerprintDrawable.setTint(mContext.getColor(R.color.udfps_enroll_icon));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSensorRectUpdated(@NonNull RectF sensorRect) {
|
||||
super.onSensorRectUpdated(sensorRect);
|
||||
mSensorRect = sensorRect;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(@NonNull Canvas canvas) {
|
||||
final boolean isNightMode = (mContext.getResources().getConfiguration().uiMode
|
||||
& Configuration.UI_MODE_NIGHT_YES) != 0;
|
||||
if (!isNightMode) {
|
||||
if (mSensorRect != null) {
|
||||
canvas.drawOval(mSensorRect, mSensorPaint);
|
||||
}
|
||||
}
|
||||
mFingerprintDrawable.draw(canvas);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAlpha(int alpha) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setColorFilter(@Nullable ColorFilter colorFilter) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOpacity() {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.systemui.biometrics;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.ColorFilter;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* UDFPS animations that should be shown when authenticating via FingerprintManager, excluding
|
||||
* keyguard.
|
||||
*/
|
||||
public class UdfpsAnimationFpmOther extends UdfpsAnimation {
|
||||
|
||||
UdfpsAnimationFpmOther(@NonNull Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
void updateColor() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(@NonNull Canvas canvas) {
|
||||
mFingerprintDrawable.draw(canvas);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAlpha(int alpha) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setColorFilter(@Nullable ColorFilter colorFilter) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOpacity() {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.systemui.biometrics;
|
||||
|
||||
import static com.android.systemui.doze.util.BurnInHelperKt.getBurnInOffset;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.ColorFilter;
|
||||
import android.util.MathUtils;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.internal.graphics.ColorUtils;
|
||||
import com.android.settingslib.Utils;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.doze.DozeReceiver;
|
||||
import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
||||
|
||||
/**
|
||||
* UDFPS animations that should be shown when authenticating on keyguard.
|
||||
*/
|
||||
public class UdfpsAnimationKeyguard extends UdfpsAnimation implements DozeReceiver,
|
||||
StatusBarStateController.StateListener {
|
||||
|
||||
private static final String TAG = "UdfpsAnimationKeyguard";
|
||||
|
||||
@NonNull private final View mParent;
|
||||
@NonNull private final Context mContext;
|
||||
private final int mMaxBurnInOffsetX;
|
||||
private final int mMaxBurnInOffsetY;
|
||||
|
||||
// AOD anti-burn-in offsets
|
||||
private float mInterpolatedDarkAmount;
|
||||
private float mBurnInOffsetX;
|
||||
private float mBurnInOffsetY;
|
||||
|
||||
UdfpsAnimationKeyguard(@NonNull View parent, @NonNull Context context,
|
||||
@NonNull StatusBarStateController statusBarStateController) {
|
||||
super(context);
|
||||
mParent = parent;
|
||||
mContext = context;
|
||||
|
||||
mMaxBurnInOffsetX = context.getResources()
|
||||
.getDimensionPixelSize(R.dimen.udfps_burn_in_offset_x);
|
||||
mMaxBurnInOffsetY = context.getResources()
|
||||
.getDimensionPixelSize(R.dimen.udfps_burn_in_offset_y);
|
||||
|
||||
statusBarStateController.addCallback(this);
|
||||
}
|
||||
|
||||
private void updateAodPositionAndColor() {
|
||||
mBurnInOffsetX = MathUtils.lerp(0f,
|
||||
getBurnInOffset(mMaxBurnInOffsetX * 2, true /* xAxis */)
|
||||
- mMaxBurnInOffsetX,
|
||||
mInterpolatedDarkAmount);
|
||||
mBurnInOffsetY = MathUtils.lerp(0f,
|
||||
getBurnInOffset(mMaxBurnInOffsetY * 2, false /* xAxis */)
|
||||
- 0.5f * mMaxBurnInOffsetY,
|
||||
mInterpolatedDarkAmount);
|
||||
updateColor();
|
||||
mParent.postInvalidate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dozeTimeTick() {
|
||||
updateAodPositionAndColor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDozeAmountChanged(float linear, float eased) {
|
||||
mInterpolatedDarkAmount = eased;
|
||||
updateAodPositionAndColor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(@NonNull Canvas canvas) {
|
||||
canvas.save();
|
||||
canvas.translate(mBurnInOffsetX, mBurnInOffsetY);
|
||||
mFingerprintDrawable.draw(canvas);
|
||||
canvas.restore();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAlpha(int alpha) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setColorFilter(@Nullable ColorFilter colorFilter) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOpacity() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateColor() {
|
||||
final int lockScreenIconColor = Utils.getColorAttrDefaultColor(mContext,
|
||||
R.attr.wallpaperTextColor);
|
||||
final int ambientDisplayIconColor = Color.WHITE;
|
||||
mFingerprintDrawable.setTint(ColorUtils.blendARGB(lockScreenIconColor,
|
||||
ambientDisplayIconColor, mInterpolatedDarkAmount));
|
||||
}
|
||||
}
|
||||
@@ -81,6 +81,7 @@ class UdfpsController implements DozeReceiver {
|
||||
private final WindowManager mWindowManager;
|
||||
private final SystemSettings mSystemSettings;
|
||||
private final DelayableExecutor mFgExecutor;
|
||||
private final StatusBarStateController mStatusBarStateController;
|
||||
// Currently the UdfpsController supports a single UDFPS sensor. If devices have multiple
|
||||
// sensors, this, in addition to a lot of the code here, will be updated.
|
||||
@VisibleForTesting final FingerprintSensorPropertiesInternal mSensorProps;
|
||||
@@ -181,6 +182,7 @@ class UdfpsController implements DozeReceiver {
|
||||
mWindowManager = windowManager;
|
||||
mSystemSettings = systemSettings;
|
||||
mFgExecutor = fgExecutor;
|
||||
mStatusBarStateController = statusBarStateController;
|
||||
|
||||
mSensorProps = findFirstUdfps();
|
||||
// At least one UDFPS sensor exists
|
||||
@@ -208,7 +210,6 @@ class UdfpsController implements DozeReceiver {
|
||||
|
||||
mHbmSupported = !TextUtils.isEmpty(mHbmPath);
|
||||
mView.setHbmSupported(mHbmSupported);
|
||||
statusBarStateController.addCallback(mView);
|
||||
|
||||
// This range only consists of the minimum and maximum values, which only cover
|
||||
// non-high-brightness mode.
|
||||
@@ -340,7 +341,7 @@ class UdfpsController implements DozeReceiver {
|
||||
if (!mIsOverlayShowing) {
|
||||
try {
|
||||
Log.v(TAG, "showUdfpsOverlay | adding window");
|
||||
mView.setShowReason(reason);
|
||||
mView.setUdfpsAnimation(getUdfpsAnimationForReason(reason));
|
||||
mWindowManager.addView(mView, computeLayoutParams());
|
||||
mView.setOnTouchListener(mOnTouchListener);
|
||||
mIsOverlayShowing = true;
|
||||
@@ -353,11 +354,27 @@ class UdfpsController implements DozeReceiver {
|
||||
});
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private UdfpsAnimation getUdfpsAnimationForReason(int reason) {
|
||||
Log.d(TAG, "getUdfpsAnimationForReason: " + reason);
|
||||
switch (reason) {
|
||||
case IUdfpsOverlayController.REASON_ENROLL:
|
||||
return new UdfpsAnimationEnroll(mContext);
|
||||
case IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD:
|
||||
return new UdfpsAnimationKeyguard(mView, mContext, mStatusBarStateController);
|
||||
case IUdfpsOverlayController.REASON_AUTH_FPM_OTHER:
|
||||
return new UdfpsAnimationFpmOther(mContext);
|
||||
default:
|
||||
Log.d(TAG, "Animation for reason " + reason + " not supported yet");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private void hideUdfpsOverlay() {
|
||||
mFgExecutor.execute(() -> {
|
||||
if (mIsOverlayShowing) {
|
||||
Log.v(TAG, "hideUdfpsOverlay | removing window");
|
||||
mView.setShowReason(IUdfpsOverlayController.REASON_UNKNOWN);
|
||||
mView.setUdfpsAnimation(null);
|
||||
mView.setOnTouchListener(null);
|
||||
// Reset the controller back to its starting state.
|
||||
onFingerUp();
|
||||
|
||||
@@ -16,45 +16,34 @@
|
||||
|
||||
package com.android.systemui.biometrics;
|
||||
|
||||
import static com.android.systemui.doze.util.BurnInHelperKt.getBurnInOffset;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
|
||||
import android.hardware.fingerprint.IUdfpsOverlayController;
|
||||
import android.text.TextUtils;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.util.MathUtils;
|
||||
import android.view.Surface;
|
||||
import android.view.View;
|
||||
import android.view.ViewTreeObserver;
|
||||
|
||||
import com.android.internal.graphics.ColorUtils;
|
||||
import com.android.settingslib.Utils;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.doze.DozeReceiver;
|
||||
import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
||||
|
||||
/**
|
||||
* A full screen view with a configurable illumination dot and scrim.
|
||||
*/
|
||||
public class UdfpsView extends View implements DozeReceiver,
|
||||
StatusBarStateController.StateListener {
|
||||
public class UdfpsView extends View implements DozeReceiver {
|
||||
private static final String TAG = "UdfpsView";
|
||||
|
||||
// Values in pixels.
|
||||
private static final float SENSOR_SHADOW_RADIUS = 2.0f;
|
||||
private static final float SENSOR_OUTLINE_WIDTH = 2.0f;
|
||||
public static final float SENSOR_SHADOW_RADIUS = 2.0f;
|
||||
|
||||
private static final int DEBUG_TEXT_SIZE_PX = 32;
|
||||
|
||||
@@ -65,8 +54,7 @@ public class UdfpsView extends View implements DozeReceiver,
|
||||
@NonNull private final RectF mSensorRect;
|
||||
@NonNull private final Paint mSensorPaint;
|
||||
private final float mSensorTouchAreaCoefficient;
|
||||
private final int mMaxBurnInOffsetX;
|
||||
private final int mMaxBurnInOffsetY;
|
||||
|
||||
|
||||
// Stores rounded up values from mSensorRect. Necessary for APIs that only take Rect (not RecF).
|
||||
@NonNull private final Rect mTouchableRegion;
|
||||
@@ -75,17 +63,11 @@ public class UdfpsView extends View implements DozeReceiver,
|
||||
// mInsetsListener to restrict the touchable region and allow the touches outside of the sensor
|
||||
// to propagate to the rest of the UI.
|
||||
@NonNull private final ViewTreeObserver.OnComputeInternalInsetsListener mInsetsListener;
|
||||
@NonNull private final Drawable mFingerprintDrawable;
|
||||
@Nullable private UdfpsAnimation mUdfpsAnimation;
|
||||
|
||||
// Used to obtain the sensor location.
|
||||
@NonNull private FingerprintSensorPropertiesInternal mSensorProps;
|
||||
|
||||
// AOD anti-burn-in offsets
|
||||
private float mInterpolatedDarkAmount;
|
||||
private float mBurnInOffsetX;
|
||||
private float mBurnInOffsetY;
|
||||
|
||||
private int mShowReason;
|
||||
private boolean mShowScrimAndDot;
|
||||
private boolean mIsHbmSupported;
|
||||
@Nullable private String mDebugMessage;
|
||||
@@ -110,10 +92,6 @@ public class UdfpsView extends View implements DozeReceiver,
|
||||
a.recycle();
|
||||
}
|
||||
|
||||
mMaxBurnInOffsetX = getResources()
|
||||
.getDimensionPixelSize(R.dimen.udfps_burn_in_offset_x);
|
||||
mMaxBurnInOffsetY = getResources()
|
||||
.getDimensionPixelSize(R.dimen.udfps_burn_in_offset_y);
|
||||
|
||||
mScrimRect = new Rect();
|
||||
mScrimPaint = new Paint(0 /* flags */);
|
||||
@@ -131,8 +109,6 @@ public class UdfpsView extends View implements DozeReceiver,
|
||||
mDebugTextPaint.setColor(Color.BLUE);
|
||||
mDebugTextPaint.setTextSize(DEBUG_TEXT_SIZE_PX);
|
||||
|
||||
mFingerprintDrawable = getResources().getDrawable(R.drawable.ic_fingerprint, null);
|
||||
|
||||
mTouchableRegion = new Rect();
|
||||
// When the device is rotated, it's important that mTouchableRegion is updated before
|
||||
// this listener is called. This listener is usually called shortly after onLayout.
|
||||
@@ -149,39 +125,20 @@ public class UdfpsView extends View implements DozeReceiver,
|
||||
mSensorProps = properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param reason See {@link android.hardware.fingerprint.IUdfpsOverlayController}
|
||||
*/
|
||||
void setShowReason(int reason) {
|
||||
mShowReason = reason;
|
||||
void setUdfpsAnimation(@Nullable UdfpsAnimation animation) {
|
||||
mUdfpsAnimation = animation;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void dozeTimeTick() {
|
||||
updateAodPositionAndColor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDozeAmountChanged(float linear, float eased) {
|
||||
mInterpolatedDarkAmount = eased;
|
||||
updateAodPositionAndColor();
|
||||
}
|
||||
|
||||
private void updateAodPositionAndColor() {
|
||||
mBurnInOffsetX = MathUtils.lerp(0f,
|
||||
getBurnInOffset(mMaxBurnInOffsetX * 2, true /* xAxis */)
|
||||
- mMaxBurnInOffsetX,
|
||||
mInterpolatedDarkAmount);
|
||||
mBurnInOffsetY = MathUtils.lerp(0f,
|
||||
getBurnInOffset(mMaxBurnInOffsetY * 2, false /* xAxis */)
|
||||
- 0.5f * mMaxBurnInOffsetY,
|
||||
mInterpolatedDarkAmount);
|
||||
updateColor();
|
||||
postInvalidate();
|
||||
if (mUdfpsAnimation instanceof DozeReceiver) {
|
||||
((DozeReceiver) mUdfpsAnimation).dozeTimeTick();
|
||||
}
|
||||
}
|
||||
|
||||
// The "h" and "w" are the display's height and width relative to its current rotation.
|
||||
private void updateSensorRect(int h, int w) {
|
||||
protected void updateSensorRect(int h, int w) {
|
||||
// mSensorProps coordinates assume portrait mode.
|
||||
mSensorRect.set(mSensorProps.sensorLocationX - mSensorProps.sensorRadius,
|
||||
mSensorProps.sensorLocationY - mSensorProps.sensorRadius,
|
||||
@@ -202,12 +159,9 @@ public class UdfpsView extends View implements DozeReceiver,
|
||||
// Do nothing to stay in portrait mode.
|
||||
}
|
||||
|
||||
int margin = (int) (mSensorRect.bottom - mSensorRect.top) / 5;
|
||||
mFingerprintDrawable.setBounds(
|
||||
(int) mSensorRect.left + margin,
|
||||
(int) mSensorRect.top + margin,
|
||||
(int) mSensorRect.right - margin,
|
||||
(int) mSensorRect.bottom - margin);
|
||||
if (mUdfpsAnimation != null) {
|
||||
mUdfpsAnimation.onSensorRectUpdated(new RectF(mSensorRect));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -239,14 +193,8 @@ public class UdfpsView extends View implements DozeReceiver,
|
||||
}
|
||||
|
||||
private void updateColor() {
|
||||
if (mShowReason == IUdfpsOverlayController.REASON_AUTH) {
|
||||
final int lockScreenIconColor = Utils.getColorAttrDefaultColor(mContext,
|
||||
com.android.systemui.R.attr.wallpaperTextColor);
|
||||
final int ambientDisplayIconColor = Color.WHITE;
|
||||
mFingerprintDrawable.setTint(ColorUtils.blendARGB(lockScreenIconColor,
|
||||
ambientDisplayIconColor, mInterpolatedDarkAmount));
|
||||
} else if (mShowReason == IUdfpsOverlayController.REASON_ENROLL) {
|
||||
mFingerprintDrawable.setTint(mContext.getColor(R.color.udfps_enroll_icon));
|
||||
if (mUdfpsAnimation != null) {
|
||||
mUdfpsAnimation.updateColor();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -266,9 +214,6 @@ public class UdfpsView extends View implements DozeReceiver,
|
||||
canvas.drawRect(mScrimRect, mScrimPaint);
|
||||
}
|
||||
|
||||
// Translation should affect everything but the scrim.
|
||||
canvas.save();
|
||||
canvas.translate(mBurnInOffsetX, mBurnInOffsetY);
|
||||
if (!TextUtils.isEmpty(mDebugMessage)) {
|
||||
canvas.drawText(mDebugMessage, 0, 160, mDebugTextPaint);
|
||||
}
|
||||
@@ -277,17 +222,11 @@ public class UdfpsView extends View implements DozeReceiver,
|
||||
// draw dot (white circle)
|
||||
canvas.drawOval(mSensorRect, mSensorPaint);
|
||||
} else {
|
||||
final boolean isNightMode = (getResources().getConfiguration().uiMode
|
||||
& Configuration.UI_MODE_NIGHT_YES) != 0;
|
||||
if (mShowReason == IUdfpsOverlayController.REASON_ENROLL && !isNightMode) {
|
||||
canvas.drawOval(mSensorRect, mSensorPaint);
|
||||
if (mUdfpsAnimation != null) {
|
||||
mUdfpsAnimation.draw(canvas);
|
||||
}
|
||||
// draw fingerprint icon
|
||||
mFingerprintDrawable.draw(canvas);
|
||||
}
|
||||
|
||||
canvas.restore();
|
||||
|
||||
if (mShowScrimAndDot && mRunAfterShowingScrimAndDot != null) {
|
||||
post(mRunAfterShowingScrimAndDot);
|
||||
mRunAfterShowingScrimAndDot = null;
|
||||
|
||||
@@ -162,7 +162,7 @@ public class UdfpsControllerTest extends SysuiTestCase {
|
||||
@Test
|
||||
public void showUdfpsOverlay_addsViewToWindow() throws RemoteException {
|
||||
mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID,
|
||||
IUdfpsOverlayController.REASON_AUTH);
|
||||
IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD);
|
||||
mFgExecutor.runAllReady();
|
||||
verify(mWindowManager).addView(eq(mUdfpsView), any());
|
||||
}
|
||||
@@ -170,7 +170,7 @@ public class UdfpsControllerTest extends SysuiTestCase {
|
||||
@Test
|
||||
public void hideUdfpsOverlay_removesViewFromWindow() throws RemoteException {
|
||||
mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID,
|
||||
IUdfpsOverlayController.REASON_AUTH);
|
||||
IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD);
|
||||
mOverlayController.hideUdfpsOverlay(TEST_UDFPS_SENSOR_ID);
|
||||
mFgExecutor.runAllReady();
|
||||
verify(mWindowManager).removeView(eq(mUdfpsView));
|
||||
@@ -184,7 +184,7 @@ public class UdfpsControllerTest extends SysuiTestCase {
|
||||
|
||||
// GIVEN that the overlay is showing
|
||||
mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID,
|
||||
IUdfpsOverlayController.REASON_AUTH);
|
||||
IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD);
|
||||
mFgExecutor.runAllReady();
|
||||
// WHEN ACTION_DOWN is received
|
||||
verify(mUdfpsView).setOnTouchListener(mTouchListenerCaptor.capture());
|
||||
@@ -205,7 +205,7 @@ public class UdfpsControllerTest extends SysuiTestCase {
|
||||
public void aodInterrupt() throws RemoteException {
|
||||
// GIVEN that the overlay is showing
|
||||
mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID,
|
||||
IUdfpsOverlayController.REASON_AUTH);
|
||||
IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD);
|
||||
mFgExecutor.runAllReady();
|
||||
// WHEN fingerprint is requested because of AOD interrupt
|
||||
mUdfpsController.onAodInterrupt(0, 0, 2f, 3f);
|
||||
@@ -223,7 +223,7 @@ public class UdfpsControllerTest extends SysuiTestCase {
|
||||
public void cancelAodInterrupt() throws RemoteException {
|
||||
// GIVEN AOD interrupt
|
||||
mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID,
|
||||
IUdfpsOverlayController.REASON_AUTH);
|
||||
IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD);
|
||||
mFgExecutor.runAllReady();
|
||||
mUdfpsController.onAodInterrupt(0, 0, 0f, 0f);
|
||||
// WHEN it is cancelled
|
||||
@@ -236,7 +236,7 @@ public class UdfpsControllerTest extends SysuiTestCase {
|
||||
public void aodInterruptTimeout() throws RemoteException {
|
||||
// GIVEN AOD interrupt
|
||||
mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID,
|
||||
IUdfpsOverlayController.REASON_AUTH);
|
||||
IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD);
|
||||
mFgExecutor.runAllReady();
|
||||
mUdfpsController.onAodInterrupt(0, 0, 0f, 0f);
|
||||
// WHEN it times out
|
||||
|
||||
@@ -50,6 +50,7 @@ import android.hardware.biometrics.IBiometricService;
|
||||
import android.hardware.biometrics.PromptInfo;
|
||||
import android.hardware.biometrics.SensorProperties;
|
||||
import android.hardware.biometrics.SensorPropertiesInternal;
|
||||
import android.hardware.fingerprint.IUdfpsOverlayController;
|
||||
import android.os.Binder;
|
||||
import android.os.Build;
|
||||
import android.os.RemoteException;
|
||||
@@ -61,6 +62,7 @@ import android.util.Slog;
|
||||
|
||||
import com.android.internal.R;
|
||||
import com.android.internal.widget.LockPatternUtils;
|
||||
import com.android.server.biometrics.sensors.AuthenticationClient;
|
||||
import com.android.server.biometrics.sensors.BaseClientMonitor;
|
||||
|
||||
import java.util.List;
|
||||
@@ -478,4 +480,14 @@ public class Utils {
|
||||
throw new IllegalArgumentException("Unknown strength: " + strength);
|
||||
}
|
||||
}
|
||||
|
||||
public static int getUdfpsAuthReason(@NonNull AuthenticationClient<?> client) {
|
||||
if (client.isKeyguard()) {
|
||||
return IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD;
|
||||
} else if (client.isBiometricPrompt()) {
|
||||
return IUdfpsOverlayController.REASON_AUTH_BP;
|
||||
} else {
|
||||
return IUdfpsOverlayController.REASON_AUTH_FPM_OTHER;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,6 +53,7 @@ public abstract class AuthenticationClient<T> extends AcquisitionClient<T>
|
||||
@Nullable private final TaskStackListener mTaskStackListener;
|
||||
private final LockoutTracker mLockoutTracker;
|
||||
private final boolean mIsRestricted;
|
||||
private final boolean mIsKeyguard;
|
||||
|
||||
protected final long mOperationId;
|
||||
|
||||
@@ -65,7 +66,7 @@ public abstract class AuthenticationClient<T> extends AcquisitionClient<T>
|
||||
int targetUserId, long operationId, boolean restricted, @NonNull String owner,
|
||||
int cookie, boolean requireConfirmation, int sensorId, boolean isStrongBiometric,
|
||||
int statsModality, int statsClient, @Nullable TaskStackListener taskStackListener,
|
||||
@NonNull LockoutTracker lockoutTracker) {
|
||||
@NonNull LockoutTracker lockoutTracker, boolean isKeyguard) {
|
||||
super(context, lazyDaemon, token, listener, targetUserId, owner, cookie, sensorId,
|
||||
statsModality, BiometricsProtoEnums.ACTION_AUTHENTICATE, statsClient);
|
||||
mIsStrongBiometric = isStrongBiometric;
|
||||
@@ -75,6 +76,7 @@ public abstract class AuthenticationClient<T> extends AcquisitionClient<T>
|
||||
mTaskStackListener = taskStackListener;
|
||||
mLockoutTracker = lockoutTracker;
|
||||
mIsRestricted = restricted;
|
||||
mIsKeyguard = isKeyguard;
|
||||
}
|
||||
|
||||
public @LockoutTracker.LockoutMode int handleFailedAttempt(int userId) {
|
||||
@@ -114,6 +116,10 @@ public abstract class AuthenticationClient<T> extends AcquisitionClient<T>
|
||||
return mIsRestricted;
|
||||
}
|
||||
|
||||
public boolean isKeyguard() {
|
||||
return mIsKeyguard;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isCryptoOperation() {
|
||||
return mOperationId != 0;
|
||||
|
||||
@@ -67,11 +67,11 @@ class FaceAuthenticationClient extends AuthenticationClient<ISession> implements
|
||||
@NonNull ClientMonitorCallbackConverter listener, int targetUserId, long operationId,
|
||||
boolean restricted, String owner, int cookie, boolean requireConfirmation, int sensorId,
|
||||
boolean isStrongBiometric, int statsClient, @NonNull UsageStats usageStats,
|
||||
@NonNull LockoutCache lockoutCache) {
|
||||
@NonNull LockoutCache lockoutCache, boolean isKeyguard) {
|
||||
super(context, lazyDaemon, token, listener, targetUserId, operationId, restricted,
|
||||
owner, cookie, requireConfirmation, sensorId, isStrongBiometric,
|
||||
BiometricsProtoEnums.MODALITY_FACE, statsClient, null /* taskStackListener */,
|
||||
lockoutCache);
|
||||
lockoutCache, isKeyguard);
|
||||
mUsageStats = usageStats;
|
||||
mLockoutCache = lockoutCache;
|
||||
mNotificationManager = context.getSystemService(NotificationManager.class);
|
||||
|
||||
@@ -451,7 +451,7 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
|
||||
mContext, mSensors.get(sensorId).getLazySession(), token, callback, userId,
|
||||
operationId, restricted, opPackageName, cookie,
|
||||
false /* requireConfirmation */, sensorId, isStrongBiometric, statsClient,
|
||||
mUsageStats, mSensors.get(sensorId).getLockoutCache());
|
||||
mUsageStats, mSensors.get(sensorId).getLockoutCache(), isKeyguard);
|
||||
mSensors.get(sensorId).getScheduler().scheduleClientMonitor(client);
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(getTag(), "Remote exception when scheduling authenticate", e);
|
||||
|
||||
@@ -646,7 +646,7 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider {
|
||||
final FaceAuthenticationClient client = new FaceAuthenticationClient(mContext,
|
||||
mLazyDaemon, token, receiver, userId, operationId, restricted, opPackageName,
|
||||
cookie, false /* requireConfirmation */, mSensorId, isStrongBiometric,
|
||||
statsClient, mLockoutTracker, mUsageStats);
|
||||
statsClient, mLockoutTracker, mUsageStats, isKeyguard);
|
||||
mScheduler.scheduleClientMonitor(client);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -66,12 +66,12 @@ class FaceAuthenticationClient extends AuthenticationClient<IBiometricsFace> {
|
||||
@NonNull LazyDaemon<IBiometricsFace> lazyDaemon, @NonNull IBinder token,
|
||||
@NonNull ClientMonitorCallbackConverter listener, int targetUserId, long operationId,
|
||||
boolean restricted, String owner, int cookie, boolean requireConfirmation, int sensorId,
|
||||
boolean isStrongBiometric, int statsClient,
|
||||
@NonNull LockoutTracker lockoutTracker, @NonNull UsageStats usageStats) {
|
||||
boolean isStrongBiometric, int statsClient, @NonNull LockoutTracker lockoutTracker,
|
||||
@NonNull UsageStats usageStats, boolean isKeyguard) {
|
||||
super(context, lazyDaemon, token, listener, targetUserId, operationId, restricted,
|
||||
owner, cookie, requireConfirmation, sensorId, isStrongBiometric,
|
||||
BiometricsProtoEnums.MODALITY_FACE, statsClient, null /* taskStackListener */,
|
||||
lockoutTracker);
|
||||
lockoutTracker, isKeyguard);
|
||||
mNotificationManager = context.getSystemService(NotificationManager.class);
|
||||
mUsageStats = usageStats;
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Slog;
|
||||
|
||||
import com.android.server.biometrics.Utils;
|
||||
import com.android.server.biometrics.sensors.AuthenticationClient;
|
||||
import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
|
||||
import com.android.server.biometrics.sensors.LockoutCache;
|
||||
@@ -58,11 +59,11 @@ class FingerprintAuthenticationClient extends AuthenticationClient<ISession> imp
|
||||
boolean restricted, @NonNull String owner, int cookie, boolean requireConfirmation,
|
||||
int sensorId, boolean isStrongBiometric, int statsClient,
|
||||
@Nullable TaskStackListener taskStackListener, @NonNull LockoutCache lockoutCache,
|
||||
@Nullable IUdfpsOverlayController udfpsOverlayController) {
|
||||
@Nullable IUdfpsOverlayController udfpsOverlayController, boolean isKeyguard) {
|
||||
super(context, lazyDaemon, token, listener, targetUserId, operationId, restricted, owner,
|
||||
cookie, requireConfirmation, sensorId, isStrongBiometric,
|
||||
BiometricsProtoEnums.MODALITY_FINGERPRINT, statsClient, taskStackListener,
|
||||
lockoutCache);
|
||||
lockoutCache, isKeyguard);
|
||||
mLockoutCache = lockoutCache;
|
||||
mUdfpsOverlayController = udfpsOverlayController;
|
||||
}
|
||||
@@ -87,7 +88,7 @@ class FingerprintAuthenticationClient extends AuthenticationClient<ISession> imp
|
||||
|
||||
@Override
|
||||
protected void startHalOperation() {
|
||||
UdfpsHelper.showUdfpsOverlay(getSensorId(), IUdfpsOverlayController.REASON_AUTH,
|
||||
UdfpsHelper.showUdfpsOverlay(getSensorId(), Utils.getUdfpsAuthReason(this),
|
||||
mUdfpsOverlayController);
|
||||
try {
|
||||
mCancellationSignal = getFreshDaemon().authenticate(mSequentialId, mOperationId);
|
||||
|
||||
@@ -70,7 +70,8 @@ class FingerprintDetectClient extends AcquisitionClient<ISession> {
|
||||
|
||||
@Override
|
||||
protected void startHalOperation() {
|
||||
UdfpsHelper.showUdfpsOverlay(getSensorId(), IUdfpsOverlayController.REASON_AUTH,
|
||||
UdfpsHelper.showUdfpsOverlay(getSensorId(),
|
||||
IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD,
|
||||
mUdfpsOverlayController);
|
||||
try {
|
||||
mCancellationSignal = getFreshDaemon().detectInteraction(mSequentialId);
|
||||
|
||||
@@ -466,7 +466,7 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
|
||||
operationId, restricted, opPackageName, cookie,
|
||||
false /* requireConfirmation */, sensorId, isStrongBiometric, statsClient,
|
||||
mTaskStackListener, mSensors.get(sensorId).getLockoutCache(),
|
||||
mUdfpsOverlayController);
|
||||
mUdfpsOverlayController, isKeyguard);
|
||||
mSensors.get(sensorId).getScheduler().scheduleClientMonitor(client);
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(getTag(), "Remote exception when scheduling authenticate", e);
|
||||
|
||||
@@ -30,6 +30,7 @@ import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Slog;
|
||||
|
||||
import com.android.server.biometrics.Utils;
|
||||
import com.android.server.biometrics.sensors.AuthenticationClient;
|
||||
import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
|
||||
import com.android.server.biometrics.sensors.LockoutTracker;
|
||||
@@ -48,7 +49,6 @@ class FingerprintAuthenticationClient extends AuthenticationClient<IBiometricsFi
|
||||
|
||||
private static final String TAG = "Biometrics/FingerprintAuthClient";
|
||||
|
||||
private final boolean mIsKeyguard;
|
||||
private final LockoutFrameworkImpl mLockoutFrameworkImpl;
|
||||
@Nullable private final IUdfpsOverlayController mUdfpsOverlayController;
|
||||
|
||||
@@ -63,10 +63,9 @@ class FingerprintAuthenticationClient extends AuthenticationClient<IBiometricsFi
|
||||
super(context, lazyDaemon, token, listener, targetUserId, operationId, restricted,
|
||||
owner, cookie, requireConfirmation, sensorId, isStrongBiometric,
|
||||
BiometricsProtoEnums.MODALITY_FINGERPRINT, statsClient, taskStackListener,
|
||||
lockoutTracker);
|
||||
lockoutTracker, isKeyguard);
|
||||
mLockoutFrameworkImpl = lockoutTracker;
|
||||
mUdfpsOverlayController = udfpsOverlayController;
|
||||
mIsKeyguard = isKeyguard;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -120,7 +119,7 @@ class FingerprintAuthenticationClient extends AuthenticationClient<IBiometricsFi
|
||||
|
||||
@Override
|
||||
protected void startHalOperation() {
|
||||
UdfpsHelper.showUdfpsOverlay(getSensorId(), IUdfpsOverlayController.REASON_AUTH,
|
||||
UdfpsHelper.showUdfpsOverlay(getSensorId(), Utils.getUdfpsAuthReason(this),
|
||||
mUdfpsOverlayController);
|
||||
try {
|
||||
// GroupId was never used. In fact, groupId is always the same as userId.
|
||||
@@ -170,8 +169,4 @@ class FingerprintAuthenticationClient extends AuthenticationClient<IBiometricsFi
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isKeyguard() {
|
||||
return mIsKeyguard;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,7 +83,8 @@ class FingerprintDetectClient extends AcquisitionClient<IBiometricsFingerprint>
|
||||
|
||||
@Override
|
||||
protected void startHalOperation() {
|
||||
UdfpsHelper.showUdfpsOverlay(getSensorId(), IUdfpsOverlayController.REASON_AUTH,
|
||||
UdfpsHelper.showUdfpsOverlay(getSensorId(),
|
||||
IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD,
|
||||
mUdfpsOverlayController);
|
||||
try {
|
||||
getFreshDaemon().authenticate(0 /* operationId */, getTargetUserId());
|
||||
|
||||
@@ -34,7 +34,6 @@ import android.hardware.biometrics.IBiometricService;
|
||||
import android.os.Binder;
|
||||
import android.os.IBinder;
|
||||
import android.platform.test.annotations.Presubmit;
|
||||
import android.util.proto.ProtoOutputStream;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.test.InstrumentationRegistry;
|
||||
@@ -279,7 +278,8 @@ public class BiometricSchedulerTest {
|
||||
super(context, lazyDaemon, token, listener, 0 /* targetUserId */, 0 /* operationId */,
|
||||
false /* restricted */, TAG, 1 /* cookie */, false /* requireConfirmation */,
|
||||
TEST_SENSOR_ID, true /* isStrongBiometric */, 0 /* statsModality */,
|
||||
0 /* statsClient */, null /* taskStackListener */, mock(LockoutTracker.class));
|
||||
0 /* statsClient */, null /* taskStackListener */, mock(LockoutTracker.class),
|
||||
false /* isKeyguard */);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user