Add Coordinators to the NewNotifPipeline

Coordinators added to NotifCoordinators will be passed the
initialized NotifListBuilder and NotifCollection when they're
ready for Pluggables, NotiLfetimeExtenders and NotifCollectionListeners
to be registered.

This CL adds the KeyguardCoordinator which filters notifications based
on whether the keyguard is showing and user lockscreen notifcation
settings

Test: atest KeyguardCoordinatorTest
Bug: 145134683
Change-Id: Ie5a2c0f696a6eedbed203b1b5809164742d23132
This commit is contained in:
Beverly
2019-11-25 10:38:56 -05:00
parent 0f2b7fd29a
commit af16ee0c01
10 changed files with 621 additions and 6 deletions

View File

@@ -65,8 +65,18 @@ public interface NotificationLockscreenUserManager {
boolean needsRedaction(NotificationEntry entry);
/**
* Has the given user chosen to allow their private (full) notifications to be shown even
* when the lockscreen is in "public" (secure & locked) mode?
*/
boolean userAllowsPrivateNotificationsInPublic(int currentUserId);
/**
* Has the given user chosen to allow notifications to be shown even when the lockscreen is in
* "public" (secure & locked) mode?
*/
boolean userAllowsNotificationsInPublic(int userId);
/** Notified when the current user changes. */
interface UserChangedListener {
void onUserChanged(int userId);

View File

@@ -435,7 +435,7 @@ public class NotificationLockscreenUserManagerImpl implements
* Has the given user chosen to allow notifications to be shown even when the lockscreen is in
* "public" (secure & locked) mode?
*/
private boolean userAllowsNotificationsInPublic(int userHandle) {
public boolean userAllowsNotificationsInPublic(int userHandle) {
if (isCurrentProfile(userHandle) && userHandle != mCurrentUserId) {
return true;
}

View File

@@ -36,7 +36,10 @@ import com.android.systemui.statusbar.phone.StatusBar;
import javax.inject.Inject;
import javax.inject.Singleton;
/** Component which manages the various reasons a notification might be filtered out. */
/** Component which manages the various reasons a notification might be filtered out.*/
// TODO: delete NotificationFilter.java after migrating to new NotifPipeline b/145659174.
// Notification filtering is taken care of across the different Coordinators (mostly
// KeyguardCoordinator.java)
@Singleton
public class NotificationFilter {
@@ -109,7 +112,7 @@ public class NotificationFilter {
return true;
}
if (entry.isSuspended()) {
if (entry.getRanking().isSuspended()) {
return true;
}

View File

@@ -18,6 +18,8 @@ package com.android.systemui.statusbar.notification.collection;
import android.annotation.Nullable;
import com.android.internal.annotations.VisibleForTesting;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
@@ -34,7 +36,8 @@ public class GroupEntry extends ListEntry {
private final List<NotificationEntry> mUnmodifiableChildren =
Collections.unmodifiableList(mChildren);
GroupEntry(String key) {
@VisibleForTesting
public GroupEntry(String key) {
super(key);
}
@@ -52,7 +55,8 @@ public class GroupEntry extends ListEntry {
return mUnmodifiableChildren;
}
void setSummary(@Nullable NotificationEntry summary) {
@VisibleForTesting
public void setSummary(@Nullable NotificationEntry summary) {
mSummary = summary;
}

View File

@@ -18,6 +18,8 @@ package com.android.systemui.statusbar.notification.collection;
import android.annotation.Nullable;
import com.android.internal.annotations.VisibleForTesting;
/**
* Abstract superclass for top-level entries, i.e. things that can appear in the final notification
* list shown to users. In practice, this means either GroupEntries or NotificationEntries.
@@ -49,7 +51,8 @@ public abstract class ListEntry {
return mParent;
}
void setParent(@Nullable GroupEntry parent) {
@VisibleForTesting
public void setParent(@Nullable GroupEntry parent) {
mParent = parent;
}

View File

@@ -0,0 +1,42 @@
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.systemui.statusbar.notification.collection.coordinator;
import com.android.systemui.statusbar.notification.collection.NotifCollection;
import com.android.systemui.statusbar.notification.collection.NotifCollectionListener;
import com.android.systemui.statusbar.notification.collection.NotifLifetimeExtender;
import com.android.systemui.statusbar.notification.collection.init.NewNotifPipeline;
import com.android.systemui.statusbar.notification.collection.listbuilder.NotifListBuilder;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.Pluggable;
/**
* Interface for registering callbacks to the {@link NewNotifPipeline}.
*
* This includes registering:
* {@link Pluggable}s to the {@link NotifListBuilder}
* {@link NotifCollectionListener}s and {@link NotifLifetimeExtender}s to {@link NotifCollection}
*/
public interface Coordinator {
/**
* Called after the NewNotifPipeline is initialized.
* Coordinators should register their {@link Pluggable}s to the notifListBuilder
* and their {@link NotifCollectionListener}s and {@link NotifLifetimeExtender}s
* to the notifCollection in this method.
*/
void attach(NotifCollection notifCollection, NotifListBuilder notifListBuilder);
}

View File

@@ -0,0 +1,233 @@
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.systemui.statusbar.notification.collection.coordinator;
import static android.app.Notification.VISIBILITY_SECRET;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Handler;
import android.os.UserHandle;
import android.provider.Settings;
import android.service.notification.StatusBarNotification;
import androidx.annotation.MainThread;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.notification.NotificationUtils;
import com.android.systemui.statusbar.notification.collection.NotifCollection;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.listbuilder.NotifListBuilder;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import javax.inject.Inject;
import javax.inject.Singleton;
/**
* Filters low priority and privacy-sensitive notifications from the lockscreen.
*/
@Singleton
public class KeyguardCoordinator implements Coordinator {
private static final String TAG = "KeyguardNotificationCoordinator";
private final Context mContext;
private final Handler mMainHandler;
private final KeyguardStateController mKeyguardStateController;
private final NotificationLockscreenUserManager mLockscreenUserManager;
private final BroadcastDispatcher mBroadcastDispatcher;
private final StatusBarStateController mStatusBarStateController;
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
@Inject
public KeyguardCoordinator(
Context context,
@MainThread Handler mainThreadHandler,
KeyguardStateController keyguardStateController,
NotificationLockscreenUserManager lockscreenUserManager,
BroadcastDispatcher broadcastDispatcher,
StatusBarStateController statusBarStateController,
KeyguardUpdateMonitor keyguardUpdateMonitor) {
mContext = context;
mMainHandler = mainThreadHandler;
mKeyguardStateController = keyguardStateController;
mLockscreenUserManager = lockscreenUserManager;
mBroadcastDispatcher = broadcastDispatcher;
mStatusBarStateController = statusBarStateController;
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
}
@Override
public void attach(NotifCollection notifCollection, NotifListBuilder notifListBuilder) {
setupInvalidateNotifListCallbacks();
notifListBuilder.addFilter(mNotifFilter);
}
protected final NotifFilter mNotifFilter = new NotifFilter(TAG) {
@Override
public boolean shouldFilterOut(NotificationEntry entry, long now) {
final StatusBarNotification sbn = entry.getSbn();
// FILTER OUT the notification when the notification isn't for the current profile
if (!mLockscreenUserManager.isCurrentProfile(sbn.getUserId())) {
return true;
}
// FILTER OUT the notification when the keyguard is showing and...
if (mKeyguardStateController.isShowing()) {
// ... user settings or the device policy manager doesn't allow lockscreen
// notifications;
if (!mLockscreenUserManager.shouldShowLockscreenNotifications()) {
return true;
}
final int currUserId = mLockscreenUserManager.getCurrentUserId();
final int notifUserId = (sbn.getUser().getIdentifier() == UserHandle.USER_ALL)
? currUserId : sbn.getUser().getIdentifier();
// ... user is in lockdown
if (mKeyguardUpdateMonitor.isUserInLockdown(currUserId)
|| mKeyguardUpdateMonitor.isUserInLockdown(notifUserId)) {
return true;
}
// ... device is in public mode and the user's settings doesn't allow
// notifications to show in public mode
if (mLockscreenUserManager.isLockscreenPublicMode(currUserId)
|| mLockscreenUserManager.isLockscreenPublicMode(notifUserId)) {
if (entry.getRanking().getVisibilityOverride() == VISIBILITY_SECRET) {
return true;
}
if (!mLockscreenUserManager.userAllowsNotificationsInPublic(currUserId)
|| !mLockscreenUserManager.userAllowsNotificationsInPublic(
notifUserId)) {
return true;
}
}
// ... neither this notification nor its summary have high enough priority
// to be shown on the lockscreen
// TODO: grouping hasn't happened yet (b/145134683)
if (entry.getParent() != null) {
final NotificationEntry summary = entry.getParent().getRepresentativeEntry();
if (priorityExceedsLockscreenShowingThreshold(summary)) {
return false;
}
}
return !priorityExceedsLockscreenShowingThreshold(entry);
}
return false;
}
};
private boolean priorityExceedsLockscreenShowingThreshold(NotificationEntry entry) {
if (entry == null) {
return false;
}
if (NotificationUtils.useNewInterruptionModel(mContext)
&& hideSilentNotificationsOnLockscreen()) {
// TODO: make sure in the NewNotifPipeline that entry.isHighPriority() has been
// correctly updated before reaching this point (b/145134683)
return entry.isHighPriority();
} else {
return !entry.getRanking().isAmbient();
}
}
private boolean hideSilentNotificationsOnLockscreen() {
return Settings.Secure.getInt(mContext.getContentResolver(),
Settings.Secure.LOCK_SCREEN_SHOW_SILENT_NOTIFICATIONS, 1) == 0;
}
private void setupInvalidateNotifListCallbacks() {
// register onKeyguardShowing callback
mKeyguardStateController.addCallback(mKeyguardCallback);
// register lockscreen settings changed callbacks:
final ContentObserver settingsObserver = new ContentObserver(mMainHandler) {
@Override
public void onChange(boolean selfChange, Uri uri) {
if (mKeyguardStateController.isShowing()) {
invalidateListFromFilter("Settings " + uri + " changed");
}
}
};
mContext.getContentResolver().registerContentObserver(
Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS),
false,
settingsObserver,
UserHandle.USER_ALL);
mContext.getContentResolver().registerContentObserver(
Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS),
true,
settingsObserver,
UserHandle.USER_ALL);
mContext.getContentResolver().registerContentObserver(
Settings.Global.getUriFor(Settings.Global.ZEN_MODE),
false,
settingsObserver);
// register (maybe) public mode changed callbacks:
mStatusBarStateController.addCallback(mStatusBarStateListener);
mBroadcastDispatcher.registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (mKeyguardStateController.isShowing()) {
// maybe public mode changed
invalidateListFromFilter(intent.getAction());
}
}}, new IntentFilter(Intent.ACTION_USER_SWITCHED));
}
private void invalidateListFromFilter(String reason) {
mNotifFilter.invalidateList();
}
private final KeyguardStateController.Callback mKeyguardCallback =
new KeyguardStateController.Callback() {
@Override
public void onUnlockedChanged() {
invalidateListFromFilter("onUnlockedChanged");
}
@Override
public void onKeyguardShowingChanged() {
invalidateListFromFilter("onKeyguardShowingChanged");
}
};
private final StatusBarStateController.StateListener mStatusBarStateListener =
new StatusBarStateController.StateListener() {
@Override
public void onStateChanged(int newState) {
// maybe public mode changed
invalidateListFromFilter("onStatusBarStateChanged");
}
};
}

View File

@@ -0,0 +1,71 @@
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.systemui.statusbar.notification.collection.coordinator;
import com.android.systemui.Dumpable;
import com.android.systemui.statusbar.notification.collection.NotifCollection;
import com.android.systemui.statusbar.notification.collection.NotifCollectionListener;
import com.android.systemui.statusbar.notification.collection.NotifLifetimeExtender;
import com.android.systemui.statusbar.notification.collection.listbuilder.NotifListBuilder;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.Pluggable;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import javax.inject.Inject;
import javax.inject.Singleton;
/**
* Handles the attachment of the {@link NotifListBuilder} and {@link NotifCollection} to the
* {@link Coordinator}s, so that the Coordinators can register their respective callbacks.
*/
@Singleton
public class NotifCoordinators implements Dumpable {
private static final String TAG = "NotifCoordinators";
private final List<Coordinator> mCoordinators = new ArrayList<>();
/**
* Creates all the coordinators.
*/
@Inject
public NotifCoordinators(KeyguardCoordinator keyguardNotificationCoordinator) {
mCoordinators.add(keyguardNotificationCoordinator);
// TODO: add new Coordinators here! (b/145134683, b/112656837)
}
/**
* Sends the initialized notifListBuilder and notifCollection to each
* coordinator to indicate the notifListBuilder is ready to accept {@link Pluggable}s
* and the notifCollection is ready to accept {@link NotifCollectionListener}s and
* {@link NotifLifetimeExtender}s.
*/
public void attach(NotifCollection notifCollection, NotifListBuilder notifListBuilder) {
for (Coordinator c : mCoordinators) {
c.attach(notifCollection, notifListBuilder);
}
}
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.println(TAG + ":");
for (Coordinator c : mCoordinators) {
pw.println("\t" + c.getClass());
}
}
}

View File

@@ -23,6 +23,7 @@ import com.android.systemui.Dumpable;
import com.android.systemui.statusbar.NotificationListener;
import com.android.systemui.statusbar.notification.collection.NotifCollection;
import com.android.systemui.statusbar.notification.collection.NotifListBuilderImpl;
import com.android.systemui.statusbar.notification.collection.coordinator.NotifCoordinators;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -37,6 +38,7 @@ import javax.inject.Singleton;
public class NewNotifPipeline implements Dumpable {
private final NotifCollection mNotifCollection;
private final NotifListBuilderImpl mNotifPipeline;
private final NotifCoordinators mNotifPluggableCoordinators;
private final DumpController mDumpController;
private final FakePipelineConsumer mFakePipelineConsumer = new FakePipelineConsumer();
@@ -45,9 +47,11 @@ public class NewNotifPipeline implements Dumpable {
public NewNotifPipeline(
NotifCollection notifCollection,
NotifListBuilderImpl notifPipeline,
NotifCoordinators notifCoordinators,
DumpController dumpController) {
mNotifCollection = notifCollection;
mNotifPipeline = notifPipeline;
mNotifPluggableCoordinators = notifCoordinators;
mDumpController = dumpController;
}
@@ -57,6 +61,7 @@ public class NewNotifPipeline implements Dumpable {
mFakePipelineConsumer.attach(mNotifPipeline);
mNotifPipeline.attach(mNotifCollection);
mNotifCollection.attach(notificationService);
mNotifPluggableCoordinators.attach(mNotifCollection, mNotifPipeline);
Log.d(TAG, "Notif pipeline initialized");
@@ -66,6 +71,7 @@ public class NewNotifPipeline implements Dumpable {
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
mFakePipelineConsumer.dump(fd, pw, args);
mNotifPluggableCoordinators.dump(fd, pw, args);
}
private static final String TAG = "NewNotifPipeline";

View File

@@ -0,0 +1,243 @@
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.systemui.statusbar.notification.collection.coordinator;
import static android.app.Notification.VISIBILITY_PUBLIC;
import static android.app.Notification.VISIBILITY_SECRET;
import static android.app.NotificationManager.IMPORTANCE_HIGH;
import static android.app.NotificationManager.IMPORTANCE_MIN;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
import static org.mockito.Mockito.when;
import android.os.Handler;
import android.os.UserHandle;
import android.testing.AndroidTestingRunner;
import androidx.test.filters.SmallTest;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.NotificationEntryBuilder;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.RankingBuilder;
import com.android.systemui.statusbar.notification.collection.GroupEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@SmallTest
@RunWith(AndroidTestingRunner.class)
public class KeyguardCoordinatorTest extends SysuiTestCase {
private static final int NOTIF_USER_ID = 0;
private static final int CURR_USER_ID = 1;
@Mock private Handler mMainHandler;
@Mock private KeyguardStateController mKeyguardStateController;
@Mock private NotificationLockscreenUserManager mLockscreenUserManager;
@Mock private BroadcastDispatcher mBroadcastDispatcher;
@Mock private StatusBarStateController mStatusBarStateController;
@Mock private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
private NotificationEntry mEntry;
private KeyguardCoordinator mKeyguardNotificationCoordinator;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
mKeyguardNotificationCoordinator = new KeyguardCoordinator(
mContext, mMainHandler, mKeyguardStateController, mLockscreenUserManager,
mBroadcastDispatcher, mStatusBarStateController,
mKeyguardUpdateMonitor);
mEntry = new NotificationEntryBuilder()
.setUser(new UserHandle(NOTIF_USER_ID))
.build();
}
@Test
public void unfilteredState() {
// GIVEN an 'unfiltered-keyguard-showing' state
setupUnfilteredState();
// THEN don't filter out the entry
assertFalse(mKeyguardNotificationCoordinator.mNotifFilter.shouldFilterOut(mEntry, 0));
}
@Test
public void notificationNotForCurrentProfile() {
// GIVEN the notification isn't for the given user
setupUnfilteredState();
when(mLockscreenUserManager.isCurrentProfile(NOTIF_USER_ID)).thenReturn(false);
// THEN filter out the entry
assertTrue(mKeyguardNotificationCoordinator.mNotifFilter.shouldFilterOut(mEntry, 0));
}
@Test
public void keyguardNotShowing() {
// GIVEN the lockscreen isn't showing
setupUnfilteredState();
when(mKeyguardStateController.isShowing()).thenReturn(false);
// THEN don't filter out the entry
assertFalse(mKeyguardNotificationCoordinator.mNotifFilter.shouldFilterOut(mEntry, 0));
}
@Test
public void doNotShowLockscreenNotifications() {
// GIVEN an 'unfiltered-keyguard-showing' state
setupUnfilteredState();
// WHEN we shouldn't show any lockscreen notifications
when(mLockscreenUserManager.shouldShowLockscreenNotifications()).thenReturn(false);
// THEN filter out the entry
assertTrue(mKeyguardNotificationCoordinator.mNotifFilter.shouldFilterOut(mEntry, 0));
}
@Test
public void lockdown() {
// GIVEN an 'unfiltered-keyguard-showing' state
setupUnfilteredState();
// WHEN the notification's user is in lockdown:
when(mKeyguardUpdateMonitor.isUserInLockdown(NOTIF_USER_ID)).thenReturn(true);
// THEN filter out the entry
assertTrue(mKeyguardNotificationCoordinator.mNotifFilter.shouldFilterOut(mEntry, 0));
}
@Test
public void publicMode_settingsDisallow() {
// GIVEN an 'unfiltered-keyguard-showing' state
setupUnfilteredState();
// 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);
// THEN filter out the entry
assertTrue(mKeyguardNotificationCoordinator.mNotifFilter.shouldFilterOut(mEntry, 0));
}
@Test
public void publicMode_notifDisallowed() {
// GIVEN an 'unfiltered-keyguard-showing' state
setupUnfilteredState();
// 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())
.setVisibilityOverride(VISIBILITY_SECRET).build());
// THEN filter out the entry
assertTrue(mKeyguardNotificationCoordinator.mNotifFilter.shouldFilterOut(mEntry, 0));
}
@Test
public void doesNotExceedThresholdToShow() {
// GIVEN an 'unfiltered-keyguard-showing' state
setupUnfilteredState();
// WHEN the notification doesn't exceed the threshold to show on the lockscreen
mEntry.setRanking(new RankingBuilder()
.setKey(mEntry.getKey())
.setImportance(IMPORTANCE_MIN)
.build());
// THEN filter out the entry
assertTrue(mKeyguardNotificationCoordinator.mNotifFilter.shouldFilterOut(mEntry, 0));
}
@Test
public void summaryExceedsThresholdToShow() {
// GIVEN an 'unfiltered-keyguard-showing' state
setupUnfilteredState();
// WHEN the notification doesn't exceed the threshold to show on the lockscreen
// but its summary does
mEntry.setRanking(new RankingBuilder()
.setKey(mEntry.getKey())
.setImportance(IMPORTANCE_MIN)
.build());
final NotificationEntry summary = new NotificationEntryBuilder().build();
summary.setRanking(new RankingBuilder()
.setKey(summary.getKey())
.setImportance(IMPORTANCE_HIGH)
.build());
final GroupEntry group = new GroupEntry(mEntry.getSbn().getGroupKey());
group.setSummary(summary);
mEntry.setParent(group);
// THEN don't filter out the entry
assertFalse(mKeyguardNotificationCoordinator.mNotifFilter.shouldFilterOut(mEntry, 0));
}
/**
* setup a state where the notification will not be filtered by the
* KeyguardNotificationCoordinator when the keyguard is showing.
*/
private void setupUnfilteredState() {
// notification is for current profile
when(mLockscreenUserManager.isCurrentProfile(NOTIF_USER_ID)).thenReturn(true);
// keyguard is showing
when(mKeyguardStateController.isShowing()).thenReturn(true);
// show notifications on the lockscreen
when(mLockscreenUserManager.shouldShowLockscreenNotifications()).thenReturn(true);
// neither the current user nor the notification's user is in lockdown
when(mLockscreenUserManager.getCurrentUserId()).thenReturn(CURR_USER_ID);
when(mKeyguardUpdateMonitor.isUserInLockdown(NOTIF_USER_ID)).thenReturn(false);
when(mKeyguardUpdateMonitor.isUserInLockdown(CURR_USER_ID)).thenReturn(false);
// not in public mode
when(mLockscreenUserManager.isLockscreenPublicMode(CURR_USER_ID)).thenReturn(false);
when(mLockscreenUserManager.isLockscreenPublicMode(NOTIF_USER_ID)).thenReturn(false);
// entry's ranking - should show on all lockscreens
// + priority of the notification exceeds the threshold to be shown on the lockscreen
mEntry.setRanking(new RankingBuilder()
.setKey(mEntry.getKey())
.setVisibilityOverride(VISIBILITY_PUBLIC)
.setImportance(IMPORTANCE_HIGH)
.build());
// settings allows notifications in public mode
when(mLockscreenUserManager.userAllowsNotificationsInPublic(CURR_USER_ID)).thenReturn(true);
when(mLockscreenUserManager.userAllowsNotificationsInPublic(NOTIF_USER_ID))
.thenReturn(true);
// notification doesn't have a summary
}
}