Merge "[RESTRICT AUTOMERGE] Add BubbleMetadata detection to block FSI" into tm-qpr-dev
This commit is contained in:
@@ -58,6 +58,12 @@ public interface NotificationInterruptStateProvider {
|
|||||||
* FSI even while the device was unlocked.
|
* FSI even while the device was unlocked.
|
||||||
*/
|
*/
|
||||||
NO_FSI_SUPPRESSIVE_GROUP_ALERT_BEHAVIOR(false),
|
NO_FSI_SUPPRESSIVE_GROUP_ALERT_BEHAVIOR(false),
|
||||||
|
/**
|
||||||
|
* Notification should not FSI due to having suppressive BubbleMetadata. This blocks a
|
||||||
|
* potentially malicious use of flags that previously allowed apps to escalate a HUN to an
|
||||||
|
* FSI even while the device was unlocked.
|
||||||
|
*/
|
||||||
|
NO_FSI_SUPPRESSIVE_BUBBLE_METADATA(false),
|
||||||
/**
|
/**
|
||||||
* Device screen is off, so the FSI should launch.
|
* Device screen is off, so the FSI should launch.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ package com.android.systemui.statusbar.notification.interruption;
|
|||||||
|
|
||||||
import static com.android.systemui.statusbar.StatusBarState.SHADE;
|
import static com.android.systemui.statusbar.StatusBarState.SHADE;
|
||||||
import static com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProviderImpl.NotificationInterruptEvent.FSI_SUPPRESSED_NO_HUN_OR_KEYGUARD;
|
import static com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProviderImpl.NotificationInterruptEvent.FSI_SUPPRESSED_NO_HUN_OR_KEYGUARD;
|
||||||
|
import static com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProviderImpl.NotificationInterruptEvent.FSI_SUPPRESSED_SUPPRESSIVE_BUBBLE_METADATA;
|
||||||
import static com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProviderImpl.NotificationInterruptEvent.FSI_SUPPRESSED_SUPPRESSIVE_GROUP_ALERT_BEHAVIOR;
|
import static com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProviderImpl.NotificationInterruptEvent.FSI_SUPPRESSED_SUPPRESSIVE_GROUP_ALERT_BEHAVIOR;
|
||||||
import static com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProviderImpl.NotificationInterruptEvent.HUN_SNOOZE_BYPASSED_POTENTIALLY_SUPPRESSED_FSI;
|
import static com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProviderImpl.NotificationInterruptEvent.HUN_SNOOZE_BYPASSED_POTENTIALLY_SUPPRESSED_FSI;
|
||||||
|
|
||||||
@@ -80,6 +81,9 @@ public class NotificationInterruptStateProviderImpl implements NotificationInter
|
|||||||
@UiEvent(doc = "FSI suppressed for suppressive GroupAlertBehavior")
|
@UiEvent(doc = "FSI suppressed for suppressive GroupAlertBehavior")
|
||||||
FSI_SUPPRESSED_SUPPRESSIVE_GROUP_ALERT_BEHAVIOR(1235),
|
FSI_SUPPRESSED_SUPPRESSIVE_GROUP_ALERT_BEHAVIOR(1235),
|
||||||
|
|
||||||
|
@UiEvent(doc = "FSI suppressed for suppressive BubbleMetadata")
|
||||||
|
FSI_SUPPRESSED_SUPPRESSIVE_BUBBLE_METADATA(1353),
|
||||||
|
|
||||||
@UiEvent(doc = "FSI suppressed for requiring neither HUN nor keyguard")
|
@UiEvent(doc = "FSI suppressed for requiring neither HUN nor keyguard")
|
||||||
FSI_SUPPRESSED_NO_HUN_OR_KEYGUARD(1236),
|
FSI_SUPPRESSED_NO_HUN_OR_KEYGUARD(1236),
|
||||||
|
|
||||||
@@ -270,6 +274,16 @@ public class NotificationInterruptStateProviderImpl implements NotificationInter
|
|||||||
suppressedByDND);
|
suppressedByDND);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the notification has suppressive BubbleMetadata, block FSI and warn.
|
||||||
|
Notification.BubbleMetadata bubbleMetadata = sbn.getNotification().getBubbleMetadata();
|
||||||
|
if (bubbleMetadata != null && bubbleMetadata.isNotificationSuppressed()) {
|
||||||
|
// b/274759612: Detect and report an event when a notification has both an FSI and a
|
||||||
|
// suppressive BubbleMetadata, and now correctly block the FSI from firing.
|
||||||
|
return getDecisionGivenSuppression(
|
||||||
|
FullScreenIntentDecision.NO_FSI_SUPPRESSIVE_BUBBLE_METADATA,
|
||||||
|
suppressedByDND);
|
||||||
|
}
|
||||||
|
|
||||||
// If the screen is off, then launch the FullScreenIntent
|
// If the screen is off, then launch the FullScreenIntent
|
||||||
if (!mPowerManager.isInteractive()) {
|
if (!mPowerManager.isInteractive()) {
|
||||||
return getDecisionGivenSuppression(FullScreenIntentDecision.FSI_DEVICE_NOT_INTERACTIVE,
|
return getDecisionGivenSuppression(FullScreenIntentDecision.FSI_DEVICE_NOT_INTERACTIVE,
|
||||||
@@ -350,6 +364,11 @@ public class NotificationInterruptStateProviderImpl implements NotificationInter
|
|||||||
packageName);
|
packageName);
|
||||||
mLogger.logNoFullscreenWarning(entry, "GroupAlertBehavior will prevent HUN");
|
mLogger.logNoFullscreenWarning(entry, "GroupAlertBehavior will prevent HUN");
|
||||||
return;
|
return;
|
||||||
|
case NO_FSI_SUPPRESSIVE_BUBBLE_METADATA:
|
||||||
|
android.util.EventLog.writeEvent(0x534e4554, "274759612", uid, "bubbleMetadata");
|
||||||
|
mUiEventLogger.log(FSI_SUPPRESSED_SUPPRESSIVE_BUBBLE_METADATA, uid, packageName);
|
||||||
|
mLogger.logNoFullscreenWarning(entry, "BubbleMetadata may prevent HUN");
|
||||||
|
return;
|
||||||
case FSI_DEVICE_NOT_INTERACTIVE:
|
case FSI_DEVICE_NOT_INTERACTIVE:
|
||||||
mLogger.logFullscreen(entry, "Device is not interactive");
|
mLogger.logFullscreen(entry, "Device is not interactive");
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -629,6 +629,38 @@ public class NotificationInterruptStateProviderImplTest extends SysuiTestCase {
|
|||||||
assertThat(fakeUiEvent.packageName).isEqualTo(entry.getSbn().getPackageName());
|
assertThat(fakeUiEvent.packageName).isEqualTo(entry.getSbn().getPackageName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testShouldNotFullScreen_isSuppressedByBubbleMetadata_withStrictFlag() {
|
||||||
|
when(mFlags.fullScreenIntentRequiresKeyguard()).thenReturn(true);
|
||||||
|
testShouldNotFullScreen_isSuppressedByBubbleMetadata();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testShouldNotFullScreen_isSuppressedByBubbleMetadata() {
|
||||||
|
NotificationEntry entry = createFsiNotification(IMPORTANCE_HIGH, /* silenced */ false);
|
||||||
|
Notification.BubbleMetadata bubbleMetadata = new Notification.BubbleMetadata.Builder("foo")
|
||||||
|
.setSuppressNotification(true).build();
|
||||||
|
entry.getSbn().getNotification().setBubbleMetadata(bubbleMetadata);
|
||||||
|
when(mPowerManager.isInteractive()).thenReturn(false);
|
||||||
|
when(mStatusBarStateController.isDreaming()).thenReturn(true);
|
||||||
|
when(mStatusBarStateController.getState()).thenReturn(KEYGUARD);
|
||||||
|
|
||||||
|
assertThat(mNotifInterruptionStateProvider.getFullScreenIntentDecision(entry))
|
||||||
|
.isEqualTo(FullScreenIntentDecision.NO_FSI_SUPPRESSIVE_BUBBLE_METADATA);
|
||||||
|
assertThat(mNotifInterruptionStateProvider.shouldLaunchFullScreenIntentWhenAdded(entry))
|
||||||
|
.isFalse();
|
||||||
|
verify(mLogger, never()).logNoFullscreen(any(), any());
|
||||||
|
verify(mLogger).logNoFullscreenWarning(entry, "BubbleMetadata may prevent HUN");
|
||||||
|
verify(mLogger, never()).logFullscreen(any(), any());
|
||||||
|
|
||||||
|
assertThat(mUiEventLoggerFake.numLogs()).isEqualTo(1);
|
||||||
|
UiEventLoggerFake.FakeUiEvent fakeUiEvent = mUiEventLoggerFake.get(0);
|
||||||
|
assertThat(fakeUiEvent.eventId).isEqualTo(
|
||||||
|
NotificationInterruptEvent.FSI_SUPPRESSED_SUPPRESSIVE_BUBBLE_METADATA.getId());
|
||||||
|
assertThat(fakeUiEvent.uid).isEqualTo(entry.getSbn().getUid());
|
||||||
|
assertThat(fakeUiEvent.packageName).isEqualTo(entry.getSbn().getPackageName());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testShouldFullScreen_notInteractive_withStrictFlag() throws Exception {
|
public void testShouldFullScreen_notInteractive_withStrictFlag() throws Exception {
|
||||||
when(mFlags.fullScreenIntentRequiresKeyguard()).thenReturn(true);
|
when(mFlags.fullScreenIntentRequiresKeyguard()).thenReturn(true);
|
||||||
@@ -638,6 +670,9 @@ public class NotificationInterruptStateProviderImplTest extends SysuiTestCase {
|
|||||||
@Test
|
@Test
|
||||||
public void testShouldFullScreen_notInteractive() throws RemoteException {
|
public void testShouldFullScreen_notInteractive() throws RemoteException {
|
||||||
NotificationEntry entry = createFsiNotification(IMPORTANCE_HIGH, /* silenced */ false);
|
NotificationEntry entry = createFsiNotification(IMPORTANCE_HIGH, /* silenced */ false);
|
||||||
|
Notification.BubbleMetadata bubbleMetadata = new Notification.BubbleMetadata.Builder("foo")
|
||||||
|
.setSuppressNotification(false).build();
|
||||||
|
entry.getSbn().getNotification().setBubbleMetadata(bubbleMetadata);
|
||||||
when(mPowerManager.isInteractive()).thenReturn(false);
|
when(mPowerManager.isInteractive()).thenReturn(false);
|
||||||
when(mStatusBarStateController.isDreaming()).thenReturn(false);
|
when(mStatusBarStateController.isDreaming()).thenReturn(false);
|
||||||
when(mStatusBarStateController.getState()).thenReturn(SHADE);
|
when(mStatusBarStateController.getState()).thenReturn(SHADE);
|
||||||
|
|||||||
Reference in New Issue
Block a user