diff options
5 files changed, 125 insertions, 14 deletions
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml index 421f41f60d85..9c864abca9dd 100644 --- a/packages/SystemUI/res/values/config.xml +++ b/packages/SystemUI/res/values/config.xml @@ -698,6 +698,10 @@ --> <integer name="config_face_auth_supported_posture">0</integer> + <!-- Components to allow running fingerprint listening if their activity is occluding the lock screen. --> + <string-array name="config_fingerprint_listen_on_occluding_activity_packages" translatable="false"> + </string-array> + <!-- Whether the communal service should be enabled --> <bool name="config_communalServiceEnabled">false</bool> diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardFingerprintListenModel.kt b/packages/SystemUI/src/com/android/keyguard/KeyguardFingerprintListenModel.kt index f2685c5200ad..f23ae67992a1 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardFingerprintListenModel.kt +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardFingerprintListenModel.kt @@ -27,6 +27,7 @@ data class KeyguardFingerprintListenModel( override var userId: Int = 0, override var listening: Boolean = false, // keepSorted + var allowOnCurrentOccludingActivity: Boolean = false, var alternateBouncerShowing: Boolean = false, var biometricEnabledForUser: Boolean = false, var bouncerIsOrWillShow: Boolean = false, @@ -58,6 +59,7 @@ data class KeyguardFingerprintListenModel( userId.toString(), listening.toString(), // keep sorted + allowOnCurrentOccludingActivity.toString(), alternateBouncerShowing.toString(), biometricEnabledForUser.toString(), bouncerIsOrWillShow.toString(), @@ -98,6 +100,7 @@ data class KeyguardFingerprintListenModel( userId = model.userId listening = model.listening // keep sorted + allowOnCurrentOccludingActivity = model.allowOnCurrentOccludingActivity alternateBouncerShowing = model.alternateBouncerShowing biometricEnabledForUser = model.biometricEnabledForUser bouncerIsOrWillShow = model.bouncerIsOrWillShow @@ -144,6 +147,7 @@ data class KeyguardFingerprintListenModel( "userId", "listening", // keep sorted + "allowOnCurrentOccludingActivity", "alternateBouncerShowing", "biometricAllowedForUser", "bouncerIsOrWillShow", diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java index 4b3f2814e410..89ef749f05bf 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -18,6 +18,8 @@ package com.android.keyguard; import static android.app.StatusBarManager.SESSION_KEYGUARD; import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; +import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static android.content.Intent.ACTION_USER_REMOVED; import static android.content.Intent.ACTION_USER_STOPPED; @@ -76,9 +78,9 @@ import static com.android.systemui.statusbar.policy.DevicePostureController.DEVI import android.annotation.AnyThread; import android.annotation.MainThread; import android.annotation.SuppressLint; -import android.app.ActivityTaskManager; import android.app.ActivityTaskManager.RootTaskInfo; import android.app.AlarmManager; +import android.app.IActivityTaskManager; import android.app.admin.DevicePolicyManager; import android.app.trust.TrustManager; import android.content.BroadcastReceiver; @@ -305,6 +307,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab private final AuthController mAuthController; private final UiEventLogger mUiEventLogger; private final Set<Integer> mFaceAcquiredInfoIgnoreList; + private final Set<String> mAllowFingerprintOnOccludingActivitiesFromPackage; private final PackageManager mPackageManager; private int mStatusBarState; private final StatusBarStateController.StateListener mStatusBarStateControllerListener = @@ -346,6 +349,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab private boolean mSecureCameraLaunched; @VisibleForTesting protected boolean mTelephonyCapable; + private boolean mAllowFingerprintOnCurrentOccludingActivity; // Device provisioning state private boolean mDeviceProvisioned; @@ -389,6 +393,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab private final FaceManager mFaceManager; @Nullable private KeyguardFaceAuthInteractor mFaceAuthInteractor; + private final TaskStackChangeListeners mTaskStackChangeListeners; + private final IActivityTaskManager mActivityTaskManager; private final LockPatternUtils mLockPatternUtils; @VisibleForTesting @DevicePostureInt @@ -2322,7 +2328,9 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab FaceWakeUpTriggersConfig faceWakeUpTriggersConfig, DevicePostureController devicePostureController, Optional<FingerprintInteractiveToAuthProvider> interactiveToAuthProvider, - FeatureFlags featureFlags) { + FeatureFlags featureFlags, + TaskStackChangeListeners taskStackChangeListeners, + IActivityTaskManager activityTaskManagerService) { mContext = context; mSubscriptionManager = subscriptionManager; mUserTracker = userTracker; @@ -2364,6 +2372,12 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab mConfigFaceAuthSupportedPosture = mContext.getResources().getInteger( R.integer.config_face_auth_supported_posture); mFaceWakeUpTriggersConfig = faceWakeUpTriggersConfig; + mAllowFingerprintOnOccludingActivitiesFromPackage = Arrays.stream( + mContext.getResources().getStringArray( + R.array.config_fingerprint_listen_on_occluding_activity_packages)) + .collect(Collectors.toSet()); + mTaskStackChangeListeners = taskStackChangeListeners; + mActivityTaskManager = activityTaskManagerService; mHandler = new Handler(mainLooper) { @Override @@ -2579,7 +2593,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab } updateBiometricListeningState(BIOMETRIC_ACTION_UPDATE, FACE_AUTH_UPDATED_ON_KEYGUARD_INIT); - TaskStackChangeListeners.getInstance().registerTaskStackListener(mTaskStackListener); + mTaskStackChangeListeners.registerTaskStackListener(mTaskStackListener); mIsSystemUser = mUserManager.isSystemUser(); int user = mUserTracker.getUserId(); mUserIsUnlocked.put(user, mUserManager.isUserUnlocked(user)); @@ -3049,7 +3063,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab && (mOccludingAppRequestingFp || isUdfps || mAlternateBouncerShowing - || mFeatureFlags.isEnabled(Flags.FP_LISTEN_OCCLUDING_APPS) + || mAllowFingerprintOnCurrentOccludingActivity ) ); @@ -3092,6 +3106,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab System.currentTimeMillis(), user, shouldListen, + mAllowFingerprintOnCurrentOccludingActivity, mAlternateBouncerShowing, biometricEnabledForUser, mPrimaryBouncerIsOrWillBeShowing, @@ -4120,19 +4135,35 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab return mSimDatas.get(subId).slotId; } - private final TaskStackChangeListener - mTaskStackListener = new TaskStackChangeListener() { + private final TaskStackChangeListener mTaskStackListener = new TaskStackChangeListener() { @Override public void onTaskStackChangedBackground() { try { - RootTaskInfo info = ActivityTaskManager.getService().getRootTaskInfo( + if (mFeatureFlags.isEnabled(Flags.FP_LISTEN_OCCLUDING_APPS)) { + RootTaskInfo standardTask = mActivityTaskManager.getRootTaskInfo( + WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD); + final boolean previousState = mAllowFingerprintOnCurrentOccludingActivity; + mAllowFingerprintOnCurrentOccludingActivity = + standardTask.topActivity != null + && !TextUtils.isEmpty(standardTask.topActivity.getPackageName()) + && mAllowFingerprintOnOccludingActivitiesFromPackage.contains( + standardTask.topActivity.getPackageName()) + && standardTask.visible; + if (mAllowFingerprintOnCurrentOccludingActivity != previousState) { + mLogger.allowFingerprintOnCurrentOccludingActivityChanged( + mAllowFingerprintOnCurrentOccludingActivity); + updateFingerprintListeningState(BIOMETRIC_ACTION_UPDATE); + } + } + + RootTaskInfo assistantTask = mActivityTaskManager.getRootTaskInfo( WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_ASSISTANT); - if (info == null) { + if (assistantTask == null) { return; } - mLogger.logTaskStackChangedForAssistant(info.visible); + mLogger.logTaskStackChangedForAssistant(assistantTask.visible); mHandler.sendMessage(mHandler.obtainMessage(MSG_ASSISTANT_STACK_CHANGED, - info.visible)); + assistantTask.visible)); } catch (RemoteException e) { mLogger.logException(e, "unable to check task stack "); } @@ -4324,7 +4355,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab mUserTracker.removeCallback(mUserChangedCallback); - TaskStackChangeListeners.getInstance().unregisterTaskStackListener(mTaskStackListener); + mTaskStackChangeListeners.unregisterTaskStackListener(mTaskStackListener); mBroadcastDispatcher.unregisterReceiver(mBroadcastReceiver); mBroadcastDispatcher.unregisterReceiver(mBroadcastAllReceiver); @@ -4383,6 +4414,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab pw.println(" enabledByUser=" + mBiometricEnabledForUser.get(userId)); pw.println(" mKeyguardOccluded=" + mKeyguardOccluded); pw.println(" mIsDreaming=" + mIsDreaming); + pw.println(" mFingerprintListenOnOccludingActivitiesFromPackage=" + + mAllowFingerprintOnOccludingActivitiesFromPackage); if (isUdfpsSupported()) { pw.println(" udfpsEnrolled=" + isUdfpsEnrolled()); pw.println(" shouldListenForUdfps=" + shouldListenForFingerprint(true)); diff --git a/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt b/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt index b5963312cb2d..a192803ea0e8 100644 --- a/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt +++ b/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt @@ -601,6 +601,15 @@ constructor(@KeyguardUpdateMonitorLog private val logBuffer: LogBuffer) { ) } + fun allowFingerprintOnCurrentOccludingActivityChanged(allow: Boolean) { + logBuffer.log( + TAG, + VERBOSE, + { bool1 = allow }, + { "allowFingerprintOnCurrentOccludingActivityChanged: $bool1" } + ) + } + fun logAssistantVisible(assistantVisible: Boolean) { logBuffer.log( TAG, diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java index b0576e02f998..901c3fb05b2f 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java @@ -17,6 +17,7 @@ package com.android.keyguard; import static android.app.StatusBarManager.SESSION_KEYGUARD; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT; import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ERROR_LOCKOUT; import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ERROR_LOCKOUT_PERMANENT; @@ -65,6 +66,8 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.app.Activity; +import android.app.ActivityTaskManager; +import android.app.IActivityTaskManager; import android.app.admin.DevicePolicyManager; import android.app.trust.IStrongAuthTracker; import android.app.trust.TrustManager; @@ -116,6 +119,7 @@ import android.telephony.TelephonyManager; import android.test.suitebuilder.annotation.SmallTest; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; +import android.text.TextUtils; import androidx.annotation.NonNull; @@ -139,6 +143,8 @@ import com.android.systemui.flags.FakeFeatureFlags; import com.android.systemui.log.SessionTracker; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.settings.UserTracker; +import com.android.systemui.shared.system.TaskStackChangeListener; +import com.android.systemui.shared.system.TaskStackChangeListeners; import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.phone.KeyguardBypassController; import com.android.systemui.statusbar.policy.DevicePostureController; @@ -175,6 +181,8 @@ import java.util.concurrent.atomic.AtomicInteger; @RunWith(AndroidTestingRunner.class) @TestableLooper.RunWithLooper public class KeyguardUpdateMonitorTest extends SysuiTestCase { + private static final String PKG_ALLOWING_FP_LISTEN_ON_OCCLUDING_ACTIVITY = + "test_app_fp_listen_on_occluding_activity"; private static final String TEST_CARRIER = "TEST_CARRIER"; private static final String TEST_CARRIER_2 = "TEST_CARRIER_2"; private static final int TEST_CARRIER_ID = 1; @@ -264,6 +272,10 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { private UsbPortStatus mUsbPortStatus; @Mock private Uri mURI; + @Mock + private TaskStackChangeListeners mTaskStackChangeListeners; + @Mock + private IActivityTaskManager mActivityTaskManager; private List<FaceSensorPropertiesInternal> mFaceSensorProperties; private List<FingerprintSensorPropertiesInternal> mFingerprintSensorProperties; @@ -327,6 +339,10 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { mDumpManager ); + mContext.getOrCreateTestableResources().addOverride(com.android.systemui + .R.array.config_fingerprint_listen_on_occluding_activity_packages, + new String[]{ PKG_ALLOWING_FP_LISTEN_ON_OCCLUDING_ACTIVITY }); + mTestableLooper = TestableLooper.get(this); allowTestableLooperAsMainThread(); mFeatureFlags = new FakeFeatureFlags(); @@ -1560,7 +1576,8 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { } @Test - public void testOccludingAppFingerprintListeningState_featureFlagEnabled() { + public void listenForFingerprint_whenOccludingAppPkgOnAllowlist() + throws RemoteException { mFeatureFlags.set(FP_LISTEN_OCCLUDING_APPS, true); // GIVEN keyguard isn't visible (app occluding) @@ -1568,10 +1585,36 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { mKeyguardUpdateMonitor.setKeyguardShowing(true, true); when(mStrongAuthTracker.hasUserAuthenticatedSinceBoot()).thenReturn(true); + // GIVEN the top activity is from a package that allows fingerprint listening over its + // occluding activities + setTopStandardActivity(PKG_ALLOWING_FP_LISTEN_ON_OCCLUDING_ACTIVITY); + onTaskStackChanged(); + // THEN we SHOULD listen for non-UDFPS fingerprint assertThat(mKeyguardUpdateMonitor.shouldListenForFingerprint(false)).isEqualTo(true); - // THEN we should listen for udfps (hiding of mechanism to actually auth is + // THEN we should listen for udfps (hiding mechanism to actually auth is + // controlled by UdfpsKeyguardViewController) + assertThat(mKeyguardUpdateMonitor.shouldListenForFingerprint(true)).isEqualTo(true); + } + + @Test + public void doNotListenForFingerprint_whenOccludingAppPkgNotOnAllowlist() + throws RemoteException { + mFeatureFlags.set(FP_LISTEN_OCCLUDING_APPS, true); + + // GIVEN keyguard isn't visible (app occluding) + mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON); + mKeyguardUpdateMonitor.setKeyguardShowing(true, true); + when(mStrongAuthTracker.hasUserAuthenticatedSinceBoot()).thenReturn(true); + + // GIVEN top activity is not in the allowlist for listening to fp over occluding activities + setTopStandardActivity("notInAllowList"); + + // THEN we should not listen for non-UDFPS fingerprint + assertThat(mKeyguardUpdateMonitor.shouldListenForFingerprint(false)).isEqualTo(false); + + // THEN we should listen for udfps (hiding mechanism to actually auth is // controlled by UdfpsKeyguardViewController) assertThat(mKeyguardUpdateMonitor.shouldListenForFingerprint(true)).isEqualTo(true); } @@ -3267,6 +3310,23 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { BatteryManager.CHARGING_POLICY_ADAPTIVE_LONGLIFE); } + private void setTopStandardActivity(String pkgName) throws RemoteException { + final ActivityTaskManager.RootTaskInfo taskInfo = new ActivityTaskManager.RootTaskInfo(); + taskInfo.visible = true; + taskInfo.topActivity = TextUtils.isEmpty(pkgName) + ? null : new ComponentName(pkgName, "testClass"); + when(mActivityTaskManager.getRootTaskInfo(anyInt(), eq(ACTIVITY_TYPE_STANDARD))) + .thenReturn(taskInfo); + } + + private void onTaskStackChanged() { + ArgumentCaptor<TaskStackChangeListener> taskStackChangeListenerCaptor = + ArgumentCaptor.forClass(TaskStackChangeListener.class); + verify(mTaskStackChangeListeners).registerTaskStackListener( + taskStackChangeListenerCaptor.capture()); + taskStackChangeListenerCaptor.getValue().onTaskStackChangedBackground(); + } + private class TestableKeyguardUpdateMonitor extends KeyguardUpdateMonitor { AtomicBoolean mSimStateChanged = new AtomicBoolean(false); AtomicInteger mCachedSimState = new AtomicInteger(-1); @@ -3284,7 +3344,8 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { mDreamManager, mDevicePolicyManager, mSensorPrivacyManager, mTelephonyManager, mPackageManager, mFaceManager, mFingerprintManager, mBiometricManager, mFaceWakeUpTriggersConfig, mDevicePostureController, - Optional.of(mInteractiveToAuthProvider), mFeatureFlags); + Optional.of(mInteractiveToAuthProvider), mFeatureFlags, + mTaskStackChangeListeners, mActivityTaskManager); setStrongAuthTracker(KeyguardUpdateMonitorTest.this.mStrongAuthTracker); } |