1 /* 2 * Copyright (C) 2020 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.listbuilder 18 19 import com.android.systemui.log.LogBuffer 20 import com.android.systemui.log.LogLevel.DEBUG 21 import com.android.systemui.log.LogLevel.INFO 22 import com.android.systemui.log.LogLevel.WARNING 23 import com.android.systemui.log.dagger.NotificationLog 24 import com.android.systemui.statusbar.notification.collection.GroupEntry 25 import com.android.systemui.statusbar.notification.collection.ListEntry 26 import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter 27 import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifPromoter 28 import javax.inject.Inject 29 30 class ShadeListBuilderLogger @Inject constructor( 31 @NotificationLog private val buffer: LogBuffer 32 ) { 33 fun logOnBuildList() { 34 buffer.log(TAG, INFO, { 35 }, { 36 "Request received from NotifCollection" 37 }) 38 } 39 40 fun logEndBuildList(iterationCount: Int, topLevelEntries: Int, numChildren: Int) { 41 buffer.log(TAG, INFO, { 42 long1 = iterationCount.toLong() 43 int1 = topLevelEntries 44 int2 = numChildren 45 }, { 46 "(Build $long1) Build complete ($int1 top-level entries, $int2 children)" 47 }) 48 } 49 50 fun logPreRenderInvalidated(filterName: String, pipelineState: Int) { 51 buffer.log(TAG, DEBUG, { 52 str1 = filterName 53 int1 = pipelineState 54 }, { 55 """Pre-render Invalidator "$str1" invalidated; pipeline state is $int1""" 56 }) 57 } 58 59 fun logPreGroupFilterInvalidated(filterName: String, pipelineState: Int) { 60 buffer.log(TAG, DEBUG, { 61 str1 = filterName 62 int1 = pipelineState 63 }, { 64 """Pre-group NotifFilter "$str1" invalidated; pipeline state is $int1""" 65 }) 66 } 67 68 fun logReorderingAllowedInvalidated(name: String, pipelineState: Int) { 69 buffer.log(TAG, DEBUG, { 70 str1 = name 71 int1 = pipelineState 72 }, { 73 """ReorderingNowAllowed "$str1" invalidated; pipeline state is $int1""" 74 }) 75 } 76 77 fun logPromoterInvalidated(name: String, pipelineState: Int) { 78 buffer.log(TAG, DEBUG, { 79 str1 = name 80 int1 = pipelineState 81 }, { 82 """NotifPromoter "$str1" invalidated; pipeline state is $int1""" 83 }) 84 } 85 86 fun logNotifSectionInvalidated(name: String, pipelineState: Int) { 87 buffer.log(TAG, DEBUG, { 88 str1 = name 89 int1 = pipelineState 90 }, { 91 """NotifSection "$str1" invalidated; pipeline state is $int1""" 92 }) 93 } 94 95 fun logNotifComparatorInvalidated(name: String, pipelineState: Int) { 96 buffer.log(TAG, DEBUG, { 97 str1 = name 98 int1 = pipelineState 99 }, { 100 """NotifComparator "$str1" invalidated; pipeline state is $int1""" 101 }) 102 } 103 104 fun logFinalizeFilterInvalidated(name: String, pipelineState: Int) { 105 buffer.log(TAG, DEBUG, { 106 str1 = name 107 int1 = pipelineState 108 }, { 109 """Finalize NotifFilter "$str1" invalidated; pipeline state is $int1""" 110 }) 111 } 112 113 fun logDuplicateSummary(buildId: Int, groupKey: String, existingKey: String, newKey: String) { 114 buffer.log(TAG, WARNING, { 115 int1 = buildId 116 str1 = groupKey 117 str2 = existingKey 118 str3 = newKey 119 }, { 120 """(Build $int1) Duplicate summary for group "$str1": "$str2" vs. "$str3"""" 121 }) 122 } 123 124 fun logDuplicateTopLevelKey(buildId: Int, topLevelKey: String) { 125 buffer.log(TAG, WARNING, { 126 int1 = buildId 127 str1 = topLevelKey 128 }, { 129 "(Build $int1) Duplicate top-level key: $str1" 130 }) 131 } 132 133 fun logEntryAttachStateChanged( 134 buildId: Int, 135 key: String, 136 prevParent: GroupEntry?, 137 newParent: GroupEntry? 138 ) { 139 buffer.log(TAG, INFO, { 140 int1 = buildId 141 str1 = key 142 str2 = prevParent?.key 143 str3 = newParent?.key 144 }, { 145 146 val action = if (str2 == null && str3 != null) { 147 "ATTACHED" 148 } else if (str2 != null && str3 == null) { 149 "DETACHED" 150 } else if (str2 == null && str3 == null) { 151 "MODIFIED (DETACHED)" 152 } else { 153 "MODIFIED (ATTACHED)" 154 } 155 156 "(Build $int1) $action {$str1}" 157 }) 158 } 159 160 fun logParentChanged(buildId: Int, prevParent: GroupEntry?, newParent: GroupEntry?) { 161 buffer.log(TAG, INFO, { 162 int1 = buildId 163 str1 = prevParent?.key 164 str2 = newParent?.key 165 }, { 166 if (str1 == null && str2 != null) { 167 "(Build $int1) Parent is {$str2}" 168 } else if (str1 != null && str2 == null) { 169 "(Build $int1) Parent was {$str1}" 170 } else { 171 "(Build $int1) Reparent: {$str1} -> {$str2}" 172 } 173 }) 174 } 175 176 fun logParentChangeSuppressed( 177 buildId: Int, 178 suppressedParent: GroupEntry?, 179 keepingParent: GroupEntry? 180 ) { 181 buffer.log(TAG, INFO, { 182 int1 = buildId 183 str1 = suppressedParent?.key 184 str2 = keepingParent?.key 185 }, { 186 "(Build $long1) Change of parent to '$str1' suppressed; keeping parent '$str2'" 187 }) 188 } 189 190 fun logGroupPruningSuppressed( 191 buildId: Int, 192 keepingParent: GroupEntry? 193 ) { 194 buffer.log(TAG, INFO, { 195 int1 = buildId 196 str1 = keepingParent?.key 197 }, { 198 "(Build $long1) Group pruning suppressed; keeping parent '$str1'" 199 }) 200 } 201 202 fun logFilterChanged( 203 buildId: Int, 204 prevFilter: NotifFilter?, 205 newFilter: NotifFilter? 206 ) { 207 buffer.log(TAG, INFO, { 208 int1 = buildId 209 str1 = prevFilter?.name 210 str2 = newFilter?.name 211 }, { 212 "(Build $int1) Filter changed: $str1 -> $str2" 213 }) 214 } 215 216 fun logPromoterChanged( 217 buildId: Int, 218 prevPromoter: NotifPromoter?, 219 newPromoter: NotifPromoter? 220 ) { 221 buffer.log(TAG, INFO, { 222 int1 = buildId 223 str1 = prevPromoter?.name 224 str2 = newPromoter?.name 225 }, { 226 "(Build $int1) Promoter changed: $str1 -> $str2" 227 }) 228 } 229 230 fun logSectionChanged( 231 buildId: Int, 232 prevSection: NotifSection?, 233 newSection: NotifSection? 234 ) { 235 buffer.log(TAG, INFO, { 236 long1 = buildId.toLong() 237 str1 = prevSection?.label 238 str2 = newSection?.label 239 }, { 240 if (str1 == null) { 241 "(Build $long1) Section assigned: $str2" 242 } else { 243 "(Build $long1) Section changed: $str1 -> $str2" 244 } 245 }) 246 } 247 248 fun logSectionChangeSuppressed( 249 buildId: Int, 250 suppressedSection: NotifSection?, 251 assignedSection: NotifSection? 252 ) { 253 buffer.log(TAG, INFO, { 254 long1 = buildId.toLong() 255 str1 = suppressedSection?.label 256 str2 = assignedSection?.label 257 }, { 258 "(Build $long1) Suppressing section change to $str1 (staying at $str2)" 259 }) 260 } 261 262 fun logFinalList(entries: List<ListEntry>) { 263 if (entries.isEmpty()) { 264 buffer.log(TAG, DEBUG, {}, { "(empty list)" }) 265 } 266 for (i in entries.indices) { 267 val entry = entries[i] 268 buffer.log(TAG, DEBUG, { 269 int1 = i 270 str1 = entry.key 271 }, { 272 "[$int1] $str1" 273 }) 274 275 if (entry is GroupEntry) { 276 entry.summary?.let { 277 buffer.log(TAG, DEBUG, { 278 str1 = it.key 279 }, { 280 " [*] $str1 (summary)" 281 }) 282 } 283 for (j in entry.children.indices) { 284 val child = entry.children[j] 285 buffer.log(TAG, DEBUG, { 286 int1 = j 287 str1 = child.key 288 }, { 289 " [$int1] $str1" 290 }) 291 } 292 } 293 } 294 } 295 } 296 297 private const val TAG = "ShadeListBuilder"