1 /*
2  * Copyright (C) 2023 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 import java.io.File;
18 import java.io.IOException;
19 
20 public class NonStreamTraceParser extends BaseTraceParser {
21 
CheckTraceFileFormat(File file, int expectedVersion, String threadName)22     public void CheckTraceFileFormat(File file,
23         int expectedVersion, String threadName) throws Exception {
24         InitializeParser(file);
25 
26         // On non-streaming formats, the file starts with information about options and threads and
27         // method information.
28         // Read version string and version.
29         String line = readLine();
30         if (!line.equals("*version")) {
31             throw new Exception("Trace doesn't start with version. Starts with: " + line);
32         }
33         int version = Integer.decode(readLine());
34         if (version != expectedVersion) {
35             throw new Exception("Unexpected version: " + version);
36         }
37 
38         // Record numEntries and ignore next few options that provides some metadata.
39         line = readLine();
40         int numEntries = 0;
41         while (!line.startsWith(START_SECTION_ID)) {
42             if (line.startsWith("num-method-calls")) {
43                 String[] tokens = line.split("=");
44                 numEntries = Integer.decode(tokens[1]);
45             }
46             line = readLine();
47         }
48 
49         // This should be threads.
50         if (!line.equals(THREADS_SECTION_ID)) {
51             throw new Exception("Missing information about threads " + line);
52         }
53 
54         line = readLine();
55         while (!line.startsWith(START_SECTION_ID)) {
56             String[] threadInfo = line.split("\t", 2);
57             threadIdMap.put(Integer.decode(threadInfo[0]), threadInfo[1]);
58             line = readLine();
59         }
60 
61         // Parse methods
62         if (!line.equals(METHODS_SECTION_ID)) {
63             throw new Exception("Missing information about methods " + line);
64         }
65 
66         line = readLine();
67         while (!line.startsWith(START_SECTION_ID)) {
68             String[] methodInfo = line.split("\t", 2);
69             methodIdMap.put(Integer.decode(methodInfo[0]), methodInfo[1].replace('\t', ' '));
70             line = readLine();
71         }
72 
73         // This should be end
74         if (!line.equals(END_SECTION_ID)) {
75             throw new Exception("Missing end after methods " + line);
76         }
77 
78         // Validate the actual data.
79         validateTraceHeader(expectedVersion);
80         boolean hasEntries = true;
81         boolean seenStopTracingMethod = false;
82         for (int i = 0; i < numEntries; i++) {
83             int threadId = GetThreadID();
84             String eventString = ProcessEventEntry(threadId);
85             // Ignore daemons (ex: heap task daemon, reference queue daemon) because they may not
86             // be deterministic.
87             if (!ShouldCheckThread(threadId, threadName)) {
88                 continue;
89             }
90             // Ignore events after method tracing was stopped. The code that is executed
91             // later could be non-deterministic.
92             if (!seenStopTracingMethod) {
93                 UpdateThreadEvents(threadId, eventString);
94             }
95             if (eventString.contains("Main$VMDebug $noinline$stopMethodTracing")) {
96                 seenStopTracingMethod = true;
97             }
98         }
99         closeFile();
100 
101         // Printout the events.
102         for (String str : threadEventsMap.values()) {
103             System.out.println(str);
104         }
105     }
106 }
107