Skip to content

Commit 433ded7

Browse files
Jeff DeCewofficialputuid
authored andcommitted
Block FullScreenIntent while device is in use if notification has a silencing GroupAlertBehavior.
Bug: 231322873 Test: atest NotificationInterruptStateProviderImplTest Merged-In: Id82d20c9f1f2001400871b5381f52b40fbdf81c5 Change-Id: Id82d20c9f1f2001400871b5381f52b40fbdf81c5 (cherry picked from commit 09761a9) Merged-In: Id82d20c9f1f2001400871b5381f52b40fbdf81c5
1 parent 0909fce commit 433ded7

2 files changed

Lines changed: 193 additions & 10 deletions

File tree

packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImpl.java

Lines changed: 81 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -201,9 +201,86 @@ public boolean shouldHeadsUp(NotificationEntry entry) {
201201
*/
202202
@Override
203203
public boolean shouldLaunchFullScreenIntentWhenAdded(NotificationEntry entry) {
204-
return entry.getSbn().getNotification().fullScreenIntent != null
205-
&& (!shouldHeadsUp(entry)
206-
|| mStatusBarStateController.getState() == StatusBarState.KEYGUARD);
204+
if (entry.getSbn().getNotification().fullScreenIntent == null) {
205+
return false;
206+
}
207+
208+
// Never show FSI when suppressed by DND
209+
if (entry.shouldSuppressFullScreenIntent()) {
210+
if (DEBUG) {
211+
Log.d(TAG, "No FullScreenIntent: Suppressed by DND: " + entry.getKey());
212+
}
213+
return false;
214+
}
215+
216+
// Never show FSI if importance is not HIGH
217+
if (entry.getImportance() < NotificationManager.IMPORTANCE_HIGH) {
218+
if (DEBUG) {
219+
Log.d(TAG, "No FullScreenIntent: Not important enough: " + entry.getKey());
220+
}
221+
return false;
222+
}
223+
224+
// If the notification has suppressive GroupAlertBehavior, block FSI and warn.
225+
StatusBarNotification sbn = entry.getSbn();
226+
if (sbn.isGroup() && sbn.getNotification().suppressAlertingDueToGrouping()) {
227+
// b/231322873: Detect and report an event when a notification has both an FSI and a
228+
// suppressive groupAlertBehavior, and now correctly block the FSI from firing.
229+
final int uid = entry.getSbn().getUid();
230+
android.util.EventLog.writeEvent(0x534e4554, "231322873", uid, "groupAlertBehavior");
231+
if (DEBUG) {
232+
Log.w(TAG, "No FullScreenIntent: WARNING: GroupAlertBehavior will prevent HUN: "
233+
+ entry.getKey());
234+
}
235+
return false;
236+
}
237+
238+
// If the screen is off, then launch the FullScreenIntent
239+
if (!mPowerManager.isInteractive()) {
240+
if (DEBUG) {
241+
Log.d(TAG, "FullScreenIntent: Device is not interactive: " + entry.getKey());
242+
}
243+
return true;
244+
}
245+
246+
// If the device is currently dreaming, then launch the FullScreenIntent
247+
if (isDreaming()) {
248+
if (DEBUG) {
249+
Log.d(TAG, "FullScreenIntent: Device is dreaming: " + entry.getKey());
250+
}
251+
return true;
252+
}
253+
254+
// If the keyguard is showing, then launch the FullScreenIntent
255+
if (mStatusBarStateController.getState() == StatusBarState.KEYGUARD) {
256+
if (DEBUG) {
257+
Log.d(TAG, "FullScreenIntent: Keyguard is showing: " + entry.getKey());
258+
}
259+
return true;
260+
}
261+
262+
// If the notification should HUN, then we don't need FSI
263+
if (shouldHeadsUp(entry)) {
264+
if (DEBUG) {
265+
Log.d(TAG, "No FullScreenIntent: Expected to HUN: " + entry.getKey());
266+
}
267+
return false;
268+
}
269+
270+
// If the notification won't HUN for some other reason (DND/snooze/etc), launch FSI.
271+
if (DEBUG) {
272+
Log.d(TAG, "FullScreenIntent: Expected not to HUN: " + entry.getKey());
273+
}
274+
return true;
275+
}
276+
277+
private boolean isDreaming() {
278+
try {
279+
return mDreamManager.isDreaming();
280+
} catch (RemoteException e) {
281+
Log.e(TAG, "Failed to query dream manager.", e);
282+
return false;
283+
}
207284
}
208285

209286
private boolean shouldHeadsUpWhenAwake(NotificationEntry entry) {
@@ -280,13 +357,7 @@ private boolean shouldHeadsUpWhenAwake(NotificationEntry entry) {
280357
return false;
281358
}
282359

283-
boolean isDreaming = false;
284-
try {
285-
isDreaming = mDreamManager.isDreaming();
286-
} catch (RemoteException e) {
287-
Log.e(TAG, "Failed to query dream manager.", e);
288-
}
289-
boolean inUse = mPowerManager.isScreenOn() && !isDreaming;
360+
boolean inUse = mPowerManager.isScreenOn() && !isDreaming();
290361

291362
if (!inUse) {
292363
if (DEBUG_HEADS_UP) {

packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImplTest.java

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK;
2525

2626
import static com.android.systemui.statusbar.NotificationEntryHelper.modifyRanking;
27+
import static com.android.systemui.statusbar.StatusBarState.KEYGUARD;
2728
import static com.android.systemui.statusbar.StatusBarState.SHADE;
2829

2930
import static com.google.common.truth.Truth.assertThat;
@@ -84,6 +85,8 @@ public class NotificationInterruptStateProviderImplTest extends SysuiTestCase {
8485
BatteryController mBatteryController;
8586
@Mock
8687
Handler mMockHandler;
88+
@Mock
89+
PendingIntent mPendingIntent;
8790

8891
private NotificationInterruptStateProviderImpl mNotifInterruptionStateProvider;
8992

@@ -399,6 +402,97 @@ public void testShouldNotHeadsUp_justLaunchedFullscreen() {
399402
assertThat(mNotifInterruptionStateProvider.shouldHeadsUp(entry)).isFalse();
400403
}
401404

405+
@Test
406+
public void testShouldNotFullScreen_notPendingIntent() throws RemoteException {
407+
NotificationEntry entry = createNotification(IMPORTANCE_HIGH);
408+
when(mPowerManager.isInteractive()).thenReturn(true);
409+
when(mDreamManager.isDreaming()).thenReturn(false);
410+
when(mStatusBarStateController.getState()).thenReturn(SHADE);
411+
412+
assertThat(mNotifInterruptionStateProvider.shouldLaunchFullScreenIntentWhenAdded(entry))
413+
.isFalse();
414+
}
415+
416+
@Test
417+
public void testShouldNotFullScreen_notHighImportance() throws RemoteException {
418+
NotificationEntry entry = createFsiNotification(IMPORTANCE_DEFAULT, /* silenced */ false);
419+
when(mPowerManager.isInteractive()).thenReturn(true);
420+
when(mDreamManager.isDreaming()).thenReturn(false);
421+
when(mStatusBarStateController.getState()).thenReturn(SHADE);
422+
423+
assertThat(mNotifInterruptionStateProvider.shouldLaunchFullScreenIntentWhenAdded(entry))
424+
.isFalse();
425+
}
426+
427+
@Test
428+
public void testShouldNotFullScreen_isGroupAlertSilenced() throws RemoteException {
429+
NotificationEntry entry = createFsiNotification(IMPORTANCE_HIGH, /* silenced */ true);
430+
when(mPowerManager.isInteractive()).thenReturn(false);
431+
when(mDreamManager.isDreaming()).thenReturn(true);
432+
when(mStatusBarStateController.getState()).thenReturn(KEYGUARD);
433+
434+
assertThat(mNotifInterruptionStateProvider.shouldLaunchFullScreenIntentWhenAdded(entry))
435+
.isFalse();
436+
}
437+
438+
@Test
439+
public void testShouldFullScreen_notInteractive() throws RemoteException {
440+
NotificationEntry entry = createFsiNotification(IMPORTANCE_HIGH, /* silenced */ false);
441+
when(mPowerManager.isInteractive()).thenReturn(false);
442+
when(mDreamManager.isDreaming()).thenReturn(false);
443+
when(mStatusBarStateController.getState()).thenReturn(SHADE);
444+
445+
assertThat(mNotifInterruptionStateProvider.shouldLaunchFullScreenIntentWhenAdded(entry))
446+
.isTrue();
447+
}
448+
449+
@Test
450+
public void testShouldFullScreen_isDreaming() throws RemoteException {
451+
NotificationEntry entry = createFsiNotification(IMPORTANCE_HIGH, /* silenced */ false);
452+
when(mPowerManager.isInteractive()).thenReturn(true);
453+
when(mDreamManager.isDreaming()).thenReturn(true);
454+
when(mStatusBarStateController.getState()).thenReturn(SHADE);
455+
456+
assertThat(mNotifInterruptionStateProvider.shouldLaunchFullScreenIntentWhenAdded(entry))
457+
.isTrue();
458+
}
459+
460+
@Test
461+
public void testShouldFullScreen_onKeyguard() throws RemoteException {
462+
NotificationEntry entry = createFsiNotification(IMPORTANCE_HIGH, /* silenced */ false);
463+
when(mPowerManager.isInteractive()).thenReturn(true);
464+
when(mDreamManager.isDreaming()).thenReturn(false);
465+
when(mStatusBarStateController.getState()).thenReturn(KEYGUARD);
466+
467+
assertThat(mNotifInterruptionStateProvider.shouldLaunchFullScreenIntentWhenAdded(entry))
468+
.isTrue();
469+
}
470+
471+
@Test
472+
public void testShouldNotFullScreen_willHun() throws RemoteException {
473+
NotificationEntry entry = createFsiNotification(IMPORTANCE_HIGH, /* silenced */ false);
474+
when(mPowerManager.isInteractive()).thenReturn(true);
475+
when(mPowerManager.isScreenOn()).thenReturn(true);
476+
when(mDreamManager.isDreaming()).thenReturn(false);
477+
when(mStatusBarStateController.getState()).thenReturn(SHADE);
478+
479+
assertThat(mNotifInterruptionStateProvider.shouldLaunchFullScreenIntentWhenAdded(entry))
480+
.isFalse();
481+
}
482+
483+
@Test
484+
public void testShouldFullScreen_packageSnoozed() throws RemoteException {
485+
NotificationEntry entry = createFsiNotification(IMPORTANCE_HIGH, /* silenced */ false);
486+
when(mPowerManager.isInteractive()).thenReturn(true);
487+
when(mPowerManager.isScreenOn()).thenReturn(true);
488+
when(mDreamManager.isDreaming()).thenReturn(false);
489+
when(mStatusBarStateController.getState()).thenReturn(SHADE);
490+
when(mHeadsUpManager.isSnoozed("a")).thenReturn(true);
491+
492+
assertThat(mNotifInterruptionStateProvider.shouldLaunchFullScreenIntentWhenAdded(entry))
493+
.isTrue();
494+
}
495+
402496
/**
403497
* Bubbles can happen.
404498
*/
@@ -502,6 +596,10 @@ private NotificationEntry createNotification(int importance) {
502596
.setContentText("content text")
503597
.build();
504598

599+
return createNotification(importance, n);
600+
}
601+
602+
private NotificationEntry createNotification(int importance, Notification n) {
505603
return new NotificationEntryBuilder()
506604
.setPkg("a")
507605
.setOpPkg("a")
@@ -511,6 +609,20 @@ private NotificationEntry createNotification(int importance) {
511609
.build();
512610
}
513611

612+
private NotificationEntry createFsiNotification(int importance, boolean silent) {
613+
Notification n = new Notification.Builder(getContext(), "a")
614+
.setContentTitle("title")
615+
.setContentText("content text")
616+
.setFullScreenIntent(mPendingIntent, true)
617+
.setGroup("fsi")
618+
.setGroupAlertBehavior(silent
619+
? Notification.GROUP_ALERT_SUMMARY
620+
: Notification.GROUP_ALERT_ALL)
621+
.build();
622+
623+
return createNotification(importance, n);
624+
}
625+
514626
private final NotificationInterruptSuppressor
515627
mSuppressAwakeHeadsUp =
516628
new NotificationInterruptSuppressor() {

0 commit comments

Comments
 (0)