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

Commit 6c5a5207 authored by Beverly's avatar Beverly
Browse files

Create NotifLog

Test: atest SystemUiTests
Bug: 141470043
Change-Id: I7ce99e998f0cc09da0fa4f111b8357d803e104a5
parent 4bec4b2f
Loading
Loading
Loading
Loading
+153 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 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.systemui.statusbar.notification.logging;

import android.annotation.IntDef;
import android.service.notification.NotificationListenerService.Ranking;
import android.service.notification.StatusBarNotification;

import com.android.systemui.log.RichEvent;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

/**
 * An event related to notifications. {@link NotifLog} stores and prints these events for debugging
 * and triaging purposes.
 */
public class NotifEvent extends RichEvent {
    public static final int TOTAL_EVENT_TYPES = 8;
    private StatusBarNotification mSbn;
    private Ranking mRanking;

    /**
     * Creates a NotifEvent with an event type that matches with an index in the array
     * getSupportedEvents() and {@link EventType}.
     *
     * The status bar notification and ranking objects are stored as shallow copies of the current
     * state of the event when this event occurred.
     */
    public NotifEvent(int logLevel, int type, String reason, StatusBarNotification sbn,
            Ranking ranking) {
        super(logLevel, type, reason);
        mSbn = sbn.clone();
        mRanking = new Ranking();
        mRanking.populate(ranking);
        mMessage += getExtraInfo();
    }

    private String getExtraInfo() {
        StringBuilder extraInfo = new StringBuilder();

        if (mSbn != null) {
            extraInfo.append(" Sbn=");
            extraInfo.append(mSbn);
        }

        if (mRanking != null) {
            extraInfo.append(" Ranking=");
            extraInfo.append(mRanking);
        }

        return extraInfo.toString();
    }

    /**
     * Event labels for NotifEvents
     * Index corresponds to the {@link EventType}
     */
    @Override
    public String[] getEventLabels() {
        final String[] events = new String[]{
                "NotifAdded",
                "NotifRemoved",
                "NotifUpdated",
                "HeadsUpStarted",
                "HeadsUpEnded",
                "Filter",
                "Sort",
                "NotifVisibilityChanged",
        };

        if (events.length != TOTAL_EVENT_TYPES) {
            throw new IllegalStateException("NotifEvents events.length should match "
                    + TOTAL_EVENT_TYPES
                    + " events.length=" + events.length
                    + " TOTAL_EVENT_LENGTH=" + TOTAL_EVENT_TYPES);
        }
        return events;
    }

    /**
     * @return a copy of the status bar notification that changed with this event
     */
    public StatusBarNotification getSbn() {
        return mSbn;
    }

    /**
     * Builds a NotifEvent.
     */
    public static class NotifEventBuilder extends RichEvent.Builder<NotifEventBuilder> {
        private StatusBarNotification mSbn;
        private Ranking mRanking;

        @Override
        public NotifEventBuilder getBuilder() {
            return this;
        }

        /**
         * Stores the status bar notification object. A shallow copy is stored in the NotifEvent's
         * constructor.
         */
        public NotifEventBuilder setSbn(StatusBarNotification sbn) {
            mSbn = sbn;
            return this;
        }

        /**
         * Stores the ranking object. A shallow copy is stored in the NotifEvent's
         * constructor.
         */
        public NotifEventBuilder setRanking(Ranking ranking) {
            mRanking = ranking;
            return this;
        }

        @Override
        public RichEvent build() {
            return new NotifEvent(mLogLevel, mType, mReason, mSbn, mRanking);
        }
    }

    @IntDef({NOTIF_ADDED, NOTIF_REMOVED, NOTIF_UPDATED, HEADS_UP_STARTED, HEADS_UP_ENDED, FILTER,
            SORT, NOTIF_VISIBILITY_CHANGED})
    /**
     * Types of NotifEvents
     */
    @Retention(RetentionPolicy.SOURCE)
    public @interface EventType {}
    public static final int NOTIF_ADDED = 0;
    public static final int NOTIF_REMOVED = 1;
    public static final int NOTIF_UPDATED = 2;
    public static final int HEADS_UP_STARTED = 3;
    public static final int HEADS_UP_ENDED = 4;
    public static final int FILTER = 5;
    public static final int SORT = 6;
    public static final int NOTIF_VISIBILITY_CHANGED = 7;
}
+117 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 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.systemui.statusbar.notification.logging;

import android.service.notification.NotificationListenerService.Ranking;
import android.service.notification.StatusBarNotification;

import com.android.systemui.DumpController;
import com.android.systemui.log.SysuiLog;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;

import javax.inject.Inject;
import javax.inject.Singleton;

/**
 * Logs systemui notification events for debugging and triaging purposes. Logs are dumped in
 * bugreports or on demand:
 *      adb shell dumpsys activity service com.android.systemui/.SystemUIService \
 *      dependency DumpController NotifLog
 */
@Singleton
public class NotifLog extends SysuiLog {
    private static final String TAG = "NotifLog";
    private static final int MAX_DOZE_DEBUG_LOGS = 400;
    private static final int MAX_DOZE_LOGS = 50;

    @Inject
    public NotifLog(DumpController dumpController) {
        super(dumpController, TAG, MAX_DOZE_DEBUG_LOGS, MAX_DOZE_LOGS);
    }

    /**
     * Logs a {@link NotifEvent} with a notification, ranking and message
     * @return true if successfully logged, else false
     */
    public boolean log(@NotifEvent.EventType int eventType, StatusBarNotification sbn,
            Ranking ranking, String msg) {
        return log(new NotifEvent.NotifEventBuilder()
                .setType(eventType)
                .setSbn(sbn)
                .setRanking(ranking)
                .setReason(msg)
                .build());
    }

    /**
     * Logs a {@link NotifEvent}
     * @return true if successfully logged, else false
     */
    public boolean log(@NotifEvent.EventType int eventType) {
        return log(eventType, null, null, null);
    }

    /**
     * Logs a {@link NotifEvent} with a message
     * @return true if successfully logged, else false
     */
    public boolean log(@NotifEvent.EventType int eventType, String msg) {
        return log(eventType, null, null, msg);
    }

    /**
     * Logs a {@link NotifEvent} with a notification
     * @return true if successfully logged, else false
     */
    public boolean log(@NotifEvent.EventType int eventType, StatusBarNotification sbn) {
        return log(eventType, sbn, null, "");
    }

    /**
     * Logs a {@link NotifEvent} with a ranking
     * @return true if successfully logged, else false
     */
    public boolean log(@NotifEvent.EventType int eventType, Ranking ranking) {
        return log(eventType, null, ranking, "");
    }

    /**
     * Logs a {@link NotifEvent} with a notification and ranking
     * @return true if successfully logged, else false
     */
    public boolean log(@NotifEvent.EventType int eventType, StatusBarNotification sbn,
            Ranking ranking) {
        return log(eventType, sbn, ranking, "");
    }

    /**
     * Logs a {@link NotifEvent} with a notification entry
     * @return true if successfully logged, else false
     */
    public boolean log(@NotifEvent.EventType int eventType, NotificationEntry entry) {
        return log(eventType, entry.sbn(), entry.ranking(), "");
    }

    /**
     * Logs a {@link NotifEvent} with a notification entry
     * @return true if successfully logged, else false
     */
    public boolean log(@NotifEvent.EventType int eventType, NotificationEntry entry,
            String msg) {
        return log(eventType, entry.sbn(), entry.ranking(), msg);
    }
}