diff options
35 files changed, 561 insertions, 794 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/HeadsUpStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/HeadsUpStatusBarView.java index 4d933d9ad21e..e44d334c776d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/HeadsUpStatusBarView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/HeadsUpStatusBarView.java @@ -29,7 +29,6 @@ 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; @@ -49,6 +48,7 @@ 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,29 +111,28 @@ 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 (entry.isSensitive()) { + if (mRedactSensitiveContent && entry.hasSensitiveContents()) { text = entry.headsUpStatusBarTextPublic; } mTextView.setText(text); - mShowingEntry.addOnSensitivityChangedListener(mOnSensitivityChangedListener); } } - private final OnSensitivityChangedListener mOnSensitivityChangedListener = entry -> { - if (entry != mShowingEntry) { - throw new IllegalStateException("Got a sensitivity change for " + entry - + " but mShowingEntry is " + mShowingEntry); + public void setRedactSensitiveContent(boolean redactSensitiveContent) { + if (mRedactSensitiveContent == redactSensitiveContent) { + return; + } + 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 c1ea6bf7cec8..cbe722b6f82f 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 view.entry.isSensitive + return lockScreenUserManager.notifNeedsRedactionInPublic(view.entry) } } return false @@ -552,7 +552,8 @@ class LockscreenShadeTransitionController @Inject constructor( logger.logShadeDisabledOnGoToLockedShade() return } - var userId: Int = lockScreenUserManager.getCurrentUserId() + val currentUser = lockScreenUserManager.currentUserId + var userId: Int = currentUser var entry: NotificationEntry? = null if (expandView is ExpandableNotificationRow) { entry = expandView.entry @@ -562,12 +563,18 @@ class LockscreenShadeTransitionController @Inject constructor( entry.setGroupExpansionChanging(true) userId = entry.sbn.userId } - var fullShadeNeedsBouncer = (!lockScreenUserManager.userAllowsPrivateNotificationsInPublic( - lockScreenUserManager.getCurrentUserId()) || - !lockScreenUserManager.shouldShowLockscreenNotifications() || - falsingCollector.shouldEnforceBouncer()) - if (keyguardBypassController.bypassEnabled) { - fullShadeNeedsBouncer = false + 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 } if (lockScreenUserManager.isLockscreenPublicMode(userId) && fullShadeNeedsBouncer) { statusBarStateController.setLeaveOpenOnKeyguardHide(true) @@ -911,4 +918,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 9a1a144924e2..5fd9671bda01 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManager.java @@ -71,17 +71,22 @@ public interface NotificationLockscreenUserManager { boolean shouldHideNotifications(String key); boolean shouldShowOnKeyguard(NotificationEntry entry); + void addOnNeedsRedactionInPublicChangedListener(Runnable listener); + + void removeOnNeedsRedactionInPublicChangedListener(Runnable listener); + boolean isAnyProfilePublicMode(); void updatePublicMode(); - boolean needsRedaction(NotificationEntry entry); + /** Does this notification require redaction if it is displayed when the device is public? */ + boolean notifNeedsRedactionInPublic(NotificationEntry entry); /** - * Has the given user chosen to allow their private (full) notifications to be shown even - * when the lockscreen is in "public" (secure & locked) mode? + * Do all sensitive notifications belonging to the given user require redaction when they are + * displayed in public? */ - boolean userAllowsPrivateNotificationsInPublic(int currentUserId); + boolean sensitiveNotifsNeedRedactionInPublic(int userId); /** * 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 56e09f03aa6b..334cfe5f4c41 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java @@ -24,7 +24,6 @@ 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; @@ -45,7 +44,6 @@ 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; @@ -60,6 +58,7 @@ 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; @@ -85,13 +84,12 @@ public class NotificationLockscreenUserManagerImpl implements private final DeviceProvisionedController mDeviceProvisionedController; private final KeyguardStateController mKeyguardStateController; private final SecureSettings mSecureSettings; + private final KeyguardUpdateMonitor mKeyguardUpdateMonitor; + private final Lazy<OverviewProxyService> mOverviewProxyService; private final Object mLock = new Object(); - - // Lazy - private NotificationEntryManager mEntryManager; - private final Lazy<NotificationVisibilityProvider> mVisibilityProviderLazy; private final Lazy<CommonNotifCollection> mCommonNotifCollectionLazy; + private final Lazy<NotificationEntryManager> mEntryManagerLazy; private final DevicePolicyManager mDevicePolicyManager; private final SparseBooleanArray mLockscreenPublicMode = new SparseBooleanArray(); private final SparseBooleanArray mUsersWithSeparateWorkChallenge = new SparseBooleanArray(); @@ -103,13 +101,14 @@ public class NotificationLockscreenUserManagerImpl implements private final List<UserChangedListener> mListeners = new ArrayList<>(); private final BroadcastDispatcher mBroadcastDispatcher; private final NotificationClickNotifier mClickNotifier; - - private boolean mShowLockscreenNotifications; - private boolean mAllowLockscreenRemoteInput; - private LockPatternUtils mLockPatternUtils; - protected KeyguardManager mKeyguardManager; - private int mState = StatusBarState.SHADE; - private List<KeyguardNotificationSuppressor> mKeyguardSuppressors = new ArrayList<>(); + private final LockPatternUtils mLockPatternUtils; + private final List<KeyguardNotificationSuppressor> mKeyguardSuppressors = new ArrayList<>(); + protected final Context mContext; + private final Handler mMainHandler; + protected final SparseArray<UserInfo> mCurrentProfiles = new SparseArray<>(); + protected final SparseArray<UserInfo> mCurrentManagedProfiles = new SparseArray<>(); + private final ListenerSet<Runnable> mOnSensitiveContentRedactionChangeListeners = + new ListenerSet<>(); protected final BroadcastReceiver mAllUsersReceiver = new BroadcastReceiver() { @Override @@ -120,7 +119,11 @@ public class NotificationLockscreenUserManagerImpl implements isCurrentProfile(getSendingUserId())) { mUsersAllowingPrivateNotifications.clear(); updateLockscreenNotificationSetting(); - getEntryManager().updateNotifications("ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED"); + for (Runnable listener : mOnSensitiveContentRedactionChangeListeners) { + listener.run(); + } + mEntryManagerLazy.get() + .updateNotifications("ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED"); } } }; @@ -142,7 +145,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 - getEntryManager().reapplyFilterAndSort("user switched"); + mEntryManagerLazy.get().reapplyFilterAndSort("user switched"); mPresenter.onUserSwitched(mCurrentUserId); for (UserChangedListener listener : mListeners) { @@ -156,7 +159,7 @@ public class NotificationLockscreenUserManagerImpl implements break; case Intent.ACTION_USER_UNLOCKED: // Start the overview connection to the launcher service - Dependency.get(OverviewProxyService.class).startConnectionToCurrentUser(); + mOverviewProxyService.get().startConnectionToCurrentUser(); break; case NOTIFICATION_UNLOCKED_BY_WORK_CHALLENGE_ACTION: final IntentSender intentSender = intent.getParcelableExtra( @@ -179,28 +182,26 @@ public class NotificationLockscreenUserManagerImpl implements } }; - protected final Context mContext; - private final Handler mMainHandler; - protected final SparseArray<UserInfo> mCurrentProfiles = new SparseArray<>(); - protected final SparseArray<UserInfo> mCurrentManagedProfiles = new SparseArray<>(); - - protected int mCurrentUserId = 0; + // Late-init protected NotificationPresenter mPresenter; protected ContentObserver mLockscreenSettingsObserver; protected ContentObserver mSettingsObserver; - private boolean mHideSilentNotificationsOnLockscreen; + protected KeyguardManager mKeyguardManager; - private NotificationEntryManager getEntryManager() { - if (mEntryManager == null) { - mEntryManager = Dependency.get(NotificationEntryManager.class); - } - return mEntryManager; - } + protected int mCurrentUserId = 0; + private int mState = StatusBarState.SHADE; + private boolean mHideSilentNotificationsOnLockscreen; + private boolean mShowLockscreenNotifications; + private boolean mAllowLockscreenRemoteInput; @Inject - public NotificationLockscreenUserManagerImpl(Context context, + public NotificationLockscreenUserManagerImpl( + Context context, BroadcastDispatcher broadcastDispatcher, DevicePolicyManager devicePolicyManager, + KeyguardUpdateMonitor keyguardUpdateMonitor, + Lazy<NotificationEntryManager> notificationEntryManagerLazy, + Lazy<OverviewProxyService> overviewProxyServiceLazy, UserManager userManager, Lazy<NotificationVisibilityProvider> visibilityProviderLazy, Lazy<CommonNotifCollection> commonNotifCollectionLazy, @@ -216,9 +217,11 @@ 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); @@ -227,10 +230,12 @@ public class NotificationLockscreenUserManagerImpl implements mDeviceProvisionedController = deviceProvisionedController; mSecureSettings = secureSettings; mKeyguardStateController = keyguardStateController; + mKeyguardUpdateMonitor = keyguardUpdateMonitor; dumpManager.registerDumpable(this); } + @Override public void setUpWithPresenter(NotificationPresenter presenter) { mPresenter = presenter; @@ -243,7 +248,10 @@ public class NotificationLockscreenUserManagerImpl implements mUsersAllowingNotifications.clear(); // ... and refresh all the notifications updateLockscreenNotificationSetting(); - getEntryManager().updateNotifications("LOCK_SCREEN_SHOW_NOTIFICATIONS," + for (Runnable listener : mOnSensitiveContentRedactionChangeListeners) { + listener.run(); + } + mEntryManagerLazy.get().updateNotifications("LOCK_SCREEN_SHOW_NOTIFICATIONS," + " or LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS change"); } }; @@ -253,7 +261,7 @@ public class NotificationLockscreenUserManagerImpl implements public void onChange(boolean selfChange) { updateLockscreenNotificationSetting(); if (mDeviceProvisionedController.isDeviceProvisioned()) { - getEntryManager().updateNotifications("LOCK_SCREEN_ALLOW_REMOTE_INPUT" + mEntryManagerLazy.get().updateNotifications("LOCK_SCREEN_ALLOW_REMOTE_INPUT" + " or ZEN_MODE change"); } } @@ -312,14 +320,17 @@ 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; @@ -334,7 +345,7 @@ public class NotificationLockscreenUserManagerImpl implements if (userId == UserHandle.USER_ALL) { userId = mCurrentUserId; } - boolean inLockdown = Dependency.get(KeyguardUpdateMonitor.class).isUserInLockdown(userId); + boolean inLockdown = mKeyguardUpdateMonitor.isUserInLockdown(userId); mUsersInLockdownLatestResult.put(userId, inLockdown); return inLockdown; } @@ -343,6 +354,7 @@ 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)) @@ -355,6 +367,7 @@ 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()); @@ -365,6 +378,7 @@ 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()); @@ -387,14 +401,6 @@ 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, @@ -408,7 +414,7 @@ public class NotificationLockscreenUserManagerImpl implements mHideSilentNotificationsOnLockscreen = mSecureSettings.getIntForUser( Settings.Secure.LOCK_SCREEN_SHOW_SILENT_NOTIFICATIONS, 1, mCurrentUserId) == 0; - setShowLockscreenNotifications(show && allowedByDpm); + mShowLockscreenNotifications = show && allowedByDpm; if (ENABLE_LOCK_SCREEN_ALLOW_REMOTE_INPUT) { final boolean remoteInput = mSecureSettings.getIntForUser( @@ -418,9 +424,9 @@ public class NotificationLockscreenUserManagerImpl implements final boolean remoteInputDpm = (dpmFlags & DevicePolicyManager.KEYGUARD_DISABLE_REMOTE_INPUT) == 0; - setLockscreenAllowRemoteInput(remoteInput && remoteInputDpm); + mAllowLockscreenRemoteInput = remoteInput && remoteInputDpm; } else { - setLockscreenAllowRemoteInput(false); + mAllowLockscreenRemoteInput = false; } } @@ -428,7 +434,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? */ - public boolean userAllowsPrivateNotificationsInPublic(int userHandle) { + protected boolean userAllowsPrivateNotificationsInPublic(int userHandle) { if (userHandle == UserHandle.USER_ALL) { return true; } @@ -473,10 +479,12 @@ 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); @@ -493,6 +501,7 @@ 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; @@ -513,36 +522,37 @@ public class NotificationLockscreenUserManagerImpl implements } /** @return true if the entry needs redaction when on the lockscreen. */ - public boolean needsRedaction(NotificationEntry ent) { + @Override + public boolean notifNeedsRedactionInPublic(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 - boolean isNotifRedacted = (!isNotifForManagedProfile && isCurrentUserRedactingNotifs) - || isNotifUserRedacted; - - boolean notificationRequestsRedaction = - ent.getSbn().getNotification().visibility == Notification.VISIBILITY_PRIVATE; - boolean userForcesRedaction = packageHasVisibilityOverride(ent.getSbn().getKey()); + return (!isNotifForManagedProfile && isCurrentUserRedactingNotifs) || isNotifUserRedacted; + } - return userForcesRedaction || notificationRequestsRedaction && isNotifRedacted; + @Override + public void addOnNeedsRedactionInPublicChangedListener(Runnable listener) { + mOnSensitiveContentRedactionChangeListeners.addIfAbsent(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; + @Override + public void removeOnNeedsRedactionInPublicChangedListener(Runnable listener) { + mOnSensitiveContentRedactionChangeListeners.remove(listener); } private void updateCurrentProfilesCache() { @@ -562,12 +572,16 @@ 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--) { @@ -596,10 +610,12 @@ 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<UserInfo> getCurrentProfiles() { return mCurrentProfiles; } @@ -640,7 +656,8 @@ public class NotificationLockscreenUserManagerImpl implements setLockscreenPublicMode(isProfilePublic, userId); mUsersWithSeparateWorkChallenge.put(userId, needsSeparateChallenge); } - getEntryManager().updateNotifications("NotificationLockscreenUserManager.updatePublicMode"); + mEntryManagerLazy.get() + .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 054543c7d2b1..30cb09d56f17 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java @@ -53,6 +53,7 @@ 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; @@ -207,12 +208,9 @@ public class NotificationViewHierarchyManager implements DynamicPrivacyControlle || !mLockscreenUserManager.needsSeparateWorkChallenge(userId))) { userPublic = false; } - boolean needsRedaction = mLockscreenUserManager.needsRedaction(ent); + boolean needsRedaction = mLockscreenUserManager.notifNeedsRedactionInPublic(ent); boolean sensitive = userPublic && needsRedaction; - boolean deviceSensitive = devicePublic - && !mLockscreenUserManager.userAllowsPrivateNotificationsInPublic( - currentUserId); - ent.setSensitive(sensitive, deviceSensitive); + ent.getRow().setSensitive(sensitive); ent.getRow().setNeedsRedaction(needsRedaction); mLowPriorityInflationHelper.recheckLowPriorityViewAndInflate(ent, ent.getRow()); boolean isChildInGroup = mGroupManager.isChildInGroup(ent); @@ -365,6 +363,8 @@ public class NotificationViewHierarchyManager implements DynamicPrivacyControlle boolean hasClearableAlertingNotifs = false; boolean hasNonClearableSilentNotifs = false; boolean hasClearableSilentNotifs = false; + HashSet<Integer> clearableAlertingSensitiveNotifUsers = new HashSet<>(); + HashSet<Integer> clearableSilentSensitiveNotifUsers = new HashSet<>(); final int childCount = mListContainer.getContainerChildCount(); int visibleTopLevelEntries = 0; for (int i = 0; i < childCount; i++) { @@ -376,10 +376,11 @@ public class NotificationViewHierarchyManager implements DynamicPrivacyControlle continue; } final ExpandableNotificationRow row = (ExpandableNotificationRow) child; - boolean isSilent = row.getEntry().getBucket() == BUCKET_SILENT; + NotificationEntry entry = row.getEntry(); + boolean isSilent = entry.getBucket() == BUCKET_SILENT; // NOTE: NotificationEntry.isClearable() will internally check group children to ensure // the group itself definitively clearable. - boolean isClearable = row.getEntry().isClearable(); + boolean isClearable = entry.isClearable(); visibleTopLevelEntries++; if (isSilent) { if (isClearable) { @@ -394,13 +395,24 @@ 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 */ + hasClearableSilentNotifs /* hasClearableSilentNotifs */, + clearableAlertingSensitiveNotifUsers /* clearableAlertingSensitiveNotifUsers */, + clearableSilentSensitiveNotifUsers /* clearableSilentSensitiveNotifUsers */ + )); 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 a0ccd5726c75..d16e9e5d7faf 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.userAllowsPrivateNotificationsInPublic( + return mLockscreenUserManager.sensitiveNotifsNeedRedactionInPublic( mLockscreenUserManager.getCurrentUserId()); } @@ -95,6 +95,10 @@ 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 4fc347a09292..e3c39ddad145 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,9 +169,6 @@ public final class NotificationEntry extends ListEntry { */ private boolean hasSentReply; - private boolean mSensitive = true; - private List<OnSensitivityChangedListener> mOnSensitivityChangedListeners = new ArrayList<>(); - private boolean mAutoHeadsUp; private boolean mPulseSupressed; private int mBucket = BUCKET_ALERTING; @@ -867,33 +864,29 @@ public final class NotificationEntry extends ListEntry { } /** - * 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 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); - } + * 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. + */ + public int getLockscreenVisibility() { + int setting = mRanking.getLockscreenVisibilityOverride(); + if (setting == Ranking.VISIBILITY_NO_OVERRIDE) { + setting = mSbn.getNotification().visibility; } + return setting; } - 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); + /** + * 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 isPulseSuppressed() { @@ -954,12 +947,6 @@ 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 3516625cc471..b24d2922adfb 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,7 +56,6 @@ class NotifCoordinatorsImpl @Inject constructor( smartspaceDedupingCoordinator: SmartspaceDedupingCoordinator, viewConfigCoordinator: ViewConfigCoordinator, visualStabilityCoordinator: VisualStabilityCoordinator, - sensitiveContentCoordinator: SensitiveContentCoordinator, activityLaunchAnimCoordinator: ActivityLaunchAnimCoordinator ) : NotifCoordinators { @@ -94,7 +93,6 @@ class NotifCoordinatorsImpl @Inject constructor( mCoordinators.add(shadeEventCoordinator) mCoordinators.add(viewConfigCoordinator) mCoordinators.add(visualStabilityCoordinator) - mCoordinators.add(sensitiveContentCoordinator) mCoordinators.add(activityLaunchAnimCoordinator) 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 57fd1975e13a..56484010c213 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,7 +16,6 @@ package com.android.systemui.statusbar.notification.collection.coordinator; -import android.annotation.NonNull; import android.annotation.Nullable; import com.android.systemui.plugins.statusbar.StatusBarStateController; @@ -29,13 +28,11 @@ 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; @@ -53,10 +50,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 boolean mHasSilentEntries; - private boolean mHasMinimizedEntries; + private final AlertingNotifSectioner mAlertingNotifSectioner = new AlertingNotifSectioner(); + private final SilentNotifSectioner mSilentNotifSectioner = new SilentNotifSectioner(); + private final MinimizedNotifSectioner mMinimizedNotifSectioner = new MinimizedNotifSectioner(); @Inject public RankingCoordinator( @@ -64,14 +61,12 @@ 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 @@ -95,8 +90,44 @@ public class RankingCoordinator implements Coordinator { return mMinimizedNotifSectioner; } - private final NotifSectioner mAlertingNotifSectioner = new NotifSectioner("Alerting", - NotificationPriorityBucketKt.BUCKET_ALERTING) { + /** + * 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, + * so we don't need to explicitly invalidate this filter on ranking update. + */ + private final NotifFilter mSuspendedFilter = new NotifFilter("IsSuspendedFilter") { + @Override + public boolean shouldFilterOut(NotificationEntry entry, long now) { + return entry.getRanking().isSuspended(); + } + }; + + private final NotifFilter mDndVisualEffectsFilter = new NotifFilter( + "DndSuppressingVisualEffects") { + @Override + public boolean shouldFilterOut(NotificationEntry entry, long now) { + if (mStatusBarStateController.isDozing() && entry.shouldSuppressAmbient()) { + return true; + } + + return !mStatusBarStateController.isDozing() && entry.shouldSuppressNotificationList(); + } + }; + + private final StatusBarStateController.StateListener mStatusBarStateCallback = + new StatusBarStateController.StateListener() { + @Override + public void onDozingChanged(boolean isDozing) { + mDndVisualEffectsFilter.invalidateList(); + } + }; + + private class AlertingNotifSectioner extends NotifSectioner { + + AlertingNotifSectioner() { + super("Alerting", NotificationPriorityBucketKt.BUCKET_ALERTING); + } + @Override public boolean isInSection(ListEntry entry) { return mHighPriorityProvider.isHighPriority(entry); @@ -111,10 +142,14 @@ public class RankingCoordinator implements Coordinator { } return null; } - }; + } + + private class SilentNotifSectioner extends NotifSectioner { + + SilentNotifSectioner() { + super("Silent", NotificationPriorityBucketKt.BUCKET_SILENT); + } - private final NotifSectioner mSilentNotifSectioner = new NotifSectioner("Silent", - NotificationPriorityBucketKt.BUCKET_SILENT) { @Override public boolean isInSection(ListEntry entry) { return !mHighPriorityProvider.isHighPriority(entry) @@ -126,24 +161,14 @@ public class RankingCoordinator implements Coordinator { public NodeController getHeaderNodeController() { return mSilentNodeController; } + } - @Nullable - @Override - public void onEntriesUpdated(@NonNull List<ListEntry> 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 class MinimizedNotifSectioner extends NotifSectioner { + + MinimizedNotifSectioner() { + super("Minimized", NotificationPriorityBucketKt.BUCKET_SILENT); } - }; - private final NotifSectioner mMinimizedNotifSectioner = new NotifSectioner("Minimized", - NotificationPriorityBucketKt.BUCKET_SILENT) { @Override public boolean isInSection(ListEntry entry) { return !mHighPriorityProvider.isHighPriority(entry) @@ -155,51 +180,5 @@ public class RankingCoordinator implements Coordinator { public NodeController getHeaderNodeController() { return mSilentNodeController; } - - @Nullable - @Override - public void onEntriesUpdated(@NonNull List<ListEntry> 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, - * so we don't need to explicitly invalidate this filter on ranking update. - */ - private final NotifFilter mSuspendedFilter = new NotifFilter("IsSuspendedFilter") { - @Override - public boolean shouldFilterOut(NotificationEntry entry, long now) { - return entry.getRanking().isSuspended(); - } - }; - - private final NotifFilter mDndVisualEffectsFilter = new NotifFilter( - "DndSuppressingVisualEffects") { - @Override - public boolean shouldFilterOut(NotificationEntry entry, long now) { - if (mStatusBarStateController.isDozing() && entry.shouldSuppressAmbient()) { - return true; - } - - return !mStatusBarStateController.isDozing() && entry.shouldSuppressNotificationList(); - } - }; - - private final StatusBarStateController.StateListener mStatusBarStateCallback = - new StatusBarStateController.StateListener() { - @Override - public void onDozingChanged(boolean isDozing) { - mDndVisualEffectsFilter.invalidateList(); - } - }; + } } 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 deleted file mode 100644 index 3f8a39f62dfb..000000000000 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinator.kt +++ /dev/null @@ -1,124 +0,0 @@ -/* - * 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<ListEntry>) { - if (keyguardStateController.isKeyguardGoingAway() || - statusBarStateController.getState() == StatusBarState.KEYGUARD && - keyguardUpdateMonitor.getUserUnlockedWithBiometricAndIsBypassing( - KeyguardUpdateMonitor.getCurrentUser())) { - // don't update yet if: - // - the keyguard is currently going away - // - LS is about to be dismissed by a biometric that bypasses LS (avoid notif flash) - - // TODO(b/206118999): merge this class with KeyguardCoordinator which ensures the - // dependent state changes invalidate the pipeline - return - } - - val currentUserId = lockscreenUserManager.currentUserId - val devicePublic = lockscreenUserManager.isLockscreenPublicMode(currentUserId) - val deviceSensitive = devicePublic && - !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<ListEntry> -): Sequence<NotificationEntry> = - entries.asSequence().flatMap(::extractAllRepresentativeEntries) - -private fun extractAllRepresentativeEntries(listEntry: ListEntry): Sequence<NotificationEntry> = - 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 1c96e8ceb27f..2374e9c58177 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,6 +50,8 @@ class StackCoordinator @Inject internal constructor( var hasClearableAlertingNotifs = false var hasNonClearableSilentNotifs = false var hasClearableSilentNotifs = false + val clearableAlertingSensitiveNotifUsers = mutableSetOf<Int>() + val clearableSilentSensitiveNotifUsers = mutableSetOf<Int>() entries.forEach { val section = checkNotNull(it.section) { "Null section for ${it.key}" } val entry = checkNotNull(it.representativeEntry) { "Null notif entry for ${it.key}" } @@ -63,13 +65,22 @@ 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 + hasClearableSilentNotifs = hasClearableSilentNotifs, + clearableAlertingSensitiveNotifUsers = clearableAlertingSensitiveNotifUsers, + clearableSilentSensitiveNotifUsers = clearableSilentSensitiveNotifUsers ) } }
\ 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 274affd9da43..8ecffcb7670a 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 @@ -20,7 +20,6 @@ import com.android.systemui.dagger.SysUISingleton import com.android.systemui.statusbar.notification.collection.coordinator.ActivityLaunchAnimCoordinatorModule 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 @@ -50,7 +49,6 @@ interface CoordinatorsSubcomponent { @Module(includes = [ ActivityLaunchAnimCoordinatorModule::class, - 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 4c7b2bbfb6d9..6e96aad776d2 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,6 +16,8 @@ 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; @@ -249,10 +251,13 @@ public class NotificationRowBinderImpl implements NotificationRowBinder { RowContentBindParams params = mRowContentBindStage.getStageParams(entry); params.setUseIncreasedCollapsedHeight(useIncreasedCollapsedHeight); params.setUseLowPriority(isLowPriority); - - // TODO: Replace this API with RowContentBindParams directly. Also move to a separate - // redaction controller. - row.setNeedsRedaction(mNotificationLockscreenUserManager.needsRedaction(entry)); + boolean needsRedaction = + mNotificationLockscreenUserManager.notifNeedsRedactionInPublic(entry); + if (needsRedaction) { + params.requireContentViews(FLAG_CONTENT_VIEW_PUBLIC); + } else { + params.markContentViewsFreeable(FLAG_CONTENT_VIEW_PUBLIC); + } 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 b6278d1d5f01..580d853dc5e9 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,11 +28,21 @@ data class NotifStats( val hasNonClearableAlertingNotifs: Boolean, val hasClearableAlertingNotifs: Boolean, val hasNonClearableSilentNotifs: Boolean, - val hasClearableSilentNotifs: Boolean + val hasClearableSilentNotifs: Boolean, + val clearableAlertingSensitiveNotifUsers: Set<Int>, + val clearableSilentSensitiveNotifUsers: Set<Int> ) { companion object { @JvmStatic - val empty = NotifStats(0, false, false, false, false) + val empty = NotifStats( + numActiveNotifs = 0, + hasNonClearableAlertingNotifs = false, + hasClearableAlertingNotifs = false, + hasNonClearableSilentNotifs = false, + hasClearableSilentNotifs = false, + clearableAlertingSensitiveNotifUsers = emptySet(), + clearableSilentSensitiveNotifUsers = emptySet(), + ) } } 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 2a9cfd034dce..f58918fe6f80 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
\ No newline at end of file +annotation class SectionHeaderScope 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 d8965418b4c4..015e3d8cd553 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,6 +28,7 @@ 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 @@ -49,31 +50,29 @@ import javax.inject.Inject class IconManager @Inject constructor( private val notifCollection: CommonNotifCollection, private val launcherApps: LauncherApps, - private val iconBuilder: IconBuilder + private val iconBuilder: IconBuilder, + private val notifLockscreenUserManager: NotificationLockscreenUserManager ) : ConversationIconManager { private var unimportantConversationKeys: Set<String> = 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 = NotificationEntry.OnSensitivityChangedListener { - entry -> updateIconsSafe(entry) + private val sensitivityListener = Runnable { + for (entry in notifCollection.allNotifs) { + if (entry.hasSensitiveContents()) { + updateIconsSafe(entry) + } + } } private fun recalculateForImportantConversationChange() { @@ -182,12 +181,16 @@ 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<StatusBarIcon, StatusBarIcon> { val iconDescriptor = getIconDescriptor(entry, false /* redact */) - val sensitiveDescriptor = if (entry.isSensitive) { + val sensitiveDescriptor = if (entry.needsRedactionInPublic) { getIconDescriptor(entry, true /* redact */) } else { iconDescriptor @@ -310,7 +313,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.isSensitive) + (!usedInSensitiveContext || !entry.needsRedactionInPublic) } private fun isImportantConversation(entry: NotificationEntry): Boolean { @@ -338,4 +341,4 @@ interface ConversationIconManager { * of a group from which the priority notification has been removed. */ fun setUnimportantConversations(keys: Collection<String>) -}
\ 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 dff8c47e36e0..ed69e0609096 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 @@ -93,8 +93,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.LaunchAnimationParameters; import com.android.systemui.statusbar.notification.FeedbackIcon; +import com.android.systemui.statusbar.notification.LaunchAnimationParameters; import com.android.systemui.statusbar.notification.NotificationFadeAware; import com.android.systemui.statusbar.notification.NotificationLaunchAnimatorController; import com.android.systemui.statusbar.notification.NotificationUtils; @@ -206,7 +206,6 @@ 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; @@ -1538,6 +1537,7 @@ 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) { @@ -2622,9 +2622,8 @@ public class ExpandableNotificationRow extends ActivatableNotificationView getShowingLayout().requestSelectLayout(needsAnimation || isUserLocked()); } - public void setSensitive(boolean sensitive, boolean hideSensitive) { + public void setSensitive(boolean sensitive) { mSensitive = sensitive; - mSensitiveHiddenInGeneral = hideSensitive; } @Override @@ -2714,7 +2713,15 @@ public class ExpandableNotificationRow extends ActivatableNotificationView * see {@link NotificationEntry#isDismissable()}. */ public boolean canViewBeDismissed() { - return mEntry.isDismissable() && (!shouldShowPublic() || !mSensitiveHiddenInGeneral); + // 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; } /** @@ -2723,7 +2730,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView * clearability see {@link NotificationEntry#isClearable()}. */ public boolean canViewBeCleared() { - return mEntry.isClearable() && (!shouldShowPublic() || !mSensitiveHiddenInGeneral); + return mEntry.isClearable() && !shouldShowPublic(); } private boolean shouldShowPublic() { @@ -3487,10 +3494,28 @@ public class ExpandableNotificationRow extends ActivatableNotificationView pw.print(", translation: " + getTranslation()); pw.print(", removed: " + isRemoved()); pw.print(", expandAnimationRunning: " + mExpandAnimationRunning); - NotificationContentView showingLayout = getShowingLayout(); - pw.print(", privateShowing: " + (showingLayout == mPrivateLayout)); - pw.println(); - showingLayout.dump(pw, args); + 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"); + } if (getViewState() != null) { getViewState().dump(pw, args); @@ -3516,8 +3541,6 @@ 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 599039d46556..a60026c7a97b 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,6 +35,7 @@ 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; @@ -69,6 +70,7 @@ 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; @@ -86,7 +88,6 @@ 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; @@ -100,12 +101,12 @@ public class ExpandableNotificationRowController implements NotifViewController private final Optional<BubblesManager> 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, @@ -135,6 +136,7 @@ public class ExpandableNotificationRowController implements NotifViewController Optional<BubblesManager> bubblesManagerOptional, ExpandableNotificationRowDragController dragController) { mView = view; + mLockscreenUserManager = lockscreenUserManager; mListContainer = listContainer; mRemoteInputViewSubcomponentFactory = rivSubcomponentFactory; mActivatableNotificationViewController = activatableNotificationViewController; @@ -214,6 +216,10 @@ 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) { @@ -232,6 +238,14 @@ 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 @@ -333,4 +347,5 @@ 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 ba26cfaa30b4..a7c6bfb0289c 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,6 +61,7 @@ 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; @@ -1994,22 +1995,33 @@ public class NotificationContentView extends FrameLayout implements Notification } } - public void dump(PrintWriter pw, String[] args) { + public void dump(PrintWriter pwOriginal, String[] args) { + IndentingPrintWriter pw = DumpUtilsKt.asIndenting(pwOriginal); pw.print("contentView visibility: " + getVisibility()); pw.print(", alpha: " + getAlpha()); pw.print(", clipBounds: " + getClipBounds()); pw.print(", contentHeight: " + mContentHeight); - 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(); + 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(); + } + }); } /** 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 f26ecc32821d..a52f638e7c26 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,8 +102,9 @@ public final class RowContentBindParams { * @see InflationFlag */ public void markContentViewsFreeable(@InflationFlag int contentViews) { + @InflationFlag int existingContentViews = contentViews &= mContentViews; mContentViews &= ~contentViews; - mDirtyContentViews &= ~contentViews; + mDirtyContentViews |= existingContentViews; } 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 2493ccbe5a48..6a8f4796813a 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,6 +216,9 @@ public class NotificationStackScrollLayoutController { mBarState = mStatusBarStateController.getState(); mStatusBarStateController.addCallback( mStateListener, SysuiStatusBarStateController.RANK_STACK_SCROLLER); + mLockscreenUserManager.addOnNeedsRedactionInPublicChangedListener( + mOnNeedsRedactionInPublicChangedListener); + updateClearButtonVisibility(); } @Override @@ -223,6 +226,8 @@ public class NotificationStackScrollLayoutController { mConfigurationController.removeCallback(mConfigurationListener); mZenModeController.removeCallback(mZenModeControllerCallback); mStatusBarStateController.removeCallback(mStateListener); + mLockscreenUserManager.removeOnNeedsRedactionInPublicChangedListener( + mOnNeedsRedactionInPublicChangedListener); } }; @@ -326,6 +331,7 @@ public class NotificationStackScrollLayoutController { mLockscreenUserManager.isAnyProfilePublicMode()); mView.onStatePostChange(mStatusBarStateController.fromShadeLocked()); mNotificationEntryManager.updateNotifications("CentralSurfaces state changed"); + updateClearButtonVisibility(); } }; @@ -338,6 +344,17 @@ 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. */ @@ -1274,12 +1291,44 @@ 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 - ? mNotifStats.getHasClearableAlertingNotifs() + ? hasClearableAlertingNotifs() : mNotifStats.getHasNonClearableAlertingNotifs(); boolean hasSilentMatchingClearable = isClearable - ? mNotifStats.getHasClearableSilentNotifs() + ? hasClearableSilentNotifs() : mNotifStats.getHasNonClearableSilentNotifs(); switch (selection) { case ROWS_GENTLE: @@ -1579,6 +1628,15 @@ public class NotificationStackScrollLayoutController { mNotificationActivityStarter = activityStarter; } + private void updateClearButtonVisibility() { + updateClearSilentButton(); + updateFooter(); + } + + private void updateClearSilentButton() { + mSilentHeaderController.setClearSectionEnabled(hasClearableSilentNotifs()); + } + /** * Enum for UiEvent logged from this class */ @@ -1904,6 +1962,7 @@ 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 9863a0ed1ce0..f386797e322a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java @@ -29,6 +29,7 @@ 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; @@ -40,8 +41,8 @@ import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener; import com.android.systemui.util.ViewController; -import java.util.Optional; import java.util.ArrayList; +import java.util.Optional; import java.util.function.BiConsumer; import java.util.function.Consumer; @@ -61,17 +62,17 @@ public class HeadsUpAppearanceController extends ViewController<HeadsUpStatusBar private final NotificationIconAreaController mNotificationIconAreaController; private final HeadsUpManagerPhone mHeadsUpManager; private final NotificationStackScrollLayoutController mStackScrollerController; - private final DarkIconDispatcher mDarkIconDispatcher; private final NotificationPanelViewController mNotificationPanelViewController; - private final Consumer<ExpandableNotificationRow> - mSetTrackingHeadsUp = this::setTrackingHeadsUp; + private final Consumer<ExpandableNotificationRow> mSetTrackingHeadsUp = + this::setTrackingHeadsUp; private final BiConsumer<Float, Float> 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<View> mOperatorNameViewOptional; @@ -90,6 +91,13 @@ public class HeadsUpAppearanceController extends ViewController<HeadsUpStatusBar }; private boolean mAnimationsEnabled = true; private final KeyguardStateController mKeyguardStateController; + private final StatusBarStateController.StateListener mStatusBarStateListener = + new StatusBarStateController.StateListener() { + @Override + public void onStatePostChange() { + updateRedaction(); + } + }; @VisibleForTesting @Inject @@ -98,6 +106,7 @@ public class HeadsUpAppearanceController extends ViewController<HeadsUpStatusBar HeadsUpManagerPhone headsUpManager, StatusBarStateController stateController, KeyguardBypassController bypassController, + NotificationLockscreenUserManager notifLockscreenUserManager, NotificationWakeUpCoordinator wakeUpCoordinator, DarkIconDispatcher darkIconDispatcher, KeyguardStateController keyguardStateController, @@ -125,6 +134,7 @@ public class HeadsUpAppearanceController extends ViewController<HeadsUpStatusBar mClockView = clockView; mOperatorNameViewOptional = operatorNameViewOptional; mDarkIconDispatcher = darkIconDispatcher; + mNotifLockscreenUserManager = notifLockscreenUserManager; mView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() { @Override @@ -156,6 +166,8 @@ public class HeadsUpAppearanceController extends ViewController<HeadsUpStatusBar mNotificationPanelViewController.setHeadsUpAppearanceController(this); mStackScrollerController.addOnExpandedHeightChangedListener(mSetExpandedHeight); mDarkIconDispatcher.addDarkReceiver(this); + mNotifLockscreenUserManager.addOnNeedsRedactionInPublicChangedListener(mRedactionChanged); + mStatusBarStateController.addCallback(mStatusBarStateListener); } @Override @@ -167,6 +179,9 @@ public class HeadsUpAppearanceController extends ViewController<HeadsUpStatusBar mNotificationPanelViewController.setHeadsUpAppearanceController(null); mStackScrollerController.removeOnExpandedHeightChangedListener(mSetExpandedHeight); mDarkIconDispatcher.removeDarkReceiver(this); + mNotifLockscreenUserManager + .removeOnNeedsRedactionInPublicChangedListener(mRedactionChanged); + mStatusBarStateController.removeCallback(mStatusBarStateListener); } private void updateIsolatedIconLocation(boolean requireStateUpdate) { @@ -180,6 +195,19 @@ public class HeadsUpAppearanceController extends ViewController<HeadsUpStatusBar updateHeader(entry); } + private void updateRedaction() { + NotificationEntry showingEntry = mView.getShowingEntry(); + if (showingEntry == null) { + return; + } + int notifUserId = showingEntry.getSbn().getUserId(); + boolean redactSensitiveContent = + mNotifLockscreenUserManager.isLockscreenPublicMode(notifUserId) + && mNotifLockscreenUserManager + .sensitiveNotifsNeedRedactionInPublic(notifUserId); + mView.setRedactSensitiveContent(redactSensitiveContent); + } + private void updateTopEntry() { NotificationEntry newEntry = null; if (shouldBeVisible()) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java index d241b90de797..f15ea627af47 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java @@ -32,7 +32,6 @@ import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_N import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_QUICK_SETTINGS_EXPANDED; import static com.android.systemui.statusbar.StatusBarState.KEYGUARD; import static com.android.systemui.statusbar.StatusBarState.SHADE; -import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.ROWS_ALL; import static com.android.systemui.statusbar.notification.stack.StackStateAnimator.ANIMATION_DURATION_FOLD_TO_AOD; import static com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManagerKt.STATE_CLOSED; import static com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManagerKt.STATE_OPEN; @@ -3944,10 +3943,6 @@ public class NotificationPanelViewController extends PanelViewController { } } - public boolean hasActiveClearableNotifications() { - return mNotificationStackScrollLayoutController.hasActiveClearableNotifications(ROWS_ALL); - } - public RemoteInputController.Delegate createRemoteInputDelegate() { return mNotificationStackScrollLayoutController.createDelegate(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java index aa061d74f6c6..037063f4f7b0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java @@ -411,8 +411,8 @@ class StatusBarNotificationPresenter implements NotificationPresenter, if (nowExpanded) { if (mStatusBarStateController.getState() == StatusBarState.KEYGUARD) { mShadeTransitionController.goToLockedShade(clickedEntry.getRow()); - } else if (clickedEntry.isSensitive() - && mDynamicPrivacyController.isInLockedDownShade()) { + } else if (mDynamicPrivacyController.isInLockedDownShade() + && mLockscreenUserManager.notifNeedsRedactionInPublic(clickedEntry)) { mStatusBarStateController.setLeaveOpenOnKeyguardHide(true); mActivityStarter.dismissKeyguardThenExecute(() -> 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.needsRedaction(entry); + boolean needsRedaction = mLockscreenUserManager.notifNeedsRedactionInPublic(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 562c97017862..73e574eddd17 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.userAllowsPrivateNotificationsInPublic(anyInt())).thenReturn( - true) + whenever(lockScreenUserManager.sensitiveNotifsNeedRedactionInPublic(anyInt())) + .thenReturn(false) 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.userAllowsPrivateNotificationsInPublic(anyInt())).thenReturn( - false) + whenever(lockScreenUserManager.sensitiveNotifsNeedRedactionInPublic(anyInt())) + .thenReturn(true) 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 7687d1204541..18937e784ed1 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java @@ -53,11 +53,13 @@ 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; @@ -106,6 +108,10 @@ 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; @@ -119,7 +125,6 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase { @Before public void setUp() { MockitoAnnotations.initMocks(this); - mDependency.injectTestDependency(NotificationEntryManager.class, mEntryManager); int currentUserId = ActivityManager.getCurrentUser(); mSettings = new FakeSettings(); @@ -212,7 +217,7 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase { mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false); // THEN current user's notification is redacted - assertTrue(mLockscreenUserManager.needsRedaction(mCurrentUserNotif)); + assertTrue(mLockscreenUserManager.notifNeedsRedactionInPublic(mCurrentUserNotif)); } @Test @@ -223,7 +228,7 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase { mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false); // THEN current user's notification isn't redacted - assertFalse(mLockscreenUserManager.needsRedaction(mCurrentUserNotif)); + assertFalse(mLockscreenUserManager.notifNeedsRedactionInPublic(mCurrentUserNotif)); } @Test @@ -234,7 +239,7 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase { mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false); // THEN work profile notification is redacted - assertTrue(mLockscreenUserManager.needsRedaction(mWorkProfileNotif)); + assertTrue(mLockscreenUserManager.notifNeedsRedactionInPublic(mWorkProfileNotif)); } @Test @@ -245,7 +250,7 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase { mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false); // THEN work profile notification isn't redacted - assertFalse(mLockscreenUserManager.needsRedaction(mWorkProfileNotif)); + assertFalse(mLockscreenUserManager.notifNeedsRedactionInPublic(mWorkProfileNotif)); } @Test @@ -260,11 +265,11 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase { mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false); // THEN the work profile notification doesn't need to be redacted - assertFalse(mLockscreenUserManager.needsRedaction(mWorkProfileNotif)); + assertFalse(mLockscreenUserManager.notifNeedsRedactionInPublic(mWorkProfileNotif)); // THEN the current user and secondary user notifications do need to be redacted - assertTrue(mLockscreenUserManager.needsRedaction(mCurrentUserNotif)); - assertTrue(mLockscreenUserManager.needsRedaction(mSecondaryUserNotif)); + assertTrue(mLockscreenUserManager.notifNeedsRedactionInPublic(mCurrentUserNotif)); + assertTrue(mLockscreenUserManager.notifNeedsRedactionInPublic(mSecondaryUserNotif)); } @Test @@ -279,11 +284,11 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase { mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false); // THEN the work profile notification needs to be redacted - assertTrue(mLockscreenUserManager.needsRedaction(mWorkProfileNotif)); + assertTrue(mLockscreenUserManager.notifNeedsRedactionInPublic(mWorkProfileNotif)); // THEN the current user and secondary user notifications don't need to be redacted - assertFalse(mLockscreenUserManager.needsRedaction(mCurrentUserNotif)); - assertFalse(mLockscreenUserManager.needsRedaction(mSecondaryUserNotif)); + assertFalse(mLockscreenUserManager.notifNeedsRedactionInPublic(mCurrentUserNotif)); + assertFalse(mLockscreenUserManager.notifNeedsRedactionInPublic(mSecondaryUserNotif)); } @Test @@ -298,7 +303,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.needsRedaction(mSecondaryUserNotif)); + assertTrue(mLockscreenUserManager.notifNeedsRedactionInPublic(mSecondaryUserNotif)); } @Test @@ -418,9 +423,12 @@ 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 7d06abf5cd67..e43ae0d2b22a 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.userAllowsPrivateNotificationsInPublic(anyInt())).thenReturn( - allow); + when(mLockScreenUserManager.sensitiveNotifsNeedRedactionInPublic(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 f4d8405a796e..5c2f5fa6bc1c 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,7 +23,6 @@ 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; @@ -33,7 +32,6 @@ 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; @@ -41,7 +39,6 @@ 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; @@ -49,7 +46,6 @@ 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; @@ -72,7 +68,6 @@ public class RankingCoordinatorTest extends SysuiTestCase { @Mock private NotifPipeline mNotifPipeline; @Mock private NodeController mAlertingHeaderController; @Mock private NodeController mSilentNodeController; - @Mock private SectionHeaderController mSilentHeaderController; @Captor private ArgumentCaptor<NotifFilter> mNotifFilterCaptor; @@ -94,7 +89,6 @@ public class RankingCoordinatorTest extends SysuiTestCase { mHighPriorityProvider, mSectionClassifier, mAlertingHeaderController, - mSilentHeaderController, mSilentNodeController); mEntry = spy(new NotificationEntryBuilder().build()); mEntry.setRanking(getRankingForUnfilteredNotif().build()); @@ -112,25 +106,6 @@ public class RankingCoordinatorTest extends SysuiTestCase { } @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 mEntry.setRanking(getRankingForUnfilteredNotif().build()); @@ -225,46 +200,6 @@ 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 deleted file mode 100644 index a2d8e3ddba24..000000000000 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinatorTest.kt +++ /dev/null @@ -1,268 +0,0 @@ -/* - * 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<Invalidator> { - verify(pipeline).addPreRenderInvalidator(capture()) - } - val dynamicPrivacyListener = withArgCaptor<DynamicPrivacyController.Listener> { - verify(dynamicPrivacyController).addListener(capture()) - } - - val invalidationListener = mock<Pluggable.PluggableListener<Invalidator>>() - invalidator.setInvalidationListener(invalidationListener) - - dynamicPrivacyListener.onDynamicPrivacyChanged() - - verify(invalidationListener).onPluggableInvalidated(invalidator) - } - - @Test - fun onBeforeRenderList_deviceUnlocked_notifDoesNotNeedRedaction() { - coordinator.attach(pipeline) - val onBeforeRenderListListener = withArgCaptor<OnBeforeRenderListListener> { - 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<OnBeforeRenderListListener> { - 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<OnBeforeRenderListListener> { - 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<OnBeforeRenderListListener> { - verify(pipeline).addOnBeforeRenderListListener(capture()) - } - - whenever(lockscreenUserManager.currentUserId).thenReturn(1) - whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(true) - whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1)).thenReturn(false) - whenever(dynamicPrivacyController.isDynamicallyUnlocked).thenReturn(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<OnBeforeRenderListListener> { - verify(pipeline).addOnBeforeRenderListListener(capture()) - } - - whenever(lockscreenUserManager.currentUserId).thenReturn(1) - whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(true) - whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1)).thenReturn(false) - whenever(dynamicPrivacyController.isDynamicallyUnlocked).thenReturn(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<OnBeforeRenderListListener> { - verify(pipeline).addOnBeforeRenderListListener(capture()) - } - - whenever(lockscreenUserManager.currentUserId).thenReturn(1) - whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(true) - whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1)).thenReturn(false) - whenever(dynamicPrivacyController.isDynamicallyUnlocked).thenReturn(true) - 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<OnBeforeRenderListListener> { - verify(pipeline).addOnBeforeRenderListListener(capture()) - } - - whenever(lockscreenUserManager.currentUserId).thenReturn(1) - whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(true) - whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1)).thenReturn(false) - whenever(dynamicPrivacyController.isDynamicallyUnlocked).thenReturn(true) - whenever(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<OnBeforeRenderListListener> { - verify(pipeline).addOnBeforeRenderListListener(capture()) - } - - whenever(lockscreenUserManager.currentUserId).thenReturn(1) - whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(true) - whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1)).thenReturn(false) - whenever(dynamicPrivacyController.isDynamicallyUnlocked).thenReturn(true) - whenever(statusBarStateController.getState()).thenReturn(StatusBarState.KEYGUARD) - whenever(keyguardUpdateMonitor.getUserUnlockedWithBiometricAndIsBypassing(any())) - .thenReturn(true) - - val entry = fakeNotification(2, true) - - onBeforeRenderListListener.onBeforeRenderList(listOf(entry)) - - verify(entry.representativeEntry!!, never()).setSensitive(any(), any()) - } - - private fun fakeNotification(notifUserId: Int, needsRedaction: Boolean): ListEntry { - val mockUserHandle = mock<UserHandle>().apply { - whenever(identifier).thenReturn(notifUserId) - } - val mockSbn: StatusBarNotification = mock<StatusBarNotification>().apply { - whenever(user).thenReturn(mockUserHandle) - } - val mockEntry = mock<NotificationEntry>().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 70266e401f8a..cf2fc7c3a5fe 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,6 +15,7 @@ */ 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 @@ -43,6 +44,11 @@ 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 @@ -61,7 +67,10 @@ class StackCoordinatorTest : SysuiTestCase() { afterRenderListListener = withArgCaptor { verify(pipeline).addOnAfterRenderListListener(capture()) } - entry = NotificationEntryBuilder().setSection(section).build() + entry = NotificationEntryBuilder() + .setSection(section) + .setUser(UserHandle.of(NOTIF_USER_ID)) + .build() } @Test @@ -74,13 +83,31 @@ 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)) + verify(stackController) + .setNotifStats( + NotifStats( + 1, + false, + true, + false, + false, + setOf(NOTIF_USER_ID), + emptySet())) } @Test fun testSetNotificationStats_clearableSilent() { whenever(section.bucket).thenReturn(BUCKET_SILENT) afterRenderListListener.onAfterRenderList(listOf(entry), stackController) - verify(stackController).setNotifStats(NotifStats(1, false, false, false, true)) + verify(stackController) + .setNotifStats( + NotifStats( + 1, + false, + false, + false, + true, + emptySet(), + setOf(NOTIF_USER_ID))) } } 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 b63e66f1ebe3..c7f7ec213b0c 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,11 +27,12 @@ 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 @@ -40,7 +41,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 @@ -48,15 +49,14 @@ 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,6 +65,7 @@ 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 @@ -83,13 +84,16 @@ 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) + iconManager = + IconManager(notifCollection, launcherApps, iconBuilder, notifLockscreenUserManager) } @Test fun testCreateIcons_importantConversation_shortcutIcon() { - val entry = notificationEntry(true, true, true) + val entry = notificationEntry() entry?.channel?.isImportantConversation = true entry?.let { iconManager.createIcons(it) @@ -99,7 +103,7 @@ class IconManagerTest: SysuiTestCase() { @Test fun testCreateIcons_importantConversation_messageIcon() { - val entry = notificationEntry(false, true, true) + val entry = notificationEntry(hasShortcut = false) entry?.channel?.isImportantConversation = true entry?.let { iconManager.createIcons(it) @@ -109,7 +113,7 @@ class IconManagerTest: SysuiTestCase() { @Test fun testCreateIcons_importantConversation_largeIcon() { - val entry = notificationEntry(false, false, true) + val entry = notificationEntry(hasShortcut = false, hasMessage = false) entry?.channel?.isImportantConversation = true entry?.let { iconManager.createIcons(it) @@ -119,7 +123,7 @@ class IconManagerTest: SysuiTestCase() { @Test fun testCreateIcons_importantConversation_smallIcon() { - val entry = notificationEntry(false, false, false) + val entry = notificationEntry(hasShortcut = false, hasMessage = false, hasLargeIcon = false) entry?.channel?.isImportantConversation = true entry?.let { iconManager.createIcons(it) @@ -129,7 +133,7 @@ class IconManagerTest: SysuiTestCase() { @Test fun testCreateIcons_notImportantConversation() { - val entry = notificationEntry(true, true, true) + val entry = notificationEntry() entry?.let { iconManager.createIcons(it) } @@ -138,8 +142,10 @@ class IconManagerTest: SysuiTestCase() { @Test fun testCreateIcons_sensitiveImportantConversation() { - val entry = notificationEntry(true, false, false) - entry?.setSensitive(true, true); + val entry = notificationEntry( + hasMessage = false, + hasLargeIcon = false, + hasSensitiveContent = true) entry?.channel?.isImportantConversation = true entry?.let { iconManager.createIcons(it) @@ -151,14 +157,17 @@ class IconManagerTest: SysuiTestCase() { @Test fun testUpdateIcons_sensitivityChange() { - val entry = notificationEntry(true, false, false) + val entry = notificationEntry( + hasMessage = false, + hasLargeIcon = false, + hasSensitiveContent = true) entry?.channel?.isImportantConversation = true - entry?.setSensitive(true, true); entry?.let { iconManager.createIcons(it) } assertEquals(entry?.icons?.aodIcon?.sourceIcon, smallIc) - entry?.setSensitive(false, false); + `when`(notifLockscreenUserManager.sensitiveNotifsNeedRedactionInPublic(TEST_UID)) + .thenReturn(false) entry?.let { iconManager.updateIcons(it) } @@ -166,14 +175,19 @@ class IconManagerTest: SysuiTestCase() { } private fun notificationEntry( - hasShortcut: Boolean, - hasMessage: Boolean, - hasLargeIcon: Boolean + hasShortcut: Boolean = true, + hasMessage: Boolean = true, + hasLargeIcon: Boolean = true, + hasSensitiveContent: Boolean = false ): 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("") @@ -203,7 +217,6 @@ 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 0f2e9bccc215..b3c34c1e4ff4 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, true); + mGroupRow.setSensitive(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, true); + mGroupRow.setSensitive(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, true); + row.setSensitive(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, true); + mGroupRow.setSensitive(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 251ac7d250fe..a8557050dddb 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,7 +78,6 @@ 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; @@ -132,7 +131,6 @@ 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; @@ -254,6 +252,7 @@ public class NotificationEntryManagerInflationTest extends SysuiTestCase { .thenAnswer((Answer<ExpandableNotificationRowController>) invocation -> new ExpandableNotificationRowController( viewCaptor.getValue(), + mLockscreenUserManager, mock(ActivatableNotificationViewController.class), mock(RemoteInputViewSubcomponent.Factory.class), mock(MetricsLogger.class), @@ -300,7 +299,8 @@ public class NotificationEntryManagerInflationTest extends SysuiTestCase { new IconManager( mEntryManager, mock(LauncherApps.class), - new IconBuilder(mContext)), + new IconBuilder(mContext), + mLockscreenUserManager), 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 1ecb09bc8514..d5ed37a570d2 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 @@ -52,6 +52,7 @@ 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; @@ -152,7 +153,8 @@ public class NotificationTestHelper { mIconManager = new IconManager( mock(CommonNotifCollection.class), mock(LauncherApps.class), - new IconBuilder(mContext)); + new IconBuilder(mContext), + mock(NotificationLockscreenUserManager.class)); 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 ed22cd3c55fc..169c04c692e0 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,6 +36,7 @@ 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; @@ -57,9 +58,12 @@ public class HeadsUpAppearanceControllerTest extends SysuiTestCase { private final NotificationStackScrollLayoutController mStackScrollerController = mock(NotificationStackScrollLayoutController.class); - private final NotificationPanelViewController mPanelView = + private final NotificationPanelViewController mPanelViewController = 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; @@ -93,12 +97,13 @@ public class HeadsUpAppearanceControllerTest extends SysuiTestCase { mHeadsUpManager, mStatusbarStateController, mBypassController, + mLockscreenUserManager, mWakeUpCoordinator, mDarkIconDispatcher, mKeyguardStateController, mCommandQueue, mStackScrollerController, - mPanelView, + mPanelViewController, mHeadsUpStatusBarView, new Clock(mContext, null), Optional.of(mOperatorNameView)); @@ -175,12 +180,13 @@ public class HeadsUpAppearanceControllerTest extends SysuiTestCase { mHeadsUpManager, mStatusbarStateController, mBypassController, + mLockscreenUserManager, mWakeUpCoordinator, mDarkIconDispatcher, mKeyguardStateController, mCommandQueue, mStackScrollerController, - mPanelView, + mPanelViewController, mHeadsUpStatusBarView, new Clock(mContext, null), Optional.empty()); @@ -193,15 +199,15 @@ public class HeadsUpAppearanceControllerTest extends SysuiTestCase { public void testDestroy() { reset(mHeadsUpManager); reset(mDarkIconDispatcher); - reset(mPanelView); + reset(mPanelViewController); reset(mStackScrollerController); mHeadsUpAppearanceController.onViewDetached(); verify(mHeadsUpManager).removeListener(any()); verify(mDarkIconDispatcher).removeDarkReceiver((DarkIconDispatcher.DarkReceiver) any()); - verify(mPanelView).removeTrackingHeadsUpListener(any()); - verify(mPanelView).setHeadsUpAppearanceController(isNull()); + verify(mPanelViewController).removeTrackingHeadsUpListener(any()); + verify(mPanelViewController).setHeadsUpAppearanceController(isNull()); verify(mStackScrollerController).removeOnExpandedHeightChangedListener(any()); } } |