1*795d594fSAndroid Build Coastguard Worker /* 2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2023 The Android Open Source Project 3*795d594fSAndroid Build Coastguard Worker * 4*795d594fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*795d594fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*795d594fSAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*795d594fSAndroid Build Coastguard Worker * 8*795d594fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*795d594fSAndroid Build Coastguard Worker * 10*795d594fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*795d594fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*795d594fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*795d594fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*795d594fSAndroid Build Coastguard Worker * limitations under the License. 15*795d594fSAndroid Build Coastguard Worker */ 16*795d594fSAndroid Build Coastguard Worker 17*795d594fSAndroid Build Coastguard Worker import java.io.File; 18*795d594fSAndroid Build Coastguard Worker import java.io.IOException; 19*795d594fSAndroid Build Coastguard Worker 20*795d594fSAndroid Build Coastguard Worker public class NonStreamTraceParser extends BaseTraceParser { 21*795d594fSAndroid Build Coastguard Worker CheckTraceFileFormat(File file, int expectedVersion, String threadName)22*795d594fSAndroid Build Coastguard Worker public void CheckTraceFileFormat(File file, 23*795d594fSAndroid Build Coastguard Worker int expectedVersion, String threadName) throws Exception { 24*795d594fSAndroid Build Coastguard Worker InitializeParser(file); 25*795d594fSAndroid Build Coastguard Worker 26*795d594fSAndroid Build Coastguard Worker // On non-streaming formats, the file starts with information about options and threads and 27*795d594fSAndroid Build Coastguard Worker // method information. 28*795d594fSAndroid Build Coastguard Worker // Read version string and version. 29*795d594fSAndroid Build Coastguard Worker String line = readLine(); 30*795d594fSAndroid Build Coastguard Worker if (!line.equals("*version")) { 31*795d594fSAndroid Build Coastguard Worker throw new Exception("Trace doesn't start with version. Starts with: " + line); 32*795d594fSAndroid Build Coastguard Worker } 33*795d594fSAndroid Build Coastguard Worker int version = Integer.decode(readLine()); 34*795d594fSAndroid Build Coastguard Worker if (version != expectedVersion) { 35*795d594fSAndroid Build Coastguard Worker throw new Exception("Unexpected version: " + version); 36*795d594fSAndroid Build Coastguard Worker } 37*795d594fSAndroid Build Coastguard Worker 38*795d594fSAndroid Build Coastguard Worker // Record numEntries and ignore next few options that provides some metadata. 39*795d594fSAndroid Build Coastguard Worker line = readLine(); 40*795d594fSAndroid Build Coastguard Worker int numEntries = 0; 41*795d594fSAndroid Build Coastguard Worker while (!line.startsWith(START_SECTION_ID)) { 42*795d594fSAndroid Build Coastguard Worker if (line.startsWith("num-method-calls")) { 43*795d594fSAndroid Build Coastguard Worker String[] tokens = line.split("="); 44*795d594fSAndroid Build Coastguard Worker numEntries = Integer.decode(tokens[1]); 45*795d594fSAndroid Build Coastguard Worker } 46*795d594fSAndroid Build Coastguard Worker line = readLine(); 47*795d594fSAndroid Build Coastguard Worker } 48*795d594fSAndroid Build Coastguard Worker 49*795d594fSAndroid Build Coastguard Worker // This should be threads. 50*795d594fSAndroid Build Coastguard Worker if (!line.equals(THREADS_SECTION_ID)) { 51*795d594fSAndroid Build Coastguard Worker throw new Exception("Missing information about threads " + line); 52*795d594fSAndroid Build Coastguard Worker } 53*795d594fSAndroid Build Coastguard Worker 54*795d594fSAndroid Build Coastguard Worker line = readLine(); 55*795d594fSAndroid Build Coastguard Worker while (!line.startsWith(START_SECTION_ID)) { 56*795d594fSAndroid Build Coastguard Worker String[] threadInfo = line.split("\t", 2); 57*795d594fSAndroid Build Coastguard Worker threadIdMap.put(Integer.decode(threadInfo[0]), threadInfo[1]); 58*795d594fSAndroid Build Coastguard Worker line = readLine(); 59*795d594fSAndroid Build Coastguard Worker } 60*795d594fSAndroid Build Coastguard Worker 61*795d594fSAndroid Build Coastguard Worker // Parse methods 62*795d594fSAndroid Build Coastguard Worker if (!line.equals(METHODS_SECTION_ID)) { 63*795d594fSAndroid Build Coastguard Worker throw new Exception("Missing information about methods " + line); 64*795d594fSAndroid Build Coastguard Worker } 65*795d594fSAndroid Build Coastguard Worker 66*795d594fSAndroid Build Coastguard Worker line = readLine(); 67*795d594fSAndroid Build Coastguard Worker while (!line.startsWith(START_SECTION_ID)) { 68*795d594fSAndroid Build Coastguard Worker String[] methodInfo = line.split("\t", 2); 69*795d594fSAndroid Build Coastguard Worker methodIdMap.put(Integer.decode(methodInfo[0]), methodInfo[1].replace('\t', ' ')); 70*795d594fSAndroid Build Coastguard Worker line = readLine(); 71*795d594fSAndroid Build Coastguard Worker } 72*795d594fSAndroid Build Coastguard Worker 73*795d594fSAndroid Build Coastguard Worker // This should be end 74*795d594fSAndroid Build Coastguard Worker if (!line.equals(END_SECTION_ID)) { 75*795d594fSAndroid Build Coastguard Worker throw new Exception("Missing end after methods " + line); 76*795d594fSAndroid Build Coastguard Worker } 77*795d594fSAndroid Build Coastguard Worker 78*795d594fSAndroid Build Coastguard Worker // Validate the actual data. 79*795d594fSAndroid Build Coastguard Worker validateTraceHeader(expectedVersion); 80*795d594fSAndroid Build Coastguard Worker boolean hasEntries = true; 81*795d594fSAndroid Build Coastguard Worker boolean seenStopTracingMethod = false; 82*795d594fSAndroid Build Coastguard Worker for (int i = 0; i < numEntries; i++) { 83*795d594fSAndroid Build Coastguard Worker int threadId = GetThreadID(); 84*795d594fSAndroid Build Coastguard Worker String eventString = ProcessEventEntry(threadId); 85*795d594fSAndroid Build Coastguard Worker // This is an event from one of the ignored methods. Don't record this entry. 86*795d594fSAndroid Build Coastguard Worker if (eventString == null) { 87*795d594fSAndroid Build Coastguard Worker continue; 88*795d594fSAndroid Build Coastguard Worker } 89*795d594fSAndroid Build Coastguard Worker // Ignore daemons (ex: heap task daemon, reference queue daemon) because they may not 90*795d594fSAndroid Build Coastguard Worker // be deterministic. 91*795d594fSAndroid Build Coastguard Worker if (!ShouldCheckThread(threadId, threadName)) { 92*795d594fSAndroid Build Coastguard Worker continue; 93*795d594fSAndroid Build Coastguard Worker } 94*795d594fSAndroid Build Coastguard Worker // Ignore events after method tracing was stopped. The code that is executed 95*795d594fSAndroid Build Coastguard Worker // later could be non-deterministic. 96*795d594fSAndroid Build Coastguard Worker if (!seenStopTracingMethod) { 97*795d594fSAndroid Build Coastguard Worker UpdateThreadEvents(threadId, eventString); 98*795d594fSAndroid Build Coastguard Worker } 99*795d594fSAndroid Build Coastguard Worker if (eventString.contains("Main$VMDebug $noinline$stopMethodTracing")) { 100*795d594fSAndroid Build Coastguard Worker seenStopTracingMethod = true; 101*795d594fSAndroid Build Coastguard Worker } 102*795d594fSAndroid Build Coastguard Worker } 103*795d594fSAndroid Build Coastguard Worker closeFile(); 104*795d594fSAndroid Build Coastguard Worker 105*795d594fSAndroid Build Coastguard Worker // Printout the events. 106*795d594fSAndroid Build Coastguard Worker for (String str : threadEventsMap.values()) { 107*795d594fSAndroid Build Coastguard Worker System.out.println(str); 108*795d594fSAndroid Build Coastguard Worker } 109*795d594fSAndroid Build Coastguard Worker } 110*795d594fSAndroid Build Coastguard Worker } 111