Home | History | Annotate | Download | only in parser
      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 
     17 package com.android.loganalysis.parser;
     18 
     19 import com.android.loganalysis.item.BatteryStatsDetailedInfoItem;
     20 import com.android.loganalysis.item.BatteryUsageItem;
     21 import com.android.loganalysis.item.InterruptItem;
     22 import com.android.loganalysis.item.ProcessUsageItem;
     23 import com.android.loganalysis.item.WakelockItem;
     24 import com.android.loganalysis.util.NumberFormattingUtil;
     25 
     26 import java.util.List;
     27 import java.util.regex.Matcher;
     28 import java.util.regex.Pattern;
     29 
     30 
     31 /**
     32  * A {@link IParser} to parse the battery stats section of the bugreport
     33  */
     34 public class BatteryStatsDetailedInfoParser extends AbstractSectionParser {
     35 
     36     private static final String BATTERY_USAGE_SECTION_REGEX = "^\\s*Estimated power use \\(mAh\\):$";
     37     private static final String KERNEL_WAKELOCK_SECTION_REGEX = "^\\s*All kernel wake locks:$";
     38     private static final String PARTIAL_WAKELOCK_SECTION_REGEX = "^\\s*All partial wake locks:$";
     39     private static final String INTERRUPT_SECTION_REGEX = "^\\s*All wakeup reasons:$";
     40     private static final String PROCESS_USAGE_SECTION_REGEX = "^\\s*0:$";
     41 
     42     /**
     43      * Matches: Time on battery: 7h 45m 54s 332ms (98.3%) realtime, 4h 40m 51s 315ms (59.3%) uptime
     44      */
     45     private static final Pattern TIME_ON_BATTERY_PATTERN = Pattern.compile(
     46             "^\\s*Time on battery: (?:(\\d+)d)?\\s?(?:(\\d+)h)?\\s?(?:(\\d+)m)?\\s?(?:(\\d+)s)?" +
     47             "\\s?(?:(\\d+)ms)?.*");
     48     /**
     49      * Matches:Time on battery screen off: 1d 4h 6m 16s 46ms (99.1%) realtime, 6h 37m 49s 201ms
     50      */
     51     private static final Pattern SCREEN_OFF_TIME_PATTERN = Pattern.compile("^\\s*Time on battery "
     52         + "screen off: (?:(\\d+)d)?\\s?(?:(\\d+)h)?\\s?(?:(\\d+)m)?\\s?(?:(\\d+)s)?\\s?"
     53         + "(?:(\\d+)ms).*");
     54 
     55     private BatteryUsageParser mBatteryUsageParser = new BatteryUsageParser();
     56     private WakelockParser mWakelockParser = new WakelockParser();
     57     private InterruptParser mInterruptParser = new InterruptParser();
     58     private ProcessUsageParser mProcessUsageParser = new ProcessUsageParser();
     59 
     60     private IParser mBatteryTimeParser = new IParser() {
     61         @Override
     62         public BatteryStatsDetailedInfoItem parse(List<String> lines) {
     63             BatteryStatsDetailedInfoItem detailedInfo = null;
     64             long timeOnBattery = 0, screenOffTime = 0;
     65             Matcher m = null;
     66             for (String line : lines) {
     67                 if (detailedInfo == null && !"".equals(line.trim())) {
     68                     detailedInfo = new BatteryStatsDetailedInfoItem();
     69                 }
     70                 m = TIME_ON_BATTERY_PATTERN.matcher(line);
     71                 if (m.matches()) {
     72                     timeOnBattery = NumberFormattingUtil.getMs(
     73                             NumberFormattingUtil.parseIntOrZero(m.group(1)),
     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                     detailedInfo.setTimeOnBattery(timeOnBattery);
     79                 } else {
     80                     m = SCREEN_OFF_TIME_PATTERN.matcher(line);
     81                     if (m.matches()) {
     82                         screenOffTime = NumberFormattingUtil.getMs(
     83                                 NumberFormattingUtil.parseIntOrZero(m.group(1)),
     84                                 NumberFormattingUtil.parseIntOrZero(m.group(2)),
     85                                 NumberFormattingUtil.parseIntOrZero(m.group(3)),
     86                                 NumberFormattingUtil.parseIntOrZero(m.group(4)),
     87                                 NumberFormattingUtil.parseIntOrZero(m.group(5)));
     88                         detailedInfo.setScreenOnTime(getScreenOnTime(timeOnBattery, screenOffTime));
     89                         return detailedInfo;
     90                     }
     91                 }
     92             }
     93             return detailedInfo;
     94         }
     95 
     96         private long getScreenOnTime(long timeOnBattery, long screenOffTime) {
     97             if (timeOnBattery > screenOffTime) {
     98                 return (timeOnBattery - screenOffTime);
     99             }
    100             return 0;
    101         }
    102     };
    103 
    104     private BatteryStatsDetailedInfoItem mBatteryStatsDetailedInfoItem = null;
    105     private boolean mParsedInput = false;
    106 
    107     /**
    108      * {@inheritDoc}
    109      *
    110      * @return The {@link BatteryStatsDetailedInfoItem}
    111      */
    112     @Override
    113     public BatteryStatsDetailedInfoItem parse(List<String> lines) {
    114         setup();
    115         for (String line : lines) {
    116             if (!mParsedInput && !"".equals(line.trim())) {
    117                 mParsedInput = true;
    118             }
    119             parseLine(line);
    120         }
    121         commit();
    122         return mBatteryStatsDetailedInfoItem;
    123     }
    124 
    125     /**
    126      * Sets up the parser by adding the section parsers.
    127      */
    128     protected void setup() {
    129         setParser(mBatteryTimeParser);
    130         addSectionParser(mBatteryUsageParser, BATTERY_USAGE_SECTION_REGEX);
    131         addSectionParser(mWakelockParser, KERNEL_WAKELOCK_SECTION_REGEX);
    132         addSectionParser(mWakelockParser, PARTIAL_WAKELOCK_SECTION_REGEX);
    133         addSectionParser(mInterruptParser, INTERRUPT_SECTION_REGEX);
    134         addSectionParser(mProcessUsageParser, PROCESS_USAGE_SECTION_REGEX);
    135     }
    136 
    137     /**
    138      * Set the {@link BatteryStatsDetailedInfoItem}
    139      *
    140      */
    141     @Override
    142     protected void onSwitchParser() {
    143         if (mBatteryStatsDetailedInfoItem == null) {
    144             mBatteryStatsDetailedInfoItem = (BatteryStatsDetailedInfoItem)
    145                     getSection(mBatteryTimeParser);
    146         }
    147     }
    148 
    149     /**
    150      * {@inheritDoc}
    151      */
    152     @Override
    153     protected void commit() {
    154         // signal EOF
    155         super.commit();
    156         if (mParsedInput) {
    157             if (mBatteryStatsDetailedInfoItem == null) {
    158                 mBatteryStatsDetailedInfoItem = new BatteryStatsDetailedInfoItem();
    159             }
    160         }
    161 
    162         if (mBatteryStatsDetailedInfoItem != null) {
    163             mBatteryStatsDetailedInfoItem.setBatteryUsageItem(
    164                     (BatteryUsageItem) getSection(mBatteryUsageParser));
    165             mBatteryStatsDetailedInfoItem.setWakelockItem(
    166                     (WakelockItem) getSection(mWakelockParser));
    167             mBatteryStatsDetailedInfoItem.setInterruptItem(
    168                     (InterruptItem) getSection(mInterruptParser));
    169             mBatteryStatsDetailedInfoItem.setProcessUsageItem(
    170                     (ProcessUsageItem) getSection(mProcessUsageParser));
    171         }
    172     }
    173 }
    174