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

Commit f0e93000 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Statsd logging of notification cancels."

parents b994372e 75c60571
Loading
Loading
Loading
Loading
+26 −0
Original line number Diff line number Diff line
@@ -213,6 +213,32 @@ public abstract class NotificationListenerService extends Service {
    /** Notification was canceled due to timeout */
    public static final int REASON_TIMEOUT = 19;

    /**
     * @hide
     */
    @IntDef(prefix = "REASON_", value = {
            REASON_CLICK,
            REASON_CANCEL,
            REASON_CANCEL_ALL,
            REASON_ERROR,
            REASON_PACKAGE_CHANGED,
            REASON_USER_STOPPED,
            REASON_PACKAGE_BANNED,
            REASON_APP_CANCEL,
            REASON_APP_CANCEL_ALL,
            REASON_LISTENER_CANCEL,
            REASON_LISTENER_CANCEL_ALL,
            REASON_GROUP_SUMMARY_CANCELED,
            REASON_GROUP_OPTIMIZATION,
            REASON_PACKAGE_SUSPENDED,
            REASON_PROFILE_TURNED_OFF,
            REASON_UNAUTOBUNDLED,
            REASON_CHANNEL_BANNED,
            REASON_SNOOZED,
            REASON_TIMEOUT
    })
    public @interface NotificationCancelReason{};

    /**
     * The full trim of the StatusBarNotification including all its features.
     *
+2 −2
Original line number Diff line number Diff line
@@ -56,8 +56,8 @@ public interface UiEventLogger {
     * @param event an enum implementing UiEventEnum interface.
     * @param uid the uid of the relevant app, if known (0 otherwise).
     * @param packageName the package name of the relevant app, if known (null otherwise).
     * @param instance An identifier obtained from an InstanceIdSequence.
     * @param instance An identifier obtained from an InstanceIdSequence. If null, reduces to log().
     */
    void logWithInstanceId(@NonNull UiEventEnum event, int uid, @Nullable String packageName,
            @NonNull InstanceId instance);
            @Nullable InstanceId instance);
}
+3 −1
Original line number Diff line number Diff line
@@ -41,9 +41,11 @@ public class UiEventLoggerImpl implements UiEventLogger {
    public void logWithInstanceId(UiEventEnum event, int uid, String packageName,
            InstanceId instance) {
        final int eventID = event.getId();
        if (eventID > 0) {
        if ((eventID > 0)  && (instance != null)) {
            FrameworkStatsLog.write(FrameworkStatsLog.UI_EVENT_REPORTED, eventID, uid, packageName,
                    instance.getId());
        } else {
            log(event, uid, packageName);
        }
    }
}
+8 −2
Original line number Diff line number Diff line
@@ -7463,13 +7463,15 @@ public class NotificationManagerService extends SystemService {
    }

    @GuardedBy("mNotificationLock")
    private void cancelNotificationLocked(NotificationRecord r, boolean sendDelete, int reason,
    private void cancelNotificationLocked(NotificationRecord r, boolean sendDelete,
            @NotificationListenerService.NotificationCancelReason int reason,
            boolean wasPosted, String listenerName) {
        cancelNotificationLocked(r, sendDelete, reason, -1, -1, wasPosted, listenerName);
    }

    @GuardedBy("mNotificationLock")
    private void cancelNotificationLocked(NotificationRecord r, boolean sendDelete, int reason,
    private void cancelNotificationLocked(NotificationRecord r, boolean sendDelete,
            @NotificationListenerService.NotificationCancelReason int reason,
            int rank, int count, boolean wasPosted, String listenerName) {
        final String canceledKey = r.getKey();

@@ -7587,6 +7589,10 @@ public class NotificationManagerService extends SystemService {
        EventLogTags.writeNotificationCanceled(canceledKey, reason,
                r.getLifespanMs(now), r.getFreshnessMs(now), r.getExposureMs(now),
                rank, count, listenerName);
        if (wasPosted) {
            mNotificationRecordLogger.logNotificationCancelled(r, reason,
                    r.getStats().getDismissalSurface());
        }
    }

    @VisibleForTesting
+134 −10
Original line number Diff line number Diff line
@@ -16,10 +16,16 @@

package com.android.server.notification;

import static android.service.notification.NotificationListenerService.REASON_CANCEL;
import static android.service.notification.NotificationListenerService.REASON_CLICK;
import static android.service.notification.NotificationListenerService.REASON_TIMEOUT;

import android.annotation.Nullable;
import android.app.Notification;
import android.app.Person;
import android.os.Bundle;
import android.service.notification.NotificationListenerService;
import android.service.notification.NotificationStats;

import com.android.internal.logging.UiEvent;
import com.android.internal.logging.UiEventLogger;
@@ -43,23 +49,145 @@ public interface NotificationRecordLogger {
    void logNotificationReported(@Nullable NotificationRecord r, @Nullable NotificationRecord old,
            int position, int buzzBeepBlink);

    /**
     * Logs a notification cancel / dismiss event using UiEventReported (event ids from the
     * NotificationCancelledEvents enum).
     * @param r The NotificationRecord. If null, no action is taken.
     * @param reason The reason the notification was canceled.
     * @param dismissalSurface The surface the notification was dismissed from.
     */
    void logNotificationCancelled(@Nullable NotificationRecord r,
            @NotificationListenerService.NotificationCancelReason int reason,
            @NotificationStats.DismissalSurface int dismissalSurface);

    /**
     * The UiEvent enums that this class can log.
     */
    enum NotificationReportedEvents implements UiEventLogger.UiEventEnum {
        INVALID(0),
    enum NotificationReportedEvent implements UiEventLogger.UiEventEnum {
        @UiEvent(doc = "New notification enqueued to post")
        NOTIFICATION_POSTED(162),
        @UiEvent(doc = "Notification substantially updated")
        @UiEvent(doc = "Notification substantially updated, or alerted again.")
        NOTIFICATION_UPDATED(163);

        private final int mId;
        NotificationReportedEvents(int id) {
        NotificationReportedEvent(int id) {
            mId = id;
        }
        @Override public int getId() {
            return mId;
        }

        public static NotificationReportedEvent fromRecordPair(NotificationRecordPair p) {
            return (p.old != null) ? NotificationReportedEvent.NOTIFICATION_UPDATED :
                            NotificationReportedEvent.NOTIFICATION_POSTED;
        }
    }

    enum NotificationCancelledEvent implements UiEventLogger.UiEventEnum {
        INVALID(0),
        @UiEvent(doc = "Notification was canceled due to a notification click.")
        NOTIFICATION_CANCEL_CLICK(164),
        @UiEvent(doc = "Notification was canceled due to a user dismissal, surface not specified.")
        NOTIFICATION_CANCEL_USER_OTHER(165),
        @UiEvent(doc = "Notification was canceled due to a user dismiss-all (from the notification"
                + " shade).")
        NOTIFICATION_CANCEL_USER_CANCEL_ALL(166),
        @UiEvent(doc = "Notification was canceled due to an inflation error.")
        NOTIFICATION_CANCEL_ERROR(167),
        @UiEvent(doc = "Notification was canceled by the package manager modifying the package.")
        NOTIFICATION_CANCEL_PACKAGE_CHANGED(168),
        @UiEvent(doc = "Notification was canceled by the owning user context being stopped.")
        NOTIFICATION_CANCEL_USER_STOPPED(169),
        @UiEvent(doc = "Notification was canceled by the user banning the package.")
        NOTIFICATION_CANCEL_PACKAGE_BANNED(170),
        @UiEvent(doc = "Notification was canceled by the app canceling this specific notification.")
        NOTIFICATION_CANCEL_APP_CANCEL(171),
        @UiEvent(doc = "Notification was canceled by the app cancelling all its notifications.")
        NOTIFICATION_CANCEL_APP_CANCEL_ALL(172),
        @UiEvent(doc = "Notification was canceled by a listener reporting a user dismissal.")
        NOTIFICATION_CANCEL_LISTENER_CANCEL(173),
        @UiEvent(doc = "Notification was canceled by a listener reporting a user dismiss all.")
        NOTIFICATION_CANCEL_LISTENER_CANCEL_ALL(174),
        @UiEvent(doc = "Notification was canceled because it was a member of a canceled group.")
        NOTIFICATION_CANCEL_GROUP_SUMMARY_CANCELED(175),
        @UiEvent(doc = "Notification was canceled because it was an invisible member of a group.")
        NOTIFICATION_CANCEL_GROUP_OPTIMIZATION(176),
        @UiEvent(doc = "Notification was canceled by the device administrator suspending the "
                + "package.")
        NOTIFICATION_CANCEL_PACKAGE_SUSPENDED(177),
        @UiEvent(doc = "Notification was canceled by the owning managed profile being turned off.")
        NOTIFICATION_CANCEL_PROFILE_TURNED_OFF(178),
        @UiEvent(doc = "Autobundled summary notification was canceled because its group was "
                + "unbundled")
        NOTIFICATION_CANCEL_UNAUTOBUNDLED(179),
        @UiEvent(doc = "Notification was canceled by the user banning the channel.")
        NOTIFICATION_CANCEL_CHANNEL_BANNED(180),
        @UiEvent(doc = "Notification was snoozed.")
        NOTIFICATION_CANCEL_SNOOZED(181),
        @UiEvent(doc = "Notification was canceled due to timeout")
        NOTIFICATION_CANCEL_TIMEOUT(182),
        // Values 183-189 reserved for future system dismissal reasons
        @UiEvent(doc = "Notification was canceled due to user dismissal of a peeking notification.")
        NOTIFICATION_CANCEL_USER_PEEK(190),
        @UiEvent(doc = "Notification was canceled due to user dismissal from the always-on display")
        NOTIFICATION_CANCEL_USER_AOD(191),
        @UiEvent(doc = "Notification was canceled due to user dismissal from the notification"
                + " shade.")
        NOTIFICATION_CANCEL_USER_SHADE(192),
        @UiEvent(doc = "Notification was canceled due to user dismissal from the lockscreen")
        NOTIFICATION_CANCEL_USER_LOCKSCREEN(193);

        private final int mId;
        NotificationCancelledEvent(int id) {
            mId = id;
        }
        @Override public int getId() {
            return mId;
        }
        public static NotificationCancelledEvent fromCancelReason(
                @NotificationListenerService.NotificationCancelReason int reason,
                @NotificationStats.DismissalSurface int surface) {
            // Shouldn't be possible to get a non-dismissed notification here.
            if (surface == NotificationStats.DISMISSAL_NOT_DISMISSED) {
                if (NotificationManagerService.DBG) {
                    throw new IllegalArgumentException("Unexpected surface " + surface);
                }
                return INVALID;
            }
            // Most cancel reasons do not have a meaningful surface. Reason codes map directly
            // to NotificationCancelledEvent codes.
            if (surface == NotificationStats.DISMISSAL_OTHER) {
                if ((REASON_CLICK <= reason) && (reason <= REASON_TIMEOUT)) {
                    return NotificationCancelledEvent.values()[reason];
                }
                if (NotificationManagerService.DBG) {
                    throw new IllegalArgumentException("Unexpected cancel reason " + reason);
                }
                return INVALID;
            }
            // User cancels have a meaningful surface, which we differentiate by. See b/149038335
            // for caveats.
            if (reason != REASON_CANCEL) {
                if (NotificationManagerService.DBG) {
                    throw new IllegalArgumentException("Unexpected cancel with surface " + reason);
                }
                return INVALID;
            }
            switch (surface) {
                case NotificationStats.DISMISSAL_PEEK:
                    return NOTIFICATION_CANCEL_USER_PEEK;
                case NotificationStats.DISMISSAL_AOD:
                    return NOTIFICATION_CANCEL_USER_AOD;
                case NotificationStats.DISMISSAL_SHADE:
                    return NOTIFICATION_CANCEL_USER_SHADE;
                default:
                    if (NotificationManagerService.DBG) {
                        throw new IllegalArgumentException("Unexpected surface for user-dismiss "
                                + reason);
                    }
                    return INVALID;
            }
        }
    }

    /**
@@ -88,7 +216,8 @@ public interface NotificationRecordLogger {
                return true;
            }

            return !(Objects.equals(r.getSbn().getChannelIdLogTag(), old.getSbn().getChannelIdLogTag())
            return !(Objects.equals(r.getSbn().getChannelIdLogTag(),
                        old.getSbn().getChannelIdLogTag())
                    && Objects.equals(r.getSbn().getGroupLogTag(), old.getSbn().getGroupLogTag())
                    && (r.getSbn().getNotification().isGroupSummary()
                        == old.getSbn().getNotification().isGroupSummary())
@@ -97,11 +226,6 @@ public interface NotificationRecordLogger {
                    && (r.getImportance() == old.getImportance()));
        }

        NotificationReportedEvents getUiEvent() {
            return (old != null) ? NotificationReportedEvents.NOTIFICATION_UPDATED :
                    NotificationReportedEvents.NOTIFICATION_POSTED;
        }

        /**
         * @return hash code for the notification style class, or 0 if none exists.
         */
Loading