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.loganalysis.parser;
18 
19 import com.android.loganalysis.item.BatteryDischargeStatsInfoItem;
20 import com.android.loganalysis.util.NumberFormattingUtil;
21 
22 import java.util.List;
23 import java.util.regex.Matcher;
24 import java.util.regex.Pattern;
25 
26 /**
27  * A {@link IParser} to parse the battery discharge section.
28  */
29 public class BatteryDischargeStatsInfoParser extends AbstractSectionParser {
30 
31     /** Matches; #47: +5m5s105ms to 47 (screen-on, power-save-off, device-idle-off) */
32     private static final Pattern DISCHARGE_STEP_PATTERN =
33             Pattern.compile("^.*: \\+((\\d+)h)?((\\d+)m)?((\\d+)s)?(\\d+)ms.* to (\\d+).*");
34 
35     /**
36      * {@inheritDoc}
37      *
38      * @return The {@link BatteryDischargeStatsInfoItem}.
39      */
40     @Override
parse(List<String> lines)41     public BatteryDischargeStatsInfoItem parse(List<String> lines) {
42         long totalDuration = 0;
43         long projectionDuration = 0;
44         Integer minPercent = null;
45         Integer maxPercent = null;
46         Integer minProjectionPercent = null;
47         Integer maxProjectionPercent = null;
48 
49         for (String line : lines) {
50             Matcher m = DISCHARGE_STEP_PATTERN.matcher(line);
51 
52             if (m.matches()) {
53                 int percent = Integer.parseInt(m.group(8));
54 
55                 if (minPercent == null || percent < minPercent) {
56                     minPercent = percent;
57                 }
58 
59                 if (maxPercent == null || maxPercent < percent) {
60                     maxPercent = percent;
61                 }
62 
63                 long duration = NumberFormattingUtil.getMs(
64                     NumberFormattingUtil.parseIntOrZero(m.group(2)),
65                     NumberFormattingUtil.parseIntOrZero(m.group(4)),
66                     NumberFormattingUtil.parseIntOrZero(m.group(6)),
67                     NumberFormattingUtil.parseIntOrZero(m.group(7)));
68 
69                 totalDuration += duration;
70 
71                 // For computing the projected battery life we drop the first 5% of the battery
72                 // charge because these discharge 'slower' and are not reliable for the projection.
73                 if (percent > 94) {
74                     continue;
75                 }
76 
77                 if (minProjectionPercent == null || percent < minProjectionPercent) {
78                     minProjectionPercent = percent;
79                 }
80 
81                 if (maxProjectionPercent == null || maxProjectionPercent < percent) {
82                     maxProjectionPercent = percent;
83                 }
84 
85                 projectionDuration += duration;
86             }
87         }
88 
89         if (minPercent == null) {
90             return null;
91         }
92 
93         int dischargePercent = maxPercent - minPercent + 1;
94 
95         BatteryDischargeStatsInfoItem item = new BatteryDischargeStatsInfoItem();
96         item.setDischargeDuration(totalDuration);
97         item.setDischargePercentage(dischargePercent);
98         item.setMaxPercentage(maxPercent);
99         item.setMinPercentage(minPercent);
100 
101         if (minProjectionPercent == null) {
102             return item;
103         }
104 
105         int projectionDischargePercent = maxProjectionPercent - minProjectionPercent + 1;
106         item.setProjectedBatteryLife((projectionDuration * 100) / projectionDischargePercent);
107         return item;
108     }
109 }
110