Fix bug where FSI decision was not logged unless FSI was launching.

* Change HeadsUpCoordinator's `onEntryAdded` logic so that `logFullScreenIntentDecision` is called unconditionally after `getFullScreenIntentDecision`.
* Change HeadsUpCoordinator's `onEntryUpdated` logic so each reconsideration can keep happening ONLY if the decision keeps being `NO_FSI_SUPPRESSED_ONLY_BY_DND`.
  * If the FSI should launch, in addition to launching it still calls `logFullScreenIntentDecision` and now also revokes the candidacy for reconsideration.
  * If the FSI should NOT launch (and the decision changed), it now calls `logFullScreenIntentDecision` and also revokes the candidacy for reconsideration.
* Fixes a bug & fragile code in `logFullScreenIntentDecision` where not all decision values were enumerated for logging.  The "human readable" string is gone, and replaced with a default case which logs the enum name.
* Adds some nullability annotations to the java interface.
  * Remove an unnecessary null check on the decision.
  * Convert an enum `.equals()` to `==`.

Bug: 265977861
Test: dumpsysui NotifInterruptLog
Test: atest HeadsUpCoordinatorTest NotificationInterruptStateProviderImplTest
Change-Id: Ie6d379008c9cd99cfcfe0f9da43e602a436a0d39
This commit is contained in:
Jeff DeCew
2023-03-09 22:12:41 +00:00
parent b457973c31
commit 4a6a45ef85
6 changed files with 248 additions and 58 deletions

View File

