Merge "Register KeyguardNotifVisProvider CoreStartable" into tm-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
f0a312d294
@@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user