1 /* 2 * Copyright (C) 2012 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 package com.android.loganalysis.parser; 17 18 import com.android.loganalysis.item.AnrItem; 19 20 import java.util.List; 21 import java.util.regex.Matcher; 22 import java.util.regex.Pattern; 23 24 /** 25 * An {@link IParser} to handle ANRs. 26 */ 27 public class AnrParser implements IParser { 28 /** 29 * Matches: ANR (application not responding) in process: app 30 * Matches: ANR in app 31 * Matches: ANR in app (class/package) 32 */ 33 public static final Pattern START = Pattern.compile( 34 "^ANR (?:\\(application not responding\\) )?in (?:process: )?(\\S+).*$"); 35 /** 36 * Matches: PID: 1234 37 */ 38 private static final Pattern PID = Pattern.compile("^PID: (\\d+)$"); 39 /** 40 * Matches: Reason: reason 41 */ 42 private static final Pattern REASON = Pattern.compile("^Reason: (.*)$"); 43 /** 44 * Matches: Load: 0.71 / 0.83 / 0.51 45 */ 46 private static final Pattern LOAD = Pattern.compile( 47 "^Load: (\\d+\\.\\d+) / (\\d+\\.\\d+) / (\\d+\\.\\d+)$"); 48 49 /** 50 * Matches: 33% TOTAL: 21% user + 11% kernel + 0.3% iowait 51 */ 52 private static final Pattern TOTAL = Pattern.compile("^(\\d+(\\.\\d+)?)% TOTAL: .*$"); 53 private static final Pattern USER = Pattern.compile("^.* (\\d+(\\.\\d+)?)% user.*$"); 54 private static final Pattern KERNEL = Pattern.compile("^.* (\\d+(\\.\\d+)?)% kernel.*$"); 55 private static final Pattern IOWAIT = Pattern.compile("^.* (\\d+(\\.\\d+)?)% iowait.*$"); 56 57 /** 58 * {@inheritDoc} 59 * 60 * @return The {@link AnrItem}. 61 */ 62 @Override parse(List<String> lines)63 public AnrItem parse(List<String> lines) { 64 AnrItem anr = null; 65 StringBuilder stack = new StringBuilder(); 66 boolean matchedTotal = false; 67 68 for (String line : lines) { 69 Matcher m = START.matcher(line); 70 // Ignore all input until the start pattern is matched. 71 if (m.matches()) { 72 anr = new AnrItem(); 73 anr.setApp(m.group(1)); 74 } 75 76 if (anr != null) { 77 m = PID.matcher(line); 78 if (m.matches()) { 79 anr.setPid(Integer.valueOf(m.group(1))); 80 } 81 m = REASON.matcher(line); 82 if (m.matches()) { 83 anr.setReason(m.group(1)); 84 } 85 86 m = LOAD.matcher(line); 87 if (m.matches()) { 88 anr.setLoad(AnrItem.LoadCategory.LOAD_1, Double.parseDouble(m.group(1))); 89 anr.setLoad(AnrItem.LoadCategory.LOAD_5, Double.parseDouble(m.group(2))); 90 anr.setLoad(AnrItem.LoadCategory.LOAD_15, Double.parseDouble(m.group(3))); 91 } 92 93 m = TOTAL.matcher(line); 94 if (!matchedTotal && m.matches()) { 95 matchedTotal = true; 96 anr.setCpuUsage(AnrItem.CpuUsageCategory.TOTAL, Double.parseDouble(m.group(1))); 97 98 m = USER.matcher(line); 99 Double usage = m.matches() ? Double.parseDouble(m.group(1)) : 0.0; 100 anr.setCpuUsage(AnrItem.CpuUsageCategory.USER, usage); 101 102 m = KERNEL.matcher(line); 103 usage = m.matches() ? Double.parseDouble(m.group(1)) : 0.0; 104 anr.setCpuUsage(AnrItem.CpuUsageCategory.KERNEL, usage); 105 106 m = IOWAIT.matcher(line); 107 usage = m.matches() ? Double.parseDouble(m.group(1)) : 0.0; 108 anr.setCpuUsage(AnrItem.CpuUsageCategory.IOWAIT, usage); 109 } 110 111 stack.append(line); 112 stack.append("\n"); 113 } 114 } 115 116 if (anr != null) { 117 anr.setStack(stack.toString().trim()); 118 } 119 return anr; 120 } 121 } 122 123