summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/HeadsUpStatusBarView.java27
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt25
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManager.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java143
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java28
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/DynamicPrivacyController.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java53
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java129
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinator.kt124
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinator.kt13
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/dagger/CoordinatorsModule.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifStackController.kt14
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationSectionHeadersModule.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/IconManager.kt31
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java47
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java19
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java36
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowContentBindParams.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java63
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java38
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java6
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt8
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java36
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/DynamicPrivacyControllerTest.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinatorTest.java65
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinatorTest.kt268
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinatorTest.kt33
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/IconManagerTest.kt63
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java8
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationEntryManagerInflationTest.java6
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java18
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());
}
}