• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 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 @file:OptIn(InternalComposeTracingApi::class)
18 
19 package com.android.systemui.compose
20 
21 import android.os.Trace
22 import android.util.Log
23 import androidx.compose.runtime.Composer
24 import androidx.compose.runtime.CompositionTracer
25 import androidx.compose.runtime.InternalComposeTracingApi
26 import com.android.systemui.CoreStartable
27 import com.android.systemui.dagger.SysUISingleton
28 import com.android.systemui.statusbar.commandline.Command
29 import com.android.systemui.statusbar.commandline.CommandRegistry
30 import com.android.systemui.statusbar.commandline.ParseableCommand
31 import java.io.PrintWriter
32 import javax.inject.Inject
33 
34 private const val TAG = "ComposeTracingStartable"
35 private const val COMMAND_NAME = "composition-tracing"
36 private const val SUBCOMMAND_ENABLE = "enable"
37 private const val SUBCOMMAND_DISABLE = "disable"
38 
39 /**
40  * Sets up a [Command] to enable or disable Composition tracing.
41  *
42  * Usage:
43  * ```
44  * adb shell cmd statusbar composition-tracing [enable|disable]
45  * ${ANDROID_BUILD_TOP}/external/perfetto/tools/record_android_trace -c ${ANDROID_BUILD_TOP}/prebuilts/tools/linux-x86_64/perfetto/configs/trace_config_detailed.textproto
46  * ```
47  */
48 @SysUISingleton
49 class ComposeTracingStartable @Inject constructor(private val commandRegistry: CommandRegistry) :
50     CoreStartable {
51     @OptIn(InternalComposeTracingApi::class)
startnull52     override fun start() {
53         Log.i(TAG, "Set up Compose tracing command")
54         commandRegistry.registerCommand(COMMAND_NAME) { CompositionTracingCommand() }
55     }
56 }
57 
58 private class CompositionTracingCommand : ParseableCommand(COMMAND_NAME) {
59     val enable by subCommand(EnableCommand())
60     val disable by subCommand(DisableCommand())
61 
executenull62     override fun execute(pw: PrintWriter) {
63         if ((enable != null) xor (disable != null)) {
64             enable?.execute(pw)
65             disable?.execute(pw)
66         } else {
67             help(pw)
68         }
69     }
70 }
71 
72 private class EnableCommand : ParseableCommand(SUBCOMMAND_ENABLE) {
executenull73     override fun execute(pw: PrintWriter) {
74         val msg = "Enabled Composition tracing"
75         Log.i(TAG, msg)
76         pw.println(msg)
77         enableCompositionTracing()
78     }
79 
enableCompositionTracingnull80     private fun enableCompositionTracing() {
81         Composer.setTracer(
82             object : CompositionTracer {
83                 override fun traceEventStart(key: Int, dirty1: Int, dirty2: Int, info: String) {
84                     Trace.traceBegin(Trace.TRACE_TAG_APP, info)
85                 }
86 
87                 override fun traceEventEnd() = Trace.traceEnd(Trace.TRACE_TAG_APP)
88 
89                 override fun isTraceInProgress(): Boolean = Trace.isEnabled()
90             }
91         )
92     }
93 }
94 
95 private class DisableCommand : ParseableCommand(SUBCOMMAND_DISABLE) {
executenull96     override fun execute(pw: PrintWriter) {
97         val msg = "Disabled Composition tracing"
98         Log.i(TAG, msg)
99         pw.println(msg)
100         disableCompositionTracing()
101     }
102 
disableCompositionTracingnull103     private fun disableCompositionTracing() {
104         Composer.setTracer(null)
105     }
106 }
107