diff options
author | Avinankumar Vellore Suriyakumar <avellore@google.com> | 2016-01-13 18:52:59 -0800 |
---|---|---|
committer | Avinankumar Vellore Suriyakumar <avellore@google.com> | 2016-01-19 17:19:13 -0800 |
commit | b9b98773204a467f7a6100ff62a33fbb00c9eaf3 (patch) | |
tree | d1cc6f54fc6c860cc80680a901ed4cf58a90f6d9 | |
parent | a81b9db05d513c1284aed2a2802a193f2ec88b60 (diff) | |
download | loganalysis-b9b98773204a467f7a6100ff62a33fbb00c9eaf3.tar.gz |
Add more information to analysis
Added more information to analysis. Also added rule for Interrupts
Change-Id: I090ec531d170693a3a96047a02c3b057cfb80bb4
13 files changed, 741 insertions, 60 deletions
diff --git a/src/com/android/loganalysis/item/InterruptItem.java b/src/com/android/loganalysis/item/InterruptItem.java index 1169004..4ff7662 100644 --- a/src/com/android/loganalysis/item/InterruptItem.java +++ b/src/com/android/loganalysis/item/InterruptItem.java @@ -125,6 +125,13 @@ public class InterruptItem implements IItem { } /** + * Get a list of {@link InterruptInfoItem} objects + */ + public List<InterruptInfoItem> getInterrupts() { + return (List<InterruptInfoItem>) mInterrupts; + } + + /** * {@inheritDoc} */ @Override diff --git a/src/com/android/loganalysis/parser/InterruptParser.java b/src/com/android/loganalysis/parser/InterruptParser.java index 26417c4..27ccc4c 100644 --- a/src/com/android/loganalysis/parser/InterruptParser.java +++ b/src/com/android/loganalysis/parser/InterruptParser.java @@ -70,7 +70,7 @@ public class InterruptParser implements IParser { } private InterruptCategory getInterruptCategory(String interruptName) { - if (interruptName.contains("bcmsdh_sdmmc")) { + if (interruptName.contains("bcmsdh_sdmmc") || interruptName.contains("msm_pcie_wake")) { return InterruptCategory.WIFI_INTERRUPT; } else if (interruptName.contains("smd-modem") || interruptName.contains("smsm-modem")) { diff --git a/src/com/android/loganalysis/rule/InterruptRule.java b/src/com/android/loganalysis/rule/InterruptRule.java new file mode 100644 index 0000000..ab8e678 --- /dev/null +++ b/src/com/android/loganalysis/rule/InterruptRule.java @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.loganalysis.rule; + +import com.android.loganalysis.item.BugreportItem; +import com.android.loganalysis.item.InterruptItem; +import com.android.loganalysis.item.InterruptItem.InterruptInfoItem; +import com.android.loganalysis.item.InterruptItem.InterruptCategory; + +import java.util.concurrent.TimeUnit; +import java.util.ArrayList; +import java.util.List; + +import org.json.JSONException; +import org.json.JSONObject; + +/** + * Rules definition for Interrupt rule + */ +public class InterruptRule extends AbstractPowerRule { + + private static final String INTERRUPT_ANALYSIS = "INTERRUPT_ANALYSIS"; + private static final long INTERRUPT_THRESHOLD_MS = 120000; + + private List<InterruptInfoItem> mOffendingInterruptsList; + + public InterruptRule (BugreportItem bugreportItem) { + super(bugreportItem); + } + + @Override + public void applyRule() { + mOffendingInterruptsList = new ArrayList<InterruptInfoItem>(); + InterruptItem interruptItem = getDetailedAnalysisItem().getInterruptItem(); + if (interruptItem == null || getTimeOnBattery() < 0) { + return; + } + for (InterruptInfoItem interrupts : interruptItem.getInterrupts()) { + final long interruptsPerMs = getTimeOnBattery()/interrupts.getInterruptCount(); + if (interruptsPerMs < INTERRUPT_THRESHOLD_MS) { + mOffendingInterruptsList.add(interrupts); + } + } + } + + @Override + public JSONObject getAnalysis() { + JSONObject interruptAnalysis = new JSONObject(); + StringBuilder analysis = new StringBuilder(); + if (mOffendingInterruptsList == null || mOffendingInterruptsList.size() <= 0) { + analysis.append(String.format( + "No interrupts woke up device more frequent than %d secs.", + TimeUnit.MILLISECONDS.toSeconds(INTERRUPT_THRESHOLD_MS))); + } else { + for (InterruptInfoItem interrupts : mOffendingInterruptsList) { + if (interrupts.getCategory() != InterruptCategory.UNKNOWN_INTERRUPT) { + analysis.append(String.format("Frequent interrupts from %s (%s). ", + interrupts.getCategory(), + interrupts.getName())); + } else { + analysis.append(String.format("Frequent interrupts from %s. ", + interrupts.getName())); + } + } + } + try { + interruptAnalysis.put(INTERRUPT_ANALYSIS, analysis.toString().trim()); + } catch (JSONException e) { + // do nothing + } + return interruptAnalysis; + } +} diff --git a/src/com/android/loganalysis/rule/LocationUsageRule.java b/src/com/android/loganalysis/rule/LocationUsageRule.java index 71defa2..ad208aa 100644 --- a/src/com/android/loganalysis/rule/LocationUsageRule.java +++ b/src/com/android/loganalysis/rule/LocationUsageRule.java @@ -21,13 +21,15 @@ import com.android.loganalysis.item.LocationDumpsItem; import com.android.loganalysis.item.LocationDumpsItem.LocationInfoItem; import java.util.concurrent.TimeUnit; +import java.util.ArrayList; +import java.util.List; import org.json.JSONException; import org.json.JSONObject; /** - * Rules definition for Process usage + * Rules definition for Location usage */ public class LocationUsageRule extends AbstractPowerRule { @@ -36,48 +38,58 @@ public class LocationUsageRule extends AbstractPowerRule { // GSA requests for location every 285 seconds, anything more frequent is an issue private static final int LOCATION_INTERVAL_THRESHOLD = 285; - private StringBuffer mAnalysisBuffer; - - private BugreportItem mBugreportItem = null; + private List<LocationInfoItem> mOffendingLocationRequestList; + private BugreportItem mBugreportItem; public LocationUsageRule (BugreportItem bugreportItem) { super(bugreportItem); mBugreportItem = bugreportItem; } - @Override public void applyRule() { - mAnalysisBuffer = new StringBuffer(); + mOffendingLocationRequestList = new ArrayList<LocationInfoItem>(); + if (mBugreportItem.getActivityService() == null || getTimeOnBattery() <= 0) { + return; + } LocationDumpsItem locationDumpsItem = mBugreportItem.getActivityService() .getLocationDumps(); + if (locationDumpsItem == null) { + return; + } final long locationRequestThresholdMs = (long) (getTimeOnBattery() * LOCATION_REQUEST_DURATION_THRESHOLD); - if (locationDumpsItem != null) { - for (LocationInfoItem locationClient : locationDumpsItem.getLocationClients()) { - final String packageName = locationClient.getPackage(); - final String priority = locationClient.getPriority(); - final int effectiveIntervalSec = locationClient.getEffectiveInterval(); - if (effectiveIntervalSec < LOCATION_INTERVAL_THRESHOLD && - !priority.equals("PRIORITY_NO_POWER") && - (TimeUnit.MINUTES.toMillis(locationClient.getDuration()) > - locationRequestThresholdMs)) { - mAnalysisBuffer.append(String.format("Package %s is requesting for location " - + "updates every %d secs with priority %s", packageName, - effectiveIntervalSec, priority)); - } + + for (LocationInfoItem locationClient : locationDumpsItem.getLocationClients()) { + final String priority = locationClient.getPriority(); + final int effectiveIntervalSec = locationClient.getEffectiveInterval(); + if (effectiveIntervalSec < LOCATION_INTERVAL_THRESHOLD && + !priority.equals("PRIORITY_NO_POWER") && + (TimeUnit.MINUTES.toMillis(locationClient.getDuration()) > + locationRequestThresholdMs)) { + mOffendingLocationRequestList.add(locationClient); } } } @Override public JSONObject getAnalysis() { - JSONObject usageAnalysis = new JSONObject(); + JSONObject locationAnalysis = new JSONObject(); + StringBuilder analysis = new StringBuilder(); + if (mOffendingLocationRequestList == null || mOffendingLocationRequestList.size() <= 0) { + analysis.append("No apps requested for frequent location updates. "); + } else { + for (LocationInfoItem locationClient : mOffendingLocationRequestList) { + analysis.append(String.format("Package %s is requesting for location " + +"updates every %d secs with priority %s.", locationClient.getPackage(), + locationClient.getEffectiveInterval(), locationClient.getPriority())); + } + } try { - usageAnalysis.put(LOCATION_USAGE_ANALYSIS, mAnalysisBuffer.toString()); + locationAnalysis.put(LOCATION_USAGE_ANALYSIS, analysis.toString().trim()); } catch (JSONException e) { // do nothing } - return usageAnalysis; + return locationAnalysis; } } diff --git a/src/com/android/loganalysis/rule/ProcessUsageRule.java b/src/com/android/loganalysis/rule/ProcessUsageRule.java index 4e15aee..876bdd1 100644 --- a/src/com/android/loganalysis/rule/ProcessUsageRule.java +++ b/src/com/android/loganalysis/rule/ProcessUsageRule.java @@ -17,9 +17,14 @@ package com.android.loganalysis.rule; import com.android.loganalysis.item.BugreportItem; -import com.android.loganalysis.item.DumpsysProcStatsItem; import com.android.loganalysis.item.ProcessUsageItem; import com.android.loganalysis.item.ProcessUsageItem.ProcessUsageInfoItem; +import com.android.loganalysis.item.ProcessUsageItem.SensorInfoItem; + +import com.android.loganalysis.util.NumberFormattingUtil; + +import java.util.ArrayList; +import java.util.List; import org.json.JSONException; import org.json.JSONObject; @@ -30,10 +35,13 @@ import org.json.JSONObject; */ public class ProcessUsageRule extends AbstractPowerRule { - private static final String PROCESS_USAGE_ANALYSIS = "PROCESS_USAGE_ANALYSIS"; + private static final String ALARM_USAGE_ANALYSIS = "ALARM_USAGE_ANALYSIS"; + private static final String SENSOR_USAGE_ANALYSIS = "SENSOR_USAGE_ANALYSIS"; private static final long ALARM_THRESHOLD = 60000; + private static final float SENSOR_ACTIVE_TIME_THRESHOLD_PERCENTAGE = 0.1f; // 10% - private StringBuffer mAnalysisBuffer; + private List<ProcessUsageInfoItem> mOffendingAlarmList; + private List<ProcessUsageInfoItem> mOffendingSensorList; public ProcessUsageRule (BugreportItem bugreportItem) { super(bugreportItem); @@ -42,34 +50,70 @@ public class ProcessUsageRule extends AbstractPowerRule { @Override public void applyRule() { - mAnalysisBuffer = new StringBuffer(); + mOffendingAlarmList = new ArrayList<ProcessUsageInfoItem>(); + mOffendingSensorList = new ArrayList<ProcessUsageInfoItem>(); + ProcessUsageItem processUsageItem = getDetailedAnalysisItem().getProcessUsageItem(); - DumpsysProcStatsItem procStatsItem = getProcStatsItem(); - if (processUsageItem != null && procStatsItem!= null) { + if (processUsageItem != null && getTimeOnBattery() > 0) { for (ProcessUsageInfoItem usage : processUsageItem.getProcessUsage()) { if (usage.getAlarmWakeups() > 0) { - final long alarmsPerMs = getTimeOnBattery()/usage.getAlarmWakeups(); - if (alarmsPerMs < ALARM_THRESHOLD) { - final String processName = procStatsItem.get(usage.getProcessUID()); - if (processName != null) { - mAnalysisBuffer.append(processName); - } else { - mAnalysisBuffer.append(usage.getProcessUID()); - } - mAnalysisBuffer.append(" has requested frequent repeating alarms"); - } + addAlarmAnalysis(usage); + } + if (usage.getSensorUsage() != null && usage.getSensorUsage().size() > 0) { + addSensorAnalysis(usage); } } } } + private void addAlarmAnalysis(ProcessUsageInfoItem usage) { + final long alarmsPerMs = getTimeOnBattery()/usage.getAlarmWakeups(); + if (alarmsPerMs < ALARM_THRESHOLD) { + mOffendingAlarmList.add(usage); + } + } + + private void addSensorAnalysis(ProcessUsageInfoItem usage) { + final long sensorUsageThresholdMs = (long) (getTimeOnBattery() + * SENSOR_ACTIVE_TIME_THRESHOLD_PERCENTAGE); + for (SensorInfoItem sensorInfo : usage.getSensorUsage()) { + if (sensorInfo.getUsageDurationMs() > sensorUsageThresholdMs) { + mOffendingSensorList.add(usage); + } + } + } + @Override public JSONObject getAnalysis() { JSONObject usageAnalysis = new JSONObject(); + StringBuilder alarmAnalysis = new StringBuilder(); + if (mOffendingAlarmList == null || mOffendingAlarmList.size() <= 0) { + alarmAnalysis.append("No apps requested for alarms more frequent than 60 secs."); + } else { + for (ProcessUsageInfoItem alarmInfo : mOffendingAlarmList) { + alarmAnalysis.append(String.format( + "UID %s has requested frequent repeating alarms. ", + alarmInfo.getProcessUID())); + } + } + StringBuilder sensorAnalysis = new StringBuilder(); + if (mOffendingSensorList == null || mOffendingSensorList.size() <= 0) { + sensorAnalysis.append("No apps used sensors more than 10% time on battery."); + } else { + for (ProcessUsageInfoItem sensorInfo : mOffendingSensorList) { + for (SensorInfoItem sensors : sensorInfo.getSensorUsage()) { + sensorAnalysis.append(String.format("sensor %s was used for %s by UID %s. ", + sensors.getSensorName(), + NumberFormattingUtil.getDuration(sensors.getUsageDurationMs()), + sensorInfo.getProcessUID())); + } + } + } try { - usageAnalysis.put(PROCESS_USAGE_ANALYSIS, mAnalysisBuffer.toString()); + usageAnalysis.put(ALARM_USAGE_ANALYSIS, alarmAnalysis.toString().trim()); + usageAnalysis.put(SENSOR_USAGE_ANALYSIS, sensorAnalysis.toString().trim()); } catch (JSONException e) { - // do nothing + // do nothing } return usageAnalysis; } diff --git a/src/com/android/loganalysis/rule/RuleEngine.java b/src/com/android/loganalysis/rule/RuleEngine.java index 61c2081..728eeb8 100644 --- a/src/com/android/loganalysis/rule/RuleEngine.java +++ b/src/com/android/loganalysis/rule/RuleEngine.java @@ -68,5 +68,6 @@ public class RuleEngine { mRulesList.add(new ProcessUsageRule(mBugreportItem)); mRulesList.add(new LocationUsageRule(mBugreportItem)); mRulesList.add(new WifiStatsRule(mBugreportItem)); + mRulesList.add(new InterruptRule(mBugreportItem)); } } diff --git a/src/com/android/loganalysis/rule/WakelockRule.java b/src/com/android/loganalysis/rule/WakelockRule.java index b2db2cd..3be02ee 100644 --- a/src/com/android/loganalysis/rule/WakelockRule.java +++ b/src/com/android/loganalysis/rule/WakelockRule.java @@ -21,6 +21,9 @@ import com.android.loganalysis.item.WakelockItem; import com.android.loganalysis.item.WakelockItem.WakelockInfoItem; import com.android.loganalysis.util.NumberFormattingUtil; +import java.util.ArrayList; +import java.util.List; + import org.json.JSONException; import org.json.JSONObject; @@ -32,25 +35,23 @@ public class WakelockRule extends AbstractPowerRule { private static final String WAKELOCK_ANALYSIS = "WAKELOCK_ANALYSIS"; private static final float WAKELOCK_HELD_TIME_THRESHOLD_PERCENTAGE = 0.1f; // 10% - private String mAnalysis = null; + private List<WakelockInfoItem> mOffendingWakelockList; public WakelockRule (BugreportItem bugreportItem) { super(bugreportItem); } - @SuppressWarnings("cast") @Override public void applyRule() { + mOffendingWakelockList = new ArrayList<WakelockInfoItem>(); WakelockItem wakelockItem = getDetailedAnalysisItem().getWakelockItem(); - if (wakelockItem != null) { + if (wakelockItem != null && getTimeOnBattery() > 0) { long wakelockThreshold = (long)(getTimeOnBattery() * WAKELOCK_HELD_TIME_THRESHOLD_PERCENTAGE); for (WakelockInfoItem wakelocks : wakelockItem.getWakeLocks()) { if (wakelocks.getHeldTime() > wakelockThreshold) { - mAnalysis = String.format("%s %s is held for %s", wakelocks.getName(), - wakelocks.getCategory(), - NumberFormattingUtil.getDuration(wakelocks.getHeldTime())); + mOffendingWakelockList.add(wakelocks); } } } @@ -59,10 +60,19 @@ public class WakelockRule extends AbstractPowerRule { @Override public JSONObject getAnalysis() { JSONObject wakelockAnalysis = new JSONObject(); - try { - if (mAnalysis != null) { - wakelockAnalysis.put(WAKELOCK_ANALYSIS, mAnalysis); + + StringBuilder analysis = new StringBuilder(); + if (mOffendingWakelockList == null || mOffendingWakelockList.size() <= 0) { + analysis.append("No wakelocks were held for more than 10% of time on battery."); + } else { + for (WakelockInfoItem wakelocks : mOffendingWakelockList) { + analysis.append(String.format("%s %s is held for %s. ", wakelocks.getName(), + wakelocks.getCategory(), + NumberFormattingUtil.getDuration(wakelocks.getHeldTime()))); } + } + try { + wakelockAnalysis.put(WAKELOCK_ANALYSIS, analysis.toString().trim()); } catch (JSONException e) { // do nothing } diff --git a/src/com/android/loganalysis/rule/WifiStatsRule.java b/src/com/android/loganalysis/rule/WifiStatsRule.java index 4a20520..f9bca39 100644 --- a/src/com/android/loganalysis/rule/WifiStatsRule.java +++ b/src/com/android/loganalysis/rule/WifiStatsRule.java @@ -25,7 +25,7 @@ import org.json.JSONException; import org.json.JSONObject; /** - * Rules definition for Process usage + * Rules definition for Wifi stats */ public class WifiStatsRule extends AbstractPowerRule { @@ -34,7 +34,9 @@ public class WifiStatsRule extends AbstractPowerRule { // Wifi scans are scheduled by GSA every 285 seconds, anything more frequent is an issue private static final long WIFI_SCAN_INTERVAL_THRESHOLD_MS = 285000; - private StringBuffer mAnalysisBuffer; + private long mFrequentWifiScansIntervalSecs = 0; + private int mNumFrequentWifiDisconnects = 0; + private BugreportItem mBugreportItem = null; public WifiStatsRule (BugreportItem bugreportItem) { @@ -44,7 +46,6 @@ public class WifiStatsRule extends AbstractPowerRule { @Override public void applyRule() { - mAnalysisBuffer = new StringBuffer(); if (mBugreportItem.getDumpsys() == null || getTimeOnBattery() <= 0) { return; } @@ -57,21 +58,33 @@ public class WifiStatsRule extends AbstractPowerRule { dumpsysWifiStatsItem.getNumWifiScans(); if (observedWifiScanIntervalMs < WIFI_SCAN_INTERVAL_THRESHOLD_MS) { - mAnalysisBuffer.append(String.format("Wifi scans happened every %d seconds.", - TimeUnit.MILLISECONDS.toSeconds(observedWifiScanIntervalMs))); - } - if (dumpsysWifiStatsItem.getNumWifiDisconnects() >= WIFI_DISCONNECT_THRESHOLD) { - mAnalysisBuffer.append(String.format("Wifi got disconnected %d times", - dumpsysWifiStatsItem.getNumWifiDisconnects())); + mFrequentWifiScansIntervalSecs = TimeUnit.MILLISECONDS.toSeconds( + observedWifiScanIntervalMs); } } + if (dumpsysWifiStatsItem.getNumWifiDisconnects() >= WIFI_DISCONNECT_THRESHOLD) { + mNumFrequentWifiDisconnects = dumpsysWifiStatsItem.getNumWifiDisconnects(); + } } @Override public JSONObject getAnalysis() { JSONObject wifiStatsAnalysis = new JSONObject(); + StringBuilder analysis = new StringBuilder(); + if (mFrequentWifiScansIntervalSecs == 0) { + analysis.append("No apps requested for frequent wifi scans. "); + } else { + analysis.append(String.format("Wifi scans happened every %d seconds. ", + mFrequentWifiScansIntervalSecs)); + } + if (mNumFrequentWifiDisconnects == 0) { + analysis.append("No frequent wifi disconnects were observed. "); + } else { + analysis.append(String.format("Wifi got disconnected %d times. ", + mNumFrequentWifiDisconnects)); + } try { - wifiStatsAnalysis.put(WIFI_STATS, mAnalysisBuffer.toString()); + wifiStatsAnalysis.put(WIFI_STATS, analysis.toString().trim()); } catch (JSONException e) { // do nothing } diff --git a/tests/src/com/android/loganalysis/rule/InterruptRuleTest.java b/tests/src/com/android/loganalysis/rule/InterruptRuleTest.java new file mode 100644 index 0000000..7a08db0 --- /dev/null +++ b/tests/src/com/android/loganalysis/rule/InterruptRuleTest.java @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.loganalysis.rule; + +import com.android.loganalysis.item.BatteryStatsDetailedInfoItem; +import com.android.loganalysis.item.BugreportItem; +import com.android.loganalysis.item.DumpsysBatteryStatsItem; +import com.android.loganalysis.item.DumpsysItem; +import com.android.loganalysis.item.InterruptItem; +import com.android.loganalysis.item.InterruptItem.InterruptCategory; + +import junit.framework.TestCase; + +import org.json.JSONObject; + +/** + * Unit tests for {@link InterruptRule} + */ +public class InterruptRuleTest extends TestCase { + + BugreportItem mBugreport; + DumpsysItem mDumpsys; + DumpsysBatteryStatsItem mDumpsysBatteryStats; + BatteryStatsDetailedInfoItem mBatteryStatsDetailedInfo; + + @Override + public void setUp() { + mBugreport = new BugreportItem(); + mDumpsys = new DumpsysItem(); + mDumpsysBatteryStats = new DumpsysBatteryStatsItem(); + mBatteryStatsDetailedInfo = new BatteryStatsDetailedInfoItem(); + + mBatteryStatsDetailedInfo.setTimeOnBattery(3902004); + mDumpsysBatteryStats.setDetailedBatteryStatsItem(mBatteryStatsDetailedInfo); + mDumpsys.setBatteryInfo(mDumpsysBatteryStats); + mBugreport.setDumpsys(mDumpsys); + } + + /** + * Test interrupt analysis + */ + public void testInterruptAnalysis() throws Exception { + InterruptItem interrupt = new InterruptItem(); + interrupt.addInterrupt("2:bcmsdh_sdmmc:2:qcom,smd:2:msmgio", 40, + InterruptCategory.WIFI_INTERRUPT); + interrupt.addInterrupt("2:qcom,smd-rpm:2:fc4c.qcom,spmi", 7, + InterruptCategory.UNKNOWN_INTERRUPT); + + mBatteryStatsDetailedInfo.setInterruptItem(interrupt); + + InterruptRule interruptRule = new InterruptRule(mBugreport); + interruptRule.applyRule(); + JSONObject analysis = interruptRule.getAnalysis(); + assertNotNull(analysis); + assertTrue(analysis.has("INTERRUPT_ANALYSIS")); + assertEquals(analysis.getString("INTERRUPT_ANALYSIS"), + "Frequent interrupts from WIFI_INTERRUPT (2:bcmsdh_sdmmc:2:qcom,smd:2:msmgio)."); + } + + + public void testNoSignificantInterruptAnalysis() throws Exception { + InterruptItem interrupt = new InterruptItem(); + interrupt.addInterrupt("2:bcmsdh_sdmmc:2:qcom,smd:2:msmgio", 5, + InterruptCategory.WIFI_INTERRUPT); + interrupt.addInterrupt("2:qcom,smd-rpm:2:fc4c.qcom,spmi", 7, + InterruptCategory.UNKNOWN_INTERRUPT); + + mBatteryStatsDetailedInfo.setInterruptItem(interrupt); + + InterruptRule interruptRule = new InterruptRule(mBugreport); + interruptRule.applyRule(); + JSONObject analysis = interruptRule.getAnalysis(); + assertNotNull(analysis); + assertTrue(analysis.has("INTERRUPT_ANALYSIS")); + assertEquals(analysis.getString("INTERRUPT_ANALYSIS"), + "No interrupts woke up device more frequent than 120 secs."); + } + + public void testMissingInterruptAnalysis() throws Exception { + InterruptRule interruptRule = new InterruptRule(mBugreport); + interruptRule.applyRule(); + JSONObject analysis = interruptRule.getAnalysis(); + assertNotNull(analysis); + assertTrue(analysis.has("INTERRUPT_ANALYSIS")); + assertEquals(analysis.getString("INTERRUPT_ANALYSIS"), + "No interrupts woke up device more frequent than 120 secs."); + } +} diff --git a/tests/src/com/android/loganalysis/rule/LocationUsageRuleTest.java b/tests/src/com/android/loganalysis/rule/LocationUsageRuleTest.java new file mode 100644 index 0000000..5dd7e9e --- /dev/null +++ b/tests/src/com/android/loganalysis/rule/LocationUsageRuleTest.java @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.loganalysis.rule; + +import com.android.loganalysis.item.ActivityServiceItem; +import com.android.loganalysis.item.BatteryStatsDetailedInfoItem; +import com.android.loganalysis.item.BugreportItem; +import com.android.loganalysis.item.DumpsysBatteryStatsItem; +import com.android.loganalysis.item.DumpsysItem; +import com.android.loganalysis.item.LocationDumpsItem; + +import junit.framework.TestCase; + +import org.json.JSONObject; + +/** + * Unit tests for {@link LocationUsageRule} + */ +public class LocationUsageRuleTest extends TestCase { + + BugreportItem mBugreport; + DumpsysItem mDumpsys; + DumpsysBatteryStatsItem mDumpsysBatteryStats; + BatteryStatsDetailedInfoItem mBatteryStatsDetailedInfo; + ActivityServiceItem mActivityService; + + @Override + public void setUp() { + mBugreport = new BugreportItem(); + mDumpsys = new DumpsysItem(); + mDumpsysBatteryStats = new DumpsysBatteryStatsItem(); + mBatteryStatsDetailedInfo = new BatteryStatsDetailedInfoItem(); + mActivityService = new ActivityServiceItem(); + + mBatteryStatsDetailedInfo.setTimeOnBattery(3902004); + mDumpsysBatteryStats.setDetailedBatteryStatsItem(mBatteryStatsDetailedInfo); + mDumpsys.setBatteryInfo(mDumpsysBatteryStats); + mBugreport.setDumpsys(mDumpsys); + mBugreport.setActivityService(mActivityService); + } + + /** + * Test location usage analysis + */ + public void testLocationUsageAnalysis() throws Exception { + LocationDumpsItem location = new LocationDumpsItem(); + location.addLocationClient("com.google.android.gms", 1, 0, 0, "PRIORITY_NO_POWER", 140); + location.addLocationClient("com.google.android.gms", 5, 5, 5, + "PRIORITY_BALANCED_POWER_ACCURACY", 140); + mActivityService.setLocationDumps(location); + + LocationUsageRule locationUsageRule = new LocationUsageRule(mBugreport); + locationUsageRule.applyRule(); + JSONObject analysis = locationUsageRule.getAnalysis(); + assertNotNull(analysis); + assertTrue(analysis.has("LOCATION_USAGE_ANALYSIS")); + assertEquals(analysis.getString("LOCATION_USAGE_ANALYSIS"), + "Package com.google.android.gms is requesting for location updates every 5 secs " + + "with priority PRIORITY_BALANCED_POWER_ACCURACY."); + } + + public void testNoSignificantLocationUsageAnalysis() throws Exception { + LocationDumpsItem location = new LocationDumpsItem(); + location.addLocationClient("com.google.android.gms", 1, 0, 0, "PRIORITY_NO_POWER", 140); + location.addLocationClient("com.google.android.gms", 285, 285, 285, + "PRIORITY_BALANCED_POWER_ACCURACY", 140); + mActivityService.setLocationDumps(location); + + LocationUsageRule locationUsageRule = new LocationUsageRule(mBugreport); + locationUsageRule.applyRule(); + JSONObject analysis = locationUsageRule.getAnalysis(); + assertNotNull(analysis); + assertTrue(analysis.has("LOCATION_USAGE_ANALYSIS")); + assertEquals(analysis.getString("LOCATION_USAGE_ANALYSIS"), + "No apps requested for frequent location updates."); + } + + public void testNoLocationUsageAnalysis() throws Exception { + LocationUsageRule locationUsageRule = new LocationUsageRule(mBugreport); + locationUsageRule.applyRule(); + JSONObject analysis = locationUsageRule.getAnalysis(); + assertNotNull(analysis); + assertTrue(analysis.has("LOCATION_USAGE_ANALYSIS")); + assertEquals(analysis.getString("LOCATION_USAGE_ANALYSIS"), + "No apps requested for frequent location updates."); + } +} diff --git a/tests/src/com/android/loganalysis/rule/ProcessUsageRuleTest.java b/tests/src/com/android/loganalysis/rule/ProcessUsageRuleTest.java new file mode 100644 index 0000000..cc322dc --- /dev/null +++ b/tests/src/com/android/loganalysis/rule/ProcessUsageRuleTest.java @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.loganalysis.rule; + +import com.android.loganalysis.item.BatteryStatsDetailedInfoItem; +import com.android.loganalysis.item.BugreportItem; +import com.android.loganalysis.item.DumpsysBatteryStatsItem; +import com.android.loganalysis.item.DumpsysItem; +import com.android.loganalysis.item.ProcessUsageItem; +import com.android.loganalysis.item.ProcessUsageItem.SensorInfoItem; + +import java.util.LinkedList; +import junit.framework.TestCase; + +import org.json.JSONObject; + +/** + * Unit tests for {@link ProcessUsageRule} + */ +public class ProcessUsageRuleTest extends TestCase { + + BugreportItem mBugreport; + DumpsysItem mDumpsys; + DumpsysBatteryStatsItem mDumpsysBatteryStats; + BatteryStatsDetailedInfoItem mBatteryStatsDetailedInfo; + + @Override + public void setUp() { + mBugreport = new BugreportItem(); + mDumpsys = new DumpsysItem(); + mDumpsysBatteryStats = new DumpsysBatteryStatsItem(); + mBatteryStatsDetailedInfo = new BatteryStatsDetailedInfoItem(); + + mBatteryStatsDetailedInfo.setTimeOnBattery(3902004); + mDumpsysBatteryStats.setDetailedBatteryStatsItem(mBatteryStatsDetailedInfo); + mDumpsys.setBatteryInfo(mDumpsysBatteryStats); + mBugreport.setDumpsys(mDumpsys); + } + + /** + * Test alarm usage analysis + */ + public void testAlarmAnalysis() throws Exception { + ProcessUsageItem processUsage = new ProcessUsageItem(); + LinkedList<SensorInfoItem> uid0Sensor = new LinkedList<SensorInfoItem>(); + uid0Sensor.add(new SensorInfoItem("0", 9908)); + uid0Sensor.add(new SensorInfoItem("1", 9997)); + + LinkedList<SensorInfoItem> uidU0a9Sensor = new LinkedList<SensorInfoItem>(); + uidU0a9Sensor.add(new SensorInfoItem("2", 1315)); + + processUsage.addProcessUsage("0", 0, uid0Sensor); + processUsage.addProcessUsage("u0a9", 180, uidU0a9Sensor); + processUsage.addProcessUsage("u0a8", 0, null); + + mBatteryStatsDetailedInfo.setProcessUsageItem(processUsage); + ProcessUsageRule usage = new ProcessUsageRule(mBugreport); + usage.applyRule(); + JSONObject analysis = usage.getAnalysis(); + assertNotNull(analysis); + assertTrue(analysis.has("ALARM_USAGE_ANALYSIS")); + assertEquals(analysis.getString("ALARM_USAGE_ANALYSIS"), + "UID u0a9 has requested frequent repeating alarms."); + assertTrue(analysis.has("SENSOR_USAGE_ANALYSIS")); + assertEquals(analysis.getString("SENSOR_USAGE_ANALYSIS"), + "No apps used sensors more than 10% time on battery."); + } + + /** + * Test sensor usage analysis + */ + public void testSensorAnalysis() throws Exception { + ProcessUsageItem processUsage = new ProcessUsageItem(); + LinkedList<SensorInfoItem> uid0Sensor = new LinkedList<SensorInfoItem>(); + uid0Sensor.add(new SensorInfoItem("0", 9908)); + uid0Sensor.add(new SensorInfoItem("1", 9997)); + + LinkedList<SensorInfoItem> uidU0a9Sensor = new LinkedList<SensorInfoItem>(); + uidU0a9Sensor.add(new SensorInfoItem("2", 913015)); + + processUsage.addProcessUsage("0", 0, uid0Sensor); + processUsage.addProcessUsage("u0a9", 15, uidU0a9Sensor); + processUsage.addProcessUsage("u0a8", 0, null); + + mBatteryStatsDetailedInfo.setProcessUsageItem(processUsage); + ProcessUsageRule usage = new ProcessUsageRule(mBugreport); + usage.applyRule(); + JSONObject analysis = usage.getAnalysis(); + assertNotNull(analysis); + assertTrue(analysis.has("SENSOR_USAGE_ANALYSIS")); + assertEquals(analysis.getString("SENSOR_USAGE_ANALYSIS"), + "sensor 2 was used for 0d 0h 15m 13s by UID u0a9."); + + assertTrue(analysis.has("ALARM_USAGE_ANALYSIS")); + assertEquals(analysis.getString("ALARM_USAGE_ANALYSIS"), + "No apps requested for alarms more frequent than 60 secs."); + } +} diff --git a/tests/src/com/android/loganalysis/rule/WakelockRuleTest.java b/tests/src/com/android/loganalysis/rule/WakelockRuleTest.java new file mode 100644 index 0000000..6900c07 --- /dev/null +++ b/tests/src/com/android/loganalysis/rule/WakelockRuleTest.java @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.loganalysis.rule; + +import com.android.loganalysis.item.BatteryStatsDetailedInfoItem; +import com.android.loganalysis.item.BugreportItem; +import com.android.loganalysis.item.DumpsysBatteryStatsItem; +import com.android.loganalysis.item.DumpsysItem; +import com.android.loganalysis.item.WakelockItem; +import com.android.loganalysis.item.WakelockItem.WakeLockCategory; + +import junit.framework.TestCase; + +import org.json.JSONObject; + +/** + * Unit tests for {@link WakelockRule} + */ +public class WakelockRuleTest extends TestCase { + + BugreportItem mBugreport; + DumpsysItem mDumpsys; + DumpsysBatteryStatsItem mDumpsysBatteryStats; + BatteryStatsDetailedInfoItem mBatteryStatsDetailedInfo; + + @Override + public void setUp() { + mBugreport = new BugreportItem(); + mDumpsys = new DumpsysItem(); + mDumpsysBatteryStats = new DumpsysBatteryStatsItem(); + mBatteryStatsDetailedInfo = new BatteryStatsDetailedInfoItem(); + + mBatteryStatsDetailedInfo.setTimeOnBattery(3902004); + mDumpsysBatteryStats.setDetailedBatteryStatsItem(mBatteryStatsDetailedInfo); + mDumpsys.setBatteryInfo(mDumpsysBatteryStats); + mBugreport.setDumpsys(mDumpsys); + } + + /** + * Test wakelock analysis + */ + public void testWakelockAnalysis() throws Exception { + WakelockItem wakelock = new WakelockItem(); + wakelock.addWakeLock("PowerManagerService.WakeLocks", 310006, 2, + WakeLockCategory.KERNEL_WAKELOCK); + wakelock.addWakeLock("msm_serial_hs_rx", 133612, 258, + WakeLockCategory.KERNEL_WAKELOCK); + + wakelock.addWakeLock("ProxyController", "1001", 3887565, 4, + WakeLockCategory.PARTIAL_WAKELOCK); + wakelock.addWakeLock("AudioMix", "1013", 1979, 3, + WakeLockCategory.PARTIAL_WAKELOCK); + + mBatteryStatsDetailedInfo.setWakelockItem(wakelock); + WakelockRule wakelockRule = new WakelockRule(mBugreport); + wakelockRule.applyRule(); + JSONObject analysis = wakelockRule.getAnalysis(); + assertNotNull(analysis); + assertTrue(analysis.has("WAKELOCK_ANALYSIS")); + assertEquals(analysis.getString("WAKELOCK_ANALYSIS"), + "ProxyController PARTIAL_WAKELOCK is held for 0d 1h 4m 47s."); + } + + public void testNoSignificantWakelockAnalysis() throws Exception { + WakelockItem wakelock = new WakelockItem(); + wakelock.addWakeLock("PowerManagerService.WakeLocks", 310006, 2, + WakeLockCategory.KERNEL_WAKELOCK); + wakelock.addWakeLock("msm_serial_hs_rx", 133612, 258, + WakeLockCategory.KERNEL_WAKELOCK); + + wakelock.addWakeLock("ProxyController", "1001", 287565, 4, + WakeLockCategory.PARTIAL_WAKELOCK); + wakelock.addWakeLock("AudioMix", "1013", 1979, 3, + WakeLockCategory.PARTIAL_WAKELOCK); + + mBatteryStatsDetailedInfo.setWakelockItem(wakelock); + WakelockRule wakelockRule = new WakelockRule(mBugreport); + wakelockRule.applyRule(); + JSONObject analysis = wakelockRule.getAnalysis(); + assertNotNull(analysis); + assertTrue(analysis.has("WAKELOCK_ANALYSIS")); + assertEquals(analysis.getString("WAKELOCK_ANALYSIS"), + "No wakelocks were held for more than 10% of time on battery."); + } + + public void testNoWakelockAnalysis() throws Exception { + WakelockRule wakelockRule = new WakelockRule(mBugreport); + wakelockRule.applyRule(); + JSONObject analysis = wakelockRule.getAnalysis(); + assertNotNull(analysis); + assertTrue(analysis.has("WAKELOCK_ANALYSIS")); + assertEquals(analysis.getString("WAKELOCK_ANALYSIS"), + "No wakelocks were held for more than 10% of time on battery."); + } +} diff --git a/tests/src/com/android/loganalysis/rule/WifiStatsRuleTest.java b/tests/src/com/android/loganalysis/rule/WifiStatsRuleTest.java new file mode 100644 index 0000000..628039e --- /dev/null +++ b/tests/src/com/android/loganalysis/rule/WifiStatsRuleTest.java @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.loganalysis.rule; + +import com.android.loganalysis.item.BatteryStatsDetailedInfoItem; +import com.android.loganalysis.item.BugreportItem; +import com.android.loganalysis.item.DumpsysBatteryStatsItem; +import com.android.loganalysis.item.DumpsysItem; +import com.android.loganalysis.item.DumpsysWifiStatsItem; +import com.android.loganalysis.parser.BugreportParser; + +import java.util.Arrays; +import java.util.List; + +import junit.framework.TestCase; + +import org.json.JSONObject; + +/** + */ +public class WifiStatsRuleTest extends TestCase { + + BugreportItem mBugreport; + DumpsysItem mDumpsys; + DumpsysBatteryStatsItem mDumpsysBatteryStats; + BatteryStatsDetailedInfoItem mBatteryStatsDetailedInfo; + + @Override + public void setUp() { + mBugreport = new BugreportItem(); + mDumpsys = new DumpsysItem(); + mDumpsysBatteryStats = new DumpsysBatteryStatsItem(); + mBatteryStatsDetailedInfo = new BatteryStatsDetailedInfoItem(); + + mBatteryStatsDetailedInfo.setTimeOnBattery(302004); + mDumpsysBatteryStats.setDetailedBatteryStatsItem(mBatteryStatsDetailedInfo); + mDumpsys.setBatteryInfo(mDumpsysBatteryStats); + mBugreport.setDumpsys(mDumpsys); + } + + /** + * Test wifistats analysis + */ + public void testWifiDisconnectAnalysis() throws Exception { + DumpsysWifiStatsItem wifiStats = new DumpsysWifiStatsItem(); + wifiStats.setNumWifiDisconnect(1); + wifiStats.setNumWifiScan(0); + + mDumpsys.setWifiStats(wifiStats); + WifiStatsRule wifiStatsRule = new WifiStatsRule(mBugreport); + wifiStatsRule.applyRule(); + JSONObject analysis = wifiStatsRule.getAnalysis(); + assertNotNull(analysis); + assertTrue(analysis.has("WIFI_STATS")); + assertEquals(analysis.getString("WIFI_STATS"), + "No apps requested for frequent wifi scans. Wifi got disconnected 1 times."); + } + + public void testWifiScanAnalysis() throws Exception { + DumpsysWifiStatsItem wifiStats = new DumpsysWifiStatsItem(); + wifiStats.setNumWifiDisconnect(0); + wifiStats.setNumWifiScan(3); + + mDumpsys.setWifiStats(wifiStats); + WifiStatsRule wifiStatsRule = new WifiStatsRule(mBugreport); + wifiStatsRule.applyRule(); + JSONObject analysis = wifiStatsRule.getAnalysis(); + assertNotNull(analysis); + assertTrue(analysis.has("WIFI_STATS")); + assertEquals(analysis.getString("WIFI_STATS"), + "Wifi scans happened every 100 seconds. No frequent wifi disconnects were observed." + ); + } +} |