From 03f5e4c4a76b1301f8668927bebfff90de25c7db Mon Sep 17 00:00:00 2001 From: Daniel Sandler Date: Tue, 17 May 2022 22:08:22 +0000 Subject: [PATCH] Revert "Don't show "Clear All" w/ redacted notifs" Revert "Update NotifLockscreenUserMgrGoogle constructor" Revert "Update ArcNotifLockscreenUserMgr constructor" Revert submission 17183599-pipeline-clearall Reason for revert: b/232727914 b/232587284 Reverted Changes: I84e9f909e:Update ArcNotifLockscreenUserMgr constructor Ic88341de0:Update NotifLockscreenUserMgrGoogle constructor Ibc66576d2:Don't show "Clear All" w/ redacted notifs Change-Id: Ie7469cb568471f4739a8c591ccc6d669895a8315 Merged-In: Ie7469cb568471f4739a8c591ccc6d669895a8315 --- .../statusbar/HeadsUpStatusBarView.java | 27 +- .../LockscreenShadeTransitionController.kt | 25 +- .../NotificationLockscreenUserManager.java | 13 +- ...NotificationLockscreenUserManagerImpl.java | 145 +++++----- .../NotificationViewHierarchyManager.java | 28 +- .../DynamicPrivacyController.java | 6 +- .../collection/NotificationEntry.java | 51 ++-- .../coordinator/NotifCoordinators.kt | 2 + .../coordinator/RankingCoordinator.java | 147 ++++++---- .../SensitiveContentCoordinator.kt | 124 ++++++++ .../coordinator/StackCoordinator.kt | 13 +- .../coordinator/dagger/CoordinatorsModule.kt | 2 + .../inflation/NotificationRowBinderImpl.java | 13 +- .../collection/render/NotifStackController.kt | 14 +- .../NotificationSectionHeadersModule.kt | 2 +- .../notification/icon/IconManager.kt | 31 +- .../row/ExpandableNotificationRow.java | 47 +-- .../ExpandableNotificationRowController.java | 19 +- .../row/NotificationContentView.java | 36 +-- .../row/RowContentBindParams.java | 3 +- ...tificationStackScrollLayoutController.java | 63 +--- .../phone/HeadsUpAppearanceController.java | 38 +-- .../NotificationPanelViewController.java | 5 + .../phone/StatusBarNotificationPresenter.java | 6 +- ...LockscreenShadeTransitionControllerTest.kt | 8 +- ...NotificationLockscreenUserManagerTest.java | 36 +-- .../DynamicPrivacyControllerTest.java | 4 +- .../coordinator/RankingCoordinatorTest.java | 65 +++++ .../SensitiveContentCoordinatorTest.kt | 268 ++++++++++++++++++ .../coordinator/StackCoordinatorTest.kt | 33 +-- .../notification/icon/IconManagerTest.kt | 63 ++-- .../row/ExpandableNotificationRowTest.java | 8 +- ...NotificationEntryManagerInflationTest.java | 6 +- .../row/NotificationTestHelper.java | 4 +- .../HeadsUpAppearanceControllerTest.java | 18 +- 35 files changed, 803 insertions(+), 570 deletions(-) create mode 100644 packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinator.kt create mode 100644 packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinatorTest.kt diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/HeadsUpStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/HeadsUpStatusBarView.java index e44d334c776d0..4d933d9ad21ee 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/HeadsUpStatusBarView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/HeadsUpStatusBarView.java @@ -29,6 +29,7 @@ import com.android.keyguard.AlphaOptimizedLinearLayout; import com.android.systemui.R; import com.android.systemui.plugins.DarkIconDispatcher; import com.android.systemui.statusbar.notification.collection.NotificationEntry; +import com.android.systemui.statusbar.notification.collection.NotificationEntry.OnSensitivityChangedListener; import java.util.ArrayList; @@ -48,7 +49,6 @@ public class HeadsUpStatusBarView extends AlphaOptimizedLinearLayout { private TextView mTextView; private NotificationEntry mShowingEntry; private Runnable mOnDrawingRectChangedListener; - private boolean mRedactSensitiveContent; public HeadsUpStatusBarView(Context context) { this(context, null); @@ -111,28 +111,29 @@ public class HeadsUpStatusBarView extends AlphaOptimizedLinearLayout { } public void setEntry(NotificationEntry entry) { + if (mShowingEntry != null) { + mShowingEntry.removeOnSensitivityChangedListener(mOnSensitivityChangedListener); + } mShowingEntry = entry; + if (mShowingEntry != null) { CharSequence text = entry.headsUpStatusBarText; - if (mRedactSensitiveContent && entry.hasSensitiveContents()) { + if (entry.isSensitive()) { text = entry.headsUpStatusBarTextPublic; } mTextView.setText(text); + mShowingEntry.addOnSensitivityChangedListener(mOnSensitivityChangedListener); } } - public void setRedactSensitiveContent(boolean redactSensitiveContent) { - if (mRedactSensitiveContent == redactSensitiveContent) { - return; + private final OnSensitivityChangedListener mOnSensitivityChangedListener = entry -> { + if (entry != mShowingEntry) { + throw new IllegalStateException("Got a sensitivity change for " + entry + + " but mShowingEntry is " + mShowingEntry); } - mRedactSensitiveContent = redactSensitiveContent; - if (mShowingEntry != null && mShowingEntry.hasSensitiveContents()) { - mTextView.setText( - mRedactSensitiveContent - ? mShowingEntry.headsUpStatusBarTextPublic - : mShowingEntry.headsUpStatusBarText); - } - } + // Update the text + setEntry(entry); + }; @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt index cbe722b6f82fd..c1ea6bf7cec87 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt @@ -386,7 +386,7 @@ class LockscreenShadeTransitionController @Inject constructor( } if (view is ExpandableNotificationRow) { // Only drag down on sensitive views, otherwise the ExpandHelper will take this - return lockScreenUserManager.notifNeedsRedactionInPublic(view.entry) + return view.entry.isSensitive } } return false @@ -552,8 +552,7 @@ class LockscreenShadeTransitionController @Inject constructor( logger.logShadeDisabledOnGoToLockedShade() return } - val currentUser = lockScreenUserManager.currentUserId - var userId: Int = currentUser + var userId: Int = lockScreenUserManager.getCurrentUserId() var entry: NotificationEntry? = null if (expandView is ExpandableNotificationRow) { entry = expandView.entry @@ -563,18 +562,12 @@ class LockscreenShadeTransitionController @Inject constructor( entry.setGroupExpansionChanging(true) userId = entry.sbn.userId } - val fullShadeNeedsBouncer = when { - // No bouncer necessary if we're bypassing - keyguardBypassController.bypassEnabled -> false - // Redacted notificationss are present, bouncer should be shown before un-redacting in - // the full shade - lockScreenUserManager.sensitiveNotifsNeedRedactionInPublic(currentUser) -> true - // Notifications are hidden in public, bouncer should be shown before showing them in - // the full shade - !lockScreenUserManager.shouldShowLockscreenNotifications() -> true - // Bouncer is being enforced, so we need to show it - falsingCollector.shouldEnforceBouncer() -> true - else -> false + var fullShadeNeedsBouncer = (!lockScreenUserManager.userAllowsPrivateNotificationsInPublic( + lockScreenUserManager.getCurrentUserId()) || + !lockScreenUserManager.shouldShowLockscreenNotifications() || + falsingCollector.shouldEnforceBouncer()) + if (keyguardBypassController.bypassEnabled) { + fullShadeNeedsBouncer = false } if (lockScreenUserManager.isLockscreenPublicMode(userId) && fullShadeNeedsBouncer) { statusBarStateController.setLeaveOpenOnKeyguardHide(true) @@ -918,4 +911,4 @@ class DragDownHelper( host.getLocationOnScreen(temp2) return expandCallback.getChildAtRawPosition(x + temp2[0], y + temp2[1]) } -} +} \ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManager.java index 512230ee54a6a..21a70d59419ef 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManager.java @@ -71,22 +71,17 @@ public interface NotificationLockscreenUserManager { boolean shouldHideNotifications(String key); boolean shouldShowOnKeyguard(NotificationEntry entry); - void addOnNeedsRedactionInPublicChangedListener(Runnable listener); - - void removeOnNeedsRedactionInPublicChangedListener(Runnable listener); - boolean isAnyProfilePublicMode(); void updatePublicMode(); - /** Does this notification require redaction if it is displayed when the device is public? */ - boolean notifNeedsRedactionInPublic(NotificationEntry entry); + boolean needsRedaction(NotificationEntry entry); /** - * Do all sensitive notifications belonging to the given user require redaction when they are - * displayed in public? + * Has the given user chosen to allow their private (full) notifications to be shown even + * when the lockscreen is in "public" (secure & locked) mode? */ - boolean sensitiveNotifsNeedRedactionInPublic(int userId); + boolean userAllowsPrivateNotificationsInPublic(int currentUserId); /** * Has the given user chosen to allow notifications to be shown even when the lockscreen is in diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java index 0394724dd5972..ecbe32f1b7378 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java @@ -24,6 +24,7 @@ import static com.android.systemui.statusbar.notification.stack.NotificationPrio import android.app.ActivityManager; import android.app.KeyguardManager; +import android.app.Notification; import android.app.NotificationManager; import android.app.admin.DevicePolicyManager; import android.content.BroadcastReceiver; @@ -44,6 +45,7 @@ import android.util.SparseBooleanArray; import com.android.internal.statusbar.NotificationVisibility; import com.android.internal.widget.LockPatternUtils; import com.android.keyguard.KeyguardUpdateMonitor; +import com.android.systemui.Dependency; import com.android.systemui.Dumpable; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.dagger.SysUISingleton; @@ -58,7 +60,6 @@ import com.android.systemui.statusbar.notification.collection.notifcollection.Co import com.android.systemui.statusbar.notification.collection.render.NotificationVisibilityProvider; 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.settings.SecureSettings; import java.io.PrintWriter; @@ -84,12 +85,13 @@ public class NotificationLockscreenUserManagerImpl implements private final DeviceProvisionedController mDeviceProvisionedController; private final KeyguardStateController mKeyguardStateController; private final SecureSettings mSecureSettings; - private final KeyguardUpdateMonitor mKeyguardUpdateMonitor; - private final Lazy mOverviewProxyService; private final Object mLock = new Object(); + + // Lazy + private NotificationEntryManager mEntryManager; + private final Lazy mVisibilityProviderLazy; private final Lazy mCommonNotifCollectionLazy; - private final Lazy mEntryManagerLazy; private final DevicePolicyManager mDevicePolicyManager; private final SparseBooleanArray mLockscreenPublicMode = new SparseBooleanArray(); private final SparseBooleanArray mUsersWithSeparateWorkChallenge = new SparseBooleanArray(); @@ -101,14 +103,13 @@ public class NotificationLockscreenUserManagerImpl implements private final List mListeners = new ArrayList<>(); private final BroadcastDispatcher mBroadcastDispatcher; private final NotificationClickNotifier mClickNotifier; - private final LockPatternUtils mLockPatternUtils; - private final List mKeyguardSuppressors = new ArrayList<>(); - protected final Context mContext; - private final Handler mMainHandler; - protected final SparseArray mCurrentProfiles = new SparseArray<>(); - protected final SparseArray mCurrentManagedProfiles = new SparseArray<>(); - private final ListenerSet mOnSensitiveContentRedactionChangeListeners = - new ListenerSet<>(); + + private boolean mShowLockscreenNotifications; + private boolean mAllowLockscreenRemoteInput; + private LockPatternUtils mLockPatternUtils; + protected KeyguardManager mKeyguardManager; + private int mState = StatusBarState.SHADE; + private List mKeyguardSuppressors = new ArrayList<>(); protected final BroadcastReceiver mAllUsersReceiver = new BroadcastReceiver() { @Override @@ -119,11 +120,7 @@ public class NotificationLockscreenUserManagerImpl implements isCurrentProfile(getSendingUserId())) { mUsersAllowingPrivateNotifications.clear(); updateLockscreenNotificationSetting(); - for (Runnable listener : mOnSensitiveContentRedactionChangeListeners) { - listener.run(); - } - mEntryManagerLazy.get() - .updateNotifications("ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED"); + getEntryManager().updateNotifications("ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED"); } } }; @@ -145,7 +142,7 @@ public class NotificationLockscreenUserManagerImpl implements // The filtering needs to happen before the update call below in order to // make sure // the presenter has the updated notifications from the new user - mEntryManagerLazy.get().reapplyFilterAndSort("user switched"); + getEntryManager().reapplyFilterAndSort("user switched"); mPresenter.onUserSwitched(mCurrentUserId); for (UserChangedListener listener : mListeners) { @@ -168,7 +165,7 @@ public class NotificationLockscreenUserManagerImpl implements break; case Intent.ACTION_USER_UNLOCKED: // Start the overview connection to the launcher service - mOverviewProxyService.get().startConnectionToCurrentUser(); + Dependency.get(OverviewProxyService.class).startConnectionToCurrentUser(); break; case NOTIFICATION_UNLOCKED_BY_WORK_CHALLENGE_ACTION: final IntentSender intentSender = intent.getParcelableExtra( @@ -191,26 +188,28 @@ public class NotificationLockscreenUserManagerImpl implements } }; - // Late-init + protected final Context mContext; + private final Handler mMainHandler; + protected final SparseArray mCurrentProfiles = new SparseArray<>(); + protected final SparseArray mCurrentManagedProfiles = new SparseArray<>(); + + protected int mCurrentUserId = 0; protected NotificationPresenter mPresenter; protected ContentObserver mLockscreenSettingsObserver; protected ContentObserver mSettingsObserver; - protected KeyguardManager mKeyguardManager; - - protected int mCurrentUserId = 0; - private int mState = StatusBarState.SHADE; private boolean mHideSilentNotificationsOnLockscreen; - private boolean mShowLockscreenNotifications; - private boolean mAllowLockscreenRemoteInput; + + private NotificationEntryManager getEntryManager() { + if (mEntryManager == null) { + mEntryManager = Dependency.get(NotificationEntryManager.class); + } + return mEntryManager; + } @Inject - public NotificationLockscreenUserManagerImpl( - Context context, + public NotificationLockscreenUserManagerImpl(Context context, BroadcastDispatcher broadcastDispatcher, DevicePolicyManager devicePolicyManager, - KeyguardUpdateMonitor keyguardUpdateMonitor, - Lazy notificationEntryManagerLazy, - Lazy overviewProxyServiceLazy, UserManager userManager, Lazy visibilityProviderLazy, Lazy commonNotifCollectionLazy, @@ -226,11 +225,9 @@ public class NotificationLockscreenUserManagerImpl implements mMainHandler = mainHandler; mDevicePolicyManager = devicePolicyManager; mUserManager = userManager; - mOverviewProxyService = overviewProxyServiceLazy; mCurrentUserId = ActivityManager.getCurrentUser(); mVisibilityProviderLazy = visibilityProviderLazy; mCommonNotifCollectionLazy = commonNotifCollectionLazy; - mEntryManagerLazy = notificationEntryManagerLazy; mClickNotifier = clickNotifier; statusBarStateController.addCallback(this); mLockPatternUtils = new LockPatternUtils(context); @@ -239,12 +236,10 @@ public class NotificationLockscreenUserManagerImpl implements mDeviceProvisionedController = deviceProvisionedController; mSecureSettings = secureSettings; mKeyguardStateController = keyguardStateController; - mKeyguardUpdateMonitor = keyguardUpdateMonitor; dumpManager.registerDumpable(this); } - @Override public void setUpWithPresenter(NotificationPresenter presenter) { mPresenter = presenter; @@ -257,10 +252,7 @@ public class NotificationLockscreenUserManagerImpl implements mUsersAllowingNotifications.clear(); // ... and refresh all the notifications updateLockscreenNotificationSetting(); - for (Runnable listener : mOnSensitiveContentRedactionChangeListeners) { - listener.run(); - } - mEntryManagerLazy.get().updateNotifications("LOCK_SCREEN_SHOW_NOTIFICATIONS," + getEntryManager().updateNotifications("LOCK_SCREEN_SHOW_NOTIFICATIONS," + " or LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS change"); } }; @@ -270,7 +262,7 @@ public class NotificationLockscreenUserManagerImpl implements public void onChange(boolean selfChange) { updateLockscreenNotificationSetting(); if (mDeviceProvisionedController.isDeviceProvisioned()) { - mEntryManagerLazy.get().updateNotifications("LOCK_SCREEN_ALLOW_REMOTE_INPUT" + getEntryManager().updateNotifications("LOCK_SCREEN_ALLOW_REMOTE_INPUT" + " or ZEN_MODE change"); } } @@ -330,17 +322,14 @@ public class NotificationLockscreenUserManagerImpl implements mSettingsObserver.onChange(false); // set up } - @Override public boolean shouldShowLockscreenNotifications() { return mShowLockscreenNotifications; } - @Override public boolean shouldAllowLockscreenRemoteInput() { return mAllowLockscreenRemoteInput; } - @Override public boolean isCurrentProfile(int userId) { synchronized (mLock) { return userId == UserHandle.USER_ALL || mCurrentProfiles.get(userId) != null; @@ -355,7 +344,7 @@ public class NotificationLockscreenUserManagerImpl implements if (userId == UserHandle.USER_ALL) { userId = mCurrentUserId; } - boolean inLockdown = mKeyguardUpdateMonitor.isUserInLockdown(userId); + boolean inLockdown = Dependency.get(KeyguardUpdateMonitor.class).isUserInLockdown(userId); mUsersInLockdownLatestResult.put(userId, inLockdown); return inLockdown; } @@ -364,7 +353,6 @@ public class NotificationLockscreenUserManagerImpl implements * Returns true if we're on a secure lockscreen and the user wants to hide notification data. * If so, notifications should be hidden. */ - @Override public boolean shouldHideNotifications(int userId) { boolean hide = isLockscreenPublicMode(userId) && !userAllowsNotificationsInPublic(userId) || (userId != mCurrentUserId && shouldHideNotifications(mCurrentUserId)) @@ -377,7 +365,6 @@ public class NotificationLockscreenUserManagerImpl implements * Returns true if we're on a secure lockscreen and the user wants to hide notifications via * package-specific override. */ - @Override public boolean shouldHideNotifications(String key) { if (mCommonNotifCollectionLazy.get() == null) { Log.wtf(TAG, "mCommonNotifCollectionLazy was null!", new Throwable()); @@ -388,7 +375,6 @@ public class NotificationLockscreenUserManagerImpl implements && visibleEntry.getRanking().getLockscreenVisibilityOverride() == VISIBILITY_SECRET; } - @Override public boolean shouldShowOnKeyguard(NotificationEntry entry) { if (mCommonNotifCollectionLazy.get() == null) { Log.wtf(TAG, "mCommonNotifCollectionLazy was null!", new Throwable()); @@ -411,6 +397,14 @@ public class NotificationLockscreenUserManagerImpl implements return mShowLockscreenNotifications && exceedsPriorityThreshold; } + private void setShowLockscreenNotifications(boolean show) { + mShowLockscreenNotifications = show; + } + + private void setLockscreenAllowRemoteInput(boolean allowLockscreenRemoteInput) { + mAllowLockscreenRemoteInput = allowLockscreenRemoteInput; + } + protected void updateLockscreenNotificationSetting() { final boolean show = mSecureSettings.getIntForUser( Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, @@ -424,7 +418,7 @@ public class NotificationLockscreenUserManagerImpl implements mHideSilentNotificationsOnLockscreen = mSecureSettings.getIntForUser( Settings.Secure.LOCK_SCREEN_SHOW_SILENT_NOTIFICATIONS, 1, mCurrentUserId) == 0; - mShowLockscreenNotifications = show && allowedByDpm; + setShowLockscreenNotifications(show && allowedByDpm); if (ENABLE_LOCK_SCREEN_ALLOW_REMOTE_INPUT) { final boolean remoteInput = mSecureSettings.getIntForUser( @@ -434,9 +428,9 @@ public class NotificationLockscreenUserManagerImpl implements final boolean remoteInputDpm = (dpmFlags & DevicePolicyManager.KEYGUARD_DISABLE_REMOTE_INPUT) == 0; - mAllowLockscreenRemoteInput = remoteInput && remoteInputDpm; + setLockscreenAllowRemoteInput(remoteInput && remoteInputDpm); } else { - mAllowLockscreenRemoteInput = false; + setLockscreenAllowRemoteInput(false); } } @@ -444,7 +438,7 @@ public class NotificationLockscreenUserManagerImpl implements * Has the given user chosen to allow their private (full) notifications to be shown even * when the lockscreen is in "public" (secure & locked) mode? */ - protected boolean userAllowsPrivateNotificationsInPublic(int userHandle) { + public boolean userAllowsPrivateNotificationsInPublic(int userHandle) { if (userHandle == UserHandle.USER_ALL) { return true; } @@ -489,12 +483,10 @@ public class NotificationLockscreenUserManagerImpl implements /** * Save the current "public" (locked and secure) state of the lockscreen. */ - @Override public void setLockscreenPublicMode(boolean publicMode, int userId) { mLockscreenPublicMode.put(userId, publicMode); } - @Override public boolean isLockscreenPublicMode(int userId) { if (userId == UserHandle.USER_ALL) { return mLockscreenPublicMode.get(mCurrentUserId, false); @@ -511,7 +503,6 @@ public class NotificationLockscreenUserManagerImpl implements * Has the given user chosen to allow notifications to be shown even when the lockscreen is in * "public" (secure & locked) mode? */ - @Override public boolean userAllowsNotificationsInPublic(int userHandle) { if (isCurrentProfile(userHandle) && userHandle != mCurrentUserId) { return true; @@ -532,37 +523,36 @@ public class NotificationLockscreenUserManagerImpl implements } /** @return true if the entry needs redaction when on the lockscreen. */ - @Override - public boolean notifNeedsRedactionInPublic(NotificationEntry ent) { + public boolean needsRedaction(NotificationEntry ent) { int userId = ent.getSbn().getUserId(); - return ent.hasSensitiveContents() && sensitiveNotifsNeedRedactionInPublic(userId); - } - @Override - public boolean sensitiveNotifsNeedRedactionInPublic(int userId) { boolean isCurrentUserRedactingNotifs = !userAllowsPrivateNotificationsInPublic(mCurrentUserId); - if (userId == mCurrentUserId) { - return isCurrentUserRedactingNotifs; - } - boolean isNotifForManagedProfile = mCurrentManagedProfiles.contains(userId); boolean isNotifUserRedacted = !userAllowsPrivateNotificationsInPublic(userId); // redact notifications if the current user is redacting notifications; however if the // notification is associated with a managed profile, we rely on the managed profile // setting to determine whether to redact it - return (!isNotifForManagedProfile && isCurrentUserRedactingNotifs) || isNotifUserRedacted; + boolean isNotifRedacted = (!isNotifForManagedProfile && isCurrentUserRedactingNotifs) + || isNotifUserRedacted; + + boolean notificationRequestsRedaction = + ent.getSbn().getNotification().visibility == Notification.VISIBILITY_PRIVATE; + boolean userForcesRedaction = packageHasVisibilityOverride(ent.getSbn().getKey()); + + return userForcesRedaction || notificationRequestsRedaction && isNotifRedacted; } - @Override - public void addOnNeedsRedactionInPublicChangedListener(Runnable listener) { - mOnSensitiveContentRedactionChangeListeners.addIfAbsent(listener); - } - - @Override - public void removeOnNeedsRedactionInPublicChangedListener(Runnable listener) { - mOnSensitiveContentRedactionChangeListeners.remove(listener); + private boolean packageHasVisibilityOverride(String key) { + if (mCommonNotifCollectionLazy.get() == null) { + Log.wtf(TAG, "mEntryManager was null!", new Throwable()); + return true; + } + NotificationEntry entry = mCommonNotifCollectionLazy.get().getEntry(key); + return entry != null + && entry.getRanking().getLockscreenVisibilityOverride() + == Notification.VISIBILITY_PRIVATE; } private void updateCurrentProfilesCache() { @@ -582,16 +572,12 @@ public class NotificationLockscreenUserManagerImpl implements for (UserChangedListener listener : mListeners) { listener.onCurrentProfilesChanged(mCurrentProfiles); } - for (Runnable listener : mOnSensitiveContentRedactionChangeListeners) { - listener.run(); - } }); } /** * If any of the profiles are in public mode. */ - @Override public boolean isAnyProfilePublicMode() { synchronized (mLock) { for (int i = mCurrentProfiles.size() - 1; i >= 0; i--) { @@ -620,12 +606,10 @@ public class NotificationLockscreenUserManagerImpl implements /** * Returns the current user id. This can change if the user is switched. */ - @Override public int getCurrentUserId() { return mCurrentUserId; } - @Override public SparseArray getCurrentProfiles() { return mCurrentProfiles; } @@ -666,8 +650,7 @@ public class NotificationLockscreenUserManagerImpl implements setLockscreenPublicMode(isProfilePublic, userId); mUsersWithSeparateWorkChallenge.put(userId, needsSeparateChallenge); } - mEntryManagerLazy.get() - .updateNotifications("NotificationLockscreenUserManager.updatePublicMode"); + getEntryManager().updateNotifications("NotificationLockscreenUserManager.updatePublicMode"); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java index 30cb09d56f172..054543c7d2b18 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java @@ -53,7 +53,6 @@ import com.android.wm.shell.bubbles.Bubbles; import java.util.ArrayList; import java.util.HashMap; -import java.util.HashSet; import java.util.List; import java.util.Optional; import java.util.Stack; @@ -208,9 +207,12 @@ public class NotificationViewHierarchyManager implements DynamicPrivacyControlle || !mLockscreenUserManager.needsSeparateWorkChallenge(userId))) { userPublic = false; } - boolean needsRedaction = mLockscreenUserManager.notifNeedsRedactionInPublic(ent); + boolean needsRedaction = mLockscreenUserManager.needsRedaction(ent); boolean sensitive = userPublic && needsRedaction; - ent.getRow().setSensitive(sensitive); + boolean deviceSensitive = devicePublic + && !mLockscreenUserManager.userAllowsPrivateNotificationsInPublic( + currentUserId); + ent.setSensitive(sensitive, deviceSensitive); ent.getRow().setNeedsRedaction(needsRedaction); mLowPriorityInflationHelper.recheckLowPriorityViewAndInflate(ent, ent.getRow()); boolean isChildInGroup = mGroupManager.isChildInGroup(ent); @@ -363,8 +365,6 @@ public class NotificationViewHierarchyManager implements DynamicPrivacyControlle boolean hasClearableAlertingNotifs = false; boolean hasNonClearableSilentNotifs = false; boolean hasClearableSilentNotifs = false; - HashSet clearableAlertingSensitiveNotifUsers = new HashSet<>(); - HashSet clearableSilentSensitiveNotifUsers = new HashSet<>(); final int childCount = mListContainer.getContainerChildCount(); int visibleTopLevelEntries = 0; for (int i = 0; i < childCount; i++) { @@ -376,11 +376,10 @@ public class NotificationViewHierarchyManager implements DynamicPrivacyControlle continue; } final ExpandableNotificationRow row = (ExpandableNotificationRow) child; - NotificationEntry entry = row.getEntry(); - boolean isSilent = entry.getBucket() == BUCKET_SILENT; + boolean isSilent = row.getEntry().getBucket() == BUCKET_SILENT; // NOTE: NotificationEntry.isClearable() will internally check group children to ensure // the group itself definitively clearable. - boolean isClearable = entry.isClearable(); + boolean isClearable = row.getEntry().isClearable(); visibleTopLevelEntries++; if (isSilent) { if (isClearable) { @@ -395,24 +394,13 @@ public class NotificationViewHierarchyManager implements DynamicPrivacyControlle hasNonClearableAlertingNotifs = true; } } - if (isClearable && entry.hasSensitiveContents()) { - int userId = entry.getSbn().getUserId(); - if (isSilent) { - clearableSilentSensitiveNotifUsers.add(userId); - } else { - clearableAlertingSensitiveNotifUsers.add(userId); - } - } } mStackController.setNotifStats(new NotifStats( visibleTopLevelEntries /* numActiveNotifs */, hasNonClearableAlertingNotifs /* hasNonClearableAlertingNotifs */, hasClearableAlertingNotifs /* hasClearableAlertingNotifs */, hasNonClearableSilentNotifs /* hasNonClearableSilentNotifs */, - hasClearableSilentNotifs /* hasClearableSilentNotifs */, - clearableAlertingSensitiveNotifUsers /* clearableAlertingSensitiveNotifUsers */, - clearableSilentSensitiveNotifUsers /* clearableSilentSensitiveNotifUsers */ - + hasClearableSilentNotifs /* hasClearableSilentNotifs */ )); Trace.endSection(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/DynamicPrivacyController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/DynamicPrivacyController.java index d16e9e5d7faf0..a0ccd5726c755 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/DynamicPrivacyController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/DynamicPrivacyController.java @@ -80,7 +80,7 @@ public class DynamicPrivacyController implements KeyguardStateController.Callbac @VisibleForTesting boolean isDynamicPrivacyEnabled() { - return mLockscreenUserManager.sensitiveNotifsNeedRedactionInPublic( + return !mLockscreenUserManager.userAllowsPrivateNotificationsInPublic( mLockscreenUserManager.getCurrentUserId()); } @@ -95,10 +95,6 @@ public class DynamicPrivacyController implements KeyguardStateController.Callbac mListeners.add(listener); } - public void removeListener(Listener listener) { - mListeners.remove(listener); - } - /** * Is the notification shade currently in a locked down mode where it's fully showing but the * contents aren't revealed yet? diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java index e3c39ddad1450..4fc347a09292c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java @@ -169,6 +169,9 @@ public final class NotificationEntry extends ListEntry { */ private boolean hasSentReply; + private boolean mSensitive = true; + private List mOnSensitivityChangedListeners = new ArrayList<>(); + private boolean mAutoHeadsUp; private boolean mPulseSupressed; private int mBucket = BUCKET_ALERTING; @@ -864,29 +867,33 @@ public final class NotificationEntry extends ListEntry { } /** - * Returns the visibility of this notification on the lockscreen, taking into account both the - * notification's defined visibility, as well as the visibility override as determined by the - * device policy. + * Set this notification to be sensitive. + * + * @param sensitive true if the content of this notification is sensitive right now + * @param deviceSensitive true if the device in general is sensitive right now */ - public int getLockscreenVisibility() { - int setting = mRanking.getLockscreenVisibilityOverride(); - if (setting == Ranking.VISIBILITY_NO_OVERRIDE) { - setting = mSbn.getNotification().visibility; + public void setSensitive(boolean sensitive, boolean deviceSensitive) { + getRow().setSensitive(sensitive, deviceSensitive); + if (sensitive != mSensitive) { + mSensitive = sensitive; + for (int i = 0; i < mOnSensitivityChangedListeners.size(); i++) { + mOnSensitivityChangedListeners.get(i).onSensitivityChanged(this); + } } - return setting; } - /** - * Does this notification contain sensitive content? If the user's settings specify, then this - * content would need to be redacted when the device this public. - * - * NOTE: If the notification's visibility setting is VISIBILITY_SECRET, then this will return - * false; SECRET notifications are omitted entirely when the device is public, so effectively - * the contents of the notification are not sensitive whenever the notification is actually - * visible. - */ - public boolean hasSensitiveContents() { - return getLockscreenVisibility() == Notification.VISIBILITY_PRIVATE; + public boolean isSensitive() { + return mSensitive; + } + + /** Add a listener to be notified when the entry's sensitivity changes. */ + public void addOnSensitivityChangedListener(OnSensitivityChangedListener listener) { + mOnSensitivityChangedListeners.add(listener); + } + + /** Remove a listener that was registered above. */ + public void removeOnSensitivityChangedListener(OnSensitivityChangedListener listener) { + mOnSensitivityChangedListeners.remove(listener); } public boolean isPulseSuppressed() { @@ -947,6 +954,12 @@ public final class NotificationEntry extends ListEntry { } } + /** Listener interface for {@link #addOnSensitivityChangedListener} */ + public interface OnSensitivityChangedListener { + /** Called when the sensitivity changes */ + void onSensitivityChanged(@NonNull NotificationEntry entry); + } + /** @see #getDismissState() */ public enum DismissState { /** User has not dismissed this notif or its parent */ diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.kt index 0b3a0dc9dd580..359e2028d9f3f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.kt @@ -56,6 +56,7 @@ class NotifCoordinatorsImpl @Inject constructor( smartspaceDedupingCoordinator: SmartspaceDedupingCoordinator, viewConfigCoordinator: ViewConfigCoordinator, visualStabilityCoordinator: VisualStabilityCoordinator, + sensitiveContentCoordinator: SensitiveContentCoordinator, ) : NotifCoordinators { private val mCoordinators: MutableList = ArrayList() @@ -92,6 +93,7 @@ class NotifCoordinatorsImpl @Inject constructor( mCoordinators.add(shadeEventCoordinator) mCoordinators.add(viewConfigCoordinator) mCoordinators.add(visualStabilityCoordinator) + mCoordinators.add(sensitiveContentCoordinator) if (notifPipelineFlags.isSmartspaceDedupingEnabled()) { mCoordinators.add(smartspaceDedupingCoordinator) } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java index 56484010c2134..57fd1975e13ac 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java @@ -16,6 +16,7 @@ package com.android.systemui.statusbar.notification.collection.coordinator; +import android.annotation.NonNull; import android.annotation.Nullable; import com.android.systemui.plugins.statusbar.StatusBarStateController; @@ -28,11 +29,13 @@ import com.android.systemui.statusbar.notification.collection.listbuilder.plugga import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner; import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider; import com.android.systemui.statusbar.notification.collection.render.NodeController; +import com.android.systemui.statusbar.notification.collection.render.SectionHeaderController; import com.android.systemui.statusbar.notification.dagger.AlertingHeader; import com.android.systemui.statusbar.notification.dagger.SilentHeader; import com.android.systemui.statusbar.notification.stack.NotificationPriorityBucketKt; import java.util.Collections; +import java.util.List; import javax.inject.Inject; @@ -50,10 +53,10 @@ public class RankingCoordinator implements Coordinator { private final HighPriorityProvider mHighPriorityProvider; private final SectionClassifier mSectionClassifier; private final NodeController mSilentNodeController; + private final SectionHeaderController mSilentHeaderController; private final NodeController mAlertingHeaderController; - private final AlertingNotifSectioner mAlertingNotifSectioner = new AlertingNotifSectioner(); - private final SilentNotifSectioner mSilentNotifSectioner = new SilentNotifSectioner(); - private final MinimizedNotifSectioner mMinimizedNotifSectioner = new MinimizedNotifSectioner(); + private boolean mHasSilentEntries; + private boolean mHasMinimizedEntries; @Inject public RankingCoordinator( @@ -61,12 +64,14 @@ public class RankingCoordinator implements Coordinator { HighPriorityProvider highPriorityProvider, SectionClassifier sectionClassifier, @AlertingHeader NodeController alertingHeaderController, + @SilentHeader SectionHeaderController silentHeaderController, @SilentHeader NodeController silentNodeController) { mStatusBarStateController = statusBarStateController; mHighPriorityProvider = highPriorityProvider; mSectionClassifier = sectionClassifier; mAlertingHeaderController = alertingHeaderController; mSilentNodeController = silentNodeController; + mSilentHeaderController = silentHeaderController; } @Override @@ -90,6 +95,82 @@ public class RankingCoordinator implements Coordinator { return mMinimizedNotifSectioner; } + private final NotifSectioner mAlertingNotifSectioner = new NotifSectioner("Alerting", + NotificationPriorityBucketKt.BUCKET_ALERTING) { + @Override + public boolean isInSection(ListEntry entry) { + return mHighPriorityProvider.isHighPriority(entry); + } + + @Nullable + @Override + public NodeController getHeaderNodeController() { + // TODO: remove SHOW_ALL_SECTIONS, this redundant method, and mAlertingHeaderController + if (SHOW_ALL_SECTIONS) { + return mAlertingHeaderController; + } + return null; + } + }; + + private final NotifSectioner mSilentNotifSectioner = new NotifSectioner("Silent", + NotificationPriorityBucketKt.BUCKET_SILENT) { + @Override + public boolean isInSection(ListEntry entry) { + return !mHighPriorityProvider.isHighPriority(entry) + && !entry.getRepresentativeEntry().isAmbient(); + } + + @Nullable + @Override + public NodeController getHeaderNodeController() { + return mSilentNodeController; + } + + @Nullable + @Override + public void onEntriesUpdated(@NonNull List entries) { + mHasSilentEntries = false; + for (int i = 0; i < entries.size(); i++) { + if (entries.get(i).getRepresentativeEntry().getSbn().isClearable()) { + mHasSilentEntries = true; + break; + } + } + mSilentHeaderController.setClearSectionEnabled( + mHasSilentEntries | mHasMinimizedEntries); + } + }; + + private final NotifSectioner mMinimizedNotifSectioner = new NotifSectioner("Minimized", + NotificationPriorityBucketKt.BUCKET_SILENT) { + @Override + public boolean isInSection(ListEntry entry) { + return !mHighPriorityProvider.isHighPriority(entry) + && entry.getRepresentativeEntry().isAmbient(); + } + + @Nullable + @Override + public NodeController getHeaderNodeController() { + return mSilentNodeController; + } + + @Nullable + @Override + public void onEntriesUpdated(@NonNull List entries) { + mHasMinimizedEntries = false; + for (int i = 0; i < entries.size(); i++) { + if (entries.get(i).getRepresentativeEntry().getSbn().isClearable()) { + mHasMinimizedEntries = true; + break; + } + } + mSilentHeaderController.setClearSectionEnabled( + mHasSilentEntries | mHasMinimizedEntries); + } + }; + /** * Checks whether to filter out the given notification based the notification's Ranking object. * NotifListBuilder invalidates the notification list each time the ranking is updated, @@ -121,64 +202,4 @@ public class RankingCoordinator implements Coordinator { mDndVisualEffectsFilter.invalidateList(); } }; - - private class AlertingNotifSectioner extends NotifSectioner { - - AlertingNotifSectioner() { - super("Alerting", NotificationPriorityBucketKt.BUCKET_ALERTING); - } - - @Override - public boolean isInSection(ListEntry entry) { - return mHighPriorityProvider.isHighPriority(entry); - } - - @Nullable - @Override - public NodeController getHeaderNodeController() { - // TODO: remove SHOW_ALL_SECTIONS, this redundant method, and mAlertingHeaderController - if (SHOW_ALL_SECTIONS) { - return mAlertingHeaderController; - } - return null; - } - } - - private class SilentNotifSectioner extends NotifSectioner { - - SilentNotifSectioner() { - super("Silent", NotificationPriorityBucketKt.BUCKET_SILENT); - } - - @Override - public boolean isInSection(ListEntry entry) { - return !mHighPriorityProvider.isHighPriority(entry) - && !entry.getRepresentativeEntry().isAmbient(); - } - - @Nullable - @Override - public NodeController getHeaderNodeController() { - return mSilentNodeController; - } - } - - private class MinimizedNotifSectioner extends NotifSectioner { - - MinimizedNotifSectioner() { - super("Minimized", NotificationPriorityBucketKt.BUCKET_SILENT); - } - - @Override - public boolean isInSection(ListEntry entry) { - return !mHighPriorityProvider.isHighPriority(entry) - && entry.getRepresentativeEntry().isAmbient(); - } - - @Nullable - @Override - public NodeController getHeaderNodeController() { - return mSilentNodeController; - } - } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinator.kt new file mode 100644 index 0000000000000..3f8a39f62dfb3 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinator.kt @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +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 +import com.android.systemui.statusbar.notification.collection.NotifPipeline +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.Binds +import dagger.Module +import javax.inject.Inject + +@Module(includes = [PrivateSensitiveContentCoordinatorModule::class]) +interface SensitiveContentCoordinatorModule + +@Module +private interface PrivateSensitiveContentCoordinatorModule { + @Binds + fun bindCoordinator(impl: SensitiveContentCoordinatorImpl): SensitiveContentCoordinator +} + +/** Coordinates re-inflation and post-processing of sensitive notification content. */ +interface SensitiveContentCoordinator : Coordinator + +@CoordinatorScope +private class SensitiveContentCoordinatorImpl @Inject constructor( + private val dynamicPrivacyController: DynamicPrivacyController, + private val lockscreenUserManager: NotificationLockscreenUserManager, + private val keyguardUpdateMonitor: KeyguardUpdateMonitor, + private val statusBarStateController: StatusBarStateController, + private val keyguardStateController: KeyguardStateController +) : Invalidator("SensitiveContentInvalidator"), + SensitiveContentCoordinator, + DynamicPrivacyController.Listener, + OnBeforeRenderListListener { + + override fun attach(pipeline: NotifPipeline) { + dynamicPrivacyController.addListener(this) + pipeline.addOnBeforeRenderListListener(this) + pipeline.addPreRenderInvalidator(this) + } + + override fun onDynamicPrivacyChanged(): Unit = invalidateList() + + override fun onBeforeRenderList(entries: List) { + 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 && + !lockscreenUserManager.userAllowsPrivateNotificationsInPublic(currentUserId) + val dynamicallyUnlocked = dynamicPrivacyController.isDynamicallyUnlocked + for (entry in extractAllRepresentativeEntries(entries).filter { it.rowExists() }) { + val notifUserId = entry.sbn.user.identifier + val userLockscreen = devicePublic || + lockscreenUserManager.isLockscreenPublicMode(notifUserId) + val userPublic = when { + // if we're not on the lockscreen, we're definitely private + !userLockscreen -> false + // we are on the lockscreen, so unless we're dynamically unlocked, we're + // definitely public + !dynamicallyUnlocked -> true + // we're dynamically unlocked, but check if the notification needs + // a separate challenge if it's from a work profile + else -> when (notifUserId) { + currentUserId -> false + UserHandle.USER_ALL -> false + else -> lockscreenUserManager.needsSeparateWorkChallenge(notifUserId) + } + } + val needsRedaction = lockscreenUserManager.needsRedaction(entry) + val isSensitive = userPublic && needsRedaction + entry.setSensitive(isSensitive, deviceSensitive) + } + } +} + +private fun extractAllRepresentativeEntries( + entries: List +): Sequence = + entries.asSequence().flatMap(::extractAllRepresentativeEntries) + +private fun extractAllRepresentativeEntries(listEntry: ListEntry): Sequence = + sequence { + listEntry.representativeEntry?.let { yield(it) } + if (listEntry is GroupEntry) { + yieldAll(extractAllRepresentativeEntries(listEntry.children)) + } + } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinator.kt index 2374e9c581779..1c96e8ceb27f9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinator.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinator.kt @@ -50,8 +50,6 @@ class StackCoordinator @Inject internal constructor( var hasClearableAlertingNotifs = false var hasNonClearableSilentNotifs = false var hasClearableSilentNotifs = false - val clearableAlertingSensitiveNotifUsers = mutableSetOf() - val clearableSilentSensitiveNotifUsers = mutableSetOf() entries.forEach { val section = checkNotNull(it.section) { "Null section for ${it.key}" } val entry = checkNotNull(it.representativeEntry) { "Null notif entry for ${it.key}" } @@ -65,22 +63,13 @@ class StackCoordinator @Inject internal constructor( !isSilent && isClearable -> hasClearableAlertingNotifs = true !isSilent && !isClearable -> hasNonClearableAlertingNotifs = true } - if (isClearable && entry.hasSensitiveContents()) { - if (isSilent) { - clearableSilentSensitiveNotifUsers.add(entry.sbn.userId) - } else { - clearableAlertingSensitiveNotifUsers.add(entry.sbn.userId) - } - } } return NotifStats( numActiveNotifs = entries.size, hasNonClearableAlertingNotifs = hasNonClearableAlertingNotifs, hasClearableAlertingNotifs = hasClearableAlertingNotifs, hasNonClearableSilentNotifs = hasNonClearableSilentNotifs, - hasClearableSilentNotifs = hasClearableSilentNotifs, - clearableAlertingSensitiveNotifUsers = clearableAlertingSensitiveNotifUsers, - clearableSilentSensitiveNotifUsers = clearableSilentSensitiveNotifUsers + hasClearableSilentNotifs = hasClearableSilentNotifs ) } } \ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/dagger/CoordinatorsModule.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/dagger/CoordinatorsModule.kt index 839cf0d7ef921..357c5b219fa2c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/dagger/CoordinatorsModule.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/dagger/CoordinatorsModule.kt @@ -19,6 +19,7 @@ package com.android.systemui.statusbar.notification.collection.coordinator.dagge import com.android.systemui.dagger.SysUISingleton import com.android.systemui.statusbar.notification.collection.coordinator.NotifCoordinators import com.android.systemui.statusbar.notification.collection.coordinator.NotifCoordinatorsImpl +import com.android.systemui.statusbar.notification.collection.coordinator.SensitiveContentCoordinatorModule import dagger.Binds import dagger.Module import dagger.Provides @@ -47,6 +48,7 @@ interface CoordinatorsSubcomponent { } @Module(includes = [ + SensitiveContentCoordinatorModule::class, ]) private abstract class InternalCoordinatorsModule { @Binds diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java index 6e96aad776d25..4c7b2bbfb6d90 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java @@ -16,8 +16,6 @@ package com.android.systemui.statusbar.notification.collection.inflation; -import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_PUBLIC; - import static java.util.Objects.requireNonNull; import android.annotation.Nullable; @@ -251,13 +249,10 @@ public class NotificationRowBinderImpl implements NotificationRowBinder { RowContentBindParams params = mRowContentBindStage.getStageParams(entry); params.setUseIncreasedCollapsedHeight(useIncreasedCollapsedHeight); params.setUseLowPriority(isLowPriority); - boolean needsRedaction = - mNotificationLockscreenUserManager.notifNeedsRedactionInPublic(entry); - if (needsRedaction) { - params.requireContentViews(FLAG_CONTENT_VIEW_PUBLIC); - } else { - params.markContentViewsFreeable(FLAG_CONTENT_VIEW_PUBLIC); - } + + // TODO: Replace this API with RowContentBindParams directly. Also move to a separate + // redaction controller. + row.setNeedsRedaction(mNotificationLockscreenUserManager.needsRedaction(entry)); params.rebindAllContentViews(); mRowContentBindStage.requestRebind(entry, en -> { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifStackController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifStackController.kt index 580d853dc5e97..b6278d1d5f01b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifStackController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifStackController.kt @@ -28,21 +28,11 @@ data class NotifStats( val hasNonClearableAlertingNotifs: Boolean, val hasClearableAlertingNotifs: Boolean, val hasNonClearableSilentNotifs: Boolean, - val hasClearableSilentNotifs: Boolean, - val clearableAlertingSensitiveNotifUsers: Set, - val clearableSilentSensitiveNotifUsers: Set + val hasClearableSilentNotifs: Boolean ) { companion object { @JvmStatic - val empty = NotifStats( - numActiveNotifs = 0, - hasNonClearableAlertingNotifs = false, - hasClearableAlertingNotifs = false, - hasNonClearableSilentNotifs = false, - hasClearableSilentNotifs = false, - clearableAlertingSensitiveNotifUsers = emptySet(), - clearableSilentSensitiveNotifUsers = emptySet(), - ) + val empty = NotifStats(0, false, false, false, false) } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationSectionHeadersModule.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationSectionHeadersModule.kt index f58918fe6f80f..2a9cfd034dcef 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationSectionHeadersModule.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationSectionHeadersModule.kt @@ -182,4 +182,4 @@ annotation class HeaderClickAction @Scope @Retention(AnnotationRetention.BINARY) -annotation class SectionHeaderScope +annotation class SectionHeaderScope \ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/IconManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/IconManager.kt index 015e3d8cd553d..d8965418b4c43 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/IconManager.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/IconManager.kt @@ -28,7 +28,6 @@ import android.widget.ImageView import com.android.internal.statusbar.StatusBarIcon import com.android.systemui.R import com.android.systemui.dagger.SysUISingleton -import com.android.systemui.statusbar.NotificationLockscreenUserManager import com.android.systemui.statusbar.StatusBarIconView import com.android.systemui.statusbar.notification.InflationException import com.android.systemui.statusbar.notification.collection.NotificationEntry @@ -50,29 +49,31 @@ import javax.inject.Inject class IconManager @Inject constructor( private val notifCollection: CommonNotifCollection, private val launcherApps: LauncherApps, - private val iconBuilder: IconBuilder, - private val notifLockscreenUserManager: NotificationLockscreenUserManager + private val iconBuilder: IconBuilder ) : ConversationIconManager { private var unimportantConversationKeys: Set = emptySet() fun attach() { notifCollection.addCollectionListener(entryListener) - notifLockscreenUserManager.addOnNeedsRedactionInPublicChangedListener(sensitivityListener) } private val entryListener = object : NotifCollectionListener { + override fun onEntryInit(entry: NotificationEntry) { + entry.addOnSensitivityChangedListener(sensitivityListener) + } + + override fun onEntryCleanUp(entry: NotificationEntry) { + entry.removeOnSensitivityChangedListener(sensitivityListener) + } + override fun onRankingApplied() { // rankings affect whether a conversation is important, which can change the icons recalculateForImportantConversationChange() } } - private val sensitivityListener = Runnable { - for (entry in notifCollection.allNotifs) { - if (entry.hasSensitiveContents()) { - updateIconsSafe(entry) - } - } + private val sensitivityListener = NotificationEntry.OnSensitivityChangedListener { + entry -> updateIconsSafe(entry) } private fun recalculateForImportantConversationChange() { @@ -181,16 +182,12 @@ class IconManager @Inject constructor( } } - private inline val NotificationEntry.needsRedactionInPublic: Boolean get() = - hasSensitiveContents() && - notifLockscreenUserManager.sensitiveNotifsNeedRedactionInPublic(sbn.userId) - @Throws(InflationException::class) private fun getIconDescriptors( entry: NotificationEntry ): Pair { val iconDescriptor = getIconDescriptor(entry, false /* redact */) - val sensitiveDescriptor = if (entry.needsRedactionInPublic) { + val sensitiveDescriptor = if (entry.isSensitive) { getIconDescriptor(entry, true /* redact */) } else { iconDescriptor @@ -313,7 +310,7 @@ class IconManager @Inject constructor( iconView === entry.icons.shelfIcon || iconView === entry.icons.aodIcon val isSmallIcon = iconDescriptor.icon.equals(entry.sbn.notification.smallIcon) return isImportantConversation(entry) && !isSmallIcon && - (!usedInSensitiveContext || !entry.needsRedactionInPublic) + (!usedInSensitiveContext || !entry.isSensitive) } private fun isImportantConversation(entry: NotificationEntry): Boolean { @@ -341,4 +338,4 @@ interface ConversationIconManager { * of a group from which the priority notification has been removed. */ fun setUnimportantConversations(keys: Collection) -} +} \ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java index d5088acaa61c2..1cae60b3d37dd 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java @@ -90,8 +90,8 @@ import com.android.systemui.statusbar.RemoteInputController; import com.android.systemui.statusbar.SmartReplyController; import com.android.systemui.statusbar.StatusBarIconView; import com.android.systemui.statusbar.notification.AboveShelfChangedListener; -import com.android.systemui.statusbar.notification.FeedbackIcon; import com.android.systemui.statusbar.notification.LaunchAnimationParameters; +import com.android.systemui.statusbar.notification.FeedbackIcon; import com.android.systemui.statusbar.notification.NotificationFadeAware; import com.android.systemui.statusbar.notification.NotificationLaunchAnimatorController; import com.android.systemui.statusbar.notification.NotificationUtils; @@ -202,6 +202,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView /** Are we showing the "public" version */ private boolean mShowingPublic; private boolean mSensitive; + private boolean mSensitiveHiddenInGeneral; private boolean mShowingPublicInitialized; private boolean mHideSensitiveForIntrinsicHeight; private float mHeaderVisibleAmount = DEFAULT_HEADER_VISIBLE_AMOUNT; @@ -1504,7 +1505,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView mUseIncreasedHeadsUpHeight = use; } - // TODO: remove this method and mNeedsRedaction entirely once the old pipeline is gone public void setNeedsRedaction(boolean needsRedaction) { // TODO: Move inflation logic out of this call and remove this method if (mNeedsRedaction != needsRedaction) { @@ -2587,8 +2587,9 @@ public class ExpandableNotificationRow extends ActivatableNotificationView getShowingLayout().requestSelectLayout(needsAnimation || isUserLocked()); } - public void setSensitive(boolean sensitive) { + public void setSensitive(boolean sensitive, boolean hideSensitive) { mSensitive = sensitive; + mSensitiveHiddenInGeneral = hideSensitive; } @Override @@ -2678,15 +2679,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView * see {@link NotificationEntry#isDismissable()}. */ public boolean canViewBeDismissed() { - // Entry not dismissable. - if (!mEntry.isDismissable()) { - return false; - } - // Entry shouldn't be showing the public layout, it can be dismissed. - if (!shouldShowPublic()) { - return true; - } - return false; + return mEntry.isDismissable() && (!shouldShowPublic() || !mSensitiveHiddenInGeneral); } /** @@ -2695,7 +2688,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView * clearability see {@link NotificationEntry#isClearable()}. */ public boolean canViewBeCleared() { - return mEntry.isClearable() && !shouldShowPublic(); + return mEntry.isClearable() && (!shouldShowPublic() || !mSensitiveHiddenInGeneral); } private boolean shouldShowPublic() { @@ -3459,28 +3452,10 @@ public class ExpandableNotificationRow extends ActivatableNotificationView pw.print(", translation: " + getTranslation()); pw.print(", removed: " + isRemoved()); pw.print(", expandAnimationRunning: " + mExpandAnimationRunning); - pw.print(", sensitive: " + mSensitive); - pw.print(", hideSensitiveForIntrinsicHeight: " + mHideSensitiveForIntrinsicHeight); - pw.println(", privateShowing: " + !shouldShowPublic()); - pw.print("privateLayout: "); - if (mPrivateLayout != null) { - pw.println(); - DumpUtilsKt.withIncreasedIndent(pw, () -> { - mPrivateLayout.dump(pw, args); - mPrivateLayout.dumpSmartReplies(pw); - }); - } else { - pw.println("null"); - } - pw.print("publicLayout: "); - if (mPublicLayout != null) { - pw.println(); - DumpUtilsKt.withIncreasedIndent(pw, () -> { - mPublicLayout.dump(pw, args); - }); - } else { - pw.println("null"); - } + NotificationContentView showingLayout = getShowingLayout(); + pw.print(", privateShowing: " + (showingLayout == mPrivateLayout)); + pw.println(); + showingLayout.dump(pw, args); if (getViewState() != null) { getViewState().dump(pw, args); @@ -3506,6 +3481,8 @@ public class ExpandableNotificationRow extends ActivatableNotificationView } pw.decreaseIndent(); pw.println("}"); + } else if (mPrivateLayout != null) { + mPrivateLayout.dumpSmartReplies(pw); } }); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java index a60026c7a97b7..599039d465561 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java @@ -35,7 +35,6 @@ import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.shared.plugins.PluginManager; -import com.android.systemui.statusbar.NotificationLockscreenUserManager; import com.android.systemui.statusbar.NotificationMediaManager; import com.android.systemui.statusbar.SmartReplyController; import com.android.systemui.statusbar.notification.FeedbackIcon; @@ -70,7 +69,6 @@ import javax.inject.Named; public class ExpandableNotificationRowController implements NotifViewController { private static final String TAG = "NotifRowController"; private final ExpandableNotificationRow mView; - private final NotificationLockscreenUserManager mLockscreenUserManager; private final NotificationListContainer mListContainer; private final RemoteInputViewSubcomponent.Factory mRemoteInputViewSubcomponentFactory; private final ActivatableNotificationViewController mActivatableNotificationViewController; @@ -88,6 +86,7 @@ public class ExpandableNotificationRowController implements NotifViewController private final ExpandableNotificationRow.OnExpandClickListener mOnExpandClickListener; private final StatusBarStateController mStatusBarStateController; private final MetricsLogger mMetricsLogger; + private final ExpandableNotificationRow.ExpansionLogger mExpansionLogger = this::logNotificationExpansion; private final ExpandableNotificationRow.CoordinateOnClickListener mOnFeedbackClickListener; @@ -101,12 +100,12 @@ public class ExpandableNotificationRowController implements NotifViewController private final Optional mBubblesManagerOptional; private final SmartReplyConstants mSmartReplyConstants; private final SmartReplyController mSmartReplyController; + private final ExpandableNotificationRowDragController mDragController; @Inject public ExpandableNotificationRowController( ExpandableNotificationRow view, - NotificationLockscreenUserManager lockscreenUserManager, ActivatableNotificationViewController activatableNotificationViewController, RemoteInputViewSubcomponent.Factory rivSubcomponentFactory, MetricsLogger metricsLogger, @@ -136,7 +135,6 @@ public class ExpandableNotificationRowController implements NotifViewController Optional bubblesManagerOptional, ExpandableNotificationRowDragController dragController) { mView = view; - mLockscreenUserManager = lockscreenUserManager; mListContainer = listContainer; mRemoteInputViewSubcomponentFactory = rivSubcomponentFactory; mActivatableNotificationViewController = activatableNotificationViewController; @@ -216,10 +214,6 @@ public class ExpandableNotificationRowController implements NotifViewController mView.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS); } - mLockscreenUserManager - .addOnNeedsRedactionInPublicChangedListener(mNeedsRedactionListener); - mNeedsRedactionListener.run(); - mView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() { @Override public void onViewAttachedToWindow(View v) { @@ -238,14 +232,6 @@ public class ExpandableNotificationRowController implements NotifViewController }); } - private final Runnable mNeedsRedactionListener = new Runnable() { - @Override - public void run() { - mView.setSensitive( - mLockscreenUserManager.notifNeedsRedactionInPublic(mView.getEntry())); - } - }; - private final StatusBarStateController.StateListener mStatusBarStateListener = new StatusBarStateController.StateListener() { @Override @@ -347,5 +333,4 @@ public class ExpandableNotificationRowController implements NotifViewController public void setFeedbackIcon(@Nullable FeedbackIcon icon) { mView.setFeedbackIcon(icon); } - } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java index a7c6bfb0289c1..ba26cfaa30b43 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java @@ -61,7 +61,6 @@ import com.android.systemui.statusbar.policy.SmartReplyStateInflaterKt; import com.android.systemui.statusbar.policy.SmartReplyView; import com.android.systemui.statusbar.policy.dagger.RemoteInputViewSubcomponent; import com.android.systemui.util.Compile; -import com.android.systemui.util.DumpUtilsKt; import com.android.systemui.wmshell.BubblesManager; import java.io.PrintWriter; @@ -1995,33 +1994,22 @@ public class NotificationContentView extends FrameLayout implements Notification } } - public void dump(PrintWriter pwOriginal, String[] args) { - IndentingPrintWriter pw = DumpUtilsKt.asIndenting(pwOriginal); + public void dump(PrintWriter pw, String[] args) { pw.print("contentView visibility: " + getVisibility()); pw.print(", alpha: " + getAlpha()); pw.print(", clipBounds: " + getClipBounds()); pw.print(", contentHeight: " + mContentHeight); - pw.println(", currentVisibleType: " + mVisibleType); - DumpUtilsKt.withIncreasedIndent(pw, () -> { - int[] visTypes = { - VISIBLE_TYPE_CONTRACTED, - VISIBLE_TYPE_EXPANDED, - VISIBLE_TYPE_HEADSUP, - VISIBLE_TYPE_SINGLELINE - }; - for (int visType : visTypes) { - pw.print("visType: " + visType + " :: "); - View view = getViewForVisibleType(visType); - if (view != null) { - pw.print("visibility: " + view.getVisibility()); - pw.print(", alpha: " + view.getAlpha()); - pw.print(", clipBounds: " + view.getClipBounds()); - } else { - pw.print("null"); - } - pw.println(); - } - }); + pw.print(", visibleType: " + mVisibleType); + View view = getViewForVisibleType(mVisibleType); + pw.print(", visibleView "); + if (view != null) { + pw.print(" visibility: " + view.getVisibility()); + pw.print(", alpha: " + view.getAlpha()); + pw.print(", clipBounds: " + view.getClipBounds()); + } else { + pw.print("null"); + } + pw.println(); } /** Add any existing SmartReplyView to the dump */ diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowContentBindParams.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowContentBindParams.java index a52f638e7c26e..f26ecc32821d4 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowContentBindParams.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowContentBindParams.java @@ -102,9 +102,8 @@ public final class RowContentBindParams { * @see InflationFlag */ public void markContentViewsFreeable(@InflationFlag int contentViews) { - @InflationFlag int existingContentViews = contentViews &= mContentViews; mContentViews &= ~contentViews; - mDirtyContentViews |= existingContentViews; + mDirtyContentViews &= ~contentViews; } public @InflationFlag int getContentViews() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java index 6a8f4796813aa..2493ccbe5a484 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java @@ -216,9 +216,6 @@ public class NotificationStackScrollLayoutController { mBarState = mStatusBarStateController.getState(); mStatusBarStateController.addCallback( mStateListener, SysuiStatusBarStateController.RANK_STACK_SCROLLER); - mLockscreenUserManager.addOnNeedsRedactionInPublicChangedListener( - mOnNeedsRedactionInPublicChangedListener); - updateClearButtonVisibility(); } @Override @@ -226,8 +223,6 @@ public class NotificationStackScrollLayoutController { mConfigurationController.removeCallback(mConfigurationListener); mZenModeController.removeCallback(mZenModeControllerCallback); mStatusBarStateController.removeCallback(mStateListener); - mLockscreenUserManager.removeOnNeedsRedactionInPublicChangedListener( - mOnNeedsRedactionInPublicChangedListener); } }; @@ -331,7 +326,6 @@ public class NotificationStackScrollLayoutController { mLockscreenUserManager.isAnyProfilePublicMode()); mView.onStatePostChange(mStatusBarStateController.fromShadeLocked()); mNotificationEntryManager.updateNotifications("CentralSurfaces state changed"); - updateClearButtonVisibility(); } }; @@ -344,17 +338,6 @@ public class NotificationStackScrollLayoutController { } }; - private final Runnable mOnNeedsRedactionInPublicChangedListener = new Runnable() { - @Override - public void run() { - // Whether or not the notification needs redaction when in public has changed, but if - // we're not actually in public, then we don't need to update anything. - if (mLockscreenUserManager.isAnyProfilePublicMode()) { - updateClearButtonVisibility(); - } - } - }; - /** * Set the overexpansion of the panel to be applied to the view. */ @@ -1291,44 +1274,12 @@ public class NotificationStackScrollLayoutController { return hasNotifications(selection, true /* clearable */); } - private boolean hasRedactedClearableSilentNotifs() { - if (!mLockscreenUserManager.isAnyProfilePublicMode()) { - return false; - } - for (int userId : mNotifStats.getClearableSilentSensitiveNotifUsers()) { - if (mLockscreenUserManager.sensitiveNotifsNeedRedactionInPublic(userId)) { - return true; - } - } - return false; - } - - private boolean hasClearableSilentNotifs() { - return mNotifStats.getHasClearableSilentNotifs() && !hasRedactedClearableSilentNotifs(); - } - - private boolean hasRedactedClearableAlertingNotifs() { - if (!mLockscreenUserManager.isAnyProfilePublicMode()) { - return false; - } - for (int userId : mNotifStats.getClearableAlertingSensitiveNotifUsers()) { - if (mLockscreenUserManager.sensitiveNotifsNeedRedactionInPublic(userId)) { - return true; - } - } - return false; - } - - private boolean hasClearableAlertingNotifs() { - return mNotifStats.getHasClearableAlertingNotifs() && !hasRedactedClearableAlertingNotifs(); - } - public boolean hasNotifications(@SelectedRows int selection, boolean isClearable) { boolean hasAlertingMatchingClearable = isClearable - ? hasClearableAlertingNotifs() + ? mNotifStats.getHasClearableAlertingNotifs() : mNotifStats.getHasNonClearableAlertingNotifs(); boolean hasSilentMatchingClearable = isClearable - ? hasClearableSilentNotifs() + ? mNotifStats.getHasClearableSilentNotifs() : mNotifStats.getHasNonClearableSilentNotifs(); switch (selection) { case ROWS_GENTLE: @@ -1628,15 +1579,6 @@ public class NotificationStackScrollLayoutController { mNotificationActivityStarter = activityStarter; } - private void updateClearButtonVisibility() { - updateClearSilentButton(); - updateFooter(); - } - - private void updateClearSilentButton() { - mSilentHeaderController.setClearSectionEnabled(hasClearableSilentNotifs()); - } - /** * Enum for UiEvent logged from this class */ @@ -1962,7 +1904,6 @@ public class NotificationStackScrollLayoutController { @Override public void setNotifStats(@NonNull NotifStats notifStats) { mNotifStats = notifStats; - updateClearSilentButton(); updateFooter(); updateShowEmptyShadeView(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java index f386797e322aa..9863a0ed1ce0c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java @@ -29,7 +29,6 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.CrossFadeHelper; import com.android.systemui.statusbar.HeadsUpStatusBarView; -import com.android.systemui.statusbar.NotificationLockscreenUserManager; import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator; import com.android.systemui.statusbar.notification.collection.NotificationEntry; @@ -41,8 +40,8 @@ import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener; import com.android.systemui.util.ViewController; -import java.util.ArrayList; import java.util.Optional; +import java.util.ArrayList; import java.util.function.BiConsumer; import java.util.function.Consumer; @@ -62,17 +61,17 @@ public class HeadsUpAppearanceController extends ViewController mSetTrackingHeadsUp = - this::setTrackingHeadsUp; + private final Consumer + mSetTrackingHeadsUp = this::setTrackingHeadsUp; private final BiConsumer mSetExpandedHeight = this::setAppearFraction; private final KeyguardBypassController mBypassController; private final StatusBarStateController mStatusBarStateController; private final CommandQueue mCommandQueue; private final NotificationWakeUpCoordinator mWakeUpCoordinator; - private final NotificationLockscreenUserManager mNotifLockscreenUserManager; - private final Runnable mRedactionChanged = this::updateRedaction; + private final View mClockView; private final Optional mOperatorNameViewOptional; @@ -91,13 +90,6 @@ public class HeadsUpAppearanceController extends ViewController false /* dismissAction */ , null /* cancelRunnable */, false /* afterKeyguardGone */); @@ -480,7 +480,7 @@ class StatusBarNotificationPresenter implements NotificationPresenter, .isLockscreenPublicMode(mLockscreenUserManager.getCurrentUserId()); boolean userPublic = devicePublic || mLockscreenUserManager.isLockscreenPublicMode(sbn.getUserId()); - boolean needsRedaction = mLockscreenUserManager.notifNeedsRedactionInPublic(entry); + boolean needsRedaction = mLockscreenUserManager.needsRedaction(entry); if (userPublic && needsRedaction) { // TODO(b/135046837): we can probably relax this with dynamic privacy return true; diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt index 73e574eddd17d..562c970178622 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt @@ -130,8 +130,8 @@ class LockscreenShadeTransitionControllerTest : SysuiTestCase() { whenever(statusbarStateController.state).thenReturn(StatusBarState.KEYGUARD) whenever(nsslController.isInLockedDownShade).thenReturn(false) whenever(qS.isFullyCollapsed).thenReturn(true) - whenever(lockScreenUserManager.sensitiveNotifsNeedRedactionInPublic(anyInt())) - .thenReturn(false) + whenever(lockScreenUserManager.userAllowsPrivateNotificationsInPublic(anyInt())).thenReturn( + true) whenever(lockScreenUserManager.shouldShowLockscreenNotifications()).thenReturn(true) whenever(lockScreenUserManager.isLockscreenPublicMode(anyInt())).thenReturn(true) whenever(falsingCollector.shouldEnforceBouncer()).thenReturn(false) @@ -207,8 +207,8 @@ class LockscreenShadeTransitionControllerTest : SysuiTestCase() { @Test fun testTriggeringBouncerWhenPrivateNotificationsArentAllowed() { - whenever(lockScreenUserManager.sensitiveNotifsNeedRedactionInPublic(anyInt())) - .thenReturn(true) + whenever(lockScreenUserManager.userAllowsPrivateNotificationsInPublic(anyInt())).thenReturn( + false) transitionController.goToLockedShade(null) verify(statusbarStateController, never()).setState(anyInt()) verify(statusbarStateController).setLeaveOpenOnKeyguardHide(true) diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java index 18937e784ed10..7687d12045414 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java @@ -53,13 +53,11 @@ import android.testing.TestableLooper; import androidx.test.filters.SmallTest; -import com.android.keyguard.KeyguardUpdateMonitor; import com.android.systemui.Dependency; import com.android.systemui.SysuiTestCase; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.dump.DumpManager; import com.android.systemui.plugins.statusbar.StatusBarStateController; -import com.android.systemui.recents.OverviewProxyService; import com.android.systemui.statusbar.NotificationLockscreenUserManager.KeyguardNotificationSuppressor; import com.android.systemui.statusbar.notification.NotificationEntryManager; import com.android.systemui.statusbar.notification.collection.NotificationEntry; @@ -108,10 +106,6 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase { private BroadcastDispatcher mBroadcastDispatcher; @Mock private KeyguardStateController mKeyguardStateController; - @Mock - private KeyguardUpdateMonitor mKeyguardUpdateMonitor; - @Mock - private OverviewProxyService mOverviewProxyService; private UserInfo mCurrentUser; private UserInfo mSecondaryUser; @@ -125,6 +119,7 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase { @Before public void setUp() { MockitoAnnotations.initMocks(this); + mDependency.injectTestDependency(NotificationEntryManager.class, mEntryManager); int currentUserId = ActivityManager.getCurrentUser(); mSettings = new FakeSettings(); @@ -217,7 +212,7 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase { mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false); // THEN current user's notification is redacted - assertTrue(mLockscreenUserManager.notifNeedsRedactionInPublic(mCurrentUserNotif)); + assertTrue(mLockscreenUserManager.needsRedaction(mCurrentUserNotif)); } @Test @@ -228,7 +223,7 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase { mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false); // THEN current user's notification isn't redacted - assertFalse(mLockscreenUserManager.notifNeedsRedactionInPublic(mCurrentUserNotif)); + assertFalse(mLockscreenUserManager.needsRedaction(mCurrentUserNotif)); } @Test @@ -239,7 +234,7 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase { mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false); // THEN work profile notification is redacted - assertTrue(mLockscreenUserManager.notifNeedsRedactionInPublic(mWorkProfileNotif)); + assertTrue(mLockscreenUserManager.needsRedaction(mWorkProfileNotif)); } @Test @@ -250,7 +245,7 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase { mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false); // THEN work profile notification isn't redacted - assertFalse(mLockscreenUserManager.notifNeedsRedactionInPublic(mWorkProfileNotif)); + assertFalse(mLockscreenUserManager.needsRedaction(mWorkProfileNotif)); } @Test @@ -265,11 +260,11 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase { mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false); // THEN the work profile notification doesn't need to be redacted - assertFalse(mLockscreenUserManager.notifNeedsRedactionInPublic(mWorkProfileNotif)); + assertFalse(mLockscreenUserManager.needsRedaction(mWorkProfileNotif)); // THEN the current user and secondary user notifications do need to be redacted - assertTrue(mLockscreenUserManager.notifNeedsRedactionInPublic(mCurrentUserNotif)); - assertTrue(mLockscreenUserManager.notifNeedsRedactionInPublic(mSecondaryUserNotif)); + assertTrue(mLockscreenUserManager.needsRedaction(mCurrentUserNotif)); + assertTrue(mLockscreenUserManager.needsRedaction(mSecondaryUserNotif)); } @Test @@ -284,11 +279,11 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase { mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false); // THEN the work profile notification needs to be redacted - assertTrue(mLockscreenUserManager.notifNeedsRedactionInPublic(mWorkProfileNotif)); + assertTrue(mLockscreenUserManager.needsRedaction(mWorkProfileNotif)); // THEN the current user and secondary user notifications don't need to be redacted - assertFalse(mLockscreenUserManager.notifNeedsRedactionInPublic(mCurrentUserNotif)); - assertFalse(mLockscreenUserManager.notifNeedsRedactionInPublic(mSecondaryUserNotif)); + assertFalse(mLockscreenUserManager.needsRedaction(mCurrentUserNotif)); + assertFalse(mLockscreenUserManager.needsRedaction(mSecondaryUserNotif)); } @Test @@ -303,7 +298,7 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase { // THEN the secondary profile notification still needs to be redacted because the current // user's setting takes precedence - assertTrue(mLockscreenUserManager.notifNeedsRedactionInPublic(mSecondaryUserNotif)); + assertTrue(mLockscreenUserManager.needsRedaction(mSecondaryUserNotif)); } @Test @@ -423,12 +418,9 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase { context, mBroadcastDispatcher, mDevicePolicyManager, - mKeyguardUpdateMonitor, - () -> mEntryManager, - () -> mOverviewProxyService, mUserManager, - () -> mVisibilityProvider, - () -> mNotifCollection, + (() -> mVisibilityProvider), + (() -> mNotifCollection), mClickNotifier, NotificationLockscreenUserManagerTest.this.mKeyguardManager, mStatusBarStateController, diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/DynamicPrivacyControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/DynamicPrivacyControllerTest.java index e43ae0d2b22ac..7d06abf5cd671 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/DynamicPrivacyControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/DynamicPrivacyControllerTest.java @@ -124,8 +124,8 @@ public class DynamicPrivacyControllerTest extends SysuiTestCase { } private void allowPrivateNotificationsInPublic(boolean allow) { - when(mLockScreenUserManager.sensitiveNotifsNeedRedactionInPublic(anyInt())).thenReturn( - !allow); + when(mLockScreenUserManager.userAllowsPrivateNotificationsInPublic(anyInt())).thenReturn( + allow); } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinatorTest.java index 5c2f5fa6bc1cf..f4d8405a796e1 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinatorTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinatorTest.java @@ -23,6 +23,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -32,6 +33,7 @@ import android.app.Notification; import android.app.NotificationManager; import android.testing.AndroidTestingRunner; +import androidx.annotation.Nullable; import androidx.test.filters.SmallTest; import com.android.systemui.SysuiTestCase; @@ -39,6 +41,7 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.RankingBuilder; import com.android.systemui.statusbar.SbnBuilder; import com.android.systemui.statusbar.notification.SectionClassifier; +import com.android.systemui.statusbar.notification.collection.ListEntry; import com.android.systemui.statusbar.notification.collection.NotifPipeline; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder; @@ -46,6 +49,7 @@ import com.android.systemui.statusbar.notification.collection.listbuilder.plugga import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner; import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider; import com.android.systemui.statusbar.notification.collection.render.NodeController; +import com.android.systemui.statusbar.notification.collection.render.SectionHeaderController; import org.junit.Before; import org.junit.Test; @@ -68,6 +72,7 @@ public class RankingCoordinatorTest extends SysuiTestCase { @Mock private NotifPipeline mNotifPipeline; @Mock private NodeController mAlertingHeaderController; @Mock private NodeController mSilentNodeController; + @Mock private SectionHeaderController mSilentHeaderController; @Captor private ArgumentCaptor mNotifFilterCaptor; @@ -89,6 +94,7 @@ public class RankingCoordinatorTest extends SysuiTestCase { mHighPriorityProvider, mSectionClassifier, mAlertingHeaderController, + mSilentHeaderController, mSilentNodeController); mEntry = spy(new NotificationEntryBuilder().build()); mEntry.setRanking(getRankingForUnfilteredNotif().build()); @@ -105,6 +111,25 @@ public class RankingCoordinatorTest extends SysuiTestCase { mSections.addAll(Arrays.asList(mAlertingSectioner, mSilentSectioner, mMinimizedSectioner)); } + @Test + public void testSilentHeaderClearableChildrenUpdate() { + ListEntry listEntry = new ListEntry(mEntry.getKey(), 0L) { + @Nullable + @Override + public NotificationEntry getRepresentativeEntry() { + return mEntry; + } + }; + setRankingAmbient(false); + setSbnClearable(true); + mSilentSectioner.onEntriesUpdated(Arrays.asList(listEntry)); + verify(mSilentHeaderController).setClearSectionEnabled(eq(true)); + + setSbnClearable(false); + mSilentSectioner.onEntriesUpdated(Arrays.asList(listEntry)); + verify(mSilentHeaderController).setClearSectionEnabled(eq(false)); + } + @Test public void testUnfilteredState() { // GIVEN no suppressed visual effects + app not suspended @@ -200,6 +225,46 @@ public class RankingCoordinatorTest extends SysuiTestCase { assertInSection(mEntry, mSilentSectioner); } + @Test + public void testClearableSilentSection() { + when(mHighPriorityProvider.isHighPriority(mEntry)).thenReturn(false); + setSbnClearable(true); + setRankingAmbient(false); + mSilentSectioner.onEntriesUpdated(Arrays.asList(mEntry)); + verify(mSilentHeaderController).setClearSectionEnabled(eq(true)); + } + + @Test + public void testClearableMinimizedSection() { + when(mHighPriorityProvider.isHighPriority(mEntry)).thenReturn(false); + setSbnClearable(true); + setRankingAmbient(true); + mMinimizedSectioner.onEntriesUpdated(Arrays.asList(mEntry)); + verify(mSilentHeaderController).setClearSectionEnabled(eq(true)); + } + + @Test + public void testNotClearableSilentSection() { + setSbnClearable(false); + when(mHighPriorityProvider.isHighPriority(mEntry)).thenReturn(false); + setRankingAmbient(false); + mSilentSectioner.onEntriesUpdated(Arrays.asList(mEntry)); + mMinimizedSectioner.onEntriesUpdated(Arrays.asList(mEntry)); + mAlertingSectioner.onEntriesUpdated(Arrays.asList(mEntry)); + verify(mSilentHeaderController, times(2)).setClearSectionEnabled(eq(false)); + } + + @Test + public void testNotClearableMinimizedSection() { + setSbnClearable(false); + when(mHighPriorityProvider.isHighPriority(mEntry)).thenReturn(false); + setRankingAmbient(true); + mSilentSectioner.onEntriesUpdated(Arrays.asList(mEntry)); + mMinimizedSectioner.onEntriesUpdated(Arrays.asList(mEntry)); + mAlertingSectioner.onEntriesUpdated(Arrays.asList(mEntry)); + verify(mSilentHeaderController, times(2)).setClearSectionEnabled(eq(false)); + } + private void assertInSection(NotificationEntry entry, NotifSectioner section) { for (NotifSectioner current: mSections) { if (current == section) { diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinatorTest.kt new file mode 100644 index 0000000000000..a2d8e3ddba24d --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinatorTest.kt @@ -0,0 +1,268 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +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 +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.notification.collection.listbuilder.pluggable.Pluggable +import com.android.systemui.statusbar.policy.KeyguardStateController +import com.android.systemui.util.mockito.any +import com.android.systemui.util.mockito.mock +import com.android.systemui.util.mockito.withArgCaptor +import dagger.BindsInstance +import dagger.Component +import org.junit.Test +import org.mockito.Mockito.never +import org.mockito.Mockito.verify +import org.mockito.Mockito.`when` as whenever + +@SmallTest +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 = + DaggerTestSensitiveContentCoordinatorComponent + .factory() + .create( + dynamicPrivacyController, + lockscreenUserManager, + keyguardUpdateMonitor, + statusBarStateController, + keyguardStateController) + .coordinator + + @Test + fun onDynamicPrivacyChanged_invokeInvalidationListener() { + coordinator.attach(pipeline) + val invalidator = withArgCaptor { + verify(pipeline).addPreRenderInvalidator(capture()) + } + val dynamicPrivacyListener = withArgCaptor { + verify(dynamicPrivacyController).addListener(capture()) + } + + val invalidationListener = mock>() + invalidator.setInvalidationListener(invalidationListener) + + dynamicPrivacyListener.onDynamicPrivacyChanged() + + verify(invalidationListener).onPluggableInvalidated(invalidator) + } + + @Test + fun onBeforeRenderList_deviceUnlocked_notifDoesNotNeedRedaction() { + coordinator.attach(pipeline) + val onBeforeRenderListListener = withArgCaptor { + verify(pipeline).addOnBeforeRenderListListener(capture()) + } + + whenever(lockscreenUserManager.currentUserId).thenReturn(1) + whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(false) + whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1)).thenReturn(true) + whenever(dynamicPrivacyController.isDynamicallyUnlocked).thenReturn(false) + val entry = fakeNotification(1, false) + + onBeforeRenderListListener.onBeforeRenderList(listOf(entry)) + + verify(entry.representativeEntry!!).setSensitive(false, false) + } + + @Test + fun onBeforeRenderList_deviceUnlocked_notifWouldNeedRedaction() { + coordinator.attach(pipeline) + val onBeforeRenderListListener = withArgCaptor { + verify(pipeline).addOnBeforeRenderListListener(capture()) + } + + whenever(lockscreenUserManager.currentUserId).thenReturn(1) + whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(false) + whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1)).thenReturn(true) + whenever(dynamicPrivacyController.isDynamicallyUnlocked).thenReturn(false) + val entry = fakeNotification(1, true) + + onBeforeRenderListListener.onBeforeRenderList(listOf(entry)) + + verify(entry.representativeEntry!!).setSensitive(false, false) + } + + @Test + fun onBeforeRenderList_deviceLocked_userAllowsPublicNotifs() { + coordinator.attach(pipeline) + val onBeforeRenderListListener = withArgCaptor { + verify(pipeline).addOnBeforeRenderListListener(capture()) + } + + whenever(lockscreenUserManager.currentUserId).thenReturn(1) + whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(true) + whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1)).thenReturn(true) + whenever(dynamicPrivacyController.isDynamicallyUnlocked).thenReturn(false) + val entry = fakeNotification(1, false) + + onBeforeRenderListListener.onBeforeRenderList(listOf(entry)) + + verify(entry.representativeEntry!!).setSensitive(false, false) + } + + @Test + fun onBeforeRenderList_deviceLocked_userDisallowsPublicNotifs_notifDoesNotNeedRedaction() { + coordinator.attach(pipeline) + val onBeforeRenderListListener = withArgCaptor { + 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(false) + val entry = fakeNotification(1, false) + + onBeforeRenderListListener.onBeforeRenderList(listOf(entry)) + + verify(entry.representativeEntry!!).setSensitive(false, true) + } + + @Test + fun onBeforeRenderList_deviceLocked_notifNeedsRedaction() { + coordinator.attach(pipeline) + val onBeforeRenderListListener = withArgCaptor { + 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(false) + val entry = fakeNotification(1, true) + + onBeforeRenderListListener.onBeforeRenderList(listOf(entry)) + + verify(entry.representativeEntry!!).setSensitive(true, true) + } + + @Test + fun onBeforeRenderList_deviceDynamicallyUnlocked_notifNeedsRedaction() { + coordinator.attach(pipeline) + val onBeforeRenderListListener = withArgCaptor { + 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) + val entry = fakeNotification(1, true) + + onBeforeRenderListListener.onBeforeRenderList(listOf(entry)) + + verify(entry.representativeEntry!!).setSensitive(false, true) + } + + @Test + fun onBeforeRenderList_deviceDynamicallyUnlocked_notifUserNeedsWorkChallenge() { + coordinator.attach(pipeline) + val onBeforeRenderListListener = withArgCaptor { + 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(lockscreenUserManager.needsSeparateWorkChallenge(2)).thenReturn(true) + + val entry = fakeNotification(2, true) + + onBeforeRenderListListener.onBeforeRenderList(listOf(entry)) + + verify(entry.representativeEntry!!).setSensitive(true, true) + } + + @Test + fun onBeforeRenderList_deviceDynamicallyUnlocked_deviceBiometricBypassingLockScreen() { + coordinator.attach(pipeline) + val onBeforeRenderListListener = withArgCaptor { + 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().apply { + whenever(identifier).thenReturn(notifUserId) + } + val mockSbn: StatusBarNotification = mock().apply { + whenever(user).thenReturn(mockUserHandle) + } + val mockEntry = mock().apply { + whenever(sbn).thenReturn(mockSbn) + } + whenever(lockscreenUserManager.needsRedaction(mockEntry)).thenReturn(needsRedaction) + whenever(mockEntry.rowExists()).thenReturn(true) + return object : ListEntry("key", 0) { + override fun getRepresentativeEntry(): NotificationEntry = mockEntry + } + } +} + +@CoordinatorScope +@Component(modules = [SensitiveContentCoordinatorModule::class]) +interface TestSensitiveContentCoordinatorComponent { + val coordinator: SensitiveContentCoordinator + + @Component.Factory + interface Factory { + fun create( + @BindsInstance dynamicPrivacyController: DynamicPrivacyController, + @BindsInstance lockscreenUserManager: NotificationLockscreenUserManager, + @BindsInstance keyguardUpdateMonitor: KeyguardUpdateMonitor, + @BindsInstance statusBarStateController: StatusBarStateController, + @BindsInstance keyguardStateController: KeyguardStateController + ): TestSensitiveContentCoordinatorComponent + } +} \ No newline at end of file diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinatorTest.kt index cf2fc7c3a5fef..70266e401f8af 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinatorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinatorTest.kt @@ -15,7 +15,6 @@ */ package com.android.systemui.statusbar.notification.collection.coordinator -import android.os.UserHandle import android.testing.AndroidTestingRunner import android.testing.TestableLooper.RunWithLooper import androidx.test.filters.SmallTest @@ -44,11 +43,6 @@ import org.mockito.Mockito.`when` as whenever @RunWith(AndroidTestingRunner::class) @RunWithLooper class StackCoordinatorTest : SysuiTestCase() { - - companion object { - const val NOTIF_USER_ID = 0 - } - private lateinit var coordinator: StackCoordinator private lateinit var afterRenderListListener: OnAfterRenderListListener @@ -67,10 +61,7 @@ class StackCoordinatorTest : SysuiTestCase() { afterRenderListListener = withArgCaptor { verify(pipeline).addOnAfterRenderListListener(capture()) } - entry = NotificationEntryBuilder() - .setSection(section) - .setUser(UserHandle.of(NOTIF_USER_ID)) - .build() + entry = NotificationEntryBuilder().setSection(section).build() } @Test @@ -83,31 +74,13 @@ class StackCoordinatorTest : SysuiTestCase() { fun testSetNotificationStats_clearableAlerting() { whenever(section.bucket).thenReturn(BUCKET_ALERTING) afterRenderListListener.onAfterRenderList(listOf(entry), stackController) - verify(stackController) - .setNotifStats( - NotifStats( - 1, - false, - true, - false, - false, - setOf(NOTIF_USER_ID), - emptySet())) + verify(stackController).setNotifStats(NotifStats(1, false, true, false, false)) } @Test fun testSetNotificationStats_clearableSilent() { whenever(section.bucket).thenReturn(BUCKET_SILENT) afterRenderListListener.onAfterRenderList(listOf(entry), stackController) - verify(stackController) - .setNotifStats( - NotifStats( - 1, - false, - false, - false, - true, - emptySet(), - setOf(NOTIF_USER_ID))) + verify(stackController).setNotifStats(NotifStats(1, false, false, false, true)) } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/IconManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/IconManagerTest.kt index c7f7ec213b0c9..b63e66f1ebe37 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/IconManagerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/IconManagerTest.kt @@ -14,10 +14,10 @@ * limitations under the License. */ -package com.android.systemui.statusbar.notification.icon +package com.android.systemui.statusbar.notification.icon; -import android.app.ActivityManager -import android.app.Notification +import android.app.ActivityManager; +import android.app.Notification; import android.app.NotificationChannel import android.app.NotificationManager.IMPORTANCE_DEFAULT import android.app.Person @@ -27,12 +27,11 @@ import android.graphics.drawable.Drawable import android.graphics.drawable.Icon import android.os.SystemClock import android.os.UserHandle -import android.testing.AndroidTestingRunner +import android.testing.AndroidTestingRunner; import androidx.test.InstrumentationRegistry import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.controls.controller.AuxiliaryPersistenceWrapperTest.Companion.any -import com.android.systemui.statusbar.NotificationLockscreenUserManager 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 @@ -41,7 +40,7 @@ import org.junit.Assert.assertEquals import org.junit.Before import org.junit.Test -import org.junit.runner.RunWith +import org.junit.runner.RunWith; import org.mockito.Mock import org.mockito.Mockito.`when` import org.mockito.Mockito.anyInt @@ -49,14 +48,15 @@ import org.mockito.MockitoAnnotations @SmallTest @RunWith(AndroidTestingRunner::class) -class IconManagerTest : SysuiTestCase() { +class IconManagerTest: SysuiTestCase() { companion object { - private const val TEST_PACKAGE_NAME = "test" - private const val TEST_UID = 0 + private const val TEST_PACKAGE_NAME = "test"; + private const val TEST_UID = 0; } + private var id = 0 - private val context = InstrumentationRegistry.getTargetContext() + private val context = InstrumentationRegistry.getTargetContext(); @Mock private lateinit var shortcut: ShortcutInfo @Mock private lateinit var shortcutIc: Icon @Mock private lateinit var messageIc: Icon @@ -65,7 +65,6 @@ class IconManagerTest : SysuiTestCase() { @Mock private lateinit var drawable: Drawable @Mock private lateinit var row: ExpandableNotificationRow - @Mock private lateinit var notifLockscreenUserManager: NotificationLockscreenUserManager @Mock private lateinit var notifCollection: CommonNotifCollection @Mock private lateinit var launcherApps: LauncherApps @@ -84,16 +83,13 @@ class IconManagerTest : SysuiTestCase() { `when`(shortcut.icon).thenReturn(shortcutIc) `when`(launcherApps.getShortcutIcon(shortcut)).thenReturn(shortcutIc) - `when`(notifLockscreenUserManager.sensitiveNotifsNeedRedactionInPublic(TEST_UID)) - .thenReturn(true) - iconManager = - IconManager(notifCollection, launcherApps, iconBuilder, notifLockscreenUserManager) + iconManager = IconManager(notifCollection, launcherApps, iconBuilder) } @Test fun testCreateIcons_importantConversation_shortcutIcon() { - val entry = notificationEntry() + val entry = notificationEntry(true, true, true) entry?.channel?.isImportantConversation = true entry?.let { iconManager.createIcons(it) @@ -103,7 +99,7 @@ class IconManagerTest : SysuiTestCase() { @Test fun testCreateIcons_importantConversation_messageIcon() { - val entry = notificationEntry(hasShortcut = false) + val entry = notificationEntry(false, true, true) entry?.channel?.isImportantConversation = true entry?.let { iconManager.createIcons(it) @@ -113,7 +109,7 @@ class IconManagerTest : SysuiTestCase() { @Test fun testCreateIcons_importantConversation_largeIcon() { - val entry = notificationEntry(hasShortcut = false, hasMessage = false) + val entry = notificationEntry(false, false, true) entry?.channel?.isImportantConversation = true entry?.let { iconManager.createIcons(it) @@ -123,7 +119,7 @@ class IconManagerTest : SysuiTestCase() { @Test fun testCreateIcons_importantConversation_smallIcon() { - val entry = notificationEntry(hasShortcut = false, hasMessage = false, hasLargeIcon = false) + val entry = notificationEntry(false, false, false) entry?.channel?.isImportantConversation = true entry?.let { iconManager.createIcons(it) @@ -133,7 +129,7 @@ class IconManagerTest : SysuiTestCase() { @Test fun testCreateIcons_notImportantConversation() { - val entry = notificationEntry() + val entry = notificationEntry(true, true, true) entry?.let { iconManager.createIcons(it) } @@ -142,10 +138,8 @@ class IconManagerTest : SysuiTestCase() { @Test fun testCreateIcons_sensitiveImportantConversation() { - val entry = notificationEntry( - hasMessage = false, - hasLargeIcon = false, - hasSensitiveContent = true) + val entry = notificationEntry(true, false, false) + entry?.setSensitive(true, true); entry?.channel?.isImportantConversation = true entry?.let { iconManager.createIcons(it) @@ -157,17 +151,14 @@ class IconManagerTest : SysuiTestCase() { @Test fun testUpdateIcons_sensitivityChange() { - val entry = notificationEntry( - hasMessage = false, - hasLargeIcon = false, - hasSensitiveContent = true) + val entry = notificationEntry(true, false, false) entry?.channel?.isImportantConversation = true + entry?.setSensitive(true, true); entry?.let { iconManager.createIcons(it) } assertEquals(entry?.icons?.aodIcon?.sourceIcon, smallIc) - `when`(notifLockscreenUserManager.sensitiveNotifsNeedRedactionInPublic(TEST_UID)) - .thenReturn(false) + entry?.setSensitive(false, false); entry?.let { iconManager.updateIcons(it) } @@ -175,19 +166,14 @@ class IconManagerTest : SysuiTestCase() { } private fun notificationEntry( - hasShortcut: Boolean = true, - hasMessage: Boolean = true, - hasLargeIcon: Boolean = true, - hasSensitiveContent: Boolean = false + hasShortcut: Boolean, + hasMessage: Boolean, + hasLargeIcon: Boolean ): NotificationEntry? { val n = Notification.Builder(mContext, "id") .setSmallIcon(smallIc) .setContentTitle("Title") .setContentText("Text") - .setVisibility( - if (hasSensitiveContent) - Notification.VISIBILITY_PRIVATE - else Notification.VISIBILITY_PUBLIC) if (hasMessage) { n.style = Notification.MessagingStyle("") @@ -217,6 +203,7 @@ class IconManagerTest : SysuiTestCase() { val entry = builder.build() entry.row = row + entry.setSensitive(false, true); return entry } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java index f5a0e2d48859c..b0da3eb84802e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java @@ -91,7 +91,7 @@ public class ExpandableNotificationRowTest extends SysuiTestCase { @Test public void testGroupSummaryNotShowingIconWhenPublic() { - mGroupRow.setSensitive(true); + mGroupRow.setSensitive(true, true); mGroupRow.setHideSensitiveForIntrinsicHeight(true); assertTrue(mGroupRow.isSummaryWithChildren()); assertFalse(mGroupRow.isShowingIcon()); @@ -99,7 +99,7 @@ public class ExpandableNotificationRowTest extends SysuiTestCase { @Test public void testNotificationHeaderVisibleWhenAnimating() { - mGroupRow.setSensitive(true); + mGroupRow.setSensitive(true, true); mGroupRow.setHideSensitive(true, false, 0, 0); mGroupRow.setHideSensitive(false, true, 0, 0); assertEquals(View.VISIBLE, mGroupRow.getChildrenContainer().getVisibleWrapper() @@ -130,7 +130,7 @@ public class ExpandableNotificationRowTest extends SysuiTestCase { public void testIconColorShouldBeUpdatedWhenSensitive() throws Exception { ExpandableNotificationRow row = spy(mNotificationTestHelper.createRow( FLAG_CONTENT_VIEW_ALL)); - row.setSensitive(true); + row.setSensitive(true, true); row.setHideSensitive(true, false, 0, 0); verify(row).updateShelfIconColor(); } @@ -214,7 +214,7 @@ public class ExpandableNotificationRowTest extends SysuiTestCase { @Test public void testFeedback_noHeader() { // public notification is custom layout - no header - mGroupRow.setSensitive(true); + mGroupRow.setSensitive(true, true); mGroupRow.setOnFeedbackClickListener(null); mGroupRow.setFeedbackIcon(null); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationEntryManagerInflationTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationEntryManagerInflationTest.java index a8557050dddb6..251ac7d250fe1 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationEntryManagerInflationTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationEntryManagerInflationTest.java @@ -78,6 +78,7 @@ import com.android.systemui.statusbar.notification.collection.legacy.Notificatio import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider; import com.android.systemui.statusbar.notification.icon.IconBuilder; import com.android.systemui.statusbar.notification.icon.IconManager; +import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider; import com.android.systemui.statusbar.notification.logging.NotificationLogger; import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier; import com.android.systemui.statusbar.notification.row.dagger.ExpandableNotificationRowComponent; @@ -131,6 +132,7 @@ public class NotificationEntryManagerInflationTest extends SysuiTestCase { @Mock private NotificationEntryListener mEntryListener; @Mock private NotificationRowBinderImpl.BindRowCallback mBindCallback; @Mock private HeadsUpManager mHeadsUpManager; + @Mock private NotificationInterruptStateProvider mNotificationInterruptionStateProvider; @Mock private NotificationLockscreenUserManager mLockscreenUserManager; @Mock private NotificationGutsManager mGutsManager; @Mock private NotificationRemoteInputManager mRemoteInputManager; @@ -252,7 +254,6 @@ public class NotificationEntryManagerInflationTest extends SysuiTestCase { .thenAnswer((Answer) invocation -> new ExpandableNotificationRowController( viewCaptor.getValue(), - mLockscreenUserManager, mock(ActivatableNotificationViewController.class), mock(RemoteInputViewSubcomponent.Factory.class), mock(MetricsLogger.class), @@ -299,8 +300,7 @@ public class NotificationEntryManagerInflationTest extends SysuiTestCase { new IconManager( mEntryManager, mock(LauncherApps.class), - new IconBuilder(mContext), - mLockscreenUserManager), + new IconBuilder(mContext)), mock(LowPriorityInflationHelper.class), mNotifPipelineFlags); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java index 7a8b329bec64d..eceff7cc63623 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java @@ -55,7 +55,6 @@ import com.android.systemui.dump.DumpManager; import com.android.systemui.media.MediaFeatureFlag; import com.android.systemui.media.dialog.MediaOutputDialogFactory; import com.android.systemui.plugins.statusbar.StatusBarStateController; -import com.android.systemui.statusbar.NotificationLockscreenUserManager; import com.android.systemui.statusbar.NotificationMediaManager; import com.android.systemui.statusbar.NotificationRemoteInputManager; import com.android.systemui.statusbar.NotificationShadeWindowController; @@ -157,8 +156,7 @@ public class NotificationTestHelper { mIconManager = new IconManager( mock(CommonNotifCollection.class), mock(LauncherApps.class), - new IconBuilder(mContext), - mock(NotificationLockscreenUserManager.class)); + new IconBuilder(mContext)); NotificationContentInflater contentBinder = new NotificationContentInflater( mock(NotifRemoteViewCache.class), diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java index 169c04c692e0d..ed22cd3c55fc9 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java @@ -36,7 +36,6 @@ import com.android.systemui.plugins.DarkIconDispatcher; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.HeadsUpStatusBarView; -import com.android.systemui.statusbar.NotificationLockscreenUserManager; import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; import com.android.systemui.statusbar.notification.row.NotificationTestHelper; @@ -58,12 +57,9 @@ public class HeadsUpAppearanceControllerTest extends SysuiTestCase { private final NotificationStackScrollLayoutController mStackScrollerController = mock(NotificationStackScrollLayoutController.class); - private final NotificationPanelViewController mPanelViewController = + private final NotificationPanelViewController mPanelView = mock(NotificationPanelViewController.class); private final DarkIconDispatcher mDarkIconDispatcher = mock(DarkIconDispatcher.class); - private final NotificationLockscreenUserManager mLockscreenUserManager = - mock(NotificationLockscreenUserManager.class); - private HeadsUpAppearanceController mHeadsUpAppearanceController; private ExpandableNotificationRow mFirst; private HeadsUpStatusBarView mHeadsUpStatusBarView; @@ -97,13 +93,12 @@ public class HeadsUpAppearanceControllerTest extends SysuiTestCase { mHeadsUpManager, mStatusbarStateController, mBypassController, - mLockscreenUserManager, mWakeUpCoordinator, mDarkIconDispatcher, mKeyguardStateController, mCommandQueue, mStackScrollerController, - mPanelViewController, + mPanelView, mHeadsUpStatusBarView, new Clock(mContext, null), Optional.of(mOperatorNameView)); @@ -180,13 +175,12 @@ public class HeadsUpAppearanceControllerTest extends SysuiTestCase { mHeadsUpManager, mStatusbarStateController, mBypassController, - mLockscreenUserManager, mWakeUpCoordinator, mDarkIconDispatcher, mKeyguardStateController, mCommandQueue, mStackScrollerController, - mPanelViewController, + mPanelView, mHeadsUpStatusBarView, new Clock(mContext, null), Optional.empty()); @@ -199,15 +193,15 @@ public class HeadsUpAppearanceControllerTest extends SysuiTestCase { public void testDestroy() { reset(mHeadsUpManager); reset(mDarkIconDispatcher); - reset(mPanelViewController); + reset(mPanelView); reset(mStackScrollerController); mHeadsUpAppearanceController.onViewDetached(); verify(mHeadsUpManager).removeListener(any()); verify(mDarkIconDispatcher).removeDarkReceiver((DarkIconDispatcher.DarkReceiver) any()); - verify(mPanelViewController).removeTrackingHeadsUpListener(any()); - verify(mPanelViewController).setHeadsUpAppearanceController(isNull()); + verify(mPanelView).removeTrackingHeadsUpListener(any()); + verify(mPanelView).setHeadsUpAppearanceController(isNull()); verify(mStackScrollerController).removeOnExpandedHeightChangedListener(any()); } }