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.rule; 18 19 import com.android.loganalysis.item.BugreportItem; 20 import com.android.loganalysis.item.ProcessUsageItem; 21 import com.android.loganalysis.item.ProcessUsageItem.ProcessUsageInfoItem; 22 import com.android.loganalysis.item.ProcessUsageItem.SensorInfoItem; 23 24 import com.android.loganalysis.util.NumberFormattingUtil; 25 26 import java.util.ArrayList; 27 import java.util.List; 28 29 import org.json.JSONException; 30 import org.json.JSONObject; 31 32 33 /** 34 * Rules definition for Process usage 35 */ 36 public class ProcessUsageRule extends AbstractPowerRule { 37 38 private static final String ALARM_USAGE_ANALYSIS = "ALARM_USAGE_ANALYSIS"; 39 private static final String SENSOR_USAGE_ANALYSIS = "SENSOR_USAGE_ANALYSIS"; 40 private static final long ALARM_THRESHOLD = 60000; 41 private static final float SENSOR_ACTIVE_TIME_THRESHOLD_PERCENTAGE = 0.1f; // 10% 42 43 private List<ProcessUsageInfoItem> mOffendingAlarmList; 44 private List<ProcessUsageInfoItem> mOffendingSensorList; 45 46 public ProcessUsageRule (BugreportItem bugreportItem) { 47 super(bugreportItem); 48 } 49 50 51 @Override 52 public void applyRule() { 53 mOffendingAlarmList = new ArrayList<ProcessUsageInfoItem>(); 54 mOffendingSensorList = new ArrayList<ProcessUsageInfoItem>(); 55 56 ProcessUsageItem processUsageItem = getDetailedAnalysisItem().getProcessUsageItem(); 57 if (processUsageItem != null && getTimeOnBattery() > 0) { 58 for (ProcessUsageInfoItem usage : processUsageItem.getProcessUsage()) { 59 if (usage.getAlarmWakeups() > 0) { 60 addAlarmAnalysis(usage); 61 } 62 if (usage.getSensorUsage() != null && usage.getSensorUsage().size() > 0) { 63 addSensorAnalysis(usage); 64 } 65 } 66 } 67 } 68 69 private void addAlarmAnalysis(ProcessUsageInfoItem usage) { 70 final long alarmsPerMs = getTimeOnBattery()/usage.getAlarmWakeups(); 71 if (alarmsPerMs < ALARM_THRESHOLD) { 72 mOffendingAlarmList.add(usage); 73 } 74 } 75 76 private void addSensorAnalysis(ProcessUsageInfoItem usage) { 77 final long sensorUsageThresholdMs = (long) (getTimeOnBattery() 78 * SENSOR_ACTIVE_TIME_THRESHOLD_PERCENTAGE); 79 for (SensorInfoItem sensorInfo : usage.getSensorUsage()) { 80 if (sensorInfo.getUsageDurationMs() > sensorUsageThresholdMs) { 81 mOffendingSensorList.add(usage); 82 } 83 } 84 } 85 86 @Override 87 public JSONObject getAnalysis() { 88 JSONObject usageAnalysis = new JSONObject(); 89 StringBuilder alarmAnalysis = new StringBuilder(); 90 if (mOffendingAlarmList == null || mOffendingAlarmList.size() <= 0) { 91 alarmAnalysis.append("No apps requested for alarms more frequent than 60 secs."); 92 } else { 93 for (ProcessUsageInfoItem alarmInfo : mOffendingAlarmList) { 94 alarmAnalysis.append(String.format( 95 "UID %s has requested frequent repeating alarms. ", 96 alarmInfo.getProcessUID())); 97 } 98 } 99 StringBuilder sensorAnalysis = new StringBuilder(); 100 if (mOffendingSensorList == null || mOffendingSensorList.size() <= 0) { 101 sensorAnalysis.append("No apps used sensors more than 10% time on battery."); 102 } else { 103 for (ProcessUsageInfoItem sensorInfo : mOffendingSensorList) { 104 for (SensorInfoItem sensors : sensorInfo.getSensorUsage()) { 105 sensorAnalysis.append(String.format("sensor %s was used for %s by UID %s. ", 106 sensors.getSensorName(), 107 NumberFormattingUtil.getDuration(sensors.getUsageDurationMs()), 108 sensorInfo.getProcessUID())); 109 } 110 } 111 } 112 try { 113 usageAnalysis.put(ALARM_USAGE_ANALYSIS, alarmAnalysis.toString().trim()); 114 usageAnalysis.put(SENSOR_USAGE_ANALYSIS, sensorAnalysis.toString().trim()); 115 } catch (JSONException e) { 116 // do nothing 117 } 118 return usageAnalysis; 119 } 120 } 121