Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b68f9f98 authored by Mady Mellor's avatar Mady Mellor Committed by Android (Google) Code Review
Browse files

Merge "Make bubble flag removals from notification delegate (sysui) sticky" into rvc-dev

parents d8cf9a98 13f9bc83
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -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 {
+3 −0
Original line number Diff line number Diff line
@@ -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();
+14 −0
Original line number Diff line number Diff line
@@ -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;
+30 −0
Original line number Diff line number Diff line
@@ -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());
    }
}
+71 −0
Original line number Diff line number Diff line
@@ -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!