1 /*
<lambda>null2  * 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 package android.tools.traces.parsers.perfetto
18 
19 import android.tools.parsers.AbstractTraceParser
20 import android.tools.traces.wm.WindowManagerState
21 import android.tools.traces.wm.WindowManagerTrace
22 
23 /** Parser for [WindowManagerTrace] objects containing traces */
24 class WindowManagerTraceParser :
25     AbstractTraceParser<
26         TraceProcessorSession,
27         WindowManagerState,
28         WindowManagerState,
29         WindowManagerTrace,
30     >() {
31     override val traceName: String = "WM Trace"
32 
33     override fun doDecodeByteArray(bytes: ByteArray): TraceProcessorSession {
34         error("This parser can only read from perfetto trace processor")
35     }
36 
37     override fun createTrace(entries: Collection<WindowManagerState>): WindowManagerTrace =
38         WindowManagerTrace(entries)
39 
40     override fun getEntries(input: TraceProcessorSession): List<WindowManagerState> {
41         return input.query("INCLUDE PERFETTO MODULE android.winscope.windowmanager;") {
42             val realToElapsedTimeOffsetNs = queryRealToElapsedTimeOffsetNs(input, TABLE_NAME)
43 
44             val traceEntries = mutableListOf<WindowManagerState>()
45             val entryIds = queryEntryIds(input)
46 
47             for (entryId in entryIds) {
48                 val entry =
49                     input.query(getSqlQueryEntry(entryId)) { rows ->
50                         val args = Args.build(rows)
51                         WindowManagerStateBuilder(args, realToElapsedTimeOffsetNs).build()
52                     }
53                 traceEntries.add(entry)
54             }
55 
56             traceEntries
57         }
58     }
59 
60     override fun getTimestamp(entry: WindowManagerState) = entry.timestamp
61 
62     override fun doParseEntry(entry: WindowManagerState) = entry
63 
64     companion object {
65         val TABLE_NAME = "android_windowmanager"
66 
67         private fun queryEntryIds(input: TraceProcessorSession): List<Long> {
68             val sql =
69                 """
70                 SELECT id FROM $TABLE_NAME ORDER BY ts;
71             """
72                     .trimIndent()
73             return input.query(sql) { rows ->
74                 val ids = rows.map { it["id"] as Long }
75                 ids
76             }
77         }
78 
79         private fun getSqlQueryEntry(entryId: Long): String {
80             return """
81                 SELECT
82                     args.key as key,
83                     args.display_value as value,
84                     args.value_type
85                 FROM
86                     $TABLE_NAME as wm
87                 INNER JOIN args ON wm.arg_set_id = args.arg_set_id
88                 WHERE wm.id = $entryId;
89             """
90                 .trimIndent()
91         }
92     }
93 }
94