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 parse(List<String> lines)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 */ setup()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 onSwitchParser()142 protected void onSwitchParser() { 143 if (mBatteryStatsDetailedInfoItem == null) { 144 mBatteryStatsDetailedInfoItem = (BatteryStatsDetailedInfoItem) 145 getSection(mBatteryTimeParser); 146 } 147 } 148 149 /** 150 * {@inheritDoc} 151 */ 152 @Override commit()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