Merge "Don't show notification private view too early"
This commit is contained in:
@@ -1196,6 +1196,21 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|
||||
return fingerprintAllowed || faceAllowed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the user is unlocked with a biometric that is currently bypassing
|
||||
* the lock screen.
|
||||
*/
|
||||
public boolean getUserUnlockedWithBiometricAndIsBypassing(int userId) {
|
||||
BiometricAuthenticated fingerprint = mUserFingerprintAuthenticated.get(userId);
|
||||
BiometricAuthenticated face = mUserFaceAuthenticated.get(userId);
|
||||
// fingerprint always bypasses
|
||||
boolean fingerprintAllowed = fingerprint != null && fingerprint.mAuthenticated
|
||||
&& isUnlockingWithBiometricAllowed(fingerprint.mIsStrongBiometric);
|
||||
boolean faceAllowed = face != null && face.mAuthenticated
|
||||
&& isUnlockingWithBiometricAllowed(face.mIsStrongBiometric);
|
||||
return fingerprintAllowed || faceAllowed && mKeyguardBypassController.canBypass();
|
||||
}
|
||||
|
||||
public boolean getUserTrustIsManaged(int userId) {
|
||||
return mUserTrustIsManaged.get(userId) && !isTrustDisabled(userId);
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.android.keyguard.KeyguardUpdateMonitor;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.dagger.qualifiers.Main;
|
||||
import com.android.systemui.flags.FeatureFlags;
|
||||
@@ -47,6 +48,7 @@ import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
|
||||
import com.android.systemui.statusbar.notification.stack.ForegroundServiceSectionController;
|
||||
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
|
||||
import com.android.systemui.statusbar.phone.KeyguardBypassController;
|
||||
import com.android.systemui.statusbar.policy.KeyguardStateController;
|
||||
import com.android.systemui.util.Assert;
|
||||
import com.android.wm.shell.bubbles.Bubbles;
|
||||
|
||||
@@ -98,6 +100,8 @@ public class NotificationViewHierarchyManager implements DynamicPrivacyControlle
|
||||
private final ForegroundServiceSectionController mFgsSectionController;
|
||||
private final NotifPipelineFlags mNotifPipelineFlags;
|
||||
private AssistantFeedbackController mAssistantFeedbackController;
|
||||
private final KeyguardStateController mKeyguardStateController;
|
||||
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
|
||||
private final Context mContext;
|
||||
|
||||
private NotificationPresenter mPresenter;
|
||||
@@ -129,7 +133,9 @@ public class NotificationViewHierarchyManager implements DynamicPrivacyControlle
|
||||
DynamicChildBindController dynamicChildBindController,
|
||||
LowPriorityInflationHelper lowPriorityInflationHelper,
|
||||
AssistantFeedbackController assistantFeedbackController,
|
||||
NotifPipelineFlags notifPipelineFlags) {
|
||||
NotifPipelineFlags notifPipelineFlags,
|
||||
KeyguardUpdateMonitor keyguardUpdateMonitor,
|
||||
KeyguardStateController keyguardStateController) {
|
||||
mContext = context;
|
||||
mHandler = mainHandler;
|
||||
mFeatureFlags = featureFlags;
|
||||
@@ -149,6 +155,8 @@ public class NotificationViewHierarchyManager implements DynamicPrivacyControlle
|
||||
mDynamicChildBindController = dynamicChildBindController;
|
||||
mLowPriorityInflationHelper = lowPriorityInflationHelper;
|
||||
mAssistantFeedbackController = assistantFeedbackController;
|
||||
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
|
||||
mKeyguardStateController = keyguardStateController;
|
||||
}
|
||||
|
||||
public void setUpWithPresenter(NotificationPresenter presenter,
|
||||
@@ -174,6 +182,11 @@ public class NotificationViewHierarchyManager implements DynamicPrivacyControlle
|
||||
|
||||
beginUpdate();
|
||||
|
||||
boolean dynamicallyUnlocked = mDynamicPrivacyController.isDynamicallyUnlocked()
|
||||
&& !(mStatusBarStateController.getState() == StatusBarState.KEYGUARD
|
||||
&& mKeyguardUpdateMonitor.getUserUnlockedWithBiometricAndIsBypassing(
|
||||
KeyguardUpdateMonitor.getCurrentUser()))
|
||||
&& !mKeyguardStateController.isKeyguardGoingAway();
|
||||
List<NotificationEntry> activeNotifications = mEntryManager.getVisibleNotifications();
|
||||
ArrayList<ExpandableNotificationRow> toShow = new ArrayList<>(activeNotifications.size());
|
||||
final int N = activeNotifications.size();
|
||||
@@ -192,7 +205,7 @@ public class NotificationViewHierarchyManager implements DynamicPrivacyControlle
|
||||
boolean devicePublic = mLockscreenUserManager.isLockscreenPublicMode(currentUserId);
|
||||
boolean userPublic = devicePublic
|
||||
|| mLockscreenUserManager.isLockscreenPublicMode(userId);
|
||||
if (userPublic && mDynamicPrivacyController.isDynamicallyUnlocked()
|
||||
if (userPublic && dynamicallyUnlocked
|
||||
&& (userId == currentUserId || userId == UserHandle.USER_ALL
|
||||
|| !mLockscreenUserManager.needsSeparateWorkChallenge(userId))) {
|
||||
userPublic = false;
|
||||
|
||||
@@ -23,6 +23,7 @@ import android.os.Handler;
|
||||
import android.service.dreams.IDreamManager;
|
||||
|
||||
import com.android.internal.statusbar.IStatusBarService;
|
||||
import com.android.keyguard.KeyguardUpdateMonitor;
|
||||
import com.android.systemui.animation.ActivityLaunchAnimator;
|
||||
import com.android.systemui.animation.DialogLaunchAnimator;
|
||||
import com.android.systemui.dagger.SysUISingleton;
|
||||
@@ -72,6 +73,7 @@ import com.android.systemui.statusbar.phone.StatusBarRemoteInputCallback;
|
||||
import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController;
|
||||
import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallFlags;
|
||||
import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallLogger;
|
||||
import com.android.systemui.statusbar.policy.KeyguardStateController;
|
||||
import com.android.systemui.statusbar.policy.RemoteInputUriController;
|
||||
import com.android.systemui.statusbar.window.StatusBarWindowController;
|
||||
import com.android.systemui.tracing.ProtoTracer;
|
||||
@@ -214,7 +216,9 @@ public interface StatusBarDependenciesModule {
|
||||
DynamicChildBindController dynamicChildBindController,
|
||||
LowPriorityInflationHelper lowPriorityInflationHelper,
|
||||
AssistantFeedbackController assistantFeedbackController,
|
||||
NotifPipelineFlags notifPipelineFlags) {
|
||||
NotifPipelineFlags notifPipelineFlags,
|
||||
KeyguardUpdateMonitor keyguardUpdateMonitor,
|
||||
KeyguardStateController keyguardStateController) {
|
||||
return new NotificationViewHierarchyManager(
|
||||
context,
|
||||
mainHandler,
|
||||
@@ -231,7 +235,9 @@ public interface StatusBarDependenciesModule {
|
||||
dynamicChildBindController,
|
||||
lowPriorityInflationHelper,
|
||||
assistantFeedbackController,
|
||||
notifPipelineFlags);
|
||||
notifPipelineFlags,
|
||||
keyguardUpdateMonitor,
|
||||
keyguardStateController);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -166,6 +166,8 @@ public class KeyguardCoordinator implements Coordinator {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(b/206118999): merge this class with SensitiveContentCoordinator which also depends on
|
||||
// these same updates
|
||||
private void setupInvalidateNotifListCallbacks() {
|
||||
// register onKeyguardShowing callback
|
||||
mKeyguardStateController.addCallback(mKeyguardCallback);
|
||||
|
||||
@@ -17,7 +17,10 @@
|
||||
package com.android.systemui.statusbar.notification.collection.coordinator
|
||||
|
||||
import android.os.UserHandle
|
||||
import com.android.keyguard.KeyguardUpdateMonitor
|
||||
import com.android.systemui.plugins.statusbar.StatusBarStateController
|
||||
import com.android.systemui.statusbar.NotificationLockscreenUserManager
|
||||
import com.android.systemui.statusbar.StatusBarState
|
||||
import com.android.systemui.statusbar.notification.DynamicPrivacyController
|
||||
import com.android.systemui.statusbar.notification.collection.GroupEntry
|
||||
import com.android.systemui.statusbar.notification.collection.ListEntry
|
||||
@@ -26,6 +29,7 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry
|
||||
import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope
|
||||
import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeRenderListListener
|
||||
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.Invalidator
|
||||
import com.android.systemui.statusbar.policy.KeyguardStateController
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
|
||||
@@ -36,9 +40,13 @@ object SensitiveContentCoordinatorModule {
|
||||
@CoordinatorScope
|
||||
fun provideCoordinator(
|
||||
dynamicPrivacyController: DynamicPrivacyController,
|
||||
lockscreenUserManager: NotificationLockscreenUserManager
|
||||
lockscreenUserManager: NotificationLockscreenUserManager,
|
||||
keyguardUpdateMonitor: KeyguardUpdateMonitor,
|
||||
statusBarStateController: StatusBarStateController,
|
||||
keyguardStateController: KeyguardStateController
|
||||
): SensitiveContentCoordinator =
|
||||
SensitiveContentCoordinatorImpl(dynamicPrivacyController, lockscreenUserManager)
|
||||
SensitiveContentCoordinatorImpl(dynamicPrivacyController, lockscreenUserManager,
|
||||
keyguardUpdateMonitor, statusBarStateController, keyguardStateController)
|
||||
}
|
||||
|
||||
/** Coordinates re-inflation and post-processing of sensitive notification content. */
|
||||
@@ -46,7 +54,10 @@ interface SensitiveContentCoordinator : Coordinator
|
||||
|
||||
private class SensitiveContentCoordinatorImpl(
|
||||
private val dynamicPrivacyController: DynamicPrivacyController,
|
||||
private val lockscreenUserManager: NotificationLockscreenUserManager
|
||||
private val lockscreenUserManager: NotificationLockscreenUserManager,
|
||||
private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
|
||||
private val statusBarStateController: StatusBarStateController,
|
||||
private val keyguardStateController: KeyguardStateController
|
||||
) : Invalidator("SensitiveContentInvalidator"),
|
||||
SensitiveContentCoordinator,
|
||||
DynamicPrivacyController.Listener,
|
||||
@@ -61,6 +72,19 @@ private class SensitiveContentCoordinatorImpl(
|
||||
override fun onDynamicPrivacyChanged(): Unit = invalidateList()
|
||||
|
||||
override fun onBeforeRenderList(entries: List<ListEntry>) {
|
||||
if (keyguardStateController.isKeyguardGoingAway() ||
|
||||
statusBarStateController.getState() == StatusBarState.KEYGUARD &&
|
||||
keyguardUpdateMonitor.getUserUnlockedWithBiometricAndIsBypassing(
|
||||
KeyguardUpdateMonitor.getCurrentUser())) {
|
||||
// don't update yet if:
|
||||
// - the keyguard is currently going away
|
||||
// - LS is about to be dismissed by a biometric that bypasses LS (avoid notif flash)
|
||||
|
||||
// TODO(b/206118999): merge this class with KeyguardCoordinator which ensures the
|
||||
// dependent state changes invalidate the pipeline
|
||||
return
|
||||
}
|
||||
|
||||
val currentUserId = lockscreenUserManager.currentUserId
|
||||
val devicePublic = lockscreenUserManager.isLockscreenPublicMode(currentUserId)
|
||||
val deviceSensitive = devicePublic &&
|
||||
|
||||
@@ -35,6 +35,7 @@ import android.widget.LinearLayout;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.keyguard.KeyguardUpdateMonitor;
|
||||
import com.android.systemui.SysuiTestCase;
|
||||
import com.android.systemui.flags.FeatureFlags;
|
||||
import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
|
||||
@@ -56,6 +57,7 @@ import com.android.systemui.statusbar.notification.row.NotificationTestHelper;
|
||||
import com.android.systemui.statusbar.notification.stack.ForegroundServiceSectionController;
|
||||
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
|
||||
import com.android.systemui.statusbar.phone.KeyguardBypassController;
|
||||
import com.android.systemui.statusbar.policy.KeyguardStateController;
|
||||
import com.android.wm.shell.bubbles.Bubbles;
|
||||
|
||||
import com.google.android.collect.Lists;
|
||||
@@ -123,7 +125,9 @@ public class NotificationViewHierarchyManagerTest extends SysuiTestCase {
|
||||
mock(DynamicChildBindController.class),
|
||||
mock(LowPriorityInflationHelper.class),
|
||||
mock(AssistantFeedbackController.class),
|
||||
mNotifPipelineFlags);
|
||||
mNotifPipelineFlags,
|
||||
mock(KeyguardUpdateMonitor.class),
|
||||
mock(KeyguardStateController.class));
|
||||
mViewHierarchyManager.setUpWithPresenter(mPresenter, mStackController, mListContainer);
|
||||
}
|
||||
|
||||
|
||||
@@ -19,8 +19,11 @@ package com.android.systemui.statusbar.notification.collection.coordinator
|
||||
import android.os.UserHandle
|
||||
import android.service.notification.StatusBarNotification
|
||||
import androidx.test.filters.SmallTest
|
||||
import com.android.keyguard.KeyguardUpdateMonitor
|
||||
import com.android.systemui.SysuiTestCase
|
||||
import com.android.systemui.plugins.statusbar.StatusBarStateController
|
||||
import com.android.systemui.statusbar.NotificationLockscreenUserManager
|
||||
import com.android.systemui.statusbar.StatusBarState
|
||||
import com.android.systemui.statusbar.notification.DynamicPrivacyController
|
||||
import com.android.systemui.statusbar.notification.collection.ListEntry
|
||||
import com.android.systemui.statusbar.notification.collection.NotifPipeline
|
||||
@@ -28,9 +31,12 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry
|
||||
import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeRenderListListener
|
||||
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.Invalidator
|
||||
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.Pluggable
|
||||
import com.android.systemui.statusbar.policy.KeyguardStateController
|
||||
import com.android.systemui.util.mockito.withArgCaptor
|
||||
import com.android.systemui.util.mockito.any
|
||||
import com.android.systemui.util.mockito.mock
|
||||
import org.junit.Test
|
||||
import org.mockito.Mockito.never
|
||||
import org.mockito.Mockito.verify
|
||||
import org.mockito.Mockito.`when` as whenever
|
||||
|
||||
@@ -40,9 +46,13 @@ class SensitiveContentCoordinatorTest : SysuiTestCase() {
|
||||
val dynamicPrivacyController: DynamicPrivacyController = mock()
|
||||
val lockscreenUserManager: NotificationLockscreenUserManager = mock()
|
||||
val pipeline: NotifPipeline = mock()
|
||||
val keyguardUpdateMonitor: KeyguardUpdateMonitor = mock()
|
||||
val statusBarStateController: StatusBarStateController = mock()
|
||||
val keyguardStateController: KeyguardStateController = mock()
|
||||
|
||||
val coordinator: SensitiveContentCoordinator = SensitiveContentCoordinatorModule
|
||||
.provideCoordinator(dynamicPrivacyController, lockscreenUserManager)
|
||||
.provideCoordinator(dynamicPrivacyController, lockscreenUserManager,
|
||||
keyguardUpdateMonitor, statusBarStateController, keyguardStateController)
|
||||
|
||||
@Test
|
||||
fun onDynamicPrivacyChanged_invokeInvalidationListener() {
|
||||
@@ -190,6 +200,28 @@ class SensitiveContentCoordinatorTest : SysuiTestCase() {
|
||||
verify(entry.representativeEntry!!).setSensitive(true, true)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun onBeforeRenderList_deviceDynamicallyUnlocked_deviceBiometricBypassingLockScreen() {
|
||||
coordinator.attach(pipeline)
|
||||
val onBeforeRenderListListener = withArgCaptor<OnBeforeRenderListListener> {
|
||||
verify(pipeline).addOnBeforeRenderListListener(capture())
|
||||
}
|
||||
|
||||
whenever(lockscreenUserManager.currentUserId).thenReturn(1)
|
||||
whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(true)
|
||||
whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1)).thenReturn(false)
|
||||
whenever(dynamicPrivacyController.isDynamicallyUnlocked).thenReturn(true)
|
||||
whenever(statusBarStateController.getState()).thenReturn(StatusBarState.KEYGUARD)
|
||||
whenever(keyguardUpdateMonitor.getUserUnlockedWithBiometricAndIsBypassing(any()))
|
||||
.thenReturn(true)
|
||||
|
||||
val entry = fakeNotification(2, true)
|
||||
|
||||
onBeforeRenderListListener.onBeforeRenderList(listOf(entry))
|
||||
|
||||
verify(entry.representativeEntry!!, never()).setSensitive(any(), any())
|
||||
}
|
||||
|
||||
private fun fakeNotification(notifUserId: Int, needsRedaction: Boolean): ListEntry {
|
||||
val mockUserHandle = mock<UserHandle>().apply {
|
||||
whenever(identifier).thenReturn(notifUserId)
|
||||
|
||||
Reference in New Issue
Block a user