Merge "Register KeyguardNotifVisProvider CoreStartable" into tm-dev

This commit is contained in:
TreeHugger Robot
2022-03-21 17:42:59 +00:00
committed by Android (Google) Code Review
7 changed files with 354 additions and 67 deletions

View File

@@ -70,7 +70,7 @@ public class KeyguardCoordinator implements Coordinator {
private final NotifFilter mNotifFilter = new NotifFilter(TAG) {
@Override
public boolean shouldFilterOut(NotificationEntry entry, long now) {
return mKeyguardNotificationVisibilityProvider.hideNotification(entry);
return mKeyguardNotificationVisibilityProvider.shouldHideNotification(entry);
}
};

View File

@@ -73,6 +73,7 @@ import com.android.systemui.statusbar.notification.collection.render.Notificatio
import com.android.systemui.statusbar.notification.init.NotificationsController;
import com.android.systemui.statusbar.notification.init.NotificationsControllerImpl;
import com.android.systemui.statusbar.notification.init.NotificationsControllerStub;
import com.android.systemui.statusbar.notification.interruption.KeyguardNotificationVisibilityProviderModule;
import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider;
import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProviderImpl;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
@@ -107,9 +108,10 @@ import dagger.Provides;
*/
@Module(includes = {
CoordinatorsModule.class,
KeyguardNotificationVisibilityProviderModule.class,
NotifActivityLaunchEventsModule.class,
NotifPipelineChoreographerModule.class,
NotifPanelEventsModule.class,
NotifPipelineChoreographerModule.class,
NotificationSectionHeadersModule.class,
})
public interface NotificationsModule {

View File

@@ -14,6 +14,7 @@ import com.android.keyguard.KeyguardUpdateMonitor
import com.android.keyguard.KeyguardUpdateMonitorCallback
import com.android.systemui.CoreStartable
import com.android.systemui.broadcast.BroadcastDispatcher
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.statusbar.NotificationLockscreenUserManager
@@ -22,13 +23,49 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.util.ListenerSet
import com.android.systemui.util.settings.GlobalSettings
import com.android.systemui.util.settings.SecureSettings
import dagger.Binds
import dagger.Module
import dagger.multibindings.ClassKey
import dagger.multibindings.IntoMap
import java.util.function.Consumer
import javax.inject.Inject
/**
* Determines if notifications should be visible based on the state of the keyguard
*/
class KeyguardNotificationVisibilityProvider @Inject constructor(
/** Determines if notifications should be visible based on the state of the keyguard. */
interface KeyguardNotificationVisibilityProvider {
/**
* Determines if the given notification should be hidden based on the current keyguard state.
* If a [Consumer] registered via [addOnStateChangedListener] is invoked, the results of this
* method may no longer be valid and should be re-queried.
*/
fun shouldHideNotification(entry: NotificationEntry): Boolean
/** Registers a listener to be notified when the internal keyguard state has been updated. */
fun addOnStateChangedListener(listener: Consumer<String>)
/** Unregisters a listener previously registered with [addOnStateChangedListener]. */
fun removeOnStateChangedListener(listener: Consumer<String>)
}
/** Provides a [KeyguardNotificationVisibilityProvider] in [SysUISingleton] scope. */
@Module(includes = [KeyguardNotificationVisibilityProviderImplModule::class])
object KeyguardNotificationVisibilityProviderModule
@Module
private interface KeyguardNotificationVisibilityProviderImplModule {
@Binds
fun bindImpl(impl: KeyguardNotificationVisibilityProviderImpl):
KeyguardNotificationVisibilityProvider
@Binds
@IntoMap
@ClassKey(KeyguardNotificationVisibilityProvider::class)
fun bindStartable(impl: KeyguardNotificationVisibilityProviderImpl): CoreStartable
}
@SysUISingleton
private class KeyguardNotificationVisibilityProviderImpl @Inject constructor(
context: Context,
@Main private val handler: Handler,
private val keyguardStateController: KeyguardStateController,
@@ -36,8 +73,10 @@ class KeyguardNotificationVisibilityProvider @Inject constructor(
private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
private val highPriorityProvider: HighPriorityProvider,
private val statusBarStateController: StatusBarStateController,
private val broadcastDispatcher: BroadcastDispatcher
) : CoreStartable(context) {
private val broadcastDispatcher: BroadcastDispatcher,
private val secureSettings: SecureSettings,
private val globalSettings: GlobalSettings
) : CoreStartable(context), KeyguardNotificationVisibilityProvider {
private val onStateChangedListeners = ListenerSet<Consumer<String>>()
private var hideSilentNotificationsOnLockscreen: Boolean = false
@@ -60,33 +99,28 @@ class KeyguardNotificationVisibilityProvider @Inject constructor(
// register lockscreen settings changed callbacks:
val settingsObserver: ContentObserver = object : ContentObserver(handler) {
override fun onChange(selfChange: Boolean, uri: Uri) {
override fun onChange(selfChange: Boolean, uri: Uri?) {
if (keyguardStateController.isShowing) {
notifyStateChanged("Settings $uri changed")
}
}
}
mContext.contentResolver.registerContentObserver(
Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS),
false,
secureSettings.registerContentObserverForUser(
Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS,
settingsObserver,
UserHandle.USER_ALL)
mContext.contentResolver.registerContentObserver(
Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS),
secureSettings.registerContentObserverForUser(
Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS,
true,
settingsObserver,
UserHandle.USER_ALL)
mContext.contentResolver.registerContentObserver(
Settings.Global.getUriFor(Settings.Global.ZEN_MODE),
false,
settingsObserver)
globalSettings.registerContentObserver(Settings.Global.ZEN_MODE, settingsObserver)
mContext.contentResolver.registerContentObserver(
Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_SHOW_SILENT_NOTIFICATIONS),
false,
secureSettings.registerContentObserverForUser(
Settings.Secure.LOCK_SCREEN_SHOW_SILENT_NOTIFICATIONS,
settingsObserver,
UserHandle.USER_ALL)
@@ -98,41 +132,36 @@ class KeyguardNotificationVisibilityProvider @Inject constructor(
})
broadcastDispatcher.registerReceiver(object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
if (keyguardStateController.isShowing()) {
if (keyguardStateController.isShowing) {
// maybe public mode changed
notifyStateChanged(intent.action)
notifyStateChanged(intent.action!!)
}
}
}, IntentFilter(Intent.ACTION_USER_SWITCHED))
}
fun addOnStateChangedListener(listener: Consumer<String>) {
override fun addOnStateChangedListener(listener: Consumer<String>) {
onStateChangedListeners.addIfAbsent(listener)
}
fun removeOnStateChangedListener(listener: Consumer<String>) {
override fun removeOnStateChangedListener(listener: Consumer<String>) {
onStateChangedListeners.remove(listener)
}
private fun notifyStateChanged(reason: String) {
onStateChangedListeners.forEach({ it.accept(reason) })
onStateChangedListeners.forEach { it.accept(reason) }
}
/**
* Determines if the given notification should be hidden based on the current keyguard state.
* If Listener#onKeyguardStateChanged is invoked, the results of this method may no longer
* be valid, and so should be re-queried
*/
fun hideNotification(entry: NotificationEntry): Boolean {
override fun shouldHideNotification(entry: NotificationEntry): Boolean {
val sbn = entry.sbn
// FILTER OUT the notification when the keyguard is showing and...
if (keyguardStateController.isShowing()) {
if (keyguardStateController.isShowing) {
// ... user settings or the device policy manager doesn't allow lockscreen
// notifications;
if (!lockscreenUserManager.shouldShowLockscreenNotifications()) {
return true
}
val currUserId: Int = lockscreenUserManager.getCurrentUserId()
val currUserId: Int = lockscreenUserManager.currentUserId
val notifUserId =
if (sbn.user.identifier == UserHandle.USER_ALL) currUserId
else sbn.user.identifier
@@ -178,9 +207,7 @@ class KeyguardNotificationVisibilityProvider @Inject constructor(
}
private fun readShowSilentNotificationSetting() {
hideSilentNotificationsOnLockscreen = Settings.Secure.getInt(
mContext.getContentResolver(),
Settings.Secure.LOCK_SCREEN_SHOW_SILENT_NOTIFICATIONS,
1) == 0
hideSilentNotificationsOnLockscreen =
secureSettings.getBool(Settings.Secure.LOCK_SCREEN_SHOW_SILENT_NOTIFICATIONS, true)
}
}

View File

@@ -312,7 +312,7 @@ public class NotificationInterruptStateProviderImpl implements NotificationInter
return false;
}
if (mKeyguardNotificationVisibilityProvider.hideNotification(entry)) {
if (mKeyguardNotificationVisibilityProvider.shouldHideNotification(entry)) {
mLogger.keyguardHideNotification(entry.getKey());
return false;
}

View File

@@ -303,11 +303,82 @@ public interface SettingsProxy {
default boolean putInt(String name, int value) {
return putIntForUser(name, value, getUserId());
}
/** See {@link #putInt(String, int)}. */
default boolean putIntForUser(String name, int value, int userHandle) {
return putStringForUser(name, Integer.toString(value), userHandle);
}
/**
* Convenience function for retrieving a single secure settings value
* as a boolean. Note that internally setting values are always
* stored as strings; this function converts the string to a boolean
* for you. The default value will be returned if the setting is
* not defined or not a boolean.
*
* @param name The name of the setting to retrieve.
* @param def Value to return if the setting is not defined.
*
* @return The setting's current value, or 'def' if it is not defined
* or not a valid boolean.
*/
default boolean getBool(String name, boolean def) {
return getBoolForUser(name, def, getUserId());
}
/** See {@link #getBool(String, boolean)}. */
default boolean getBoolForUser(String name, boolean def, int userHandle) {
return getIntForUser(name, def ? 1 : 0, userHandle) != 0;
}
/**
* Convenience function for retrieving a single secure settings value
* as a boolean. Note that internally setting values are always
* stored as strings; this function converts the string to a boolean
* for you.
* <p>
* This version does not take a default value. If the setting has not
* been set, or the string value is not a number,
* it throws {@link Settings.SettingNotFoundException}.
*
* @param name The name of the setting to retrieve.
*
* @throws Settings.SettingNotFoundException Thrown if a setting by the given
* name can't be found or the setting value is not a boolean.
*
* @return The setting's current value.
*/
default boolean getBool(String name) throws Settings.SettingNotFoundException {
return getBoolForUser(name, getUserId());
}
/** See {@link #getBool(String)}. */
default boolean getBoolForUser(String name, int userHandle)
throws Settings.SettingNotFoundException {
return getIntForUser(name, userHandle) != 0;
}
/**
* Convenience function for updating a single settings value as a
* boolean. This will either create a new entry in the table if the
* given name does not exist, or modify the value of the existing row
* with that name. Note that internally setting values are always
* stored as strings, so this function converts the given value to a
* string before storing it.
*
* @param name The name of the setting to modify.
* @param value The new value for the setting.
* @return true if the value was set, false on database errors
*/
default boolean putBool(String name, boolean value) {
return putBoolForUser(name, value, getUserId());
}
/** See {@link #putBool(String, boolean)}. */
default boolean putBoolForUser(String name, boolean value, int userHandle) {
return putIntForUser(name, value ? 1 : 0, userHandle);
}
/**
* Convenience function for retrieving a single secure settings value
* as a {@code long}. Note that internally setting values are always

View File

@@ -22,84 +22,238 @@ import static android.app.NotificationManager.IMPORTANCE_HIGH;
import static android.app.NotificationManager.IMPORTANCE_MIN;
import static com.android.systemui.statusbar.notification.collection.EntryUtilKt.modifyEntry;
import static com.android.systemui.util.mockito.KotlinMockitoHelpersKt.argThat;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.spy;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Handler;
import android.os.UserHandle;
import android.provider.Settings;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import androidx.test.filters.SmallTest;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.systemui.CoreStartable;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.RankingBuilder;
import com.android.systemui.statusbar.notification.SectionHeaderVisibilityProvider;
import com.android.systemui.statusbar.notification.collection.GroupEntry;
import com.android.systemui.statusbar.notification.collection.GroupEntryBuilder;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.util.settings.FakeSettings;
import com.android.systemui.util.settings.GlobalSettings;
import com.android.systemui.util.settings.SecureSettings;
import com.android.systemui.utils.os.FakeHandler;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.util.Map;
import java.util.function.Consumer;
import dagger.BindsInstance;
import dagger.Component;
@SmallTest
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
public class KeyguardNotificationVisibilityProviderTest 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 KeyguardUpdateMonitor mKeyguardUpdateMonitor;
@Mock private HighPriorityProvider mHighPriorityProvider;
@Mock private SectionHeaderVisibilityProvider mSectionHeaderVisibilityProvider;
@Mock private KeyguardNotificationVisibilityProvider mKeyguardNotificationVisibilityProvider;
@Mock private StatusBarStateController mStatusBarStateController;
@Mock private BroadcastDispatcher mBroadcastDispatcher;
private final FakeSettings mFakeSettings = new FakeSettings();
private KeyguardNotificationVisibilityProvider mKeyguardNotificationVisibilityProvider;
private NotificationEntry mEntry;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
// TODO refactor the test of KeyguardNotificationVisibilityProvider out
mKeyguardNotificationVisibilityProvider = spy(new KeyguardNotificationVisibilityProvider(
mContext,
mMainHandler,
mKeyguardStateController,
mLockscreenUserManager,
mKeyguardUpdateMonitor,
mHighPriorityProvider,
mStatusBarStateController,
mBroadcastDispatcher
));
TestComponent component =
DaggerKeyguardNotificationVisibilityProviderTest_TestComponent
.factory()
.create(
mContext,
new FakeHandler(TestableLooper.get(this).getLooper()),
mKeyguardStateController,
mLockscreenUserManager,
mKeyguardUpdateMonitor,
mHighPriorityProvider,
mStatusBarStateController,
mBroadcastDispatcher,
mFakeSettings,
mFakeSettings);
mKeyguardNotificationVisibilityProvider = component.getProvider();
for (CoreStartable startable : component.getCoreStartables().values()) {
startable.start();
}
mEntry = new NotificationEntryBuilder()
.setUser(new UserHandle(NOTIF_USER_ID))
.build();
}
@Test
public void notifyListeners_onUnlockedChanged() {
ArgumentCaptor<KeyguardStateController.Callback> callbackCaptor =
ArgumentCaptor.forClass(KeyguardStateController.Callback.class);
verify(mKeyguardStateController).addCallback(callbackCaptor.capture());
KeyguardStateController.Callback callback = callbackCaptor.getValue();
Consumer<String> listener = mock(Consumer.class);
mKeyguardNotificationVisibilityProvider.addOnStateChangedListener(listener);
callback.onUnlockedChanged();
verify(listener).accept(anyString());
}
@Test
public void notifyListeners_onKeyguardShowingChanged() {
ArgumentCaptor<KeyguardStateController.Callback> callbackCaptor =
ArgumentCaptor.forClass(KeyguardStateController.Callback.class);
verify(mKeyguardStateController).addCallback(callbackCaptor.capture());
KeyguardStateController.Callback callback = callbackCaptor.getValue();
Consumer<String> listener = mock(Consumer.class);
mKeyguardNotificationVisibilityProvider.addOnStateChangedListener(listener);
callback.onKeyguardShowingChanged();
verify(listener).accept(anyString());
}
@Test
public void notifyListeners_onStrongAuthStateChanged() {
ArgumentCaptor<KeyguardUpdateMonitorCallback> callbackCaptor =
ArgumentCaptor.forClass(KeyguardUpdateMonitorCallback.class);
verify(mKeyguardUpdateMonitor).registerCallback(callbackCaptor.capture());
KeyguardUpdateMonitorCallback callback = callbackCaptor.getValue();
Consumer<String> listener = mock(Consumer.class);
mKeyguardNotificationVisibilityProvider.addOnStateChangedListener(listener);
callback.onStrongAuthStateChanged(0);
verify(listener).accept(anyString());
}
@Test
public void notifyListeners_onStatusBarStateChanged() {
ArgumentCaptor<StatusBarStateController.StateListener> callbackCaptor =
ArgumentCaptor.forClass(StatusBarStateController.StateListener.class);
verify(mStatusBarStateController).addCallback(callbackCaptor.capture());
StatusBarStateController.StateListener callback = callbackCaptor.getValue();
Consumer<String> listener = mock(Consumer.class);
mKeyguardNotificationVisibilityProvider.addOnStateChangedListener(listener);
callback.onStateChanged(0);
verify(listener).accept(anyString());
}
@Test
public void notifyListeners_onReceiveUserSwitchBroadcast() {
ArgumentCaptor<BroadcastReceiver> callbackCaptor =
ArgumentCaptor.forClass(BroadcastReceiver.class);
verify(mBroadcastDispatcher).registerReceiver(
callbackCaptor.capture(),
argThat(intentFilter -> intentFilter.hasAction(Intent.ACTION_USER_SWITCHED)),
isNull(),
isNull(),
eq(Context.RECEIVER_EXPORTED));
BroadcastReceiver callback = callbackCaptor.getValue();
Consumer<String> listener = mock(Consumer.class);
mKeyguardNotificationVisibilityProvider.addOnStateChangedListener(listener);
when(mKeyguardStateController.isShowing()).thenReturn(true);
callback.onReceive(mContext, new Intent(Intent.ACTION_USER_SWITCHED));
verify(listener).accept(anyString());
}
@Test
public void notifyListeners_onSettingChange_lockScreenShowNotifs() {
when(mKeyguardStateController.isShowing()).thenReturn(true);
Consumer<String> listener = mock(Consumer.class);
mKeyguardNotificationVisibilityProvider.addOnStateChangedListener(listener);
mFakeSettings.putInt(Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, 1);
verify(listener).accept(anyString());
}
@Test
public void notifyListeners_onSettingChange_lockScreenAllowPrivateNotifs() {
when(mKeyguardStateController.isShowing()).thenReturn(true);
Consumer<String> listener = mock(Consumer.class);
mKeyguardNotificationVisibilityProvider.addOnStateChangedListener(listener);
mFakeSettings.putInt(Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 1);
verify(listener).accept(anyString());
}
@Test
public void notifyListeners_onSettingChange_zenMode() {
when(mKeyguardStateController.isShowing()).thenReturn(true);
Consumer<String> listener = mock(Consumer.class);
mKeyguardNotificationVisibilityProvider.addOnStateChangedListener(listener);
mFakeSettings.putInt(Settings.Global.ZEN_MODE, 1);
verify(listener).accept(anyString());
}
@Test
public void notifyListeners_onSettingChange_lockScreenShowSilentNotifs() {
when(mKeyguardStateController.isShowing()).thenReturn(true);
Consumer<String> listener = mock(Consumer.class);
mKeyguardNotificationVisibilityProvider.addOnStateChangedListener(listener);
mFakeSettings.putInt(Settings.Secure.LOCK_SCREEN_SHOW_SILENT_NOTIFICATIONS, 1);
verify(listener).accept(anyString());
}
@Test
public void unfilteredState() {
// GIVEN an 'unfiltered-keyguard-showing' state
setupUnfilteredState(mEntry);
// THEN don't filter out the entry
assertFalse(mKeyguardNotificationVisibilityProvider.hideNotification(mEntry));
assertFalse(mKeyguardNotificationVisibilityProvider.shouldHideNotification(mEntry));
}
@Test
@@ -109,7 +263,7 @@ public class KeyguardNotificationVisibilityProviderTest extends SysuiTestCase {
when(mKeyguardStateController.isShowing()).thenReturn(false);
// THEN don't filter out the entry
assertFalse(mKeyguardNotificationVisibilityProvider.hideNotification(mEntry));
assertFalse(mKeyguardNotificationVisibilityProvider.shouldHideNotification(mEntry));
}
@Test
@@ -121,7 +275,7 @@ public class KeyguardNotificationVisibilityProviderTest extends SysuiTestCase {
when(mLockscreenUserManager.shouldShowLockscreenNotifications()).thenReturn(false);
// THEN filter out the entry
assertTrue(mKeyguardNotificationVisibilityProvider.hideNotification(mEntry));
assertTrue(mKeyguardNotificationVisibilityProvider.shouldHideNotification(mEntry));
}
@Test
@@ -133,7 +287,7 @@ public class KeyguardNotificationVisibilityProviderTest extends SysuiTestCase {
when(mKeyguardUpdateMonitor.isUserInLockdown(NOTIF_USER_ID)).thenReturn(true);
// THEN filter out the entry
assertTrue(mKeyguardNotificationVisibilityProvider.hideNotification(mEntry));
assertTrue(mKeyguardNotificationVisibilityProvider.shouldHideNotification(mEntry));
}
@Test
@@ -148,7 +302,7 @@ public class KeyguardNotificationVisibilityProviderTest extends SysuiTestCase {
.thenReturn(false);
// THEN filter out the entry
assertTrue(mKeyguardNotificationVisibilityProvider.hideNotification(mEntry));
assertTrue(mKeyguardNotificationVisibilityProvider.shouldHideNotification(mEntry));
}
@Test
@@ -164,7 +318,7 @@ public class KeyguardNotificationVisibilityProviderTest extends SysuiTestCase {
.setVisibilityOverride(VISIBILITY_SECRET).build());
// THEN filter out the entry
assertTrue(mKeyguardNotificationVisibilityProvider.hideNotification(mEntry));
assertTrue(mKeyguardNotificationVisibilityProvider.shouldHideNotification(mEntry));
}
@Test
@@ -180,7 +334,7 @@ public class KeyguardNotificationVisibilityProviderTest extends SysuiTestCase {
when(mHighPriorityProvider.isHighPriority(mEntry)).thenReturn(false);
// THEN filter out the entry
assertTrue(mKeyguardNotificationVisibilityProvider.hideNotification(mEntry));
assertTrue(mKeyguardNotificationVisibilityProvider.shouldHideNotification(mEntry));
}
@Test
@@ -209,7 +363,8 @@ public class KeyguardNotificationVisibilityProviderTest extends SysuiTestCase {
when(mHighPriorityProvider.isHighPriority(parent)).thenReturn(true);
// THEN don't filter out the entry
assertFalse(mKeyguardNotificationVisibilityProvider.hideNotification(entryWithParent));
assertFalse(
mKeyguardNotificationVisibilityProvider.shouldHideNotification(entryWithParent));
// WHEN its parent doesn't exceed threshold to show on lockscreen
when(mHighPriorityProvider.isHighPriority(parent)).thenReturn(false);
@@ -218,7 +373,7 @@ public class KeyguardNotificationVisibilityProviderTest extends SysuiTestCase {
.done());
// THEN filter out the entry
assertTrue(mKeyguardNotificationVisibilityProvider.hideNotification(entryWithParent));
assertTrue(mKeyguardNotificationVisibilityProvider.shouldHideNotification(entryWithParent));
}
/**
@@ -259,4 +414,27 @@ public class KeyguardNotificationVisibilityProviderTest extends SysuiTestCase {
// notification is high priority, so it shouldn't be filtered
when(mHighPriorityProvider.isHighPriority(mEntry)).thenReturn(true);
}
}
@SysUISingleton
@Component(modules = { KeyguardNotificationVisibilityProviderModule.class })
interface TestComponent {
KeyguardNotificationVisibilityProvider getProvider();
Map<Class<?>, CoreStartable> getCoreStartables();
@Component.Factory
interface Factory {
TestComponent create(
@BindsInstance Context context,
@BindsInstance @Main Handler handler,
@BindsInstance KeyguardStateController keyguardStateController,
@BindsInstance NotificationLockscreenUserManager lockscreenUserManager,
@BindsInstance KeyguardUpdateMonitor keyguardUpdateMonitor,
@BindsInstance HighPriorityProvider highPriorityProvider,
@BindsInstance StatusBarStateController statusBarStateController,
@BindsInstance BroadcastDispatcher broadcastDispatcher,
@BindsInstance SecureSettings secureSettings,
@BindsInstance GlobalSettings globalSettings
);
}
}
}

View File

@@ -24,6 +24,7 @@ package com.android.systemui.util.mockito
*/
import org.mockito.ArgumentCaptor
import org.mockito.ArgumentMatcher
import org.mockito.Mockito
/**
@@ -43,6 +44,14 @@ fun <T> eq(obj: T): T = Mockito.eq<T>(obj)
fun <T> any(type: Class<T>): T = Mockito.any<T>(type)
inline fun <reified T> any(): T = any(T::class.java)
/**
* Returns Mockito.argThat() as nullable type to avoid java.lang.IllegalStateException when
* null is returned.
*
* Generic T is nullable because implicitly bounded by Any?.
*/
fun <T> argThat(matcher: ArgumentMatcher<T>): T = Mockito.argThat(matcher)
/**
* Kotlin type-inferred version of Mockito.nullable()
*/