1 /* 2 * Copyright (C) 2016 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.bugreport.anr; 18 19 import com.android.bugreport.cpuinfo.CpuUsageParser; 20 import com.android.bugreport.cpuinfo.CpuUsageSnapshot; 21 import com.android.bugreport.util.Utils; 22 import com.android.bugreport.util.Line; 23 import com.android.bugreport.util.Lines; 24 import com.android.bugreport.stacks.ProcessSnapshot; 25 import com.android.bugreport.stacks.ProcessSnapshotParser; 26 import com.android.bugreport.stacks.VmTraces; 27 28 import java.io.BufferedReader; 29 import java.io.IOException; 30 import java.util.ArrayList; 31 import java.util.regex.Pattern; 32 import java.util.regex.Matcher; 33 34 /** 35 * Parse an anr block from a monkey log. 36 * 37 * The parser can be reused, but is not thread safe. 38 */ 39 public class AnrParser { 40 private static final Pattern PROC_NAME_RE 41 = Pattern.compile("ANR in (\\S+) \\((\\S+)/(\\S+)\\)"); 42 private static final Pattern PID_RE 43 = Pattern.compile("PID: (\\d+)"); 44 private static final Pattern REASON_RE 45 = Pattern.compile("Reason: (.*)"); 46 private static final Pattern BLANK_RE 47 = Pattern.compile("\\s+"); 48 49 /** 50 * Construct a new parser. 51 */ 52 public AnrParser() { 53 } 54 55 /** 56 * Do the parsing. 57 */ 58 public ArrayList<Anr> parse(Lines<? extends Line> lines, boolean tryTraces) { 59 final ArrayList<Anr> results = new ArrayList<Anr>(); 60 Anr anr = null; 61 62 final Matcher procNameRe = PROC_NAME_RE.matcher(""); 63 final Matcher pidRe = PID_RE.matcher(""); 64 final Matcher reasonRe = REASON_RE.matcher(""); 65 final Matcher cpuUsageRe = CpuUsageParser.CPU_USAGE_RE.matcher(""); 66 final Matcher beginProcessRe = ProcessSnapshotParser.BEGIN_PROCESS_RE.matcher(""); 67 68 while (lines.hasNext()) { 69 final Line line = lines.next(); 70 final String text = line.text; 71 if (Utils.matches(procNameRe, text)) { 72 anr = new Anr(); 73 anr.vmTraces = new VmTraces(); 74 results.add(anr); 75 anr.processName = procNameRe.group(1); 76 anr.componentPackage = procNameRe.group(2); 77 anr.componentClass = procNameRe.group(3); 78 } else if (Utils.matches(pidRe, text)) { 79 if (anr != null) { 80 anr.pid = Integer.parseInt(pidRe.group(1)); 81 } 82 } else if (Utils.matches(reasonRe, text)) { 83 if (anr != null) { 84 anr.reason = reasonRe.group(1); 85 } 86 } else if (Utils.matches(cpuUsageRe, text)) { 87 if (anr != null) { 88 lines.rewind(); 89 CpuUsageParser parser = new CpuUsageParser(); 90 final CpuUsageSnapshot snapshot = parser.parse(lines); 91 if (snapshot != null) { 92 anr.cpuUsages.add(snapshot); 93 } else { 94 // TODO: Try to backtrack and correct the parsing. 95 } 96 } 97 } else if (Utils.matches(beginProcessRe, text)) { 98 if (tryTraces && anr != null) { 99 lines.rewind(); 100 ProcessSnapshotParser parser = new ProcessSnapshotParser(); 101 final ProcessSnapshot snapshot = parser.parse(lines); 102 if (snapshot != null) { 103 anr.vmTraces.processes.add(snapshot); 104 } else { 105 // TODO: Try to backtrack and correct the parsing. 106 } 107 } 108 } else { 109 // Unknown 110 // 111 // TODO: These lines: 112 // Load: 16.37 / 7.19 / 2.73 113 // procrank: 114 if (false) { 115 System.out.println("AnrParser Dropping: " + text); 116 } 117 } 118 } 119 120 if (false) { 121 for (Anr item: results) { 122 System.out.println("ANR"); 123 System.out.println(" processName=" + item.processName); 124 System.out.println(" componentPackage=" + item.componentPackage); 125 System.out.println(" componentClass=" + item.componentClass); 126 System.out.println(" pid=" + item.pid); 127 System.out.println(" reason=" + item.reason); 128 } 129 } 130 131 return results; 132 } 133 134 } 135 136