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.monkey; 18 19 import com.android.bugreport.anr.Anr; 20 import com.android.bugreport.anr.AnrParser; 21 import com.android.bugreport.bugreport.Bugreport; 22 import com.android.bugreport.util.Line; 23 import com.android.bugreport.util.Lines; 24 import com.android.bugreport.util.Utils; 25 26 import java.io.BufferedReader; 27 import java.io.IOException; 28 import java.util.ArrayList; 29 import java.util.regex.Pattern; 30 import java.util.regex.Matcher; 31 32 /** 33 * Parser for a monkey log file. 34 */ 35 public class MonkeyLogParser { 36 private static final Pattern NOT_RESPONDING_RE 37 = Pattern.compile("// NOT RESPONDING: \\S+ \\(pid \\d+\\)"); 38 private static final Pattern ABORTED_RE 39 = Pattern.compile("\\*\\* Monkey aborted due to error\\."); 40 41 public MonkeyLogParser() { 42 } 43 44 /** 45 * Parses the monkey file, adding in what's there into an already 46 * created bugreport. 47 */ 48 public void parse(Bugreport bugreport, Lines<? extends Line> in) throws IOException { 49 // Get the lines 50 final Lines<Line> lines = extractAnrLines(in); 51 if (!lines.hasNext()) { 52 return; 53 } 54 55 final Line line = lines.next(); 56 final String text = line.text; 57 58 // ANRs 59 final Matcher anrStart = NOT_RESPONDING_RE.matcher(text); 60 if (Utils.matches(anrStart, text)) { 61 final AnrParser anrParser = new AnrParser(); 62 final ArrayList<Anr> anrs = anrParser.parse(lines, true); 63 if (anrs.size() >= 1) { 64 // Pick the first one. 65 bugreport.anr = bugreport.monkeyAnr = anrs.get(0); 66 } 67 } 68 } 69 70 /** 71 * Pull out the ANR lines from a monkey log. 72 */ 73 private static Lines<Line> extractAnrLines(Lines<? extends Line> lines) throws IOException { 74 final int STATE_INITIAL = 0; 75 final int STATE_ANR = 1; 76 final int STATE_DONE = 2; 77 78 ArrayList<Line> list = new ArrayList<Line>(); 79 80 final Matcher anrStart = NOT_RESPONDING_RE.matcher(""); 81 final Matcher monkeyEnd = ABORTED_RE.matcher(""); 82 83 int state = STATE_INITIAL; 84 int lineno = 0; 85 while (state != STATE_DONE && lines.hasNext()) { 86 final Line line = lines.next(); 87 lineno++; 88 switch (state) { 89 case STATE_INITIAL: 90 anrStart.reset(line.text); 91 if (anrStart.matches()) { 92 state = STATE_ANR; 93 list.add(new Line(lineno, line.text)); 94 } 95 break; 96 case STATE_ANR: 97 monkeyEnd.reset(line.text); 98 if (monkeyEnd.matches()) { 99 state = STATE_DONE; 100 } else { 101 list.add(new Line(lineno, line.text)); 102 } 103 break; 104 default: 105 break; 106 } 107 } 108 109 return new Lines<Line>(list); 110 } 111 } 112