Move NEM and friends over to LogBuffer
Test: atest Change-Id: I276d1253094ac160b3738bf01fc00bc94d767756
This commit is contained in:
@@ -1,84 +0,0 @@
|
||||
/*
|
||||
* 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.log;
|
||||
|
||||
import android.annotation.IntDef;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
/**
|
||||
* Stores information about an event that occurred in SystemUI to be used for debugging and triage.
|
||||
* Every event has a time stamp, log level and message.
|
||||
* Events are stored in {@link SysuiLog} and can be printed in a dumpsys.
|
||||
*/
|
||||
public class Event {
|
||||
public static final int UNINITIALIZED = -1;
|
||||
|
||||
@IntDef({ERROR, WARN, INFO, DEBUG, VERBOSE})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface Level {}
|
||||
public static final int VERBOSE = 2;
|
||||
public static final int DEBUG = 3;
|
||||
public static final int INFO = 4;
|
||||
public static final int WARN = 5;
|
||||
public static final int ERROR = 6;
|
||||
public static final @Level int DEFAULT_LOG_LEVEL = DEBUG;
|
||||
|
||||
private long mTimestamp;
|
||||
private @Level int mLogLevel = DEFAULT_LOG_LEVEL;
|
||||
private String mMessage = "";
|
||||
|
||||
/**
|
||||
* initialize an event with a message
|
||||
*/
|
||||
public Event init(String message) {
|
||||
init(DEFAULT_LOG_LEVEL, message);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* initialize an event with a logLevel and message
|
||||
*/
|
||||
public Event init(@Level int logLevel, String message) {
|
||||
mTimestamp = System.currentTimeMillis();
|
||||
mLogLevel = logLevel;
|
||||
mMessage = message;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return mMessage;
|
||||
}
|
||||
|
||||
public long getTimestamp() {
|
||||
return mTimestamp;
|
||||
}
|
||||
|
||||
public @Level int getLogLevel() {
|
||||
return mLogLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recycle this event
|
||||
*/
|
||||
void recycle() {
|
||||
mTimestamp = -1;
|
||||
mLogLevel = DEFAULT_LOG_LEVEL;
|
||||
mMessage = "";
|
||||
}
|
||||
}
|
||||
@@ -1,123 +0,0 @@
|
||||
/*
|
||||
* 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.log;
|
||||
|
||||
/**
|
||||
* Stores information about an event that occurred in SystemUI to be used for debugging and triage.
|
||||
* Every rich event has a time stamp, event type, and log level, with the option to provide the
|
||||
* reason this event was triggered.
|
||||
* Events are stored in {@link SysuiLog} and can be printed in a dumpsys.
|
||||
*/
|
||||
public abstract class RichEvent extends Event {
|
||||
private int mType;
|
||||
|
||||
/**
|
||||
* Initializes a rich event that includes an event type that matches with an index in the array
|
||||
* getEventLabels().
|
||||
*/
|
||||
public RichEvent init(@Event.Level int logLevel, int type, String reason) {
|
||||
final int numEvents = getEventLabels().length;
|
||||
if (type < 0 || type >= numEvents) {
|
||||
throw new IllegalArgumentException("Unsupported event type. Events only supported"
|
||||
+ " from 0 to " + (numEvents - 1) + ", but given type=" + type);
|
||||
}
|
||||
mType = type;
|
||||
super.init(logLevel, getEventLabels()[mType] + " " + reason);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of the event labels. The index represents the event type and the
|
||||
* corresponding String stored at that index is the user-readable representation of that event.
|
||||
* @return array of user readable events, where the index represents its event type constant
|
||||
*/
|
||||
public abstract String[] getEventLabels();
|
||||
|
||||
@Override
|
||||
public void recycle() {
|
||||
super.recycle();
|
||||
mType = -1;
|
||||
}
|
||||
|
||||
public int getType() {
|
||||
return mType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builder to build a RichEvent.
|
||||
* @param <B> Log specific builder that is extending this builder
|
||||
* @param <E> Type of event we'll be building
|
||||
*/
|
||||
public abstract static class Builder<B extends Builder<B, E>, E extends RichEvent> {
|
||||
public static final int UNINITIALIZED = -1;
|
||||
|
||||
public final SysuiLog mLog;
|
||||
private B mBuilder = getBuilder();
|
||||
protected int mType;
|
||||
protected String mReason;
|
||||
protected @Level int mLogLevel;
|
||||
|
||||
public Builder(SysuiLog sysuiLog) {
|
||||
mLog = sysuiLog;
|
||||
reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset this builder's parameters so it can be reused to build another RichEvent.
|
||||
*/
|
||||
public void reset() {
|
||||
mType = UNINITIALIZED;
|
||||
mReason = null;
|
||||
mLogLevel = VERBOSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the log-specific builder.
|
||||
*/
|
||||
public abstract B getBuilder();
|
||||
|
||||
/**
|
||||
* Build the log-specific event given an event to populate.
|
||||
*/
|
||||
public abstract E build(E e);
|
||||
|
||||
/**
|
||||
* Optional - set the log level. Defaults to DEBUG.
|
||||
*/
|
||||
public B setLogLevel(@Level int logLevel) {
|
||||
mLogLevel = logLevel;
|
||||
return mBuilder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Required - set the event type. These events must correspond with the events from
|
||||
* getEventLabels().
|
||||
*/
|
||||
public B setType(int type) {
|
||||
mType = type;
|
||||
return mBuilder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Optional - set the reason why this event was triggered.
|
||||
*/
|
||||
public B setReason(String reason) {
|
||||
mReason = reason;
|
||||
return mBuilder;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,180 +0,0 @@
|
||||
/*
|
||||
* 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.log;
|
||||
|
||||
import android.os.Build;
|
||||
import android.os.SystemProperties;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.systemui.DumpController;
|
||||
import com.android.systemui.Dumpable;
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.PrintWriter;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* Thread-safe logger in SystemUI which prints logs to logcat and stores logs to be
|
||||
* printed by the DumpController. This is an alternative to printing directly
|
||||
* to avoid logs being deleted by chatty. The number of logs retained is varied based on
|
||||
* whether the build is {@link Build.IS_DEBUGGABLE}.
|
||||
*
|
||||
* To manually view the logs via adb:
|
||||
* adb shell dumpsys activity service com.android.systemui/.SystemUIService \
|
||||
* dependency DumpController <SysuiLogId>
|
||||
*
|
||||
* Logs can be disabled by setting the following SystemProperty and then restarting the device:
|
||||
* adb shell setprop persist.sysui.log.enabled.<id> true/false && adb reboot
|
||||
*
|
||||
* @param <E> Type of event we'll be logging
|
||||
*/
|
||||
public class SysuiLog<E extends Event> implements Dumpable {
|
||||
public static final SimpleDateFormat DATE_FORMAT =
|
||||
new SimpleDateFormat("MM-dd HH:mm:ss.S", Locale.US);
|
||||
|
||||
protected final Object mDataLock = new Object();
|
||||
private final String mId;
|
||||
private final int mMaxLogs;
|
||||
protected boolean mEnabled;
|
||||
protected boolean mLogToLogcatEnabled;
|
||||
|
||||
@VisibleForTesting protected ArrayDeque<E> mTimeline;
|
||||
|
||||
/**
|
||||
* Creates a SysuiLog
|
||||
* @param dumpController where to register this logger's dumpsys
|
||||
* @param id user-readable tag for this logger
|
||||
* @param maxDebugLogs maximum number of logs to retain when {@link sDebuggable} is true
|
||||
* @param maxLogs maximum number of logs to retain when {@link sDebuggable} is false
|
||||
*/
|
||||
public SysuiLog(DumpController dumpController, String id, int maxDebugLogs, int maxLogs) {
|
||||
this(dumpController, id, sDebuggable ? maxDebugLogs : maxLogs,
|
||||
SystemProperties.getBoolean(SYSPROP_ENABLED_PREFIX + id, DEFAULT_ENABLED),
|
||||
SystemProperties.getBoolean(SYSPROP_LOGCAT_ENABLED_PREFIX + id,
|
||||
DEFAULT_LOGCAT_ENABLED));
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
protected SysuiLog(DumpController dumpController, String id, int maxLogs, boolean enabled,
|
||||
boolean logcatEnabled) {
|
||||
mId = id;
|
||||
mMaxLogs = maxLogs;
|
||||
mEnabled = enabled;
|
||||
mLogToLogcatEnabled = logcatEnabled;
|
||||
mTimeline = mEnabled ? new ArrayDeque<>(mMaxLogs) : null;
|
||||
dumpController.registerDumpable(mId, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs an event to the timeline which can be printed by the dumpsys.
|
||||
* May also log to logcat if enabled.
|
||||
* @return the last event that was discarded from the Timeline (can be recycled)
|
||||
*/
|
||||
public E log(E event) {
|
||||
if (!mEnabled) {
|
||||
return null;
|
||||
}
|
||||
|
||||
E recycledEvent = null;
|
||||
synchronized (mDataLock) {
|
||||
if (mTimeline.size() >= mMaxLogs) {
|
||||
recycledEvent = mTimeline.removeFirst();
|
||||
}
|
||||
|
||||
mTimeline.add(event);
|
||||
}
|
||||
|
||||
if (mLogToLogcatEnabled) {
|
||||
final String strEvent = eventToString(event);
|
||||
switch (event.getLogLevel()) {
|
||||
case Event.VERBOSE:
|
||||
Log.v(mId, strEvent);
|
||||
break;
|
||||
case Event.DEBUG:
|
||||
Log.d(mId, strEvent);
|
||||
break;
|
||||
case Event.ERROR:
|
||||
Log.e(mId, strEvent);
|
||||
break;
|
||||
case Event.INFO:
|
||||
Log.i(mId, strEvent);
|
||||
break;
|
||||
case Event.WARN:
|
||||
Log.w(mId, strEvent);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (recycledEvent != null) {
|
||||
recycledEvent.recycle();
|
||||
}
|
||||
|
||||
return recycledEvent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return user-readable string of the given event with timestamp
|
||||
*/
|
||||
private String eventToTimestampedString(Event event) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(SysuiLog.DATE_FORMAT.format(event.getTimestamp()));
|
||||
sb.append(" ");
|
||||
sb.append(event.getMessage());
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return user-readable string of the given event without a timestamp
|
||||
*/
|
||||
public String eventToString(Event event) {
|
||||
return event.getMessage();
|
||||
}
|
||||
|
||||
@GuardedBy("mDataLock")
|
||||
private void dumpTimelineLocked(PrintWriter pw) {
|
||||
pw.println("\tTimeline:");
|
||||
|
||||
for (Event event : mTimeline) {
|
||||
pw.println("\t" + eventToTimestampedString(event));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
|
||||
pw.println(mId + ":");
|
||||
|
||||
if (mEnabled) {
|
||||
synchronized (mDataLock) {
|
||||
dumpTimelineLocked(pw);
|
||||
}
|
||||
} else {
|
||||
pw.print(" - Logging disabled.");
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean sDebuggable = Build.IS_DEBUGGABLE;
|
||||
private static final String SYSPROP_ENABLED_PREFIX = "persist.sysui.log.enabled.";
|
||||
private static final String SYSPROP_LOGCAT_ENABLED_PREFIX = "persist.sysui.log.enabled.logcat.";
|
||||
private static final boolean DEFAULT_ENABLED = sDebuggable;
|
||||
private static final boolean DEFAULT_LOGCAT_ENABLED = false;
|
||||
private static final int DEFAULT_MAX_DEBUG_LOGS = 100;
|
||||
private static final int DEFAULT_MAX_LOGS = 50;
|
||||
}
|
||||
@@ -47,8 +47,6 @@ import com.android.systemui.statusbar.notification.collection.NotificationRankin
|
||||
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.NotifCollectionListener;
|
||||
import com.android.systemui.statusbar.notification.logging.NotifEvent;
|
||||
import com.android.systemui.statusbar.notification.logging.NotifLog;
|
||||
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
|
||||
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
|
||||
import com.android.systemui.statusbar.phone.NotificationGroupManager;
|
||||
@@ -129,6 +127,8 @@ public class NotificationEntryManager implements
|
||||
private final Map<NotificationEntry, NotificationLifetimeExtender> mRetainedNotifications =
|
||||
new ArrayMap<>();
|
||||
|
||||
private final NotificationEntryManagerLogger mLogger;
|
||||
|
||||
// Lazily retrieved dependencies
|
||||
private final Lazy<NotificationRowBinder> mNotificationRowBinderLazy;
|
||||
private final Lazy<NotificationRemoteInputManager> mRemoteInputManagerLazy;
|
||||
@@ -143,7 +143,6 @@ public class NotificationEntryManager implements
|
||||
|
||||
private NotificationPresenter mPresenter;
|
||||
private RankingMap mLatestRankingMap;
|
||||
private NotifLog mNotifLog;
|
||||
|
||||
@VisibleForTesting
|
||||
final ArrayList<NotificationLifetimeExtender> mNotificationLifetimeExtenders
|
||||
@@ -184,7 +183,7 @@ public class NotificationEntryManager implements
|
||||
|
||||
@Inject
|
||||
public NotificationEntryManager(
|
||||
NotifLog notifLog,
|
||||
NotificationEntryManagerLogger logger,
|
||||
NotificationGroupManager groupManager,
|
||||
NotificationRankingManager rankingManager,
|
||||
KeyguardEnvironment keyguardEnvironment,
|
||||
@@ -193,7 +192,7 @@ public class NotificationEntryManager implements
|
||||
Lazy<NotificationRemoteInputManager> notificationRemoteInputManagerLazy,
|
||||
LeakDetector leakDetector,
|
||||
ForegroundServiceDismissalFeatureController fgsFeatureController) {
|
||||
mNotifLog = notifLog;
|
||||
mLogger = logger;
|
||||
mGroupManager = groupManager;
|
||||
mRankingManager = rankingManager;
|
||||
mKeyguardEnvironment = keyguardEnvironment;
|
||||
@@ -291,13 +290,12 @@ public class NotificationEntryManager implements
|
||||
NotificationEntry entry = mPendingNotifications.get(key);
|
||||
entry.abortTask();
|
||||
mPendingNotifications.remove(key);
|
||||
mNotifLog.log(NotifEvent.INFLATION_ABORTED, entry, "PendingNotification aborted"
|
||||
+ " reason=" + reason);
|
||||
mLogger.logInflationAborted(key, "pending", reason);
|
||||
}
|
||||
NotificationEntry addedEntry = getActiveNotificationUnfiltered(key);
|
||||
if (addedEntry != null) {
|
||||
addedEntry.abortTask();
|
||||
mNotifLog.log(NotifEvent.INFLATION_ABORTED, addedEntry.getKey() + " " + reason);
|
||||
mLogger.logInflationAborted(key, "active", reason);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -328,9 +326,9 @@ public class NotificationEntryManager implements
|
||||
// the list, otherwise we might get leaks.
|
||||
if (!entry.isRowRemoved()) {
|
||||
boolean isNew = getActiveNotificationUnfiltered(entry.getKey()) == null;
|
||||
mLogger.logNotifInflated(entry.getKey(), isNew);
|
||||
if (isNew) {
|
||||
for (NotificationEntryListener listener : mNotificationEntryListeners) {
|
||||
mNotifLog.log(NotifEvent.INFLATED, entry);
|
||||
listener.onEntryInflated(entry);
|
||||
}
|
||||
addActiveNotification(entry);
|
||||
@@ -340,7 +338,6 @@ public class NotificationEntryManager implements
|
||||
}
|
||||
} else {
|
||||
for (NotificationEntryListener listener : mNotificationEntryListeners) {
|
||||
mNotifLog.log(NotifEvent.INFLATED, entry);
|
||||
listener.onEntryReinflated(entry);
|
||||
}
|
||||
}
|
||||
@@ -422,7 +419,7 @@ public class NotificationEntryManager implements
|
||||
for (NotificationRemoveInterceptor interceptor : mRemoveInterceptors) {
|
||||
if (interceptor.onNotificationRemoveRequested(key, entry, reason)) {
|
||||
// Remove intercepted; log and skip
|
||||
mNotifLog.log(NotifEvent.REMOVE_INTERCEPTED);
|
||||
mLogger.logRemovalIntercepted(key);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -437,10 +434,7 @@ public class NotificationEntryManager implements
|
||||
if (extender.shouldExtendLifetimeForPendingNotification(pendingEntry)) {
|
||||
extendLifetime(pendingEntry, extender);
|
||||
lifetimeExtended = true;
|
||||
mNotifLog.log(
|
||||
NotifEvent.LIFETIME_EXTENDED,
|
||||
pendingEntry.getSbn(),
|
||||
"pendingEntry extendedBy=" + extender.toString());
|
||||
mLogger.logLifetimeExtended(key, extender.getClass().getName(), "pending");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -460,10 +454,7 @@ public class NotificationEntryManager implements
|
||||
mLatestRankingMap = ranking;
|
||||
extendLifetime(entry, extender);
|
||||
lifetimeExtended = true;
|
||||
mNotifLog.log(
|
||||
NotifEvent.LIFETIME_EXTENDED,
|
||||
entry.getSbn(),
|
||||
"entry extendedBy=" + extender.toString());
|
||||
mLogger.logLifetimeExtended(key, extender.getClass().getName(), "active");
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -486,8 +477,7 @@ public class NotificationEntryManager implements
|
||||
mLeakDetector.trackGarbage(entry);
|
||||
removedByUser |= entryDismissed;
|
||||
|
||||
mNotifLog.log(NotifEvent.NOTIF_REMOVED, entry.getSbn(),
|
||||
"removedByUser=" + removedByUser);
|
||||
mLogger.logNotifRemoved(entry.getKey(), removedByUser);
|
||||
for (NotificationEntryListener listener : mNotificationEntryListeners) {
|
||||
listener.onEntryRemoved(entry, visibility, removedByUser);
|
||||
}
|
||||
@@ -576,7 +566,7 @@ public class NotificationEntryManager implements
|
||||
|
||||
abortExistingInflation(key, "addNotification");
|
||||
mPendingNotifications.put(key, entry);
|
||||
mNotifLog.log(NotifEvent.NOTIF_ADDED, entry);
|
||||
mLogger.logNotifAdded(entry.getKey());
|
||||
for (NotificationEntryListener listener : mNotificationEntryListeners) {
|
||||
listener.onPendingEntryAdded(entry);
|
||||
}
|
||||
@@ -613,7 +603,7 @@ public class NotificationEntryManager implements
|
||||
entry.setSbn(notification);
|
||||
mGroupManager.onEntryUpdated(entry, oldSbn);
|
||||
|
||||
mNotifLog.log(NotifEvent.NOTIF_UPDATED, entry);
|
||||
mLogger.logNotifUpdated(entry.getKey());
|
||||
for (NotificationEntryListener listener : mNotificationEntryListeners) {
|
||||
listener.onPreEntryUpdated(entry);
|
||||
}
|
||||
@@ -808,7 +798,7 @@ public class NotificationEntryManager implements
|
||||
//TODO: Get rid of this in favor of NotificationUpdateHandler#updateNotificationRanking
|
||||
/**
|
||||
* @param rankingMap the {@link RankingMap} to apply to the current notification list
|
||||
* @param reason the reason for calling this method, for {@link NotifLog}
|
||||
* @param reason the reason for calling this method, which will be logged
|
||||
*/
|
||||
public void updateRanking(RankingMap rankingMap, String reason) {
|
||||
updateRankingAndSort(rankingMap, reason);
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* 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.systemui.statusbar.notification
|
||||
|
||||
import com.android.systemui.log.LogBuffer
|
||||
import com.android.systemui.log.LogLevel.DEBUG
|
||||
import com.android.systemui.log.LogLevel.INFO
|
||||
import com.android.systemui.log.dagger.NotificationLog
|
||||
import javax.inject.Inject
|
||||
|
||||
/** Logger for [NotificationEntryManager]. */
|
||||
class NotificationEntryManagerLogger @Inject constructor(
|
||||
@NotificationLog private val buffer: LogBuffer
|
||||
) {
|
||||
fun logNotifAdded(key: String) {
|
||||
buffer.log(TAG, INFO, {
|
||||
str1 = key
|
||||
}, {
|
||||
"NOTIF ADDED $str1"
|
||||
})
|
||||
}
|
||||
|
||||
fun logNotifUpdated(key: String) {
|
||||
buffer.log(TAG, INFO, {
|
||||
str1 = key
|
||||
}, {
|
||||
"NOTIF UPDATED $str1"
|
||||
})
|
||||
}
|
||||
|
||||
fun logInflationAborted(key: String, status: String, reason: String) {
|
||||
buffer.log(TAG, DEBUG, {
|
||||
str1 = key
|
||||
str2 = status
|
||||
str3 = reason
|
||||
}, {
|
||||
"NOTIF INFLATION ABORTED $str1 notifStatus=$str2 reason=$str3"
|
||||
})
|
||||
}
|
||||
|
||||
fun logNotifInflated(key: String, isNew: Boolean) {
|
||||
buffer.log(TAG, DEBUG, {
|
||||
str1 = key
|
||||
bool1 = isNew
|
||||
}, {
|
||||
"NOTIF INFLATED $str1 isNew=$bool1}"
|
||||
})
|
||||
}
|
||||
|
||||
fun logRemovalIntercepted(key: String) {
|
||||
buffer.log(TAG, INFO, {
|
||||
str1 = key
|
||||
}, {
|
||||
"NOTIF REMOVE INTERCEPTED for $str1"
|
||||
})
|
||||
}
|
||||
|
||||
fun logLifetimeExtended(key: String, extenderName: String, status: String) {
|
||||
buffer.log(TAG, INFO, {
|
||||
str1 = key
|
||||
str2 = extenderName
|
||||
str3 = status
|
||||
}, {
|
||||
"NOTIF LIFETIME EXTENDED $str1 extender=$str2 status=$str3"
|
||||
})
|
||||
}
|
||||
|
||||
fun logNotifRemoved(key: String, removedByUser: Boolean) {
|
||||
buffer.log(TAG, INFO, {
|
||||
str1 = key
|
||||
bool1 = removedByUser
|
||||
}, {
|
||||
"NOTIF REMOVED $str1 removedByUser=$bool1"
|
||||
})
|
||||
}
|
||||
|
||||
fun logFilterAndSort(reason: String) {
|
||||
buffer.log(TAG, INFO, {
|
||||
str1 = reason
|
||||
}, {
|
||||
"FILTER AND SORT reason=$str1"
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
private const val TAG = "NotificationEntryMgr"
|
||||
@@ -22,11 +22,10 @@ import android.service.notification.NotificationListenerService.Ranking
|
||||
import android.service.notification.NotificationListenerService.RankingMap
|
||||
import android.service.notification.StatusBarNotification
|
||||
import com.android.systemui.statusbar.NotificationMediaManager
|
||||
import com.android.systemui.statusbar.notification.NotificationEntryManagerLogger
|
||||
import com.android.systemui.statusbar.notification.NotificationFilter
|
||||
import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager
|
||||
import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider
|
||||
import com.android.systemui.statusbar.notification.logging.NotifEvent
|
||||
import com.android.systemui.statusbar.notification.logging.NotifLog
|
||||
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier
|
||||
import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_ALERTING
|
||||
import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_PEOPLE
|
||||
@@ -53,7 +52,7 @@ open class NotificationRankingManager @Inject constructor(
|
||||
private val groupManager: NotificationGroupManager,
|
||||
private val headsUpManager: HeadsUpManager,
|
||||
private val notifFilter: NotificationFilter,
|
||||
private val notifLog: NotifLog,
|
||||
private val logger: NotificationEntryManagerLogger,
|
||||
sectionsFeatureManager: NotificationSectionsFeatureManager,
|
||||
private val peopleNotificationIdentifier: PeopleNotificationIdentifier,
|
||||
private val highPriorityProvider: HighPriorityProvider
|
||||
@@ -134,7 +133,7 @@ open class NotificationRankingManager @Inject constructor(
|
||||
entries: Sequence<NotificationEntry>,
|
||||
reason: String
|
||||
): Sequence<NotificationEntry> {
|
||||
notifLog.log(NotifEvent.FILTER_AND_SORT, reason)
|
||||
logger.logFilterAndSort(reason)
|
||||
|
||||
return entries.filter { !notifFilter.shouldFilterOut(it) }
|
||||
.sortedWith(rankingComparator)
|
||||
|
||||
@@ -22,8 +22,6 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry;
|
||||
import com.android.systemui.statusbar.notification.collection.inflation.NotifInflater;
|
||||
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
|
||||
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
|
||||
import com.android.systemui.statusbar.notification.logging.NotifEvent;
|
||||
import com.android.systemui.statusbar.notification.logging.NotifLog;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -42,13 +40,15 @@ import javax.inject.Singleton;
|
||||
public class PreparationCoordinator implements Coordinator {
|
||||
private static final String TAG = "PreparationCoordinator";
|
||||
|
||||
private final NotifLog mNotifLog;
|
||||
private final PreparationCoordinatorLogger mLogger;
|
||||
private final NotifInflater mNotifInflater;
|
||||
private final List<NotificationEntry> mPendingNotifications = new ArrayList<>();
|
||||
|
||||
@Inject
|
||||
public PreparationCoordinator(NotifLog notifLog, NotifInflaterImpl notifInflater) {
|
||||
mNotifLog = notifLog;
|
||||
public PreparationCoordinator(
|
||||
PreparationCoordinatorLogger logger,
|
||||
NotifInflaterImpl notifInflater) {
|
||||
mLogger = logger;
|
||||
mNotifInflater = notifInflater;
|
||||
mNotifInflater.setInflationCallback(mInflationCallback);
|
||||
}
|
||||
@@ -106,7 +106,7 @@ public class PreparationCoordinator implements Coordinator {
|
||||
new NotifInflater.InflationCallback() {
|
||||
@Override
|
||||
public void onInflationFinished(NotificationEntry entry) {
|
||||
mNotifLog.log(NotifEvent.INFLATED, entry);
|
||||
mLogger.logNotifInflated(entry.getKey());
|
||||
mPendingNotifications.remove(entry);
|
||||
mNotifInflatingFilter.invalidateList();
|
||||
}
|
||||
@@ -123,7 +123,7 @@ public class PreparationCoordinator implements Coordinator {
|
||||
}
|
||||
|
||||
private void abortInflation(NotificationEntry entry, String reason) {
|
||||
mNotifLog.log(NotifEvent.INFLATION_ABORTED, reason);
|
||||
mLogger.logInflationAborted(entry.getKey(), reason);
|
||||
entry.abortTask();
|
||||
mPendingNotifications.remove(entry);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* 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.systemui.statusbar.notification.collection.coordinator
|
||||
|
||||
import com.android.systemui.log.LogBuffer
|
||||
import com.android.systemui.log.LogLevel
|
||||
import com.android.systemui.log.dagger.NotificationLog
|
||||
import javax.inject.Inject
|
||||
|
||||
class PreparationCoordinatorLogger @Inject constructor(
|
||||
@NotificationLog private val buffer: LogBuffer
|
||||
) {
|
||||
fun logNotifInflated(key: String) {
|
||||
buffer.log(TAG, LogLevel.DEBUG, {
|
||||
str1 = key
|
||||
}, {
|
||||
"NOTIF INFLATED $str1"
|
||||
})
|
||||
}
|
||||
|
||||
fun logInflationAborted(key: String, reason: String) {
|
||||
buffer.log(TAG, LogLevel.DEBUG, {
|
||||
str1 = key
|
||||
str2 = reason
|
||||
}, {
|
||||
"NOTIF INFLATION ABORTED $str1 reason=$str2"
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
private const val TAG = "PreparationCoordinator"
|
||||
@@ -1,212 +0,0 @@
|
||||
/*
|
||||
* 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;
|
||||
import android.service.notification.StatusBarNotification;
|
||||
|
||||
import com.android.systemui.log.RichEvent;
|
||||
import com.android.systemui.statusbar.notification.NotificationEntryManager;
|
||||
import com.android.systemui.statusbar.notification.collection.ShadeListBuilder;
|
||||
import com.android.systemui.statusbar.notification.collection.coalescer.GroupCoalescer;
|
||||
|
||||
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. We do not store a copy of the status bar notification nor ranking
|
||||
* here to mitigate memory usage.
|
||||
*/
|
||||
public class NotifEvent extends RichEvent {
|
||||
/**
|
||||
* Initializes a rich event that includes an event type that matches with an index in the array
|
||||
* getEventLabels().
|
||||
*/
|
||||
public NotifEvent init(@EventType int type, StatusBarNotification sbn,
|
||||
NotificationListenerService.Ranking ranking, String reason) {
|
||||
StringBuilder extraInfo = new StringBuilder(reason);
|
||||
if (sbn != null) {
|
||||
extraInfo.append(" " + sbn.getKey());
|
||||
}
|
||||
|
||||
if (ranking != null) {
|
||||
extraInfo.append(" Ranking=");
|
||||
extraInfo.append(ranking.getRank());
|
||||
}
|
||||
super.init(INFO, type, extraInfo.toString());
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Event labels for ListBuilderEvents
|
||||
* Index corresponds to an # in {@link EventType}
|
||||
*/
|
||||
@Override
|
||||
public String[] getEventLabels() {
|
||||
assert (TOTAL_EVENT_LABELS
|
||||
== (TOTAL_NEM_EVENT_TYPES
|
||||
+ TOTAL_LIST_BUILDER_EVENT_TYPES
|
||||
+ TOTAL_COALESCER_EVENT_TYPES));
|
||||
return EVENT_LABELS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return if this event occurred in {@link ShadeListBuilder}
|
||||
*/
|
||||
static boolean isListBuilderEvent(@EventType int type) {
|
||||
return isBetweenInclusive(type, 0, TOTAL_LIST_BUILDER_EVENT_TYPES);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return if this event occurred in {@link NotificationEntryManager}
|
||||
*/
|
||||
static boolean isNemEvent(@EventType int type) {
|
||||
return isBetweenInclusive(type, TOTAL_LIST_BUILDER_EVENT_TYPES,
|
||||
TOTAL_LIST_BUILDER_EVENT_TYPES + TOTAL_NEM_EVENT_TYPES);
|
||||
}
|
||||
|
||||
private static boolean isBetweenInclusive(int x, int a, int b) {
|
||||
return x >= a && x <= b;
|
||||
}
|
||||
|
||||
@IntDef({
|
||||
// NotifListBuilder events:
|
||||
WARN,
|
||||
ON_BUILD_LIST,
|
||||
START_BUILD_LIST,
|
||||
DISPATCH_FINAL_LIST,
|
||||
LIST_BUILD_COMPLETE,
|
||||
PRE_GROUP_FILTER_INVALIDATED,
|
||||
PROMOTER_INVALIDATED,
|
||||
SECTION_INVALIDATED,
|
||||
COMPARATOR_INVALIDATED,
|
||||
PARENT_CHANGED,
|
||||
FILTER_CHANGED,
|
||||
PROMOTER_CHANGED,
|
||||
PRE_RENDER_FILTER_INVALIDATED,
|
||||
|
||||
// NotificationEntryManager events:
|
||||
NOTIF_ADDED,
|
||||
NOTIF_REMOVED,
|
||||
NOTIF_UPDATED,
|
||||
FILTER,
|
||||
SORT,
|
||||
FILTER_AND_SORT,
|
||||
NOTIF_VISIBILITY_CHANGED,
|
||||
LIFETIME_EXTENDED,
|
||||
REMOVE_INTERCEPTED,
|
||||
INFLATION_ABORTED,
|
||||
INFLATED,
|
||||
|
||||
// GroupCoalescer
|
||||
COALESCED_EVENT,
|
||||
EARLY_BATCH_EMIT,
|
||||
EMIT_EVENT_BATCH
|
||||
})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface EventType {}
|
||||
|
||||
private static final String[] EVENT_LABELS =
|
||||
new String[]{
|
||||
// NotifListBuilder labels:
|
||||
"Warning",
|
||||
"OnBuildList",
|
||||
"StartBuildList",
|
||||
"DispatchFinalList",
|
||||
"ListBuildComplete",
|
||||
"FilterInvalidated",
|
||||
"PromoterInvalidated",
|
||||
"SectionInvalidated",
|
||||
"ComparatorInvalidated",
|
||||
"ParentChanged",
|
||||
"FilterChanged",
|
||||
"PromoterChanged",
|
||||
"FinalFilterInvalidated",
|
||||
"SectionerChanged",
|
||||
|
||||
// NEM event labels:
|
||||
"NotifAdded",
|
||||
"NotifRemoved",
|
||||
"NotifUpdated",
|
||||
"Filter",
|
||||
"Sort",
|
||||
"FilterAndSort",
|
||||
"NotifVisibilityChanged",
|
||||
"LifetimeExtended",
|
||||
"RemoveIntercepted",
|
||||
"InflationAborted",
|
||||
"Inflated",
|
||||
|
||||
// GroupCoalescer labels:
|
||||
"CoalescedEvent",
|
||||
"EarlyBatchEmit",
|
||||
"EmitEventBatch",
|
||||
"BatchMaxTimeout"
|
||||
};
|
||||
|
||||
private static final int TOTAL_EVENT_LABELS = EVENT_LABELS.length;
|
||||
|
||||
/**
|
||||
* Events related to {@link ShadeListBuilder}
|
||||
*/
|
||||
public static final int WARN = 0;
|
||||
public static final int ON_BUILD_LIST = 1;
|
||||
public static final int START_BUILD_LIST = 2;
|
||||
public static final int DISPATCH_FINAL_LIST = 3;
|
||||
public static final int LIST_BUILD_COMPLETE = 4;
|
||||
public static final int PRE_GROUP_FILTER_INVALIDATED = 5;
|
||||
public static final int PROMOTER_INVALIDATED = 6;
|
||||
public static final int SECTION_INVALIDATED = 7;
|
||||
public static final int COMPARATOR_INVALIDATED = 8;
|
||||
public static final int PARENT_CHANGED = 9;
|
||||
public static final int FILTER_CHANGED = 10;
|
||||
public static final int PROMOTER_CHANGED = 11;
|
||||
public static final int PRE_RENDER_FILTER_INVALIDATED = 12;
|
||||
public static final int SECTION_CHANGED = 13;
|
||||
private static final int TOTAL_LIST_BUILDER_EVENT_TYPES = 14;
|
||||
|
||||
/**
|
||||
* Events related to {@link NotificationEntryManager}
|
||||
*/
|
||||
private static final int NEM_EVENT_START_INDEX = TOTAL_LIST_BUILDER_EVENT_TYPES;
|
||||
public static final int NOTIF_ADDED = NEM_EVENT_START_INDEX;
|
||||
public static final int NOTIF_REMOVED = NEM_EVENT_START_INDEX + 1;
|
||||
public static final int NOTIF_UPDATED = NEM_EVENT_START_INDEX + 2;
|
||||
public static final int FILTER = NEM_EVENT_START_INDEX + 3;
|
||||
public static final int SORT = NEM_EVENT_START_INDEX + 4;
|
||||
public static final int FILTER_AND_SORT = NEM_EVENT_START_INDEX + 5;
|
||||
public static final int NOTIF_VISIBILITY_CHANGED = NEM_EVENT_START_INDEX + 6;
|
||||
public static final int LIFETIME_EXTENDED = NEM_EVENT_START_INDEX + 7;
|
||||
// unable to remove notif - removal intercepted by {@link NotificationRemoveInterceptor}
|
||||
public static final int REMOVE_INTERCEPTED = NEM_EVENT_START_INDEX + 8;
|
||||
public static final int INFLATION_ABORTED = NEM_EVENT_START_INDEX + 9;
|
||||
public static final int INFLATED = NEM_EVENT_START_INDEX + 10;
|
||||
private static final int TOTAL_NEM_EVENT_TYPES = 11;
|
||||
|
||||
/**
|
||||
* Events related to {@link GroupCoalescer}
|
||||
*/
|
||||
private static final int COALESCER_EVENT_START_INDEX = NEM_EVENT_START_INDEX
|
||||
+ TOTAL_NEM_EVENT_TYPES;
|
||||
public static final int COALESCED_EVENT = COALESCER_EVENT_START_INDEX;
|
||||
public static final int EARLY_BATCH_EMIT = COALESCER_EVENT_START_INDEX + 1;
|
||||
public static final int EMIT_EVENT_BATCH = COALESCER_EVENT_START_INDEX + 2;
|
||||
public static final int BATCH_MAX_TIMEOUT = COALESCER_EVENT_START_INDEX + 3;
|
||||
private static final int TOTAL_COALESCER_EVENT_TYPES = 3;
|
||||
}
|
||||
@@ -1,115 +0,0 @@
|
||||
/*
|
||||
* 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.os.SystemProperties;
|
||||
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<NotifEvent> {
|
||||
private static final String TAG = "NotifLog";
|
||||
private static final boolean SHOW_NEM_LOGS =
|
||||
SystemProperties.getBoolean("persist.sysui.log.notif.nem", true);
|
||||
private static final boolean SHOW_LIST_BUILDER_LOGS =
|
||||
SystemProperties.getBoolean("persist.sysui.log.notif.listbuilder", true);
|
||||
|
||||
private static final int MAX_DOZE_DEBUG_LOGS = 400;
|
||||
private static final int MAX_DOZE_LOGS = 50;
|
||||
|
||||
private NotifEvent mRecycledEvent;
|
||||
|
||||
@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.
|
||||
* Uses the last recycled event if available.
|
||||
* @return true if successfully logged, else false
|
||||
*/
|
||||
public void log(@NotifEvent.EventType int eventType,
|
||||
StatusBarNotification sbn, Ranking ranking, String msg) {
|
||||
if (!mEnabled
|
||||
|| (NotifEvent.isListBuilderEvent(eventType) && !SHOW_LIST_BUILDER_LOGS)
|
||||
|| (NotifEvent.isNemEvent(eventType) && !SHOW_NEM_LOGS)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mRecycledEvent != null) {
|
||||
mRecycledEvent = log(mRecycledEvent.init(eventType, sbn, ranking, msg));
|
||||
} else {
|
||||
mRecycledEvent = log(new NotifEvent().init(eventType, sbn, ranking, msg));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs a {@link NotifEvent} with no extra information aside from the event type
|
||||
*/
|
||||
public void log(@NotifEvent.EventType int eventType) {
|
||||
log(eventType, null, null, "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs a {@link NotifEvent} with a message
|
||||
*/
|
||||
public void log(@NotifEvent.EventType int eventType, String msg) {
|
||||
log(eventType, null, null, msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs a {@link NotifEvent} with a entry
|
||||
*/
|
||||
public void log(@NotifEvent.EventType int eventType, NotificationEntry entry) {
|
||||
log(eventType, entry.getSbn(), entry.getRanking(), "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs a {@link NotifEvent} with a NotificationEntry and message
|
||||
*/
|
||||
public void log(@NotifEvent.EventType int eventType, NotificationEntry entry, String msg) {
|
||||
log(eventType, entry.getSbn(), entry.getRanking(), msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs a {@link NotifEvent} with a notification and message
|
||||
*/
|
||||
public void log(@NotifEvent.EventType int eventType, StatusBarNotification sbn, String msg) {
|
||||
log(eventType, sbn, null, msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs a {@link NotifEvent} with a ranking and message
|
||||
*/
|
||||
public void log(@NotifEvent.EventType int eventType, Ranking ranking, String msg) {
|
||||
log(eventType, null, ranking, msg);
|
||||
}
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
/*
|
||||
* 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.log;
|
||||
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
|
||||
import android.testing.AndroidTestingRunner;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.systemui.SysuiTestCase;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
@SmallTest
|
||||
@RunWith(AndroidTestingRunner.class)
|
||||
public class RichEventTest extends SysuiTestCase {
|
||||
|
||||
private static final int TOTAL_EVENT_TYPES = 1;
|
||||
|
||||
@Test
|
||||
public void testCreateRichEvent_invalidType() {
|
||||
try {
|
||||
// indexing for events starts at 0, so TOTAL_EVENT_TYPES is an invalid type
|
||||
new TestableRichEvent(Event.DEBUG, TOTAL_EVENT_TYPES, "msg");
|
||||
} catch (IllegalArgumentException e) {
|
||||
// expected
|
||||
return;
|
||||
}
|
||||
|
||||
Assert.fail("Expected an invalidArgumentException since the event type was invalid.");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateRichEvent() {
|
||||
final int eventType = 0;
|
||||
RichEvent e = new TestableRichEvent(Event.DEBUG, eventType, "msg");
|
||||
assertEquals(e.getType(), eventType);
|
||||
}
|
||||
|
||||
class TestableRichEvent extends RichEvent {
|
||||
TestableRichEvent(int logLevel, int type, String reason) {
|
||||
init(logLevel, type, reason);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getEventLabels() {
|
||||
return new String[]{"ACTION_NAME"};
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,111 +0,0 @@
|
||||
/*
|
||||
* 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.log;
|
||||
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
|
||||
import android.testing.AndroidTestingRunner;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.systemui.DumpController;
|
||||
import com.android.systemui.SysuiTestCase;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
@SmallTest
|
||||
@RunWith(AndroidTestingRunner.class)
|
||||
public class SysuiLogTest extends SysuiTestCase {
|
||||
private static final String TEST_ID = "TestLogger";
|
||||
private static final String TEST_MSG = "msg";
|
||||
private static final int MAX_LOGS = 5;
|
||||
|
||||
@Mock
|
||||
private DumpController mDumpController;
|
||||
private SysuiLog<Event> mSysuiLog;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLogDisabled_noLogsWritten() {
|
||||
mSysuiLog = new TestSysuiLog(mDumpController, TEST_ID, MAX_LOGS, false);
|
||||
assertEquals(null, mSysuiLog.mTimeline);
|
||||
|
||||
mSysuiLog.log(createEvent(TEST_MSG));
|
||||
assertEquals(null, mSysuiLog.mTimeline);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLogEnabled_logWritten() {
|
||||
mSysuiLog = new TestSysuiLog(mDumpController, TEST_ID, MAX_LOGS, true);
|
||||
assertEquals(0, mSysuiLog.mTimeline.size());
|
||||
|
||||
mSysuiLog.log(createEvent(TEST_MSG));
|
||||
assertEquals(1, mSysuiLog.mTimeline.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMaxLogs() {
|
||||
mSysuiLog = new TestSysuiLog(mDumpController, TEST_ID, MAX_LOGS, true);
|
||||
assertEquals(mSysuiLog.mTimeline.size(), 0);
|
||||
|
||||
for (int i = 0; i < MAX_LOGS + 1; i++) {
|
||||
mSysuiLog.log(createEvent(TEST_MSG + i));
|
||||
}
|
||||
|
||||
assertEquals(MAX_LOGS, mSysuiLog.mTimeline.size());
|
||||
|
||||
// check the first message (msg0) was replaced with msg1:
|
||||
assertEquals(TEST_MSG + "1", mSysuiLog.mTimeline.getFirst().getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRecycleLogs() {
|
||||
// GIVEN a SysuiLog with one log
|
||||
mSysuiLog = new TestSysuiLog(mDumpController, TEST_ID, MAX_LOGS, true);
|
||||
Event e = createEvent(TEST_MSG); // msg
|
||||
mSysuiLog.log(e); // Logs: [msg]
|
||||
|
||||
Event recycledEvent = null;
|
||||
// WHEN we add MAX_LOGS after the first log
|
||||
for (int i = 0; i < MAX_LOGS; i++) {
|
||||
recycledEvent = mSysuiLog.log(createEvent(TEST_MSG + i));
|
||||
}
|
||||
// Logs: [msg1, msg2, msg3, msg4]
|
||||
|
||||
// THEN we see the recycledEvent is e
|
||||
assertEquals(e, recycledEvent);
|
||||
}
|
||||
|
||||
private Event createEvent(String msg) {
|
||||
return new Event().init(msg);
|
||||
}
|
||||
|
||||
public class TestSysuiLog extends SysuiLog<Event> {
|
||||
protected TestSysuiLog(DumpController dumpController, String id, int maxLogs,
|
||||
boolean enabled) {
|
||||
super(dumpController, id, maxLogs, enabled, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -79,7 +79,6 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntryB
|
||||
import com.android.systemui.statusbar.notification.collection.NotificationRankingManager;
|
||||
import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl;
|
||||
import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider;
|
||||
import com.android.systemui.statusbar.notification.logging.NotifLog;
|
||||
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
|
||||
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
|
||||
import com.android.systemui.statusbar.notification.row.ActivatableNotificationViewController;
|
||||
@@ -139,7 +138,7 @@ public class NotificationEntryManagerTest extends SysuiTestCase {
|
||||
@Mock private NotificationRemoteInputManager mRemoteInputManager;
|
||||
@Mock private DeviceProvisionedController mDeviceProvisionedController;
|
||||
@Mock private RowInflaterTask mAsyncInflationTask;
|
||||
@Mock private NotifLog mNotifLog;
|
||||
@Mock private NotificationEntryManagerLogger mLogger;
|
||||
@Mock private FeatureFlags mFeatureFlags;
|
||||
@Mock private LeakDetector mLeakDetector;
|
||||
@Mock private ActivatableNotificationViewController mActivatableNotificationViewController;
|
||||
@@ -234,14 +233,14 @@ public class NotificationEntryManagerTest extends SysuiTestCase {
|
||||
when(mFeatureFlags.isNewNotifPipelineEnabled()).thenReturn(false);
|
||||
when(mFeatureFlags.isNewNotifPipelineRenderingEnabled()).thenReturn(false);
|
||||
mEntryManager = new TestableNotificationEntryManager(
|
||||
mNotifLog,
|
||||
mLogger,
|
||||
mGroupManager,
|
||||
new NotificationRankingManager(
|
||||
() -> mock(NotificationMediaManager.class),
|
||||
mGroupManager,
|
||||
mHeadsUpManager,
|
||||
mock(NotificationFilter.class),
|
||||
mNotifLog,
|
||||
mLogger,
|
||||
mock(NotificationSectionsFeatureManager.class),
|
||||
mock(PeopleNotificationIdentifier.class),
|
||||
mock(HighPriorityProvider.class)),
|
||||
|
||||
@@ -22,7 +22,6 @@ import com.android.systemui.statusbar.NotificationRemoteInputManager
|
||||
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.logging.NotifLog
|
||||
import com.android.systemui.statusbar.notification.stack.NotificationListContainer
|
||||
import com.android.systemui.statusbar.phone.HeadsUpManagerPhone
|
||||
import com.android.systemui.statusbar.phone.NotificationGroupManager
|
||||
@@ -34,7 +33,7 @@ import java.util.concurrent.CountDownLatch
|
||||
* Enable some test capabilities for NEM without making everything public on the base class
|
||||
*/
|
||||
class TestableNotificationEntryManager(
|
||||
log: NotifLog,
|
||||
logger: NotificationEntryManagerLogger,
|
||||
gm: NotificationGroupManager,
|
||||
rm: NotificationRankingManager,
|
||||
ke: KeyguardEnvironment,
|
||||
@@ -43,7 +42,7 @@ class TestableNotificationEntryManager(
|
||||
notificationRemoteInputManagerLazy: dagger.Lazy<NotificationRemoteInputManager>,
|
||||
leakDetector: LeakDetector,
|
||||
fgsFeatureController: ForegroundServiceDismissalFeatureController
|
||||
) : NotificationEntryManager(log, gm, rm, ke, ff, rb,
|
||||
) : NotificationEntryManager(logger, gm, rm, ke, ff, rb,
|
||||
notificationRemoteInputManagerLazy, leakDetector, fgsFeatureController) {
|
||||
|
||||
public var countDownLatch: CountDownLatch = CountDownLatch(1)
|
||||
|
||||
@@ -27,10 +27,10 @@ import androidx.test.filters.SmallTest
|
||||
import com.android.systemui.SysuiTestCase
|
||||
import com.android.systemui.statusbar.NotificationEntryHelper.modifyRanking
|
||||
import com.android.systemui.statusbar.NotificationMediaManager
|
||||
import com.android.systemui.statusbar.notification.NotificationEntryManagerLogger
|
||||
import com.android.systemui.statusbar.notification.NotificationFilter
|
||||
import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager
|
||||
import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider
|
||||
import com.android.systemui.statusbar.notification.logging.NotifLog
|
||||
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier
|
||||
import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_ALERTING
|
||||
import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_SILENT
|
||||
@@ -62,7 +62,7 @@ class NotificationRankingManagerTest : SysuiTestCase() {
|
||||
mock(NotificationGroupManager::class.java),
|
||||
mock(HeadsUpManager::class.java),
|
||||
mock(NotificationFilter::class.java),
|
||||
mock(NotifLog::class.java),
|
||||
mock(NotificationEntryManagerLogger::class.java),
|
||||
mock(NotificationSectionsFeatureManager::class.java),
|
||||
personNotificationIdentifier,
|
||||
HighPriorityProvider(personNotificationIdentifier)
|
||||
@@ -189,7 +189,7 @@ class NotificationRankingManagerTest : SysuiTestCase() {
|
||||
groupManager: NotificationGroupManager,
|
||||
headsUpManager: HeadsUpManager,
|
||||
filter: NotificationFilter,
|
||||
notifLog: NotifLog,
|
||||
logger: NotificationEntryManagerLogger,
|
||||
sectionsFeatureManager: NotificationSectionsFeatureManager,
|
||||
peopleNotificationIdentifier: PeopleNotificationIdentifier,
|
||||
highPriorityProvider: HighPriorityProvider
|
||||
@@ -198,7 +198,7 @@ class NotificationRankingManagerTest : SysuiTestCase() {
|
||||
groupManager,
|
||||
headsUpManager,
|
||||
filter,
|
||||
notifLog,
|
||||
logger,
|
||||
sectionsFeatureManager,
|
||||
peopleNotificationIdentifier,
|
||||
highPriorityProvider
|
||||
|
||||
@@ -65,6 +65,7 @@ import com.android.systemui.statusbar.SysuiStatusBarStateController;
|
||||
import com.android.systemui.statusbar.notification.DynamicPrivacyController;
|
||||
import com.android.systemui.statusbar.notification.ForegroundServiceDismissalFeatureController;
|
||||
import com.android.systemui.statusbar.notification.NotificationEntryManager;
|
||||
import com.android.systemui.statusbar.notification.NotificationEntryManagerLogger;
|
||||
import com.android.systemui.statusbar.notification.NotificationFilter;
|
||||
import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager;
|
||||
import com.android.systemui.statusbar.notification.TestableNotificationEntryManager;
|
||||
@@ -74,7 +75,6 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntryB
|
||||
import com.android.systemui.statusbar.notification.collection.NotificationRankingManager;
|
||||
import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinder;
|
||||
import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider;
|
||||
import com.android.systemui.statusbar.notification.logging.NotifLog;
|
||||
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
|
||||
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
|
||||
import com.android.systemui.statusbar.notification.row.FooterView;
|
||||
@@ -163,14 +163,14 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase {
|
||||
ArgumentCaptor<UserChangedListener> userChangedCaptor = ArgumentCaptor
|
||||
.forClass(UserChangedListener.class);
|
||||
mEntryManager = new TestableNotificationEntryManager(
|
||||
mock(NotifLog.class),
|
||||
mock(NotificationEntryManagerLogger.class),
|
||||
mock(NotificationGroupManager.class),
|
||||
new NotificationRankingManager(
|
||||
() -> mock(NotificationMediaManager.class),
|
||||
mGroupManager,
|
||||
mHeadsUpManager,
|
||||
mock(NotificationFilter.class),
|
||||
mock(NotifLog.class),
|
||||
mock(NotificationEntryManagerLogger.class),
|
||||
mock(NotificationSectionsFeatureManager.class),
|
||||
mock(PeopleNotificationIdentifier.class),
|
||||
mock(HighPriorityProvider.class)
|
||||
|
||||
Reference in New Issue
Block a user