1 /* 2 * Copyright (C) 2021 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.util 18 19 import android.os.Trace 20 import android.os.TraceNameSupplier 21 import java.util.concurrent.atomic.AtomicInteger 22 23 /** 24 * Run a block within a [Trace] section. Calls [Trace.beginSection] before and [Trace.endSection] 25 * after the passed block. 26 */ 27 inline fun <T> traceSection(tag: String, block: () -> T): T = 28 if (Trace.isTagEnabled(Trace.TRACE_TAG_APP)) { 29 Trace.traceBegin(Trace.TRACE_TAG_APP, tag) 30 try { 31 block() 32 } finally { 33 Trace.traceEnd(Trace.TRACE_TAG_APP) 34 } 35 } else { 36 block() 37 } 38 39 class TraceUtils { 40 companion object { 41 inline fun traceRunnable(tag: String, crossinline block: () -> Unit): Runnable { 42 return Runnable { traceSection(tag) { block() } } 43 } 44 45 /** 46 * Helper function for creating a Runnable object that implements TraceNameSupplier. 47 * 48 * This is useful for posting Runnables to Handlers with meaningful names. 49 */ 50 inline fun namedRunnable(tag: String, crossinline block: () -> Unit): Runnable { 51 return object : Runnable, TraceNameSupplier { 52 override fun getTraceName(): String = tag 53 override fun run() = block() 54 } 55 } 56 57 /** 58 * Cookie used for async traces. Shouldn't be public, but to use it inside inline methods 59 * there is no other way around. 60 */ 61 val lastCookie = AtomicInteger(0) 62 63 /** 64 * Creates an async slice in a track called "AsyncTraces". 65 * 66 * This can be used to trace coroutine code. Note that all usages of this method will appear 67 * under a single track. 68 */ 69 inline fun <T> traceAsync(method: String, block: () -> T): T = 70 traceAsync("AsyncTraces", method, block) 71 72 /** 73 * Creates an async slice in a track with [trackName] while [block] runs. 74 * 75 * This can be used to trace coroutine code. [method] will be the name of the slice, 76 * [trackName] of the track. The track is one of the rows visible in a perfetto trace inside 77 * SystemUI process. 78 */ 79 inline fun <T> traceAsync(trackName: String, method: String, block: () -> T): T { 80 val cookie = lastCookie.incrementAndGet() 81 Trace.asyncTraceForTrackBegin(Trace.TRACE_TAG_APP, trackName, method, cookie) 82 try { 83 return block() 84 } finally { 85 Trace.asyncTraceForTrackEnd(Trace.TRACE_TAG_APP, trackName, cookie) 86 } 87 } 88 } 89 } 90