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

Commit ff3f860c authored by Julia Reynolds's avatar Julia Reynolds
Browse files

Update FGS notification behavior

Allow FGS notifications to be individually dismissed bu users, but not
clearable by clear all. Apps still cannot dismiss their FGS
notifications.

Also cleaned up some code from a previous 'allow dismissal' project.

Bug: 201579707
Test: atest SystemUITest
Test: atest NotificationManagerServiceTest
Test: flip flag, clear all does not dismiss a FGS but individual
swipe does
Test: without flag FGSes are not dismissible
Test: verify swipe/dismiss behavior for notif with FLAG_NO_CLEAR
Test: verify swipe/dismiss behavior for notif with FLAG_ONGOING_EVENT

Change-Id: Ibf9f55df400b7e9984d3fda5e6959878474f9886
parent e62cb766
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -626,7 +626,6 @@ public class NotificationEntryManager implements
            entry = new NotificationEntry(
                    notification,
                    ranking,
                    mFgsFeatureController.isForegroundServiceDismissalEnabled(),
                    SystemClock.uptimeMillis());
            mAllNotifications.add(entry);
            mLeakDetector.trackInstance(entry);
+9 −2
Original line number Diff line number Diff line
@@ -56,10 +56,12 @@ import android.service.notification.NotificationListenerService.RankingMap;
import android.service.notification.StatusBarNotification;
import android.util.ArrayMap;
import android.util.Pair;
import android.util.Slog;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.statusbar.IStatusBarService;
import com.android.systemui.Dumpable;
import com.android.systemui.dagger.SysUISingleton;
@@ -240,6 +242,10 @@ public class NotifCollection implements Dumpable {
        Assert.isMainThread();
        checkForReentrantCall();

        // TODO (b/206842750): This method is called from (silent) clear all and non-clear all
        // contexts and should be checking the NO_CLEAR flag, rather than depending on NSSL
        // to pass in a properly filtered list of notifications

        final List<NotificationEntry> entriesToLocallyDismiss = new ArrayList<>();
        for (int i = 0; i < entriesToDismiss.size(); i++) {
            NotificationEntry entry = entriesToDismiss.get(i).first;
@@ -742,12 +748,13 @@ public class NotifCollection implements Dumpable {
     *
     * See NotificationManager.cancelGroupChildrenByListLocked() for corresponding code.
     */
    private static boolean shouldAutoDismissChildren(
    @VisibleForTesting
    static boolean shouldAutoDismissChildren(
            NotificationEntry entry,
            String dismissedGroupKey) {
        return entry.getSbn().getGroupKey().equals(dismissedGroupKey)
                && !entry.getSbn().getNotification().isGroupSummary()
                && !hasFlag(entry, Notification.FLAG_FOREGROUND_SERVICE)
                && !hasFlag(entry, Notification.FLAG_ONGOING_EVENT)
                && !hasFlag(entry, Notification.FLAG_BUBBLE)
                && entry.getDismissState() != DISMISSED;
    }
+20 −36
Original line number Diff line number Diff line
@@ -174,7 +174,6 @@ public final class NotificationEntry extends ListEntry {

    private boolean mAutoHeadsUp;
    private boolean mPulseSupressed;
    private boolean mAllowFgsDismissal;
    private int mBucket = BUCKET_ALERTING;
    @Nullable private Long mPendingAnimationDuration;
    private boolean mIsMarkedForUserTriggeredMovement;
@@ -192,14 +191,6 @@ public final class NotificationEntry extends ListEntry {
    public NotificationEntry(
            @NonNull StatusBarNotification sbn,
            @NonNull Ranking ranking,
            long creationTime) {
        this(sbn, ranking, false, creationTime);
    }

    public NotificationEntry(
            @NonNull StatusBarNotification sbn,
            @NonNull Ranking ranking,
            boolean allowFgsDismissal,
            long creationTime
    ) {
        super(requireNonNull(requireNonNull(sbn).getKey()), creationTime);
@@ -209,8 +200,6 @@ public final class NotificationEntry extends ListEntry {
        mKey = sbn.getKey();
        setSbn(sbn);
        setRanking(ranking);

        mAllowFgsDismissal = allowFgsDismissal;
    }

    @Override
@@ -743,13 +732,11 @@ public final class NotificationEntry extends ListEntry {
    /**
     * @return Can the underlying notification be cleared? This can be different from whether the
     *         notification can be dismissed in case notifications are sensitive on the lockscreen.
     * @see #canViewBeDismissed()
     */
    // TOOD: This logic doesn't belong on NotificationEntry. It should be moved to the
    // ForegroundsServiceDismissalFeatureController or some other controller that can be added
    // as a dependency to any class that needs to answer this question.
    // TODO: This logic doesn't belong on NotificationEntry. It should be moved to a controller
    // that can be added as a dependency to any class that needs to answer this question.
    public boolean isClearable() {
        if (!isDismissable()) {
        if (!mSbn.isClearable()) {
            return false;
        }

@@ -757,7 +744,7 @@ public final class NotificationEntry extends ListEntry {
        if (children != null && children.size() > 0) {
            for (int i = 0; i < children.size(); i++) {
                NotificationEntry child =  children.get(i);
                if (!child.isDismissable()) {
                if (!child.getSbn().isClearable()) {
                    return false;
                }
            }
@@ -766,28 +753,25 @@ public final class NotificationEntry extends ListEntry {
    }

    /**
     * Notifications might have any combination of flags:
     * - FLAG_ONGOING_EVENT
     * - FLAG_NO_CLEAR
     * - FLAG_FOREGROUND_SERVICE
     *
     * We want to allow dismissal of notifications that represent foreground services, which may
     * have all 3 flags set. If we only find NO_CLEAR though, we don't want to allow dismissal
     * @return Can the underlying notification be individually dismissed?
     * @see #canViewBeDismissed()
     */
    private boolean isDismissable() {
        boolean ongoing = ((mSbn.getNotification().flags & Notification.FLAG_ONGOING_EVENT) != 0);
        boolean noclear = ((mSbn.getNotification().flags & Notification.FLAG_NO_CLEAR) != 0);
        boolean fgs = ((mSbn.getNotification().flags & FLAG_FOREGROUND_SERVICE) != 0);

        if (mAllowFgsDismissal) {
            if (noclear && !ongoing && !fgs) {
    // TODO: This logic doesn't belong on NotificationEntry. It should be moved to a controller
    // that can be added as a dependency to any class that needs to answer this question.
    public boolean isDismissable() {
        if  (mSbn.isOngoing()) {
            return false;
        }
            return true;
        } else {
            return mSbn.isClearable();
        List<NotificationEntry> children = getAttachedNotifChildren();
        if (children != null && children.size() > 0) {
            for (int i = 0; i < children.size(); i++) {
                NotificationEntry child =  children.get(i);
                if (child.getSbn().isOngoing()) {
                    return false;
                }

            }
        }
        return true;
    }

    public boolean canViewBeDismissed() {
+1 −1
Original line number Diff line number Diff line
@@ -111,7 +111,7 @@ public class OnUserInteractionCallbackImpl implements OnUserInteractionCallback
        String group = entry.getSbn().getGroup();
        if (mNotifCollection.isOnlyChildInGroup(entry)) {
            NotificationEntry summary = mNotifCollection.getGroupSummary(group);
            if (summary != null && summary.isClearable()) return summary;
            if (summary != null && summary.isDismissable()) return summary;
        }
        return null;
    }
+1 −1
Original line number Diff line number Diff line
@@ -111,7 +111,7 @@ public class OnUserInteractionCallbackImplLegacy implements OnUserInteractionCal
    public NotificationEntry getGroupSummaryToDismiss(NotificationEntry entry) {
        if (mGroupMembershipManager.isOnlyChildInGroup(entry)) {
            NotificationEntry groupSummary = mGroupMembershipManager.getLogicalGroupSummary(entry);
            return groupSummary.isClearable() ? groupSummary : null;
            return groupSummary.isDismissable() ? groupSummary : null;
        }
        return null;
    }
Loading