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