Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8a5c5b3d authored by Jordan Demeulenaere's avatar Jordan Demeulenaere
Browse files

Add ComposeTracingStartable

This CL adds a new startable and SystemUI command to enable composition
tracing.

Usage:
$ adb shell cmd statusbar composition_tracing enable
$ ${ANDROID_BUILD_TOP}/external/perfetto/tools/record_android_trace -c ${ANDROID_BUILD_TOP}/prebuilts/tools/linux-x86_64/perfetto/configs/trace_config_detailed.textproto

Bug: 233351637
Test: Manual, recorded a trace and saw that compositions were traced
Flag: EXEMPT simple startable and tracing is disabled by default
Change-Id: I7488bd83b3427fb242a96f3110eb8c4845ed4981
parent 6ee3b28e
Loading
Loading
Loading
Loading
+31 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.systemui.compose

import com.android.systemui.CoreStartable
import dagger.Binds
import dagger.Module
import dagger.multibindings.ClassKey
import dagger.multibindings.IntoMap

@Module
interface ComposeModule {
    @Binds
    @IntoMap
    @ClassKey(ComposeTracingStartable::class)
    fun composeTracing(impl: ComposeTracingStartable): CoreStartable
}
+106 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

@file:OptIn(InternalComposeTracingApi::class)

package com.android.systemui.compose

import android.os.Trace
import android.util.Log
import androidx.compose.runtime.Composer
import androidx.compose.runtime.CompositionTracer
import androidx.compose.runtime.InternalComposeTracingApi
import com.android.systemui.CoreStartable
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.statusbar.commandline.Command
import com.android.systemui.statusbar.commandline.CommandRegistry
import com.android.systemui.statusbar.commandline.ParseableCommand
import java.io.PrintWriter
import javax.inject.Inject

private const val TAG = "ComposeTracingStartable"
private const val COMMAND_NAME = "composition-tracing"
private const val SUBCOMMAND_ENABLE = "enable"
private const val SUBCOMMAND_DISABLE = "disable"

/**
 * Sets up a [Command] to enable or disable Composition tracing.
 *
 * Usage:
 * ```
 * adb shell cmd statusbar composition-tracing [enable|disable]
 * ${ANDROID_BUILD_TOP}/external/perfetto/tools/record_android_trace -c ${ANDROID_BUILD_TOP}/prebuilts/tools/linux-x86_64/perfetto/configs/trace_config_detailed.textproto
 * ```
 */
@SysUISingleton
class ComposeTracingStartable @Inject constructor(private val commandRegistry: CommandRegistry) :
    CoreStartable {
    @OptIn(InternalComposeTracingApi::class)
    override fun start() {
        Log.i(TAG, "Set up Compose tracing command")
        commandRegistry.registerCommand(COMMAND_NAME) { CompositionTracingCommand() }
    }
}

private class CompositionTracingCommand : ParseableCommand(COMMAND_NAME) {
    val enable by subCommand(EnableCommand())
    val disable by subCommand(DisableCommand())

    override fun execute(pw: PrintWriter) {
        if ((enable != null) xor (disable != null)) {
            enable?.execute(pw)
            disable?.execute(pw)
        } else {
            help(pw)
        }
    }
}

private class EnableCommand : ParseableCommand(SUBCOMMAND_ENABLE) {
    override fun execute(pw: PrintWriter) {
        val msg = "Enabled Composition tracing"
        Log.i(TAG, msg)
        pw.println(msg)
        enableCompositionTracing()
    }

    private fun enableCompositionTracing() {
        Composer.setTracer(
            object : CompositionTracer {
                override fun traceEventStart(key: Int, dirty1: Int, dirty2: Int, info: String) {
                    Trace.traceBegin(Trace.TRACE_TAG_APP, info)
                }

                override fun traceEventEnd() = Trace.traceEnd(Trace.TRACE_TAG_APP)

                override fun isTraceInProgress(): Boolean = Trace.isEnabled()
            }
        )
    }
}

private class DisableCommand : ParseableCommand(SUBCOMMAND_DISABLE) {
    override fun execute(pw: PrintWriter) {
        val msg = "Disabled Composition tracing"
        Log.i(TAG, msg)
        pw.println(msg)
        disableCompositionTracing()
    }

    private fun disableCompositionTracing() {
        Composer.setTracer(null)
    }
}
+3 −1
Original line number Diff line number Diff line
@@ -54,6 +54,7 @@ import com.android.systemui.common.ui.data.repository.ConfigurationRepositoryMod
import com.android.systemui.common.usagestats.data.CommonUsageStatsDataLayerModule;
import com.android.systemui.communal.dagger.CommunalModule;
import com.android.systemui.complication.dagger.ComplicationComponent;
import com.android.systemui.compose.ComposeModule;
import com.android.systemui.controls.dagger.ControlsModule;
import com.android.systemui.dagger.qualifiers.Application;
import com.android.systemui.dagger.qualifiers.Main;
@@ -133,6 +134,7 @@ import com.android.systemui.statusbar.notification.collection.inflation.Notifica
import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl;
import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection;
import com.android.systemui.statusbar.notification.collection.render.NotificationVisibilityProvider;
import com.android.systemui.statusbar.notification.headsup.HeadsUpManager;
import com.android.systemui.statusbar.notification.interruption.VisualInterruptionDecisionProvider;
import com.android.systemui.statusbar.notification.people.PeopleHubModule;
import com.android.systemui.statusbar.notification.row.dagger.ExpandableNotificationRowComponent;
@@ -141,7 +143,6 @@ import com.android.systemui.statusbar.phone.CentralSurfaces;
import com.android.systemui.statusbar.phone.ConfigurationControllerModule;
import com.android.systemui.statusbar.phone.LetterboxModule;
import com.android.systemui.statusbar.pipeline.dagger.StatusBarPipelineModule;
import com.android.systemui.statusbar.notification.headsup.HeadsUpManager;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.statusbar.policy.PolicyModule;
import com.android.systemui.statusbar.policy.SensitiveNotificationProtectionController;
@@ -214,6 +215,7 @@ import javax.inject.Named;
        ClockRegistryModule.class,
        CommunalModule.class,
        CommonDataLayerModule.class,
        ComposeModule.class,
        ConfigurationModule.class,
        ConfigurationRepositoryModule.class,
        CommonUsageStatsDataLayerModule.class,