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

Commit b6f4dc22 authored by Beverly's avatar Beverly
Browse files

Add ListBuilder and NotifCollection to dump

For easier debugging

Test: atest SystemUiTests
Change-Id: I8af3065ef10230607b67f9605f3b73a871759c3a
parent 1035b49a
Loading
Loading
Loading
Loading
+103 −17
Original line number Diff line number Diff line
@@ -16,42 +16,128 @@

package com.android.systemui.statusbar.notification.collection;

import java.util.Arrays;
import java.util.List;


/**
 * Utility class for dumping the results of a {@link ShadeListBuilder} to a debug string.
 */
public class ListDumper {

    /** See class description */
    public static String dumpList(List<ListEntry> entries) {
    /**
     * Creates a debug string for a list of grouped notifications that will be printed
     * in the order given in a tiered/tree structure.
     * @param includeRecordKeeping whether to print out the Pluggables that caused the notification
     *                             entry to be in its current state (ie: filter, lifeExtender)
     */
    public static String dumpTree(
            List<ListEntry> entries,
            boolean includeRecordKeeping,
            String indent) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < entries.size(); i++) {
            ListEntry entry = entries.get(i);
            dumpEntry(entry, Integer.toString(i), "", sb);
        final String childEntryIndent = indent + INDENT;
        for (int topEntryIndex = 0; topEntryIndex < entries.size(); topEntryIndex++) {
            ListEntry entry = entries.get(topEntryIndex);
            dumpEntry(entry,
                    Integer.toString(topEntryIndex),
                    indent,
                    sb,
                    true,
                    includeRecordKeeping);
            if (entry instanceof GroupEntry) {
                GroupEntry ge = (GroupEntry) entry;
                for (int j = 0; j < ge.getChildren().size(); j++) {
                    dumpEntry(
                            ge.getChildren().get(j),
                            Integer.toString(j),
                            INDENT,
                            sb);
                List<NotificationEntry> children = ge.getChildren();
                for (int childIndex = 0;  childIndex < children.size(); childIndex++) {
                    dumpEntry(children.get(childIndex),
                            Integer.toString(topEntryIndex) + "." + Integer.toString(childIndex),
                            childEntryIndent,
                            sb,
                            true,
                            includeRecordKeeping);
                }
            }
        }
        return sb.toString();
    }

    /**
     * Creates a debug string for a flat list of notifications
     * @param includeRecordKeeping whether to print out the Pluggables that caused the notification
     *                             entry to be in its current state (ie: filter, lifeExtender)
     */
    public static String dumpList(
            List<NotificationEntry> entries,
            boolean includeRecordKeeping,
            String indent) {
        StringBuilder sb = new StringBuilder();
        for (int j = 0; j < entries.size(); j++) {
            dumpEntry(
                    entries.get(j),
                    Integer.toString(j),
                    indent,
                    sb,
                    false,
                    includeRecordKeeping);
        }
        return sb.toString();
    }

    private static void dumpEntry(
            ListEntry entry, String index, String indent, StringBuilder sb) {
            ListEntry entry,
            String index,
            String indent,
            StringBuilder sb,
            boolean includeParent,
            boolean includeRecordKeeping) {
        sb.append(indent)
                .append("[").append(index).append("] ")
                .append(entry.getKey())
                .append(" (parent=")
                .append(entry.getKey());

        if (includeParent) {
            sb.append(" (parent=")
                    .append(entry.getParent() != null ? entry.getParent().getKey() : null)
                .append(")\n");
                    .append(")");
        }

        if (includeRecordKeeping) {
            NotificationEntry notifEntry = entry.getRepresentativeEntry();
            StringBuilder rksb = new StringBuilder();

            if (!notifEntry.mLifetimeExtenders.isEmpty()) {
                String[] lifetimeExtenderNames = new String[notifEntry.mLifetimeExtenders.size()];
                for (int i = 0; i < lifetimeExtenderNames.length; i++) {
                    lifetimeExtenderNames[i] = notifEntry.mLifetimeExtenders.get(i).getName();
                }
                rksb.append("lifetimeExtenders=")
                        .append(Arrays.toString(lifetimeExtenderNames))
                        .append(" ");
            }

            if (notifEntry.mExcludingFilter != null) {
                rksb.append("filter=")
                        .append(notifEntry.mExcludingFilter)
                        .append(" ");
            }

            if (notifEntry.mNotifPromoter != null) {
                rksb.append("promoter=")
                        .append(notifEntry.mNotifPromoter)
                        .append(" ");
            }

            if (notifEntry.hasInflationError()) {
                rksb.append("hasInflationError ");
            }

            String rkString = rksb.toString();
            if (!rkString.isEmpty()) {
                sb.append("\n\t")
                        .append(indent)
                        .append(rkString);
            }
        }

        sb.append("\n");
    }

    private static final String INDENT = "  ";
+22 −2
Original line number Diff line number Diff line
@@ -47,6 +47,8 @@ import android.util.ArrayMap;
import android.util.Log;

import com.android.internal.statusbar.IStatusBarService;
import com.android.systemui.DumpController;
import com.android.systemui.Dumpable;
import com.android.systemui.statusbar.notification.collection.coalescer.CoalescedEvent;
import com.android.systemui.statusbar.notification.collection.coalescer.GroupCoalescer;
import com.android.systemui.statusbar.notification.collection.coalescer.GroupCoalescer.BatchableNotificationHandler;
@@ -56,6 +58,8 @@ import com.android.systemui.statusbar.notification.collection.notifcollection.No
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifLifetimeExtender;
import com.android.systemui.util.Assert;

import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
@@ -92,7 +96,7 @@ import javax.inject.Singleton;
 */
@MainThread
@Singleton
public class NotifCollection {
public class NotifCollection implements Dumpable {
    private final IStatusBarService mStatusBarService;

    private final Map<String, NotificationEntry> mNotificationSet = new ArrayMap<>();
@@ -107,9 +111,10 @@ public class NotifCollection {
    private boolean mAmDispatchingToOtherCode;

    @Inject
    public NotifCollection(IStatusBarService statusBarService) {
    public NotifCollection(IStatusBarService statusBarService, DumpController dumpController) {
        Assert.isMainThread();
        mStatusBarService = statusBarService;
        dumpController.registerDumpable(TAG, this);
    }

    /** Initializes the NotifCollection and registers it to receive notification events. */
@@ -442,4 +447,19 @@ public class NotifCollection {
    public @interface CancellationReason {}

    public static final int REASON_UNKNOWN = 0;

    @Override
    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
        final List<NotificationEntry> entries = new ArrayList<>(getActiveNotifs());

        pw.println("\t" + TAG + " unsorted/unfiltered notifications:");
        if (entries.size() == 0) {
            pw.println("\t\t None");
        }
        pw.println(
                ListDumper.dumpList(
                        entries,
                        true,
                        "\t\t"));
    }
}
+24 −4
Original line number Diff line number Diff line
@@ -17,7 +17,6 @@
package com.android.systemui.statusbar.notification.collection;

import static com.android.systemui.statusbar.notification.collection.GroupEntry.ROOT_ENTRY;
import static com.android.systemui.statusbar.notification.collection.ListDumper.dumpList;
import static com.android.systemui.statusbar.notification.collection.listbuilder.PipelineState.STATE_BUILD_STARTED;
import static com.android.systemui.statusbar.notification.collection.listbuilder.PipelineState.STATE_FINALIZING;
import static com.android.systemui.statusbar.notification.collection.listbuilder.PipelineState.STATE_GROUPING;
@@ -32,6 +31,8 @@ import android.annotation.MainThread;
import android.annotation.Nullable;
import android.util.ArrayMap;

import com.android.systemui.DumpController;
import com.android.systemui.Dumpable;
import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeRenderListListener;
import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeSortListener;
import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeTransformGroupsListener;
@@ -46,6 +47,8 @@ import com.android.systemui.statusbar.notification.logging.NotifLog;
import com.android.systemui.util.Assert;
import com.android.systemui.util.time.SystemClock;

import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -63,7 +66,7 @@ import javax.inject.Singleton;
 */
@MainThread
@Singleton
public class ShadeListBuilder {
public class ShadeListBuilder implements Dumpable {
    private final SystemClock mSystemClock;
    private final NotifLog mNotifLog;

@@ -92,10 +95,14 @@ public class ShadeListBuilder {
    private final List<ListEntry> mReadOnlyNotifList = Collections.unmodifiableList(mNotifList);

    @Inject
    public ShadeListBuilder(SystemClock systemClock, NotifLog notifLog) {
    public ShadeListBuilder(
            SystemClock systemClock,
            NotifLog notifLog,
            DumpController dumpController) {
        Assert.isMainThread();
        mSystemClock = systemClock;
        mNotifLog = notifLog;
        dumpController.registerDumpable(TAG, this);
    }

    /**
@@ -324,7 +331,7 @@ public class ShadeListBuilder {

        // Step 6: Dispatch the new list, first to any listeners and then to the view layer
        mNotifLog.log(NotifEvent.DISPATCH_FINAL_LIST, "List finalized, is:\n"
                + dumpList(mNotifList));
                + ListDumper.dumpTree(mNotifList, false, "\t\t"));
        dispatchOnBeforeRenderList(mReadOnlyNotifList);
        if (mOnRenderListListener != null) {
            mOnRenderListListener.onRenderList(mReadOnlyNotifList);
@@ -772,6 +779,19 @@ public class ShadeListBuilder {
        }
    }

    @Override
    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
        pw.println("\t" + TAG + " shade notifications:");
        if (getShadeList().size() == 0) {
            pw.println("\t\t None");
        }

        pw.println(ListDumper.dumpTree(
                getShadeList(),
                true,
                "\t\t"));
    }

    /** See {@link #setOnRenderListListener(OnRenderListListener)} */
    public interface OnRenderListListener {
        /**
+3 −1
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -48,6 +49,7 @@ import androidx.test.filters.SmallTest;

import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.statusbar.NotificationVisibility;
import com.android.systemui.DumpController;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.RankingBuilder;
import com.android.systemui.statusbar.notification.collection.NoManSimulator.NotifEvent;
@@ -103,7 +105,7 @@ public class NotifCollectionTest extends SysuiTestCase {
        MockitoAnnotations.initMocks(this);
        Assert.sMainLooper = TestableLooper.get(this).getLooper();

        mCollection = new NotifCollection(mStatusBarService);
        mCollection = new NotifCollection(mStatusBarService, mock(DumpController.class));
        mCollection.attach(mGroupCoalescer);
        mCollection.addCollectionListener(mCollectionListener);
        mCollection.setBuildListener(mBuildListener);
+6 −3
Original line number Diff line number Diff line
@@ -16,7 +16,7 @@

package com.android.systemui.statusbar.notification.collection;

import static com.android.systemui.statusbar.notification.collection.ListDumper.dumpList;
import static com.android.systemui.statusbar.notification.collection.ListDumper.dumpTree;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
@@ -27,6 +27,7 @@ import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
@@ -37,6 +38,7 @@ import android.util.ArrayMap;

import androidx.test.filters.SmallTest;

import com.android.systemui.DumpController;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.notification.collection.ShadeListBuilder.OnRenderListListener;
import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeRenderListListener;
@@ -100,7 +102,7 @@ public class ShadeListBuilderTest extends SysuiTestCase {
        MockitoAnnotations.initMocks(this);
        Assert.sMainLooper = TestableLooper.get(this).getLooper();

        mListBuilder = new ShadeListBuilder(mSystemClock, mNotifLog);
        mListBuilder = new ShadeListBuilder(mSystemClock, mNotifLog, mock(DumpController.class));
        mListBuilder.setOnRenderListListener(mOnRenderListListener);

        mListBuilder.attach(mNotifCollection);
@@ -1081,7 +1083,8 @@ public class ShadeListBuilderTest extends SysuiTestCase {
            }
        } catch (AssertionError err) {
            throw new AssertionError(
                    "List under test failed verification:\n" + dumpList(mBuiltList), err);
                    "List under test failed verification:\n" + dumpTree(mBuiltList,
                            true, ""), err);
        }
    }