1 /* 2 * Copyright (C) 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.systemui.statusbar.notification.collection; 18 19 import static com.android.systemui.statusbar.notification.collection.NotifCollection.REASON_NOT_CANCELED; 20 import static com.android.systemui.statusbar.notification.collection.NotificationEntry.DismissState.NOT_DISMISSED; 21 22 import static java.util.Objects.requireNonNull; 23 24 import com.android.systemui.statusbar.NotificationInteractionTracker; 25 26 import java.util.Arrays; 27 import java.util.List; 28 29 /** 30 * Utility class for dumping the results of a {@link ShadeListBuilder} to a debug string. 31 */ 32 public class ListDumper { 33 34 /** 35 * Creates a debug string for a list of grouped notifications that will be printed 36 * in the order given in a tiered/tree structure. 37 * @param includeRecordKeeping whether to print out the Pluggables that caused the notification 38 * entry to be in its current state (ie: filter, lifeExtender) 39 */ dumpTree( List<ListEntry> entries, NotificationInteractionTracker interactionTracker, boolean includeRecordKeeping, String indent)40 public static String dumpTree( 41 List<ListEntry> entries, 42 NotificationInteractionTracker interactionTracker, 43 boolean includeRecordKeeping, 44 String indent) { 45 StringBuilder sb = new StringBuilder(); 46 final String childEntryIndent = indent + INDENT; 47 for (int topEntryIndex = 0; topEntryIndex < entries.size(); topEntryIndex++) { 48 ListEntry entry = entries.get(topEntryIndex); 49 dumpEntry(entry, 50 Integer.toString(topEntryIndex), 51 indent, 52 sb, 53 true, 54 includeRecordKeeping, 55 interactionTracker.hasUserInteractedWith(entry.getKey())); 56 if (entry instanceof GroupEntry) { 57 GroupEntry ge = (GroupEntry) entry; 58 List<NotificationEntry> children = ge.getChildren(); 59 for (int childIndex = 0; childIndex < children.size(); childIndex++) { 60 dumpEntry(children.get(childIndex), 61 topEntryIndex + "." + childIndex, 62 childEntryIndent, 63 sb, 64 true, 65 includeRecordKeeping, 66 interactionTracker.hasUserInteractedWith(entry.getKey())); 67 } 68 } 69 } 70 return sb.toString(); 71 } 72 73 /** 74 * Creates a debug string for a flat list of notifications 75 * @param includeRecordKeeping whether to print out the Pluggables that caused the notification 76 * entry to be in its current state (ie: filter, lifeExtender) 77 */ dumpList( List<NotificationEntry> entries, boolean includeRecordKeeping, String indent)78 public static String dumpList( 79 List<NotificationEntry> entries, 80 boolean includeRecordKeeping, 81 String indent) { 82 StringBuilder sb = new StringBuilder(); 83 for (int j = 0; j < entries.size(); j++) { 84 dumpEntry( 85 entries.get(j), 86 Integer.toString(j), 87 indent, 88 sb, 89 false, 90 includeRecordKeeping, 91 false); 92 } 93 return sb.toString(); 94 } 95 dumpEntry( ListEntry entry, String index, String indent, StringBuilder sb, boolean includeParent, boolean includeRecordKeeping, boolean hasBeenInteractedWith )96 private static void dumpEntry( 97 ListEntry entry, 98 String index, 99 String indent, 100 StringBuilder sb, 101 boolean includeParent, 102 boolean includeRecordKeeping, 103 boolean hasBeenInteractedWith 104 ) { 105 sb.append(indent) 106 .append("[").append(index).append("] ") 107 .append(entry.getKey()); 108 109 if (includeParent) { 110 sb.append(" (parent=") 111 .append(entry.getParent() != null ? entry.getParent().getKey() : null) 112 .append(")"); 113 } 114 115 if (entry.getSection() != null) { 116 sb.append(" section=") 117 .append(entry.getSection().getLabel()); 118 } 119 120 if (includeRecordKeeping) { 121 NotificationEntry notifEntry = requireNonNull(entry.getRepresentativeEntry()); 122 StringBuilder rksb = new StringBuilder(); 123 124 if (!notifEntry.mLifetimeExtenders.isEmpty()) { 125 String[] lifetimeExtenderNames = new String[notifEntry.mLifetimeExtenders.size()]; 126 for (int i = 0; i < lifetimeExtenderNames.length; i++) { 127 lifetimeExtenderNames[i] = notifEntry.mLifetimeExtenders.get(i).getName(); 128 } 129 rksb.append("lifetimeExtenders=") 130 .append(Arrays.toString(lifetimeExtenderNames)) 131 .append(" "); 132 } 133 134 if (!notifEntry.mDismissInterceptors.isEmpty()) { 135 String[] interceptorsNames = new String[notifEntry.mDismissInterceptors.size()]; 136 for (int i = 0; i < interceptorsNames.length; i++) { 137 interceptorsNames[i] = notifEntry.mDismissInterceptors.get(i).getName(); 138 } 139 rksb.append("dismissInterceptors=") 140 .append(Arrays.toString(interceptorsNames)) 141 .append(" "); 142 } 143 144 if (notifEntry.getExcludingFilter() != null) { 145 rksb.append("filter=") 146 .append(notifEntry.getExcludingFilter().getName()) 147 .append(" "); 148 } 149 150 if (notifEntry.getNotifPromoter() != null) { 151 rksb.append("promoter=") 152 .append(notifEntry.getNotifPromoter().getName()) 153 .append(" "); 154 } 155 156 if (notifEntry.mCancellationReason != REASON_NOT_CANCELED) { 157 rksb.append("cancellationReason=") 158 .append(notifEntry.mCancellationReason) 159 .append(" "); 160 } 161 162 if (notifEntry.getDismissState() != NOT_DISMISSED) { 163 rksb.append("dismissState=") 164 .append(notifEntry.getDismissState()) 165 .append(" "); 166 } 167 168 if (notifEntry.getAttachState().getSuppressedChanges().getParent() != null) { 169 rksb.append("suppressedParent=") 170 .append(notifEntry.getAttachState().getSuppressedChanges() 171 .getParent().getKey()) 172 .append(" "); 173 } 174 175 if (notifEntry.getAttachState().getSuppressedChanges().getSection() != null) { 176 rksb.append("suppressedSection=") 177 .append(notifEntry.getAttachState().getSuppressedChanges() 178 .getSection()) 179 .append(" "); 180 } 181 182 if (hasBeenInteractedWith) { 183 rksb.append("interacted=yes "); 184 } 185 186 String rkString = rksb.toString(); 187 if (!rkString.isEmpty()) { 188 sb.append("\n\t") 189 .append(indent) 190 .append(rkString); 191 } 192 } 193 194 sb.append("\n"); 195 } 196 197 private static final String INDENT = " "; 198 } 199