Merge "Make bubble flag removals from notification delegate (sysui) sticky" into rvc-dev am: b68f9f985f
Change-Id: Ib2bee30e4acf9f860e325c3589b1806a000b4d06
This commit is contained in:
@@ -76,7 +76,8 @@ public class BubbleExtractor implements NotificationSignalExtractor {
|
||||
record.setAllowBubble(appCanShowBubble);
|
||||
}
|
||||
}
|
||||
final boolean applyFlag = mBubbleChecker.isNotificationAppropriateToBubble(record);
|
||||
final boolean applyFlag = mBubbleChecker.isNotificationAppropriateToBubble(record)
|
||||
&& !record.isFlagBubbleRemoved();
|
||||
if (applyFlag) {
|
||||
record.getNotification().flags |= FLAG_BUBBLE;
|
||||
} else {
|
||||
|
||||
@@ -1214,10 +1214,12 @@ public class NotificationManagerService extends SystemService {
|
||||
// apps querying noMan will know that their notification is not showing
|
||||
// as a bubble.
|
||||
r.getNotification().flags &= ~FLAG_BUBBLE;
|
||||
r.setFlagBubbleRemoved(true);
|
||||
} else {
|
||||
// Enqueue will trigger resort & if the flag is allowed to be true it'll
|
||||
// be applied there.
|
||||
r.getNotification().flags |= FLAG_ONLY_ALERT_ONCE;
|
||||
r.setFlagBubbleRemoved(false);
|
||||
mHandler.post(new EnqueueNotificationRunnable(r.getUser().getIdentifier(),
|
||||
r, isAppForeground));
|
||||
}
|
||||
@@ -5637,6 +5639,7 @@ public class NotificationManagerService extends SystemService {
|
||||
final NotificationRecord r = new NotificationRecord(getContext(), n, channel);
|
||||
r.setIsAppImportanceLocked(mPreferencesHelper.getIsAppImportanceLocked(pkg, callingUid));
|
||||
r.setPostSilently(postSilently);
|
||||
r.setFlagBubbleRemoved(false);
|
||||
|
||||
if ((notification.flags & Notification.FLAG_FOREGROUND_SERVICE) != 0) {
|
||||
final boolean fgServiceShown = channel.isFgServiceShown();
|
||||
|
||||
@@ -187,6 +187,7 @@ public final class NotificationRecord {
|
||||
private boolean mSuggestionsGeneratedByAssistant;
|
||||
private boolean mEditChoicesBeforeSending;
|
||||
private boolean mHasSeenSmartReplies;
|
||||
private boolean mFlagBubbleRemoved;
|
||||
private boolean mPostSilently;
|
||||
/**
|
||||
* Whether this notification (and its channels) should be considered user locked. Used in
|
||||
@@ -1201,6 +1202,19 @@ public final class NotificationRecord {
|
||||
return stats.hasBeenVisiblyExpanded();
|
||||
}
|
||||
|
||||
/**
|
||||
* When the bubble state on a notif changes due to user action (e.g. dismiss a bubble) then
|
||||
* this value is set until an update or bubble change event due to user action (e.g. create
|
||||
* bubble from sysui)
|
||||
**/
|
||||
public boolean isFlagBubbleRemoved() {
|
||||
return mFlagBubbleRemoved;
|
||||
}
|
||||
|
||||
public void setFlagBubbleRemoved(boolean flagBubbleRemoved) {
|
||||
mFlagBubbleRemoved = flagBubbleRemoved;
|
||||
}
|
||||
|
||||
public void setSystemGeneratedSmartActions(
|
||||
ArrayList<Notification.Action> systemGeneratedSmartActions) {
|
||||
mSystemGeneratedSmartActions = systemGeneratedSmartActions;
|
||||
|
||||
@@ -47,6 +47,7 @@ import org.mockito.MockitoAnnotations;
|
||||
public class BubbleExtractorTest extends UiServiceTestCase {
|
||||
|
||||
@Mock RankingConfig mConfig;
|
||||
@Mock BubbleExtractor.BubbleChecker mBubbleChecker;
|
||||
BubbleExtractor mBubbleExtractor;
|
||||
|
||||
private String mPkg = "com.android.server.notification";
|
||||
@@ -141,4 +142,33 @@ public class BubbleExtractorTest extends UiServiceTestCase {
|
||||
|
||||
assertFalse(r.canBubble());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFlagBubble_true() {
|
||||
when(mConfig.bubblesEnabled()).thenReturn(true);
|
||||
when(mConfig.areBubblesAllowed(mPkg, mUid)).thenReturn(true);
|
||||
NotificationRecord r = getNotificationRecord(true, IMPORTANCE_UNSPECIFIED);
|
||||
|
||||
mBubbleExtractor.setBubbleChecker(mBubbleChecker);
|
||||
when(mBubbleChecker.isNotificationAppropriateToBubble(r)).thenReturn(true);
|
||||
mBubbleExtractor.process(r);
|
||||
|
||||
assertTrue(r.canBubble());
|
||||
assertTrue(r.getNotification().isBubbleNotification());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFlagBubble_noFlag_previouslyRemoved() {
|
||||
when(mConfig.bubblesEnabled()).thenReturn(true);
|
||||
when(mConfig.areBubblesAllowed(mPkg, mUid)).thenReturn(true);
|
||||
NotificationRecord r = getNotificationRecord(true, IMPORTANCE_UNSPECIFIED);
|
||||
r.setFlagBubbleRemoved(true);
|
||||
|
||||
mBubbleExtractor.setBubbleChecker(mBubbleChecker);
|
||||
when(mBubbleChecker.isNotificationAppropriateToBubble(r)).thenReturn(true);
|
||||
mBubbleExtractor.process(r);
|
||||
|
||||
assertTrue(r.canBubble());
|
||||
assertFalse(r.getNotification().isBubbleNotification());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,6 +78,7 @@ import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.app.ActivityManager;
|
||||
import android.app.ActivityManagerInternal;
|
||||
import android.app.AppOpsManager;
|
||||
import android.app.AutomaticZenRule;
|
||||
import android.app.IActivityManager;
|
||||
@@ -154,6 +155,7 @@ import com.android.internal.logging.InstanceIdSequence;
|
||||
import com.android.internal.logging.InstanceIdSequenceFake;
|
||||
import com.android.internal.statusbar.NotificationVisibility;
|
||||
import com.android.internal.util.FastXmlSerializer;
|
||||
import com.android.server.DeviceIdleInternal;
|
||||
import com.android.server.LocalServices;
|
||||
import com.android.server.SystemService;
|
||||
import com.android.server.UiServiceTestCase;
|
||||
@@ -380,12 +382,20 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
|
||||
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
||||
DeviceIdleInternal deviceIdleInternal = mock(DeviceIdleInternal.class);
|
||||
when(deviceIdleInternal.getNotificationWhitelistDuration()).thenReturn(3000L);
|
||||
ActivityManagerInternal activityManagerInternal = mock(ActivityManagerInternal.class);
|
||||
|
||||
LocalServices.removeServiceForTest(UriGrantsManagerInternal.class);
|
||||
LocalServices.addService(UriGrantsManagerInternal.class, mUgmInternal);
|
||||
LocalServices.removeServiceForTest(WindowManagerInternal.class);
|
||||
LocalServices.addService(WindowManagerInternal.class, mWindowManagerInternal);
|
||||
LocalServices.removeServiceForTest(StatusBarManagerInternal.class);
|
||||
LocalServices.addService(StatusBarManagerInternal.class, mStatusBar);
|
||||
LocalServices.removeServiceForTest(DeviceIdleInternal.class);
|
||||
LocalServices.addService(DeviceIdleInternal.class, deviceIdleInternal);
|
||||
LocalServices.removeServiceForTest(ActivityManagerInternal.class);
|
||||
LocalServices.addService(ActivityManagerInternal.class, activityManagerInternal);
|
||||
|
||||
doNothing().when(mContext).sendBroadcastAsUser(any(), any(), any());
|
||||
|
||||
@@ -5591,6 +5601,67 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
|
||||
assertEquals((notifsAfter[0].getNotification().flags & FLAG_BUBBLE), 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotificationBubbleIsFlagRemoved_resetOnUpdate() throws Exception {
|
||||
// Bubbles are allowed!
|
||||
setUpPrefsForBubbles(PKG, mUid, true /* global */, true /* app */, true /* channel */);
|
||||
// Notif with bubble metadata
|
||||
NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
|
||||
"testNotificationBubbleIsFlagRemoved_resetOnUpdate");
|
||||
|
||||
mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
|
||||
nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
|
||||
waitForIdle();
|
||||
// Flag shouldn't be modified
|
||||
NotificationRecord recordToCheck = mService.getNotificationRecord(nr.getSbn().getKey());
|
||||
assertFalse(recordToCheck.isFlagBubbleRemoved());
|
||||
|
||||
// Notify we're not a bubble
|
||||
mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), false);
|
||||
waitForIdle();
|
||||
// Flag should be modified
|
||||
recordToCheck = mService.getNotificationRecord(nr.getSbn().getKey());
|
||||
assertTrue(recordToCheck.isFlagBubbleRemoved());
|
||||
|
||||
|
||||
// Update the notif
|
||||
mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
|
||||
nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
|
||||
waitForIdle();
|
||||
// And the flag is reset
|
||||
recordToCheck = mService.getNotificationRecord(nr.getSbn().getKey());
|
||||
assertFalse(recordToCheck.isFlagBubbleRemoved());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotificationBubbleIsFlagRemoved_resetOnBubbleChangedTrue() throws Exception {
|
||||
// Bubbles are allowed!
|
||||
setUpPrefsForBubbles(PKG, mUid, true /* global */, true /* app */, true /* channel */);
|
||||
// Notif with bubble metadata
|
||||
NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
|
||||
"testNotificationBubbleIsFlagRemoved_trueOnBubbleChangedTrue");
|
||||
|
||||
mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
|
||||
nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
|
||||
waitForIdle();
|
||||
// Flag shouldn't be modified
|
||||
NotificationRecord recordToCheck = mService.getNotificationRecord(nr.getSbn().getKey());
|
||||
assertFalse(recordToCheck.isFlagBubbleRemoved());
|
||||
|
||||
// Notify we're not a bubble
|
||||
mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), false);
|
||||
waitForIdle();
|
||||
// Flag should be modified
|
||||
recordToCheck = mService.getNotificationRecord(nr.getSbn().getKey());
|
||||
assertTrue(recordToCheck.isFlagBubbleRemoved());
|
||||
|
||||
// Notify we are a bubble
|
||||
mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), true);
|
||||
waitForIdle();
|
||||
// And the flag is reset
|
||||
assertFalse(recordToCheck.isFlagBubbleRemoved());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnBubbleNotificationSuppressionChanged() throws Exception {
|
||||
// Bubbles are allowed!
|
||||
|
||||
Reference in New Issue
Block a user