1 /*
2  * Copyright (C) 2015 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.ProcessUsageItem;
19 import com.android.loganalysis.item.ProcessUsageItem.SensorInfoItem;
20 import com.android.loganalysis.util.NumberFormattingUtil;
21 
22 import java.util.LinkedList;
23 import java.util.List;
24 import java.util.regex.Matcher;
25 import java.util.regex.Pattern;
26 
27 /**
28  * A {@link IParser} to handle the parsing of process usage information
29  */
30 public class ProcessUsageParser implements IParser {
31 
32     private ProcessUsageItem mItem = new ProcessUsageItem();
33     private LinkedList<SensorInfoItem> mSensorUsage = new LinkedList<SensorInfoItem>();
34 
35     /**
36      * Matches: 1000:
37      */
38     private static final Pattern UID_PATTERN = Pattern.compile("^\\s*(\\w+):$");
39 
40     /**
41      * Matches: Sensor 1: 12m 52s 311ms realtime (29 times)
42      */
43     private static final Pattern SENSOR_PATTERN = Pattern.compile(
44             "^\\s*Sensor (\\d+): (?:(\\d+)d\\s)?"
45             + "(?:(\\d+)h\\s)?(?:(\\d+)m\\s)?(?:(\\d+)s\\s)?(\\d+)ms "
46             + "realtime \\((\\d+) times\\)$");
47 
48     /**
49      * Matches: 507 wakeup alarms
50      */
51     private static final Pattern ALARM_PATTERN = Pattern.compile("^\\s*(\\d+) wakeup alarms$");
52 
53     /**
54      * {@inheritDoc}
55      */
56     @Override
parse(List<String> lines)57     public ProcessUsageItem parse(List<String> lines) {
58         String processUid = null;
59         int alarmWakeups = 0;
60         for (String line : lines) {
61             Matcher m = UID_PATTERN.matcher(line);
62             if (m.matches()) {
63                 if (processUid != null) {
64                     // Save the process usage info for the previous process
65                     mItem.addProcessUsage(processUid, alarmWakeups, mSensorUsage);
66                 }
67                 processUid = m.group(1);
68                 mSensorUsage = new LinkedList<SensorInfoItem>();
69                 continue;
70             }
71             m = SENSOR_PATTERN.matcher(line);
72             if (m.matches()) {
73                 final long duration = NumberFormattingUtil.getMs(
74                         NumberFormattingUtil.parseIntOrZero(m.group(2)),
75                         NumberFormattingUtil.parseIntOrZero(m.group(3)),
76                         NumberFormattingUtil.parseIntOrZero(m.group(4)),
77                         NumberFormattingUtil.parseIntOrZero(m.group(5)),
78                         NumberFormattingUtil.parseIntOrZero(m.group(6)));
79                 mSensorUsage.add(new SensorInfoItem(m.group(1), duration));
80                 continue;
81             }
82             m = ALARM_PATTERN.matcher(line);
83             if (m.matches()) {
84                 alarmWakeups = Integer.parseInt(m.group(1));
85             }
86         }
87         // Add the last process usage stats to the list
88         if (processUid != null) {
89             // Save the process usage info for the previous process
90             mItem.addProcessUsage(processUid, alarmWakeups, mSensorUsage);
91         }
92 
93         return mItem;
94     }
95 
96     /**
97      * Get the {@link ProcessUsageItem}.
98      * <p>
99      * Exposed for unit testing.
100      * </p>
101      */
getItem()102     ProcessUsageItem getItem() {
103         return mItem;
104     }
105 }
106