parent
f18f99a009
commit
fd57f24a14
@ -0,0 +1,280 @@
|
||||
package cfig.lazybox.staging
|
||||
|
||||
import java.io.File
|
||||
import org.slf4j.LoggerFactory
|
||||
|
||||
class Perfetto {
|
||||
private val log = LoggerFactory.getLogger(Perfetto::class.java.simpleName)
|
||||
|
||||
/**
|
||||
* Main entry method to generate the configuration file.
|
||||
*/
|
||||
fun run(args: Array<String>) {
|
||||
val options = args.toSet()
|
||||
|
||||
// Check for help flags
|
||||
if ("-h" in options || "--help" in options) {
|
||||
printUsage()
|
||||
return
|
||||
}
|
||||
|
||||
log.info("Running Perfetto configuration generation with arguments: ${args.joinToString(", ")}")
|
||||
val outputFileName = "pftrace.cfg"
|
||||
val finalConfig = generatePerfettoConfig(options)
|
||||
|
||||
try {
|
||||
File(outputFileName).writeText(finalConfig)
|
||||
log.info("Successfully wrote Perfetto configuration to '$outputFileName'.")
|
||||
log.info("Options used: ${options.ifEmpty { setOf("default") }}")
|
||||
|
||||
if ("+boot" in options) {
|
||||
val adbCommands = """
|
||||
|
||||
--------------------------------------------------------------------
|
||||
Boot trace config enabled. To capture a boot trace, run these commands:
|
||||
|
||||
[enable tracing]
|
||||
adb root
|
||||
adb push pftrace.cfg /data/misc/perfetto-configs/boottrace.pbtxt
|
||||
adb shell setprop persist.debug.perfetto.boottrace 1
|
||||
|
||||
[pull trace result after reboot]
|
||||
adb pull /data/misc/perfetto-traces/boottrace.perfetto-trace
|
||||
--------------------------------------------------------------------
|
||||
""".trimIndent()
|
||||
println(adbCommands)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
log.error("Failed to write to file '$outputFileName'. Reason: ${e.message}")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the help/usage message for the script.
|
||||
*/
|
||||
private fun printUsage() {
|
||||
val usage = """
|
||||
Usage: kotlin Perfetto.main.kts [options...]
|
||||
|
||||
Generates a pftrace.cfg file for Perfetto tracing based on specified options.
|
||||
The output file is named 'pftrace.cfg'.
|
||||
|
||||
Options:
|
||||
-h, --help Show this help message and exit.
|
||||
|
||||
+power Include ftrace power events and Android power rail data sources.
|
||||
+atrace Include a wide range of atrace categories for detailed app tracing.
|
||||
+lmk Include Low Memory Killer (LMK) and OOM score ftrace events.
|
||||
+cpu_usage Include detailed CPU time and process fork count statistics.
|
||||
+logcat Include all Android logcat buffers in the trace.
|
||||
+sf Include SurfaceFlinger frame timeline data.
|
||||
+boot Enable boot tracing. After generating the config, this prints the
|
||||
necessary adb commands to set up the trace for the next boot.
|
||||
""".trimIndent()
|
||||
println(usage)
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the Perfetto configuration string based on the provided options.
|
||||
*/
|
||||
fun generatePerfettoConfig(options: Set<String> = emptySet()): String {
|
||||
log.info("Generating Perfetto configuration with options: $options")
|
||||
val configBuilder = StringBuilder()
|
||||
|
||||
// --- 1. Base Config: Buffers ---
|
||||
log.info("Adding buffers")
|
||||
configBuilder.append(
|
||||
"""
|
||||
# === Buffers ===
|
||||
buffers: {
|
||||
size_kb: 63488
|
||||
fill_policy: DISCARD
|
||||
}
|
||||
buffers: {
|
||||
size_kb: 2048
|
||||
fill_policy: DISCARD
|
||||
}
|
||||
|
||||
""".trimIndent()
|
||||
)
|
||||
|
||||
// --- 2. Base Config: Core Data Sources (excluding sys_stats) ---
|
||||
log.info("Adding core data sources")
|
||||
configBuilder.append(
|
||||
"""
|
||||
# === Base Data Sources ===
|
||||
data_sources: {
|
||||
config {
|
||||
name: "linux.process_stats"
|
||||
process_stats_config {
|
||||
scan_all_processes_on_start: true
|
||||
proc_stats_poll_ms: 250
|
||||
}
|
||||
}
|
||||
}
|
||||
data_sources: {
|
||||
config {
|
||||
name: "android.packages_list"
|
||||
target_buffer: 1
|
||||
}
|
||||
}
|
||||
""".trimIndent()
|
||||
)
|
||||
|
||||
// --- 3. Dynamic and Optional Config ---
|
||||
|
||||
// Dynamically build linux.sys_stats config
|
||||
val sysStatsLines = mutableListOf(
|
||||
"meminfo_period_ms: 250",
|
||||
"vmstat_period_ms: 250",
|
||||
"cpufreq_period_ms: 250"
|
||||
)
|
||||
if ("+cpu_usage" in options) {
|
||||
log.info("Adding data sources for: +cpu_usage")
|
||||
sysStatsLines.add("stat_period_ms: 250")
|
||||
sysStatsLines.add("stat_counters: STAT_CPU_TIMES")
|
||||
sysStatsLines.add("stat_counters: STAT_FORK_COUNT")
|
||||
}
|
||||
|
||||
log.info("Appending sys_stats data source to config")
|
||||
configBuilder.append("\n\n# === System-wide Stats ===")
|
||||
configBuilder.append(
|
||||
"""
|
||||
data_sources: {
|
||||
config {
|
||||
name: "linux.sys_stats"
|
||||
sys_stats_config {
|
||||
""".trimIndent()
|
||||
)
|
||||
sysStatsLines.forEach { configBuilder.append("\n $it") }
|
||||
configBuilder.append(
|
||||
"""
|
||||
}
|
||||
}
|
||||
}
|
||||
""".trimIndent()
|
||||
)
|
||||
|
||||
// Dynamically build ftrace config
|
||||
val ftraceEvents = mutableListOf<String>()
|
||||
val atraceCategories = mutableListOf<String>()
|
||||
val atraceApps = mutableListOf<String>()
|
||||
|
||||
if ("+power" in options) {
|
||||
ftraceEvents.add("power/*")
|
||||
}
|
||||
if ("+atrace" in options) {
|
||||
ftraceEvents.add("ftrace/print")
|
||||
atraceCategories.addAll(
|
||||
listOf(
|
||||
"adb", "aidl", "am", "audio", "binder_driver", "binder_lock",
|
||||
"bionic", "camera", "dalvik", "database", "gfx", "hal",
|
||||
"input", "network", "nnapi", "pm", "power", "res", "rro",
|
||||
"rs", "sm", "ss", "vibrator", "video", "view", "webview", "wm"
|
||||
)
|
||||
)
|
||||
}
|
||||
if ("+lmk" in options) {
|
||||
log.info("Adding data sources for: +lmk")
|
||||
ftraceEvents.add("lowmemorykiller/lowmemory_kill")
|
||||
ftraceEvents.add("oom/oom_score_adj_update")
|
||||
atraceApps.add("lmkd")
|
||||
}
|
||||
|
||||
if (ftraceEvents.isNotEmpty() || atraceCategories.isNotEmpty() || atraceApps.isNotEmpty()) {
|
||||
log.info("Appending ftrace data source to config")
|
||||
configBuilder.append("\n\n# === Optional Ftrace/Atrace Tracing ===")
|
||||
configBuilder.append(
|
||||
"""
|
||||
data_sources: {
|
||||
config {
|
||||
name: "linux.ftrace"
|
||||
ftrace_config {
|
||||
""".trimIndent()
|
||||
)
|
||||
ftraceEvents.forEach { configBuilder.append("\n ftrace_events: \"$it\"") }
|
||||
atraceCategories.forEach { configBuilder.append("\n atrace_categories: \"$it\"") }
|
||||
atraceApps.forEach { configBuilder.append("\n atrace_apps: \"$it\"") }
|
||||
configBuilder.append(
|
||||
"""
|
||||
}
|
||||
}
|
||||
}
|
||||
""".trimIndent()
|
||||
)
|
||||
}
|
||||
|
||||
if ("+power" in options) {
|
||||
log.info("Adding data sources for: android.power")
|
||||
configBuilder.append(
|
||||
"""
|
||||
|
||||
# === Optional Android Power Tracing ===
|
||||
data_sources: {
|
||||
config {
|
||||
name: "android.power"
|
||||
android_power_config {
|
||||
battery_poll_ms: 250
|
||||
battery_counters: BATTERY_COUNTER_CAPACITY_PERCENT
|
||||
battery_counters: BATTERY_COUNTER_CHARGE
|
||||
battery_counters: BATTERY_COUNTER_CURRENT
|
||||
collect_power_rails: true
|
||||
}
|
||||
}
|
||||
}
|
||||
""".trimIndent()
|
||||
)
|
||||
}
|
||||
|
||||
if ("+logcat" in options) {
|
||||
log.info("Adding data sources for: +logcat")
|
||||
configBuilder.append(
|
||||
"""
|
||||
# === Optional Logcat Tracing ===
|
||||
data_sources {
|
||||
config {
|
||||
name: "android.log"
|
||||
android_log_config {
|
||||
log_ids: LID_CRASH
|
||||
log_ids: LID_DEFAULT
|
||||
log_ids: LID_EVENTS
|
||||
log_ids: LID_KERNEL
|
||||
log_ids: LID_RADIO
|
||||
log_ids: LID_SECURITY
|
||||
log_ids: LID_STATS
|
||||
log_ids: LID_SYSTEM
|
||||
}
|
||||
}
|
||||
}
|
||||
""".trimIndent()
|
||||
)
|
||||
}
|
||||
|
||||
// (REVISED) Add SurfaceFlinger data source if option is present
|
||||
if ("+sf" in options) {
|
||||
log.info("Adding data sources for: +sf")
|
||||
configBuilder.append(
|
||||
"""
|
||||
# === Optional SurfaceFlinger Tracing ===
|
||||
data_sources {
|
||||
config {
|
||||
name: "android.surfaceflinger.frametimeline"
|
||||
}
|
||||
}
|
||||
""".trimIndent()
|
||||
)
|
||||
}
|
||||
|
||||
// --- 4. Trace Duration ---
|
||||
log.info("Adding trace duration")
|
||||
configBuilder.append(
|
||||
"""
|
||||
# === Trace Duration ===
|
||||
# The total duration of the trace in milliseconds.
|
||||
duration_ms: 15000
|
||||
""".trimIndent()
|
||||
)
|
||||
|
||||
return configBuilder.toString()
|
||||
}
|
||||
}
|
Binary file not shown.
Loading…
Reference in New Issue