1 /*
2  * Copyright (C) 2011 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.TracesItem;
19 
20 import java.util.List;
21 import java.util.regex.Matcher;
22 import java.util.regex.Pattern;
23 
24 /**
25  * A {@link IParser} to parse Android traces files.
26  * <p>
27  * For now, this only extracts the main stack trace from the first process. It is used to get a
28  * stack from {@code /data/anr/traces.txt} which can be used to give some context about the ANR. If
29  * there is a need, this parser can be expanded to parse all stacks from all processes.
30  */
31 public class TracesParser implements IParser {
32 
33     /**
34      * Matches: ----- pid PID at YYYY-MM-DD hh:mm:ss -----
35      */
36     private static final Pattern PID = Pattern.compile(
37             "^----- pid (\\d+) at \\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2} -----$");
38 
39     /**
40      * Matches: Cmd line: APP
41      */
42     private static final Pattern APP = Pattern.compile("^Cmd ?line: (\\S+).*$");
43 
44     /**
45      * Matches: "main" prio=5 tid=1 STATE
46      */
47     private static final Pattern STACK = Pattern.compile("^\"main\" .*$");
48 
49     /**
50      * {@inheritDoc}
51      *
52      * @return The {@link TracesItem}.
53      */
54     @Override
parse(List<String> lines)55     public TracesItem parse(List<String> lines) {
56         TracesItem traces = new TracesItem();
57         StringBuffer stack = null;
58 
59         for (String line : lines) {
60             if (stack == null) {
61                 Matcher m = PID.matcher(line);
62                 if (m.matches()) {
63                     traces.setPid(Integer.parseInt(m.group(1)));
64                 }
65                 m = APP.matcher(line);
66                 if (m.matches()) {
67                     traces.setApp(m.group(1));
68                 }
69                 m = STACK.matcher(line);
70                 if (m.matches()) {
71                     stack = new StringBuffer();
72                     stack.append(line);
73                     stack.append("\n");
74                 }
75             } else if (!"".equals(line)) {
76                 stack.append(line);
77                 stack.append("\n");
78             } else {
79                 traces.setStack(stack.toString().trim());
80                 return traces;
81             }
82         }
83         if (stack == null) {
84             return null;
85         }
86         traces.setStack(stack.toString().trim());
87         return traces;
88     }
89 
90 }
91