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

Commit 8d260a46 authored by Beverly Tai's avatar Beverly Tai Committed by Android (Google) Code Review
Browse files

Merge "Add dismissUserStats to NEM#performRemoveNotif"

parents 3db80dea 189d4af7
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -73,6 +73,11 @@ public final class NotificationStats implements Parcelable {
     * Notification has been dismissed from the notification shade.
     */
    public static final int DISMISSAL_SHADE = 3;
    /**
     * Notification has been dismissed as a bubble.
     * @hide
     */
    public static final int DISMISSAL_BUBBLE = 3;

    /** @hide */
    @IntDef(prefix = { "DISMISS_SENTIMENT_" }, value = {
+52 −9
Original line number Diff line number Diff line
@@ -25,6 +25,8 @@ import static android.service.notification.NotificationListenerService.REASON_CA
import static android.service.notification.NotificationListenerService.REASON_CANCEL_ALL;
import static android.service.notification.NotificationListenerService.REASON_CLICK;
import static android.service.notification.NotificationListenerService.REASON_GROUP_SUMMARY_CANCELED;
import static android.service.notification.NotificationStats.DISMISSAL_BUBBLE;
import static android.service.notification.NotificationStats.DISMISS_SENTIMENT_NEUTRAL;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;
import static android.view.View.INVISIBLE;
@@ -100,8 +102,11 @@ import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotifCollection;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.coordinator.BubbleCoordinator;
import com.android.systemui.statusbar.notification.collection.notifcollection.DismissedByUserStats;
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.NotificationShadeWindowController;
import com.android.systemui.statusbar.phone.ScrimController;
@@ -277,7 +282,10 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
         * This can happen when an app cancels a bubbled notification or when the user dismisses a
         * bubble.
         */
        void removeNotification(@NonNull NotificationEntry entry, int reason);
        void removeNotification(
                @NonNull NotificationEntry entry,
                @NonNull DismissedByUserStats stats,
                int reason);

        /**
         * Called when a bubbled notification has changed whether it should be
@@ -543,6 +551,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
                    }
                });

        // The new pipeline takes care of this as a NotifDismissInterceptor BubbleCoordinator
        mNotificationEntryManager.addNotificationRemoveInterceptor(
                new NotificationRemoveInterceptor() {
                    @Override
@@ -551,7 +560,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
                            NotificationEntry entry,
                            int dismissReason) {
                        final boolean isClearAll = dismissReason == REASON_CANCEL_ALL;
                        final boolean isUserDimiss = dismissReason == REASON_CANCEL
                        final boolean isUserDismiss = dismissReason == REASON_CANCEL
                                || dismissReason == REASON_CLICK;
                        final boolean isAppCancel = dismissReason == REASON_APP_CANCEL
                                || dismissReason == REASON_APP_CANCEL_ALL;
@@ -562,7 +571,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
                        // previously been dismissed & entry.isRowDismissed would still be true
                        boolean userRemovedNotif =
                                (entry != null && entry.isRowDismissed() && !isAppCancel)
                                || isClearAll || isUserDimiss || isSummaryCancel;
                                || isClearAll || isUserDismiss || isSummaryCancel;

                        if (userRemovedNotif) {
                            return handleDismissalInterception(entry);
@@ -591,8 +600,13 @@ public class BubbleController implements ConfigurationController.ConfigurationLi

        addNotifCallback(new NotifCallback() {
            @Override
            public void removeNotification(NotificationEntry entry, int reason) {
                mNotificationEntryManager.performRemoveNotification(entry.getSbn(), reason);
            public void removeNotification(
                    NotificationEntry entry,
                    DismissedByUserStats dismissedByUserStats,
                    int reason
            ) {
                mNotificationEntryManager.performRemoveNotification(entry.getSbn(),
                        dismissedByUserStats, reason);
            }

            @Override
@@ -612,7 +626,9 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
                            mNotificationEntryManager.getActiveNotificationUnfiltered(
                                    mBubbleData.getSummaryKey(groupKey));
                    if (summary != null) {
                        mNotificationEntryManager.performRemoveNotification(summary.getSbn(),
                        mNotificationEntryManager.performRemoveNotification(
                                summary.getSbn(),
                                getDismissedByUserStats(summary, false),
                                UNDEFINED_DISMISS_REASON);
                    }
                }
@@ -634,7 +650,9 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
                    boolean isSummaryThisNotif = summary.getKey().equals(entry.getKey());
                    if (!isSummaryThisNotif && (summaryChildren == null
                            || summaryChildren.isEmpty())) {
                        mNotificationEntryManager.performRemoveNotification(summary.getSbn(),
                        mNotificationEntryManager.performRemoveNotification(
                                summary.getSbn(),
                                getDismissedByUserStats(summary, false),
                                UNDEFINED_DISMISS_REASON);
                    }
                }
@@ -1331,7 +1349,10 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
                        // time to actually remove it
                        for (NotifCallback cb : mCallbacks) {
                            if (entry != null) {
                                cb.removeNotification(entry, REASON_CANCEL);
                                cb.removeNotification(
                                        entry,
                                        getDismissedByUserStats(entry, true),
                                        REASON_CANCEL);
                            }
                        }
                    } else {
@@ -1487,7 +1508,10 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
                } else {
                    // non-bubbled children can be removed
                    for (NotifCallback cb : mCallbacks) {
                        cb.removeNotification(child, REASON_GROUP_SUMMARY_CANCELED);
                        cb.removeNotification(
                                child,
                                getDismissedByUserStats(child, true),
                                REASON_GROUP_SUMMARY_CANCELED);
                    }
                }
            }
@@ -1501,6 +1525,25 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
                summary.getKey());
    }

    /**
     * Gets the DismissedByUserStats used by {@link NotificationEntryManager}.
     * Will not be necessary when using the new notification pipeline's {@link NotifCollection}.
     * Instead, this is taken care of by {@link BubbleCoordinator}.
     */
    private DismissedByUserStats getDismissedByUserStats(
            NotificationEntry entry,
            boolean isVisible) {
        return new DismissedByUserStats(
                DISMISSAL_BUBBLE,
                DISMISS_SENTIMENT_NEUTRAL,
                NotificationVisibility.obtain(
                        entry.getKey(),
                        entry.getRanking().getRank(),
                        mNotificationEntryManager.getActiveNotificationsCount(),
                        isVisible,
                        NotificationLogger.getNotificationLocation(entry)));
    }

    /**
     * Updates the visibility of the bubbles based on current state.
     * Does not un-bubble, just hides or un-hides.
+47 −59
Original line number Diff line number Diff line
@@ -15,7 +15,6 @@
 */
package com.android.systemui.statusbar.notification;

import static android.service.notification.NotificationListenerService.REASON_CANCEL;
import static android.service.notification.NotificationListenerService.REASON_ERROR;

import static com.android.systemui.statusbar.notification.collection.NotifCollection.REASON_UNKNOWN;
@@ -24,14 +23,11 @@ import static com.android.systemui.statusbar.notification.row.NotificationRowCon
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.Notification;
import android.content.Context;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
import android.service.notification.NotificationListenerService;
import android.service.notification.NotificationListenerService.Ranking;
import android.service.notification.NotificationListenerService.RankingMap;
import android.service.notification.NotificationStats;
import android.service.notification.StatusBarNotification;
import android.util.ArrayMap;
import android.util.ArraySet;
@@ -41,7 +37,6 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.statusbar.NotificationVisibility;
import com.android.systemui.Dumpable;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.FeatureFlags;
import com.android.systemui.statusbar.NotificationLifetimeExtender;
import com.android.systemui.statusbar.NotificationListener;
@@ -54,11 +49,11 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationRankingManager;
import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinder;
import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection;
import com.android.systemui.statusbar.notification.collection.notifcollection.DismissedByUserStats;
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
import com.android.systemui.statusbar.notification.dagger.NotificationsModule;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.util.Assert;
import com.android.systemui.util.leak.LeakDetector;

@@ -147,8 +142,6 @@ public class NotificationEntryManager implements
    private final NotificationRankingManager mRankingManager;
    private final FeatureFlags mFeatureFlags;
    private final ForegroundServiceDismissalFeatureController mFgsFeatureController;
    private final HeadsUpManager mHeadsUpManager;
    private final StatusBarStateController mStatusBarStateController;

    private NotificationPresenter mPresenter;
    private RankingMap mLatestRankingMap;
@@ -213,8 +206,7 @@ public class NotificationEntryManager implements
            Lazy<NotificationRemoteInputManager> notificationRemoteInputManagerLazy,
            LeakDetector leakDetector,
            ForegroundServiceDismissalFeatureController fgsFeatureController,
            HeadsUpManager headsUpManager,
            StatusBarStateController statusBarStateController
            IStatusBarService statusBarService
    ) {
        mLogger = logger;
        mGroupManager = groupManager;
@@ -225,11 +217,7 @@ public class NotificationEntryManager implements
        mRemoteInputManagerLazy = notificationRemoteInputManagerLazy;
        mLeakDetector = leakDetector;
        mFgsFeatureController = fgsFeatureController;
        mHeadsUpManager = headsUpManager;
        mStatusBarStateController = statusBarStateController;

        mStatusBarService = IStatusBarService.Stub.asInterface(
                ServiceManager.checkService(Context.STATUS_BAR_SERVICE));
        mStatusBarService = statusBarService;
    }

    /** Once called, the NEM will start processing notification events from system server. */
@@ -284,16 +272,23 @@ public class NotificationEntryManager implements
    }

    /**
     * Requests a notification to be removed.
     * User requests a notification to be removed.
     *
     * @param n the notification to remove.
     * @param reason why it is being removed e.g. {@link NotificationListenerService#REASON_CANCEL},
     *               or 0 if unknown.
     */
    public void performRemoveNotification(StatusBarNotification n, int reason) {
        final NotificationVisibility nv = obtainVisibility(n.getKey());
    public void performRemoveNotification(
            StatusBarNotification n,
            @NonNull DismissedByUserStats stats,
            int reason
    ) {
        removeNotificationInternal(
                n.getKey(), null, nv, false /* forceRemove */, true /* removedByUser */,
                n.getKey(),
                null,
                stats.notificationVisibility,
                false /* forceRemove */,
                stats,
                reason);
    }

@@ -337,7 +332,11 @@ public class NotificationEntryManager implements
     */
    private void handleInflationException(StatusBarNotification n, Exception e) {
        removeNotificationInternal(
                n.getKey(), null, null, true /* forceRemove */, false /* removedByUser */,
                n.getKey(),
                null,
                null,
                true /* forceRemove */,
                null /* dismissedByUserStats */,
                REASON_ERROR);
        for (NotificationEntryListener listener : mNotificationEntryListeners) {
            listener.onInflationError(n, e);
@@ -435,19 +434,28 @@ public class NotificationEntryManager implements
        reapplyFilterAndSort("addVisibleNotification");
    }


    public void removeNotification(String key, RankingMap ranking,
            int reason) {
        removeNotificationInternal(key, ranking, obtainVisibility(key), false /* forceRemove */,
                false /* removedByUser */, reason);
    @VisibleForTesting
    protected void removeNotification(String key, RankingMap ranking, int reason) {
        removeNotificationInternal(
                key,
                ranking,
                obtainVisibility(key),
                false /* forceRemove */,
                null /* dismissedByUserStats */,
                reason);
    }

    /**
     * Internally remove a notification because system server has reported the notification
     * should be removed OR the user has manually dismissed the notification
     * @param dismissedByUserStats non-null if the user manually dismissed the notification
     */
    private void removeNotificationInternal(
            String key,
            @Nullable RankingMap ranking,
            @Nullable NotificationVisibility visibility,
            boolean forceRemove,
            boolean removedByUser,
            DismissedByUserStats dismissedByUserStats,
            int reason) {

        final NotificationEntry entry = getActiveNotificationUnfiltered(key);
@@ -512,11 +520,11 @@ public class NotificationEntryManager implements
                handleGroupSummaryRemoved(key);
                removeVisibleNotification(key);
                updateNotifications("removeNotificationInternal");
                removedByUser |= entryDismissed;
                final boolean removedByUser = dismissedByUserStats != null;

                mLogger.logNotifRemoved(entry.getKey(), removedByUser);
                if (removedByUser && visibility != null) {
                    sendNotificationRemovalToServer(entry.getKey(), entry.getSbn(), visibility);
                    sendNotificationRemovalToServer(entry.getSbn(), dismissedByUserStats);
                }
                for (NotificationEntryListener listener : mNotificationEntryListeners) {
                    listener.onEntryRemoved(entry, visibility, removedByUser, reason);
@@ -534,30 +542,18 @@ public class NotificationEntryManager implements
    }

    private void sendNotificationRemovalToServer(
            String key,
            StatusBarNotification notification,
            NotificationVisibility nv) {
        final String pkg = notification.getPackageName();
        final String tag = notification.getTag();
        final int id = notification.getId();
        final int userId = notification.getUser().getIdentifier();
            DismissedByUserStats dismissedByUserStats) {
        try {
            int dismissalSurface = NotificationStats.DISMISSAL_SHADE;
            if (mHeadsUpManager.isAlerting(key)) {
                dismissalSurface = NotificationStats.DISMISSAL_PEEK;
            } else if (mStatusBarStateController.isDozing()) {
                dismissalSurface = NotificationStats.DISMISSAL_AOD;
            }
            int dismissalSentiment = NotificationStats.DISMISS_SENTIMENT_NEUTRAL;
            mStatusBarService.onNotificationClear(
                    pkg,
                    tag,
                    id,
                    userId,
                    notification.getPackageName(),
                    notification.getTag(),
                    notification.getId(),
                    notification.getUser().getIdentifier(),
                    notification.getKey(),
                    dismissalSurface,
                    dismissalSentiment,
                    nv);
                    dismissedByUserStats.dismissalSurface,
                    dismissedByUserStats.dismissalSentiment,
                    dismissedByUserStats.notificationVisibility);
        } catch (RemoteException ex) {
            // system process is dead if we're here.
        }
@@ -641,11 +637,7 @@ public class NotificationEntryManager implements

        // Construct the expanded view.
        if (!mFeatureFlags.isNewNotifPipelineRenderingEnabled()) {
            mNotificationRowBinderLazy.get()
                    .inflateViews(
                            entry,
                            () -> performRemoveNotification(notification, REASON_CANCEL),
                            mInflationCallback);
            mNotificationRowBinderLazy.get().inflateViews(entry, mInflationCallback);
        }

        mPendingNotifications.put(key, entry);
@@ -675,7 +667,7 @@ public class NotificationEntryManager implements

        final String key = notification.getKey();
        abortExistingInflation(key, "updateNotification");
        NotificationEntry entry = getActiveNotificationUnfiltered(key);
        final NotificationEntry entry = getActiveNotificationUnfiltered(key);
        if (entry == null) {
            return;
        }
@@ -701,11 +693,7 @@ public class NotificationEntryManager implements
        }

        if (!mFeatureFlags.isNewNotifPipelineRenderingEnabled()) {
            mNotificationRowBinderLazy.get()
                    .inflateViews(
                            entry,
                            () -> performRemoveNotification(notification, REASON_CANCEL),
                            mInflationCallback);
            mNotificationRowBinderLazy.get().inflateViews(entry, mInflationCallback);
        }

        updateNotifications("updateNotificationInternal");
+0 −32
Original line number Diff line number Diff line
@@ -16,17 +16,10 @@

package com.android.systemui.statusbar.notification.collection;

import static android.service.notification.NotificationStats.DISMISS_SENTIMENT_NEUTRAL;

import android.service.notification.NotificationStats;

import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.statusbar.NotificationVisibility;
import com.android.systemui.statusbar.notification.InflationException;
import com.android.systemui.statusbar.notification.collection.inflation.NotifInflater;
import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl;
import com.android.systemui.statusbar.notification.collection.notifcollection.DismissedByUserStats;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.row.NotifInflationErrorManager;
import com.android.systemui.statusbar.notification.row.NotificationContentInflater;

@@ -81,7 +74,6 @@ public class NotifInflaterImpl implements NotifInflater {
        try {
            requireBinder().inflateViews(
                    entry,
                    getDismissCallback(entry),
                    wrapInflationCallback(callback));
        } catch (InflationException e) {
            mNotifErrorManager.setInflationError(entry, e);
@@ -93,30 +85,6 @@ public class NotifInflaterImpl implements NotifInflater {
        entry.abortTask();
    }

    private Runnable getDismissCallback(NotificationEntry entry) {
        return new Runnable() {
            @Override
            public void run() {
                int dismissalSurface = NotificationStats.DISMISSAL_SHADE;
                /*
                 * TODO: determine dismissal surface (ie: shade / headsup / aod)
                 * see {@link NotificationLogger#logNotificationClear}
                 */
                mNotifCollection.dismissNotification(
                        entry,
                        new DismissedByUserStats(
                                dismissalSurface,
                                DISMISS_SENTIMENT_NEUTRAL,
                                NotificationVisibility.obtain(entry.getKey(),
                                        entry.getRanking().getRank(),
                                        mNotifPipeline.getShadeListCount(),
                                        true,
                                        NotificationLogger.getNotificationLocation(entry))
                        ));
            }
        };
    }

    private NotificationContentInflater.InflationCallback wrapInflationCallback(
            InflationCallback callback) {
        return new NotificationContentInflater.InflationCallback() {
+7 −21
Original line number Diff line number Diff line
@@ -16,10 +16,6 @@

package com.android.systemui.statusbar.notification.collection.coordinator;

import static android.service.notification.NotificationStats.DISMISSAL_OTHER;
import static android.service.notification.NotificationStats.DISMISS_SENTIMENT_NEUTRAL;

import com.android.internal.statusbar.NotificationVisibility;
import com.android.systemui.bubbles.BubbleController;
import com.android.systemui.statusbar.notification.collection.NotifCollection;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
@@ -27,7 +23,6 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
import com.android.systemui.statusbar.notification.collection.notifcollection.DismissedByUserStats;
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifDismissInterceptor;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;

import java.util.HashSet;
import java.util.Set;
@@ -101,7 +96,6 @@ public class BubbleCoordinator implements Coordinator {

        @Override
        public boolean shouldInterceptDismissal(NotificationEntry entry) {
            // TODO: b/149041810 add support for intercepting app-cancelled bubble notifications
            // for experimental bubbles
            if (mBubbleController.handleDismissalInterception(entry)) {
                mInterceptedDismissalEntries.add(entry.getKey());
@@ -121,17 +115,21 @@ public class BubbleCoordinator implements Coordinator {
    private final BubbleController.NotifCallback mNotifCallback =
            new BubbleController.NotifCallback() {
        @Override
        public void removeNotification(NotificationEntry entry, int reason) {
        public void removeNotification(
                NotificationEntry entry,
                DismissedByUserStats dismissedByUserStats,
                int reason
        ) {
            if (isInterceptingDismissal(entry)) {
                mInterceptedDismissalEntries.remove(entry.getKey());
                mOnEndDismissInterception.onEndDismissInterception(mDismissInterceptor, entry,
                        createDismissedByUserStats(entry));
                        dismissedByUserStats);
            } else if (mNotifPipeline.getAllNotifs().contains(entry)) {
                // Bubbles are hiding the notifications from the shade, but the bubble was
                // deleted; therefore, the notification should be cancelled as if it were a user
                // dismissal (this won't re-enter handleInterceptDimissal because Bubbles
                // will have already marked it as no longer a bubble)
                mNotifCollection.dismissNotification(entry, createDismissedByUserStats(entry));
                mNotifCollection.dismissNotification(entry, dismissedByUserStats);
            }
        }

@@ -149,16 +147,4 @@ public class BubbleCoordinator implements Coordinator {
    private boolean isInterceptingDismissal(NotificationEntry entry) {
        return mInterceptedDismissalEntries.contains(entry.getKey());
    }

    private DismissedByUserStats createDismissedByUserStats(NotificationEntry entry) {
        return new DismissedByUserStats(
                DISMISSAL_OTHER,
                DISMISS_SENTIMENT_NEUTRAL,
                NotificationVisibility.obtain(entry.getKey(),
                        entry.getRanking().getRank(),
                        mNotifPipeline.getShadeListCount(),
                        true, // was visible as a bubble
                        NotificationLogger.getNotificationLocation(entry))
        );
    }
}
Loading