summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java392
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProvider.kt19
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerMainThreadTest.java597
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java298
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProviderTest.java108
5 files changed, 1232 insertions, 182 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
index 2147510bbde5..f32f1c2dcd25 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
@@ -16,9 +16,16 @@
package com.android.systemui.statusbar;
import static android.app.admin.DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED;
+import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_SECURE_NOTIFICATIONS;
+import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS;
+import static android.os.UserHandle.USER_NULL;
+import static android.provider.Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS;
+import static android.provider.Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS;
import static com.android.systemui.DejankUtils.whitelistIpcs;
+import android.annotation.SuppressLint;
+import android.annotation.UserIdInt;
import android.app.ActivityOptions;
import android.app.KeyguardManager;
import android.app.Notification;
@@ -30,8 +37,10 @@ import android.content.IntentFilter;
import android.content.IntentSender;
import android.content.pm.UserInfo;
import android.database.ContentObserver;
+import android.net.Uri;
import android.os.Handler;
import android.os.HandlerExecutor;
+import android.os.Looper;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
@@ -41,14 +50,18 @@ import android.util.SparseBooleanArray;
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
+import androidx.annotation.WorkerThread;
import com.android.internal.statusbar.NotificationVisibility;
import com.android.internal.widget.LockPatternUtils;
import com.android.systemui.Dumpable;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dump.DumpManager;
+import com.android.systemui.flags.FeatureFlagsClassic;
+import com.android.systemui.flags.Flags;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
import com.android.systemui.recents.OverviewProxyService;
@@ -63,7 +76,9 @@ import com.android.systemui.util.settings.SecureSettings;
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.List;
+import java.util.concurrent.Executor;
import javax.inject.Inject;
@@ -84,6 +99,11 @@ public class NotificationLockscreenUserManagerImpl implements
private final SecureSettings mSecureSettings;
private final Object mLock = new Object();
+ private static final Uri SHOW_LOCKSCREEN =
+ Settings.Secure.getUriFor(LOCK_SCREEN_SHOW_NOTIFICATIONS);
+ private static final Uri SHOW_PRIVATE_LOCKSCREEN =
+ Settings.Secure.getUriFor(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS);
+
private final Lazy<NotificationVisibilityProvider> mVisibilityProviderLazy;
private final Lazy<CommonNotifCollection> mCommonNotifCollectionLazy;
private final DevicePolicyManager mDevicePolicyManager;
@@ -91,6 +111,23 @@ public class NotificationLockscreenUserManagerImpl implements
private final SparseBooleanArray mUsersWithSeparateWorkChallenge = new SparseBooleanArray();
private final SparseBooleanArray mUsersAllowingPrivateNotifications = new SparseBooleanArray();
private final SparseBooleanArray mUsersAllowingNotifications = new SparseBooleanArray();
+
+ // The variables between mUsersDpcAllowingNotifications and
+ // mUsersUsersAllowingPrivateNotifications (inclusive) are written on a background thread
+ // and read on the main thread. Because the pipeline needs these values, adding locks would
+ // introduce too much jank. This means that some pipeline runs could get incorrect values, that
+ // would be fixed on the next pipeline run. We think this will be rare since a pipeline run
+ // would have to overlap with a DPM sync or a user changing a value in Settings, and we run the
+ // pipeline frequently enough that it should be corrected by the next time it matters for the
+ // user.
+ private final SparseBooleanArray mUsersDpcAllowingNotifications = new SparseBooleanArray();
+ private final SparseBooleanArray mUsersUsersAllowingNotifications = new SparseBooleanArray();
+ private boolean mKeyguardAllowingNotifications = true;
+ private final SparseBooleanArray mUsersDpcAllowingPrivateNotifications
+ = new SparseBooleanArray();
+ private final SparseBooleanArray mUsersUsersAllowingPrivateNotifications
+ = new SparseBooleanArray();
+
private final SparseBooleanArray mUsersInLockdownLatestResult = new SparseBooleanArray();
private final SparseBooleanArray mShouldHideNotifsLatestResult = new SparseBooleanArray();
private final UserManager mUserManager;
@@ -99,24 +136,39 @@ public class NotificationLockscreenUserManagerImpl implements
private final BroadcastDispatcher mBroadcastDispatcher;
private final NotificationClickNotifier mClickNotifier;
private final Lazy<OverviewProxyService> mOverviewProxyServiceLazy;
+ private final FeatureFlagsClassic mFeatureFlags;
private boolean mShowLockscreenNotifications;
private LockPatternUtils mLockPatternUtils;
protected KeyguardManager mKeyguardManager;
private int mState = StatusBarState.SHADE;
private final ListenerSet<NotificationStateChangedListener> mNotifStateChangedListeners =
new ListenerSet<>();
+ private final Collection<Uri> mLockScreenUris = new ArrayList<>();
+
protected final BroadcastReceiver mAllUsersReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
- if (ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED.equals(action) &&
- isCurrentProfile(getSendingUserId())) {
- mUsersAllowingPrivateNotifications.clear();
- updateLockscreenNotificationSetting();
- // TODO(b/231976036): Consolidate pipeline invalidations related to this event
- // notifyNotificationStateChanged();
+ if (ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED.equals(action)) {
+ if (mFeatureFlags.isEnabled(Flags.NOTIF_LS_BACKGROUND_THREAD)) {
+ boolean changed = updateDpcSettings(getSendingUserId());
+ if (mCurrentUserId == getSendingUserId()) {
+ changed |= updateLockscreenNotificationSetting();
+ }
+ if (changed) {
+ notifyNotificationStateChanged();
+ }
+ } else {
+ if (isCurrentProfile(getSendingUserId())) {
+ mUsersAllowingPrivateNotifications.clear();
+ updateLockscreenNotificationSetting();
+ // TODO(b/231976036): Consolidate pipeline invalidations related to this
+ // event
+ // notifyNotificationStateChanged();
+ }
+ }
}
}
};
@@ -136,6 +188,14 @@ public class NotificationLockscreenUserManagerImpl implements
updateCurrentProfilesCache();
break;
case Intent.ACTION_USER_ADDED:
+ updateCurrentProfilesCache();
+ if (mFeatureFlags.isEnabled(Flags.NOTIF_LS_BACKGROUND_THREAD)) {
+ final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, USER_NULL);
+ mBackgroundHandler.post(() -> {
+ initValuesForUser(userId);
+ });
+ }
+ break;
case Intent.ACTION_MANAGED_PROFILE_AVAILABLE:
case Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE:
updateCurrentProfilesCache();
@@ -193,6 +253,8 @@ public class NotificationLockscreenUserManagerImpl implements
protected final Context mContext;
private final Handler mMainHandler;
+ private final Handler mBackgroundHandler;
+ private final Executor mBackgroundExecutor;
protected final SparseArray<UserInfo> mCurrentProfiles = new SparseArray<>();
protected final SparseArray<UserInfo> mCurrentManagedProfiles = new SparseArray<>();
@@ -214,13 +276,18 @@ public class NotificationLockscreenUserManagerImpl implements
KeyguardManager keyguardManager,
StatusBarStateController statusBarStateController,
@Main Handler mainHandler,
+ @Background Handler backgroundHandler,
+ @Background Executor backgroundExecutor,
DeviceProvisionedController deviceProvisionedController,
KeyguardStateController keyguardStateController,
SecureSettings secureSettings,
DumpManager dumpManager,
- LockPatternUtils lockPatternUtils) {
+ LockPatternUtils lockPatternUtils,
+ FeatureFlagsClassic featureFlags) {
mContext = context;
mMainHandler = mainHandler;
+ mBackgroundHandler = backgroundHandler;
+ mBackgroundExecutor = backgroundExecutor;
mDevicePolicyManager = devicePolicyManager;
mUserManager = userManager;
mUserTracker = userTracker;
@@ -236,6 +303,10 @@ public class NotificationLockscreenUserManagerImpl implements
mDeviceProvisionedController = deviceProvisionedController;
mSecureSettings = secureSettings;
mKeyguardStateController = keyguardStateController;
+ mFeatureFlags = featureFlags;
+
+ mLockScreenUris.add(SHOW_LOCKSCREEN);
+ mLockScreenUris.add(SHOW_PRIVATE_LOCKSCREEN);
dumpManager.registerDumpable(this);
}
@@ -243,16 +314,53 @@ public class NotificationLockscreenUserManagerImpl implements
public void setUpWithPresenter(NotificationPresenter presenter) {
mPresenter = presenter;
- mLockscreenSettingsObserver = new ContentObserver(mMainHandler) {
+ mLockscreenSettingsObserver = new ContentObserver(
+ mFeatureFlags.isEnabled(Flags.NOTIF_LS_BACKGROUND_THREAD)
+ ? mBackgroundHandler
+ : mMainHandler) {
+
@Override
- public void onChange(boolean selfChange) {
- // We don't know which user changed LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS or
- // LOCK_SCREEN_SHOW_NOTIFICATIONS, so we just dump our cache ...
- mUsersAllowingPrivateNotifications.clear();
- mUsersAllowingNotifications.clear();
- // ... and refresh all the notifications
- updateLockscreenNotificationSetting();
- notifyNotificationStateChanged();
+ public void onChange(boolean selfChange, Collection<Uri> uris, int flags) {
+ if (mFeatureFlags.isEnabled(Flags.NOTIF_LS_BACKGROUND_THREAD)) {
+ @SuppressLint("MissingPermission")
+ List<UserInfo> users = mUserManager.getUsers();
+ for (int i = users.size() - 1; i >= 0; i--) {
+ onChange(selfChange, uris, flags,users.get(i).getUserHandle());
+ }
+ } else {
+ // We don't know which user changed LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS or
+ // LOCK_SCREEN_SHOW_NOTIFICATIONS, so we just dump our cache ...
+ mUsersAllowingPrivateNotifications.clear();
+ mUsersAllowingNotifications.clear();
+ // ... and refresh all the notifications
+ updateLockscreenNotificationSetting();
+ notifyNotificationStateChanged();
+ }
+ }
+
+ // Note: even though this is an override, this method is not called by the OS
+ // since we're not in system_server. We are using it internally for cases when
+ // we have a single user id available (e.g. from USER_ADDED).
+ @Override
+ public void onChange(boolean selfChange, Collection<Uri> uris,
+ int flags, UserHandle user) {
+ if (mFeatureFlags.isEnabled(Flags.NOTIF_LS_BACKGROUND_THREAD)) {
+ boolean changed = false;
+ for (Uri uri: uris) {
+ if (SHOW_LOCKSCREEN.equals(uri)) {
+ changed |= updateUserShowSettings(user.getIdentifier());
+ } else if (SHOW_PRIVATE_LOCKSCREEN.equals(uri)) {
+ changed |= updateUserShowPrivateSettings(user.getIdentifier());
+ }
+ }
+
+ if (mCurrentUserId == user.getIdentifier()) {
+ changed |= updateLockscreenNotificationSetting();
+ }
+ if (changed) {
+ notifyNotificationStateChanged();
+ }
+ }
}
};
@@ -268,23 +376,26 @@ public class NotificationLockscreenUserManagerImpl implements
};
mContext.getContentResolver().registerContentObserver(
- mSecureSettings.getUriFor(Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS), false,
+ SHOW_LOCKSCREEN, false,
mLockscreenSettingsObserver,
UserHandle.USER_ALL);
mContext.getContentResolver().registerContentObserver(
- mSecureSettings.getUriFor(Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS),
+ SHOW_PRIVATE_LOCKSCREEN,
true,
mLockscreenSettingsObserver,
UserHandle.USER_ALL);
- mContext.getContentResolver().registerContentObserver(
- Settings.Global.getUriFor(Settings.Global.ZEN_MODE), false,
- mSettingsObserver);
+ if (!mFeatureFlags.isEnabled(Flags.NOTIF_LS_BACKGROUND_THREAD)) {
+ mContext.getContentResolver().registerContentObserver(
+ Settings.Global.getUriFor(Settings.Global.ZEN_MODE), false,
+ mSettingsObserver);
+ }
mBroadcastDispatcher.registerReceiver(mAllUsersReceiver,
new IntentFilter(ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED),
- null /* handler */, UserHandle.ALL);
+ mFeatureFlags.isEnabled(Flags.NOTIF_LS_BACKGROUND_THREAD)
+ ? mBackgroundExecutor : null, UserHandle.ALL);
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_USER_ADDED);
@@ -305,7 +416,23 @@ public class NotificationLockscreenUserManagerImpl implements
mCurrentUserId = mUserTracker.getUserId(); // in case we reg'd receiver too late
updateCurrentProfilesCache();
- mSettingsObserver.onChange(false); // set up
+ if (mFeatureFlags.isEnabled(Flags.NOTIF_LS_BACKGROUND_THREAD)) {
+ // Set up
+ mBackgroundHandler.post(() -> {
+ @SuppressLint("MissingPermission") List<UserInfo> users = mUserManager.getUsers();
+ for (int i = users.size() - 1; i >= 0; i--) {
+ initValuesForUser(users.get(i).id);
+ }
+ });
+ } else {
+ mSettingsObserver.onChange(false); // set up
+ }
+ }
+
+ private void initValuesForUser(@UserIdInt int userId) {
+ mLockscreenSettingsObserver.onChange(
+ false, mLockScreenUris, 0, UserHandle.of(userId));
+ updateDpcSettings(userId);
}
public boolean shouldShowLockscreenNotifications() {
@@ -322,17 +449,75 @@ public class NotificationLockscreenUserManagerImpl implements
mShowLockscreenNotifications = show;
}
- protected void updateLockscreenNotificationSetting() {
- final boolean show = mSecureSettings.getIntForUser(
- Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS,
- 1,
- mCurrentUserId) != 0;
- final int dpmFlags = mDevicePolicyManager.getKeyguardDisabledFeatures(
- null /* admin */, mCurrentUserId);
- final boolean allowedByDpm = (dpmFlags
- & DevicePolicyManager.KEYGUARD_DISABLE_SECURE_NOTIFICATIONS) == 0;
+ protected boolean updateLockscreenNotificationSetting() {
+ boolean show;
+ boolean allowedByDpm;
+
+ if (mFeatureFlags.isEnabled(Flags.NOTIF_LS_BACKGROUND_THREAD)) {
+ show = mUsersUsersAllowingNotifications.get(mCurrentUserId)
+ && mKeyguardAllowingNotifications;
+ // If DPC never notified us about a user, that means they have no policy for the user,
+ // and they allow the behavior
+ allowedByDpm = mUsersDpcAllowingNotifications.get(mCurrentUserId, true);
+ } else {
+ show = mSecureSettings.getIntForUser(
+ LOCK_SCREEN_SHOW_NOTIFICATIONS,
+ 1,
+ mCurrentUserId) != 0;
+ final int dpmFlags = mDevicePolicyManager.getKeyguardDisabledFeatures(
+ null /* admin */, mCurrentUserId);
+ allowedByDpm = (dpmFlags
+ & KEYGUARD_DISABLE_SECURE_NOTIFICATIONS) == 0;
+ }
+ final boolean oldValue = mShowLockscreenNotifications;
setShowLockscreenNotifications(show && allowedByDpm);
+
+ return oldValue != mShowLockscreenNotifications;
+ }
+
+ @WorkerThread
+ protected boolean updateDpcSettings(int userId) {
+ boolean originalAllowLockscreen = mUsersDpcAllowingNotifications.get(userId);
+ boolean originalAllowPrivate = mUsersDpcAllowingPrivateNotifications.get(userId);
+ final int dpmFlags = mDevicePolicyManager.getKeyguardDisabledFeatures(
+ null /* admin */, userId);
+ final boolean allowedLockscreen = (dpmFlags & KEYGUARD_DISABLE_SECURE_NOTIFICATIONS) == 0;
+ final boolean allowedPrivate = (dpmFlags & KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS) == 0;
+ mUsersDpcAllowingNotifications.put(userId, allowedLockscreen);
+ mUsersDpcAllowingPrivateNotifications.put(userId, allowedPrivate);
+ return (originalAllowLockscreen != allowedLockscreen)
+ || (originalAllowPrivate != allowedPrivate);
+ }
+
+ @WorkerThread
+ private boolean updateUserShowSettings(int userId) {
+ boolean originalAllowLockscreen = mUsersUsersAllowingNotifications.get(userId);
+ boolean newAllowLockscreen = mSecureSettings.getIntForUser(
+ LOCK_SCREEN_SHOW_NOTIFICATIONS,
+ 1,
+ userId) != 0;
+ mUsersUsersAllowingNotifications.put(userId, newAllowLockscreen);
+ boolean keyguardChanged = updateGlobalKeyguardSettings();
+ return (newAllowLockscreen != originalAllowLockscreen) || keyguardChanged;
+ }
+
+ @WorkerThread
+ private boolean updateUserShowPrivateSettings(int userId) {
+ boolean originalValue = mUsersUsersAllowingPrivateNotifications.get(userId);
+ boolean newValue = mSecureSettings.getIntForUser(
+ LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS,
+ 0,
+ userId) != 0;
+ mUsersUsersAllowingPrivateNotifications.put(userId, newValue);
+ return (newValue != originalValue);
+ }
+
+ @WorkerThread
+ private boolean updateGlobalKeyguardSettings() {
+ final boolean oldValue = mKeyguardAllowingNotifications;
+ mKeyguardAllowingNotifications = mKeyguardManager.getPrivateNotificationsAllowed();
+ return oldValue != mKeyguardAllowingNotifications;
}
/**
@@ -340,21 +525,41 @@ public class NotificationLockscreenUserManagerImpl implements
* when the lockscreen is in "public" (secure & locked) mode?
*/
public boolean userAllowsPrivateNotificationsInPublic(int userHandle) {
- if (userHandle == UserHandle.USER_ALL) {
- return true;
- }
+ if (mFeatureFlags.isEnabled(Flags.NOTIF_LS_BACKGROUND_THREAD)) {
+ if (userHandle == UserHandle.USER_ALL) {
+ userHandle = mCurrentUserId;
+ }
+ if (mUsersUsersAllowingPrivateNotifications.indexOfKey(userHandle) < 0) {
+ // TODO(b/301955929): STOP_SHIP (stop flag flip): remove this read and use a safe
+ // default value before moving to 'released'
+ Log.wtf(TAG, "Asking for redact notifs setting too early", new Throwable());
+ updateUserShowPrivateSettings(userHandle);
+ }
+ if (mUsersDpcAllowingPrivateNotifications.indexOfKey(userHandle) < 0) {
+ // TODO(b/301955929): STOP_SHIP (stop flag flip): remove this read and use a safe
+ // default value before moving to 'released'
+ Log.wtf(TAG, "Asking for redact notifs dpm override too early", new Throwable());
+ updateDpcSettings(userHandle);
+ }
+ return mUsersUsersAllowingPrivateNotifications.get(userHandle)
+ && mUsersDpcAllowingPrivateNotifications.get(userHandle);
+ } else {
+ if (userHandle == UserHandle.USER_ALL) {
+ return true;
+ }
- if (mUsersAllowingPrivateNotifications.indexOfKey(userHandle) < 0) {
- final boolean allowedByUser = 0 != mSecureSettings.getIntForUser(
- Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0, userHandle);
- final boolean allowedByDpm = adminAllowsKeyguardFeature(userHandle,
- DevicePolicyManager.KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS);
- final boolean allowed = allowedByUser && allowedByDpm;
- mUsersAllowingPrivateNotifications.append(userHandle, allowed);
- return allowed;
- }
+ if (mUsersAllowingPrivateNotifications.indexOfKey(userHandle) < 0) {
+ final boolean allowedByUser = 0 != mSecureSettings.getIntForUser(
+ LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0, userHandle);
+ final boolean allowedByDpm = adminAllowsKeyguardFeature(userHandle,
+ KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS);
+ final boolean allowed = allowedByUser && allowedByDpm;
+ mUsersAllowingPrivateNotifications.append(userHandle, allowed);
+ return allowed;
+ }
- return mUsersAllowingPrivateNotifications.get(userHandle);
+ return mUsersAllowingPrivateNotifications.get(userHandle);
+ }
}
/**
@@ -406,21 +611,44 @@ public class NotificationLockscreenUserManagerImpl implements
* "public" (secure & locked) mode?
*/
public boolean userAllowsNotificationsInPublic(int userHandle) {
- if (isCurrentProfile(userHandle) && userHandle != mCurrentUserId) {
- return true;
- }
+ if (mFeatureFlags.isEnabled(Flags.NOTIF_LS_BACKGROUND_THREAD)) {
+ // Unlike 'show private', settings does not show a copy of this setting for each
+ // profile, so it inherits from the parent user.
+ if (userHandle == UserHandle.USER_ALL || mCurrentManagedProfiles.contains(userHandle)) {
+ userHandle = mCurrentUserId;
+ }
+ if (mUsersUsersAllowingNotifications.indexOfKey(userHandle) < 0) {
+ // TODO(b/301955929): STOP_SHIP (stop flag flip): remove this read and use a safe
+ // default value before moving to 'released'
+ Log.wtf(TAG, "Asking for show notifs setting too early", new Throwable());
+ updateUserShowSettings(userHandle);
+ }
+ if (mUsersDpcAllowingNotifications.indexOfKey(userHandle) < 0) {
+ // TODO(b/301955929): STOP_SHIP (stop flag flip): remove this read and use a safe
+ // default value before moving to 'released'
+ Log.wtf(TAG, "Asking for show notifs dpm override too early", new Throwable());
+ updateDpcSettings(userHandle);
+ }
+ return mUsersUsersAllowingNotifications.get(userHandle)
+ && mUsersDpcAllowingNotifications.get(userHandle)
+ && mKeyguardAllowingNotifications;
+ } else {
+ if (isCurrentProfile(userHandle) && userHandle != mCurrentUserId) {
+ return true;
+ }
- if (mUsersAllowingNotifications.indexOfKey(userHandle) < 0) {
- final boolean allowedByUser = 0 != mSecureSettings.getIntForUser(
- Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, 0, userHandle);
- final boolean allowedByDpm = adminAllowsKeyguardFeature(userHandle,
- DevicePolicyManager.KEYGUARD_DISABLE_SECURE_NOTIFICATIONS);
- final boolean allowedBySystem = mKeyguardManager.getPrivateNotificationsAllowed();
- final boolean allowed = allowedByUser && allowedByDpm && allowedBySystem;
- mUsersAllowingNotifications.append(userHandle, allowed);
- return allowed;
+ if (mUsersAllowingNotifications.indexOfKey(userHandle) < 0) {
+ final boolean allowedByUser = 0 != mSecureSettings.getIntForUser(
+ LOCK_SCREEN_SHOW_NOTIFICATIONS, 0, userHandle);
+ final boolean allowedByDpm = adminAllowsKeyguardFeature(userHandle,
+ KEYGUARD_DISABLE_SECURE_NOTIFICATIONS);
+ final boolean allowedBySystem = mKeyguardManager.getPrivateNotificationsAllowed();
+ final boolean allowed = allowedByUser && allowedByDpm && allowedBySystem;
+ mUsersAllowingNotifications.append(userHandle, allowed);
+ return allowed;
+ }
+ return mUsersAllowingNotifications.get(userHandle);
}
- return mUsersAllowingNotifications.get(userHandle);
}
/** @return true if the entry needs redaction when on the lockscreen. */
@@ -451,9 +679,15 @@ public class NotificationLockscreenUserManagerImpl implements
return true;
}
NotificationEntry entry = mCommonNotifCollectionLazy.get().getEntry(key);
- return entry != null
- && entry.getRanking().getLockscreenVisibilityOverride()
- == Notification.VISIBILITY_PRIVATE;
+ if (mFeatureFlags.isEnabled(Flags.NOTIF_LS_BACKGROUND_THREAD)) {
+ return entry != null
+ && entry.getRanking().getChannel().getLockscreenVisibility()
+ == Notification.VISIBILITY_PRIVATE;
+ } else {
+ return entry != null
+ && entry.getRanking().getLockscreenVisibilityOverride()
+ == Notification.VISIBILITY_PRIVATE;
+ }
}
private void updateCurrentProfilesCache() {
@@ -491,20 +725,6 @@ public class NotificationLockscreenUserManagerImpl implements
}
/**
- * If any managed/work profiles are in public mode.
- */
- public boolean isAnyManagedProfilePublicMode() {
- synchronized (mLock) {
- for (int i = mCurrentManagedProfiles.size() - 1; i >= 0; i--) {
- if (isLockscreenPublicMode(mCurrentManagedProfiles.valueAt(i).id)) {
- return true;
- }
- }
- }
- return false;
- }
-
- /**
* Returns the current user id. This can change if the user is switched.
*/
public int getCurrentUserId() {
@@ -581,8 +801,16 @@ public class NotificationLockscreenUserManagerImpl implements
}
private void notifyNotificationStateChanged() {
- for (NotificationStateChangedListener listener : mNotifStateChangedListeners) {
- listener.onNotificationStateChanged();
+ if (!Looper.getMainLooper().isCurrentThread()) {
+ mMainHandler.post(() -> {
+ for (NotificationStateChangedListener listener : mNotifStateChangedListeners) {
+ listener.onNotificationStateChanged();
+ }
+ });
+ } else {
+ for (NotificationStateChangedListener listener : mNotifStateChangedListeners) {
+ listener.onNotificationStateChanged();
+ }
}
}
@@ -620,5 +848,15 @@ public class NotificationLockscreenUserManagerImpl implements
pw.println(mUsersInLockdownLatestResult);
pw.print(" mShouldHideNotifsLatestResult=");
pw.println(mShouldHideNotifsLatestResult);
+ pw.print(" mUsersDpcAllowingNotifications=");
+ pw.println(mUsersDpcAllowingNotifications);
+ pw.print(" mUsersUsersAllowingNotifications=");
+ pw.println(mUsersUsersAllowingNotifications);
+ pw.print(" mKeyguardAllowingNotifications=");
+ pw.println(mKeyguardAllowingNotifications);
+ pw.print(" mUsersDpcAllowingPrivateNotifications=");
+ pw.println(mUsersDpcAllowingPrivateNotifications);
+ pw.print(" mUsersUsersAllowingPrivateNotifications=");
+ pw.println(mUsersUsersAllowingPrivateNotifications);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProvider.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProvider.kt
index b2c32cd42d1d..db7f46eb28f2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProvider.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProvider.kt
@@ -1,6 +1,5 @@
package com.android.systemui.statusbar.notification.interruption
-import android.app.Notification
import android.app.Notification.VISIBILITY_SECRET
import android.content.Context
import android.database.ContentObserver
@@ -14,6 +13,8 @@ import com.android.keyguard.KeyguardUpdateMonitorCallback
import com.android.systemui.CoreStartable
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.flags.FeatureFlagsClassic
+import com.android.systemui.flags.Flags
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.settings.UserTracker
import com.android.systemui.statusbar.NotificationLockscreenUserManager
@@ -78,7 +79,8 @@ class KeyguardNotificationVisibilityProviderImpl @Inject constructor(
private val statusBarStateController: SysuiStatusBarStateController,
private val userTracker: UserTracker,
private val secureSettings: SecureSettings,
- private val globalSettings: GlobalSettings
+ private val globalSettings: GlobalSettings,
+ private val featureFlags: FeatureFlagsClassic
) : CoreStartable, KeyguardNotificationVisibilityProvider {
private val showSilentNotifsUri =
secureSettings.getUriFor(Settings.Secure.LOCK_SCREEN_SHOW_SILENT_NOTIFICATIONS)
@@ -201,7 +203,7 @@ class KeyguardNotificationVisibilityProviderImpl @Inject constructor(
// device isn't public, no need to check public-related settings, so allow
!lockscreenUserManager.isLockscreenPublicMode(user) -> false
// entry is meant to be secret on the lockscreen, disallow
- entry.ranking.lockscreenVisibilityOverride == Notification.VISIBILITY_SECRET -> true
+ isRankingVisibilitySecret(entry) -> true
// disallow if user disallows notifications in public
else -> !lockscreenUserManager.userAllowsNotificationsInPublic(user)
}
@@ -215,6 +217,17 @@ class KeyguardNotificationVisibilityProviderImpl @Inject constructor(
}
}
+ private fun isRankingVisibilitySecret(entry: NotificationEntry): Boolean {
+ return if (featureFlags.isEnabled(Flags.NOTIF_LS_BACKGROUND_THREAD)) {
+ // ranking.lockscreenVisibilityOverride contains possibly out of date DPC and Setting
+ // info, and NotificationLockscreenUserManagerImpl is already listening for updates
+ // to those
+ entry.ranking.channel.lockscreenVisibility == VISIBILITY_SECRET
+ } else {
+ entry.ranking.lockscreenVisibilityOverride == VISIBILITY_SECRET
+ }
+ }
+
override fun dump(pw: PrintWriter, args: Array<out String>) = pw.asIndenting().run {
println("isLockedOrLocking=$isLockedOrLocking")
withIncreasedIndent {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerMainThreadTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerMainThreadTest.java
new file mode 100644
index 000000000000..3a9c24a7109c
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerMainThreadTest.java
@@ -0,0 +1,597 @@
+/*
+ * Copyright (C) 2023 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;
+
+import static android.app.admin.DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED;
+import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_SECURE_NOTIFICATIONS;
+import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS;
+import static android.provider.Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS;
+import static android.provider.Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS;
+
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
+
+import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.ActivityManager;
+import android.app.KeyguardManager;
+import android.app.Notification;
+import android.app.admin.DevicePolicyManager;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.UserInfo;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.provider.Settings;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.internal.widget.LockPatternUtils;
+import com.android.systemui.Dependency;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.broadcast.BroadcastDispatcher;
+import com.android.systemui.dump.DumpManager;
+import com.android.systemui.flags.FakeFeatureFlagsClassic;
+import com.android.systemui.flags.Flags;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.recents.OverviewProxyService;
+import com.android.systemui.settings.UserTracker;
+import com.android.systemui.statusbar.NotificationLockscreenUserManager.NotificationStateChangedListener;
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
+import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection;
+import com.android.systemui.statusbar.notification.collection.render.NotificationVisibilityProvider;
+import com.android.systemui.statusbar.policy.DeviceProvisionedController;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
+import com.android.systemui.util.settings.FakeSettings;
+
+import com.google.android.collect.Lists;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.concurrent.Executor;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+public class NotificationLockscreenUserManagerMainThreadTest extends SysuiTestCase {
+ @Mock
+ private NotificationPresenter mPresenter;
+ @Mock
+ private UserManager mUserManager;
+ @Mock
+ private UserTracker mUserTracker;
+
+ // Dependency mocks:
+ @Mock
+ private NotificationVisibilityProvider mVisibilityProvider;
+ @Mock
+ private CommonNotifCollection mNotifCollection;
+ @Mock
+ private DevicePolicyManager mDevicePolicyManager;
+ @Mock
+ private NotificationClickNotifier mClickNotifier;
+ @Mock
+ private OverviewProxyService mOverviewProxyService;
+ @Mock
+ private KeyguardManager mKeyguardManager;
+ @Mock
+ private DeviceProvisionedController mDeviceProvisionedController;
+ @Mock
+ private StatusBarStateController mStatusBarStateController;
+ @Mock
+ private BroadcastDispatcher mBroadcastDispatcher;
+ @Mock
+ private KeyguardStateController mKeyguardStateController;
+
+ private UserInfo mCurrentUser;
+ private UserInfo mSecondaryUser;
+ private UserInfo mWorkUser;
+ private FakeSettings mSettings;
+ private TestNotificationLockscreenUserManager mLockscreenUserManager;
+ private NotificationEntry mCurrentUserNotif;
+ private NotificationEntry mSecondaryUserNotif;
+ private NotificationEntry mWorkProfileNotif;
+ private final FakeFeatureFlagsClassic mFakeFeatureFlags = new FakeFeatureFlagsClassic();
+ private Executor mBackgroundExecutor = Runnable::run; // Direct executor
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ mFakeFeatureFlags.set(Flags.NOTIF_LS_BACKGROUND_THREAD, false);
+
+ int currentUserId = ActivityManager.getCurrentUser();
+ when(mUserTracker.getUserId()).thenReturn(currentUserId);
+ mSettings = new FakeSettings();
+ mSettings.setUserId(ActivityManager.getCurrentUser());
+ mCurrentUser = new UserInfo(currentUserId, "", 0);
+ mSecondaryUser = new UserInfo(currentUserId + 1, "", 0);
+ mWorkUser = new UserInfo(currentUserId + 2, "" /* name */, null /* iconPath */, 0,
+ UserManager.USER_TYPE_PROFILE_MANAGED);
+
+ when(mKeyguardManager.getPrivateNotificationsAllowed()).thenReturn(true);
+ when(mUserManager.getProfiles(currentUserId)).thenReturn(Lists.newArrayList(
+ mCurrentUser, mWorkUser));
+ when(mUserManager.getProfiles(mSecondaryUser.id)).thenReturn(Lists.newArrayList(
+ mSecondaryUser));
+ mDependency.injectTestDependency(Dependency.MAIN_HANDLER,
+ Handler.createAsync(Looper.myLooper()));
+
+ Notification notifWithPrivateVisibility = new Notification();
+ notifWithPrivateVisibility.visibility = Notification.VISIBILITY_PRIVATE;
+ mCurrentUserNotif = new NotificationEntryBuilder()
+ .setNotification(notifWithPrivateVisibility)
+ .setUser(new UserHandle(mCurrentUser.id))
+ .build();
+ mSecondaryUserNotif = new NotificationEntryBuilder()
+ .setNotification(notifWithPrivateVisibility)
+ .setUser(new UserHandle(mSecondaryUser.id))
+ .build();
+ mWorkProfileNotif = new NotificationEntryBuilder()
+ .setNotification(notifWithPrivateVisibility)
+ .setUser(new UserHandle(mWorkUser.id))
+ .build();
+
+ mLockscreenUserManager = new TestNotificationLockscreenUserManager(mContext);
+ mLockscreenUserManager.setUpWithPresenter(mPresenter);
+ }
+
+ private void changeSetting(String setting) {
+ final Collection<Uri> lockScreenUris = new ArrayList<>();
+ lockScreenUris.add(Settings.Secure.getUriFor(setting));
+ mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false,
+ lockScreenUris, 0);
+ }
+
+ @Test
+ public void testLockScreenShowNotificationsFalse() {
+ mSettings.putInt(LOCK_SCREEN_SHOW_NOTIFICATIONS, 0);
+ changeSetting(LOCK_SCREEN_SHOW_NOTIFICATIONS);
+ assertFalse(mLockscreenUserManager.shouldShowLockscreenNotifications());
+ }
+
+ @Test
+ public void testLockScreenShowNotificationsTrue() {
+ mSettings.putInt(LOCK_SCREEN_SHOW_NOTIFICATIONS, 1);
+ changeSetting(LOCK_SCREEN_SHOW_NOTIFICATIONS);
+ assertTrue(mLockscreenUserManager.shouldShowLockscreenNotifications());
+ }
+
+ @Test
+ public void testLockScreenAllowPrivateNotificationsTrue() {
+ mSettings.putInt(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 1);
+ changeSetting(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS);
+ assertTrue(mLockscreenUserManager.userAllowsPrivateNotificationsInPublic(mCurrentUser.id));
+ }
+
+ @Test
+ public void testLockScreenAllowPrivateNotificationsFalse() {
+ mSettings.putIntForUser(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0,
+ mCurrentUser.id);
+ changeSetting(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS);
+ assertFalse(mLockscreenUserManager.userAllowsPrivateNotificationsInPublic(mCurrentUser.id));
+ }
+
+ @Test
+ public void testLockScreenAllowsWorkPrivateNotificationsFalse() {
+ mSettings.putIntForUser(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0,
+ mWorkUser.id);
+ changeSetting(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS);
+ assertFalse(mLockscreenUserManager.userAllowsPrivateNotificationsInPublic(mWorkUser.id));
+ }
+
+ @Test
+ public void testLockScreenAllowsWorkPrivateNotificationsTrue() {
+ mSettings.putIntForUser(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 1,
+ mWorkUser.id);
+ changeSetting(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS);
+ assertTrue(mLockscreenUserManager.userAllowsPrivateNotificationsInPublic(mWorkUser.id));
+ }
+
+ @Test
+ public void testCurrentUserPrivateNotificationsNotRedacted() {
+ // GIVEN current user doesn't allow private notifications to show
+ mSettings.putIntForUser(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0,
+ mCurrentUser.id);
+ changeSetting(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS);
+
+ // THEN current user's notification is redacted
+ assertTrue(mLockscreenUserManager.needsRedaction(mCurrentUserNotif));
+ }
+
+ @Test
+ public void testCurrentUserPrivateNotificationsRedacted() {
+ // GIVEN current user allows private notifications to show
+ mSettings.putIntForUser(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 1,
+ mCurrentUser.id);
+ changeSetting(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS);
+
+ // THEN current user's notification isn't redacted
+ assertFalse(mLockscreenUserManager.needsRedaction(mCurrentUserNotif));
+ }
+
+ @Test
+ public void testWorkPrivateNotificationsRedacted() {
+ // GIVEN work profile doesn't private notifications to show
+ mSettings.putIntForUser(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0,
+ mWorkUser.id);
+ changeSetting(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS);
+
+ // THEN work profile notification is redacted
+ assertTrue(mLockscreenUserManager.needsRedaction(mWorkProfileNotif));
+ assertFalse(mLockscreenUserManager.allowsManagedPrivateNotificationsInPublic());
+ }
+
+ @Test
+ public void testWorkPrivateNotificationsNotRedacted() {
+ // GIVEN work profile allows private notifications to show
+ mSettings.putIntForUser(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 1,
+ mWorkUser.id);
+ changeSetting(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS);
+
+ // THEN work profile notification isn't redacted
+ assertFalse(mLockscreenUserManager.needsRedaction(mWorkProfileNotif));
+ assertTrue(mLockscreenUserManager.allowsManagedPrivateNotificationsInPublic());
+ }
+
+ @Test
+ public void testWorkPrivateNotificationsNotRedacted_otherUsersRedacted() {
+ // GIVEN work profile allows private notifications to show but the other users don't
+ mSettings.putIntForUser(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 1,
+ mWorkUser.id);
+ mSettings.putIntForUser(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0,
+ mCurrentUser.id);
+ mSettings.putIntForUser(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0,
+ mSecondaryUser.id);
+ changeSetting(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS);
+ changeSetting(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS);
+ changeSetting(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS);
+
+ // THEN the work profile notification doesn't need to be redacted
+ assertFalse(mLockscreenUserManager.needsRedaction(mWorkProfileNotif));
+
+ // THEN the current user and secondary user notifications do need to be redacted
+ assertTrue(mLockscreenUserManager.needsRedaction(mCurrentUserNotif));
+ assertTrue(mLockscreenUserManager.needsRedaction(mSecondaryUserNotif));
+ }
+
+ @Test
+ public void testWorkProfileRedacted_otherUsersNotRedacted() {
+ // GIVEN work profile doesn't allow private notifications to show but the other users do
+ mSettings.putIntForUser(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0,
+ mWorkUser.id);
+ mSettings.putIntForUser(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 1,
+ mCurrentUser.id);
+ mSettings.putIntForUser(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 1,
+ mSecondaryUser.id);
+ changeSetting(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS);
+ changeSetting(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS);
+ changeSetting(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS);
+
+ // THEN the work profile notification needs to be redacted
+ assertTrue(mLockscreenUserManager.needsRedaction(mWorkProfileNotif));
+
+ // THEN the current user and secondary user notifications don't need to be redacted
+ assertFalse(mLockscreenUserManager.needsRedaction(mCurrentUserNotif));
+ assertFalse(mLockscreenUserManager.needsRedaction(mSecondaryUserNotif));
+ }
+
+ @Test
+ public void testSecondaryUserNotRedacted_currentUserRedacted() {
+ // GIVEN secondary profile allows private notifications to show but the current user
+ // doesn't allow private notifications to show
+ mSettings.putIntForUser(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0,
+ mCurrentUser.id);
+ mSettings.putIntForUser(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 1,
+ mSecondaryUser.id);
+ changeSetting(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS);
+ changeSetting(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS);
+
+ // THEN the secondary profile notification still needs to be redacted because the current
+ // user's setting takes precedence
+ assertTrue(mLockscreenUserManager.needsRedaction(mSecondaryUserNotif));
+ }
+
+ @Test
+ public void testUserSwitchedCallsOnUserSwitching() {
+ mLockscreenUserManager.getUserTrackerCallbackForTest().onUserChanging(mSecondaryUser.id,
+ mContext);
+ verify(mPresenter, times(1)).onUserSwitched(mSecondaryUser.id);
+ }
+
+ @Test
+ public void testIsLockscreenPublicMode() {
+ assertFalse(mLockscreenUserManager.isLockscreenPublicMode(mCurrentUser.id));
+ mLockscreenUserManager.setLockscreenPublicMode(true, mCurrentUser.id);
+ assertTrue(mLockscreenUserManager.isLockscreenPublicMode(mCurrentUser.id));
+ }
+
+ @Test
+ public void testUpdateIsPublicMode() {
+ when(mKeyguardStateController.isMethodSecure()).thenReturn(true);
+
+ NotificationStateChangedListener listener = mock(NotificationStateChangedListener.class);
+ mLockscreenUserManager.addNotificationStateChangedListener(listener);
+ mLockscreenUserManager.mCurrentProfiles.append(0, mock(UserInfo.class));
+
+ // first call explicitly sets user 0 to not public; notifies
+ mLockscreenUserManager.updatePublicMode();
+ TestableLooper.get(this).processAllMessages();
+ assertFalse(mLockscreenUserManager.isLockscreenPublicMode(0));
+ verify(listener).onNotificationStateChanged();
+ clearInvocations(listener);
+
+ // calling again has no changes; does not notify
+ mLockscreenUserManager.updatePublicMode();
+ TestableLooper.get(this).processAllMessages();
+ assertFalse(mLockscreenUserManager.isLockscreenPublicMode(0));
+ verify(listener, never()).onNotificationStateChanged();
+
+ // Calling again with keyguard now showing makes user 0 public; notifies
+ when(mKeyguardStateController.isShowing()).thenReturn(true);
+ mLockscreenUserManager.updatePublicMode();
+ TestableLooper.get(this).processAllMessages();
+ assertTrue(mLockscreenUserManager.isLockscreenPublicMode(0));
+ verify(listener).onNotificationStateChanged();
+ clearInvocations(listener);
+
+ // calling again has no changes; does not notify
+ mLockscreenUserManager.updatePublicMode();
+ TestableLooper.get(this).processAllMessages();
+ assertTrue(mLockscreenUserManager.isLockscreenPublicMode(0));
+ verify(listener, never()).onNotificationStateChanged();
+ }
+
+ @Test
+ public void testDevicePolicyDoesNotAllowNotifications() {
+ // User allows them
+ mSettings.putIntForUser(LOCK_SCREEN_SHOW_NOTIFICATIONS, 1, mCurrentUser.id);
+ changeSetting(LOCK_SCREEN_SHOW_NOTIFICATIONS);
+
+ // DevicePolicy hides notifs on lockscreen
+ when(mDevicePolicyManager.getKeyguardDisabledFeatures(null, mCurrentUser.id))
+ .thenReturn(KEYGUARD_DISABLE_SECURE_NOTIFICATIONS);
+
+ BroadcastReceiver.PendingResult pr = new BroadcastReceiver.PendingResult(
+ 0, null, null, 0, true, false, null, mCurrentUser.id, 0);
+ mLockscreenUserManager.mAllUsersReceiver.setPendingResult(pr);
+ mLockscreenUserManager.mAllUsersReceiver.onReceive(mContext,
+ new Intent(ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED));
+
+ assertFalse(mLockscreenUserManager.userAllowsNotificationsInPublic(mCurrentUser.id));
+ }
+
+ @Test
+ public void testDevicePolicyDoesNotAllowNotifications_secondary() {
+ Mockito.clearInvocations(mDevicePolicyManager);
+ // User allows notifications
+ mSettings.putIntForUser(LOCK_SCREEN_SHOW_NOTIFICATIONS, 1, mSecondaryUser.id);
+ changeSetting(LOCK_SCREEN_SHOW_NOTIFICATIONS);
+
+ // DevicePolicy hides notifications
+ when(mDevicePolicyManager.getKeyguardDisabledFeatures(null, mSecondaryUser.id))
+ .thenReturn(KEYGUARD_DISABLE_SECURE_NOTIFICATIONS);
+
+ BroadcastReceiver.PendingResult pr = new BroadcastReceiver.PendingResult(
+ 0, null, null, 0, true, false, null, mSecondaryUser.id, 0);
+ mLockscreenUserManager.mAllUsersReceiver.setPendingResult(pr);
+ mLockscreenUserManager.mAllUsersReceiver.onReceive(mContext,
+ new Intent(ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED));
+
+ assertFalse(mLockscreenUserManager.userAllowsNotificationsInPublic(mSecondaryUser.id));
+ }
+
+ @Test
+ public void testDevicePolicy_noPrivateNotifications() {
+ Mockito.clearInvocations(mDevicePolicyManager);
+ // User allows notifications
+ mSettings.putIntForUser(LOCK_SCREEN_SHOW_NOTIFICATIONS, 1, mCurrentUser.id);
+ changeSetting(LOCK_SCREEN_SHOW_NOTIFICATIONS);
+
+ // DevicePolicy hides sensitive content
+ when(mDevicePolicyManager.getKeyguardDisabledFeatures(null, mCurrentUser.id))
+ .thenReturn(KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS);
+
+ BroadcastReceiver.PendingResult pr = new BroadcastReceiver.PendingResult(
+ 0, null, null, 0, true, false, null, mCurrentUser.id, 0);
+ mLockscreenUserManager.mAllUsersReceiver.setPendingResult(pr);
+ mLockscreenUserManager.mAllUsersReceiver.onReceive(mContext,
+ new Intent(ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED));
+
+ assertTrue(mLockscreenUserManager.needsRedaction(mCurrentUserNotif));
+ }
+
+ @Test
+ public void testDevicePolicy_noPrivateNotifications_userAll() {
+ // User allows notifications
+ mSettings.putIntForUser(LOCK_SCREEN_SHOW_NOTIFICATIONS, 1, mCurrentUser.id);
+ changeSetting(LOCK_SCREEN_SHOW_NOTIFICATIONS);
+
+ // DevicePolicy hides sensitive content
+ when(mDevicePolicyManager.getKeyguardDisabledFeatures(null, mCurrentUser.id))
+ .thenReturn(KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS);
+
+ BroadcastReceiver.PendingResult pr = new BroadcastReceiver.PendingResult(
+ 0, null, null, 0, true, false, null, mCurrentUser.id, 0);
+ mLockscreenUserManager.mAllUsersReceiver.setPendingResult(pr);
+ mLockscreenUserManager.mAllUsersReceiver.onReceive(mContext,
+ new Intent(ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED));
+
+ assertTrue(mLockscreenUserManager.needsRedaction(new NotificationEntryBuilder()
+ .setNotification(new Notification())
+ .setUser(UserHandle.ALL)
+ .build()));
+ }
+
+ @Test
+ public void testDevicePolicyPrivateNotifications_secondary() {
+ Mockito.clearInvocations(mDevicePolicyManager);
+ // User allows notifications
+ mSettings.putIntForUser(LOCK_SCREEN_SHOW_NOTIFICATIONS, 1, mSecondaryUser.id);
+ changeSetting(LOCK_SCREEN_SHOW_NOTIFICATIONS);
+
+ // DevicePolicy hides sensitive content
+ when(mDevicePolicyManager.getKeyguardDisabledFeatures(null, mSecondaryUser.id))
+ .thenReturn(KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS);
+
+ BroadcastReceiver.PendingResult pr = new BroadcastReceiver.PendingResult(
+ 0, null, null, 0, true, false, null, mSecondaryUser.id, 0);
+ mLockscreenUserManager.mAllUsersReceiver.setPendingResult(pr);
+ mLockscreenUserManager.mAllUsersReceiver.onReceive(mContext,
+ new Intent(ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED));
+
+ mLockscreenUserManager.mUserChangedCallback.onUserChanging(mSecondaryUser.id, mContext);
+ assertTrue(mLockscreenUserManager.needsRedaction(mSecondaryUserNotif));
+ }
+
+ @Test
+ public void testHideNotifications_primary() {
+ mSettings.putIntForUser(LOCK_SCREEN_SHOW_NOTIFICATIONS, 0, mCurrentUser.id);
+ changeSetting(LOCK_SCREEN_SHOW_NOTIFICATIONS);
+
+ assertFalse(mLockscreenUserManager.userAllowsNotificationsInPublic(mCurrentUser.id));
+ }
+
+ @Test
+ public void testHideNotifications_secondary() {
+ mSettings.putIntForUser(LOCK_SCREEN_SHOW_NOTIFICATIONS, 0, mSecondaryUser.id);
+ changeSetting(LOCK_SCREEN_SHOW_NOTIFICATIONS);
+
+ assertFalse(mLockscreenUserManager.userAllowsNotificationsInPublic(mSecondaryUser.id));
+ }
+
+ @Test
+ public void testHideNotifications_secondary_userSwitch() {
+ mSettings.putIntForUser(LOCK_SCREEN_SHOW_NOTIFICATIONS, 0, mSecondaryUser.id);
+ changeSetting(LOCK_SCREEN_SHOW_NOTIFICATIONS);
+
+ mLockscreenUserManager.mUserChangedCallback.onUserChanging(mSecondaryUser.id, mContext);
+
+ assertFalse(mLockscreenUserManager.userAllowsNotificationsInPublic(mSecondaryUser.id));
+ }
+
+ @Test
+ public void testShowNotifications_secondary_userSwitch() {
+ mSettings.putIntForUser(LOCK_SCREEN_SHOW_NOTIFICATIONS, 1, mSecondaryUser.id);
+ changeSetting(LOCK_SCREEN_SHOW_NOTIFICATIONS);
+
+ mLockscreenUserManager.mUserChangedCallback.onUserChanging(mSecondaryUser.id, mContext);
+
+ assertTrue(mLockscreenUserManager.userAllowsNotificationsInPublic(mSecondaryUser.id));
+ }
+
+ @Test
+ public void testUserAllowsNotificationsInPublic_keyguardManagerNoPrivateNotifications() {
+ // DevicePolicy allows notifications
+ when(mDevicePolicyManager.getKeyguardDisabledFeatures(null, mCurrentUser.id))
+ .thenReturn(0);
+ BroadcastReceiver.PendingResult pr = new BroadcastReceiver.PendingResult(
+ 0, null, null, 0, true, false, null, mCurrentUser.id, 0);
+ mLockscreenUserManager.mAllUsersReceiver.setPendingResult(pr);
+ mLockscreenUserManager.mAllUsersReceiver.onReceive(mContext,
+ new Intent(ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED));
+
+ // KeyguardManager does not allow notifications
+ when(mKeyguardManager.getPrivateNotificationsAllowed()).thenReturn(false);
+
+ // User allows notifications
+ mSettings.putIntForUser(LOCK_SCREEN_SHOW_NOTIFICATIONS, 1, mCurrentUser.id);
+ // We shouldn't need to call this method, but getPrivateNotificationsAllowed has no
+ // callback, so it's only updated when the setting is
+ changeSetting(LOCK_SCREEN_SHOW_NOTIFICATIONS);
+
+ assertFalse(mLockscreenUserManager.userAllowsNotificationsInPublic(mCurrentUser.id));
+ }
+
+ @Test
+ public void testUserAllowsNotificationsInPublic_settingsChange() {
+ // User allows notifications
+ mSettings.putIntForUser(LOCK_SCREEN_SHOW_NOTIFICATIONS, 1, mCurrentUser.id);
+ changeSetting(LOCK_SCREEN_SHOW_NOTIFICATIONS);
+
+ assertTrue(mLockscreenUserManager.userAllowsNotificationsInPublic(mCurrentUser.id));
+
+ // User disables
+ mSettings.putIntForUser(LOCK_SCREEN_SHOW_NOTIFICATIONS, 0, mCurrentUser.id);
+ changeSetting(LOCK_SCREEN_SHOW_NOTIFICATIONS);
+
+ assertFalse(mLockscreenUserManager.userAllowsNotificationsInPublic(mCurrentUser.id));
+ }
+
+ private class TestNotificationLockscreenUserManager
+ extends NotificationLockscreenUserManagerImpl {
+ public TestNotificationLockscreenUserManager(Context context) {
+ super(
+ context,
+ mBroadcastDispatcher,
+ mDevicePolicyManager,
+ mUserManager,
+ mUserTracker,
+ (() -> mVisibilityProvider),
+ (() -> mNotifCollection),
+ mClickNotifier,
+ (() -> mOverviewProxyService),
+ NotificationLockscreenUserManagerMainThreadTest.this.mKeyguardManager,
+ mStatusBarStateController,
+ Handler.createAsync(Looper.myLooper()),
+ Handler.createAsync(Looper.myLooper()),
+ mBackgroundExecutor,
+ mDeviceProvisionedController,
+ mKeyguardStateController,
+ mSettings,
+ mock(DumpManager.class),
+ mock(LockPatternUtils.class),
+ mFakeFeatureFlags);
+ }
+
+ public BroadcastReceiver getBaseBroadcastReceiverForTest() {
+ return mBaseBroadcastReceiver;
+ }
+
+ public UserTracker.Callback getUserTrackerCallbackForTest() {
+ return mUserChangedCallback;
+ }
+
+ public ContentObserver getLockscreenSettingsObserverForTest() {
+ return mLockscreenSettingsObserver;
+ }
+
+ public ContentObserver getSettingsObserverForTest() {
+ return mSettingsObserver;
+ }
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java
index 19863ecaf723..a5f5fc7e36f2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java
@@ -16,17 +16,23 @@
package com.android.systemui.statusbar;
+import static android.app.Notification.VISIBILITY_PRIVATE;
+import static android.app.NotificationManager.IMPORTANCE_HIGH;
+import static android.app.NotificationManager.VISIBILITY_NO_OVERRIDE;
import static android.app.admin.DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED;
import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_SECURE_NOTIFICATIONS;
import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS;
import static android.os.UserHandle.USER_ALL;
+import static android.provider.Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS;
import static android.provider.Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS;
import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.atMost;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.mock;
@@ -38,12 +44,15 @@ import static org.mockito.Mockito.when;
import android.app.ActivityManager;
import android.app.KeyguardManager;
import android.app.Notification;
+import android.app.NotificationChannel;
import android.app.admin.DevicePolicyManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.UserInfo;
import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.UserHandle;
@@ -59,6 +68,8 @@ import com.android.systemui.Dependency;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dump.DumpManager;
+import com.android.systemui.flags.FakeFeatureFlagsClassic;
+import com.android.systemui.flags.Flags;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.recents.OverviewProxyService;
import com.android.systemui.settings.UserTracker;
@@ -74,12 +85,16 @@ import com.android.systemui.util.settings.FakeSettings;
import com.google.android.collect.Lists;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
+import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.concurrent.Executor;
+
@SmallTest
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
@@ -121,11 +136,15 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase {
private NotificationEntry mCurrentUserNotif;
private NotificationEntry mSecondaryUserNotif;
private NotificationEntry mWorkProfileNotif;
+ private final FakeFeatureFlagsClassic mFakeFeatureFlags = new FakeFeatureFlagsClassic();
+ private Executor mBackgroundExecutor = Runnable::run; // Direct executor
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
+ mFakeFeatureFlags.set(Flags.NOTIF_LS_BACKGROUND_THREAD, true);
+
int currentUserId = ActivityManager.getCurrentUser();
when(mUserTracker.getUserId()).thenReturn(currentUserId);
mSettings = new FakeSettings();
@@ -138,103 +157,144 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase {
when(mKeyguardManager.getPrivateNotificationsAllowed()).thenReturn(true);
when(mUserManager.getProfiles(currentUserId)).thenReturn(Lists.newArrayList(
mCurrentUser, mWorkUser));
+ when(mUserManager.getUsers()).thenReturn(Lists.newArrayList(
+ mCurrentUser, mWorkUser, mSecondaryUser));
when(mUserManager.getProfiles(mSecondaryUser.id)).thenReturn(Lists.newArrayList(
mSecondaryUser));
mDependency.injectTestDependency(Dependency.MAIN_HANDLER,
Handler.createAsync(Looper.myLooper()));
Notification notifWithPrivateVisibility = new Notification();
- notifWithPrivateVisibility.visibility = Notification.VISIBILITY_PRIVATE;
+ notifWithPrivateVisibility.visibility = VISIBILITY_PRIVATE;
mCurrentUserNotif = new NotificationEntryBuilder()
.setNotification(notifWithPrivateVisibility)
.setUser(new UserHandle(mCurrentUser.id))
.build();
+ NotificationChannel channel = new NotificationChannel("1", "1", IMPORTANCE_HIGH);
+ channel.setLockscreenVisibility(VISIBILITY_NO_OVERRIDE);
+ mCurrentUserNotif.setRanking(new RankingBuilder(mCurrentUserNotif.getRanking())
+ .setChannel(channel)
+ .setVisibilityOverride(VISIBILITY_NO_OVERRIDE).build());
+ when(mNotifCollection.getEntry(mCurrentUserNotif.getKey())).thenReturn(mCurrentUserNotif);
mSecondaryUserNotif = new NotificationEntryBuilder()
.setNotification(notifWithPrivateVisibility)
.setUser(new UserHandle(mSecondaryUser.id))
.build();
+ mSecondaryUserNotif.setRanking(new RankingBuilder(mSecondaryUserNotif.getRanking())
+ .setChannel(channel)
+ .setVisibilityOverride(VISIBILITY_NO_OVERRIDE).build());
+ when(mNotifCollection.getEntry(
+ mSecondaryUserNotif.getKey())).thenReturn(mSecondaryUserNotif);
mWorkProfileNotif = new NotificationEntryBuilder()
.setNotification(notifWithPrivateVisibility)
.setUser(new UserHandle(mWorkUser.id))
.build();
+ mWorkProfileNotif.setRanking(new RankingBuilder(mWorkProfileNotif.getRanking())
+ .setChannel(channel)
+ .setVisibilityOverride(VISIBILITY_NO_OVERRIDE).build());
+ when(mNotifCollection.getEntry(mWorkProfileNotif.getKey())).thenReturn(mWorkProfileNotif);
mLockscreenUserManager = new TestNotificationLockscreenUserManager(mContext);
mLockscreenUserManager.setUpWithPresenter(mPresenter);
}
+ private void changeSetting(String setting) {
+ final Collection<Uri> lockScreenUris = new ArrayList<>();
+ lockScreenUris.add(Settings.Secure.getUriFor(setting));
+ mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false,
+ lockScreenUris, 0);
+ }
+
@Test
public void testLockScreenShowNotificationsFalse() {
mSettings.putInt(LOCK_SCREEN_SHOW_NOTIFICATIONS, 0);
- mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false);
+ changeSetting(LOCK_SCREEN_SHOW_NOTIFICATIONS);
assertFalse(mLockscreenUserManager.shouldShowLockscreenNotifications());
}
@Test
public void testLockScreenShowNotificationsTrue() {
mSettings.putInt(LOCK_SCREEN_SHOW_NOTIFICATIONS, 1);
- mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false);
+ changeSetting(LOCK_SCREEN_SHOW_NOTIFICATIONS);
assertTrue(mLockscreenUserManager.shouldShowLockscreenNotifications());
}
@Test
public void testLockScreenAllowPrivateNotificationsTrue() {
- mSettings.putInt(Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 1);
- mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false);
+ mSettings.putInt(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 1);
+ changeSetting(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS);
assertTrue(mLockscreenUserManager.userAllowsPrivateNotificationsInPublic(mCurrentUser.id));
}
@Test
public void testLockScreenAllowPrivateNotificationsFalse() {
- mSettings.putIntForUser(Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0,
+ mSettings.putIntForUser(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0,
mCurrentUser.id);
- mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false);
+ changeSetting(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS);
assertFalse(mLockscreenUserManager.userAllowsPrivateNotificationsInPublic(mCurrentUser.id));
}
@Test
public void testLockScreenAllowsWorkPrivateNotificationsFalse() {
- mSettings.putIntForUser(Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0,
+ mSettings.putIntForUser(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0,
mWorkUser.id);
- mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false);
+ changeSetting(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS);
assertFalse(mLockscreenUserManager.userAllowsPrivateNotificationsInPublic(mWorkUser.id));
}
@Test
public void testLockScreenAllowsWorkPrivateNotificationsTrue() {
- mSettings.putIntForUser(Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 1,
+ mSettings.putIntForUser(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 1,
mWorkUser.id);
- mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false);
+ changeSetting(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS);
assertTrue(mLockscreenUserManager.userAllowsPrivateNotificationsInPublic(mWorkUser.id));
}
@Test
- public void testCurrentUserPrivateNotificationsNotRedacted() {
+ public void testCurrentUserPrivateNotificationsRedacted() {
// GIVEN current user doesn't allow private notifications to show
- mSettings.putIntForUser(Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0,
+ mSettings.putIntForUser(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0,
mCurrentUser.id);
- mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false);
+ changeSetting(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS);
// THEN current user's notification is redacted
assertTrue(mLockscreenUserManager.needsRedaction(mCurrentUserNotif));
}
@Test
- public void testCurrentUserPrivateNotificationsRedacted() {
+ public void testCurrentUserPrivateNotificationsNotRedacted() {
// GIVEN current user allows private notifications to show
- mSettings.putIntForUser(Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 1,
+ mSettings.putIntForUser(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 1,
mCurrentUser.id);
- mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false);
+ changeSetting(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS);
// THEN current user's notification isn't redacted
assertFalse(mLockscreenUserManager.needsRedaction(mCurrentUserNotif));
}
@Test
+ public void testCurrentUserPrivateNotificationsRedactedChannel() {
+ // GIVEN current user allows private notifications to show
+ mSettings.putIntForUser(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 1,
+ mCurrentUser.id);
+ changeSetting(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS);
+
+ // but doesn't allow it at the channel level
+ NotificationChannel channel = new NotificationChannel("1", "1", IMPORTANCE_HIGH);
+ channel.setLockscreenVisibility(VISIBILITY_PRIVATE);
+ mCurrentUserNotif.setRanking(new RankingBuilder(mCurrentUserNotif.getRanking())
+ .setChannel(channel)
+ .setVisibilityOverride(VISIBILITY_NO_OVERRIDE).build());
+ // THEN the notification is redacted
+ assertTrue(mLockscreenUserManager.needsRedaction(mCurrentUserNotif));
+ }
+
+ @Test
public void testWorkPrivateNotificationsRedacted() {
// GIVEN work profile doesn't private notifications to show
- mSettings.putIntForUser(Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0,
+ mSettings.putIntForUser(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0,
mWorkUser.id);
- mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false);
+ changeSetting(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS);
// THEN work profile notification is redacted
assertTrue(mLockscreenUserManager.needsRedaction(mWorkProfileNotif));
@@ -244,9 +304,9 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase {
@Test
public void testWorkPrivateNotificationsNotRedacted() {
// GIVEN work profile allows private notifications to show
- mSettings.putIntForUser(Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 1,
+ mSettings.putIntForUser(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 1,
mWorkUser.id);
- mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false);
+ changeSetting(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS);
// THEN work profile notification isn't redacted
assertFalse(mLockscreenUserManager.needsRedaction(mWorkProfileNotif));
@@ -256,13 +316,15 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase {
@Test
public void testWorkPrivateNotificationsNotRedacted_otherUsersRedacted() {
// GIVEN work profile allows private notifications to show but the other users don't
- mSettings.putIntForUser(Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 1,
+ mSettings.putIntForUser(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 1,
mWorkUser.id);
- mSettings.putIntForUser(Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0,
+ mSettings.putIntForUser(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0,
mCurrentUser.id);
- mSettings.putIntForUser(Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0,
+ mSettings.putIntForUser(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0,
mSecondaryUser.id);
- mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false);
+ changeSetting(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS);
+ changeSetting(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS);
+ changeSetting(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS);
// THEN the work profile notification doesn't need to be redacted
assertFalse(mLockscreenUserManager.needsRedaction(mWorkProfileNotif));
@@ -275,13 +337,15 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase {
@Test
public void testWorkProfileRedacted_otherUsersNotRedacted() {
// GIVEN work profile doesn't allow private notifications to show but the other users do
- mSettings.putIntForUser(Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0,
+ mSettings.putIntForUser(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0,
mWorkUser.id);
- mSettings.putIntForUser(Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 1,
+ mSettings.putIntForUser(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 1,
mCurrentUser.id);
- mSettings.putIntForUser(Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 1,
+ mSettings.putIntForUser(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 1,
mSecondaryUser.id);
- mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false);
+ changeSetting(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS);
+ changeSetting(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS);
+ changeSetting(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS);
// THEN the work profile notification needs to be redacted
assertTrue(mLockscreenUserManager.needsRedaction(mWorkProfileNotif));
@@ -295,11 +359,12 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase {
public void testSecondaryUserNotRedacted_currentUserRedacted() {
// GIVEN secondary profile allows private notifications to show but the current user
// doesn't allow private notifications to show
- mSettings.putIntForUser(Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0,
+ mSettings.putIntForUser(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0,
mCurrentUser.id);
- mSettings.putIntForUser(Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 1,
+ mSettings.putIntForUser(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 1,
mSecondaryUser.id);
- mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false);
+ changeSetting(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS);
+ changeSetting(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS);
// THEN the secondary profile notification still needs to be redacted because the current
// user's setting takes precedence
@@ -323,6 +388,7 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase {
@Test
public void testUpdateIsPublicMode() {
when(mKeyguardStateController.isMethodSecure()).thenReturn(true);
+ when(mKeyguardStateController.isShowing()).thenReturn(false);
NotificationStateChangedListener listener = mock(NotificationStateChangedListener.class);
mLockscreenUserManager.addNotificationStateChangedListener(listener);
@@ -330,24 +396,28 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase {
// first call explicitly sets user 0 to not public; notifies
mLockscreenUserManager.updatePublicMode();
+ TestableLooper.get(this).processAllMessages();
assertFalse(mLockscreenUserManager.isLockscreenPublicMode(0));
verify(listener).onNotificationStateChanged();
clearInvocations(listener);
// calling again has no changes; does not notify
mLockscreenUserManager.updatePublicMode();
+ TestableLooper.get(this).processAllMessages();
assertFalse(mLockscreenUserManager.isLockscreenPublicMode(0));
verify(listener, never()).onNotificationStateChanged();
// Calling again with keyguard now showing makes user 0 public; notifies
when(mKeyguardStateController.isShowing()).thenReturn(true);
mLockscreenUserManager.updatePublicMode();
+ TestableLooper.get(this).processAllMessages();
assertTrue(mLockscreenUserManager.isLockscreenPublicMode(0));
verify(listener).onNotificationStateChanged();
clearInvocations(listener);
// calling again has no changes; does not notify
mLockscreenUserManager.updatePublicMode();
+ TestableLooper.get(this).processAllMessages();
assertTrue(mLockscreenUserManager.isLockscreenPublicMode(0));
verify(listener, never()).onNotificationStateChanged();
}
@@ -356,14 +426,14 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase {
public void testDevicePolicyDoesNotAllowNotifications() {
// User allows them
mSettings.putIntForUser(LOCK_SCREEN_SHOW_NOTIFICATIONS, 1, mCurrentUser.id);
- mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false);
+ changeSetting(LOCK_SCREEN_SHOW_NOTIFICATIONS);
// DevicePolicy hides notifs on lockscreen
when(mDevicePolicyManager.getKeyguardDisabledFeatures(null, mCurrentUser.id))
.thenReturn(KEYGUARD_DISABLE_SECURE_NOTIFICATIONS);
- BroadcastReceiver.PendingResult pr = mock(BroadcastReceiver.PendingResult.class);
- when(pr.getSendingUserId()).thenReturn(mCurrentUser.id);
+ BroadcastReceiver.PendingResult pr = new BroadcastReceiver.PendingResult(
+ 0, null, null, 0, true, false, null, mCurrentUser.id, 0);
mLockscreenUserManager.mAllUsersReceiver.setPendingResult(pr);
mLockscreenUserManager.mAllUsersReceiver.onReceive(mContext,
new Intent(ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED));
@@ -371,19 +441,18 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase {
assertFalse(mLockscreenUserManager.userAllowsNotificationsInPublic(mCurrentUser.id));
}
- @Ignore("b/286230167")
@Test
public void testDevicePolicyDoesNotAllowNotifications_userAll() {
// User allows them
mSettings.putIntForUser(LOCK_SCREEN_SHOW_NOTIFICATIONS, 1, mCurrentUser.id);
- mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false);
+ changeSetting(LOCK_SCREEN_SHOW_NOTIFICATIONS);
// DevicePolicy hides notifications
when(mDevicePolicyManager.getKeyguardDisabledFeatures(null, mCurrentUser.id))
.thenReturn(KEYGUARD_DISABLE_SECURE_NOTIFICATIONS);
- BroadcastReceiver.PendingResult pr = mock(BroadcastReceiver.PendingResult.class);
- when(pr.getSendingUserId()).thenReturn(mCurrentUser.id);
+ BroadcastReceiver.PendingResult pr = new BroadcastReceiver.PendingResult(
+ 0, null, null, 0, true, false, null, mCurrentUser.id, 0);
mLockscreenUserManager.mAllUsersReceiver.setPendingResult(pr);
mLockscreenUserManager.mAllUsersReceiver.onReceive(mContext,
new Intent(ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED));
@@ -392,98 +461,105 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase {
}
@Test
- @Ignore("b/286230167")
public void testDevicePolicyDoesNotAllowNotifications_secondary() {
+ Mockito.clearInvocations(mDevicePolicyManager);
// User allows notifications
mSettings.putIntForUser(LOCK_SCREEN_SHOW_NOTIFICATIONS, 1, mSecondaryUser.id);
- mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false);
+ changeSetting(LOCK_SCREEN_SHOW_NOTIFICATIONS);
// DevicePolicy hides notifications
when(mDevicePolicyManager.getKeyguardDisabledFeatures(null, mSecondaryUser.id))
.thenReturn(KEYGUARD_DISABLE_SECURE_NOTIFICATIONS);
- BroadcastReceiver.PendingResult pr = mock(BroadcastReceiver.PendingResult.class);
- when(pr.getSendingUserId()).thenReturn(mSecondaryUser.id);
+ BroadcastReceiver.PendingResult pr = new BroadcastReceiver.PendingResult(
+ 0, null, null, 0, true, false, null, mSecondaryUser.id, 0);
mLockscreenUserManager.mAllUsersReceiver.setPendingResult(pr);
mLockscreenUserManager.mAllUsersReceiver.onReceive(mContext,
new Intent(ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED));
assertFalse(mLockscreenUserManager.userAllowsNotificationsInPublic(mSecondaryUser.id));
- // TODO (b/286230167): enable assertion
verify(mDevicePolicyManager, atMost(1)).getKeyguardDisabledFeatures(any(), anyInt());
}
@Test
public void testDevicePolicy_noPrivateNotifications() {
+ Mockito.clearInvocations(mDevicePolicyManager);
// User allows notifications
mSettings.putIntForUser(LOCK_SCREEN_SHOW_NOTIFICATIONS, 1, mCurrentUser.id);
- mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false);
+ changeSetting(LOCK_SCREEN_SHOW_NOTIFICATIONS);
// DevicePolicy hides sensitive content
when(mDevicePolicyManager.getKeyguardDisabledFeatures(null, mCurrentUser.id))
.thenReturn(KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS);
- BroadcastReceiver.PendingResult pr = mock(BroadcastReceiver.PendingResult.class);
- when(pr.getSendingUserId()).thenReturn(mCurrentUser.id);
+ BroadcastReceiver.PendingResult pr = new BroadcastReceiver.PendingResult(
+ 0, null, null, 0, true, false, null, mCurrentUser.id, 0);
mLockscreenUserManager.mAllUsersReceiver.setPendingResult(pr);
mLockscreenUserManager.mAllUsersReceiver.onReceive(mContext,
new Intent(ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED));
assertTrue(mLockscreenUserManager.needsRedaction(mCurrentUserNotif));
- // TODO (b/286230167): enable assertion. It's currently called 4 times.
- //verify(mDevicePolicyManager, atMost(1)).getKeyguardDisabledFeatures(any(), anyInt());
+ verify(mDevicePolicyManager, atMost(1)).getKeyguardDisabledFeatures(any(), anyInt());
}
@Test
public void testDevicePolicy_noPrivateNotifications_userAll() {
+ NotificationChannel channel = new NotificationChannel("1", "1", IMPORTANCE_HIGH);
+ channel.setLockscreenVisibility(VISIBILITY_NO_OVERRIDE);
+ NotificationEntry notifEntry = new NotificationEntryBuilder()
+ .setNotification(new Notification())
+ .setUser(UserHandle.ALL)
+ .build();
+ notifEntry.setRanking(new RankingBuilder(notifEntry.getRanking())
+ .setChannel(channel)
+ .setVisibilityOverride(VISIBILITY_NO_OVERRIDE).build());
+ when(mNotifCollection.getEntry(notifEntry.getKey())).thenReturn(notifEntry);
// User allows notifications
mSettings.putIntForUser(LOCK_SCREEN_SHOW_NOTIFICATIONS, 1, mCurrentUser.id);
- mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false);
+ changeSetting(LOCK_SCREEN_SHOW_NOTIFICATIONS);
// DevicePolicy hides sensitive content
when(mDevicePolicyManager.getKeyguardDisabledFeatures(null, mCurrentUser.id))
.thenReturn(KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS);
- BroadcastReceiver.PendingResult pr = mock(BroadcastReceiver.PendingResult.class);
- when(pr.getSendingUserId()).thenReturn(mCurrentUser.id);
+ BroadcastReceiver.PendingResult pr = new BroadcastReceiver.PendingResult(
+ 0, null, null, 0, true, false, null, mCurrentUser.id, 0);
mLockscreenUserManager.mAllUsersReceiver.setPendingResult(pr);
mLockscreenUserManager.mAllUsersReceiver.onReceive(mContext,
new Intent(ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED));
- assertTrue(mLockscreenUserManager.needsRedaction(new NotificationEntryBuilder()
- .setNotification(new Notification())
- .setUser(UserHandle.ALL)
- .build()));
+ assertTrue(mLockscreenUserManager.needsRedaction(notifEntry));
}
@Test
public void testDevicePolicyPrivateNotifications_secondary() {
+ Mockito.clearInvocations(mDevicePolicyManager);
// User allows notifications
mSettings.putIntForUser(LOCK_SCREEN_SHOW_NOTIFICATIONS, 1, mSecondaryUser.id);
- mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false);
+ changeSetting(LOCK_SCREEN_SHOW_NOTIFICATIONS);
// DevicePolicy hides sensitive content
when(mDevicePolicyManager.getKeyguardDisabledFeatures(null, mSecondaryUser.id))
.thenReturn(KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS);
- BroadcastReceiver.PendingResult pr = mock(BroadcastReceiver.PendingResult.class);
- when(pr.getSendingUserId()).thenReturn(mSecondaryUser.id);
+ BroadcastReceiver.PendingResult pr = new BroadcastReceiver.PendingResult(
+ 0, null, null, 0, true, false, null, mSecondaryUser.id, 0);
mLockscreenUserManager.mAllUsersReceiver.setPendingResult(pr);
mLockscreenUserManager.mAllUsersReceiver.onReceive(mContext,
new Intent(ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED));
+ mLockscreenUserManager.mUserChangedCallback.onUserChanging(mSecondaryUser.id, mContext);
assertTrue(mLockscreenUserManager.needsRedaction(mSecondaryUserNotif));
- // TODO (b/286230167): enable assertion. It's currently called 5 times.
- //verify(mDevicePolicyManager, atMost(1)).getKeyguardDisabledFeatures(any(), anyInt());
+ verify(mDevicePolicyManager, atMost(1)).getKeyguardDisabledFeatures(any(), anyInt());
}
@Test
public void testHideNotifications_primary() {
mSettings.putIntForUser(LOCK_SCREEN_SHOW_NOTIFICATIONS, 0, mCurrentUser.id);
- mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false);
+ changeSetting(LOCK_SCREEN_SHOW_NOTIFICATIONS);
assertFalse(mLockscreenUserManager.userAllowsNotificationsInPublic(mCurrentUser.id));
}
@@ -491,16 +567,17 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase {
@Test
public void testHideNotifications_secondary() {
mSettings.putIntForUser(LOCK_SCREEN_SHOW_NOTIFICATIONS, 0, mSecondaryUser.id);
- mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false);
+ changeSetting(LOCK_SCREEN_SHOW_NOTIFICATIONS);
assertFalse(mLockscreenUserManager.userAllowsNotificationsInPublic(mSecondaryUser.id));
}
- @Ignore("b/286230167")
@Test
public void testHideNotifications_workProfile() {
- mSettings.putIntForUser(LOCK_SCREEN_SHOW_NOTIFICATIONS, 0, mWorkUser.id);
- mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false);
+ mSettings.putIntForUser(LOCK_SCREEN_SHOW_NOTIFICATIONS, 0, mCurrentUser.id);
+ mSettings.putIntForUser(LOCK_SCREEN_SHOW_NOTIFICATIONS, 1, mWorkUser.id);
+ changeSetting(LOCK_SCREEN_SHOW_NOTIFICATIONS);
+ changeSetting(LOCK_SCREEN_SHOW_NOTIFICATIONS);
assertFalse(mLockscreenUserManager.userAllowsNotificationsInPublic(mWorkUser.id));
}
@@ -508,67 +585,62 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase {
@Test
public void testHideNotifications_secondary_userSwitch() {
mSettings.putIntForUser(LOCK_SCREEN_SHOW_NOTIFICATIONS, 0, mSecondaryUser.id);
+ changeSetting(LOCK_SCREEN_SHOW_NOTIFICATIONS);
- TestNotificationLockscreenUserManager lockscreenUserManager
- = new TestNotificationLockscreenUserManager(mContext);
- lockscreenUserManager.setUpWithPresenter(mPresenter);
-
- lockscreenUserManager.mUserChangedCallback.onUserChanging(mSecondaryUser.id, mContext);
+ mLockscreenUserManager.mUserChangedCallback.onUserChanging(mSecondaryUser.id, mContext);
- assertFalse(lockscreenUserManager.userAllowsNotificationsInPublic(mSecondaryUser.id));
+ assertFalse(mLockscreenUserManager.userAllowsNotificationsInPublic(mSecondaryUser.id));
}
@Test
public void testShowNotifications_secondary_userSwitch() {
mSettings.putIntForUser(LOCK_SCREEN_SHOW_NOTIFICATIONS, 1, mSecondaryUser.id);
+ changeSetting(LOCK_SCREEN_SHOW_NOTIFICATIONS);
- TestNotificationLockscreenUserManager lockscreenUserManager
- = new TestNotificationLockscreenUserManager(mContext);
- lockscreenUserManager.setUpWithPresenter(mPresenter);
-
- lockscreenUserManager.mUserChangedCallback.onUserChanging(mSecondaryUser.id, mContext);
+ mLockscreenUserManager.mUserChangedCallback.onUserChanging(mSecondaryUser.id, mContext);
- assertTrue(lockscreenUserManager.userAllowsNotificationsInPublic(mSecondaryUser.id));
+ assertTrue(mLockscreenUserManager.userAllowsNotificationsInPublic(mSecondaryUser.id));
}
- @Ignore("b/286230167")
@Test
public void testShouldShowLockscreenNotifications_keyguardManagerNoPrivateNotifications() {
+ // KeyguardManager does not allow notifications
+ when(mKeyguardManager.getPrivateNotificationsAllowed()).thenReturn(false);
// User allows notifications
mSettings.putIntForUser(LOCK_SCREEN_SHOW_NOTIFICATIONS, 1, mCurrentUser.id);
- mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false);
+ changeSetting(LOCK_SCREEN_SHOW_NOTIFICATIONS);
// DevicePolicy allows notifications
when(mDevicePolicyManager.getKeyguardDisabledFeatures(null, mCurrentUser.id))
.thenReturn(0);
- BroadcastReceiver.PendingResult pr = mock(BroadcastReceiver.PendingResult.class);
- when(pr.getSendingUserId()).thenReturn(mCurrentUser.id);
+ BroadcastReceiver.PendingResult pr = new BroadcastReceiver.PendingResult(
+ 0, null, null, 0, true, false, null, mCurrentUser.id, 0);
mLockscreenUserManager.mAllUsersReceiver.setPendingResult(pr);
mLockscreenUserManager.mAllUsersReceiver.onReceive(mContext,
new Intent(ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED));
- // KeyguardManager does not
- when(mKeyguardManager.getPrivateNotificationsAllowed()).thenReturn(false);
-
assertFalse(mLockscreenUserManager.shouldShowLockscreenNotifications());
}
@Test
public void testUserAllowsNotificationsInPublic_keyguardManagerNoPrivateNotifications() {
- // User allows notifications
- mSettings.putIntForUser(LOCK_SCREEN_SHOW_NOTIFICATIONS, 1, mCurrentUser.id);
- mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false);
// DevicePolicy allows notifications
when(mDevicePolicyManager.getKeyguardDisabledFeatures(null, mCurrentUser.id))
.thenReturn(0);
- BroadcastReceiver.PendingResult pr = mock(BroadcastReceiver.PendingResult.class);
- when(pr.getSendingUserId()).thenReturn(mCurrentUser.id);
+ BroadcastReceiver.PendingResult pr = new BroadcastReceiver.PendingResult(
+ 0, null, null, 0, true, false, null, mCurrentUser.id, 0);
mLockscreenUserManager.mAllUsersReceiver.setPendingResult(pr);
mLockscreenUserManager.mAllUsersReceiver.onReceive(mContext,
new Intent(ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED));
- // KeyguardManager does not
+ // KeyguardManager does not allow notifications
when(mKeyguardManager.getPrivateNotificationsAllowed()).thenReturn(false);
+ // User allows notifications
+ mSettings.putIntForUser(LOCK_SCREEN_SHOW_NOTIFICATIONS, 1, mCurrentUser.id);
+ // We shouldn't need to call this method, but getPrivateNotificationsAllowed has no
+ // callback, so it's only updated when the setting is
+ changeSetting(LOCK_SCREEN_SHOW_NOTIFICATIONS);
+
assertFalse(mLockscreenUserManager.userAllowsNotificationsInPublic(mCurrentUser.id));
}
@@ -576,31 +648,30 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase {
public void testUserAllowsNotificationsInPublic_settingsChange() {
// User allows notifications
mSettings.putIntForUser(LOCK_SCREEN_SHOW_NOTIFICATIONS, 1, mCurrentUser.id);
- mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false);
+ changeSetting(LOCK_SCREEN_SHOW_NOTIFICATIONS);
assertTrue(mLockscreenUserManager.userAllowsNotificationsInPublic(mCurrentUser.id));
// User disables
mSettings.putIntForUser(LOCK_SCREEN_SHOW_NOTIFICATIONS, 0, mCurrentUser.id);
- mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false);
+ changeSetting(LOCK_SCREEN_SHOW_NOTIFICATIONS);
assertFalse(mLockscreenUserManager.userAllowsNotificationsInPublic(mCurrentUser.id));
}
- @Ignore("b/286230167")
@Test
public void testUserAllowsNotificationsInPublic_devicePolicyChange() {
// User allows notifications
mSettings.putIntForUser(LOCK_SCREEN_SHOW_NOTIFICATIONS, 1, mCurrentUser.id);
- mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false);
+ changeSetting(LOCK_SCREEN_SHOW_NOTIFICATIONS);
assertTrue(mLockscreenUserManager.userAllowsNotificationsInPublic(mCurrentUser.id));
// DevicePolicy disables notifications
when(mDevicePolicyManager.getKeyguardDisabledFeatures(null, mCurrentUser.id))
.thenReturn(KEYGUARD_DISABLE_SECURE_NOTIFICATIONS);
- BroadcastReceiver.PendingResult pr = mock(BroadcastReceiver.PendingResult.class);
- when(pr.getSendingUserId()).thenReturn(mCurrentUser.id);
+ BroadcastReceiver.PendingResult pr = new BroadcastReceiver.PendingResult(
+ 0, null, null, 0, true, false, null, mCurrentUser.id, 0);
mLockscreenUserManager.mAllUsersReceiver.setPendingResult(pr);
mLockscreenUserManager.mAllUsersReceiver.onReceive(mContext,
new Intent(ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED));
@@ -608,6 +679,28 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase {
assertFalse(mLockscreenUserManager.userAllowsNotificationsInPublic(mCurrentUser.id));
}
+ @Test
+ public void testNewUserAdded() {
+ int newUserId = 14;
+ mSettings.putIntForUser(LOCK_SCREEN_SHOW_NOTIFICATIONS, 1, newUserId);
+ mSettings.putIntForUser(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 1, newUserId);
+ when(mDevicePolicyManager.getKeyguardDisabledFeatures(null, newUserId))
+ .thenReturn(KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS);
+
+ BroadcastReceiver broadcastReceiver =
+ mLockscreenUserManager.getBaseBroadcastReceiverForTest();
+ final Bundle extras = new Bundle();
+ final Intent intent = new Intent(Intent.ACTION_USER_ADDED);
+ intent.putExtras(extras);
+ intent.putExtra(Intent.EXTRA_USER_HANDLE, newUserId);
+ broadcastReceiver.onReceive(mContext, intent);
+
+ verify(mDevicePolicyManager, atMost(1)).getKeyguardDisabledFeatures(any(), eq(newUserId));
+
+ assertTrue(mLockscreenUserManager.userAllowsNotificationsInPublic(newUserId));
+ assertFalse(mLockscreenUserManager.userAllowsPrivateNotificationsInPublic(newUserId));
+ }
+
private class TestNotificationLockscreenUserManager
extends NotificationLockscreenUserManagerImpl {
public TestNotificationLockscreenUserManager(Context context) {
@@ -623,12 +716,17 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase {
(() -> mOverviewProxyService),
NotificationLockscreenUserManagerTest.this.mKeyguardManager,
mStatusBarStateController,
- Handler.createAsync(Looper.myLooper()),
+ Handler.createAsync(TestableLooper.get(
+ NotificationLockscreenUserManagerTest.this).getLooper()),
+ Handler.createAsync(TestableLooper.get(
+ NotificationLockscreenUserManagerTest.this).getLooper()),
+ mBackgroundExecutor,
mDeviceProvisionedController,
mKeyguardStateController,
mSettings,
mock(DumpManager.class),
- mock(LockPatternUtils.class));
+ mock(LockPatternUtils.class),
+ mFakeFeatureFlags);
}
public BroadcastReceiver getBaseBroadcastReceiverForTest() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProviderTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProviderTest.java
index 83f2a5d4fbdf..b922ab39912b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProviderTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProviderTest.java
@@ -22,6 +22,7 @@ import static android.app.Notification.VISIBILITY_SECRET;
import static android.app.NotificationManager.IMPORTANCE_HIGH;
import static android.app.NotificationManager.IMPORTANCE_LOW;
import static android.app.NotificationManager.IMPORTANCE_MIN;
+import static android.app.NotificationManager.VISIBILITY_NO_OVERRIDE;
import static com.android.systemui.statusbar.StatusBarState.KEYGUARD;
import static com.android.systemui.statusbar.StatusBarState.SHADE;
@@ -36,6 +37,7 @@ import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.app.NotificationChannel;
import android.content.Context;
import android.os.Handler;
import android.os.UserHandle;
@@ -51,6 +53,9 @@ import com.android.systemui.CoreStartable;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.flags.FakeFeatureFlagsClassic;
+import com.android.systemui.flags.FeatureFlagsClassic;
+import com.android.systemui.flags.Flags;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
@@ -96,6 +101,7 @@ public class KeyguardNotificationVisibilityProviderTest extends SysuiTestCase {
@Mock private UserTracker mUserTracker;
private final FakeSettings mSecureSettings = new FakeSettings();
private final FakeGlobalSettings mGlobalSettings = new FakeGlobalSettings();
+ private final FakeFeatureFlagsClassic mFeatureFlags = new FakeFeatureFlagsClassic();
private KeyguardNotificationVisibilityProvider mKeyguardNotificationVisibilityProvider;
private NotificationEntry mEntry;
@@ -116,7 +122,8 @@ public class KeyguardNotificationVisibilityProviderTest extends SysuiTestCase {
mStatusBarStateController,
mUserTracker,
mSecureSettings,
- mGlobalSettings);
+ mGlobalSettings,
+ mFeatureFlags);
mKeyguardNotificationVisibilityProvider = component.getProvider();
for (CoreStartable startable : component.getCoreStartables().values()) {
startable.start();
@@ -424,6 +431,7 @@ public class KeyguardNotificationVisibilityProviderTest extends SysuiTestCase {
@Test
public void publicMode_settingsDisallow() {
+ mFeatureFlags.set(Flags.NOTIF_LS_BACKGROUND_THREAD, true);
// GIVEN an 'unfiltered-keyguard-showing' state
setupUnfilteredState(mEntry);
@@ -433,12 +441,59 @@ public class KeyguardNotificationVisibilityProviderTest extends SysuiTestCase {
when(mLockscreenUserManager.userAllowsNotificationsInPublic(NOTIF_USER_ID))
.thenReturn(false);
+ mEntry.setRanking(new RankingBuilder()
+ .setChannel(new NotificationChannel("1", "1", 4))
+ .setVisibilityOverride(VISIBILITY_NO_OVERRIDE)
+ .setKey(mEntry.getKey()).build());
+
+ // THEN filter out the entry
+ assertTrue(mKeyguardNotificationVisibilityProvider.shouldHideNotification(mEntry));
+ }
+
+ @Test
+ public void publicMode_settingsDisallow_mainThread() {
+ mFeatureFlags.set(Flags.NOTIF_LS_BACKGROUND_THREAD, false);
+ // GIVEN an 'unfiltered-keyguard-showing' state
+ setupUnfilteredState(mEntry);
+
+ // WHEN the notification's user is in public mode and settings are configured to disallow
+ // notifications in public mode
+ when(mLockscreenUserManager.isLockscreenPublicMode(NOTIF_USER_ID)).thenReturn(true);
+ when(mLockscreenUserManager.userAllowsNotificationsInPublic(NOTIF_USER_ID))
+ .thenReturn(false);
+
+ mEntry.setRanking(new RankingBuilder()
+ .setChannel(new NotificationChannel("1", "1", 4))
+ .setVisibilityOverride(VISIBILITY_NO_OVERRIDE)
+ .setKey(mEntry.getKey()).build());
+
// THEN filter out the entry
assertTrue(mKeyguardNotificationVisibilityProvider.shouldHideNotification(mEntry));
}
@Test
public void publicMode_notifDisallowed() {
+ mFeatureFlags.set(Flags.NOTIF_LS_BACKGROUND_THREAD, true);
+ NotificationChannel channel = new NotificationChannel("1", "1", IMPORTANCE_HIGH);
+ channel.setLockscreenVisibility(VISIBILITY_SECRET);
+ // GIVEN an 'unfiltered-keyguard-showing' state
+ setupUnfilteredState(mEntry);
+
+ // WHEN the notification's user is in public mode and settings are configured to disallow
+ // notifications in public mode
+ when(mLockscreenUserManager.isLockscreenPublicMode(CURR_USER_ID)).thenReturn(true);
+ mEntry.setRanking(new RankingBuilder()
+ .setKey(mEntry.getKey())
+ .setChannel(channel)
+ .setVisibilityOverride(VISIBILITY_SECRET).build());
+
+ // THEN filter out the entry
+ assertTrue(mKeyguardNotificationVisibilityProvider.shouldHideNotification(mEntry));
+ }
+
+ @Test
+ public void publicMode_notifDisallowed_mainThread() {
+ mFeatureFlags.set(Flags.NOTIF_LS_BACKGROUND_THREAD, false);
// GIVEN an 'unfiltered-keyguard-showing' state
setupUnfilteredState(mEntry);
@@ -506,6 +561,54 @@ public class KeyguardNotificationVisibilityProviderTest extends SysuiTestCase {
}
@Test
+ public void notificationChannelVisibilityNoOverride() {
+ mFeatureFlags.set(Flags.NOTIF_LS_BACKGROUND_THREAD, true);
+ // GIVEN a VISIBILITY_PRIVATE notification
+ NotificationEntryBuilder entryBuilder = new NotificationEntryBuilder()
+ .setUser(new UserHandle(NOTIF_USER_ID));
+ entryBuilder.modifyNotification(mContext)
+ .setVisibility(VISIBILITY_PRIVATE);
+ mEntry = entryBuilder.build();
+ // ranking says secret because of DPC or Setting
+ mEntry.setRanking(new RankingBuilder()
+ .setKey(mEntry.getKey())
+ .setVisibilityOverride(VISIBILITY_SECRET)
+ .setImportance(IMPORTANCE_HIGH)
+ .build());
+
+ // WHEN we're in an 'unfiltered-keyguard-showing' state
+ setupUnfilteredState(mEntry);
+
+ // THEN don't hide the entry based on visibility. (Redaction is handled elsewhere.)
+ assertFalse(mKeyguardNotificationVisibilityProvider.shouldHideNotification(mEntry));
+ }
+
+ @Test
+ public void notificationChannelVisibilitySecret() {
+ mFeatureFlags.set(Flags.NOTIF_LS_BACKGROUND_THREAD, true);
+ // GIVEN a VISIBILITY_PRIVATE notification
+ NotificationEntryBuilder entryBuilder = new NotificationEntryBuilder()
+ .setUser(new UserHandle(NOTIF_USER_ID));
+ entryBuilder.modifyNotification(mContext)
+ .setVisibility(VISIBILITY_PRIVATE);
+ // And a VISIBILITY_SECRET NotificationChannel
+ NotificationChannel channel = new NotificationChannel("id", "name", IMPORTANCE_HIGH);
+ channel.setLockscreenVisibility(VISIBILITY_SECRET);
+ mEntry = entryBuilder.build();
+ // WHEN we're in an 'unfiltered-keyguard-showing' state
+ setupUnfilteredState(mEntry);
+ when(mLockscreenUserManager.isLockscreenPublicMode(CURR_USER_ID)).thenReturn(true);
+ when(mLockscreenUserManager.isLockscreenPublicMode(NOTIF_USER_ID)).thenReturn(true);
+
+ mEntry.setRanking(new RankingBuilder(mEntry.getRanking())
+ .setChannel(channel)
+ .build());
+
+ // THEN hide the entry based on visibility.
+ assertTrue(mKeyguardNotificationVisibilityProvider.shouldHideNotification(mEntry));
+ }
+
+ @Test
public void notificationVisibilityPrivate() {
// GIVEN a VISIBILITY_PRIVATE notification
NotificationEntryBuilder entryBuilder = new NotificationEntryBuilder()
@@ -635,7 +738,8 @@ public class KeyguardNotificationVisibilityProviderTest extends SysuiTestCase {
@BindsInstance SysuiStatusBarStateController statusBarStateController,
@BindsInstance UserTracker userTracker,
@BindsInstance SecureSettings secureSettings,
- @BindsInstance GlobalSettings globalSettings
+ @BindsInstance GlobalSettings globalSettings,
+ @BindsInstance FeatureFlagsClassic featureFlags
);
}
}