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

Commit df681736 authored by Will Brockman's avatar Will Brockman Committed by Android (Google) Code Review
Browse files

Merge "Add logging of NotificationReported statsd atom."

parents d07aa513 2b6959e6
Loading
Loading
Loading
Loading
+16 −4
Original line number Diff line number Diff line
@@ -17,7 +17,8 @@
package android.service.notification;

import static android.app.NotificationChannel.PLACEHOLDER_CONVERSATION_ID;
import static android.util.FeatureFlagUtils.*;
import static android.util.FeatureFlagUtils.NOTIF_CONVO_BYPASS_SHORTCUT_REQ;
import static android.util.FeatureFlagUtils.isEnabled;

import android.annotation.NonNull;
import android.app.Notification;
@@ -33,7 +34,6 @@ import android.os.Parcel;
import android.os.Parcelable;
import android.os.UserHandle;
import android.text.TextUtils;
import android.util.FeatureFlagUtils;

import com.android.internal.logging.nano.MetricsProto;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -454,11 +454,23 @@ public class StatusBarNotification implements Parcelable {
        return conversationId;
    }

    private String getGroupLogTag() {
    /**
     *  Returns a probably-unique string based on the notification's group name,
     *  with no more than MAX_LOG_TAG_LENGTH characters.
     * @return String based on group name of notification.
     * @hide
     */
    public String getGroupLogTag() {
        return shortenTag(getGroup());
    }

    private String getChannelIdLogTag() {
    /**
     *  Returns a probably-unique string based on the notification's channel ID,
     *  with no more than MAX_LOG_TAG_LENGTH characters.
     * @return String based on channel ID of notification.
     * @hide
     */
    public String getChannelIdLogTag() {
        if (notification.getChannelId() == null) {
            return null;
        }
+25 −5
Original line number Diff line number Diff line
@@ -513,6 +513,7 @@ public class NotificationManagerService extends SystemService {
    private TriPredicate<String, Integer, String> mAllowedManagedServicePackages;

    private final SavePolicyFileRunnable mSavePolicyFile = new SavePolicyFileRunnable();
    private NotificationRecordLogger mNotificationRecordLogger;

    private static class Archive {
        final int mBufferSize;
@@ -1727,7 +1728,14 @@ public class NotificationManagerService extends SystemService {
    }

    public NotificationManagerService(Context context) {
        this(context, new NotificationRecordLoggerImpl());
    }

    @VisibleForTesting
    public NotificationManagerService(Context context,
            NotificationRecordLogger notificationRecordLogger) {
        super(context);
        mNotificationRecordLogger = notificationRecordLogger;
        Notification.processWhitelistToken = WHITELIST_TOKEN;
    }

@@ -6304,9 +6312,11 @@ public class NotificationManagerService extends SystemService {

                    mRankingHelper.extractSignals(r);
                    mRankingHelper.sort(mNotificationList);
                    final int position = mRankingHelper.indexOf(mNotificationList, r);

                    int buzzBeepBlinkLoggingCode = 0;
                    if (!r.isHidden()) {
                        buzzBeepBlinkLocked(r);
                        buzzBeepBlinkLoggingCode = buzzBeepBlinkLocked(r);
                    }

                    if (notification.getSmallIcon() != null) {
@@ -6346,6 +6356,10 @@ public class NotificationManagerService extends SystemService {
                    }

                    maybeRecordInterruptionLocked(r);

                    // Log event to statsd
                    mNotificationRecordLogger.logNotificationReported(r, old, position,
                            buzzBeepBlinkLoggingCode);
                } finally {
                    int N = mEnqueuedNotifications.size();
                    for (int i = 0; i < N; i++) {
@@ -6574,9 +6588,13 @@ public class NotificationManagerService extends SystemService {

    @VisibleForTesting
    @GuardedBy("mNotificationLock")
    void buzzBeepBlinkLocked(NotificationRecord record) {
    /**
     * Determine whether this notification should attempt to make noise, vibrate, or flash the LED
     * @return buzzBeepBlink - bitfield (buzz ? 1 : 0) | (beep ? 2 : 0) | (blink ? 4 : 0)
     */
    int buzzBeepBlinkLocked(NotificationRecord record) {
        if (mIsAutomotive && !mNotificationEffectsEnabledForAutomotive) {
            return;
            return 0;
        }
        boolean buzz = false;
        boolean beep = false;
@@ -6674,7 +6692,8 @@ public class NotificationManagerService extends SystemService {
        } else if (wasShowLights) {
            updateLightsLocked();
        }
        if (buzz || beep || blink) {
        final int buzzBeepBlink = (buzz ? 1 : 0) | (beep ? 2 : 0) | (blink ? 4 : 0);
        if (buzzBeepBlink > 0) {
            // Ignore summary updates because we don't display most of the information.
            if (record.sbn.isGroup() && record.sbn.getNotification().isGroupSummary()) {
                if (DEBUG_INTERRUPTIVENESS) {
@@ -6696,10 +6715,11 @@ public class NotificationManagerService extends SystemService {
            MetricsLogger.action(record.getLogMaker()
                    .setCategory(MetricsEvent.NOTIFICATION_ALERT)
                    .setType(MetricsEvent.TYPE_OPEN)
                    .setSubtype((buzz ? 1 : 0) | (beep ? 2 : 0) | (blink ? 4 : 0)));
                    .setSubtype(buzzBeepBlink));
            EventLogTags.writeNotificationAlert(key, buzz ? 1 : 0, beep ? 1 : 0, blink ? 1 : 0);
        }
        record.setAudiblyAlerted(buzz || beep);
        return buzzBeepBlink;
    }

    @GuardedBy("mNotificationLock")
+16 −0
Original line number Diff line number Diff line
@@ -675,6 +675,10 @@ public final class NotificationRecord {
        }
    }

    String getAdjustmentIssuer() {
        return mAdjustmentIssuer;
    }

    public void setIsAppImportanceLocked(boolean isAppImportanceLocked) {
        mIsAppImportanceLocked = isAppImportanceLocked;
        calculateUserSentiment();
@@ -783,10 +787,22 @@ public final class NotificationRecord {
        return mImportance;
    }

    int getInitialImportance() {
        return stats.naturalImportance;
    }

    public float getRankingScore() {
        return mRankingScore;
    }

    int getImportanceExplanationCode() {
        return mImportanceExplanationCode;
    }

    int getInitialImportanceExplanationCode() {
        return mInitialImportanceExplanationCode;
    }

    public CharSequence getImportanceExplanation() {
        switch (mImportanceExplanationCode) {
            case MetricsEvent.IMPORTANCE_EXPLANATION_UNKNOWN:
+142 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.notification;

import android.annotation.Nullable;
import android.app.Notification;
import android.app.Person;
import android.os.Bundle;

import com.android.internal.logging.UiEvent;
import com.android.internal.logging.UiEventLogger;

import java.util.ArrayList;
import java.util.Objects;

/**
 * Interface for writing NotificationReported atoms to statsd log.
 * @hide
 */
public interface NotificationRecordLogger {

    /**
     * Logs a NotificationReported atom reflecting the posting or update of a notification.
     * @param r The new NotificationRecord. If null, no action is taken.
     * @param old The previous NotificationRecord.  Null if there was no previous record.
     * @param position The position at which this notification is ranked.
     * @param buzzBeepBlink Logging code reflecting whether this notification alerted the user.
     */
    void logNotificationReported(@Nullable NotificationRecord r, @Nullable NotificationRecord old,
            int position, int buzzBeepBlink);

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

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

    /**
     * A helper for extracting logging information from one or two NotificationRecords.
     */
    class NotificationRecordPair {
        public final NotificationRecord r, old;
         /**
         * Construct from one or two NotificationRecords.
         * @param r The new NotificationRecord.  If null, only shouldLog() method is usable.
         * @param old The previous NotificationRecord.  Null if there was no previous record.
         */
        NotificationRecordPair(@Nullable NotificationRecord r, @Nullable NotificationRecord old) {
            this.r = r;
            this.old = old;
        }

        /**
         * @return True if old is null, alerted, or important logged fields have changed.
         */
        boolean shouldLog(int buzzBeepBlink) {
            if (r == null) {
                return false;
            }
            if ((old == null) || (buzzBeepBlink > 0)) {
                return true;
            }

            return !(Objects.equals(r.sbn.getChannelIdLogTag(), old.sbn.getChannelIdLogTag())
                    && Objects.equals(r.sbn.getGroupLogTag(), old.sbn.getGroupLogTag())
                    && (r.sbn.getNotification().isGroupSummary()
                        == old.sbn.getNotification().isGroupSummary())
                    && Objects.equals(r.sbn.getNotification().category,
                        old.sbn.getNotification().category)
                    && (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.
         */
        public int getStyle() {
            return getStyle(r.sbn.getNotification().extras);
        }

        private int getStyle(@Nullable Bundle extras) {
            if (extras != null) {
                String template = extras.getString(Notification.EXTRA_TEMPLATE);
                if (template != null && !template.isEmpty()) {
                    return template.hashCode();
                }
            }
            return 0;
        }

        int getNumPeople() {
            return getNumPeople(r.sbn.getNotification().extras);
        }

        private int getNumPeople(@Nullable Bundle extras) {
            if (extras != null) {
                ArrayList<Person> people = extras.getParcelableArrayList(
                        Notification.EXTRA_PEOPLE_LIST);
                if (people != null && !people.isEmpty()) {
                    return people.size();
                }
            }
            return 0;
        }

        int getAssistantHash() {
            String assistant = r.getAdjustmentIssuer();
            return (assistant == null) ? 0 : assistant.hashCode();
        }
    }
}
+69 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.notification;

import android.util.StatsLog;

/**
 * Standard implementation of NotificationRecordLogger interface.
 * @hide
 */
public class NotificationRecordLoggerImpl implements NotificationRecordLogger {

    @Override
    public void logNotificationReported(NotificationRecord r, NotificationRecord old,
            int position, int buzzBeepBlink) {
        NotificationRecordPair p = new NotificationRecordPair(r, old);
        if (!p.shouldLog(buzzBeepBlink)) {
            return;
        }
        StatsLog.write(StatsLog.NOTIFICATION_REPORTED,
                /* int32 event_id = 1 */ p.getUiEvent().getId(),
                /* int32 uid = 2 */ r.getUid(),
                /* string package_name = 3 */ r.sbn.getPackageName(),
                /* int32 instance_id = 4 */ 0,  // TODO generate and fill instance ids
                /* int32 notification_id = 5 */ r.sbn.getId(),
                /* string notification_tag = 6 */ r.sbn.getTag(),
                /* string channel_id = 7 */ r.sbn.getChannelIdLogTag(),
                /* string group_id = 8 */ r.sbn.getGroupLogTag(),
                /* int32 group_instance_id = 9 */ 0, // TODO generate and fill instance ids
                /* bool is_group_summary = 10 */ r.sbn.getNotification().isGroupSummary(),
                /* string category = 11 */ r.sbn.getNotification().category,
                /* int32 style = 12 */ p.getStyle(),
                /* int32 num_people = 13 */ p.getNumPeople(),
                /* int32 position = 14 */ position,
                /* android.stats.sysui.NotificationImportance importance = 15 */ r.getImportance(),
                /* int32 alerting = 16 */ buzzBeepBlink,
                /* NotificationImportanceExplanation importance_source = 17 */
                r.getImportanceExplanationCode(),
                /* android.stats.sysui.NotificationImportance importance_initial = 18 */
                r.getInitialImportance(),
                /* NotificationImportanceExplanation importance_initial_source = 19 */
                r.getInitialImportanceExplanationCode(),
                /* android.stats.sysui.NotificationImportance importance_asst = 20 */
                r.getAssistantImportance(),
                /* int32 assistant_hash = 21 */ p.getAssistantHash(),
                /* float assistant_ranking_score = 22 */ 0  // TODO connect up ranking score
        );
    }






}
Loading