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.WakelockItem; 19 import com.android.loganalysis.item.WakelockItem.WakeLockCategory; 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 handle the parsing of wakelock information 28 */ 29 public class WakelockParser implements IParser { 30 31 private static final String WAKE_LOCK_PAT_SUFFIX = 32 "(?:(\\d+)d)?\\s?(?:(\\d+)h)?\\s?(?:(\\d+)m)?\\s?(?:(\\d+)s)?\\s?(?:(\\d+)ms)?" 33 + "\\s?\\((\\d+) times\\)(?: max=\\d+)? realtime"; 34 35 /** 36 * Match a valid line such as: 37 * " Kernel Wake lock PowerManagerService.WakeLocks: 1h 13m 50s 950ms (2858 times) realtime" 38 */ 39 private static final Pattern KERNEL_WAKE_LOCK_PAT = Pattern.compile( 40 "^\\s*Kernel Wake lock (.+): " + WAKE_LOCK_PAT_SUFFIX); 41 /** 42 * Match a valid line such as: 43 * " Wake lock u0a7 NlpWakeLock: 8m 13s 203ms (1479 times) realtime"; 44 */ 45 private static final Pattern PARTIAL_WAKE_LOCK_PAT = Pattern.compile( 46 "^\\s*Wake lock (.*)\\s(.+): " + WAKE_LOCK_PAT_SUFFIX); 47 48 private WakelockItem mItem = new WakelockItem(); 49 50 public static final int TOP_WAKELOCK_COUNT = 5; 51 52 /** 53 * {@inheritDoc} 54 */ 55 @Override parse(List<String> lines)56 public WakelockItem parse(List<String> lines) { 57 Matcher m = null; 58 int wakelockCounter = 0; 59 for (String line : lines) { 60 if (wakelockCounter >= TOP_WAKELOCK_COUNT || "".equals(line.trim())) { 61 // Done with wakelock parsing 62 break; 63 } 64 65 m = KERNEL_WAKE_LOCK_PAT.matcher(line); 66 if (m.matches() && !line.contains("PowerManagerService.WakeLocks")) { 67 parseKernelWakeLock(line, WakeLockCategory.KERNEL_WAKELOCK); 68 wakelockCounter++; 69 continue; 70 } 71 72 m = PARTIAL_WAKE_LOCK_PAT.matcher(line); 73 if (m.matches()) { 74 parsePartialWakeLock(line, WakeLockCategory.PARTIAL_WAKELOCK); 75 wakelockCounter++; 76 } 77 } 78 79 return mItem; 80 } 81 82 /** 83 * Parse a line of output and add it to wakelock section 84 * <p> 85 * Exposed for unit testing. 86 * </p> 87 */ parseKernelWakeLock(String line, WakeLockCategory category)88 void parseKernelWakeLock(String line, WakeLockCategory category) { 89 Matcher m = KERNEL_WAKE_LOCK_PAT.matcher(line); 90 if (!m.matches()) { 91 return; 92 } 93 final String name = m.group(1); 94 final long wakelockTime = NumberFormattingUtil.getMs( 95 NumberFormattingUtil.parseIntOrZero(m.group(2)), 96 NumberFormattingUtil.parseIntOrZero(m.group(3)), 97 NumberFormattingUtil.parseIntOrZero(m.group(4)), 98 NumberFormattingUtil.parseIntOrZero(m.group(5)), 99 NumberFormattingUtil.parseIntOrZero(m.group(6))); 100 101 final int timesCalled = Integer.parseInt(m.group(7)); 102 103 mItem.addWakeLock(name, wakelockTime, timesCalled, category); 104 } 105 106 /** 107 * Parse a line of output and add it to wake lock section. 108 * <p> 109 * Exposed for unit testing. 110 * </p> 111 */ parsePartialWakeLock(String line, WakeLockCategory category)112 void parsePartialWakeLock(String line, WakeLockCategory category) { 113 Matcher m = PARTIAL_WAKE_LOCK_PAT.matcher(line); 114 if (!m.matches()) { 115 return; 116 } 117 final String processUID = m.group(1); 118 final String name = m.group(2); 119 final long wakelockTime = NumberFormattingUtil.getMs( 120 NumberFormattingUtil.parseIntOrZero(m.group(3)), 121 NumberFormattingUtil.parseIntOrZero(m.group(4)), 122 NumberFormattingUtil.parseIntOrZero(m.group(5)), 123 NumberFormattingUtil.parseIntOrZero(m.group(6)), 124 NumberFormattingUtil.parseIntOrZero(m.group(7))); 125 final int timesCalled = Integer.parseInt(m.group(8)); 126 127 mItem.addWakeLock(name, processUID, wakelockTime, timesCalled, category); 128 } 129 130 /** 131 * Get the {@link WakelockItem}. 132 * <p> 133 * Exposed for unit testing. 134 * </p> 135 */ getItem()136 WakelockItem getItem() { 137 return mItem; 138 } 139 } 140