Merge "Use table logging for Notification memory use" into tm-qpr-dev

This commit is contained in:
Jernej Virag
2023-01-19 13:02:54 +00:00
committed by Android (Google) Code Review

View File

@@ -18,9 +18,12 @@
package com.android.systemui.statusbar.notification.logging package com.android.systemui.statusbar.notification.logging
import android.stats.sysui.NotificationEnums import android.stats.sysui.NotificationEnums
import android.util.Log
import com.android.systemui.Dumpable import com.android.systemui.Dumpable
import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dump.DumpManager import com.android.systemui.dump.DumpManager
import com.android.systemui.dump.DumpsysTableLogger
import com.android.systemui.dump.Row
import com.android.systemui.statusbar.notification.collection.NotifPipeline import com.android.systemui.statusbar.notification.collection.NotifPipeline
import java.io.PrintWriter import java.io.PrintWriter
import javax.inject.Inject import javax.inject.Inject
@@ -33,6 +36,7 @@ constructor(val dumpManager: DumpManager, val notificationPipeline: NotifPipelin
fun init() { fun init() {
dumpManager.registerNormalDumpable(javaClass.simpleName, this) dumpManager.registerNormalDumpable(javaClass.simpleName, this)
Log.i("NotificationMemory", "Registered dumpable.")
} }
override fun dump(pw: PrintWriter, args: Array<out String>) { override fun dump(pw: PrintWriter, args: Array<out String>) {
@@ -45,27 +49,36 @@ constructor(val dumpManager: DumpManager, val notificationPipeline: NotifPipelin
/** Renders a table of notification object usage into passed [PrintWriter]. */ /** Renders a table of notification object usage into passed [PrintWriter]. */
private fun dumpNotificationObjects(pw: PrintWriter, memoryUse: List<NotificationMemoryUsage>) { private fun dumpNotificationObjects(pw: PrintWriter, memoryUse: List<NotificationMemoryUsage>) {
pw.println("Notification Object Usage") val columns =
pw.println("-----------") listOf(
pw.println( "Package",
"Package".padEnd(35) + "Small Icon",
"\t\tSmall\tLarge\t${"Style".padEnd(15)}\t\tStyle\tBig\tExtend.\tExtras\tCustom" "Large Icon",
) "Style",
pw.println("".padEnd(35) + "\t\tIcon\tIcon\t${"".padEnd(15)}\t\tIcon\tPicture\t \t \tView") "Style Icon",
pw.println() "Big Picture",
"Extender",
memoryUse.forEach { use -> "Extras",
pw.println( "Custom View",
use.packageName.padEnd(35) + "Key"
"\t\t" +
"${use.objectUsage.smallIcon}\t${use.objectUsage.largeIcon}\t" +
(styleEnumToString(use.objectUsage.style).take(15) ?: "").padEnd(15) +
"\t\t${use.objectUsage.styleIcon}\t" +
"${use.objectUsage.bigPicture}\t${use.objectUsage.extender}\t" +
"${use.objectUsage.extras}\t${use.objectUsage.hasCustomView}\t" +
use.notificationKey
) )
} val rows: List<Row> =
memoryUse.map {
listOf(
it.packageName,
toKb(it.objectUsage.smallIcon),
toKb(it.objectUsage.largeIcon),
styleEnumToString(it.objectUsage.style),
toKb(it.objectUsage.styleIcon),
toKb(it.objectUsage.bigPicture),
toKb(it.objectUsage.extender),
toKb(it.objectUsage.extras),
it.objectUsage.hasCustomView.toString(),
// | is a field delimiter in the output format so we need to replace
// it to avoid breakage.
it.notificationKey.replace('|', '│')
)
}
// Calculate totals for easily glanceable summary. // Calculate totals for easily glanceable summary.
data class Totals( data class Totals(
@@ -88,18 +101,23 @@ constructor(val dumpManager: DumpManager, val notificationPipeline: NotifPipelin
t t
} }
pw.println() val totalsRow: List<Row> =
pw.println("TOTALS") listOf(
pw.println( listOf(
"".padEnd(35) + "TOTALS",
"\t\t" + toKb(totals.smallIcon),
"${toKb(totals.smallIcon)}\t${toKb(totals.largeIcon)}\t" + toKb(totals.largeIcon),
"".padEnd(15) + "",
"\t\t${toKb(totals.styleIcon)}\t" + toKb(totals.styleIcon),
"${toKb(totals.bigPicture)}\t${toKb(totals.extender)}\t" + toKb(totals.bigPicture),
toKb(totals.extras) toKb(totals.extender),
) toKb(totals.extras),
pw.println() "",
""
)
)
val tableLogger = DumpsysTableLogger("Notification Object Usage", columns, rows + totalsRow)
tableLogger.printTableData(pw)
} }
/** Renders a table of notification view usage into passed [PrintWriter] */ /** Renders a table of notification view usage into passed [PrintWriter] */
@@ -116,40 +134,65 @@ constructor(val dumpManager: DumpManager, val notificationPipeline: NotifPipelin
var softwareBitmapsPenalty: Int = 0, var softwareBitmapsPenalty: Int = 0,
) )
val totals = Totals() val columns =
pw.println("Notification View Usage") listOf(
pw.println("-----------") "Package",
pw.println("View Type".padEnd(24) + "\tSmall\tLarge\tStyle\tCustom\tSoftware") "View Type",
pw.println("".padEnd(24) + "\tIcon\tIcon\tUse\tView\tBitmaps") "Small Icon",
pw.println() "Large Icon",
memoryUse "Style Use",
.filter { it.viewUsage.isNotEmpty() } "Custom View",
.forEach { use -> "Software Bitmaps",
pw.println(use.packageName + " " + use.notificationKey) "Key"
use.viewUsage.forEach { view -> )
pw.println( val rows =
" ${view.viewType.toString().padEnd(24)}\t${view.smallIcon}" + memoryUse
"\t${view.largeIcon}\t${view.style}" + .filter { it.viewUsage.isNotEmpty() }
"\t${view.customViews}\t${view.softwareBitmapsPenalty}" .flatMap { use ->
) use.viewUsage.map { view ->
listOf(
if (view.viewType == ViewType.TOTAL) { use.packageName,
totals.smallIcon += view.smallIcon view.viewType.toString(),
totals.largeIcon += view.largeIcon toKb(view.smallIcon),
totals.style += view.style toKb(view.largeIcon),
totals.customViews += view.customViews toKb(view.style),
totals.softwareBitmapsPenalty += view.softwareBitmapsPenalty toKb(view.customViews),
toKb(view.softwareBitmapsPenalty),
// | is a field delimiter in the output format so we need to replace
// it to avoid breakage.
use.notificationKey.replace('|', '│')
)
} }
} }
val totals = Totals()
memoryUse
.filter { it.viewUsage.isNotEmpty() }
.map { it.viewUsage.firstOrNull { view -> view.viewType == ViewType.TOTAL } }
.filterNotNull()
.forEach { view ->
totals.smallIcon += view.smallIcon
totals.largeIcon += view.largeIcon
totals.style += view.style
totals.customViews += view.customViews
totals.softwareBitmapsPenalty += view.softwareBitmapsPenalty
} }
pw.println()
pw.println("TOTALS") val totalsRow: List<Row> =
pw.println( listOf(
" ${"".padEnd(24)}\t${toKb(totals.smallIcon)}" + listOf(
"\t${toKb(totals.largeIcon)}\t${toKb(totals.style)}" + "TOTALS",
"\t${toKb(totals.customViews)}\t${toKb(totals.softwareBitmapsPenalty)}" "",
) toKb(totals.smallIcon),
pw.println() toKb(totals.largeIcon),
toKb(totals.style),
toKb(totals.customViews),
toKb(totals.softwareBitmapsPenalty),
""
)
)
val tableLogger = DumpsysTableLogger("Notification View Usage", columns, rows + totalsRow)
tableLogger.printTableData(pw)
} }
private fun styleEnumToString(styleEnum: Int): String = private fun styleEnumToString(styleEnum: Int): String =
@@ -168,6 +211,10 @@ constructor(val dumpManager: DumpManager, val notificationPipeline: NotifPipelin
} }
private fun toKb(bytes: Int): String { private fun toKb(bytes: Int): String {
return (bytes / 1024).toString() + " KB" if (bytes == 0) {
return "--"
}
return "%.2f KB".format(bytes / 1024f)
} }
} }