Revert "Revert "Recycle SysuiLogs + add NotifLogs""
- Add back NotifLogs without feature flag set to true.
- Update ForegroundCoordinator to end lifetime extenders on the
main thread instead of the bgthread.
This reverts commit 4f2a8bfe15.
Test: atest SystemUiTests
Fixes: 145689836
Fixes: 145709036
Bug: 145134683
Bug: 141470043
Change-Id: Iefc12b7da9c64c332bf43bb88533db87dc5525ec
This commit is contained in:
@@ -28,10 +28,12 @@ import java.lang.annotation.RetentionPolicy;
|
||||
* and triaging purposes.
|
||||
*/
|
||||
public class DozeEvent extends RichEvent {
|
||||
public static final int TOTAL_EVENT_TYPES = 19;
|
||||
|
||||
public DozeEvent(int logLevel, int type, String reason) {
|
||||
super(logLevel, type, reason);
|
||||
/**
|
||||
* Initializes a doze event
|
||||
*/
|
||||
public DozeEvent init(@EventType int type, String reason) {
|
||||
super.init(DEBUG, type, reason);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -89,21 +91,6 @@ public class DozeEvent extends RichEvent {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a DozeEvent.
|
||||
*/
|
||||
public static class DozeEventBuilder extends RichEvent.Builder<DozeEventBuilder> {
|
||||
@Override
|
||||
public DozeEventBuilder getBuilder() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RichEvent build() {
|
||||
return new DozeEvent(mLogLevel, mType, mReason);
|
||||
}
|
||||
}
|
||||
|
||||
@IntDef({PICKUP_WAKEUP, PULSE_START, PULSE_FINISH, NOTIFICATION_PULSE, DOZING, FLING,
|
||||
EMERGENCY_CALL, KEYGUARD_BOUNCER_CHANGED, SCREEN_ON, SCREEN_OFF, MISSED_TICK,
|
||||
TIME_TICK_SCHEDULED, KEYGUARD_VISIBILITY_CHANGE, DOZE_STATE_CHANGED, WAKE_DISPLAY,
|
||||
@@ -132,6 +119,7 @@ public class DozeEvent extends RichEvent {
|
||||
public static final int PULSE_DROPPED = 16;
|
||||
public static final int PULSE_DISABLED_BY_PROX = 17;
|
||||
public static final int SENSOR_TRIGGERED = 18;
|
||||
public static final int TOTAL_EVENT_TYPES = 19;
|
||||
|
||||
public static final int TOTAL_REASONS = 10;
|
||||
@IntDef({PULSE_REASON_NONE, PULSE_REASON_INTENT, PULSE_REASON_NOTIFICATION,
|
||||
|
||||
@@ -35,9 +35,11 @@ import javax.inject.Singleton;
|
||||
* dependency DumpController DozeLog
|
||||
*/
|
||||
@Singleton
|
||||
public class DozeLog extends SysuiLog {
|
||||
public class DozeLog extends SysuiLog<DozeEvent> {
|
||||
private static final String TAG = "DozeLog";
|
||||
|
||||
private DozeEvent mRecycledEvent;
|
||||
|
||||
private boolean mPulsing;
|
||||
private long mSince;
|
||||
private SummaryStats mPickupPulseNearVibrationStats;
|
||||
@@ -73,8 +75,8 @@ public class DozeLog extends SysuiLog {
|
||||
* Appends pickup wakeup event to the logs
|
||||
*/
|
||||
public void tracePickupWakeUp(boolean withinVibrationThreshold) {
|
||||
if (log(DozeEvent.PICKUP_WAKEUP,
|
||||
"withinVibrationThreshold=" + withinVibrationThreshold)) {
|
||||
log(DozeEvent.PICKUP_WAKEUP, "withinVibrationThreshold=" + withinVibrationThreshold);
|
||||
if (mEnabled) {
|
||||
(withinVibrationThreshold ? mPickupPulseNearVibrationStats
|
||||
: mPickupPulseNotNearVibrationStats).append();
|
||||
}
|
||||
@@ -85,27 +87,24 @@ public class DozeLog extends SysuiLog {
|
||||
* @param reason why the pulse started
|
||||
*/
|
||||
public void tracePulseStart(@DozeEvent.Reason int reason) {
|
||||
if (log(DozeEvent.PULSE_START, DozeEvent.reasonToString(reason))) {
|
||||
mPulsing = true;
|
||||
}
|
||||
log(DozeEvent.PULSE_START, DozeEvent.reasonToString(reason));
|
||||
if (mEnabled) mPulsing = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends pulse finished event to the logs
|
||||
*/
|
||||
public void tracePulseFinish() {
|
||||
if (log(DozeEvent.PULSE_FINISH)) {
|
||||
mPulsing = false;
|
||||
}
|
||||
log(DozeEvent.PULSE_FINISH);
|
||||
if (mEnabled) mPulsing = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends pulse event to the logs
|
||||
*/
|
||||
public void traceNotificationPulse() {
|
||||
if (log(DozeEvent.NOTIFICATION_PULSE)) {
|
||||
mNotificationPulseStats.append();
|
||||
}
|
||||
log(DozeEvent.NOTIFICATION_PULSE);
|
||||
if (mEnabled) mNotificationPulseStats.append();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -113,9 +112,8 @@ public class DozeLog extends SysuiLog {
|
||||
* @param dozing true if dozing, else false
|
||||
*/
|
||||
public void traceDozing(boolean dozing) {
|
||||
if (log(DozeEvent.DOZING, "dozing=" + dozing)) {
|
||||
mPulsing = false;
|
||||
}
|
||||
log(DozeEvent.DOZING, "dozing=" + dozing);
|
||||
if (mEnabled) mPulsing = false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -133,9 +131,8 @@ public class DozeLog extends SysuiLog {
|
||||
* Appends emergency call event to the logs
|
||||
*/
|
||||
public void traceEmergencyCall() {
|
||||
if (log(DozeEvent.EMERGENCY_CALL)) {
|
||||
mEmergencyCallStats.append();
|
||||
}
|
||||
log(DozeEvent.EMERGENCY_CALL);
|
||||
if (mEnabled) mEmergencyCallStats.append();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -150,7 +147,8 @@ public class DozeLog extends SysuiLog {
|
||||
* Appends screen-on event to the logs
|
||||
*/
|
||||
public void traceScreenOn() {
|
||||
if (log(DozeEvent.SCREEN_ON, "pulsing=" + mPulsing)) {
|
||||
log(DozeEvent.SCREEN_ON, "pulsing=" + mPulsing);
|
||||
if (mEnabled) {
|
||||
(mPulsing ? mScreenOnPulsingStats : mScreenOnNotPulsingStats).append();
|
||||
mPulsing = false;
|
||||
}
|
||||
@@ -188,10 +186,8 @@ public class DozeLog extends SysuiLog {
|
||||
* @param showing whether the keyguard is now showing
|
||||
*/
|
||||
public void traceKeyguard(boolean showing) {
|
||||
if (log(DozeEvent.KEYGUARD_VISIBILITY_CHANGE, "showing=" + showing)
|
||||
&& !showing) {
|
||||
mPulsing = false;
|
||||
}
|
||||
log(DozeEvent.KEYGUARD_VISIBILITY_CHANGE, "showing=" + showing);
|
||||
if (mEnabled && !showing) mPulsing = false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -217,12 +213,11 @@ public class DozeLog extends SysuiLog {
|
||||
* @param reason why proximity result was triggered
|
||||
*/
|
||||
public void traceProximityResult(boolean near, long millis, @DozeEvent.Reason int reason) {
|
||||
if (log(DozeEvent.PROXIMITY_RESULT,
|
||||
log(DozeEvent.PROXIMITY_RESULT,
|
||||
" reason=" + DozeEvent.reasonToString(reason)
|
||||
+ " near=" + near
|
||||
+ " millis=" + millis)) {
|
||||
mProxStats[reason][near ? 0 : 1].append();
|
||||
}
|
||||
+ " near=" + near
|
||||
+ " millis=" + millis);
|
||||
if (mEnabled) mProxStats[reason][near ? 0 : 1].append();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -250,15 +245,16 @@ public class DozeLog extends SysuiLog {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean log(@DozeEvent.EventType int eventType) {
|
||||
return log(eventType, "");
|
||||
private void log(@DozeEvent.EventType int eventType) {
|
||||
log(eventType, "");
|
||||
}
|
||||
|
||||
private boolean log(@DozeEvent.EventType int eventType, String msg) {
|
||||
return super.log(new DozeEvent.DozeEventBuilder()
|
||||
.setType(eventType)
|
||||
.setReason(msg)
|
||||
.build());
|
||||
private void log(@DozeEvent.EventType int eventType, String msg) {
|
||||
if (mRecycledEvent != null) {
|
||||
mRecycledEvent = log(mRecycledEvent.init(eventType, msg));
|
||||
} else {
|
||||
mRecycledEvent = log(new DozeEvent().init(eventType, msg));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -37,20 +37,28 @@ public class Event {
|
||||
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 = DEBUG;
|
||||
protected String mMessage;
|
||||
private @Level int mLogLevel = DEFAULT_LOG_LEVEL;
|
||||
private String mMessage = "";
|
||||
|
||||
public Event(String message) {
|
||||
mTimestamp = System.currentTimeMillis();
|
||||
mMessage = message;
|
||||
/**
|
||||
* initialize an event with a message
|
||||
*/
|
||||
public Event init(String message) {
|
||||
init(DEFAULT_LOG_LEVEL, message);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Event(@Level int logLevel, String message) {
|
||||
/**
|
||||
* 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() {
|
||||
@@ -64,4 +72,13 @@ public class Event {
|
||||
public @Level int getLogLevel() {
|
||||
return mLogLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recycle this event
|
||||
*/
|
||||
void recycle() {
|
||||
mTimestamp = -1;
|
||||
mLogLevel = DEFAULT_LOG_LEVEL;
|
||||
mMessage = "";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,23 +23,21 @@ package com.android.systemui.log;
|
||||
* Events are stored in {@link SysuiLog} and can be printed in a dumpsys.
|
||||
*/
|
||||
public abstract class RichEvent extends Event {
|
||||
private final int mType;
|
||||
private final String mReason;
|
||||
private int mType;
|
||||
|
||||
/**
|
||||
* Create a rich event that includes an event type that matches with an index in the array
|
||||
* Initializes a rich event that includes an event type that matches with an index in the array
|
||||
* getEventLabels().
|
||||
*/
|
||||
public RichEvent(@Event.Level int logLevel, int type, String reason) {
|
||||
super(logLevel, null);
|
||||
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;
|
||||
mReason = reason;
|
||||
mMessage = getEventLabels()[mType] + " " + mReason;
|
||||
super.init(logLevel, getEventLabels()[mType] + " " + reason);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -49,25 +47,43 @@ public abstract class RichEvent extends Event {
|
||||
*/
|
||||
public abstract String[] getEventLabels();
|
||||
|
||||
public int getType() {
|
||||
return mType;
|
||||
@Override
|
||||
public void recycle() {
|
||||
super.recycle();
|
||||
mType = -1;
|
||||
}
|
||||
|
||||
public String getReason() {
|
||||
return mReason;
|
||||
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>> {
|
||||
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 = UNINITIALIZED;
|
||||
protected int mType;
|
||||
protected String mReason;
|
||||
protected @Level int mLogLevel = VERBOSE;
|
||||
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.
|
||||
@@ -75,9 +91,9 @@ public abstract class RichEvent extends Event {
|
||||
public abstract B getBuilder();
|
||||
|
||||
/**
|
||||
* Build the log-specific event.
|
||||
* Build the log-specific event given an event to populate.
|
||||
*/
|
||||
public abstract RichEvent build();
|
||||
public abstract E build(E e);
|
||||
|
||||
/**
|
||||
* Optional - set the log level. Defaults to DEBUG.
|
||||
|
||||
@@ -20,6 +20,7 @@ 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;
|
||||
@@ -39,23 +40,26 @@ import java.util.Locale;
|
||||
* 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 implements Dumpable {
|
||||
public class SysuiLog<E extends Event> implements Dumpable {
|
||||
public static final SimpleDateFormat DATE_FORMAT =
|
||||
new SimpleDateFormat("MM-dd HH:mm:ss", Locale.US);
|
||||
|
||||
private final Object mDataLock = new Object();
|
||||
protected final Object mDataLock = new Object();
|
||||
private final String mId;
|
||||
private final int mMaxLogs;
|
||||
protected boolean mEnabled;
|
||||
protected boolean mLogToLogcatEnabled;
|
||||
|
||||
@VisibleForTesting protected ArrayDeque<Event> mTimeline;
|
||||
@VisibleForTesting protected ArrayDeque<E> mTimeline;
|
||||
|
||||
/**
|
||||
* Creates a SysuiLog
|
||||
* To enable or disable logs, set the system property and then restart the device:
|
||||
* adb shell setprop sysui.log.enabled.<id> true/false && adb reboot
|
||||
* @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
|
||||
@@ -79,23 +83,20 @@ public class SysuiLog implements Dumpable {
|
||||
dumpController.registerDumpable(mId, this);
|
||||
}
|
||||
|
||||
public SysuiLog(DumpController dumpController, String id) {
|
||||
this(dumpController, id, DEFAULT_MAX_DEBUG_LOGS, DEFAULT_MAX_LOGS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs an event to the timeline which can be printed by the dumpsys.
|
||||
* May also log to logcat if enabled.
|
||||
* @return true if event was logged, else false
|
||||
* @return the last event that was discarded from the Timeline (can be recycled)
|
||||
*/
|
||||
public boolean log(Event event) {
|
||||
public E log(E event) {
|
||||
if (!mEnabled) {
|
||||
return false;
|
||||
return null;
|
||||
}
|
||||
|
||||
E recycledEvent = null;
|
||||
synchronized (mDataLock) {
|
||||
if (mTimeline.size() >= mMaxLogs) {
|
||||
mTimeline.removeFirst();
|
||||
recycledEvent = mTimeline.removeFirst();
|
||||
}
|
||||
|
||||
mTimeline.add(event);
|
||||
@@ -121,13 +122,18 @@ public class SysuiLog implements Dumpable {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
if (recycledEvent != null) {
|
||||
recycledEvent.recycle();
|
||||
}
|
||||
|
||||
return recycledEvent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return user-readable string of the given event with timestamp
|
||||
*/
|
||||
public String eventToTimestampedString(Event event) {
|
||||
private String eventToTimestampedString(Event event) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(SysuiLog.DATE_FORMAT.format(event.getTimestamp()));
|
||||
sb.append(" ");
|
||||
@@ -142,9 +148,7 @@ public class SysuiLog implements Dumpable {
|
||||
return event.getMessage();
|
||||
}
|
||||
|
||||
/**
|
||||
* only call on this method if you have the mDataLock
|
||||
*/
|
||||
@GuardedBy("mDataLock")
|
||||
private void dumpTimelineLocked(PrintWriter pw) {
|
||||
pw.println("\tTimeline:");
|
||||
|
||||
|
||||
@@ -267,14 +267,13 @@ public class NotificationEntryManager implements
|
||||
NotificationEntry entry = mPendingNotifications.get(key);
|
||||
entry.abortTask();
|
||||
mPendingNotifications.remove(key);
|
||||
mNotifLog.log(NotifEvent.INFLATION_ABORTED, entry.getSbn(), null,
|
||||
"PendingNotification aborted. " + reason);
|
||||
mNotifLog.log(NotifEvent.INFLATION_ABORTED, entry, "PendingNotification aborted"
|
||||
+ " reason=" + reason);
|
||||
}
|
||||
NotificationEntry addedEntry = getActiveNotificationUnfiltered(key);
|
||||
if (addedEntry != null) {
|
||||
addedEntry.abortTask();
|
||||
mNotifLog.log(NotifEvent.INFLATION_ABORTED, addedEntry.getSbn(),
|
||||
null, reason);
|
||||
mNotifLog.log(NotifEvent.INFLATION_ABORTED, addedEntry.getKey() + " " + reason);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -501,7 +500,7 @@ public class NotificationEntryManager implements
|
||||
|
||||
abortExistingInflation(key, "addNotification");
|
||||
mPendingNotifications.put(key, entry);
|
||||
mNotifLog.log(NotifEvent.NOTIF_ADDED, entry.getSbn());
|
||||
mNotifLog.log(NotifEvent.NOTIF_ADDED, entry);
|
||||
for (NotificationEntryListener listener : mNotificationEntryListeners) {
|
||||
listener.onPendingEntryAdded(entry);
|
||||
}
|
||||
@@ -536,7 +535,7 @@ public class NotificationEntryManager implements
|
||||
entry.setSbn(notification);
|
||||
mGroupManager.onEntryUpdated(entry, oldSbn);
|
||||
|
||||
mNotifLog.log(NotifEvent.NOTIF_UPDATED, entry.getSbn(), entry.getRanking());
|
||||
mNotifLog.log(NotifEvent.NOTIF_UPDATED, entry);
|
||||
for (NotificationEntryListener listener : mNotificationEntryListeners) {
|
||||
listener.onPreEntryUpdated(entry);
|
||||
}
|
||||
|
||||
@@ -29,7 +29,6 @@ import static com.android.systemui.statusbar.notification.collection.listbuilder
|
||||
import android.annotation.MainThread;
|
||||
import android.annotation.Nullable;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.systemui.statusbar.notification.collection.listbuilder.NotifListBuilder;
|
||||
import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeRenderListListener;
|
||||
@@ -40,6 +39,8 @@ import com.android.systemui.statusbar.notification.collection.listbuilder.plugga
|
||||
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
|
||||
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifPromoter;
|
||||
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.SectionsProvider;
|
||||
import com.android.systemui.statusbar.notification.logging.NotifEvent;
|
||||
import com.android.systemui.statusbar.notification.logging.NotifLog;
|
||||
import com.android.systemui.util.Assert;
|
||||
import com.android.systemui.util.time.SystemClock;
|
||||
|
||||
@@ -59,8 +60,8 @@ import javax.inject.Singleton;
|
||||
@MainThread
|
||||
@Singleton
|
||||
public class NotifListBuilderImpl implements NotifListBuilder {
|
||||
|
||||
private final SystemClock mSystemClock;
|
||||
private final NotifLog mNotifLog;
|
||||
|
||||
private final List<ListEntry> mNotifList = new ArrayList<>();
|
||||
|
||||
@@ -86,9 +87,10 @@ public class NotifListBuilderImpl implements NotifListBuilder {
|
||||
private final List<ListEntry> mReadOnlyNotifList = Collections.unmodifiableList(mNotifList);
|
||||
|
||||
@Inject
|
||||
public NotifListBuilderImpl(SystemClock systemClock) {
|
||||
public NotifListBuilderImpl(SystemClock systemClock, NotifLog notifLog) {
|
||||
Assert.isMainThread();
|
||||
mSystemClock = systemClock;
|
||||
mNotifLog = notifLog;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -193,7 +195,8 @@ public class NotifListBuilderImpl implements NotifListBuilder {
|
||||
Assert.isMainThread();
|
||||
mPipelineState.requireIsBefore(STATE_BUILD_STARTED);
|
||||
|
||||
Log.i(TAG, "Build request received from NotifCollection");
|
||||
mNotifLog.log(NotifEvent.ON_BUILD_LIST, "Request received from "
|
||||
+ "NotifCollection");
|
||||
mAllEntries = entries;
|
||||
buildList();
|
||||
}
|
||||
@@ -202,8 +205,7 @@ public class NotifListBuilderImpl implements NotifListBuilder {
|
||||
private void onFilterInvalidated(NotifFilter filter) {
|
||||
Assert.isMainThread();
|
||||
|
||||
// TODO: Convert these log statements (here and elsewhere) into timeline logging
|
||||
Log.i(TAG, String.format(
|
||||
mNotifLog.log(NotifEvent.FILTER_INVALIDATED, String.format(
|
||||
"Filter \"%s\" invalidated; pipeline state is %d",
|
||||
filter.getName(),
|
||||
mPipelineState.getState()));
|
||||
@@ -214,7 +216,7 @@ public class NotifListBuilderImpl implements NotifListBuilder {
|
||||
private void onPromoterInvalidated(NotifPromoter filter) {
|
||||
Assert.isMainThread();
|
||||
|
||||
Log.i(TAG, String.format(
|
||||
mNotifLog.log(NotifEvent.PROMOTER_INVALIDATED, String.format(
|
||||
"NotifPromoter \"%s\" invalidated; pipeline state is %d",
|
||||
filter.getName(),
|
||||
mPipelineState.getState()));
|
||||
@@ -225,7 +227,7 @@ public class NotifListBuilderImpl implements NotifListBuilder {
|
||||
private void onSectionsProviderInvalidated(SectionsProvider provider) {
|
||||
Assert.isMainThread();
|
||||
|
||||
Log.i(TAG, String.format(
|
||||
mNotifLog.log(NotifEvent.SECTIONS_PROVIDER_INVALIDATED, String.format(
|
||||
"Sections provider \"%s\" invalidated; pipeline state is %d",
|
||||
provider.getName(),
|
||||
mPipelineState.getState()));
|
||||
@@ -236,7 +238,7 @@ public class NotifListBuilderImpl implements NotifListBuilder {
|
||||
private void onNotifComparatorInvalidated(NotifComparator comparator) {
|
||||
Assert.isMainThread();
|
||||
|
||||
Log.i(TAG, String.format(
|
||||
mNotifLog.log(NotifEvent.COMPARATOR_INVALIDATED, String.format(
|
||||
"Comparator \"%s\" invalidated; pipeline state is %d",
|
||||
comparator.getName(),
|
||||
mPipelineState.getState()));
|
||||
@@ -254,7 +256,7 @@ public class NotifListBuilderImpl implements NotifListBuilder {
|
||||
* if we detect that behavior, we should crash instantly.
|
||||
*/
|
||||
private void buildList() {
|
||||
Log.i(TAG, "Starting notif list build #" + mIterationCount + "...");
|
||||
mNotifLog.log(NotifEvent.START_BUILD_LIST, "Run #" + mIterationCount + "...");
|
||||
|
||||
mPipelineState.requireIsBefore(STATE_BUILD_STARTED);
|
||||
mPipelineState.setState(STATE_BUILD_STARTED);
|
||||
@@ -288,15 +290,16 @@ public class NotifListBuilderImpl implements NotifListBuilder {
|
||||
freeEmptyGroups();
|
||||
|
||||
// Step 5: Dispatch the new list, first to any listeners and then to the view layer
|
||||
Log.i(TAG, "List finalized, is:\n" + dumpList(mNotifList));
|
||||
Log.i(TAG, "Dispatching final list to listeners...");
|
||||
mNotifLog.log(NotifEvent.DISPATCH_FINAL_LIST, "List finalized, is:\n"
|
||||
+ dumpList(mNotifList));
|
||||
dispatchOnBeforeRenderList(mReadOnlyNotifList);
|
||||
if (mOnRenderListListener != null) {
|
||||
mOnRenderListListener.onRenderList(mReadOnlyNotifList);
|
||||
}
|
||||
|
||||
// Step 6: We're done!
|
||||
Log.i(TAG, "Notif list build #" + mIterationCount + " completed");
|
||||
mNotifLog.log(NotifEvent.LIST_BUILD_COMPLETE,
|
||||
"Notif list build #" + mIterationCount + " completed");
|
||||
mPipelineState.setState(STATE_IDLE);
|
||||
mIterationCount++;
|
||||
}
|
||||
@@ -354,7 +357,7 @@ public class NotifListBuilderImpl implements NotifListBuilder {
|
||||
if (existingSummary == null) {
|
||||
group.setSummary(entry);
|
||||
} else {
|
||||
Log.w(TAG, String.format(
|
||||
mNotifLog.log(NotifEvent.WARN, String.format(
|
||||
"Duplicate summary for group '%s': '%s' vs. '%s'",
|
||||
group.getKey(),
|
||||
existingSummary.getKey(),
|
||||
@@ -377,7 +380,8 @@ public class NotifListBuilderImpl implements NotifListBuilder {
|
||||
|
||||
final String topLevelKey = entry.getKey();
|
||||
if (mGroups.containsKey(topLevelKey)) {
|
||||
Log.wtf(TAG, "Duplicate non-group top-level key: " + topLevelKey);
|
||||
mNotifLog.log(NotifEvent.WARN,
|
||||
"Duplicate non-group top-level key: " + topLevelKey);
|
||||
} else {
|
||||
entry.setParent(ROOT_ENTRY);
|
||||
out.add(entry);
|
||||
@@ -539,7 +543,7 @@ public class NotifListBuilderImpl implements NotifListBuilder {
|
||||
private void logParentingChanges() {
|
||||
for (NotificationEntry entry : mAllEntries) {
|
||||
if (entry.getParent() != entry.getPreviousParent()) {
|
||||
Log.i(TAG, String.format(
|
||||
mNotifLog.log(NotifEvent.PARENT_CHANGED, String.format(
|
||||
"%s: parent changed from %s to %s",
|
||||
entry.getKey(),
|
||||
entry.getPreviousParent() == null
|
||||
@@ -550,7 +554,7 @@ public class NotifListBuilderImpl implements NotifListBuilder {
|
||||
}
|
||||
for (GroupEntry group : mGroups.values()) {
|
||||
if (group.getParent() != group.getPreviousParent()) {
|
||||
Log.i(TAG, String.format(
|
||||
mNotifLog.log(NotifEvent.PARENT_CHANGED, String.format(
|
||||
"%s: parent changed from %s to %s",
|
||||
group.getKey(),
|
||||
group.getPreviousParent() == null
|
||||
@@ -607,17 +611,17 @@ public class NotifListBuilderImpl implements NotifListBuilder {
|
||||
|
||||
if (filter != entry.mExcludingFilter) {
|
||||
if (entry.mExcludingFilter == null) {
|
||||
Log.i(TAG, String.format(
|
||||
mNotifLog.log(NotifEvent.FILTER_CHANGED, String.format(
|
||||
"%s: filtered out by '%s'",
|
||||
entry.getKey(),
|
||||
filter.getName()));
|
||||
} else if (filter == null) {
|
||||
Log.i(TAG, String.format(
|
||||
mNotifLog.log(NotifEvent.FILTER_CHANGED, String.format(
|
||||
"%s: no longer filtered out (previous filter was '%s')",
|
||||
entry.getKey(),
|
||||
entry.mExcludingFilter.getName()));
|
||||
} else {
|
||||
Log.i(TAG, String.format(
|
||||
mNotifLog.log(NotifEvent.FILTER_CHANGED, String.format(
|
||||
"%s: filter changed: '%s' -> '%s'",
|
||||
entry.getKey(),
|
||||
entry.mExcludingFilter,
|
||||
@@ -648,23 +652,22 @@ public class NotifListBuilderImpl implements NotifListBuilder {
|
||||
|
||||
if (promoter != entry.mNotifPromoter) {
|
||||
if (entry.mNotifPromoter == null) {
|
||||
Log.i(TAG, String.format(
|
||||
mNotifLog.log(NotifEvent.PROMOTER_CHANGED, String.format(
|
||||
"%s: Entry promoted to top level by '%s'",
|
||||
entry.getKey(),
|
||||
promoter.getName()));
|
||||
} else if (promoter == null) {
|
||||
Log.i(TAG, String.format(
|
||||
mNotifLog.log(NotifEvent.PROMOTER_CHANGED, String.format(
|
||||
"%s: Entry is no longer promoted to top level (previous promoter was '%s')",
|
||||
entry.getKey(),
|
||||
entry.mNotifPromoter.getName()));
|
||||
} else {
|
||||
Log.i(TAG, String.format(
|
||||
mNotifLog.log(NotifEvent.PROMOTER_CHANGED, String.format(
|
||||
"%s: Top-level promoter changed: '%s' -> '%s'",
|
||||
entry.getKey(),
|
||||
entry.mNotifPromoter,
|
||||
promoter));
|
||||
}
|
||||
|
||||
entry.mNotifPromoter = promoter;
|
||||
}
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ public class DeviceProvisionedCoordinator implements Coordinator {
|
||||
notifListBuilder.addFilter(mNotifFilter);
|
||||
}
|
||||
|
||||
protected final NotifFilter mNotifFilter = new NotifFilter(TAG) {
|
||||
private final NotifFilter mNotifFilter = new NotifFilter(TAG) {
|
||||
@Override
|
||||
public boolean shouldFilterOut(NotificationEntry entry, long now) {
|
||||
return !mDeviceProvisionedController.isDeviceProvisioned()
|
||||
|
||||
@@ -24,7 +24,6 @@ import android.util.ArraySet;
|
||||
|
||||
import com.android.systemui.ForegroundServiceController;
|
||||
import com.android.systemui.appops.AppOpsController;
|
||||
import com.android.systemui.dagger.qualifiers.BgHandler;
|
||||
import com.android.systemui.dagger.qualifiers.MainHandler;
|
||||
import com.android.systemui.statusbar.notification.collection.NotifCollection;
|
||||
import com.android.systemui.statusbar.notification.collection.NotifCollectionListener;
|
||||
@@ -52,12 +51,11 @@ import javax.inject.Singleton;
|
||||
*/
|
||||
@Singleton
|
||||
public class ForegroundCoordinator implements Coordinator {
|
||||
private static final String TAG = "ForegroundNotificationCoordinator";
|
||||
private static final String TAG = "ForegroundCoordinator";
|
||||
|
||||
private final ForegroundServiceController mForegroundServiceController;
|
||||
private final AppOpsController mAppOpsController;
|
||||
private final Handler mMainHandler;
|
||||
private final Handler mBgHandler;
|
||||
|
||||
private NotifCollection mNotifCollection;
|
||||
|
||||
@@ -65,12 +63,10 @@ public class ForegroundCoordinator implements Coordinator {
|
||||
public ForegroundCoordinator(
|
||||
ForegroundServiceController foregroundServiceController,
|
||||
AppOpsController appOpsController,
|
||||
@MainHandler Handler mainHandler,
|
||||
@BgHandler Handler bgHandler) {
|
||||
@MainHandler Handler mainHandler) {
|
||||
mForegroundServiceController = foregroundServiceController;
|
||||
mAppOpsController = appOpsController;
|
||||
mMainHandler = mainHandler;
|
||||
mBgHandler = bgHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -93,7 +89,7 @@ public class ForegroundCoordinator implements Coordinator {
|
||||
/**
|
||||
* Filters out notifications that represent foreground services that are no longer running.
|
||||
*/
|
||||
protected final NotifFilter mNotifFilter = new NotifFilter(TAG) {
|
||||
private final NotifFilter mNotifFilter = new NotifFilter(TAG) {
|
||||
@Override
|
||||
public boolean shouldFilterOut(NotificationEntry entry, long now) {
|
||||
StatusBarNotification sbn = entry.getSbn();
|
||||
@@ -120,7 +116,8 @@ public class ForegroundCoordinator implements Coordinator {
|
||||
* Extends the lifetime of foreground notification services such that they show for at least
|
||||
* five seconds
|
||||
*/
|
||||
private final NotifLifetimeExtender mForegroundLifetimeExtender = new NotifLifetimeExtender() {
|
||||
private final NotifLifetimeExtender mForegroundLifetimeExtender =
|
||||
new NotifLifetimeExtender() {
|
||||
private static final int MIN_FGS_TIME_MS = 5000;
|
||||
private OnEndLifetimeExtensionCallback mEndCallback;
|
||||
private Map<String, Runnable> mEndRunnables = new HashMap<>();
|
||||
@@ -154,8 +151,8 @@ public class ForegroundCoordinator implements Coordinator {
|
||||
}
|
||||
};
|
||||
mEndRunnables.put(entry.getKey(), runnable);
|
||||
mBgHandler.postDelayed(runnable, MIN_FGS_TIME_MS
|
||||
- (currTime - entry.getSbn().getPostTime()));
|
||||
mMainHandler.postDelayed(runnable,
|
||||
MIN_FGS_TIME_MS - (currTime - entry.getSbn().getPostTime()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -166,7 +163,7 @@ public class ForegroundCoordinator implements Coordinator {
|
||||
public void cancelLifetimeExtension(NotificationEntry entry) {
|
||||
if (mEndRunnables.containsKey(entry.getKey())) {
|
||||
Runnable endRunnable = mEndRunnables.remove(entry.getKey());
|
||||
mBgHandler.removeCallbacks(endRunnable);
|
||||
mMainHandler.removeCallbacks(endRunnable);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -51,7 +51,7 @@ import javax.inject.Singleton;
|
||||
*/
|
||||
@Singleton
|
||||
public class KeyguardCoordinator implements Coordinator {
|
||||
private static final String TAG = "KeyguardNotificationCoordinator";
|
||||
private static final String TAG = "KeyguardCoordinator";
|
||||
|
||||
private final Context mContext;
|
||||
private final Handler mMainHandler;
|
||||
@@ -86,7 +86,7 @@ public class KeyguardCoordinator implements Coordinator {
|
||||
notifListBuilder.addFilter(mNotifFilter);
|
||||
}
|
||||
|
||||
protected final NotifFilter mNotifFilter = new NotifFilter(TAG) {
|
||||
private final NotifFilter mNotifFilter = new NotifFilter(TAG) {
|
||||
@Override
|
||||
public boolean shouldFilterOut(NotificationEntry entry, long now) {
|
||||
final StatusBarNotification sbn = entry.getSbn();
|
||||
|
||||
@@ -26,7 +26,10 @@ import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
/**
|
||||
* Filters out NotificationEntries based on its Ranking.
|
||||
* Filters out NotificationEntries based on its Ranking and dozing state.
|
||||
* We check the NotificationEntry's Ranking for:
|
||||
* - whether the notification's app is suspended or hiding its notifications
|
||||
* - whether DND settings are hiding notifications from ambient display or the notification list
|
||||
*/
|
||||
@Singleton
|
||||
public class RankingCoordinator implements Coordinator {
|
||||
@@ -51,7 +54,7 @@ public class RankingCoordinator implements Coordinator {
|
||||
* NotifListBuilder invalidates the notification list each time the ranking is updated,
|
||||
* so we don't need to explicitly invalidate this filter on ranking update.
|
||||
*/
|
||||
protected final NotifFilter mNotifFilter = new NotifFilter(TAG) {
|
||||
private final NotifFilter mNotifFilter = new NotifFilter(TAG) {
|
||||
@Override
|
||||
public boolean shouldFilterOut(NotificationEntry entry, long now) {
|
||||
// App suspended from Ranking
|
||||
|
||||
@@ -17,10 +17,12 @@
|
||||
package com.android.systemui.statusbar.notification.logging;
|
||||
|
||||
import android.annotation.IntDef;
|
||||
import android.service.notification.NotificationListenerService.Ranking;
|
||||
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.listbuilder.NotifListBuilder;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
@@ -31,103 +33,71 @@ import java.lang.annotation.RetentionPolicy;
|
||||
* here to mitigate memory usage.
|
||||
*/
|
||||
public class NotifEvent extends RichEvent {
|
||||
public static final int TOTAL_EVENT_TYPES = 11;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* Initializes a rich event that includes an event type that matches with an index in the array
|
||||
* getEventLabels().
|
||||
*/
|
||||
public NotifEvent(int logLevel, int type, String reason, StatusBarNotification sbn,
|
||||
Ranking ranking) {
|
||||
super(logLevel, type, reason);
|
||||
mMessage += getExtraInfo(sbn, ranking);
|
||||
}
|
||||
|
||||
private String getExtraInfo(StatusBarNotification sbn, Ranking ranking) {
|
||||
StringBuilder extraInfo = new StringBuilder();
|
||||
|
||||
public NotifEvent init(@EventType int type, StatusBarNotification sbn,
|
||||
NotificationListenerService.Ranking ranking, String reason) {
|
||||
StringBuilder extraInfo = new StringBuilder(reason);
|
||||
if (sbn != null) {
|
||||
extraInfo.append(" Sbn=");
|
||||
extraInfo.append(sbn);
|
||||
extraInfo.append(" " + sbn.getKey());
|
||||
}
|
||||
|
||||
if (ranking != null) {
|
||||
extraInfo.append(" Ranking=");
|
||||
extraInfo.append(ranking);
|
||||
extraInfo.append(ranking.getRank());
|
||||
}
|
||||
|
||||
return extraInfo.toString();
|
||||
super.init(INFO, type, extraInfo.toString());
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Event labels for NotifEvents
|
||||
* Index corresponds to the {@link EventType}
|
||||
* Event labels for ListBuilderEvents
|
||||
* Index corresponds to an # in {@link EventType}
|
||||
*/
|
||||
@Override
|
||||
public String[] getEventLabels() {
|
||||
final String[] events = new String[]{
|
||||
"NotifAdded",
|
||||
"NotifRemoved",
|
||||
"NotifUpdated",
|
||||
"Filter",
|
||||
"Sort",
|
||||
"FilterAndSort",
|
||||
"NotifVisibilityChanged",
|
||||
"LifetimeExtended",
|
||||
"RemoveIntercepted",
|
||||
"InflationAborted",
|
||||
"Inflated"
|
||||
};
|
||||
|
||||
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;
|
||||
assert (TOTAL_EVENT_LABELS == (TOTAL_NEM_EVENT_TYPES + TOTAL_LIST_BUILDER_EVENT_TYPES));
|
||||
return EVENT_LABELS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a NotifEvent.
|
||||
* @return if this event occurred in {@link NotifListBuilder}
|
||||
*/
|
||||
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);
|
||||
}
|
||||
static boolean isListBuilderEvent(@EventType int type) {
|
||||
return isBetweenInclusive(type, 0, TOTAL_LIST_BUILDER_EVENT_TYPES);
|
||||
}
|
||||
|
||||
@IntDef({NOTIF_ADDED,
|
||||
/**
|
||||
* @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,
|
||||
FILTER_INVALIDATED,
|
||||
PROMOTER_INVALIDATED,
|
||||
SECTIONS_PROVIDER_INVALIDATED,
|
||||
COMPARATOR_INVALIDATED,
|
||||
PARENT_CHANGED,
|
||||
FILTER_CHANGED,
|
||||
PROMOTER_CHANGED,
|
||||
|
||||
// NotificationEntryManager events:
|
||||
NOTIF_ADDED,
|
||||
NOTIF_REMOVED,
|
||||
NOTIF_UPDATED,
|
||||
FILTER,
|
||||
@@ -139,22 +109,72 @@ public class NotifEvent extends RichEvent {
|
||||
INFLATION_ABORTED,
|
||||
INFLATED
|
||||
})
|
||||
|
||||
/**
|
||||
* 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 FILTER = 3;
|
||||
public static final int SORT = 4;
|
||||
public static final int FILTER_AND_SORT = 5;
|
||||
public static final int NOTIF_VISIBILITY_CHANGED = 6;
|
||||
public static final int LIFETIME_EXTENDED = 7;
|
||||
|
||||
private static final String[] EVENT_LABELS =
|
||||
new String[]{
|
||||
// NotifListBuilder labels:
|
||||
"Warning",
|
||||
"OnBuildList",
|
||||
"StartBuildList",
|
||||
"DispatchFinalList",
|
||||
"ListBuildComplete",
|
||||
"FilterInvalidated",
|
||||
"PromoterInvalidated",
|
||||
"SectionsProviderInvalidated",
|
||||
"ComparatorInvalidated",
|
||||
"ParentChanged",
|
||||
"FilterChanged",
|
||||
"PromoterChanged",
|
||||
|
||||
// NEM event labels:
|
||||
"NotifAdded",
|
||||
"NotifRemoved",
|
||||
"NotifUpdated",
|
||||
"Filter",
|
||||
"Sort",
|
||||
"FilterAndSort",
|
||||
"NotifVisibilityChanged",
|
||||
"LifetimeExtended",
|
||||
"RemoveIntercepted",
|
||||
"InflationAborted",
|
||||
"Inflated"
|
||||
};
|
||||
|
||||
private static final int TOTAL_EVENT_LABELS = EVENT_LABELS.length;
|
||||
|
||||
/**
|
||||
* Events related to {@link NotifListBuilder}
|
||||
*/
|
||||
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 FILTER_INVALIDATED = 5;
|
||||
public static final int PROMOTER_INVALIDATED = 6;
|
||||
public static final int SECTIONS_PROVIDER_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;
|
||||
private static final int TOTAL_LIST_BUILDER_EVENT_TYPES = 12;
|
||||
|
||||
/**
|
||||
* Events related to {@link NotificationEntryManager}
|
||||
*/
|
||||
public static final int NOTIF_ADDED = TOTAL_LIST_BUILDER_EVENT_TYPES + 0;
|
||||
public static final int NOTIF_REMOVED = TOTAL_LIST_BUILDER_EVENT_TYPES + 1;
|
||||
public static final int NOTIF_UPDATED = TOTAL_LIST_BUILDER_EVENT_TYPES + 2;
|
||||
public static final int FILTER = TOTAL_LIST_BUILDER_EVENT_TYPES + 3;
|
||||
public static final int SORT = TOTAL_LIST_BUILDER_EVENT_TYPES + 4;
|
||||
public static final int FILTER_AND_SORT = TOTAL_LIST_BUILDER_EVENT_TYPES + 5;
|
||||
public static final int NOTIF_VISIBILITY_CHANGED = TOTAL_LIST_BUILDER_EVENT_TYPES + 6;
|
||||
public static final int LIFETIME_EXTENDED = TOTAL_LIST_BUILDER_EVENT_TYPES + 7;
|
||||
// unable to remove notif - removal intercepted by {@link NotificationRemoveInterceptor}
|
||||
public static final int REMOVE_INTERCEPTED = 8;
|
||||
public static final int INFLATION_ABORTED = 9;
|
||||
public static final int INFLATED = 10;
|
||||
public static final int REMOVE_INTERCEPTED = TOTAL_LIST_BUILDER_EVENT_TYPES + 8;
|
||||
public static final int INFLATION_ABORTED = TOTAL_LIST_BUILDER_EVENT_TYPES + 9;
|
||||
public static final int INFLATED = TOTAL_LIST_BUILDER_EVENT_TYPES + 10;
|
||||
private static final int TOTAL_NEM_EVENT_TYPES = 11;
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.android.systemui.statusbar.notification.logging;
|
||||
|
||||
import android.os.SystemProperties;
|
||||
import android.service.notification.NotificationListenerService.Ranking;
|
||||
import android.service.notification.StatusBarNotification;
|
||||
|
||||
@@ -33,93 +34,82 @@ import javax.inject.Singleton;
|
||||
* dependency DumpController NotifLog
|
||||
*/
|
||||
@Singleton
|
||||
public class NotifLog extends SysuiLog {
|
||||
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
|
||||
* 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 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());
|
||||
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}
|
||||
* @return true if successfully logged, else false
|
||||
* Logs a {@link NotifEvent} with no extra information aside from the event type
|
||||
*/
|
||||
public boolean log(@NotifEvent.EventType int eventType) {
|
||||
return log(eventType, null, null, null);
|
||||
public void log(@NotifEvent.EventType int eventType) {
|
||||
log(eventType, 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);
|
||||
public void log(@NotifEvent.EventType int eventType, String msg) {
|
||||
log(eventType, null, null, msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs a {@link NotifEvent} with a notification
|
||||
* @return true if successfully logged, else false
|
||||
* Logs a {@link NotifEvent} with a entry
|
||||
*/
|
||||
public boolean log(@NotifEvent.EventType int eventType, StatusBarNotification sbn) {
|
||||
return log(eventType, sbn, null, "");
|
||||
public void log(@NotifEvent.EventType int eventType, NotificationEntry entry) {
|
||||
log(eventType, entry.getSbn(), entry.getRanking(), "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs a {@link NotifEvent} with a notification
|
||||
* @return true if successfully logged, else false
|
||||
* Logs a {@link NotifEvent} with a NotificationEntry and message
|
||||
*/
|
||||
public boolean log(@NotifEvent.EventType int eventType, StatusBarNotification sbn, String msg) {
|
||||
return log(eventType, sbn, null, msg);
|
||||
public void log(@NotifEvent.EventType int eventType, NotificationEntry entry, String msg) {
|
||||
log(eventType, entry.getSbn(), entry.getRanking(), msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs a {@link NotifEvent} with a ranking
|
||||
* @return true if successfully logged, else false
|
||||
* Logs a {@link NotifEvent} with a notification and message
|
||||
*/
|
||||
public boolean log(@NotifEvent.EventType int eventType, Ranking ranking) {
|
||||
return log(eventType, null, ranking, "");
|
||||
public void log(@NotifEvent.EventType int eventType, StatusBarNotification sbn, String msg) {
|
||||
log(eventType, sbn, null, msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs a {@link NotifEvent} with a notification and ranking
|
||||
* @return true if successfully logged, else false
|
||||
* Logs a {@link NotifEvent} with a ranking and message
|
||||
*/
|
||||
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.getSbn(), entry.getRanking(), "");
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.getSbn(), entry.getRanking(), msg);
|
||||
public void log(@NotifEvent.EventType int eventType, Ranking ranking, String msg) {
|
||||
log(eventType, null, ranking, msg);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ public class RichEventTest extends SysuiTestCase {
|
||||
|
||||
class TestableRichEvent extends RichEvent {
|
||||
TestableRichEvent(int logLevel, int type, String reason) {
|
||||
super(logLevel, type, reason);
|
||||
init(logLevel, type, reason);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -35,11 +35,12 @@ import org.mockito.MockitoAnnotations;
|
||||
@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 mSysuiLog;
|
||||
private SysuiLog<Event> mSysuiLog;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
@@ -48,35 +49,63 @@ public class SysuiLogTest extends SysuiTestCase {
|
||||
|
||||
@Test
|
||||
public void testLogDisabled_noLogsWritten() {
|
||||
mSysuiLog = new SysuiLog(mDumpController, TEST_ID, MAX_LOGS, false, false);
|
||||
assertEquals(mSysuiLog.mTimeline, null);
|
||||
mSysuiLog = new TestSysuiLog(mDumpController, TEST_ID, MAX_LOGS, false);
|
||||
assertEquals(null, mSysuiLog.mTimeline);
|
||||
|
||||
mSysuiLog.log(new Event("msg"));
|
||||
assertEquals(mSysuiLog.mTimeline, null);
|
||||
mSysuiLog.log(createEvent(TEST_MSG));
|
||||
assertEquals(null, mSysuiLog.mTimeline);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLogEnabled_logWritten() {
|
||||
mSysuiLog = new SysuiLog(mDumpController, TEST_ID, MAX_LOGS, true, false);
|
||||
assertEquals(mSysuiLog.mTimeline.size(), 0);
|
||||
mSysuiLog = new TestSysuiLog(mDumpController, TEST_ID, MAX_LOGS, true);
|
||||
assertEquals(0, mSysuiLog.mTimeline.size());
|
||||
|
||||
mSysuiLog.log(new Event("msg"));
|
||||
assertEquals(mSysuiLog.mTimeline.size(), 1);
|
||||
mSysuiLog.log(createEvent(TEST_MSG));
|
||||
assertEquals(1, mSysuiLog.mTimeline.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMaxLogs() {
|
||||
mSysuiLog = new SysuiLog(mDumpController, TEST_ID, MAX_LOGS, true, false);
|
||||
mSysuiLog = new TestSysuiLog(mDumpController, TEST_ID, MAX_LOGS, true);
|
||||
assertEquals(mSysuiLog.mTimeline.size(), 0);
|
||||
|
||||
final String msg = "msg";
|
||||
for (int i = 0; i < MAX_LOGS + 1; i++) {
|
||||
mSysuiLog.log(new Event(msg + i));
|
||||
mSysuiLog.log(createEvent(TEST_MSG + i));
|
||||
}
|
||||
|
||||
assertEquals(mSysuiLog.mTimeline.size(), MAX_LOGS);
|
||||
assertEquals(MAX_LOGS, mSysuiLog.mTimeline.size());
|
||||
|
||||
// check the first message (msg0) is deleted:
|
||||
assertEquals(mSysuiLog.mTimeline.getFirst().getMessage(), msg + "1");
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,6 +47,7 @@ import com.android.systemui.statusbar.notification.collection.listbuilder.plugga
|
||||
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
|
||||
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifPromoter;
|
||||
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.SectionsProvider;
|
||||
import com.android.systemui.statusbar.notification.logging.NotifLog;
|
||||
import com.android.systemui.util.Assert;
|
||||
import com.android.systemui.util.time.FakeSystemClock;
|
||||
|
||||
@@ -76,6 +77,7 @@ public class NotifListBuilderImplTest extends SysuiTestCase {
|
||||
private NotifListBuilderImpl mListBuilder;
|
||||
private FakeSystemClock mSystemClock = new FakeSystemClock();
|
||||
|
||||
@Mock private NotifLog mNotifLog;
|
||||
@Mock private NotifCollection mNotifCollection;
|
||||
@Spy private OnBeforeTransformGroupsListener mOnBeforeTransformGroupsListener;
|
||||
@Spy private OnBeforeSortListener mOnBeforeSortListener;
|
||||
@@ -97,7 +99,7 @@ public class NotifListBuilderImplTest extends SysuiTestCase {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
Assert.sMainLooper = TestableLooper.get(this).getLooper();
|
||||
|
||||
mListBuilder = new NotifListBuilderImpl(mSystemClock);
|
||||
mListBuilder = new NotifListBuilderImpl(mSystemClock, mNotifLog);
|
||||
mListBuilder.setOnRenderListListener(mOnRenderListListener);
|
||||
|
||||
mListBuilder.attach(mNotifCollection);
|
||||
|
||||
Reference in New Issue
Block a user