Merge "DO NOT MERGE Don't show notification private view too early" into sc-v2-dev

This commit is contained in:
Beverly Tai
2022-02-08 14:00:57 +00:00
committed by Android (Google) Code Review
7 changed files with 105 additions and 9 deletions

View File

@@ -1186,6 +1186,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);
}

View File

@@ -25,6 +25,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;
@@ -42,6 +43,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;
@@ -92,6 +94,8 @@ public class NotificationViewHierarchyManager implements DynamicPrivacyControlle
private final KeyguardBypassController mBypassController;
private final ForegroundServiceSectionController mFgsSectionController;
private AssistantFeedbackController mAssistantFeedbackController;
private final KeyguardStateController mKeyguardStateController;
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
private final Context mContext;
private NotificationPresenter mPresenter;
@@ -121,7 +125,9 @@ public class NotificationViewHierarchyManager implements DynamicPrivacyControlle
ForegroundServiceSectionController fgsSectionController,
DynamicChildBindController dynamicChildBindController,
LowPriorityInflationHelper lowPriorityInflationHelper,
AssistantFeedbackController assistantFeedbackController) {
AssistantFeedbackController assistantFeedbackController,
KeyguardUpdateMonitor keyguardUpdateMonitor,
KeyguardStateController keyguardStateController) {
mContext = context;
mHandler = mainHandler;
mFeatureFlags = featureFlags;
@@ -140,6 +146,8 @@ public class NotificationViewHierarchyManager implements DynamicPrivacyControlle
mDynamicChildBindController = dynamicChildBindController;
mLowPriorityInflationHelper = lowPriorityInflationHelper;
mAssistantFeedbackController = assistantFeedbackController;
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
mKeyguardStateController = keyguardStateController;
}
public void setUpWithPresenter(NotificationPresenter presenter,
@@ -163,6 +171,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();
@@ -181,7 +194,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;

View File

@@ -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;
@@ -69,6 +70,7 @@ import com.android.systemui.statusbar.phone.StatusBarIconControllerImpl;
import com.android.systemui.statusbar.phone.StatusBarRemoteInputCallback;
import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController;
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;
@@ -201,7 +203,9 @@ public interface StatusBarDependenciesModule {
ForegroundServiceSectionController fgsSectionController,
DynamicChildBindController dynamicChildBindController,
LowPriorityInflationHelper lowPriorityInflationHelper,
AssistantFeedbackController assistantFeedbackController) {
AssistantFeedbackController assistantFeedbackController,
KeyguardUpdateMonitor keyguardUpdateMonitor,
KeyguardStateController keyguardStateController) {
return new NotificationViewHierarchyManager(
context,
mainHandler,
@@ -217,7 +221,9 @@ public interface StatusBarDependenciesModule {
fgsSectionController,
dynamicChildBindController,
lowPriorityInflationHelper,
assistantFeedbackController);
assistantFeedbackController,
keyguardUpdateMonitor,
keyguardStateController);
}
/**

View File

@@ -157,6 +157,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);

View File

@@ -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 &&

View File

@@ -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;
@@ -54,6 +55,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;
@@ -118,7 +120,9 @@ public class NotificationViewHierarchyManagerTest extends SysuiTestCase {
mock(ForegroundServiceSectionController.class),
mock(DynamicChildBindController.class),
mock(LowPriorityInflationHelper.class),
mock(AssistantFeedbackController.class));
mock(AssistantFeedbackController.class),
mock(KeyguardUpdateMonitor.class),
mock(KeyguardStateController.class));
mViewHierarchyManager.setUpWithPresenter(mPresenter, mListContainer);
}

View File

@@ -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)