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

Commit dcf12d4a authored by Julia Reynolds's avatar Julia Reynolds Committed by Android (Google) Code Review
Browse files

Merge "Log interruptive notifications" into pi-dev

parents c2ecfd97 1fac86e6
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -717,7 +717,9 @@ package android.app.usage {
  }

  public static final class UsageEvents.Event {
    method public java.lang.String getNotificationChannelId();
    method public int getStandbyBucket();
    field public static final int NOTIFICATION_INTERRUPTION = 12; // 0xc
    field public static final int NOTIFICATION_SEEN = 10; // 0xa
    field public static final int STANDBY_BUCKET_CHANGED = 11; // 0xb
  }
+34 −0
Original line number Diff line number Diff line
@@ -116,6 +116,14 @@ public final class UsageEvents implements Parcelable {
        @SystemApi
        public static final int STANDBY_BUCKET_CHANGED = 11;

        /**
         * An event type denoting that an app posted an interruptive notification. Visual and
         * audible interruptions are included.
         * @hide
         */
        @SystemApi
        public static final int NOTIFICATION_INTERRUPTION = 12;

        /** @hide */
        public static final int FLAG_IS_PACKAGE_INSTANT_APP = 1 << 0;

@@ -188,6 +196,14 @@ public final class UsageEvents implements Parcelable {
         */
        public int mBucketAndReason;

        /**
         * The id of the {@link android.app.NotificationChannel} to which an interruptive
         * notification was posted.
         * Only present for {@link #NOTIFICATION_INTERRUPTION} event types.
         * {@hide}
         */
        public String mNotificationChannelId;

        /** @hide */
        @EventFlags
        public int mFlags;
@@ -208,6 +224,7 @@ public final class UsageEvents implements Parcelable {
            mContentAnnotations = orig.mContentAnnotations;
            mFlags = orig.mFlags;
            mBucketAndReason = orig.mBucketAndReason;
            mNotificationChannelId = orig.mNotificationChannelId;
        }

        /**
@@ -285,6 +302,16 @@ public final class UsageEvents implements Parcelable {
            return mBucketAndReason & 0x0000FFFF;
        }

        /**
         * Returns the ID of the {@link android.app.NotificationChannel} for this event if the
         * event is of type {@link #NOTIFICATION_INTERRUPTION}, otherwise it returns null;
         * @hide
         */
        @SystemApi
        public String getNotificationChannelId() {
            return mNotificationChannelId;
        }

        /** @hide */
        public Event getObfuscatedIfInstantApp() {
            if ((mFlags & FLAG_IS_PACKAGE_INSTANT_APP) == 0) {
@@ -444,6 +471,9 @@ public final class UsageEvents implements Parcelable {
            case Event.STANDBY_BUCKET_CHANGED:
                p.writeInt(event.mBucketAndReason);
                break;
            case Event.NOTIFICATION_INTERRUPTION:
                p.writeString(event.mNotificationChannelId);
                break;
        }
    }

@@ -473,6 +503,7 @@ public final class UsageEvents implements Parcelable {
        eventOut.mAction = null;
        eventOut.mContentType = null;
        eventOut.mContentAnnotations = null;
        eventOut.mNotificationChannelId = null;

        switch (eventOut.mEventType) {
            case Event.CONFIGURATION_CHANGE:
@@ -490,6 +521,9 @@ public final class UsageEvents implements Parcelable {
            case Event.STANDBY_BUCKET_CHANGED:
                eventOut.mBucketAndReason = p.readInt();
                break;
            case Event.NOTIFICATION_INTERRUPTION:
                eventOut.mNotificationChannelId = p.readString();
                break;
        }
    }

+10 −0
Original line number Diff line number Diff line
@@ -58,6 +58,16 @@ public abstract class UsageStatsManagerInternal {
     */
    public abstract void reportConfigurationChange(Configuration config, @UserIdInt int userId);

    /**
     * Reports that an application has posted an interruptive notification.
     *
     * @param packageName The package name of the app that posted the notification
     * @param channelId The ID of the NotificationChannel to which the notification was posted
     * @param userId The user in which the notification was posted
     */
    public abstract void reportInterruptiveNotification(String packageName, String channelId,
            @UserIdInt int userId);

    /**
     * Reports that an action equivalent to a ShortcutInfo is taken by the user.
     *
+19 −5
Original line number Diff line number Diff line
@@ -1782,11 +1782,10 @@ public class NotificationManagerService extends SystemService {
     * Report to usage stats that the notification was seen.
     * @param r notification record
     */
    @GuardedBy("mNotificationLock")
    protected void reportSeen(NotificationRecord r) {
        final int userId = r.sbn.getUserId();
        mAppUsageStats.reportEvent(r.sbn.getPackageName(),
                userId == UserHandle.USER_ALL ? USER_SYSTEM
                        : userId,
                getRealUserId(r.sbn.getUserId()),
                UsageEvents.Event.NOTIFICATION_SEEN);
    }

@@ -1858,17 +1857,30 @@ public class NotificationManagerService extends SystemService {
        return newSuppressedVisualEffects;
    }

    // TODO: log visual differences, not just audible ones
    @GuardedBy("mNotificationLock")
    protected void maybeRecordInterruptionLocked(NotificationRecord r) {
        if (r.isInterruptive()) {
            mAppUsageStats.reportInterruptiveNotification(r.sbn.getPackageName(),
                    r.getChannel().getId(),
                    getRealUserId(r.sbn.getUserId()));
        }
    }

    /**
     * Report to usage stats that the notification was clicked.
     * @param r notification record
     */
    protected void reportUserInteraction(NotificationRecord r) {
        final int userId = r.sbn.getUserId();
        mAppUsageStats.reportEvent(r.sbn.getPackageName(),
                userId == UserHandle.USER_ALL ? UserHandle.USER_SYSTEM : userId,
                getRealUserId(r.sbn.getUserId()),
                UsageEvents.Event.USER_INTERACTION);
    }

    private int getRealUserId(int userId) {
        return userId == UserHandle.USER_ALL ? UserHandle.USER_SYSTEM : userId;
    }

    @VisibleForTesting
    NotificationManagerInternal getInternalService() {
        return mInternalService;
@@ -4345,6 +4357,7 @@ public class NotificationManagerService extends SystemService {
                    }

                    buzzBeepBlinkLocked(r);
                    maybeRecordInterruptionLocked(r);
                } finally {
                    int N = mEnqueuedNotifications.size();
                    for (int i = 0; i < N; i++) {
@@ -4554,6 +4567,7 @@ public class NotificationManagerService extends SystemService {
            updateLightsLocked();
        }
        if (buzz || beep || blink) {
            record.setInterruptive(true);
            MetricsLogger.action(record.getLogMaker()
                    .setCategory(MetricsEvent.NOTIFICATION_ALERT)
                    .setType(MetricsEvent.TYPE_OPEN)
+10 −0
Original line number Diff line number Diff line
@@ -145,6 +145,7 @@ public final class NotificationRecord {
    private final List<Adjustment> mAdjustments;
    private final NotificationStats mStats;
    private int mUserSentiment;
    private boolean mIsInterruptive;

    @VisibleForTesting
    public NotificationRecord(Context context, StatusBarNotification sbn,
@@ -519,6 +520,7 @@ public final class NotificationRecord {
        pw.println(prefix + "mLight= " + mLight);
        pw.println(prefix + "mShowBadge=" + mShowBadge);
        pw.println(prefix + "mColorized=" + notification.isColorized());
        pw.println(prefix + "mIsInterruptive=" + mIsInterruptive);
        pw.println(prefix + "effectiveNotificationChannel=" + getChannel());
        if (getPeopleOverride() != null) {
            pw.println(prefix + "overridePeople= " + TextUtils.join(",", getPeopleOverride()));
@@ -888,6 +890,14 @@ public final class NotificationRecord {
        return mPeopleOverride;
    }

    public void setInterruptive(boolean interruptive) {
        mIsInterruptive = interruptive;
    }

    public boolean isInterruptive() {
        return mIsInterruptive;
    }

    protected void setPeopleOverride(ArrayList<String> people) {
        mPeopleOverride = people;
    }
Loading