Fix settings activity showing background bp when
createConfirmDeviceCredentialIntent() API is used.
If the app uses createConfirmDeviceCredentialIntent(),
ConfirmDeviceCredentialActivity is the top activity which has "settings"
as package name. Then if the app switches to settings, since previous
foreground check only checks package name, biometric prompt isn't
cancelled. This CL adds a class name check for this case.
Flag: EXEMPT bugfix
Bug: 339532378
Test: manual test with sample app
Change-Id: I722e285cd15869799b9fadd2324014cf3c6d44ad
diff --git a/core/java/android/hardware/biometrics/BiometricPrompt.java b/core/java/android/hardware/biometrics/BiometricPrompt.java
index 9007b62..b11961c 100644
--- a/core/java/android/hardware/biometrics/BiometricPrompt.java
+++ b/core/java/android/hardware/biometrics/BiometricPrompt.java
@@ -638,17 +638,17 @@
* Set caller's component name for getting logo icon/description. This should only be used
* by ConfirmDeviceCredentialActivity, see b/337082634 for more context.
*
- * @param componentNameForConfirmDeviceCredentialActivity set the component name for
- * ConfirmDeviceCredentialActivity.
+ * @param realCaller set the component name of real caller for
+ * ConfirmDeviceCredentialActivity.
* @return This builder.
* @hide
*/
@NonNull
@RequiresPermission(anyOf = {TEST_BIOMETRIC, USE_BIOMETRIC_INTERNAL})
- public Builder setComponentNameForConfirmDeviceCredentialActivity(
- ComponentName componentNameForConfirmDeviceCredentialActivity) {
- mPromptInfo.setComponentNameForConfirmDeviceCredentialActivity(
- componentNameForConfirmDeviceCredentialActivity);
+ public Builder setRealCallerForConfirmDeviceCredentialActivity(ComponentName realCaller) {
+ mPromptInfo.setRealCallerForConfirmDeviceCredentialActivity(realCaller);
+ mPromptInfo.setClassNameIfItIsConfirmDeviceCredentialActivity(
+ mContext.getClass().getName());
return this;
}
diff --git a/core/java/android/hardware/biometrics/PromptInfo.java b/core/java/android/hardware/biometrics/PromptInfo.java
index 901f6b7..df5d864 100644
--- a/core/java/android/hardware/biometrics/PromptInfo.java
+++ b/core/java/android/hardware/biometrics/PromptInfo.java
@@ -57,7 +57,8 @@
private boolean mIsForLegacyFingerprintManager = false;
private boolean mShowEmergencyCallButton = false;
private boolean mUseParentProfileForDeviceCredential = false;
- private ComponentName mComponentNameForConfirmDeviceCredentialActivity = null;
+ private ComponentName mRealCallerForConfirmDeviceCredentialActivity = null;
+ private String mClassNameIfItIsConfirmDeviceCredentialActivity = null;
public PromptInfo() {
@@ -89,8 +90,9 @@
mIsForLegacyFingerprintManager = in.readBoolean();
mShowEmergencyCallButton = in.readBoolean();
mUseParentProfileForDeviceCredential = in.readBoolean();
- mComponentNameForConfirmDeviceCredentialActivity = in.readParcelable(
+ mRealCallerForConfirmDeviceCredentialActivity = in.readParcelable(
ComponentName.class.getClassLoader(), ComponentName.class);
+ mClassNameIfItIsConfirmDeviceCredentialActivity = in.readString();
}
public static final Creator<PromptInfo> CREATOR = new Creator<PromptInfo>() {
@@ -136,7 +138,8 @@
dest.writeBoolean(mIsForLegacyFingerprintManager);
dest.writeBoolean(mShowEmergencyCallButton);
dest.writeBoolean(mUseParentProfileForDeviceCredential);
- dest.writeParcelable(mComponentNameForConfirmDeviceCredentialActivity, 0);
+ dest.writeParcelable(mRealCallerForConfirmDeviceCredentialActivity, 0);
+ dest.writeString(mClassNameIfItIsConfirmDeviceCredentialActivity);
}
// LINT.IfChange
@@ -155,7 +158,7 @@
return true;
} else if (mShowEmergencyCallButton) {
return true;
- } else if (mComponentNameForConfirmDeviceCredentialActivity != null) {
+ } else if (mRealCallerForConfirmDeviceCredentialActivity != null) {
return true;
}
return false;
@@ -321,10 +324,8 @@
mShowEmergencyCallButton = showEmergencyCallButton;
}
- public void setComponentNameForConfirmDeviceCredentialActivity(
- ComponentName componentNameForConfirmDeviceCredentialActivity) {
- mComponentNameForConfirmDeviceCredentialActivity =
- componentNameForConfirmDeviceCredentialActivity;
+ public void setRealCallerForConfirmDeviceCredentialActivity(ComponentName realCaller) {
+ mRealCallerForConfirmDeviceCredentialActivity = realCaller;
}
public void setUseParentProfileForDeviceCredential(
@@ -332,6 +333,14 @@
mUseParentProfileForDeviceCredential = useParentProfileForDeviceCredential;
}
+ /**
+ * Set the class name of ConfirmDeviceCredentialActivity.
+ */
+ void setClassNameIfItIsConfirmDeviceCredentialActivity(String className) {
+ mClassNameIfItIsConfirmDeviceCredentialActivity = className;
+ }
+
+
// Getters
/**
@@ -455,8 +464,15 @@
return mShowEmergencyCallButton;
}
- public ComponentName getComponentNameForConfirmDeviceCredentialActivity() {
- return mComponentNameForConfirmDeviceCredentialActivity;
+ public ComponentName getRealCallerForConfirmDeviceCredentialActivity() {
+ return mRealCallerForConfirmDeviceCredentialActivity;
}
+ /**
+ * Get the class name of ConfirmDeviceCredentialActivity. Returns null if the direct caller is
+ * not ConfirmDeviceCredentialActivity.
+ */
+ public String getClassNameIfItIsConfirmDeviceCredentialActivity() {
+ return mClassNameIfItIsConfirmDeviceCredentialActivity;
+ }
}
diff --git a/packages/SystemUI/shared/biometrics/src/com/android/systemui/biometrics/Utils.kt b/packages/SystemUI/shared/biometrics/src/com/android/systemui/biometrics/Utils.kt
index 12d881b..c0b6acf 100644
--- a/packages/SystemUI/shared/biometrics/src/com/android/systemui/biometrics/Utils.kt
+++ b/packages/SystemUI/shared/biometrics/src/com/android/systemui/biometrics/Utils.kt
@@ -16,6 +16,7 @@
package com.android.systemui.biometrics
import android.Manifest
+import android.app.ActivityTaskManager
import android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC
import android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC
import android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_COMPLEX
@@ -35,6 +36,7 @@
import android.hardware.biometrics.SensorPropertiesInternal
import android.os.UserManager
import android.util.DisplayMetrics
+import android.util.Log
import android.view.ViewGroup
import android.view.WindowInsets
import android.view.WindowManager
@@ -45,6 +47,8 @@
import com.android.systemui.biometrics.shared.model.PromptKind
object Utils {
+ private const val TAG = "SysUIBiometricUtils"
+
/** Base set of layout flags for fingerprint overlay widgets. */
const val FINGERPRINT_OVERLAY_LAYOUT_PARAM_FLAGS =
(WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN or
@@ -148,4 +152,39 @@
draw(canvas)
return bitmap
}
+
+ // LINT.IfChange
+ @JvmStatic
+ /**
+ * Checks if a client package is running in the background or it's a system app.
+ *
+ * @param clientPackage The name of the package to be checked.
+ * @param clientClassNameIfItIsConfirmDeviceCredentialActivity The class name of
+ * ConfirmDeviceCredentialActivity.
+ * @return Whether the client package is running in background
+ */
+ fun ActivityTaskManager.isSystemAppOrInBackground(
+ context: Context,
+ clientPackage: String,
+ clientClassNameIfItIsConfirmDeviceCredentialActivity: String?
+ ): Boolean {
+ Log.v(TAG, "Checking if the authenticating is in background, clientPackage:$clientPackage")
+ val tasks = getTasks(Int.MAX_VALUE)
+ if (tasks == null || tasks.isEmpty()) {
+ Log.w(TAG, "No running tasks reported")
+ return false
+ }
+
+ val topActivity = tasks[0].topActivity
+ val isSystemApp = isSystem(context, clientPackage)
+ val topPackageEqualsToClient = topActivity!!.packageName == clientPackage
+ val isClientConfirmDeviceCredentialActivity =
+ clientClassNameIfItIsConfirmDeviceCredentialActivity != null
+ // b/339532378: If it's ConfirmDeviceCredentialActivity, we need to check further on
+ // class name.
+ return !(isSystemApp || topPackageEqualsToClient) ||
+ (isClientConfirmDeviceCredentialActivity &&
+ topActivity.className != clientClassNameIfItIsConfirmDeviceCredentialActivity)
+ }
+ // LINT.ThenChange(frameworks/base/services/core/java/com/android/server/biometrics/Utils.java)
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
index 9521be1..0aed2e6 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
@@ -834,6 +834,11 @@
}
@Override
+ public String getClassNameIfItIsConfirmDeviceCredentialActivity() {
+ return mConfig.mPromptInfo.getClassNameIfItIsConfirmDeviceCredentialActivity();
+ }
+
+ @Override
public long getRequestId() {
return mConfig.mRequestId;
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
index b466f31..cbd210b 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
@@ -22,7 +22,6 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.app.ActivityManager;
import android.app.ActivityTaskManager;
import android.app.TaskStackListener;
import android.content.BroadcastReceiver;
@@ -187,7 +186,7 @@
final TaskStackListener mTaskStackListener = new TaskStackListener() {
@Override
public void onTaskStackChanged() {
- if (!isOwnerInForeground()) {
+ if (isOwnerInBackground()) {
mHandler.post(AuthController.this::cancelIfOwnerIsNotInForeground);
}
}
@@ -227,21 +226,20 @@
}
}
- private boolean isOwnerInForeground() {
+ private boolean isOwnerInBackground() {
if (mCurrentDialog != null) {
final String clientPackage = mCurrentDialog.getOpPackageName();
- final List<ActivityManager.RunningTaskInfo> runningTasks =
- mActivityTaskManager.getTasks(1);
- if (!runningTasks.isEmpty()) {
- final String topPackage = runningTasks.get(0).topActivity.getPackageName();
- if (!topPackage.contentEquals(clientPackage)
- && !Utils.isSystem(mContext, clientPackage)) {
- Log.w(TAG, "Evicting client due to: " + topPackage);
- return false;
- }
+ final String clientClassNameIfItIsConfirmDeviceCredentialActivity =
+ mCurrentDialog.getClassNameIfItIsConfirmDeviceCredentialActivity();
+ final boolean isInBackground = Utils.isSystemAppOrInBackground(mActivityTaskManager,
+ mContext, clientPackage,
+ clientClassNameIfItIsConfirmDeviceCredentialActivity);
+ if (isInBackground) {
+ Log.w(TAG, "Evicting client due to top activity is not : " + clientPackage);
}
+ return isInBackground;
}
- return true;
+ return false;
}
private void cancelIfOwnerIsNotInForeground() {
@@ -1259,9 +1257,9 @@
}
mCurrentDialog = newDialog;
- // TODO(b/339532378): We should check whether |allowBackgroundAuthentication| should be
+ // TODO(b/353597496): We should check whether |allowBackgroundAuthentication| should be
// removed.
- if (!promptInfo.isAllowBackgroundAuthentication() && !isOwnerInForeground()) {
+ if (!promptInfo.isAllowBackgroundAuthentication() && isOwnerInBackground()) {
cancelIfOwnerIsNotInForeground();
} else {
mCurrentDialog.show(mWindowManager);
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthDialog.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthDialog.java
index 3fd488c..8611916 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthDialog.java
@@ -94,6 +94,12 @@
*/
String getOpPackageName();
+ /**
+ * Get the class name of ConfirmDeviceCredentialActivity. Returns null if the direct caller is
+ * not ConfirmDeviceCredentialActivity.
+ */
+ String getClassNameIfItIsConfirmDeviceCredentialActivity();
+
/** The requestId of the underlying operation within the framework. */
long getRequestId();
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/domain/model/BiometricPromptRequest.kt b/packages/SystemUI/src/com/android/systemui/biometrics/domain/model/BiometricPromptRequest.kt
index 348b423..695707d 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/domain/model/BiometricPromptRequest.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/domain/model/BiometricPromptRequest.kt
@@ -44,7 +44,7 @@
val logoDescription: String? = info.logoDescription
val negativeButtonText: String = info.negativeButtonText?.toString() ?: ""
val componentNameForConfirmDeviceCredentialActivity: ComponentName? =
- info.componentNameForConfirmDeviceCredentialActivity
+ info.realCallerForConfirmDeviceCredentialActivity
val allowBackgroundAuthentication = info.isAllowBackgroundAuthentication
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt
index 214420d..b0b411b 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt
@@ -1045,7 +1045,7 @@
val packageName =
when {
componentNameForLogo != null -> componentNameForLogo.packageName
- // TODO(b/339532378): We should check whether |allowBackgroundAuthentication| should be
+ // TODO(b/353597496): We should check whether |allowBackgroundAuthentication| should be
// removed.
// This is being consistent with the check in [AuthController.showDialog()].
allowBackgroundAuthentication || isSystem(context, opPackageName) -> opPackageName
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/domain/interactor/PromptSelectorInteractorImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/domain/interactor/PromptSelectorInteractorImplTest.kt
index 720f207..dc499cd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/domain/interactor/PromptSelectorInteractorImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/domain/interactor/PromptSelectorInteractorImplTest.kt
@@ -155,7 +155,7 @@
Authenticators.BIOMETRIC_STRONG
}
isDeviceCredentialAllowed = allowCredentialFallback
- componentNameForConfirmDeviceCredentialActivity =
+ realCallerForConfirmDeviceCredentialActivity =
if (setComponentNameForConfirmDeviceCredentialActivity)
componentNameOverriddenForConfirmDeviceCredentialActivity
else null
diff --git a/services/core/java/com/android/server/biometrics/Utils.java b/services/core/java/com/android/server/biometrics/Utils.java
index df29ca4..fb8a81b 100644
--- a/services/core/java/com/android/server/biometrics/Utils.java
+++ b/services/core/java/com/android/server/biometrics/Utils.java
@@ -586,6 +586,8 @@
}
}
+ // LINT.IfChange
+
/**
* Checks if a client package is running in the background.
*
@@ -618,4 +620,6 @@
return true;
}
+ // LINT.ThenChange(frameworks/base/packages/SystemUI/shared/biometrics/src/com/android
+ // /systemui/biometrics/Utils.kt)
}