Merge "Revert "Don't show "Clear All" w/ redacted notifs"" into tm-dev

This commit is contained in:
Steve Elliott
2022-05-19 13:49:03 +00:00
committed by Android (Google) Code Review
35 changed files with 803 additions and 570 deletions

View File

@@ -29,6 +29,7 @@ import com.android.keyguard.AlphaOptimizedLinearLayout;
import com.android.systemui.R; import com.android.systemui.R;
import com.android.systemui.plugins.DarkIconDispatcher; import com.android.systemui.plugins.DarkIconDispatcher;
import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntry.OnSensitivityChangedListener;
import java.util.ArrayList; import java.util.ArrayList;
@@ -48,7 +49,6 @@ public class HeadsUpStatusBarView extends AlphaOptimizedLinearLayout {
private TextView mTextView; private TextView mTextView;
private NotificationEntry mShowingEntry; private NotificationEntry mShowingEntry;
private Runnable mOnDrawingRectChangedListener; private Runnable mOnDrawingRectChangedListener;
private boolean mRedactSensitiveContent;
public HeadsUpStatusBarView(Context context) { public HeadsUpStatusBarView(Context context) {
this(context, null); this(context, null);
@@ -111,28 +111,29 @@ public class HeadsUpStatusBarView extends AlphaOptimizedLinearLayout {
} }
public void setEntry(NotificationEntry entry) { public void setEntry(NotificationEntry entry) {
if (mShowingEntry != null) {
mShowingEntry.removeOnSensitivityChangedListener(mOnSensitivityChangedListener);
}
mShowingEntry = entry; mShowingEntry = entry;
if (mShowingEntry != null) { if (mShowingEntry != null) {
CharSequence text = entry.headsUpStatusBarText; CharSequence text = entry.headsUpStatusBarText;
if (mRedactSensitiveContent && entry.hasSensitiveContents()) { if (entry.isSensitive()) {
text = entry.headsUpStatusBarTextPublic; text = entry.headsUpStatusBarTextPublic;
} }
mTextView.setText(text); mTextView.setText(text);
mShowingEntry.addOnSensitivityChangedListener(mOnSensitivityChangedListener);
} }
} }
public void setRedactSensitiveContent(boolean redactSensitiveContent) { private final OnSensitivityChangedListener mOnSensitivityChangedListener = entry -> {
if (mRedactSensitiveContent == redactSensitiveContent) { if (entry != mShowingEntry) {
return; throw new IllegalStateException("Got a sensitivity change for " + entry
+ " but mShowingEntry is " + mShowingEntry);
} }
mRedactSensitiveContent = redactSensitiveContent; // Update the text
if (mShowingEntry != null && mShowingEntry.hasSensitiveContents()) { setEntry(entry);
mTextView.setText( };
mRedactSensitiveContent
? mShowingEntry.headsUpStatusBarTextPublic
: mShowingEntry.headsUpStatusBarText);
}
}
@Override @Override
protected void onLayout(boolean changed, int l, int t, int r, int b) { protected void onLayout(boolean changed, int l, int t, int r, int b) {

View File

@@ -386,7 +386,7 @@ class LockscreenShadeTransitionController @Inject constructor(
} }
if (view is ExpandableNotificationRow) { if (view is ExpandableNotificationRow) {
// Only drag down on sensitive views, otherwise the ExpandHelper will take this // Only drag down on sensitive views, otherwise the ExpandHelper will take this
return lockScreenUserManager.notifNeedsRedactionInPublic(view.entry) return view.entry.isSensitive
} }
} }
return false return false
@@ -552,8 +552,7 @@ class LockscreenShadeTransitionController @Inject constructor(
logger.logShadeDisabledOnGoToLockedShade() logger.logShadeDisabledOnGoToLockedShade()
return return
} }
val currentUser = lockScreenUserManager.currentUserId var userId: Int = lockScreenUserManager.getCurrentUserId()
var userId: Int = currentUser
var entry: NotificationEntry? = null var entry: NotificationEntry? = null
if (expandView is ExpandableNotificationRow) { if (expandView is ExpandableNotificationRow) {
entry = expandView.entry entry = expandView.entry
@@ -563,18 +562,12 @@ class LockscreenShadeTransitionController @Inject constructor(
entry.setGroupExpansionChanging(true) entry.setGroupExpansionChanging(true)
userId = entry.sbn.userId userId = entry.sbn.userId
} }
val fullShadeNeedsBouncer = when { var fullShadeNeedsBouncer = (!lockScreenUserManager.userAllowsPrivateNotificationsInPublic(
// No bouncer necessary if we're bypassing lockScreenUserManager.getCurrentUserId()) ||
keyguardBypassController.bypassEnabled -> false !lockScreenUserManager.shouldShowLockscreenNotifications() ||
// Redacted notificationss are present, bouncer should be shown before un-redacting in falsingCollector.shouldEnforceBouncer())
// the full shade if (keyguardBypassController.bypassEnabled) {
lockScreenUserManager.sensitiveNotifsNeedRedactionInPublic(currentUser) -> true fullShadeNeedsBouncer = false
// 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) { if (lockScreenUserManager.isLockscreenPublicMode(userId) && fullShadeNeedsBouncer) {
statusBarStateController.setLeaveOpenOnKeyguardHide(true) statusBarStateController.setLeaveOpenOnKeyguardHide(true)

View File

@@ -71,22 +71,17 @@ public interface NotificationLockscreenUserManager {
boolean shouldHideNotifications(String key); boolean shouldHideNotifications(String key);
boolean shouldShowOnKeyguard(NotificationEntry entry); boolean shouldShowOnKeyguard(NotificationEntry entry);
void addOnNeedsRedactionInPublicChangedListener(Runnable listener);
void removeOnNeedsRedactionInPublicChangedListener(Runnable listener);
boolean isAnyProfilePublicMode(); boolean isAnyProfilePublicMode();
void updatePublicMode(); void updatePublicMode();
/** Does this notification require redaction if it is displayed when the device is public? */ boolean needsRedaction(NotificationEntry entry);
boolean notifNeedsRedactionInPublic(NotificationEntry entry);
/** /**
* Do all sensitive notifications belonging to the given user require redaction when they are * Has the given user chosen to allow their private (full) notifications to be shown even
* displayed in public? * when the lockscreen is in "public" (secure & locked) mode?
*/ */
boolean sensitiveNotifsNeedRedactionInPublic(int userId); boolean userAllowsPrivateNotificationsInPublic(int currentUserId);
/** /**
* Has the given user chosen to allow notifications to be shown even when the lockscreen is in * Has the given user chosen to allow notifications to be shown even when the lockscreen is in

View File

@@ -24,6 +24,7 @@ import static com.android.systemui.statusbar.notification.stack.NotificationPrio
import android.app.ActivityManager; import android.app.ActivityManager;
import android.app.KeyguardManager; import android.app.KeyguardManager;
import android.app.Notification;
import android.app.NotificationManager; import android.app.NotificationManager;
import android.app.admin.DevicePolicyManager; import android.app.admin.DevicePolicyManager;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
@@ -44,6 +45,7 @@ import android.util.SparseBooleanArray;
import com.android.internal.statusbar.NotificationVisibility; import com.android.internal.statusbar.NotificationVisibility;
import com.android.internal.widget.LockPatternUtils; import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardUpdateMonitor; import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.Dependency;
import com.android.systemui.Dumpable; import com.android.systemui.Dumpable;
import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.SysUISingleton;
@@ -58,7 +60,6 @@ import com.android.systemui.statusbar.notification.collection.notifcollection.Co
import com.android.systemui.statusbar.notification.collection.render.NotificationVisibilityProvider; import com.android.systemui.statusbar.notification.collection.render.NotificationVisibilityProvider;
import com.android.systemui.statusbar.policy.DeviceProvisionedController; import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.util.ListenerSet;
import com.android.systemui.util.settings.SecureSettings; import com.android.systemui.util.settings.SecureSettings;
import java.io.PrintWriter; import java.io.PrintWriter;
@@ -84,12 +85,13 @@ public class NotificationLockscreenUserManagerImpl implements
private final DeviceProvisionedController mDeviceProvisionedController; private final DeviceProvisionedController mDeviceProvisionedController;
private final KeyguardStateController mKeyguardStateController; private final KeyguardStateController mKeyguardStateController;
private final SecureSettings mSecureSettings; private final SecureSettings mSecureSettings;
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
private final Lazy<OverviewProxyService> mOverviewProxyService;
private final Object mLock = new Object(); private final Object mLock = new Object();
// Lazy
private NotificationEntryManager mEntryManager;
private final Lazy<NotificationVisibilityProvider> mVisibilityProviderLazy; private final Lazy<NotificationVisibilityProvider> mVisibilityProviderLazy;
private final Lazy<CommonNotifCollection> mCommonNotifCollectionLazy; private final Lazy<CommonNotifCollection> mCommonNotifCollectionLazy;
private final Lazy<NotificationEntryManager> mEntryManagerLazy;
private final DevicePolicyManager mDevicePolicyManager; private final DevicePolicyManager mDevicePolicyManager;
private final SparseBooleanArray mLockscreenPublicMode = new SparseBooleanArray(); private final SparseBooleanArray mLockscreenPublicMode = new SparseBooleanArray();
private final SparseBooleanArray mUsersWithSeparateWorkChallenge = new SparseBooleanArray(); private final SparseBooleanArray mUsersWithSeparateWorkChallenge = new SparseBooleanArray();
@@ -101,14 +103,13 @@ public class NotificationLockscreenUserManagerImpl implements
private final List<UserChangedListener> mListeners = new ArrayList<>(); private final List<UserChangedListener> mListeners = new ArrayList<>();
private final BroadcastDispatcher mBroadcastDispatcher; private final BroadcastDispatcher mBroadcastDispatcher;
private final NotificationClickNotifier mClickNotifier; private final NotificationClickNotifier mClickNotifier;
private final LockPatternUtils mLockPatternUtils;
private final List<KeyguardNotificationSuppressor> mKeyguardSuppressors = new ArrayList<>(); private boolean mShowLockscreenNotifications;
protected final Context mContext; private boolean mAllowLockscreenRemoteInput;
private final Handler mMainHandler; private LockPatternUtils mLockPatternUtils;
protected final SparseArray<UserInfo> mCurrentProfiles = new SparseArray<>(); protected KeyguardManager mKeyguardManager;
protected final SparseArray<UserInfo> mCurrentManagedProfiles = new SparseArray<>(); private int mState = StatusBarState.SHADE;
private final ListenerSet<Runnable> mOnSensitiveContentRedactionChangeListeners = private List<KeyguardNotificationSuppressor> mKeyguardSuppressors = new ArrayList<>();
new ListenerSet<>();
protected final BroadcastReceiver mAllUsersReceiver = new BroadcastReceiver() { protected final BroadcastReceiver mAllUsersReceiver = new BroadcastReceiver() {
@Override @Override
@@ -119,11 +120,7 @@ public class NotificationLockscreenUserManagerImpl implements
isCurrentProfile(getSendingUserId())) { isCurrentProfile(getSendingUserId())) {
mUsersAllowingPrivateNotifications.clear(); mUsersAllowingPrivateNotifications.clear();
updateLockscreenNotificationSetting(); updateLockscreenNotificationSetting();
for (Runnable listener : mOnSensitiveContentRedactionChangeListeners) { getEntryManager().updateNotifications("ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED");
listener.run();
}
mEntryManagerLazy.get()
.updateNotifications("ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED");
} }
} }
}; };
@@ -145,7 +142,7 @@ public class NotificationLockscreenUserManagerImpl implements
// The filtering needs to happen before the update call below in order to // The filtering needs to happen before the update call below in order to
// make sure // make sure
// the presenter has the updated notifications from the new user // the presenter has the updated notifications from the new user
mEntryManagerLazy.get().reapplyFilterAndSort("user switched"); getEntryManager().reapplyFilterAndSort("user switched");
mPresenter.onUserSwitched(mCurrentUserId); mPresenter.onUserSwitched(mCurrentUserId);
for (UserChangedListener listener : mListeners) { for (UserChangedListener listener : mListeners) {
@@ -168,7 +165,7 @@ public class NotificationLockscreenUserManagerImpl implements
break; break;
case Intent.ACTION_USER_UNLOCKED: case Intent.ACTION_USER_UNLOCKED:
// Start the overview connection to the launcher service // Start the overview connection to the launcher service
mOverviewProxyService.get().startConnectionToCurrentUser(); Dependency.get(OverviewProxyService.class).startConnectionToCurrentUser();
break; break;
case NOTIFICATION_UNLOCKED_BY_WORK_CHALLENGE_ACTION: case NOTIFICATION_UNLOCKED_BY_WORK_CHALLENGE_ACTION:
final IntentSender intentSender = intent.getParcelableExtra( final IntentSender intentSender = intent.getParcelableExtra(
@@ -191,26 +188,28 @@ public class NotificationLockscreenUserManagerImpl implements
} }
}; };
// Late-init protected final Context mContext;
private final Handler mMainHandler;
protected final SparseArray<UserInfo> mCurrentProfiles = new SparseArray<>();
protected final SparseArray<UserInfo> mCurrentManagedProfiles = new SparseArray<>();
protected int mCurrentUserId = 0;
protected NotificationPresenter mPresenter; protected NotificationPresenter mPresenter;
protected ContentObserver mLockscreenSettingsObserver; protected ContentObserver mLockscreenSettingsObserver;
protected ContentObserver mSettingsObserver; protected ContentObserver mSettingsObserver;
protected KeyguardManager mKeyguardManager;
protected int mCurrentUserId = 0;
private int mState = StatusBarState.SHADE;
private boolean mHideSilentNotificationsOnLockscreen; private boolean mHideSilentNotificationsOnLockscreen;
private boolean mShowLockscreenNotifications;
private boolean mAllowLockscreenRemoteInput; private NotificationEntryManager getEntryManager() {
if (mEntryManager == null) {
mEntryManager = Dependency.get(NotificationEntryManager.class);
}
return mEntryManager;
}
@Inject @Inject
public NotificationLockscreenUserManagerImpl( public NotificationLockscreenUserManagerImpl(Context context,
Context context,
BroadcastDispatcher broadcastDispatcher, BroadcastDispatcher broadcastDispatcher,
DevicePolicyManager devicePolicyManager, DevicePolicyManager devicePolicyManager,
KeyguardUpdateMonitor keyguardUpdateMonitor,
Lazy<NotificationEntryManager> notificationEntryManagerLazy,
Lazy<OverviewProxyService> overviewProxyServiceLazy,
UserManager userManager, UserManager userManager,
Lazy<NotificationVisibilityProvider> visibilityProviderLazy, Lazy<NotificationVisibilityProvider> visibilityProviderLazy,
Lazy<CommonNotifCollection> commonNotifCollectionLazy, Lazy<CommonNotifCollection> commonNotifCollectionLazy,
@@ -226,11 +225,9 @@ public class NotificationLockscreenUserManagerImpl implements
mMainHandler = mainHandler; mMainHandler = mainHandler;
mDevicePolicyManager = devicePolicyManager; mDevicePolicyManager = devicePolicyManager;
mUserManager = userManager; mUserManager = userManager;
mOverviewProxyService = overviewProxyServiceLazy;
mCurrentUserId = ActivityManager.getCurrentUser(); mCurrentUserId = ActivityManager.getCurrentUser();
mVisibilityProviderLazy = visibilityProviderLazy; mVisibilityProviderLazy = visibilityProviderLazy;
mCommonNotifCollectionLazy = commonNotifCollectionLazy; mCommonNotifCollectionLazy = commonNotifCollectionLazy;
mEntryManagerLazy = notificationEntryManagerLazy;
mClickNotifier = clickNotifier; mClickNotifier = clickNotifier;
statusBarStateController.addCallback(this); statusBarStateController.addCallback(this);
mLockPatternUtils = new LockPatternUtils(context); mLockPatternUtils = new LockPatternUtils(context);
@@ -239,12 +236,10 @@ public class NotificationLockscreenUserManagerImpl implements
mDeviceProvisionedController = deviceProvisionedController; mDeviceProvisionedController = deviceProvisionedController;
mSecureSettings = secureSettings; mSecureSettings = secureSettings;
mKeyguardStateController = keyguardStateController; mKeyguardStateController = keyguardStateController;
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
dumpManager.registerDumpable(this); dumpManager.registerDumpable(this);
} }
@Override
public void setUpWithPresenter(NotificationPresenter presenter) { public void setUpWithPresenter(NotificationPresenter presenter) {
mPresenter = presenter; mPresenter = presenter;
@@ -257,10 +252,7 @@ public class NotificationLockscreenUserManagerImpl implements
mUsersAllowingNotifications.clear(); mUsersAllowingNotifications.clear();
// ... and refresh all the notifications // ... and refresh all the notifications
updateLockscreenNotificationSetting(); updateLockscreenNotificationSetting();
for (Runnable listener : mOnSensitiveContentRedactionChangeListeners) { getEntryManager().updateNotifications("LOCK_SCREEN_SHOW_NOTIFICATIONS,"
listener.run();
}
mEntryManagerLazy.get().updateNotifications("LOCK_SCREEN_SHOW_NOTIFICATIONS,"
+ " or LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS change"); + " or LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS change");
} }
}; };
@@ -270,7 +262,7 @@ public class NotificationLockscreenUserManagerImpl implements
public void onChange(boolean selfChange) { public void onChange(boolean selfChange) {
updateLockscreenNotificationSetting(); updateLockscreenNotificationSetting();
if (mDeviceProvisionedController.isDeviceProvisioned()) { if (mDeviceProvisionedController.isDeviceProvisioned()) {
mEntryManagerLazy.get().updateNotifications("LOCK_SCREEN_ALLOW_REMOTE_INPUT" getEntryManager().updateNotifications("LOCK_SCREEN_ALLOW_REMOTE_INPUT"
+ " or ZEN_MODE change"); + " or ZEN_MODE change");
} }
} }
@@ -330,17 +322,14 @@ public class NotificationLockscreenUserManagerImpl implements
mSettingsObserver.onChange(false); // set up mSettingsObserver.onChange(false); // set up
} }
@Override
public boolean shouldShowLockscreenNotifications() { public boolean shouldShowLockscreenNotifications() {
return mShowLockscreenNotifications; return mShowLockscreenNotifications;
} }
@Override
public boolean shouldAllowLockscreenRemoteInput() { public boolean shouldAllowLockscreenRemoteInput() {
return mAllowLockscreenRemoteInput; return mAllowLockscreenRemoteInput;
} }
@Override
public boolean isCurrentProfile(int userId) { public boolean isCurrentProfile(int userId) {
synchronized (mLock) { synchronized (mLock) {
return userId == UserHandle.USER_ALL || mCurrentProfiles.get(userId) != null; return userId == UserHandle.USER_ALL || mCurrentProfiles.get(userId) != null;
@@ -355,7 +344,7 @@ public class NotificationLockscreenUserManagerImpl implements
if (userId == UserHandle.USER_ALL) { if (userId == UserHandle.USER_ALL) {
userId = mCurrentUserId; userId = mCurrentUserId;
} }
boolean inLockdown = mKeyguardUpdateMonitor.isUserInLockdown(userId); boolean inLockdown = Dependency.get(KeyguardUpdateMonitor.class).isUserInLockdown(userId);
mUsersInLockdownLatestResult.put(userId, inLockdown); mUsersInLockdownLatestResult.put(userId, inLockdown);
return inLockdown; return inLockdown;
} }
@@ -364,7 +353,6 @@ public class NotificationLockscreenUserManagerImpl implements
* Returns true if we're on a secure lockscreen and the user wants to hide notification data. * Returns true if we're on a secure lockscreen and the user wants to hide notification data.
* If so, notifications should be hidden. * If so, notifications should be hidden.
*/ */
@Override
public boolean shouldHideNotifications(int userId) { public boolean shouldHideNotifications(int userId) {
boolean hide = isLockscreenPublicMode(userId) && !userAllowsNotificationsInPublic(userId) boolean hide = isLockscreenPublicMode(userId) && !userAllowsNotificationsInPublic(userId)
|| (userId != mCurrentUserId && shouldHideNotifications(mCurrentUserId)) || (userId != mCurrentUserId && shouldHideNotifications(mCurrentUserId))
@@ -377,7 +365,6 @@ public class NotificationLockscreenUserManagerImpl implements
* Returns true if we're on a secure lockscreen and the user wants to hide notifications via * Returns true if we're on a secure lockscreen and the user wants to hide notifications via
* package-specific override. * package-specific override.
*/ */
@Override
public boolean shouldHideNotifications(String key) { public boolean shouldHideNotifications(String key) {
if (mCommonNotifCollectionLazy.get() == null) { if (mCommonNotifCollectionLazy.get() == null) {
Log.wtf(TAG, "mCommonNotifCollectionLazy was null!", new Throwable()); Log.wtf(TAG, "mCommonNotifCollectionLazy was null!", new Throwable());
@@ -388,7 +375,6 @@ public class NotificationLockscreenUserManagerImpl implements
&& visibleEntry.getRanking().getLockscreenVisibilityOverride() == VISIBILITY_SECRET; && visibleEntry.getRanking().getLockscreenVisibilityOverride() == VISIBILITY_SECRET;
} }
@Override
public boolean shouldShowOnKeyguard(NotificationEntry entry) { public boolean shouldShowOnKeyguard(NotificationEntry entry) {
if (mCommonNotifCollectionLazy.get() == null) { if (mCommonNotifCollectionLazy.get() == null) {
Log.wtf(TAG, "mCommonNotifCollectionLazy was null!", new Throwable()); Log.wtf(TAG, "mCommonNotifCollectionLazy was null!", new Throwable());
@@ -411,6 +397,14 @@ public class NotificationLockscreenUserManagerImpl implements
return mShowLockscreenNotifications && exceedsPriorityThreshold; return mShowLockscreenNotifications && exceedsPriorityThreshold;
} }
private void setShowLockscreenNotifications(boolean show) {
mShowLockscreenNotifications = show;
}
private void setLockscreenAllowRemoteInput(boolean allowLockscreenRemoteInput) {
mAllowLockscreenRemoteInput = allowLockscreenRemoteInput;
}
protected void updateLockscreenNotificationSetting() { protected void updateLockscreenNotificationSetting() {
final boolean show = mSecureSettings.getIntForUser( final boolean show = mSecureSettings.getIntForUser(
Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS,
@@ -424,7 +418,7 @@ public class NotificationLockscreenUserManagerImpl implements
mHideSilentNotificationsOnLockscreen = mSecureSettings.getIntForUser( mHideSilentNotificationsOnLockscreen = mSecureSettings.getIntForUser(
Settings.Secure.LOCK_SCREEN_SHOW_SILENT_NOTIFICATIONS, 1, mCurrentUserId) == 0; Settings.Secure.LOCK_SCREEN_SHOW_SILENT_NOTIFICATIONS, 1, mCurrentUserId) == 0;
mShowLockscreenNotifications = show && allowedByDpm; setShowLockscreenNotifications(show && allowedByDpm);
if (ENABLE_LOCK_SCREEN_ALLOW_REMOTE_INPUT) { if (ENABLE_LOCK_SCREEN_ALLOW_REMOTE_INPUT) {
final boolean remoteInput = mSecureSettings.getIntForUser( final boolean remoteInput = mSecureSettings.getIntForUser(
@@ -434,9 +428,9 @@ public class NotificationLockscreenUserManagerImpl implements
final boolean remoteInputDpm = final boolean remoteInputDpm =
(dpmFlags & DevicePolicyManager.KEYGUARD_DISABLE_REMOTE_INPUT) == 0; (dpmFlags & DevicePolicyManager.KEYGUARD_DISABLE_REMOTE_INPUT) == 0;
mAllowLockscreenRemoteInput = remoteInput && remoteInputDpm; setLockscreenAllowRemoteInput(remoteInput && remoteInputDpm);
} else { } else {
mAllowLockscreenRemoteInput = false; setLockscreenAllowRemoteInput(false);
} }
} }
@@ -444,7 +438,7 @@ public class NotificationLockscreenUserManagerImpl implements
* Has the given user chosen to allow their private (full) notifications to be shown even * Has the given user chosen to allow their private (full) notifications to be shown even
* when the lockscreen is in "public" (secure & locked) mode? * when the lockscreen is in "public" (secure & locked) mode?
*/ */
protected boolean userAllowsPrivateNotificationsInPublic(int userHandle) { public boolean userAllowsPrivateNotificationsInPublic(int userHandle) {
if (userHandle == UserHandle.USER_ALL) { if (userHandle == UserHandle.USER_ALL) {
return true; return true;
} }
@@ -489,12 +483,10 @@ public class NotificationLockscreenUserManagerImpl implements
/** /**
* Save the current "public" (locked and secure) state of the lockscreen. * Save the current "public" (locked and secure) state of the lockscreen.
*/ */
@Override
public void setLockscreenPublicMode(boolean publicMode, int userId) { public void setLockscreenPublicMode(boolean publicMode, int userId) {
mLockscreenPublicMode.put(userId, publicMode); mLockscreenPublicMode.put(userId, publicMode);
} }
@Override
public boolean isLockscreenPublicMode(int userId) { public boolean isLockscreenPublicMode(int userId) {
if (userId == UserHandle.USER_ALL) { if (userId == UserHandle.USER_ALL) {
return mLockscreenPublicMode.get(mCurrentUserId, false); return mLockscreenPublicMode.get(mCurrentUserId, false);
@@ -511,7 +503,6 @@ public class NotificationLockscreenUserManagerImpl implements
* Has the given user chosen to allow notifications to be shown even when the lockscreen is in * Has the given user chosen to allow notifications to be shown even when the lockscreen is in
* "public" (secure & locked) mode? * "public" (secure & locked) mode?
*/ */
@Override
public boolean userAllowsNotificationsInPublic(int userHandle) { public boolean userAllowsNotificationsInPublic(int userHandle) {
if (isCurrentProfile(userHandle) && userHandle != mCurrentUserId) { if (isCurrentProfile(userHandle) && userHandle != mCurrentUserId) {
return true; return true;
@@ -532,37 +523,36 @@ public class NotificationLockscreenUserManagerImpl implements
} }
/** @return true if the entry needs redaction when on the lockscreen. */ /** @return true if the entry needs redaction when on the lockscreen. */
@Override public boolean needsRedaction(NotificationEntry ent) {
public boolean notifNeedsRedactionInPublic(NotificationEntry ent) {
int userId = ent.getSbn().getUserId(); int userId = ent.getSbn().getUserId();
return ent.hasSensitiveContents() && sensitiveNotifsNeedRedactionInPublic(userId);
}
@Override
public boolean sensitiveNotifsNeedRedactionInPublic(int userId) {
boolean isCurrentUserRedactingNotifs = boolean isCurrentUserRedactingNotifs =
!userAllowsPrivateNotificationsInPublic(mCurrentUserId); !userAllowsPrivateNotificationsInPublic(mCurrentUserId);
if (userId == mCurrentUserId) {
return isCurrentUserRedactingNotifs;
}
boolean isNotifForManagedProfile = mCurrentManagedProfiles.contains(userId); boolean isNotifForManagedProfile = mCurrentManagedProfiles.contains(userId);
boolean isNotifUserRedacted = !userAllowsPrivateNotificationsInPublic(userId); boolean isNotifUserRedacted = !userAllowsPrivateNotificationsInPublic(userId);
// redact notifications if the current user is redacting notifications; however if the // 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 // notification is associated with a managed profile, we rely on the managed profile
// setting to determine whether to redact it // setting to determine whether to redact it
return (!isNotifForManagedProfile && isCurrentUserRedactingNotifs) || isNotifUserRedacted; boolean isNotifRedacted = (!isNotifForManagedProfile && isCurrentUserRedactingNotifs)
|| isNotifUserRedacted;
boolean notificationRequestsRedaction =
ent.getSbn().getNotification().visibility == Notification.VISIBILITY_PRIVATE;
boolean userForcesRedaction = packageHasVisibilityOverride(ent.getSbn().getKey());
return userForcesRedaction || notificationRequestsRedaction && isNotifRedacted;
} }
@Override private boolean packageHasVisibilityOverride(String key) {
public void addOnNeedsRedactionInPublicChangedListener(Runnable listener) { if (mCommonNotifCollectionLazy.get() == null) {
mOnSensitiveContentRedactionChangeListeners.addIfAbsent(listener); Log.wtf(TAG, "mEntryManager was null!", new Throwable());
} return true;
}
@Override NotificationEntry entry = mCommonNotifCollectionLazy.get().getEntry(key);
public void removeOnNeedsRedactionInPublicChangedListener(Runnable listener) { return entry != null
mOnSensitiveContentRedactionChangeListeners.remove(listener); && entry.getRanking().getLockscreenVisibilityOverride()
== Notification.VISIBILITY_PRIVATE;
} }
private void updateCurrentProfilesCache() { private void updateCurrentProfilesCache() {
@@ -582,16 +572,12 @@ public class NotificationLockscreenUserManagerImpl implements
for (UserChangedListener listener : mListeners) { for (UserChangedListener listener : mListeners) {
listener.onCurrentProfilesChanged(mCurrentProfiles); listener.onCurrentProfilesChanged(mCurrentProfiles);
} }
for (Runnable listener : mOnSensitiveContentRedactionChangeListeners) {
listener.run();
}
}); });
} }
/** /**
* If any of the profiles are in public mode. * If any of the profiles are in public mode.
*/ */
@Override
public boolean isAnyProfilePublicMode() { public boolean isAnyProfilePublicMode() {
synchronized (mLock) { synchronized (mLock) {
for (int i = mCurrentProfiles.size() - 1; i >= 0; i--) { for (int i = mCurrentProfiles.size() - 1; i >= 0; i--) {
@@ -620,12 +606,10 @@ public class NotificationLockscreenUserManagerImpl implements
/** /**
* Returns the current user id. This can change if the user is switched. * Returns the current user id. This can change if the user is switched.
*/ */
@Override
public int getCurrentUserId() { public int getCurrentUserId() {
return mCurrentUserId; return mCurrentUserId;
} }
@Override
public SparseArray<UserInfo> getCurrentProfiles() { public SparseArray<UserInfo> getCurrentProfiles() {
return mCurrentProfiles; return mCurrentProfiles;
} }
@@ -666,8 +650,7 @@ public class NotificationLockscreenUserManagerImpl implements
setLockscreenPublicMode(isProfilePublic, userId); setLockscreenPublicMode(isProfilePublic, userId);
mUsersWithSeparateWorkChallenge.put(userId, needsSeparateChallenge); mUsersWithSeparateWorkChallenge.put(userId, needsSeparateChallenge);
} }
mEntryManagerLazy.get() getEntryManager().updateNotifications("NotificationLockscreenUserManager.updatePublicMode");
.updateNotifications("NotificationLockscreenUserManager.updatePublicMode");
} }
@Override @Override

View File

@@ -53,7 +53,6 @@ import com.android.wm.shell.bubbles.Bubbles;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.Stack; import java.util.Stack;
@@ -208,9 +207,12 @@ public class NotificationViewHierarchyManager implements DynamicPrivacyControlle
|| !mLockscreenUserManager.needsSeparateWorkChallenge(userId))) { || !mLockscreenUserManager.needsSeparateWorkChallenge(userId))) {
userPublic = false; userPublic = false;
} }
boolean needsRedaction = mLockscreenUserManager.notifNeedsRedactionInPublic(ent); boolean needsRedaction = mLockscreenUserManager.needsRedaction(ent);
boolean sensitive = userPublic && needsRedaction; boolean sensitive = userPublic && needsRedaction;
ent.getRow().setSensitive(sensitive); boolean deviceSensitive = devicePublic
&& !mLockscreenUserManager.userAllowsPrivateNotificationsInPublic(
currentUserId);
ent.setSensitive(sensitive, deviceSensitive);
ent.getRow().setNeedsRedaction(needsRedaction); ent.getRow().setNeedsRedaction(needsRedaction);
mLowPriorityInflationHelper.recheckLowPriorityViewAndInflate(ent, ent.getRow()); mLowPriorityInflationHelper.recheckLowPriorityViewAndInflate(ent, ent.getRow());
boolean isChildInGroup = mGroupManager.isChildInGroup(ent); boolean isChildInGroup = mGroupManager.isChildInGroup(ent);
@@ -363,8 +365,6 @@ public class NotificationViewHierarchyManager implements DynamicPrivacyControlle
boolean hasClearableAlertingNotifs = false; boolean hasClearableAlertingNotifs = false;
boolean hasNonClearableSilentNotifs = false; boolean hasNonClearableSilentNotifs = false;
boolean hasClearableSilentNotifs = false; boolean hasClearableSilentNotifs = false;
HashSet<Integer> clearableAlertingSensitiveNotifUsers = new HashSet<>();
HashSet<Integer> clearableSilentSensitiveNotifUsers = new HashSet<>();
final int childCount = mListContainer.getContainerChildCount(); final int childCount = mListContainer.getContainerChildCount();
int visibleTopLevelEntries = 0; int visibleTopLevelEntries = 0;
for (int i = 0; i < childCount; i++) { for (int i = 0; i < childCount; i++) {
@@ -376,11 +376,10 @@ public class NotificationViewHierarchyManager implements DynamicPrivacyControlle
continue; continue;
} }
final ExpandableNotificationRow row = (ExpandableNotificationRow) child; final ExpandableNotificationRow row = (ExpandableNotificationRow) child;
NotificationEntry entry = row.getEntry(); boolean isSilent = row.getEntry().getBucket() == BUCKET_SILENT;
boolean isSilent = entry.getBucket() == BUCKET_SILENT;
// NOTE: NotificationEntry.isClearable() will internally check group children to ensure // NOTE: NotificationEntry.isClearable() will internally check group children to ensure
// the group itself definitively clearable. // the group itself definitively clearable.
boolean isClearable = entry.isClearable(); boolean isClearable = row.getEntry().isClearable();
visibleTopLevelEntries++; visibleTopLevelEntries++;
if (isSilent) { if (isSilent) {
if (isClearable) { if (isClearable) {
@@ -395,24 +394,13 @@ public class NotificationViewHierarchyManager implements DynamicPrivacyControlle
hasNonClearableAlertingNotifs = true; hasNonClearableAlertingNotifs = true;
} }
} }
if (isClearable && entry.hasSensitiveContents()) {
int userId = entry.getSbn().getUserId();
if (isSilent) {
clearableSilentSensitiveNotifUsers.add(userId);
} else {
clearableAlertingSensitiveNotifUsers.add(userId);
}
}
} }
mStackController.setNotifStats(new NotifStats( mStackController.setNotifStats(new NotifStats(
visibleTopLevelEntries /* numActiveNotifs */, visibleTopLevelEntries /* numActiveNotifs */,
hasNonClearableAlertingNotifs /* hasNonClearableAlertingNotifs */, hasNonClearableAlertingNotifs /* hasNonClearableAlertingNotifs */,
hasClearableAlertingNotifs /* hasClearableAlertingNotifs */, hasClearableAlertingNotifs /* hasClearableAlertingNotifs */,
hasNonClearableSilentNotifs /* hasNonClearableSilentNotifs */, hasNonClearableSilentNotifs /* hasNonClearableSilentNotifs */,
hasClearableSilentNotifs /* hasClearableSilentNotifs */, hasClearableSilentNotifs /* hasClearableSilentNotifs */
clearableAlertingSensitiveNotifUsers /* clearableAlertingSensitiveNotifUsers */,
clearableSilentSensitiveNotifUsers /* clearableSilentSensitiveNotifUsers */
)); ));
Trace.endSection(); Trace.endSection();
} }

View File

@@ -80,7 +80,7 @@ public class DynamicPrivacyController implements KeyguardStateController.Callbac
@VisibleForTesting @VisibleForTesting
boolean isDynamicPrivacyEnabled() { boolean isDynamicPrivacyEnabled() {
return mLockscreenUserManager.sensitiveNotifsNeedRedactionInPublic( return !mLockscreenUserManager.userAllowsPrivateNotificationsInPublic(
mLockscreenUserManager.getCurrentUserId()); mLockscreenUserManager.getCurrentUserId());
} }
@@ -95,10 +95,6 @@ public class DynamicPrivacyController implements KeyguardStateController.Callbac
mListeners.add(listener); 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 * Is the notification shade currently in a locked down mode where it's fully showing but the
* contents aren't revealed yet? * contents aren't revealed yet?

View File

@@ -169,6 +169,9 @@ public final class NotificationEntry extends ListEntry {
*/ */
private boolean hasSentReply; private boolean hasSentReply;
private boolean mSensitive = true;
private List<OnSensitivityChangedListener> mOnSensitivityChangedListeners = new ArrayList<>();
private boolean mAutoHeadsUp; private boolean mAutoHeadsUp;
private boolean mPulseSupressed; private boolean mPulseSupressed;
private int mBucket = BUCKET_ALERTING; private int mBucket = BUCKET_ALERTING;
@@ -864,29 +867,33 @@ public final class NotificationEntry extends ListEntry {
} }
/** /**
* Returns the visibility of this notification on the lockscreen, taking into account both the * Set this notification to be sensitive.
* notification's defined visibility, as well as the visibility override as determined by the *
* device policy. * @param sensitive true if the content of this notification is sensitive right now
* @param deviceSensitive true if the device in general is sensitive right now
*/ */
public int getLockscreenVisibility() { public void setSensitive(boolean sensitive, boolean deviceSensitive) {
int setting = mRanking.getLockscreenVisibilityOverride(); getRow().setSensitive(sensitive, deviceSensitive);
if (setting == Ranking.VISIBILITY_NO_OVERRIDE) { if (sensitive != mSensitive) {
setting = mSbn.getNotification().visibility; mSensitive = sensitive;
for (int i = 0; i < mOnSensitivityChangedListeners.size(); i++) {
mOnSensitivityChangedListeners.get(i).onSensitivityChanged(this);
}
} }
return setting;
} }
/** public boolean isSensitive() {
* Does this notification contain sensitive content? If the user's settings specify, then this return mSensitive;
* 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 /** Add a listener to be notified when the entry's sensitivity changes. */
* false; SECRET notifications are omitted entirely when the device is public, so effectively public void addOnSensitivityChangedListener(OnSensitivityChangedListener listener) {
* the contents of the notification are not sensitive whenever the notification is actually mOnSensitivityChangedListeners.add(listener);
* visible. }
*/
public boolean hasSensitiveContents() { /** Remove a listener that was registered above. */
return getLockscreenVisibility() == Notification.VISIBILITY_PRIVATE; public void removeOnSensitivityChangedListener(OnSensitivityChangedListener listener) {
mOnSensitivityChangedListeners.remove(listener);
} }
public boolean isPulseSuppressed() { public boolean isPulseSuppressed() {
@@ -947,6 +954,12 @@ public final class NotificationEntry extends ListEntry {
} }
} }
/** Listener interface for {@link #addOnSensitivityChangedListener} */
public interface OnSensitivityChangedListener {
/** Called when the sensitivity changes */
void onSensitivityChanged(@NonNull NotificationEntry entry);
}
/** @see #getDismissState() */ /** @see #getDismissState() */
public enum DismissState { public enum DismissState {
/** User has not dismissed this notif or its parent */ /** User has not dismissed this notif or its parent */

View File

@@ -56,6 +56,7 @@ class NotifCoordinatorsImpl @Inject constructor(
smartspaceDedupingCoordinator: SmartspaceDedupingCoordinator, smartspaceDedupingCoordinator: SmartspaceDedupingCoordinator,
viewConfigCoordinator: ViewConfigCoordinator, viewConfigCoordinator: ViewConfigCoordinator,
visualStabilityCoordinator: VisualStabilityCoordinator, visualStabilityCoordinator: VisualStabilityCoordinator,
sensitiveContentCoordinator: SensitiveContentCoordinator,
) : NotifCoordinators { ) : NotifCoordinators {
private val mCoordinators: MutableList<Coordinator> = ArrayList() private val mCoordinators: MutableList<Coordinator> = ArrayList()
@@ -92,6 +93,7 @@ class NotifCoordinatorsImpl @Inject constructor(
mCoordinators.add(shadeEventCoordinator) mCoordinators.add(shadeEventCoordinator)
mCoordinators.add(viewConfigCoordinator) mCoordinators.add(viewConfigCoordinator)
mCoordinators.add(visualStabilityCoordinator) mCoordinators.add(visualStabilityCoordinator)
mCoordinators.add(sensitiveContentCoordinator)
if (notifPipelineFlags.isSmartspaceDedupingEnabled()) { if (notifPipelineFlags.isSmartspaceDedupingEnabled()) {
mCoordinators.add(smartspaceDedupingCoordinator) mCoordinators.add(smartspaceDedupingCoordinator)
} }

View File

@@ -16,6 +16,7 @@
package com.android.systemui.statusbar.notification.collection.coordinator; package com.android.systemui.statusbar.notification.collection.coordinator;
import android.annotation.NonNull;
import android.annotation.Nullable; import android.annotation.Nullable;
import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -28,11 +29,13 @@ import com.android.systemui.statusbar.notification.collection.listbuilder.plugga
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner; import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner;
import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider; 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.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.AlertingHeader;
import com.android.systemui.statusbar.notification.dagger.SilentHeader; import com.android.systemui.statusbar.notification.dagger.SilentHeader;
import com.android.systemui.statusbar.notification.stack.NotificationPriorityBucketKt; import com.android.systemui.statusbar.notification.stack.NotificationPriorityBucketKt;
import java.util.Collections; import java.util.Collections;
import java.util.List;
import javax.inject.Inject; import javax.inject.Inject;
@@ -50,10 +53,10 @@ public class RankingCoordinator implements Coordinator {
private final HighPriorityProvider mHighPriorityProvider; private final HighPriorityProvider mHighPriorityProvider;
private final SectionClassifier mSectionClassifier; private final SectionClassifier mSectionClassifier;
private final NodeController mSilentNodeController; private final NodeController mSilentNodeController;
private final SectionHeaderController mSilentHeaderController;
private final NodeController mAlertingHeaderController; private final NodeController mAlertingHeaderController;
private final AlertingNotifSectioner mAlertingNotifSectioner = new AlertingNotifSectioner(); private boolean mHasSilentEntries;
private final SilentNotifSectioner mSilentNotifSectioner = new SilentNotifSectioner(); private boolean mHasMinimizedEntries;
private final MinimizedNotifSectioner mMinimizedNotifSectioner = new MinimizedNotifSectioner();
@Inject @Inject
public RankingCoordinator( public RankingCoordinator(
@@ -61,12 +64,14 @@ public class RankingCoordinator implements Coordinator {
HighPriorityProvider highPriorityProvider, HighPriorityProvider highPriorityProvider,
SectionClassifier sectionClassifier, SectionClassifier sectionClassifier,
@AlertingHeader NodeController alertingHeaderController, @AlertingHeader NodeController alertingHeaderController,
@SilentHeader SectionHeaderController silentHeaderController,
@SilentHeader NodeController silentNodeController) { @SilentHeader NodeController silentNodeController) {
mStatusBarStateController = statusBarStateController; mStatusBarStateController = statusBarStateController;
mHighPriorityProvider = highPriorityProvider; mHighPriorityProvider = highPriorityProvider;
mSectionClassifier = sectionClassifier; mSectionClassifier = sectionClassifier;
mAlertingHeaderController = alertingHeaderController; mAlertingHeaderController = alertingHeaderController;
mSilentNodeController = silentNodeController; mSilentNodeController = silentNodeController;
mSilentHeaderController = silentHeaderController;
} }
@Override @Override
@@ -90,6 +95,82 @@ public class RankingCoordinator implements Coordinator {
return mMinimizedNotifSectioner; return mMinimizedNotifSectioner;
} }
private final NotifSectioner mAlertingNotifSectioner = new NotifSectioner("Alerting",
NotificationPriorityBucketKt.BUCKET_ALERTING) {
@Override
public boolean isInSection(ListEntry entry) {
return mHighPriorityProvider.isHighPriority(entry);
}
@Nullable
@Override
public NodeController getHeaderNodeController() {
// TODO: remove SHOW_ALL_SECTIONS, this redundant method, and mAlertingHeaderController
if (SHOW_ALL_SECTIONS) {
return mAlertingHeaderController;
}
return null;
}
};
private final NotifSectioner mSilentNotifSectioner = new NotifSectioner("Silent",
NotificationPriorityBucketKt.BUCKET_SILENT) {
@Override
public boolean isInSection(ListEntry entry) {
return !mHighPriorityProvider.isHighPriority(entry)
&& !entry.getRepresentativeEntry().isAmbient();
}
@Nullable
@Override
public NodeController getHeaderNodeController() {
return mSilentNodeController;
}
@Nullable
@Override
public void onEntriesUpdated(@NonNull List<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 final NotifSectioner mMinimizedNotifSectioner = new NotifSectioner("Minimized",
NotificationPriorityBucketKt.BUCKET_SILENT) {
@Override
public boolean isInSection(ListEntry entry) {
return !mHighPriorityProvider.isHighPriority(entry)
&& entry.getRepresentativeEntry().isAmbient();
}
@Nullable
@Override
public NodeController getHeaderNodeController() {
return mSilentNodeController;
}
@Nullable
@Override
public void onEntriesUpdated(@NonNull List<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. * 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, * NotifListBuilder invalidates the notification list each time the ranking is updated,
@@ -121,64 +202,4 @@ public class RankingCoordinator implements Coordinator {
mDndVisualEffectsFilter.invalidateList(); mDndVisualEffectsFilter.invalidateList();
} }
}; };
private class AlertingNotifSectioner extends NotifSectioner {
AlertingNotifSectioner() {
super("Alerting", NotificationPriorityBucketKt.BUCKET_ALERTING);
}
@Override
public boolean isInSection(ListEntry entry) {
return mHighPriorityProvider.isHighPriority(entry);
}
@Nullable
@Override
public NodeController getHeaderNodeController() {
// TODO: remove SHOW_ALL_SECTIONS, this redundant method, and mAlertingHeaderController
if (SHOW_ALL_SECTIONS) {
return mAlertingHeaderController;
}
return null;
}
}
private class SilentNotifSectioner extends NotifSectioner {
SilentNotifSectioner() {
super("Silent", NotificationPriorityBucketKt.BUCKET_SILENT);
}
@Override
public boolean isInSection(ListEntry entry) {
return !mHighPriorityProvider.isHighPriority(entry)
&& !entry.getRepresentativeEntry().isAmbient();
}
@Nullable
@Override
public NodeController getHeaderNodeController() {
return mSilentNodeController;
}
}
private class MinimizedNotifSectioner extends NotifSectioner {
MinimizedNotifSectioner() {
super("Minimized", NotificationPriorityBucketKt.BUCKET_SILENT);
}
@Override
public boolean isInSection(ListEntry entry) {
return !mHighPriorityProvider.isHighPriority(entry)
&& entry.getRepresentativeEntry().isAmbient();
}
@Nullable
@Override
public NodeController getHeaderNodeController() {
return mSilentNodeController;
}
}
} }

View File

@@ -0,0 +1,124 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.systemui.statusbar.notification.collection.coordinator
import android.os.UserHandle
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.statusbar.NotificationLockscreenUserManager
import com.android.systemui.statusbar.StatusBarState
import com.android.systemui.statusbar.notification.DynamicPrivacyController
import com.android.systemui.statusbar.notification.collection.GroupEntry
import com.android.systemui.statusbar.notification.collection.ListEntry
import com.android.systemui.statusbar.notification.collection.NotifPipeline
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope
import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeRenderListListener
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.Invalidator
import com.android.systemui.statusbar.policy.KeyguardStateController
import dagger.Binds
import dagger.Module
import javax.inject.Inject
@Module(includes = [PrivateSensitiveContentCoordinatorModule::class])
interface SensitiveContentCoordinatorModule
@Module
private interface PrivateSensitiveContentCoordinatorModule {
@Binds
fun bindCoordinator(impl: SensitiveContentCoordinatorImpl): SensitiveContentCoordinator
}
/** Coordinates re-inflation and post-processing of sensitive notification content. */
interface SensitiveContentCoordinator : Coordinator
@CoordinatorScope
private class SensitiveContentCoordinatorImpl @Inject constructor(
private val dynamicPrivacyController: DynamicPrivacyController,
private val lockscreenUserManager: NotificationLockscreenUserManager,
private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
private val statusBarStateController: StatusBarStateController,
private val keyguardStateController: KeyguardStateController
) : Invalidator("SensitiveContentInvalidator"),
SensitiveContentCoordinator,
DynamicPrivacyController.Listener,
OnBeforeRenderListListener {
override fun attach(pipeline: NotifPipeline) {
dynamicPrivacyController.addListener(this)
pipeline.addOnBeforeRenderListListener(this)
pipeline.addPreRenderInvalidator(this)
}
override fun onDynamicPrivacyChanged(): Unit = invalidateList()
override fun onBeforeRenderList(entries: List<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))
}
}

View File

@@ -50,8 +50,6 @@ class StackCoordinator @Inject internal constructor(
var hasClearableAlertingNotifs = false var hasClearableAlertingNotifs = false
var hasNonClearableSilentNotifs = false var hasNonClearableSilentNotifs = false
var hasClearableSilentNotifs = false var hasClearableSilentNotifs = false
val clearableAlertingSensitiveNotifUsers = mutableSetOf<Int>()
val clearableSilentSensitiveNotifUsers = mutableSetOf<Int>()
entries.forEach { entries.forEach {
val section = checkNotNull(it.section) { "Null section for ${it.key}" } val section = checkNotNull(it.section) { "Null section for ${it.key}" }
val entry = checkNotNull(it.representativeEntry) { "Null notif entry for ${it.key}" } val entry = checkNotNull(it.representativeEntry) { "Null notif entry for ${it.key}" }
@@ -65,22 +63,13 @@ class StackCoordinator @Inject internal constructor(
!isSilent && isClearable -> hasClearableAlertingNotifs = true !isSilent && isClearable -> hasClearableAlertingNotifs = true
!isSilent && !isClearable -> hasNonClearableAlertingNotifs = true !isSilent && !isClearable -> hasNonClearableAlertingNotifs = true
} }
if (isClearable && entry.hasSensitiveContents()) {
if (isSilent) {
clearableSilentSensitiveNotifUsers.add(entry.sbn.userId)
} else {
clearableAlertingSensitiveNotifUsers.add(entry.sbn.userId)
}
}
} }
return NotifStats( return NotifStats(
numActiveNotifs = entries.size, numActiveNotifs = entries.size,
hasNonClearableAlertingNotifs = hasNonClearableAlertingNotifs, hasNonClearableAlertingNotifs = hasNonClearableAlertingNotifs,
hasClearableAlertingNotifs = hasClearableAlertingNotifs, hasClearableAlertingNotifs = hasClearableAlertingNotifs,
hasNonClearableSilentNotifs = hasNonClearableSilentNotifs, hasNonClearableSilentNotifs = hasNonClearableSilentNotifs,
hasClearableSilentNotifs = hasClearableSilentNotifs, hasClearableSilentNotifs = hasClearableSilentNotifs
clearableAlertingSensitiveNotifUsers = clearableAlertingSensitiveNotifUsers,
clearableSilentSensitiveNotifUsers = clearableSilentSensitiveNotifUsers
) )
} }
} }

View File

@@ -19,6 +19,7 @@ package com.android.systemui.statusbar.notification.collection.coordinator.dagge
import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.statusbar.notification.collection.coordinator.NotifCoordinators 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.NotifCoordinatorsImpl
import com.android.systemui.statusbar.notification.collection.coordinator.SensitiveContentCoordinatorModule
import dagger.Binds import dagger.Binds
import dagger.Module import dagger.Module
import dagger.Provides import dagger.Provides
@@ -47,6 +48,7 @@ interface CoordinatorsSubcomponent {
} }
@Module(includes = [ @Module(includes = [
SensitiveContentCoordinatorModule::class,
]) ])
private abstract class InternalCoordinatorsModule { private abstract class InternalCoordinatorsModule {
@Binds @Binds

View File

@@ -16,8 +16,6 @@
package com.android.systemui.statusbar.notification.collection.inflation; 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 static java.util.Objects.requireNonNull;
import android.annotation.Nullable; import android.annotation.Nullable;
@@ -251,13 +249,10 @@ public class NotificationRowBinderImpl implements NotificationRowBinder {
RowContentBindParams params = mRowContentBindStage.getStageParams(entry); RowContentBindParams params = mRowContentBindStage.getStageParams(entry);
params.setUseIncreasedCollapsedHeight(useIncreasedCollapsedHeight); params.setUseIncreasedCollapsedHeight(useIncreasedCollapsedHeight);
params.setUseLowPriority(isLowPriority); params.setUseLowPriority(isLowPriority);
boolean needsRedaction =
mNotificationLockscreenUserManager.notifNeedsRedactionInPublic(entry); // TODO: Replace this API with RowContentBindParams directly. Also move to a separate
if (needsRedaction) { // redaction controller.
params.requireContentViews(FLAG_CONTENT_VIEW_PUBLIC); row.setNeedsRedaction(mNotificationLockscreenUserManager.needsRedaction(entry));
} else {
params.markContentViewsFreeable(FLAG_CONTENT_VIEW_PUBLIC);
}
params.rebindAllContentViews(); params.rebindAllContentViews();
mRowContentBindStage.requestRebind(entry, en -> { mRowContentBindStage.requestRebind(entry, en -> {

View File

@@ -28,21 +28,11 @@ data class NotifStats(
val hasNonClearableAlertingNotifs: Boolean, val hasNonClearableAlertingNotifs: Boolean,
val hasClearableAlertingNotifs: Boolean, val hasClearableAlertingNotifs: Boolean,
val hasNonClearableSilentNotifs: Boolean, val hasNonClearableSilentNotifs: Boolean,
val hasClearableSilentNotifs: Boolean, val hasClearableSilentNotifs: Boolean
val clearableAlertingSensitiveNotifUsers: Set<Int>,
val clearableSilentSensitiveNotifUsers: Set<Int>
) { ) {
companion object { companion object {
@JvmStatic @JvmStatic
val empty = NotifStats( val empty = NotifStats(0, false, false, false, false)
numActiveNotifs = 0,
hasNonClearableAlertingNotifs = false,
hasClearableAlertingNotifs = false,
hasNonClearableSilentNotifs = false,
hasClearableSilentNotifs = false,
clearableAlertingSensitiveNotifUsers = emptySet(),
clearableSilentSensitiveNotifUsers = emptySet(),
)
} }
} }

View File

@@ -28,7 +28,6 @@ import android.widget.ImageView
import com.android.internal.statusbar.StatusBarIcon import com.android.internal.statusbar.StatusBarIcon
import com.android.systemui.R import com.android.systemui.R
import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.statusbar.NotificationLockscreenUserManager
import com.android.systemui.statusbar.StatusBarIconView import com.android.systemui.statusbar.StatusBarIconView
import com.android.systemui.statusbar.notification.InflationException import com.android.systemui.statusbar.notification.InflationException
import com.android.systemui.statusbar.notification.collection.NotificationEntry import com.android.systemui.statusbar.notification.collection.NotificationEntry
@@ -50,29 +49,31 @@ import javax.inject.Inject
class IconManager @Inject constructor( class IconManager @Inject constructor(
private val notifCollection: CommonNotifCollection, private val notifCollection: CommonNotifCollection,
private val launcherApps: LauncherApps, private val launcherApps: LauncherApps,
private val iconBuilder: IconBuilder, private val iconBuilder: IconBuilder
private val notifLockscreenUserManager: NotificationLockscreenUserManager
) : ConversationIconManager { ) : ConversationIconManager {
private var unimportantConversationKeys: Set<String> = emptySet() private var unimportantConversationKeys: Set<String> = emptySet()
fun attach() { fun attach() {
notifCollection.addCollectionListener(entryListener) notifCollection.addCollectionListener(entryListener)
notifLockscreenUserManager.addOnNeedsRedactionInPublicChangedListener(sensitivityListener)
} }
private val entryListener = object : NotifCollectionListener { private val entryListener = object : NotifCollectionListener {
override fun onEntryInit(entry: NotificationEntry) {
entry.addOnSensitivityChangedListener(sensitivityListener)
}
override fun onEntryCleanUp(entry: NotificationEntry) {
entry.removeOnSensitivityChangedListener(sensitivityListener)
}
override fun onRankingApplied() { override fun onRankingApplied() {
// rankings affect whether a conversation is important, which can change the icons // rankings affect whether a conversation is important, which can change the icons
recalculateForImportantConversationChange() recalculateForImportantConversationChange()
} }
} }
private val sensitivityListener = Runnable { private val sensitivityListener = NotificationEntry.OnSensitivityChangedListener {
for (entry in notifCollection.allNotifs) { entry -> updateIconsSafe(entry)
if (entry.hasSensitiveContents()) {
updateIconsSafe(entry)
}
}
} }
private fun recalculateForImportantConversationChange() { private fun recalculateForImportantConversationChange() {
@@ -181,16 +182,12 @@ class IconManager @Inject constructor(
} }
} }
private inline val NotificationEntry.needsRedactionInPublic: Boolean get() =
hasSensitiveContents() &&
notifLockscreenUserManager.sensitiveNotifsNeedRedactionInPublic(sbn.userId)
@Throws(InflationException::class) @Throws(InflationException::class)
private fun getIconDescriptors( private fun getIconDescriptors(
entry: NotificationEntry entry: NotificationEntry
): Pair<StatusBarIcon, StatusBarIcon> { ): Pair<StatusBarIcon, StatusBarIcon> {
val iconDescriptor = getIconDescriptor(entry, false /* redact */) val iconDescriptor = getIconDescriptor(entry, false /* redact */)
val sensitiveDescriptor = if (entry.needsRedactionInPublic) { val sensitiveDescriptor = if (entry.isSensitive) {
getIconDescriptor(entry, true /* redact */) getIconDescriptor(entry, true /* redact */)
} else { } else {
iconDescriptor iconDescriptor
@@ -313,7 +310,7 @@ class IconManager @Inject constructor(
iconView === entry.icons.shelfIcon || iconView === entry.icons.aodIcon iconView === entry.icons.shelfIcon || iconView === entry.icons.aodIcon
val isSmallIcon = iconDescriptor.icon.equals(entry.sbn.notification.smallIcon) val isSmallIcon = iconDescriptor.icon.equals(entry.sbn.notification.smallIcon)
return isImportantConversation(entry) && !isSmallIcon && return isImportantConversation(entry) && !isSmallIcon &&
(!usedInSensitiveContext || !entry.needsRedactionInPublic) (!usedInSensitiveContext || !entry.isSensitive)
} }
private fun isImportantConversation(entry: NotificationEntry): Boolean { private fun isImportantConversation(entry: NotificationEntry): Boolean {

View File

@@ -90,8 +90,8 @@ import com.android.systemui.statusbar.RemoteInputController;
import com.android.systemui.statusbar.SmartReplyController; import com.android.systemui.statusbar.SmartReplyController;
import com.android.systemui.statusbar.StatusBarIconView; import com.android.systemui.statusbar.StatusBarIconView;
import com.android.systemui.statusbar.notification.AboveShelfChangedListener; import com.android.systemui.statusbar.notification.AboveShelfChangedListener;
import com.android.systemui.statusbar.notification.FeedbackIcon;
import com.android.systemui.statusbar.notification.LaunchAnimationParameters; import com.android.systemui.statusbar.notification.LaunchAnimationParameters;
import com.android.systemui.statusbar.notification.FeedbackIcon;
import com.android.systemui.statusbar.notification.NotificationFadeAware; import com.android.systemui.statusbar.notification.NotificationFadeAware;
import com.android.systemui.statusbar.notification.NotificationLaunchAnimatorController; import com.android.systemui.statusbar.notification.NotificationLaunchAnimatorController;
import com.android.systemui.statusbar.notification.NotificationUtils; import com.android.systemui.statusbar.notification.NotificationUtils;
@@ -202,6 +202,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
/** Are we showing the "public" version */ /** Are we showing the "public" version */
private boolean mShowingPublic; private boolean mShowingPublic;
private boolean mSensitive; private boolean mSensitive;
private boolean mSensitiveHiddenInGeneral;
private boolean mShowingPublicInitialized; private boolean mShowingPublicInitialized;
private boolean mHideSensitiveForIntrinsicHeight; private boolean mHideSensitiveForIntrinsicHeight;
private float mHeaderVisibleAmount = DEFAULT_HEADER_VISIBLE_AMOUNT; private float mHeaderVisibleAmount = DEFAULT_HEADER_VISIBLE_AMOUNT;
@@ -1504,7 +1505,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
mUseIncreasedHeadsUpHeight = use; mUseIncreasedHeadsUpHeight = use;
} }
// TODO: remove this method and mNeedsRedaction entirely once the old pipeline is gone
public void setNeedsRedaction(boolean needsRedaction) { public void setNeedsRedaction(boolean needsRedaction) {
// TODO: Move inflation logic out of this call and remove this method // TODO: Move inflation logic out of this call and remove this method
if (mNeedsRedaction != needsRedaction) { if (mNeedsRedaction != needsRedaction) {
@@ -2587,8 +2587,9 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
getShowingLayout().requestSelectLayout(needsAnimation || isUserLocked()); getShowingLayout().requestSelectLayout(needsAnimation || isUserLocked());
} }
public void setSensitive(boolean sensitive) { public void setSensitive(boolean sensitive, boolean hideSensitive) {
mSensitive = sensitive; mSensitive = sensitive;
mSensitiveHiddenInGeneral = hideSensitive;
} }
@Override @Override
@@ -2678,15 +2679,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
* see {@link NotificationEntry#isDismissable()}. * see {@link NotificationEntry#isDismissable()}.
*/ */
public boolean canViewBeDismissed() { public boolean canViewBeDismissed() {
// Entry not dismissable. return mEntry.isDismissable() && (!shouldShowPublic() || !mSensitiveHiddenInGeneral);
if (!mEntry.isDismissable()) {
return false;
}
// Entry shouldn't be showing the public layout, it can be dismissed.
if (!shouldShowPublic()) {
return true;
}
return false;
} }
/** /**
@@ -2695,7 +2688,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
* clearability see {@link NotificationEntry#isClearable()}. * clearability see {@link NotificationEntry#isClearable()}.
*/ */
public boolean canViewBeCleared() { public boolean canViewBeCleared() {
return mEntry.isClearable() && !shouldShowPublic(); return mEntry.isClearable() && (!shouldShowPublic() || !mSensitiveHiddenInGeneral);
} }
private boolean shouldShowPublic() { private boolean shouldShowPublic() {
@@ -3459,28 +3452,10 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
pw.print(", translation: " + getTranslation()); pw.print(", translation: " + getTranslation());
pw.print(", removed: " + isRemoved()); pw.print(", removed: " + isRemoved());
pw.print(", expandAnimationRunning: " + mExpandAnimationRunning); pw.print(", expandAnimationRunning: " + mExpandAnimationRunning);
pw.print(", sensitive: " + mSensitive); NotificationContentView showingLayout = getShowingLayout();
pw.print(", hideSensitiveForIntrinsicHeight: " + mHideSensitiveForIntrinsicHeight); pw.print(", privateShowing: " + (showingLayout == mPrivateLayout));
pw.println(", privateShowing: " + !shouldShowPublic()); pw.println();
pw.print("privateLayout: "); showingLayout.dump(pw, args);
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) { if (getViewState() != null) {
getViewState().dump(pw, args); getViewState().dump(pw, args);
@@ -3506,6 +3481,8 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
} }
pw.decreaseIndent(); pw.decreaseIndent();
pw.println("}"); pw.println("}");
} else if (mPrivateLayout != null) {
mPrivateLayout.dumpSmartReplies(pw);
} }
}); });
} }

View File

@@ -35,7 +35,6 @@ import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin; import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.shared.plugins.PluginManager; import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationMediaManager; import com.android.systemui.statusbar.NotificationMediaManager;
import com.android.systemui.statusbar.SmartReplyController; import com.android.systemui.statusbar.SmartReplyController;
import com.android.systemui.statusbar.notification.FeedbackIcon; import com.android.systemui.statusbar.notification.FeedbackIcon;
@@ -70,7 +69,6 @@ import javax.inject.Named;
public class ExpandableNotificationRowController implements NotifViewController { public class ExpandableNotificationRowController implements NotifViewController {
private static final String TAG = "NotifRowController"; private static final String TAG = "NotifRowController";
private final ExpandableNotificationRow mView; private final ExpandableNotificationRow mView;
private final NotificationLockscreenUserManager mLockscreenUserManager;
private final NotificationListContainer mListContainer; private final NotificationListContainer mListContainer;
private final RemoteInputViewSubcomponent.Factory mRemoteInputViewSubcomponentFactory; private final RemoteInputViewSubcomponent.Factory mRemoteInputViewSubcomponentFactory;
private final ActivatableNotificationViewController mActivatableNotificationViewController; private final ActivatableNotificationViewController mActivatableNotificationViewController;
@@ -88,6 +86,7 @@ public class ExpandableNotificationRowController implements NotifViewController
private final ExpandableNotificationRow.OnExpandClickListener mOnExpandClickListener; private final ExpandableNotificationRow.OnExpandClickListener mOnExpandClickListener;
private final StatusBarStateController mStatusBarStateController; private final StatusBarStateController mStatusBarStateController;
private final MetricsLogger mMetricsLogger; private final MetricsLogger mMetricsLogger;
private final ExpandableNotificationRow.ExpansionLogger mExpansionLogger = private final ExpandableNotificationRow.ExpansionLogger mExpansionLogger =
this::logNotificationExpansion; this::logNotificationExpansion;
private final ExpandableNotificationRow.CoordinateOnClickListener mOnFeedbackClickListener; private final ExpandableNotificationRow.CoordinateOnClickListener mOnFeedbackClickListener;
@@ -101,12 +100,12 @@ public class ExpandableNotificationRowController implements NotifViewController
private final Optional<BubblesManager> mBubblesManagerOptional; private final Optional<BubblesManager> mBubblesManagerOptional;
private final SmartReplyConstants mSmartReplyConstants; private final SmartReplyConstants mSmartReplyConstants;
private final SmartReplyController mSmartReplyController; private final SmartReplyController mSmartReplyController;
private final ExpandableNotificationRowDragController mDragController; private final ExpandableNotificationRowDragController mDragController;
@Inject @Inject
public ExpandableNotificationRowController( public ExpandableNotificationRowController(
ExpandableNotificationRow view, ExpandableNotificationRow view,
NotificationLockscreenUserManager lockscreenUserManager,
ActivatableNotificationViewController activatableNotificationViewController, ActivatableNotificationViewController activatableNotificationViewController,
RemoteInputViewSubcomponent.Factory rivSubcomponentFactory, RemoteInputViewSubcomponent.Factory rivSubcomponentFactory,
MetricsLogger metricsLogger, MetricsLogger metricsLogger,
@@ -136,7 +135,6 @@ public class ExpandableNotificationRowController implements NotifViewController
Optional<BubblesManager> bubblesManagerOptional, Optional<BubblesManager> bubblesManagerOptional,
ExpandableNotificationRowDragController dragController) { ExpandableNotificationRowDragController dragController) {
mView = view; mView = view;
mLockscreenUserManager = lockscreenUserManager;
mListContainer = listContainer; mListContainer = listContainer;
mRemoteInputViewSubcomponentFactory = rivSubcomponentFactory; mRemoteInputViewSubcomponentFactory = rivSubcomponentFactory;
mActivatableNotificationViewController = activatableNotificationViewController; mActivatableNotificationViewController = activatableNotificationViewController;
@@ -216,10 +214,6 @@ public class ExpandableNotificationRowController implements NotifViewController
mView.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS); mView.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS);
} }
mLockscreenUserManager
.addOnNeedsRedactionInPublicChangedListener(mNeedsRedactionListener);
mNeedsRedactionListener.run();
mView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() { mView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
@Override @Override
public void onViewAttachedToWindow(View v) { public void onViewAttachedToWindow(View v) {
@@ -238,14 +232,6 @@ public class ExpandableNotificationRowController implements NotifViewController
}); });
} }
private final Runnable mNeedsRedactionListener = new Runnable() {
@Override
public void run() {
mView.setSensitive(
mLockscreenUserManager.notifNeedsRedactionInPublic(mView.getEntry()));
}
};
private final StatusBarStateController.StateListener mStatusBarStateListener = private final StatusBarStateController.StateListener mStatusBarStateListener =
new StatusBarStateController.StateListener() { new StatusBarStateController.StateListener() {
@Override @Override
@@ -347,5 +333,4 @@ public class ExpandableNotificationRowController implements NotifViewController
public void setFeedbackIcon(@Nullable FeedbackIcon icon) { public void setFeedbackIcon(@Nullable FeedbackIcon icon) {
mView.setFeedbackIcon(icon); mView.setFeedbackIcon(icon);
} }
} }

View File

@@ -61,7 +61,6 @@ import com.android.systemui.statusbar.policy.SmartReplyStateInflaterKt;
import com.android.systemui.statusbar.policy.SmartReplyView; import com.android.systemui.statusbar.policy.SmartReplyView;
import com.android.systemui.statusbar.policy.dagger.RemoteInputViewSubcomponent; import com.android.systemui.statusbar.policy.dagger.RemoteInputViewSubcomponent;
import com.android.systemui.util.Compile; import com.android.systemui.util.Compile;
import com.android.systemui.util.DumpUtilsKt;
import com.android.systemui.wmshell.BubblesManager; import com.android.systemui.wmshell.BubblesManager;
import java.io.PrintWriter; import java.io.PrintWriter;
@@ -1995,33 +1994,22 @@ public class NotificationContentView extends FrameLayout implements Notification
} }
} }
public void dump(PrintWriter pwOriginal, String[] args) { public void dump(PrintWriter pw, String[] args) {
IndentingPrintWriter pw = DumpUtilsKt.asIndenting(pwOriginal);
pw.print("contentView visibility: " + getVisibility()); pw.print("contentView visibility: " + getVisibility());
pw.print(", alpha: " + getAlpha()); pw.print(", alpha: " + getAlpha());
pw.print(", clipBounds: " + getClipBounds()); pw.print(", clipBounds: " + getClipBounds());
pw.print(", contentHeight: " + mContentHeight); pw.print(", contentHeight: " + mContentHeight);
pw.println(", currentVisibleType: " + mVisibleType); pw.print(", visibleType: " + mVisibleType);
DumpUtilsKt.withIncreasedIndent(pw, () -> { View view = getViewForVisibleType(mVisibleType);
int[] visTypes = { pw.print(", visibleView ");
VISIBLE_TYPE_CONTRACTED, if (view != null) {
VISIBLE_TYPE_EXPANDED, pw.print(" visibility: " + view.getVisibility());
VISIBLE_TYPE_HEADSUP, pw.print(", alpha: " + view.getAlpha());
VISIBLE_TYPE_SINGLELINE pw.print(", clipBounds: " + view.getClipBounds());
}; } else {
for (int visType : visTypes) { pw.print("null");
pw.print("visType: " + visType + " :: "); }
View view = getViewForVisibleType(visType); pw.println();
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 */ /** Add any existing SmartReplyView to the dump */

View File

@@ -102,9 +102,8 @@ public final class RowContentBindParams {
* @see InflationFlag * @see InflationFlag
*/ */
public void markContentViewsFreeable(@InflationFlag int contentViews) { public void markContentViewsFreeable(@InflationFlag int contentViews) {
@InflationFlag int existingContentViews = contentViews &= mContentViews;
mContentViews &= ~contentViews; mContentViews &= ~contentViews;
mDirtyContentViews |= existingContentViews; mDirtyContentViews &= ~contentViews;
} }
public @InflationFlag int getContentViews() { public @InflationFlag int getContentViews() {

View File

@@ -216,9 +216,6 @@ public class NotificationStackScrollLayoutController {
mBarState = mStatusBarStateController.getState(); mBarState = mStatusBarStateController.getState();
mStatusBarStateController.addCallback( mStatusBarStateController.addCallback(
mStateListener, SysuiStatusBarStateController.RANK_STACK_SCROLLER); mStateListener, SysuiStatusBarStateController.RANK_STACK_SCROLLER);
mLockscreenUserManager.addOnNeedsRedactionInPublicChangedListener(
mOnNeedsRedactionInPublicChangedListener);
updateClearButtonVisibility();
} }
@Override @Override
@@ -226,8 +223,6 @@ public class NotificationStackScrollLayoutController {
mConfigurationController.removeCallback(mConfigurationListener); mConfigurationController.removeCallback(mConfigurationListener);
mZenModeController.removeCallback(mZenModeControllerCallback); mZenModeController.removeCallback(mZenModeControllerCallback);
mStatusBarStateController.removeCallback(mStateListener); mStatusBarStateController.removeCallback(mStateListener);
mLockscreenUserManager.removeOnNeedsRedactionInPublicChangedListener(
mOnNeedsRedactionInPublicChangedListener);
} }
}; };
@@ -331,7 +326,6 @@ public class NotificationStackScrollLayoutController {
mLockscreenUserManager.isAnyProfilePublicMode()); mLockscreenUserManager.isAnyProfilePublicMode());
mView.onStatePostChange(mStatusBarStateController.fromShadeLocked()); mView.onStatePostChange(mStatusBarStateController.fromShadeLocked());
mNotificationEntryManager.updateNotifications("CentralSurfaces state changed"); mNotificationEntryManager.updateNotifications("CentralSurfaces state changed");
updateClearButtonVisibility();
} }
}; };
@@ -344,17 +338,6 @@ public class NotificationStackScrollLayoutController {
} }
}; };
private final Runnable mOnNeedsRedactionInPublicChangedListener = new Runnable() {
@Override
public void run() {
// Whether or not the notification needs redaction when in public has changed, but if
// we're not actually in public, then we don't need to update anything.
if (mLockscreenUserManager.isAnyProfilePublicMode()) {
updateClearButtonVisibility();
}
}
};
/** /**
* Set the overexpansion of the panel to be applied to the view. * Set the overexpansion of the panel to be applied to the view.
*/ */
@@ -1291,44 +1274,12 @@ public class NotificationStackScrollLayoutController {
return hasNotifications(selection, true /* clearable */); 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) { public boolean hasNotifications(@SelectedRows int selection, boolean isClearable) {
boolean hasAlertingMatchingClearable = isClearable boolean hasAlertingMatchingClearable = isClearable
? hasClearableAlertingNotifs() ? mNotifStats.getHasClearableAlertingNotifs()
: mNotifStats.getHasNonClearableAlertingNotifs(); : mNotifStats.getHasNonClearableAlertingNotifs();
boolean hasSilentMatchingClearable = isClearable boolean hasSilentMatchingClearable = isClearable
? hasClearableSilentNotifs() ? mNotifStats.getHasClearableSilentNotifs()
: mNotifStats.getHasNonClearableSilentNotifs(); : mNotifStats.getHasNonClearableSilentNotifs();
switch (selection) { switch (selection) {
case ROWS_GENTLE: case ROWS_GENTLE:
@@ -1628,15 +1579,6 @@ public class NotificationStackScrollLayoutController {
mNotificationActivityStarter = activityStarter; mNotificationActivityStarter = activityStarter;
} }
private void updateClearButtonVisibility() {
updateClearSilentButton();
updateFooter();
}
private void updateClearSilentButton() {
mSilentHeaderController.setClearSectionEnabled(hasClearableSilentNotifs());
}
/** /**
* Enum for UiEvent logged from this class * Enum for UiEvent logged from this class
*/ */
@@ -1962,7 +1904,6 @@ public class NotificationStackScrollLayoutController {
@Override @Override
public void setNotifStats(@NonNull NotifStats notifStats) { public void setNotifStats(@NonNull NotifStats notifStats) {
mNotifStats = notifStats; mNotifStats = notifStats;
updateClearSilentButton();
updateFooter(); updateFooter();
updateShowEmptyShadeView(); updateShowEmptyShadeView();
} }

View File

@@ -29,7 +29,6 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.CrossFadeHelper; import com.android.systemui.statusbar.CrossFadeHelper;
import com.android.systemui.statusbar.HeadsUpStatusBarView; import com.android.systemui.statusbar.HeadsUpStatusBarView;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator; import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.NotificationEntry;
@@ -41,8 +40,8 @@ import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener; import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
import com.android.systemui.util.ViewController; import com.android.systemui.util.ViewController;
import java.util.ArrayList;
import java.util.Optional; import java.util.Optional;
import java.util.ArrayList;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
import java.util.function.Consumer; import java.util.function.Consumer;
@@ -62,17 +61,17 @@ public class HeadsUpAppearanceController extends ViewController<HeadsUpStatusBar
private final NotificationIconAreaController mNotificationIconAreaController; private final NotificationIconAreaController mNotificationIconAreaController;
private final HeadsUpManagerPhone mHeadsUpManager; private final HeadsUpManagerPhone mHeadsUpManager;
private final NotificationStackScrollLayoutController mStackScrollerController; private final NotificationStackScrollLayoutController mStackScrollerController;
private final DarkIconDispatcher mDarkIconDispatcher; private final DarkIconDispatcher mDarkIconDispatcher;
private final NotificationPanelViewController mNotificationPanelViewController; private final NotificationPanelViewController mNotificationPanelViewController;
private final Consumer<ExpandableNotificationRow> mSetTrackingHeadsUp = private final Consumer<ExpandableNotificationRow>
this::setTrackingHeadsUp; mSetTrackingHeadsUp = this::setTrackingHeadsUp;
private final BiConsumer<Float, Float> mSetExpandedHeight = this::setAppearFraction; private final BiConsumer<Float, Float> mSetExpandedHeight = this::setAppearFraction;
private final KeyguardBypassController mBypassController; private final KeyguardBypassController mBypassController;
private final StatusBarStateController mStatusBarStateController; private final StatusBarStateController mStatusBarStateController;
private final CommandQueue mCommandQueue; private final CommandQueue mCommandQueue;
private final NotificationWakeUpCoordinator mWakeUpCoordinator; private final NotificationWakeUpCoordinator mWakeUpCoordinator;
private final NotificationLockscreenUserManager mNotifLockscreenUserManager;
private final Runnable mRedactionChanged = this::updateRedaction;
private final View mClockView; private final View mClockView;
private final Optional<View> mOperatorNameViewOptional; private final Optional<View> mOperatorNameViewOptional;
@@ -91,13 +90,6 @@ public class HeadsUpAppearanceController extends ViewController<HeadsUpStatusBar
}; };
private boolean mAnimationsEnabled = true; private boolean mAnimationsEnabled = true;
private final KeyguardStateController mKeyguardStateController; private final KeyguardStateController mKeyguardStateController;
private final StatusBarStateController.StateListener mStatusBarStateListener =
new StatusBarStateController.StateListener() {
@Override
public void onStatePostChange() {
updateRedaction();
}
};
@VisibleForTesting @VisibleForTesting
@Inject @Inject
@@ -106,7 +98,6 @@ public class HeadsUpAppearanceController extends ViewController<HeadsUpStatusBar
HeadsUpManagerPhone headsUpManager, HeadsUpManagerPhone headsUpManager,
StatusBarStateController stateController, StatusBarStateController stateController,
KeyguardBypassController bypassController, KeyguardBypassController bypassController,
NotificationLockscreenUserManager notifLockscreenUserManager,
NotificationWakeUpCoordinator wakeUpCoordinator, NotificationWakeUpCoordinator wakeUpCoordinator,
DarkIconDispatcher darkIconDispatcher, DarkIconDispatcher darkIconDispatcher,
KeyguardStateController keyguardStateController, KeyguardStateController keyguardStateController,
@@ -134,7 +125,6 @@ public class HeadsUpAppearanceController extends ViewController<HeadsUpStatusBar
mClockView = clockView; mClockView = clockView;
mOperatorNameViewOptional = operatorNameViewOptional; mOperatorNameViewOptional = operatorNameViewOptional;
mDarkIconDispatcher = darkIconDispatcher; mDarkIconDispatcher = darkIconDispatcher;
mNotifLockscreenUserManager = notifLockscreenUserManager;
mView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() { mView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
@Override @Override
@@ -166,8 +156,6 @@ public class HeadsUpAppearanceController extends ViewController<HeadsUpStatusBar
mNotificationPanelViewController.setHeadsUpAppearanceController(this); mNotificationPanelViewController.setHeadsUpAppearanceController(this);
mStackScrollerController.addOnExpandedHeightChangedListener(mSetExpandedHeight); mStackScrollerController.addOnExpandedHeightChangedListener(mSetExpandedHeight);
mDarkIconDispatcher.addDarkReceiver(this); mDarkIconDispatcher.addDarkReceiver(this);
mNotifLockscreenUserManager.addOnNeedsRedactionInPublicChangedListener(mRedactionChanged);
mStatusBarStateController.addCallback(mStatusBarStateListener);
} }
@Override @Override
@@ -179,9 +167,6 @@ public class HeadsUpAppearanceController extends ViewController<HeadsUpStatusBar
mNotificationPanelViewController.setHeadsUpAppearanceController(null); mNotificationPanelViewController.setHeadsUpAppearanceController(null);
mStackScrollerController.removeOnExpandedHeightChangedListener(mSetExpandedHeight); mStackScrollerController.removeOnExpandedHeightChangedListener(mSetExpandedHeight);
mDarkIconDispatcher.removeDarkReceiver(this); mDarkIconDispatcher.removeDarkReceiver(this);
mNotifLockscreenUserManager
.removeOnNeedsRedactionInPublicChangedListener(mRedactionChanged);
mStatusBarStateController.removeCallback(mStatusBarStateListener);
} }
private void updateIsolatedIconLocation(boolean requireStateUpdate) { private void updateIsolatedIconLocation(boolean requireStateUpdate) {
@@ -195,19 +180,6 @@ public class HeadsUpAppearanceController extends ViewController<HeadsUpStatusBar
updateHeader(entry); 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() { private void updateTopEntry() {
NotificationEntry newEntry = null; NotificationEntry newEntry = null;
if (shouldBeVisible()) { if (shouldBeVisible()) {

View File

@@ -32,6 +32,7 @@ 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.shared.system.QuickStepContract.SYSUI_STATE_QUICK_SETTINGS_EXPANDED;
import static com.android.systemui.statusbar.StatusBarState.KEYGUARD; import static com.android.systemui.statusbar.StatusBarState.KEYGUARD;
import static com.android.systemui.statusbar.StatusBarState.SHADE; 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.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_CLOSED;
import static com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManagerKt.STATE_OPEN; import static com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManagerKt.STATE_OPEN;
@@ -3950,6 +3951,10 @@ public class NotificationPanelViewController extends PanelViewController {
} }
} }
public boolean hasActiveClearableNotifications() {
return mNotificationStackScrollLayoutController.hasActiveClearableNotifications(ROWS_ALL);
}
public RemoteInputController.Delegate createRemoteInputDelegate() { public RemoteInputController.Delegate createRemoteInputDelegate() {
return mNotificationStackScrollLayoutController.createDelegate(); return mNotificationStackScrollLayoutController.createDelegate();
} }

View File

@@ -411,8 +411,8 @@ class StatusBarNotificationPresenter implements NotificationPresenter,
if (nowExpanded) { if (nowExpanded) {
if (mStatusBarStateController.getState() == StatusBarState.KEYGUARD) { if (mStatusBarStateController.getState() == StatusBarState.KEYGUARD) {
mShadeTransitionController.goToLockedShade(clickedEntry.getRow()); mShadeTransitionController.goToLockedShade(clickedEntry.getRow());
} else if (mDynamicPrivacyController.isInLockedDownShade() } else if (clickedEntry.isSensitive()
&& mLockscreenUserManager.notifNeedsRedactionInPublic(clickedEntry)) { && mDynamicPrivacyController.isInLockedDownShade()) {
mStatusBarStateController.setLeaveOpenOnKeyguardHide(true); mStatusBarStateController.setLeaveOpenOnKeyguardHide(true);
mActivityStarter.dismissKeyguardThenExecute(() -> false /* dismissAction */ mActivityStarter.dismissKeyguardThenExecute(() -> false /* dismissAction */
, null /* cancelRunnable */, false /* afterKeyguardGone */); , null /* cancelRunnable */, false /* afterKeyguardGone */);
@@ -480,7 +480,7 @@ class StatusBarNotificationPresenter implements NotificationPresenter,
.isLockscreenPublicMode(mLockscreenUserManager.getCurrentUserId()); .isLockscreenPublicMode(mLockscreenUserManager.getCurrentUserId());
boolean userPublic = devicePublic boolean userPublic = devicePublic
|| mLockscreenUserManager.isLockscreenPublicMode(sbn.getUserId()); || mLockscreenUserManager.isLockscreenPublicMode(sbn.getUserId());
boolean needsRedaction = mLockscreenUserManager.notifNeedsRedactionInPublic(entry); boolean needsRedaction = mLockscreenUserManager.needsRedaction(entry);
if (userPublic && needsRedaction) { if (userPublic && needsRedaction) {
// TODO(b/135046837): we can probably relax this with dynamic privacy // TODO(b/135046837): we can probably relax this with dynamic privacy
return true; return true;

View File

@@ -130,8 +130,8 @@ class LockscreenShadeTransitionControllerTest : SysuiTestCase() {
whenever(statusbarStateController.state).thenReturn(StatusBarState.KEYGUARD) whenever(statusbarStateController.state).thenReturn(StatusBarState.KEYGUARD)
whenever(nsslController.isInLockedDownShade).thenReturn(false) whenever(nsslController.isInLockedDownShade).thenReturn(false)
whenever(qS.isFullyCollapsed).thenReturn(true) whenever(qS.isFullyCollapsed).thenReturn(true)
whenever(lockScreenUserManager.sensitiveNotifsNeedRedactionInPublic(anyInt())) whenever(lockScreenUserManager.userAllowsPrivateNotificationsInPublic(anyInt())).thenReturn(
.thenReturn(false) true)
whenever(lockScreenUserManager.shouldShowLockscreenNotifications()).thenReturn(true) whenever(lockScreenUserManager.shouldShowLockscreenNotifications()).thenReturn(true)
whenever(lockScreenUserManager.isLockscreenPublicMode(anyInt())).thenReturn(true) whenever(lockScreenUserManager.isLockscreenPublicMode(anyInt())).thenReturn(true)
whenever(falsingCollector.shouldEnforceBouncer()).thenReturn(false) whenever(falsingCollector.shouldEnforceBouncer()).thenReturn(false)
@@ -207,8 +207,8 @@ class LockscreenShadeTransitionControllerTest : SysuiTestCase() {
@Test @Test
fun testTriggeringBouncerWhenPrivateNotificationsArentAllowed() { fun testTriggeringBouncerWhenPrivateNotificationsArentAllowed() {
whenever(lockScreenUserManager.sensitiveNotifsNeedRedactionInPublic(anyInt())) whenever(lockScreenUserManager.userAllowsPrivateNotificationsInPublic(anyInt())).thenReturn(
.thenReturn(true) false)
transitionController.goToLockedShade(null) transitionController.goToLockedShade(null)
verify(statusbarStateController, never()).setState(anyInt()) verify(statusbarStateController, never()).setState(anyInt())
verify(statusbarStateController).setLeaveOpenOnKeyguardHide(true) verify(statusbarStateController).setLeaveOpenOnKeyguardHide(true)

View File

@@ -53,13 +53,11 @@ import android.testing.TestableLooper;
import androidx.test.filters.SmallTest; import androidx.test.filters.SmallTest;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.Dependency; import com.android.systemui.Dependency;
import com.android.systemui.SysuiTestCase; import com.android.systemui.SysuiTestCase;
import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dump.DumpManager; import com.android.systemui.dump.DumpManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController; 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.NotificationLockscreenUserManager.KeyguardNotificationSuppressor;
import com.android.systemui.statusbar.notification.NotificationEntryManager; import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.NotificationEntry;
@@ -108,10 +106,6 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase {
private BroadcastDispatcher mBroadcastDispatcher; private BroadcastDispatcher mBroadcastDispatcher;
@Mock @Mock
private KeyguardStateController mKeyguardStateController; private KeyguardStateController mKeyguardStateController;
@Mock
private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
@Mock
private OverviewProxyService mOverviewProxyService;
private UserInfo mCurrentUser; private UserInfo mCurrentUser;
private UserInfo mSecondaryUser; private UserInfo mSecondaryUser;
@@ -125,6 +119,7 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase {
@Before @Before
public void setUp() { public void setUp() {
MockitoAnnotations.initMocks(this); MockitoAnnotations.initMocks(this);
mDependency.injectTestDependency(NotificationEntryManager.class, mEntryManager);
int currentUserId = ActivityManager.getCurrentUser(); int currentUserId = ActivityManager.getCurrentUser();
mSettings = new FakeSettings(); mSettings = new FakeSettings();
@@ -217,7 +212,7 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase {
mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false); mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false);
// THEN current user's notification is redacted // THEN current user's notification is redacted
assertTrue(mLockscreenUserManager.notifNeedsRedactionInPublic(mCurrentUserNotif)); assertTrue(mLockscreenUserManager.needsRedaction(mCurrentUserNotif));
} }
@Test @Test
@@ -228,7 +223,7 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase {
mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false); mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false);
// THEN current user's notification isn't redacted // THEN current user's notification isn't redacted
assertFalse(mLockscreenUserManager.notifNeedsRedactionInPublic(mCurrentUserNotif)); assertFalse(mLockscreenUserManager.needsRedaction(mCurrentUserNotif));
} }
@Test @Test
@@ -239,7 +234,7 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase {
mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false); mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false);
// THEN work profile notification is redacted // THEN work profile notification is redacted
assertTrue(mLockscreenUserManager.notifNeedsRedactionInPublic(mWorkProfileNotif)); assertTrue(mLockscreenUserManager.needsRedaction(mWorkProfileNotif));
} }
@Test @Test
@@ -250,7 +245,7 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase {
mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false); mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false);
// THEN work profile notification isn't redacted // THEN work profile notification isn't redacted
assertFalse(mLockscreenUserManager.notifNeedsRedactionInPublic(mWorkProfileNotif)); assertFalse(mLockscreenUserManager.needsRedaction(mWorkProfileNotif));
} }
@Test @Test
@@ -265,11 +260,11 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase {
mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false); mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false);
// THEN the work profile notification doesn't need to be redacted // THEN the work profile notification doesn't need to be redacted
assertFalse(mLockscreenUserManager.notifNeedsRedactionInPublic(mWorkProfileNotif)); assertFalse(mLockscreenUserManager.needsRedaction(mWorkProfileNotif));
// THEN the current user and secondary user notifications do need to be redacted // THEN the current user and secondary user notifications do need to be redacted
assertTrue(mLockscreenUserManager.notifNeedsRedactionInPublic(mCurrentUserNotif)); assertTrue(mLockscreenUserManager.needsRedaction(mCurrentUserNotif));
assertTrue(mLockscreenUserManager.notifNeedsRedactionInPublic(mSecondaryUserNotif)); assertTrue(mLockscreenUserManager.needsRedaction(mSecondaryUserNotif));
} }
@Test @Test
@@ -284,11 +279,11 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase {
mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false); mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false);
// THEN the work profile notification needs to be redacted // THEN the work profile notification needs to be redacted
assertTrue(mLockscreenUserManager.notifNeedsRedactionInPublic(mWorkProfileNotif)); assertTrue(mLockscreenUserManager.needsRedaction(mWorkProfileNotif));
// THEN the current user and secondary user notifications don't need to be redacted // THEN the current user and secondary user notifications don't need to be redacted
assertFalse(mLockscreenUserManager.notifNeedsRedactionInPublic(mCurrentUserNotif)); assertFalse(mLockscreenUserManager.needsRedaction(mCurrentUserNotif));
assertFalse(mLockscreenUserManager.notifNeedsRedactionInPublic(mSecondaryUserNotif)); assertFalse(mLockscreenUserManager.needsRedaction(mSecondaryUserNotif));
} }
@Test @Test
@@ -303,7 +298,7 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase {
// THEN the secondary profile notification still needs to be redacted because the current // THEN the secondary profile notification still needs to be redacted because the current
// user's setting takes precedence // user's setting takes precedence
assertTrue(mLockscreenUserManager.notifNeedsRedactionInPublic(mSecondaryUserNotif)); assertTrue(mLockscreenUserManager.needsRedaction(mSecondaryUserNotif));
} }
@Test @Test
@@ -423,12 +418,9 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase {
context, context,
mBroadcastDispatcher, mBroadcastDispatcher,
mDevicePolicyManager, mDevicePolicyManager,
mKeyguardUpdateMonitor,
() -> mEntryManager,
() -> mOverviewProxyService,
mUserManager, mUserManager,
() -> mVisibilityProvider, (() -> mVisibilityProvider),
() -> mNotifCollection, (() -> mNotifCollection),
mClickNotifier, mClickNotifier,
NotificationLockscreenUserManagerTest.this.mKeyguardManager, NotificationLockscreenUserManagerTest.this.mKeyguardManager,
mStatusBarStateController, mStatusBarStateController,

View File

@@ -124,8 +124,8 @@ public class DynamicPrivacyControllerTest extends SysuiTestCase {
} }
private void allowPrivateNotificationsInPublic(boolean allow) { private void allowPrivateNotificationsInPublic(boolean allow) {
when(mLockScreenUserManager.sensitiveNotifsNeedRedactionInPublic(anyInt())).thenReturn( when(mLockScreenUserManager.userAllowsPrivateNotificationsInPublic(anyInt())).thenReturn(
!allow); allow);
} }
@Test @Test

View File

@@ -23,6 +23,7 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.spy; import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times; import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
@@ -32,6 +33,7 @@ import android.app.Notification;
import android.app.NotificationManager; import android.app.NotificationManager;
import android.testing.AndroidTestingRunner; import android.testing.AndroidTestingRunner;
import androidx.annotation.Nullable;
import androidx.test.filters.SmallTest; import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase; import com.android.systemui.SysuiTestCase;
@@ -39,6 +41,7 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.RankingBuilder; import com.android.systemui.statusbar.RankingBuilder;
import com.android.systemui.statusbar.SbnBuilder; import com.android.systemui.statusbar.SbnBuilder;
import com.android.systemui.statusbar.notification.SectionClassifier; 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.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder; import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
@@ -46,6 +49,7 @@ import com.android.systemui.statusbar.notification.collection.listbuilder.plugga
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner; import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner;
import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider; 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.NodeController;
import com.android.systemui.statusbar.notification.collection.render.SectionHeaderController;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@@ -68,6 +72,7 @@ public class RankingCoordinatorTest extends SysuiTestCase {
@Mock private NotifPipeline mNotifPipeline; @Mock private NotifPipeline mNotifPipeline;
@Mock private NodeController mAlertingHeaderController; @Mock private NodeController mAlertingHeaderController;
@Mock private NodeController mSilentNodeController; @Mock private NodeController mSilentNodeController;
@Mock private SectionHeaderController mSilentHeaderController;
@Captor private ArgumentCaptor<NotifFilter> mNotifFilterCaptor; @Captor private ArgumentCaptor<NotifFilter> mNotifFilterCaptor;
@@ -89,6 +94,7 @@ public class RankingCoordinatorTest extends SysuiTestCase {
mHighPriorityProvider, mHighPriorityProvider,
mSectionClassifier, mSectionClassifier,
mAlertingHeaderController, mAlertingHeaderController,
mSilentHeaderController,
mSilentNodeController); mSilentNodeController);
mEntry = spy(new NotificationEntryBuilder().build()); mEntry = spy(new NotificationEntryBuilder().build());
mEntry.setRanking(getRankingForUnfilteredNotif().build()); mEntry.setRanking(getRankingForUnfilteredNotif().build());
@@ -105,6 +111,25 @@ public class RankingCoordinatorTest extends SysuiTestCase {
mSections.addAll(Arrays.asList(mAlertingSectioner, mSilentSectioner, mMinimizedSectioner)); mSections.addAll(Arrays.asList(mAlertingSectioner, mSilentSectioner, mMinimizedSectioner));
} }
@Test
public void testSilentHeaderClearableChildrenUpdate() {
ListEntry listEntry = new ListEntry(mEntry.getKey(), 0L) {
@Nullable
@Override
public NotificationEntry getRepresentativeEntry() {
return mEntry;
}
};
setRankingAmbient(false);
setSbnClearable(true);
mSilentSectioner.onEntriesUpdated(Arrays.asList(listEntry));
verify(mSilentHeaderController).setClearSectionEnabled(eq(true));
setSbnClearable(false);
mSilentSectioner.onEntriesUpdated(Arrays.asList(listEntry));
verify(mSilentHeaderController).setClearSectionEnabled(eq(false));
}
@Test @Test
public void testUnfilteredState() { public void testUnfilteredState() {
// GIVEN no suppressed visual effects + app not suspended // GIVEN no suppressed visual effects + app not suspended
@@ -200,6 +225,46 @@ public class RankingCoordinatorTest extends SysuiTestCase {
assertInSection(mEntry, mSilentSectioner); 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) { private void assertInSection(NotificationEntry entry, NotifSectioner section) {
for (NotifSectioner current: mSections) { for (NotifSectioner current: mSections) {
if (current == section) { if (current == section) {

View File

@@ -0,0 +1,268 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.systemui.statusbar.notification.collection.coordinator
import android.os.UserHandle
import android.service.notification.StatusBarNotification
import androidx.test.filters.SmallTest
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.systemui.SysuiTestCase
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.statusbar.NotificationLockscreenUserManager
import com.android.systemui.statusbar.StatusBarState
import com.android.systemui.statusbar.notification.DynamicPrivacyController
import com.android.systemui.statusbar.notification.collection.ListEntry
import com.android.systemui.statusbar.notification.collection.NotifPipeline
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope
import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeRenderListListener
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.Invalidator
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.Pluggable
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.withArgCaptor
import dagger.BindsInstance
import dagger.Component
import org.junit.Test
import org.mockito.Mockito.never
import org.mockito.Mockito.verify
import org.mockito.Mockito.`when` as whenever
@SmallTest
class SensitiveContentCoordinatorTest : SysuiTestCase() {
val dynamicPrivacyController: DynamicPrivacyController = mock()
val lockscreenUserManager: NotificationLockscreenUserManager = mock()
val pipeline: NotifPipeline = mock()
val keyguardUpdateMonitor: KeyguardUpdateMonitor = mock()
val statusBarStateController: StatusBarStateController = mock()
val keyguardStateController: KeyguardStateController = mock()
val coordinator: SensitiveContentCoordinator =
DaggerTestSensitiveContentCoordinatorComponent
.factory()
.create(
dynamicPrivacyController,
lockscreenUserManager,
keyguardUpdateMonitor,
statusBarStateController,
keyguardStateController)
.coordinator
@Test
fun onDynamicPrivacyChanged_invokeInvalidationListener() {
coordinator.attach(pipeline)
val invalidator = withArgCaptor<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
}
}

View File

@@ -15,7 +15,6 @@
*/ */
package com.android.systemui.statusbar.notification.collection.coordinator package com.android.systemui.statusbar.notification.collection.coordinator
import android.os.UserHandle
import android.testing.AndroidTestingRunner import android.testing.AndroidTestingRunner
import android.testing.TestableLooper.RunWithLooper import android.testing.TestableLooper.RunWithLooper
import androidx.test.filters.SmallTest import androidx.test.filters.SmallTest
@@ -44,11 +43,6 @@ import org.mockito.Mockito.`when` as whenever
@RunWith(AndroidTestingRunner::class) @RunWith(AndroidTestingRunner::class)
@RunWithLooper @RunWithLooper
class StackCoordinatorTest : SysuiTestCase() { class StackCoordinatorTest : SysuiTestCase() {
companion object {
const val NOTIF_USER_ID = 0
}
private lateinit var coordinator: StackCoordinator private lateinit var coordinator: StackCoordinator
private lateinit var afterRenderListListener: OnAfterRenderListListener private lateinit var afterRenderListListener: OnAfterRenderListListener
@@ -67,10 +61,7 @@ class StackCoordinatorTest : SysuiTestCase() {
afterRenderListListener = withArgCaptor { afterRenderListListener = withArgCaptor {
verify(pipeline).addOnAfterRenderListListener(capture()) verify(pipeline).addOnAfterRenderListListener(capture())
} }
entry = NotificationEntryBuilder() entry = NotificationEntryBuilder().setSection(section).build()
.setSection(section)
.setUser(UserHandle.of(NOTIF_USER_ID))
.build()
} }
@Test @Test
@@ -83,31 +74,13 @@ class StackCoordinatorTest : SysuiTestCase() {
fun testSetNotificationStats_clearableAlerting() { fun testSetNotificationStats_clearableAlerting() {
whenever(section.bucket).thenReturn(BUCKET_ALERTING) whenever(section.bucket).thenReturn(BUCKET_ALERTING)
afterRenderListListener.onAfterRenderList(listOf(entry), stackController) afterRenderListListener.onAfterRenderList(listOf(entry), stackController)
verify(stackController) verify(stackController).setNotifStats(NotifStats(1, false, true, false, false))
.setNotifStats(
NotifStats(
1,
false,
true,
false,
false,
setOf(NOTIF_USER_ID),
emptySet()))
} }
@Test @Test
fun testSetNotificationStats_clearableSilent() { fun testSetNotificationStats_clearableSilent() {
whenever(section.bucket).thenReturn(BUCKET_SILENT) whenever(section.bucket).thenReturn(BUCKET_SILENT)
afterRenderListListener.onAfterRenderList(listOf(entry), stackController) afterRenderListListener.onAfterRenderList(listOf(entry), stackController)
verify(stackController) verify(stackController).setNotifStats(NotifStats(1, false, false, false, true))
.setNotifStats(
NotifStats(
1,
false,
false,
false,
true,
emptySet(),
setOf(NOTIF_USER_ID)))
} }
} }

View File

@@ -14,10 +14,10 @@
* limitations under the License. * 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.ActivityManager;
import android.app.Notification import android.app.Notification;
import android.app.NotificationChannel import android.app.NotificationChannel
import android.app.NotificationManager.IMPORTANCE_DEFAULT import android.app.NotificationManager.IMPORTANCE_DEFAULT
import android.app.Person import android.app.Person
@@ -27,12 +27,11 @@ import android.graphics.drawable.Drawable
import android.graphics.drawable.Icon import android.graphics.drawable.Icon
import android.os.SystemClock import android.os.SystemClock
import android.os.UserHandle import android.os.UserHandle
import android.testing.AndroidTestingRunner import android.testing.AndroidTestingRunner;
import androidx.test.InstrumentationRegistry import androidx.test.InstrumentationRegistry
import androidx.test.filters.SmallTest import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase import com.android.systemui.SysuiTestCase
import com.android.systemui.controls.controller.AuxiliaryPersistenceWrapperTest.Companion.any 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.NotificationEntry
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder
import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection
@@ -41,7 +40,7 @@ import org.junit.Assert.assertEquals
import org.junit.Before import org.junit.Before
import org.junit.Test import org.junit.Test
import org.junit.runner.RunWith import org.junit.runner.RunWith;
import org.mockito.Mock import org.mockito.Mock
import org.mockito.Mockito.`when` import org.mockito.Mockito.`when`
import org.mockito.Mockito.anyInt import org.mockito.Mockito.anyInt
@@ -49,14 +48,15 @@ import org.mockito.MockitoAnnotations
@SmallTest @SmallTest
@RunWith(AndroidTestingRunner::class) @RunWith(AndroidTestingRunner::class)
class IconManagerTest : SysuiTestCase() { class IconManagerTest: SysuiTestCase() {
companion object { companion object {
private const val TEST_PACKAGE_NAME = "test" private const val TEST_PACKAGE_NAME = "test";
private const val TEST_UID = 0 private const val TEST_UID = 0;
} }
private var id = 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 shortcut: ShortcutInfo
@Mock private lateinit var shortcutIc: Icon @Mock private lateinit var shortcutIc: Icon
@Mock private lateinit var messageIc: Icon @Mock private lateinit var messageIc: Icon
@@ -65,7 +65,6 @@ class IconManagerTest : SysuiTestCase() {
@Mock private lateinit var drawable: Drawable @Mock private lateinit var drawable: Drawable
@Mock private lateinit var row: ExpandableNotificationRow @Mock private lateinit var row: ExpandableNotificationRow
@Mock private lateinit var notifLockscreenUserManager: NotificationLockscreenUserManager
@Mock private lateinit var notifCollection: CommonNotifCollection @Mock private lateinit var notifCollection: CommonNotifCollection
@Mock private lateinit var launcherApps: LauncherApps @Mock private lateinit var launcherApps: LauncherApps
@@ -84,16 +83,13 @@ class IconManagerTest : SysuiTestCase() {
`when`(shortcut.icon).thenReturn(shortcutIc) `when`(shortcut.icon).thenReturn(shortcutIc)
`when`(launcherApps.getShortcutIcon(shortcut)).thenReturn(shortcutIc) `when`(launcherApps.getShortcutIcon(shortcut)).thenReturn(shortcutIc)
`when`(notifLockscreenUserManager.sensitiveNotifsNeedRedactionInPublic(TEST_UID))
.thenReturn(true)
iconManager = iconManager = IconManager(notifCollection, launcherApps, iconBuilder)
IconManager(notifCollection, launcherApps, iconBuilder, notifLockscreenUserManager)
} }
@Test @Test
fun testCreateIcons_importantConversation_shortcutIcon() { fun testCreateIcons_importantConversation_shortcutIcon() {
val entry = notificationEntry() val entry = notificationEntry(true, true, true)
entry?.channel?.isImportantConversation = true entry?.channel?.isImportantConversation = true
entry?.let { entry?.let {
iconManager.createIcons(it) iconManager.createIcons(it)
@@ -103,7 +99,7 @@ class IconManagerTest : SysuiTestCase() {
@Test @Test
fun testCreateIcons_importantConversation_messageIcon() { fun testCreateIcons_importantConversation_messageIcon() {
val entry = notificationEntry(hasShortcut = false) val entry = notificationEntry(false, true, true)
entry?.channel?.isImportantConversation = true entry?.channel?.isImportantConversation = true
entry?.let { entry?.let {
iconManager.createIcons(it) iconManager.createIcons(it)
@@ -113,7 +109,7 @@ class IconManagerTest : SysuiTestCase() {
@Test @Test
fun testCreateIcons_importantConversation_largeIcon() { fun testCreateIcons_importantConversation_largeIcon() {
val entry = notificationEntry(hasShortcut = false, hasMessage = false) val entry = notificationEntry(false, false, true)
entry?.channel?.isImportantConversation = true entry?.channel?.isImportantConversation = true
entry?.let { entry?.let {
iconManager.createIcons(it) iconManager.createIcons(it)
@@ -123,7 +119,7 @@ class IconManagerTest : SysuiTestCase() {
@Test @Test
fun testCreateIcons_importantConversation_smallIcon() { fun testCreateIcons_importantConversation_smallIcon() {
val entry = notificationEntry(hasShortcut = false, hasMessage = false, hasLargeIcon = false) val entry = notificationEntry(false, false, false)
entry?.channel?.isImportantConversation = true entry?.channel?.isImportantConversation = true
entry?.let { entry?.let {
iconManager.createIcons(it) iconManager.createIcons(it)
@@ -133,7 +129,7 @@ class IconManagerTest : SysuiTestCase() {
@Test @Test
fun testCreateIcons_notImportantConversation() { fun testCreateIcons_notImportantConversation() {
val entry = notificationEntry() val entry = notificationEntry(true, true, true)
entry?.let { entry?.let {
iconManager.createIcons(it) iconManager.createIcons(it)
} }
@@ -142,10 +138,8 @@ class IconManagerTest : SysuiTestCase() {
@Test @Test
fun testCreateIcons_sensitiveImportantConversation() { fun testCreateIcons_sensitiveImportantConversation() {
val entry = notificationEntry( val entry = notificationEntry(true, false, false)
hasMessage = false, entry?.setSensitive(true, true);
hasLargeIcon = false,
hasSensitiveContent = true)
entry?.channel?.isImportantConversation = true entry?.channel?.isImportantConversation = true
entry?.let { entry?.let {
iconManager.createIcons(it) iconManager.createIcons(it)
@@ -157,17 +151,14 @@ class IconManagerTest : SysuiTestCase() {
@Test @Test
fun testUpdateIcons_sensitivityChange() { fun testUpdateIcons_sensitivityChange() {
val entry = notificationEntry( val entry = notificationEntry(true, false, false)
hasMessage = false,
hasLargeIcon = false,
hasSensitiveContent = true)
entry?.channel?.isImportantConversation = true entry?.channel?.isImportantConversation = true
entry?.setSensitive(true, true);
entry?.let { entry?.let {
iconManager.createIcons(it) iconManager.createIcons(it)
} }
assertEquals(entry?.icons?.aodIcon?.sourceIcon, smallIc) assertEquals(entry?.icons?.aodIcon?.sourceIcon, smallIc)
`when`(notifLockscreenUserManager.sensitiveNotifsNeedRedactionInPublic(TEST_UID)) entry?.setSensitive(false, false);
.thenReturn(false)
entry?.let { entry?.let {
iconManager.updateIcons(it) iconManager.updateIcons(it)
} }
@@ -175,19 +166,14 @@ class IconManagerTest : SysuiTestCase() {
} }
private fun notificationEntry( private fun notificationEntry(
hasShortcut: Boolean = true, hasShortcut: Boolean,
hasMessage: Boolean = true, hasMessage: Boolean,
hasLargeIcon: Boolean = true, hasLargeIcon: Boolean
hasSensitiveContent: Boolean = false
): NotificationEntry? { ): NotificationEntry? {
val n = Notification.Builder(mContext, "id") val n = Notification.Builder(mContext, "id")
.setSmallIcon(smallIc) .setSmallIcon(smallIc)
.setContentTitle("Title") .setContentTitle("Title")
.setContentText("Text") .setContentText("Text")
.setVisibility(
if (hasSensitiveContent)
Notification.VISIBILITY_PRIVATE
else Notification.VISIBILITY_PUBLIC)
if (hasMessage) { if (hasMessage) {
n.style = Notification.MessagingStyle("") n.style = Notification.MessagingStyle("")
@@ -217,6 +203,7 @@ class IconManagerTest : SysuiTestCase() {
val entry = builder.build() val entry = builder.build()
entry.row = row entry.row = row
entry.setSensitive(false, true);
return entry return entry
} }
} }

View File

@@ -91,7 +91,7 @@ public class ExpandableNotificationRowTest extends SysuiTestCase {
@Test @Test
public void testGroupSummaryNotShowingIconWhenPublic() { public void testGroupSummaryNotShowingIconWhenPublic() {
mGroupRow.setSensitive(true); mGroupRow.setSensitive(true, true);
mGroupRow.setHideSensitiveForIntrinsicHeight(true); mGroupRow.setHideSensitiveForIntrinsicHeight(true);
assertTrue(mGroupRow.isSummaryWithChildren()); assertTrue(mGroupRow.isSummaryWithChildren());
assertFalse(mGroupRow.isShowingIcon()); assertFalse(mGroupRow.isShowingIcon());
@@ -99,7 +99,7 @@ public class ExpandableNotificationRowTest extends SysuiTestCase {
@Test @Test
public void testNotificationHeaderVisibleWhenAnimating() { public void testNotificationHeaderVisibleWhenAnimating() {
mGroupRow.setSensitive(true); mGroupRow.setSensitive(true, true);
mGroupRow.setHideSensitive(true, false, 0, 0); mGroupRow.setHideSensitive(true, false, 0, 0);
mGroupRow.setHideSensitive(false, true, 0, 0); mGroupRow.setHideSensitive(false, true, 0, 0);
assertEquals(View.VISIBLE, mGroupRow.getChildrenContainer().getVisibleWrapper() assertEquals(View.VISIBLE, mGroupRow.getChildrenContainer().getVisibleWrapper()
@@ -130,7 +130,7 @@ public class ExpandableNotificationRowTest extends SysuiTestCase {
public void testIconColorShouldBeUpdatedWhenSensitive() throws Exception { public void testIconColorShouldBeUpdatedWhenSensitive() throws Exception {
ExpandableNotificationRow row = spy(mNotificationTestHelper.createRow( ExpandableNotificationRow row = spy(mNotificationTestHelper.createRow(
FLAG_CONTENT_VIEW_ALL)); FLAG_CONTENT_VIEW_ALL));
row.setSensitive(true); row.setSensitive(true, true);
row.setHideSensitive(true, false, 0, 0); row.setHideSensitive(true, false, 0, 0);
verify(row).updateShelfIconColor(); verify(row).updateShelfIconColor();
} }
@@ -214,7 +214,7 @@ public class ExpandableNotificationRowTest extends SysuiTestCase {
@Test @Test
public void testFeedback_noHeader() { public void testFeedback_noHeader() {
// public notification is custom layout - no header // public notification is custom layout - no header
mGroupRow.setSensitive(true); mGroupRow.setSensitive(true, true);
mGroupRow.setOnFeedbackClickListener(null); mGroupRow.setOnFeedbackClickListener(null);
mGroupRow.setFeedbackIcon(null); mGroupRow.setFeedbackIcon(null);
} }

View File

@@ -78,6 +78,7 @@ import com.android.systemui.statusbar.notification.collection.legacy.Notificatio
import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider; import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider;
import com.android.systemui.statusbar.notification.icon.IconBuilder; import com.android.systemui.statusbar.notification.icon.IconBuilder;
import com.android.systemui.statusbar.notification.icon.IconManager; 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.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier; import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
import com.android.systemui.statusbar.notification.row.dagger.ExpandableNotificationRowComponent; import com.android.systemui.statusbar.notification.row.dagger.ExpandableNotificationRowComponent;
@@ -131,6 +132,7 @@ public class NotificationEntryManagerInflationTest extends SysuiTestCase {
@Mock private NotificationEntryListener mEntryListener; @Mock private NotificationEntryListener mEntryListener;
@Mock private NotificationRowBinderImpl.BindRowCallback mBindCallback; @Mock private NotificationRowBinderImpl.BindRowCallback mBindCallback;
@Mock private HeadsUpManager mHeadsUpManager; @Mock private HeadsUpManager mHeadsUpManager;
@Mock private NotificationInterruptStateProvider mNotificationInterruptionStateProvider;
@Mock private NotificationLockscreenUserManager mLockscreenUserManager; @Mock private NotificationLockscreenUserManager mLockscreenUserManager;
@Mock private NotificationGutsManager mGutsManager; @Mock private NotificationGutsManager mGutsManager;
@Mock private NotificationRemoteInputManager mRemoteInputManager; @Mock private NotificationRemoteInputManager mRemoteInputManager;
@@ -252,7 +254,6 @@ public class NotificationEntryManagerInflationTest extends SysuiTestCase {
.thenAnswer((Answer<ExpandableNotificationRowController>) invocation -> .thenAnswer((Answer<ExpandableNotificationRowController>) invocation ->
new ExpandableNotificationRowController( new ExpandableNotificationRowController(
viewCaptor.getValue(), viewCaptor.getValue(),
mLockscreenUserManager,
mock(ActivatableNotificationViewController.class), mock(ActivatableNotificationViewController.class),
mock(RemoteInputViewSubcomponent.Factory.class), mock(RemoteInputViewSubcomponent.Factory.class),
mock(MetricsLogger.class), mock(MetricsLogger.class),
@@ -299,8 +300,7 @@ public class NotificationEntryManagerInflationTest extends SysuiTestCase {
new IconManager( new IconManager(
mEntryManager, mEntryManager,
mock(LauncherApps.class), mock(LauncherApps.class),
new IconBuilder(mContext), new IconBuilder(mContext)),
mLockscreenUserManager),
mock(LowPriorityInflationHelper.class), mock(LowPriorityInflationHelper.class),
mNotifPipelineFlags); mNotifPipelineFlags);

View File

@@ -55,7 +55,6 @@ import com.android.systemui.dump.DumpManager;
import com.android.systemui.media.MediaFeatureFlag; import com.android.systemui.media.MediaFeatureFlag;
import com.android.systemui.media.dialog.MediaOutputDialogFactory; import com.android.systemui.media.dialog.MediaOutputDialogFactory;
import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationMediaManager; import com.android.systemui.statusbar.NotificationMediaManager;
import com.android.systemui.statusbar.NotificationRemoteInputManager; import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.NotificationShadeWindowController; import com.android.systemui.statusbar.NotificationShadeWindowController;
@@ -157,8 +156,7 @@ public class NotificationTestHelper {
mIconManager = new IconManager( mIconManager = new IconManager(
mock(CommonNotifCollection.class), mock(CommonNotifCollection.class),
mock(LauncherApps.class), mock(LauncherApps.class),
new IconBuilder(mContext), new IconBuilder(mContext));
mock(NotificationLockscreenUserManager.class));
NotificationContentInflater contentBinder = new NotificationContentInflater( NotificationContentInflater contentBinder = new NotificationContentInflater(
mock(NotifRemoteViewCache.class), mock(NotifRemoteViewCache.class),

View File

@@ -36,7 +36,6 @@ import com.android.systemui.plugins.DarkIconDispatcher;
import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.HeadsUpStatusBarView; 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.NotificationWakeUpCoordinator;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.NotificationTestHelper; import com.android.systemui.statusbar.notification.row.NotificationTestHelper;
@@ -58,12 +57,9 @@ public class HeadsUpAppearanceControllerTest extends SysuiTestCase {
private final NotificationStackScrollLayoutController mStackScrollerController = private final NotificationStackScrollLayoutController mStackScrollerController =
mock(NotificationStackScrollLayoutController.class); mock(NotificationStackScrollLayoutController.class);
private final NotificationPanelViewController mPanelViewController = private final NotificationPanelViewController mPanelView =
mock(NotificationPanelViewController.class); mock(NotificationPanelViewController.class);
private final DarkIconDispatcher mDarkIconDispatcher = mock(DarkIconDispatcher.class); private final DarkIconDispatcher mDarkIconDispatcher = mock(DarkIconDispatcher.class);
private final NotificationLockscreenUserManager mLockscreenUserManager =
mock(NotificationLockscreenUserManager.class);
private HeadsUpAppearanceController mHeadsUpAppearanceController; private HeadsUpAppearanceController mHeadsUpAppearanceController;
private ExpandableNotificationRow mFirst; private ExpandableNotificationRow mFirst;
private HeadsUpStatusBarView mHeadsUpStatusBarView; private HeadsUpStatusBarView mHeadsUpStatusBarView;
@@ -97,13 +93,12 @@ public class HeadsUpAppearanceControllerTest extends SysuiTestCase {
mHeadsUpManager, mHeadsUpManager,
mStatusbarStateController, mStatusbarStateController,
mBypassController, mBypassController,
mLockscreenUserManager,
mWakeUpCoordinator, mWakeUpCoordinator,
mDarkIconDispatcher, mDarkIconDispatcher,
mKeyguardStateController, mKeyguardStateController,
mCommandQueue, mCommandQueue,
mStackScrollerController, mStackScrollerController,
mPanelViewController, mPanelView,
mHeadsUpStatusBarView, mHeadsUpStatusBarView,
new Clock(mContext, null), new Clock(mContext, null),
Optional.of(mOperatorNameView)); Optional.of(mOperatorNameView));
@@ -180,13 +175,12 @@ public class HeadsUpAppearanceControllerTest extends SysuiTestCase {
mHeadsUpManager, mHeadsUpManager,
mStatusbarStateController, mStatusbarStateController,
mBypassController, mBypassController,
mLockscreenUserManager,
mWakeUpCoordinator, mWakeUpCoordinator,
mDarkIconDispatcher, mDarkIconDispatcher,
mKeyguardStateController, mKeyguardStateController,
mCommandQueue, mCommandQueue,
mStackScrollerController, mStackScrollerController,
mPanelViewController, mPanelView,
mHeadsUpStatusBarView, mHeadsUpStatusBarView,
new Clock(mContext, null), new Clock(mContext, null),
Optional.empty()); Optional.empty());
@@ -199,15 +193,15 @@ public class HeadsUpAppearanceControllerTest extends SysuiTestCase {
public void testDestroy() { public void testDestroy() {
reset(mHeadsUpManager); reset(mHeadsUpManager);
reset(mDarkIconDispatcher); reset(mDarkIconDispatcher);
reset(mPanelViewController); reset(mPanelView);
reset(mStackScrollerController); reset(mStackScrollerController);
mHeadsUpAppearanceController.onViewDetached(); mHeadsUpAppearanceController.onViewDetached();
verify(mHeadsUpManager).removeListener(any()); verify(mHeadsUpManager).removeListener(any());
verify(mDarkIconDispatcher).removeDarkReceiver((DarkIconDispatcher.DarkReceiver) any()); verify(mDarkIconDispatcher).removeDarkReceiver((DarkIconDispatcher.DarkReceiver) any());
verify(mPanelViewController).removeTrackingHeadsUpListener(any()); verify(mPanelView).removeTrackingHeadsUpListener(any());
verify(mPanelViewController).setHeadsUpAppearanceController(isNull()); verify(mPanelView).setHeadsUpAppearanceController(isNull());
verify(mStackScrollerController).removeOnExpandedHeightChangedListener(any()); verify(mStackScrollerController).removeOnExpandedHeightChangedListener(any());
} }
} }