Loading packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java +90 −2 Original line number Diff line number Diff line Loading @@ -81,6 +81,7 @@ import com.android.systemui.dump.DumpManager; import com.android.systemui.flags.DisableSceneContainer; import com.android.systemui.flags.EnableSceneContainer; import com.android.systemui.flags.FakeFeatureFlagsClassic; import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor; import com.android.systemui.log.LogWtfHandlerRule; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.recents.OverviewProxyService; Loading @@ -90,6 +91,7 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder; import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection; import com.android.systemui.statusbar.notification.collection.render.NotificationVisibilityProvider; import com.android.systemui.statusbar.notification.row.shared.LockscreenOtpRedaction; import com.android.systemui.statusbar.policy.DeviceProvisionedController; import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.util.concurrency.FakeExecutor; Loading @@ -115,6 +117,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.concurrent.Executor; import java.util.concurrent.TimeUnit; import platform.test.runner.parameterized.ParameterizedAndroidJunit4; import platform.test.runner.parameterized.Parameters; Loading Loading @@ -169,6 +172,10 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase { @Mock private DeviceUnlockedInteractor mDeviceUnlockedInteractor; @Mock private Lazy<KeyguardInteractor> mKeyguardInteractorLazy; @Mock private KeyguardInteractor mKeyguardInteractor; @Mock private StateFlow<DeviceUnlockStatus> mDeviceUnlockStatusStateFlow; private UserInfo mCurrentUser; Loading @@ -181,6 +188,7 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase { private NotificationEntry mSecondaryUserNotif; private NotificationEntry mWorkProfileNotif; private NotificationEntry mSensitiveContentNotif; private long mSensitiveNotifPostTime; private final FakeFeatureFlagsClassic mFakeFeatureFlags = new FakeFeatureFlagsClassic(); private final FakeSystemClock mFakeSystemClock = new FakeSystemClock(); private final FakeExecutor mBackgroundExecutor = new FakeExecutor(mFakeSystemClock); Loading Loading @@ -246,13 +254,17 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase { mSensitiveContentNotif = new NotificationEntryBuilder() .setNotification(notifWithPrivateVisibility) .setUser(new UserHandle(mCurrentUser.id)) .setPostTime(System.currentTimeMillis()) .build(); mSensitiveContentNotif.setRanking(new RankingBuilder(mCurrentUserNotif.getRanking()) .setChannel(channel) .setSensitiveContent(true) .setVisibilityOverride(VISIBILITY_NO_OVERRIDE).build()); mSensitiveNotifPostTime = mSensitiveContentNotif.getSbn().getPostTime(); when(mNotifCollection.getEntry(mWorkProfileNotif.getKey())).thenReturn(mWorkProfileNotif); when(mKeyguardInteractorLazy.get()).thenReturn(mKeyguardInteractor); when(mKeyguardInteractor.isKeyguardDismissible()) .thenReturn(mock(StateFlow.class)); mLockscreenUserManager = new TestNotificationLockscreenUserManager(mContext); mLockscreenUserManager.setUpWithPresenter(mPresenter); Loading Loading @@ -504,11 +516,85 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase { } @Test @EnableFlags(LockscreenOtpRedaction.FLAG_NAME) public void testHasSensitiveContent_notRedactedIfNotLocked() { // Allow private notifications for this user mSettings.putIntForUser(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 1, mCurrentUser.id); changeSetting(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS); // Claim the device was last locked 1 day ago mLockscreenUserManager.mLastLockTime .set(mSensitiveNotifPostTime - TimeUnit.DAYS.toMillis(1)); // Device is not currently locked when(mKeyguardManager.isDeviceLocked()).thenReturn(false); // Sensitive Content notifications are always redacted assertEquals(REDACTION_TYPE_NONE, mLockscreenUserManager.getRedactionType(mSensitiveContentNotif)); } @Test @EnableFlags(LockscreenOtpRedaction.FLAG_NAME) public void testHasSensitiveContent_notRedactedIfUnlockedSinceReceipt() { // Allow private notifications for this user mSettings.putIntForUser(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 1, mCurrentUser.id); changeSetting(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS); when(mKeyguardManager.isDeviceLocked()).thenReturn(true); // Device was locked after this notification arrived mLockscreenUserManager.mLastLockTime .set(mSensitiveNotifPostTime + TimeUnit.DAYS.toMillis(1)); // Sensitive Content notifications are always redacted assertEquals(REDACTION_TYPE_NONE, mLockscreenUserManager.getRedactionType(mSensitiveContentNotif)); } @Test @EnableFlags(LockscreenOtpRedaction.FLAG_NAME) public void testHasSensitiveContent_notRedactedIfNotLockedForLongEnough() { // Allow private notifications for this user mSettings.putIntForUser(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 1, mCurrentUser.id); changeSetting(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS); // Device has been locked for 1 second before the notification came in, which is too short mLockscreenUserManager.mLastLockTime .set(mSensitiveNotifPostTime - TimeUnit.SECONDS.toMillis(1)); when(mKeyguardManager.isDeviceLocked()).thenReturn(true); // Sensitive Content notifications are always redacted assertEquals(REDACTION_TYPE_NONE, mLockscreenUserManager.getRedactionType(mSensitiveContentNotif)); } @Test @DisableFlags(LockscreenOtpRedaction.FLAG_NAME) public void testHasSensitiveContent_notRedactedFlagDisabled() { // Allow private notifications for this user mSettings.putIntForUser(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 1, mCurrentUser.id); changeSetting(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS); // Claim the device was last locked 1 day ago mLockscreenUserManager.mLastLockTime .set(mSensitiveNotifPostTime - TimeUnit.DAYS.toMillis(1)); when(mKeyguardManager.isDeviceLocked()).thenReturn(true); // Sensitive Content notifications are always redacted assertEquals(REDACTION_TYPE_NONE, mLockscreenUserManager.getRedactionType(mSensitiveContentNotif)); } @Test @EnableFlags(LockscreenOtpRedaction.FLAG_NAME) public void testHasSensitiveContent_redacted() { // Allow private notifications for this user mSettings.putIntForUser(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 1, mCurrentUser.id); changeSetting(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS); when(mKeyguardManager.isDeviceLocked()).thenReturn(true); // Claim the device was last unlocked 1 day ago mLockscreenUserManager.mLastLockTime .set(mSensitiveNotifPostTime - TimeUnit.DAYS.toMillis(1)); // Sensitive Content notifications are always redacted assertEquals(REDACTION_TYPE_SENSITIVE_CONTENT, Loading Loading @@ -1066,7 +1152,9 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase { mock(DumpManager.class), mock(LockPatternUtils.class), mFakeFeatureFlags, mDeviceUnlockedInteractorLazy mDeviceUnlockedInteractorLazy, mKeyguardInteractorLazy, null //CoroutineScope ); } Loading packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java +66 −5 Original line number Diff line number Diff line Loading @@ -61,11 +61,13 @@ import com.android.systemui.Dumpable; import com.android.systemui.Flags; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Application; import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.deviceentry.domain.interactor.DeviceUnlockedInteractor; import com.android.systemui.dump.DumpManager; import com.android.systemui.flags.FeatureFlagsClassic; import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener; import com.android.systemui.recents.OverviewProxyService; Loading @@ -78,6 +80,7 @@ import com.android.systemui.statusbar.notification.row.shared.LockscreenOtpRedac import com.android.systemui.statusbar.policy.DeviceProvisionedController; import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.util.ListenerSet; import com.android.systemui.util.kotlin.JavaAdapterKt; import com.android.systemui.util.settings.SecureSettings; import dagger.Lazy; Loading @@ -88,9 +91,13 @@ import java.util.Collection; import java.util.List; import java.util.Objects; import java.util.concurrent.Executor; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; import javax.inject.Inject; import kotlinx.coroutines.CoroutineScope; /** * Handles keeping track of the current user, profiles, and various things related to hiding * contents, redacting notifications, and the lockscreen. Loading @@ -111,6 +118,9 @@ public class NotificationLockscreenUserManagerImpl implements private static final Uri SHOW_PRIVATE_LOCKSCREEN = Settings.Secure.getUriFor(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS); private static final long LOCK_TIME_FOR_SENSITIVE_REDACTION_MS = TimeUnit.MINUTES.toMillis(10); private final Lazy<NotificationVisibilityProvider> mVisibilityProviderLazy; private final Lazy<CommonNotifCollection> mCommonNotifCollectionLazy; private final DevicePolicyManager mDevicePolicyManager; Loading Loading @@ -284,7 +294,12 @@ public class NotificationLockscreenUserManagerImpl implements protected final SparseArray<UserInfo> mCurrentProfiles = new SparseArray<>(); protected final SparseArray<UserInfo> mCurrentManagedProfiles = new SparseArray<>(); // The last lock time. Uses currentTimeMillis @VisibleForTesting protected final AtomicLong mLastLockTime = new AtomicLong(-1); protected int mCurrentUserId = 0; protected NotificationPresenter mPresenter; protected ContentObserver mLockscreenSettingsObserver; protected ContentObserver mSettingsObserver; Loading @@ -311,7 +326,10 @@ public class NotificationLockscreenUserManagerImpl implements DumpManager dumpManager, LockPatternUtils lockPatternUtils, FeatureFlagsClassic featureFlags, Lazy<DeviceUnlockedInteractor> deviceUnlockedInteractorLazy) { Lazy<DeviceUnlockedInteractor> deviceUnlockedInteractorLazy, Lazy<KeyguardInteractor> keyguardInteractor, @Application CoroutineScope coroutineScope ) { mContext = context; mMainExecutor = mainExecutor; mBackgroundExecutor = backgroundExecutor; Loading Loading @@ -341,6 +359,18 @@ public class NotificationLockscreenUserManagerImpl implements if (keyguardPrivateNotifications()) { init(); } // To avoid dependency injection cycle, finish constructing this object before using the // KeyguardInteractor. The CoroutineScope will only be null in tests. if (LockscreenOtpRedaction.isEnabled() && coroutineScope != null) { mMainExecutor.execute(() -> JavaAdapterKt.collectFlow(coroutineScope, keyguardInteractor.get().isKeyguardDismissible(), unlocked -> { if (!unlocked) { mLastLockTime.set(System.currentTimeMillis()); } })); } } public void setUpWithPresenter(NotificationPresenter presenter) { Loading Loading @@ -667,8 +697,6 @@ public class NotificationLockscreenUserManagerImpl implements !userAllowsPrivateNotificationsInPublic(mCurrentUserId); boolean isNotifForManagedProfile = mCurrentManagedProfiles.contains(userId); boolean isNotifUserRedacted = !userAllowsPrivateNotificationsInPublic(userId); boolean isNotifSensitive = LockscreenOtpRedaction.isEnabled() && ent.getRanking() != null && ent.getRanking().hasSensitiveContent(); // redact notifications if the current user is redacting notifications or the notification // contains sensitive content. However if the notification is associated with a managed Loading @@ -689,12 +717,45 @@ public class NotificationLockscreenUserManagerImpl implements if (keyguardPrivateNotifications() && !mKeyguardAllowingNotifications) { return REDACTION_TYPE_PUBLIC; } if (isNotifSensitive) { if (shouldShowSensitiveContentRedactedView(ent)) { return REDACTION_TYPE_SENSITIVE_CONTENT; } return REDACTION_TYPE_NONE; } /* * We show the sensitive content redaction view if * 1. The feature is enabled * 2. The device is locked * 3. The notification has the `hasSensitiveContent` ranking variable set to true * 4. The device has been locked for at least LOCK_TIME_FOR_SENSITIVE_REDACTION_MS * 5. The notification arrived since the last lock time */ private boolean shouldShowSensitiveContentRedactedView(NotificationEntry ent) { if (!LockscreenOtpRedaction.isEnabled()) { return false; } if (!mKeyguardManager.isDeviceLocked()) { return false; } if (ent.getRanking() == null || !ent.getRanking().hasSensitiveContent()) { return false; } long lastLockedTime = mLastLockTime.get(); if (ent.getSbn().getPostTime() < lastLockedTime) { return false; } if ((System.currentTimeMillis() - lastLockedTime) < LOCK_TIME_FOR_SENSITIVE_REDACTION_MS) { return false; } return true; } private boolean packageHasVisibilityOverride(String key) { if (mCommonNotifCollectionLazy.get() == null) { Log.wtf(TAG, "mEntryManager was null!", new Throwable()); Loading Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java +90 −2 Original line number Diff line number Diff line Loading @@ -81,6 +81,7 @@ import com.android.systemui.dump.DumpManager; import com.android.systemui.flags.DisableSceneContainer; import com.android.systemui.flags.EnableSceneContainer; import com.android.systemui.flags.FakeFeatureFlagsClassic; import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor; import com.android.systemui.log.LogWtfHandlerRule; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.recents.OverviewProxyService; Loading @@ -90,6 +91,7 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder; import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection; import com.android.systemui.statusbar.notification.collection.render.NotificationVisibilityProvider; import com.android.systemui.statusbar.notification.row.shared.LockscreenOtpRedaction; import com.android.systemui.statusbar.policy.DeviceProvisionedController; import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.util.concurrency.FakeExecutor; Loading @@ -115,6 +117,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.concurrent.Executor; import java.util.concurrent.TimeUnit; import platform.test.runner.parameterized.ParameterizedAndroidJunit4; import platform.test.runner.parameterized.Parameters; Loading Loading @@ -169,6 +172,10 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase { @Mock private DeviceUnlockedInteractor mDeviceUnlockedInteractor; @Mock private Lazy<KeyguardInteractor> mKeyguardInteractorLazy; @Mock private KeyguardInteractor mKeyguardInteractor; @Mock private StateFlow<DeviceUnlockStatus> mDeviceUnlockStatusStateFlow; private UserInfo mCurrentUser; Loading @@ -181,6 +188,7 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase { private NotificationEntry mSecondaryUserNotif; private NotificationEntry mWorkProfileNotif; private NotificationEntry mSensitiveContentNotif; private long mSensitiveNotifPostTime; private final FakeFeatureFlagsClassic mFakeFeatureFlags = new FakeFeatureFlagsClassic(); private final FakeSystemClock mFakeSystemClock = new FakeSystemClock(); private final FakeExecutor mBackgroundExecutor = new FakeExecutor(mFakeSystemClock); Loading Loading @@ -246,13 +254,17 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase { mSensitiveContentNotif = new NotificationEntryBuilder() .setNotification(notifWithPrivateVisibility) .setUser(new UserHandle(mCurrentUser.id)) .setPostTime(System.currentTimeMillis()) .build(); mSensitiveContentNotif.setRanking(new RankingBuilder(mCurrentUserNotif.getRanking()) .setChannel(channel) .setSensitiveContent(true) .setVisibilityOverride(VISIBILITY_NO_OVERRIDE).build()); mSensitiveNotifPostTime = mSensitiveContentNotif.getSbn().getPostTime(); when(mNotifCollection.getEntry(mWorkProfileNotif.getKey())).thenReturn(mWorkProfileNotif); when(mKeyguardInteractorLazy.get()).thenReturn(mKeyguardInteractor); when(mKeyguardInteractor.isKeyguardDismissible()) .thenReturn(mock(StateFlow.class)); mLockscreenUserManager = new TestNotificationLockscreenUserManager(mContext); mLockscreenUserManager.setUpWithPresenter(mPresenter); Loading Loading @@ -504,11 +516,85 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase { } @Test @EnableFlags(LockscreenOtpRedaction.FLAG_NAME) public void testHasSensitiveContent_notRedactedIfNotLocked() { // Allow private notifications for this user mSettings.putIntForUser(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 1, mCurrentUser.id); changeSetting(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS); // Claim the device was last locked 1 day ago mLockscreenUserManager.mLastLockTime .set(mSensitiveNotifPostTime - TimeUnit.DAYS.toMillis(1)); // Device is not currently locked when(mKeyguardManager.isDeviceLocked()).thenReturn(false); // Sensitive Content notifications are always redacted assertEquals(REDACTION_TYPE_NONE, mLockscreenUserManager.getRedactionType(mSensitiveContentNotif)); } @Test @EnableFlags(LockscreenOtpRedaction.FLAG_NAME) public void testHasSensitiveContent_notRedactedIfUnlockedSinceReceipt() { // Allow private notifications for this user mSettings.putIntForUser(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 1, mCurrentUser.id); changeSetting(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS); when(mKeyguardManager.isDeviceLocked()).thenReturn(true); // Device was locked after this notification arrived mLockscreenUserManager.mLastLockTime .set(mSensitiveNotifPostTime + TimeUnit.DAYS.toMillis(1)); // Sensitive Content notifications are always redacted assertEquals(REDACTION_TYPE_NONE, mLockscreenUserManager.getRedactionType(mSensitiveContentNotif)); } @Test @EnableFlags(LockscreenOtpRedaction.FLAG_NAME) public void testHasSensitiveContent_notRedactedIfNotLockedForLongEnough() { // Allow private notifications for this user mSettings.putIntForUser(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 1, mCurrentUser.id); changeSetting(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS); // Device has been locked for 1 second before the notification came in, which is too short mLockscreenUserManager.mLastLockTime .set(mSensitiveNotifPostTime - TimeUnit.SECONDS.toMillis(1)); when(mKeyguardManager.isDeviceLocked()).thenReturn(true); // Sensitive Content notifications are always redacted assertEquals(REDACTION_TYPE_NONE, mLockscreenUserManager.getRedactionType(mSensitiveContentNotif)); } @Test @DisableFlags(LockscreenOtpRedaction.FLAG_NAME) public void testHasSensitiveContent_notRedactedFlagDisabled() { // Allow private notifications for this user mSettings.putIntForUser(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 1, mCurrentUser.id); changeSetting(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS); // Claim the device was last locked 1 day ago mLockscreenUserManager.mLastLockTime .set(mSensitiveNotifPostTime - TimeUnit.DAYS.toMillis(1)); when(mKeyguardManager.isDeviceLocked()).thenReturn(true); // Sensitive Content notifications are always redacted assertEquals(REDACTION_TYPE_NONE, mLockscreenUserManager.getRedactionType(mSensitiveContentNotif)); } @Test @EnableFlags(LockscreenOtpRedaction.FLAG_NAME) public void testHasSensitiveContent_redacted() { // Allow private notifications for this user mSettings.putIntForUser(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 1, mCurrentUser.id); changeSetting(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS); when(mKeyguardManager.isDeviceLocked()).thenReturn(true); // Claim the device was last unlocked 1 day ago mLockscreenUserManager.mLastLockTime .set(mSensitiveNotifPostTime - TimeUnit.DAYS.toMillis(1)); // Sensitive Content notifications are always redacted assertEquals(REDACTION_TYPE_SENSITIVE_CONTENT, Loading Loading @@ -1066,7 +1152,9 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase { mock(DumpManager.class), mock(LockPatternUtils.class), mFakeFeatureFlags, mDeviceUnlockedInteractorLazy mDeviceUnlockedInteractorLazy, mKeyguardInteractorLazy, null //CoroutineScope ); } Loading
packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java +66 −5 Original line number Diff line number Diff line Loading @@ -61,11 +61,13 @@ import com.android.systemui.Dumpable; import com.android.systemui.Flags; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Application; import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.deviceentry.domain.interactor.DeviceUnlockedInteractor; import com.android.systemui.dump.DumpManager; import com.android.systemui.flags.FeatureFlagsClassic; import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener; import com.android.systemui.recents.OverviewProxyService; Loading @@ -78,6 +80,7 @@ import com.android.systemui.statusbar.notification.row.shared.LockscreenOtpRedac import com.android.systemui.statusbar.policy.DeviceProvisionedController; import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.util.ListenerSet; import com.android.systemui.util.kotlin.JavaAdapterKt; import com.android.systemui.util.settings.SecureSettings; import dagger.Lazy; Loading @@ -88,9 +91,13 @@ import java.util.Collection; import java.util.List; import java.util.Objects; import java.util.concurrent.Executor; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; import javax.inject.Inject; import kotlinx.coroutines.CoroutineScope; /** * Handles keeping track of the current user, profiles, and various things related to hiding * contents, redacting notifications, and the lockscreen. Loading @@ -111,6 +118,9 @@ public class NotificationLockscreenUserManagerImpl implements private static final Uri SHOW_PRIVATE_LOCKSCREEN = Settings.Secure.getUriFor(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS); private static final long LOCK_TIME_FOR_SENSITIVE_REDACTION_MS = TimeUnit.MINUTES.toMillis(10); private final Lazy<NotificationVisibilityProvider> mVisibilityProviderLazy; private final Lazy<CommonNotifCollection> mCommonNotifCollectionLazy; private final DevicePolicyManager mDevicePolicyManager; Loading Loading @@ -284,7 +294,12 @@ public class NotificationLockscreenUserManagerImpl implements protected final SparseArray<UserInfo> mCurrentProfiles = new SparseArray<>(); protected final SparseArray<UserInfo> mCurrentManagedProfiles = new SparseArray<>(); // The last lock time. Uses currentTimeMillis @VisibleForTesting protected final AtomicLong mLastLockTime = new AtomicLong(-1); protected int mCurrentUserId = 0; protected NotificationPresenter mPresenter; protected ContentObserver mLockscreenSettingsObserver; protected ContentObserver mSettingsObserver; Loading @@ -311,7 +326,10 @@ public class NotificationLockscreenUserManagerImpl implements DumpManager dumpManager, LockPatternUtils lockPatternUtils, FeatureFlagsClassic featureFlags, Lazy<DeviceUnlockedInteractor> deviceUnlockedInteractorLazy) { Lazy<DeviceUnlockedInteractor> deviceUnlockedInteractorLazy, Lazy<KeyguardInteractor> keyguardInteractor, @Application CoroutineScope coroutineScope ) { mContext = context; mMainExecutor = mainExecutor; mBackgroundExecutor = backgroundExecutor; Loading Loading @@ -341,6 +359,18 @@ public class NotificationLockscreenUserManagerImpl implements if (keyguardPrivateNotifications()) { init(); } // To avoid dependency injection cycle, finish constructing this object before using the // KeyguardInteractor. The CoroutineScope will only be null in tests. if (LockscreenOtpRedaction.isEnabled() && coroutineScope != null) { mMainExecutor.execute(() -> JavaAdapterKt.collectFlow(coroutineScope, keyguardInteractor.get().isKeyguardDismissible(), unlocked -> { if (!unlocked) { mLastLockTime.set(System.currentTimeMillis()); } })); } } public void setUpWithPresenter(NotificationPresenter presenter) { Loading Loading @@ -667,8 +697,6 @@ public class NotificationLockscreenUserManagerImpl implements !userAllowsPrivateNotificationsInPublic(mCurrentUserId); boolean isNotifForManagedProfile = mCurrentManagedProfiles.contains(userId); boolean isNotifUserRedacted = !userAllowsPrivateNotificationsInPublic(userId); boolean isNotifSensitive = LockscreenOtpRedaction.isEnabled() && ent.getRanking() != null && ent.getRanking().hasSensitiveContent(); // redact notifications if the current user is redacting notifications or the notification // contains sensitive content. However if the notification is associated with a managed Loading @@ -689,12 +717,45 @@ public class NotificationLockscreenUserManagerImpl implements if (keyguardPrivateNotifications() && !mKeyguardAllowingNotifications) { return REDACTION_TYPE_PUBLIC; } if (isNotifSensitive) { if (shouldShowSensitiveContentRedactedView(ent)) { return REDACTION_TYPE_SENSITIVE_CONTENT; } return REDACTION_TYPE_NONE; } /* * We show the sensitive content redaction view if * 1. The feature is enabled * 2. The device is locked * 3. The notification has the `hasSensitiveContent` ranking variable set to true * 4. The device has been locked for at least LOCK_TIME_FOR_SENSITIVE_REDACTION_MS * 5. The notification arrived since the last lock time */ private boolean shouldShowSensitiveContentRedactedView(NotificationEntry ent) { if (!LockscreenOtpRedaction.isEnabled()) { return false; } if (!mKeyguardManager.isDeviceLocked()) { return false; } if (ent.getRanking() == null || !ent.getRanking().hasSensitiveContent()) { return false; } long lastLockedTime = mLastLockTime.get(); if (ent.getSbn().getPostTime() < lastLockedTime) { return false; } if ((System.currentTimeMillis() - lastLockedTime) < LOCK_TIME_FOR_SENSITIVE_REDACTION_MS) { return false; } return true; } private boolean packageHasVisibilityOverride(String key) { if (mCommonNotifCollectionLazy.get() == null) { Log.wtf(TAG, "mEntryManager was null!", new Throwable()); Loading