@@ -389,11 +389,11 @@ class HeadsUpCoordinator @Inject constructor(
// First check whether this notification should launch a full screen intent, and
// launch it if needed.
val fsiDecision = mNotificationInterruptStateProvider.getFullScreenIntentDecision(entry)
if (fsiDecision != null && fsiDecision.shouldLaunch) {
mNotificationInterruptStateProvider.logFullScreenIntentDecision(entry, fsiDecision)
mNotificationInterruptStateProvider.logFullScreenIntentDecision(entry, fsiDecision)
if (fsiDecision.shouldLaunch) {
mLaunchFullScreenIntentProvider.launchFullScreenIntent(entry)
} else if (mFlags.fsiOnDNDUpdate() &&
fsiDecision.equals(FullScreenIntentDecision.NO_FSI_SUPPRESSED_ONLY_BY_DND)) {
fsiDecision == FullScreenIntentDecision.NO_FSI_SUPPRESSED_ONLY_BY_DND) {
// If DND was the only reason this entry was suppressed, note it for potential
// reconsideration on later ranking updates.
addForFSIReconsideration(entry, mSystemClock.currentTimeMillis())
@@ -514,14 +514,24 @@ class HeadsUpCoordinator @Inject constructor(
mNotificationInterruptStateProvider.getFullScreenIntentDecision(entry)
if (decision.shouldLaunch) {
// Log both the launch of the full screen and also that this was via a
// ranking update.
mLogger.logEntryUpdatedToFullScreen(entry.key)
// ranking update, and finally revoke candidacy for FSI reconsideration
mLogger.logEntryUpdatedToFullScreen(entry.key, decision.name)
mNotificationInterruptStateProvider.logFullScreenIntentDecision(
entry, decision)
mLaunchFullScreenIntentProvider.launchFullScreenIntent(entry)
mFSIUpdateCandidates.remove(entry.key)
// if we launch the FSI then this is no longer a candidate for HUN
continue
} else if (decision == FullScreenIntentDecision.NO_FSI_SUPPRESSED_ONLY_BY_DND) {
// decision has not changed; no need to log
} else {
// some other condition is now blocking FSI; log that and revoke candidacy
// for FSI reconsideration
mLogger.logEntryDisqualifiedFromFullScreen(entry.key, decision.name)
mNotificationInterruptStateProvider.logFullScreenIntentDecision(
entry, decision)
mFSIUpdateCandidates.remove(entry.key)
}
}

View File

@@ -70,11 +70,21 @@ class HeadsUpCoordinatorLogger constructor(
})
}
fun logEntryUpdatedToFullScreen(key: String) {
fun logEntryUpdatedToFullScreen(key: String, reason: String) {
buffer.log(TAG, LogLevel.DEBUG, {
str1 = key
str2 = reason
}, {
"updating entry to launch full screen intent: $str1"
"updating entry to launch full screen intent: $str1 because $str2"
})
}
fun logEntryDisqualifiedFromFullScreen(key: String, reason: String) {
buffer.log(TAG, LogLevel.DEBUG, {
str1 = key
str2 = reason
}, {
"updated entry no longer qualifies for full screen intent: $str1 because $str2"
})
}

View File

@@ -16,6 +16,8 @@
package com.android.systemui.statusbar.notification.interruption;
import androidx.annotation.NonNull;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
/**
@@ -153,7 +155,8 @@ public interface NotificationInterruptStateProvider {
* @param entry the entry to evaluate
* @return FullScreenIntentDecision representing the decision for whether to show the intent
*/
FullScreenIntentDecision getFullScreenIntentDecision(NotificationEntry entry);
@NonNull
FullScreenIntentDecision getFullScreenIntentDecision(@NonNull NotificationEntry entry);
/**
* Write the full screen launch decision for the given entry to logs.

View File

@@ -35,6 +35,8 @@ import android.service.dreams.IDreamManager;
import android.service.notification.StatusBarNotification;
import android.util.Log;
import androidx.annotation.NonNull;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.UiEvent;
import com.android.internal.logging.UiEventLogger;
@@ -232,6 +234,7 @@ public class NotificationInterruptStateProviderImpl implements NotificationInter
// suppressor.
//
// If the entry was not suppressed by DND, just returns the given decision.
@NonNull
private FullScreenIntentDecision getDecisionGivenSuppression(FullScreenIntentDecision decision,
boolean suppressedByDND) {
if (suppressedByDND) {
@@ -243,7 +246,7 @@ public class NotificationInterruptStateProviderImpl implements NotificationInter
}
@Override
public FullScreenIntentDecision getFullScreenIntentDecision(NotificationEntry entry) {
public FullScreenIntentDecision getFullScreenIntentDecision(@NonNull NotificationEntry entry) {
if (entry.getSbn().getNotification().fullScreenIntent == null) {
if (entry.isStickyAndNotDemoted()) {
return FullScreenIntentDecision.NO_FSI_SHOW_STICKY_HUN;
@@ -336,52 +339,30 @@ public class NotificationInterruptStateProviderImpl implements NotificationInter
final int uid = entry.getSbn().getUid();
final String packageName = entry.getSbn().getPackageName();
switch (decision) {
case NO_FSI_SHOW_STICKY_HUN:
mLogger.logNoFullscreen(entry, "Permission denied, show sticky HUN");
return;
case NO_FULL_SCREEN_INTENT:
return;
case NO_FSI_SUPPRESSED_BY_DND:
case NO_FSI_SUPPRESSED_ONLY_BY_DND:
mLogger.logNoFullscreen(entry, "Suppressed by DND");
return;
case NO_FSI_NOT_IMPORTANT_ENOUGH:
mLogger.logNoFullscreen(entry, "Not important enough");
// explicitly prevent logging for this (frequent) case
return;
case NO_FSI_SUPPRESSIVE_GROUP_ALERT_BEHAVIOR:
android.util.EventLog.writeEvent(0x534e4554, "231322873", uid,
"groupAlertBehavior");
mUiEventLogger.log(FSI_SUPPRESSED_SUPPRESSIVE_GROUP_ALERT_BEHAVIOR, uid,
packageName);
mLogger.logNoFullscreenWarning(entry, "GroupAlertBehavior will prevent HUN");
return;
case FSI_DEVICE_NOT_INTERACTIVE:
mLogger.logFullscreen(entry, "Device is not interactive");
return;
case FSI_DEVICE_IS_DREAMING:
mLogger.logFullscreen(entry, "Device is dreaming");
return;
case FSI_KEYGUARD_SHOWING:
mLogger.logFullscreen(entry, "Keyguard is showing");
return;
case NO_FSI_EXPECTED_TO_HUN:
mLogger.logNoFullscreen(entry, "Expected to HUN");
return;
case FSI_KEYGUARD_OCCLUDED:
mLogger.logFullscreen(entry,
"Expected not to HUN while keyguard occluded");
return;
case FSI_LOCKED_SHADE:
mLogger.logFullscreen(entry, "Keyguard is showing and not occluded");
mLogger.logNoFullscreenWarning(entry,
decision + ": GroupAlertBehavior will prevent HUN");
return;
case NO_FSI_NO_HUN_OR_KEYGUARD:
android.util.EventLog.writeEvent(0x534e4554, "231322873", uid,
"no hun or keyguard");
mUiEventLogger.log(FSI_SUPPRESSED_NO_HUN_OR_KEYGUARD, uid, packageName);
mLogger.logNoFullscreenWarning(entry, "Expected not to HUN while not on keyguard");
mLogger.logNoFullscreenWarning(entry,
decision + ": Expected not to HUN while not on keyguard");
return;
case FSI_EXPECTED_NOT_TO_HUN:
mLogger.logFullscreen(entry, "Expected not to HUN");
default:
if (decision.shouldLaunch) {
mLogger.logFullscreen(entry, decision.name());
} else {
mLogger.logNoFullscreen(entry, decision.name());
}
}
}

View File

@@ -22,6 +22,7 @@ import android.testing.TestableLooper.RunWithLooper
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.dump.logcatLogBuffer
import com.android.systemui.flags.Flags
import com.android.systemui.statusbar.NotificationRemoteInputManager
import com.android.systemui.statusbar.notification.NotifPipelineFlags
import com.android.systemui.statusbar.notification.collection.GroupEntryBuilder
@@ -58,6 +59,7 @@ import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentMatchers.anyString
import org.mockito.BDDMockito.clearInvocations
import org.mockito.BDDMockito.given
import org.mockito.Mockito.never
import org.mockito.Mockito.times
@@ -166,6 +168,12 @@ class HeadsUpCoordinatorTest : SysuiTestCase() {
mGroupChild1 = mHelper.createChildNotification(GROUP_ALERT_ALL, 1, "child", 350)
mGroupChild2 = mHelper.createChildNotification(GROUP_ALERT_ALL, 2, "child", 250)
mGroupChild3 = mHelper.createChildNotification(GROUP_ALERT_ALL, 3, "child", 150)
// Set the default FSI decision
setShouldFullScreen(any(), FullScreenIntentDecision.NO_FULL_SCREEN_INTENT)
// Run tests with default feature flag state
whenever(mFlags.fsiOnDNDUpdate()).thenReturn(Flags.FSI_ON_DND_UPDATE.default)
}
@Test
@@ -809,6 +817,39 @@ class HeadsUpCoordinatorTest : SysuiTestCase() {
verify(mHeadsUpManager, never()).showNotification(any())
}
@Test
fun onEntryAdded_whenLaunchingFSI_doesLogDecision() {
// GIVEN A new notification can FSI
setShouldFullScreen(mEntry, FullScreenIntentDecision.FSI_DEVICE_NOT_INTERACTIVE)
mCollectionListener.onEntryAdded(mEntry)
verify(mLaunchFullScreenIntentProvider).launchFullScreenIntent(mEntry)
verify(mNotificationInterruptStateProvider).logFullScreenIntentDecision(
mEntry, FullScreenIntentDecision.FSI_DEVICE_NOT_INTERACTIVE)
}
@Test
fun onEntryAdded_whenNotLaunchingFSI_doesLogDecision() {
// GIVEN A new notification can't FSI
setShouldFullScreen(mEntry, FullScreenIntentDecision.NO_FULL_SCREEN_INTENT)
mCollectionListener.onEntryAdded(mEntry)
verify(mLaunchFullScreenIntentProvider, never()).launchFullScreenIntent(any())
verify(mNotificationInterruptStateProvider).logFullScreenIntentDecision(
mEntry, FullScreenIntentDecision.NO_FULL_SCREEN_INTENT)
}
@Test
fun onEntryAdded_whenNotLaunchingFSIBecauseOfDnd_doesLogDecision() {
// GIVEN A new notification can't FSI because of DND
setShouldFullScreen(mEntry, FullScreenIntentDecision.NO_FSI_SUPPRESSED_ONLY_BY_DND)
mCollectionListener.onEntryAdded(mEntry)
verify(mLaunchFullScreenIntentProvider, never()).launchFullScreenIntent(any())
verify(mNotificationInterruptStateProvider).logFullScreenIntentDecision(
mEntry, FullScreenIntentDecision.NO_FSI_SUPPRESSED_ONLY_BY_DND)
}
@Test
fun testOnRankingApplied_noFSIOnUpdateWhenFlagOff() {
// Ensure the feature flag is off
@@ -818,13 +859,22 @@ class HeadsUpCoordinatorTest : SysuiTestCase() {
setShouldFullScreen(mEntry, FullScreenIntentDecision.NO_FSI_SUPPRESSED_ONLY_BY_DND)
mCollectionListener.onEntryAdded(mEntry)
// Verify that this causes a log
verify(mNotificationInterruptStateProvider).logFullScreenIntentDecision(
mEntry, FullScreenIntentDecision.NO_FSI_SUPPRESSED_ONLY_BY_DND)
clearInvocations(mNotificationInterruptStateProvider)
// and it is then updated to allow full screen
setShouldFullScreen(mEntry, FullScreenIntentDecision.FSI_DEVICE_NOT_INTERACTIVE)
whenever(mNotifPipeline.allNotifs).thenReturn(listOf(mEntry))
mCollectionListener.onRankingApplied()
// THEN it should not full screen because the feature is off
verify(mLaunchFullScreenIntentProvider, never()).launchFullScreenIntent(mEntry)
verify(mLaunchFullScreenIntentProvider, never()).launchFullScreenIntent(any())
// VERIFY that no additional logging happens either
verify(mNotificationInterruptStateProvider, never())
.logFullScreenIntentDecision(any(), any())
}
@Test
@@ -836,8 +886,11 @@ class HeadsUpCoordinatorTest : SysuiTestCase() {
setShouldFullScreen(mEntry, FullScreenIntentDecision.NO_FSI_SUPPRESSED_ONLY_BY_DND)
mCollectionListener.onEntryAdded(mEntry)
// at this point, it should not have full screened
verify(mLaunchFullScreenIntentProvider, never()).launchFullScreenIntent(mEntry)
// at this point, it should not have full screened, but should have logged
verify(mLaunchFullScreenIntentProvider, never()).launchFullScreenIntent(any())
verify(mNotificationInterruptStateProvider).logFullScreenIntentDecision(mEntry,
FullScreenIntentDecision.NO_FSI_SUPPRESSED_ONLY_BY_DND)
clearInvocations(mNotificationInterruptStateProvider)
// and it is then updated to allow full screen AND HUN
setShouldFullScreen(mEntry, FullScreenIntentDecision.FSI_DEVICE_NOT_INTERACTIVE)
@@ -847,10 +900,110 @@ class HeadsUpCoordinatorTest : SysuiTestCase() {
mBeforeTransformGroupsListener.onBeforeTransformGroups(listOf(mEntry))
mBeforeFinalizeFilterListener.onBeforeFinalizeFilter(listOf(mEntry))
// THEN it should full screen but it should NOT HUN
// THEN it should full screen and log but it should NOT HUN
verify(mLaunchFullScreenIntentProvider).launchFullScreenIntent(mEntry)
verify(mHeadsUpViewBinder, never()).bindHeadsUpView(any(), any())
verify(mHeadsUpManager, never()).showNotification(any())
verify(mNotificationInterruptStateProvider).logFullScreenIntentDecision(mEntry,
FullScreenIntentDecision.FSI_DEVICE_NOT_INTERACTIVE)
clearInvocations(mNotificationInterruptStateProvider)
// WHEN ranking updates again and the pipeline reruns
clearInvocations(mLaunchFullScreenIntentProvider)
mCollectionListener.onRankingApplied()
mBeforeTransformGroupsListener.onBeforeTransformGroups(listOf(mEntry))
mBeforeFinalizeFilterListener.onBeforeFinalizeFilter(listOf(mEntry))
// VERIFY that the FSI does not launch again or log
verify(mLaunchFullScreenIntentProvider, never()).launchFullScreenIntent(any())
verify(mNotificationInterruptStateProvider, never())
.logFullScreenIntentDecision(any(), any())
}
@Test
fun testOnRankingApplied_withOnlyDndSuppressionAllowsFsiLater() {
// Turn on the feature
whenever(mFlags.fsiOnDNDUpdate()).thenReturn(true)
// GIVEN that mEntry was previously suppressed from full-screen only by DND
setShouldFullScreen(mEntry, FullScreenIntentDecision.NO_FSI_SUPPRESSED_ONLY_BY_DND)
mCollectionListener.onEntryAdded(mEntry)
// at this point, it should not have full screened, but should have logged
verify(mLaunchFullScreenIntentProvider, never()).launchFullScreenIntent(any())
verify(mNotificationInterruptStateProvider).logFullScreenIntentDecision(mEntry,
FullScreenIntentDecision.NO_FSI_SUPPRESSED_ONLY_BY_DND)
clearInvocations(mNotificationInterruptStateProvider)
// ranking is applied with only DND blocking FSI
setShouldFullScreen(mEntry, FullScreenIntentDecision.NO_FSI_SUPPRESSED_ONLY_BY_DND)
mCollectionListener.onRankingApplied()
mBeforeTransformGroupsListener.onBeforeTransformGroups(listOf(mEntry))
mBeforeFinalizeFilterListener.onBeforeFinalizeFilter(listOf(mEntry))
// THEN it should still not yet full screen or HUN
verify(mLaunchFullScreenIntentProvider, never()).launchFullScreenIntent(any())
verify(mHeadsUpViewBinder, never()).bindHeadsUpView(any(), any())
verify(mHeadsUpManager, never()).showNotification(any())
// Same decision as before; is not logged
verify(mNotificationInterruptStateProvider, never())
.logFullScreenIntentDecision(any(), any())
clearInvocations(mNotificationInterruptStateProvider)
// and it is then updated to allow full screen AND HUN
setShouldFullScreen(mEntry, FullScreenIntentDecision.FSI_DEVICE_NOT_INTERACTIVE)
setShouldHeadsUp(mEntry)
whenever(mNotifPipeline.allNotifs).thenReturn(listOf(mEntry))
mCollectionListener.onRankingApplied()
mBeforeTransformGroupsListener.onBeforeTransformGroups(listOf(mEntry))
mBeforeFinalizeFilterListener.onBeforeFinalizeFilter(listOf(mEntry))
// THEN it should full screen and log but it should NOT HUN
verify(mLaunchFullScreenIntentProvider).launchFullScreenIntent(mEntry)
verify(mHeadsUpViewBinder, never()).bindHeadsUpView(any(), any())
verify(mHeadsUpManager, never()).showNotification(any())
verify(mNotificationInterruptStateProvider).logFullScreenIntentDecision(mEntry,
FullScreenIntentDecision.FSI_DEVICE_NOT_INTERACTIVE)
clearInvocations(mNotificationInterruptStateProvider)
}
@Test
fun testOnRankingApplied_newNonFullScreenAnswerInvalidatesCandidate() {
// Turn on the feature
whenever(mFlags.fsiOnDNDUpdate()).thenReturn(true)
// GIVEN that mEntry was previously suppressed from full-screen only by DND
whenever(mNotifPipeline.allNotifs).thenReturn(listOf(mEntry))
setShouldFullScreen(mEntry, FullScreenIntentDecision.NO_FSI_SUPPRESSED_ONLY_BY_DND)
mCollectionListener.onEntryAdded(mEntry)
// at this point, it should not have full screened
verify(mLaunchFullScreenIntentProvider, never()).launchFullScreenIntent(mEntry)
// now some other condition blocks FSI in addition to DND
setShouldFullScreen(mEntry, FullScreenIntentDecision.NO_FSI_SUPPRESSED_BY_DND)
mCollectionListener.onRankingApplied()
mBeforeTransformGroupsListener.onBeforeTransformGroups(listOf(mEntry))
mBeforeFinalizeFilterListener.onBeforeFinalizeFilter(listOf(mEntry))
// THEN it should NOT full screen or HUN
verify(mLaunchFullScreenIntentProvider, never()).launchFullScreenIntent(any())
verify(mHeadsUpViewBinder, never()).bindHeadsUpView(any(), any())
verify(mHeadsUpManager, never()).showNotification(any())
// NOW the DND logic changes and FSI and HUN are available
clearInvocations(mLaunchFullScreenIntentProvider)
setShouldFullScreen(mEntry, FullScreenIntentDecision.FSI_DEVICE_NOT_INTERACTIVE)
setShouldHeadsUp(mEntry)
mCollectionListener.onRankingApplied()
mBeforeTransformGroupsListener.onBeforeTransformGroups(listOf(mEntry))
mBeforeFinalizeFilterListener.onBeforeFinalizeFilter(listOf(mEntry))
// VERIFY that the FSI didn't happen, but that we do HUN
verify(mLaunchFullScreenIntentProvider, never()).launchFullScreenIntent(any())
finishBind(mEntry)
verify(mHeadsUpManager).showNotification(mEntry)
}
@Test

View File

@@ -36,9 +36,12 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.contains;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
import android.app.ActivityManager;
@@ -76,6 +79,10 @@ import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
/**
* Tests for the interruption state provider which understands whether the system & notification
* is in a state allowing a particular notification to hun, pulse, or bubble.
@@ -560,7 +567,7 @@ public class NotificationInterruptStateProviderImplTest extends SysuiTestCase {
.isFalse();
verify(mLogger, never()).logFullscreen(any(), any());
verify(mLogger, never()).logNoFullscreenWarning(any(), any());
verify(mLogger).logNoFullscreen(entry, "Suppressed by DND");
verify(mLogger).logNoFullscreen(entry, "NO_FSI_SUPPRESSED_ONLY_BY_DND");
}
@Test
@@ -579,7 +586,7 @@ public class NotificationInterruptStateProviderImplTest extends SysuiTestCase {
.isFalse();
verify(mLogger, never()).logFullscreen(any(), any());
verify(mLogger, never()).logNoFullscreenWarning(any(), any());
verify(mLogger).logNoFullscreen(entry, "Suppressed by DND");
verify(mLogger).logNoFullscreen(entry, "NO_FSI_SUPPRESSED_BY_DND");
}
@Test
@@ -599,7 +606,7 @@ public class NotificationInterruptStateProviderImplTest extends SysuiTestCase {
.isEqualTo(FullScreenIntentDecision.NO_FSI_NOT_IMPORTANT_ENOUGH);
assertThat(mNotifInterruptionStateProvider.shouldLaunchFullScreenIntentWhenAdded(entry))
.isFalse();
verify(mLogger).logNoFullscreen(entry, "Not important enough");
verify(mLogger).logNoFullscreen(entry, "NO_FSI_NOT_IMPORTANT_ENOUGH");
verify(mLogger, never()).logNoFullscreenWarning(any(), any());
verify(mLogger, never()).logFullscreen(any(), any());
}
@@ -622,7 +629,8 @@ public class NotificationInterruptStateProviderImplTest extends SysuiTestCase {
assertThat(mNotifInterruptionStateProvider.shouldLaunchFullScreenIntentWhenAdded(entry))
.isFalse();
verify(mLogger, never()).logNoFullscreen(any(), any());
verify(mLogger).logNoFullscreenWarning(entry, "GroupAlertBehavior will prevent HUN");
verify(mLogger).logNoFullscreenWarning(entry,
"NO_FSI_SUPPRESSIVE_GROUP_ALERT_BEHAVIOR: GroupAlertBehavior will prevent HUN");
verify(mLogger, never()).logFullscreen(any(), any());
assertThat(mUiEventLoggerFake.numLogs()).isEqualTo(1);
@@ -652,7 +660,7 @@ public class NotificationInterruptStateProviderImplTest extends SysuiTestCase {
.isTrue();
verify(mLogger, never()).logNoFullscreen(any(), any());
verify(mLogger, never()).logNoFullscreenWarning(any(), any());
verify(mLogger).logFullscreen(entry, "Device is not interactive");
verify(mLogger).logFullscreen(entry, "FSI_DEVICE_NOT_INTERACTIVE");
}
@Test
@@ -674,7 +682,7 @@ public class NotificationInterruptStateProviderImplTest extends SysuiTestCase {
.isTrue();
verify(mLogger, never()).logNoFullscreen(any(), any());
verify(mLogger, never()).logNoFullscreenWarning(any(), any());
verify(mLogger).logFullscreen(entry, "Device is dreaming");
verify(mLogger).logFullscreen(entry, "FSI_DEVICE_IS_DREAMING");
}
@Test
@@ -696,7 +704,7 @@ public class NotificationInterruptStateProviderImplTest extends SysuiTestCase {
.isTrue();
verify(mLogger, never()).logNoFullscreen(any(), any());
verify(mLogger, never()).logNoFullscreenWarning(any(), any());
verify(mLogger).logFullscreen(entry, "Keyguard is showing");
verify(mLogger).logFullscreen(entry, "FSI_KEYGUARD_SHOWING");
}
@Test
@@ -717,7 +725,7 @@ public class NotificationInterruptStateProviderImplTest extends SysuiTestCase {
.isEqualTo(FullScreenIntentDecision.NO_FSI_EXPECTED_TO_HUN);
assertThat(mNotifInterruptionStateProvider.shouldLaunchFullScreenIntentWhenAdded(entry))
.isFalse();
verify(mLogger).logNoFullscreen(entry, "Expected to HUN");
verify(mLogger).logNoFullscreen(entry, "NO_FSI_EXPECTED_TO_HUN");
verify(mLogger, never()).logNoFullscreenWarning(any(), any());
verify(mLogger, never()).logFullscreen(any(), any());
}
@@ -737,7 +745,7 @@ public class NotificationInterruptStateProviderImplTest extends SysuiTestCase {
.isTrue();
verify(mLogger, never()).logNoFullscreen(any(), any());
verify(mLogger, never()).logNoFullscreenWarning(any(), any());
verify(mLogger).logFullscreen(entry, "Expected not to HUN");
verify(mLogger).logFullscreen(entry, "FSI_EXPECTED_NOT_TO_HUN");
}
@Test
@@ -756,7 +764,7 @@ public class NotificationInterruptStateProviderImplTest extends SysuiTestCase {
.isEqualTo(FullScreenIntentDecision.NO_FSI_EXPECTED_TO_HUN);
assertThat(mNotifInterruptionStateProvider.shouldLaunchFullScreenIntentWhenAdded(entry))
.isFalse();
verify(mLogger).logNoFullscreen(entry, "Expected to HUN");
verify(mLogger).logNoFullscreen(entry, "NO_FSI_EXPECTED_TO_HUN");
verify(mLogger, never()).logNoFullscreenWarning(any(), any());
verify(mLogger, never()).logFullscreen(any(), any());
}
@@ -802,7 +810,7 @@ public class NotificationInterruptStateProviderImplTest extends SysuiTestCase {
.isEqualTo(FullScreenIntentDecision.NO_FSI_EXPECTED_TO_HUN);
assertThat(mNotifInterruptionStateProvider.shouldLaunchFullScreenIntentWhenAdded(entry))
.isFalse();
verify(mLogger).logNoFullscreen(entry, "Expected to HUN");
verify(mLogger).logNoFullscreen(entry, "NO_FSI_EXPECTED_TO_HUN");
verify(mLogger, never()).logNoFullscreenWarning(any(), any());
verify(mLogger, never()).logFullscreen(any(), any());
}
@@ -848,11 +856,36 @@ public class NotificationInterruptStateProviderImplTest extends SysuiTestCase {
.isEqualTo(FullScreenIntentDecision.NO_FSI_EXPECTED_TO_HUN);
assertThat(mNotifInterruptionStateProvider.shouldLaunchFullScreenIntentWhenAdded(entry))
.isFalse();
verify(mLogger).logNoFullscreen(entry, "Expected to HUN");
verify(mLogger).logNoFullscreen(entry, "NO_FSI_EXPECTED_TO_HUN");
verify(mLogger, never()).logNoFullscreenWarning(any(), any());
verify(mLogger, never()).logFullscreen(any(), any());
}
@Test
public void logFullScreenIntentDecision_shouldAlmostAlwaysLogOneTime() {
NotificationEntry entry = createFsiNotification(IMPORTANCE_HIGH, /* silenced */ false);
Set<FullScreenIntentDecision> warnings = new HashSet<>(Arrays.asList(
FullScreenIntentDecision.NO_FSI_SUPPRESSIVE_GROUP_ALERT_BEHAVIOR,
FullScreenIntentDecision.NO_FSI_NO_HUN_OR_KEYGUARD
));
for (FullScreenIntentDecision decision : FullScreenIntentDecision.values()) {
clearInvocations(mLogger);
boolean expectedToLog = decision != FullScreenIntentDecision.NO_FULL_SCREEN_INTENT;
boolean isWarning = warnings.contains(decision);
mNotifInterruptionStateProvider.logFullScreenIntentDecision(entry, decision);
if (decision.shouldLaunch) {
verify(mLogger).logFullscreen(eq(entry), contains(decision.name()));
} else if (expectedToLog) {
if (isWarning) {
verify(mLogger).logNoFullscreenWarning(eq(entry), contains(decision.name()));
} else {
verify(mLogger).logNoFullscreen(eq(entry), contains(decision.name()));
}
}
verifyNoMoreInteractions(mLogger);
}
}
@Test
public void testShouldHeadsUp_snoozed_unlocked_withStrictRules() throws Exception {
when(mFlags.fullScreenIntentRequiresKeyguard()).thenReturn(true);