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 */
traceSectionnull27 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 {
traceRunnablenull41 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 */
namedRunnablenull50 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 */
traceAsyncnull69 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