Loading src/com/android/settings/fuelgauge/BatteryUtils.java +34 −0 Original line number Diff line number Diff line Loading @@ -27,6 +27,8 @@ import android.util.Log; import android.util.SparseLongArray; import com.android.internal.os.BatterySipper; import com.android.internal.os.BatteryStatsHelper; import com.android.internal.util.ArrayUtils; import com.android.settings.overlay.FeatureFactory; import java.lang.annotation.Retention; Loading Loading @@ -213,6 +215,38 @@ public class BatteryUtils { return (powerUsageMah / (totalPowerMah - hiddenPowerMah)) * dischargeAmount; } /** * Calculate the whole running time in the state {@code statsType} * * @param batteryStatsHelper utility class that contains the data * @param statsType state that we want to calculate the time for * @return the running time in millis */ public long calculateRunningTimeBasedOnStatsType(BatteryStatsHelper batteryStatsHelper, int statsType) { final long elapsedRealtimeUs = convertMsToUs(SystemClock.elapsedRealtime()); // Return the battery time (millisecond) on status mStatsType return convertUsToMs( batteryStatsHelper.getStats().computeBatteryRealtime(elapsedRealtimeUs, statsType)); } /** * Find the package name for a {@link android.os.BatteryStats.Uid} * * @param uid id to get the package name * @return the package name. If there are multiple packages related to * given id, return the first one. Or return null if there are no known * packages with the given id * * @see PackageManager#getPackagesForUid(int) */ public String getPackageName(int uid) { final String[] packageNames = mPackageManager.getPackagesForUid(uid); return ArrayUtils.isEmpty(packageNames) ? null : packageNames[0]; } private long convertUsToMs(long timeUs) { return timeUs / 1000; } Loading src/com/android/settings/fuelgauge/PowerUsageSummary.java +2 −9 Original line number Diff line number Diff line Loading @@ -499,7 +499,8 @@ public class PowerUsageSummary extends PowerUsageBase implements BatteryInfo batteryInfo = getBatteryInfo(elapsedRealtimeUs, batteryBroadcast); updateHeaderPreference(batteryInfo); final long runningTime = calculateRunningTimeBasedOnStatsType(); final long runningTime = mBatteryUtils.calculateRunningTimeBasedOnStatsType(mStatsHelper, mStatsType); updateScreenPreference(); updateLastFullChargePreference(runningTime); Loading Loading @@ -655,14 +656,6 @@ public class PowerUsageSummary extends PowerUsageBase implements timeSequence)); } @VisibleForTesting long calculateRunningTimeBasedOnStatsType() { final long elapsedRealtimeUs = mBatteryUtils.convertMsToUs(SystemClock.elapsedRealtime()); // Return the battery time (millisecond) on status mStatsType return mStatsHelper.getStats().computeBatteryRealtime(elapsedRealtimeUs, mStatsType /* STATS_SINCE_CHARGED */) / 1000; } @VisibleForTesting void updateHeaderPreference(BatteryInfo info) { final Context context = getContext(); Loading src/com/android/settings/fuelgauge/anomaly/Anomaly.java +6 −2 Original line number Diff line number Diff line Loading @@ -34,9 +34,11 @@ import java.util.Objects; */ public class Anomaly implements Parcelable { @Retention(RetentionPolicy.SOURCE) @IntDef({AnomalyType.WAKE_LOCK}) @IntDef({AnomalyType.WAKE_LOCK, AnomalyType.WAKEUP_ALARM}) public @interface AnomalyType { int WAKE_LOCK = 0; int WAKEUP_ALARM = 1; } @Retention(RetentionPolicy.SOURCE) Loading @@ -46,7 +48,9 @@ public class Anomaly implements Parcelable { } @AnomalyType public static final int[] ANOMALY_TYPE_LIST = {AnomalyType.WAKE_LOCK}; public static final int[] ANOMALY_TYPE_LIST = {AnomalyType.WAKE_LOCK, AnomalyType.WAKEUP_ALARM}; /** * Type of this this anomaly Loading src/com/android/settings/fuelgauge/anomaly/checker/WakeLockAnomalyDetector.java +1 −7 Original line number Diff line number Diff line Loading @@ -84,7 +84,7 @@ public class WakeLockAnomalyDetector implements AnomalyDetector { // TODO: add more attributes to detect wakelock anomaly if (maxPartialWakeLockMs > WAKE_LOCK_THRESHOLD_MS && !mBatteryUtils.shouldHideSipper(sipper)) { final String packageName = getPackageName(uid.getUid()); final String packageName = mBatteryUtils.getPackageName(uid.getUid()); final CharSequence displayName = Utils.getApplicationLabel(mContext, packageName); Loading @@ -101,12 +101,6 @@ public class WakeLockAnomalyDetector implements AnomalyDetector { return anomalies; } private String getPackageName(int uid) { final String[] packageNames = mPackageManager.getPackagesForUid(uid); return packageNames == null ? null : packageNames[0]; } @VisibleForTesting long getTotalDurationMs(BatteryStats.Timer timer, long rawRealtime) { if (timer == null) { Loading src/com/android/settings/fuelgauge/anomaly/checker/WakeupAlarmAnomalyDetector.java 0 → 100644 +107 −0 Original line number Diff line number Diff line /* * Copyright (C) 2017 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.settings.fuelgauge.anomaly.checker; import android.content.Context; import android.content.pm.PackageManager; import android.os.BatteryStats; import android.os.SystemClock; import android.support.annotation.VisibleForTesting; import android.text.format.DateUtils; import android.util.ArrayMap; import com.android.internal.os.BatterySipper; import com.android.internal.os.BatteryStatsHelper; import com.android.settings.Utils; import com.android.settings.fuelgauge.BatteryUtils; import com.android.settings.fuelgauge.anomaly.Anomaly; import com.android.settings.fuelgauge.anomaly.AnomalyDetectionPolicy; import java.util.ArrayList; import java.util.List; /** * Check whether apps has too many wakeup alarms */ public class WakeupAlarmAnomalyDetector implements AnomalyDetector { private static final String TAG = "WakeupAlarmAnomalyDetector"; //TODO: add this threshold into AnomalyDetectionPolicy private static final int WAKEUP_ALARM_THRESHOLD = 60; private Context mContext; @VisibleForTesting BatteryUtils mBatteryUtils; public WakeupAlarmAnomalyDetector(Context context) { mContext = context; mBatteryUtils = BatteryUtils.getInstance(context); } @Override public List<Anomaly> detectAnomalies(BatteryStatsHelper batteryStatsHelper) { final List<BatterySipper> batterySippers = batteryStatsHelper.getUsageList(); final List<Anomaly> anomalies = new ArrayList<>(); final long totalRunningHours = mBatteryUtils.calculateRunningTimeBasedOnStatsType( batteryStatsHelper, BatteryStats.STATS_SINCE_CHARGED) / DateUtils.HOUR_IN_MILLIS; if (totalRunningHours != 0) { for (int i = 0, size = batterySippers.size(); i < size; i++) { final BatterySipper sipper = batterySippers.get(i); final BatteryStats.Uid uid = sipper.uidObj; if (uid == null || mBatteryUtils.shouldHideSipper(sipper)) { continue; } final int wakeups = getWakeupAlarmCountFromUid(uid); if ((wakeups / totalRunningHours) > WAKEUP_ALARM_THRESHOLD) { final String packageName = mBatteryUtils.getPackageName(uid.getUid()); final CharSequence displayName = Utils.getApplicationLabel(mContext, packageName); Anomaly anomaly = new Anomaly.Builder() .setUid(uid.getUid()) .setType(Anomaly.AnomalyType.WAKEUP_ALARM) .setDisplayName(displayName) .setPackageName(packageName) .build(); anomalies.add(anomaly); } } } return anomalies; } @VisibleForTesting int getWakeupAlarmCountFromUid(BatteryStats.Uid uid) { int wakeups = 0; final ArrayMap<String, ? extends BatteryStats.Uid.Pkg> packageStats = uid.getPackageStats(); for (int ipkg = packageStats.size() - 1; ipkg >= 0; ipkg--) { final BatteryStats.Uid.Pkg ps = packageStats.valueAt(ipkg); final ArrayMap<String, ? extends BatteryStats.Counter> alarms = ps.getWakeupAlarmStats(); for (int iwa = alarms.size() - 1; iwa >= 0; iwa--) { int count = alarms.valueAt(iwa).getCountLocked(BatteryStats.STATS_SINCE_CHARGED); wakeups += count; } } return wakeups; } } Loading
src/com/android/settings/fuelgauge/BatteryUtils.java +34 −0 Original line number Diff line number Diff line Loading @@ -27,6 +27,8 @@ import android.util.Log; import android.util.SparseLongArray; import com.android.internal.os.BatterySipper; import com.android.internal.os.BatteryStatsHelper; import com.android.internal.util.ArrayUtils; import com.android.settings.overlay.FeatureFactory; import java.lang.annotation.Retention; Loading Loading @@ -213,6 +215,38 @@ public class BatteryUtils { return (powerUsageMah / (totalPowerMah - hiddenPowerMah)) * dischargeAmount; } /** * Calculate the whole running time in the state {@code statsType} * * @param batteryStatsHelper utility class that contains the data * @param statsType state that we want to calculate the time for * @return the running time in millis */ public long calculateRunningTimeBasedOnStatsType(BatteryStatsHelper batteryStatsHelper, int statsType) { final long elapsedRealtimeUs = convertMsToUs(SystemClock.elapsedRealtime()); // Return the battery time (millisecond) on status mStatsType return convertUsToMs( batteryStatsHelper.getStats().computeBatteryRealtime(elapsedRealtimeUs, statsType)); } /** * Find the package name for a {@link android.os.BatteryStats.Uid} * * @param uid id to get the package name * @return the package name. If there are multiple packages related to * given id, return the first one. Or return null if there are no known * packages with the given id * * @see PackageManager#getPackagesForUid(int) */ public String getPackageName(int uid) { final String[] packageNames = mPackageManager.getPackagesForUid(uid); return ArrayUtils.isEmpty(packageNames) ? null : packageNames[0]; } private long convertUsToMs(long timeUs) { return timeUs / 1000; } Loading
src/com/android/settings/fuelgauge/PowerUsageSummary.java +2 −9 Original line number Diff line number Diff line Loading @@ -499,7 +499,8 @@ public class PowerUsageSummary extends PowerUsageBase implements BatteryInfo batteryInfo = getBatteryInfo(elapsedRealtimeUs, batteryBroadcast); updateHeaderPreference(batteryInfo); final long runningTime = calculateRunningTimeBasedOnStatsType(); final long runningTime = mBatteryUtils.calculateRunningTimeBasedOnStatsType(mStatsHelper, mStatsType); updateScreenPreference(); updateLastFullChargePreference(runningTime); Loading Loading @@ -655,14 +656,6 @@ public class PowerUsageSummary extends PowerUsageBase implements timeSequence)); } @VisibleForTesting long calculateRunningTimeBasedOnStatsType() { final long elapsedRealtimeUs = mBatteryUtils.convertMsToUs(SystemClock.elapsedRealtime()); // Return the battery time (millisecond) on status mStatsType return mStatsHelper.getStats().computeBatteryRealtime(elapsedRealtimeUs, mStatsType /* STATS_SINCE_CHARGED */) / 1000; } @VisibleForTesting void updateHeaderPreference(BatteryInfo info) { final Context context = getContext(); Loading
src/com/android/settings/fuelgauge/anomaly/Anomaly.java +6 −2 Original line number Diff line number Diff line Loading @@ -34,9 +34,11 @@ import java.util.Objects; */ public class Anomaly implements Parcelable { @Retention(RetentionPolicy.SOURCE) @IntDef({AnomalyType.WAKE_LOCK}) @IntDef({AnomalyType.WAKE_LOCK, AnomalyType.WAKEUP_ALARM}) public @interface AnomalyType { int WAKE_LOCK = 0; int WAKEUP_ALARM = 1; } @Retention(RetentionPolicy.SOURCE) Loading @@ -46,7 +48,9 @@ public class Anomaly implements Parcelable { } @AnomalyType public static final int[] ANOMALY_TYPE_LIST = {AnomalyType.WAKE_LOCK}; public static final int[] ANOMALY_TYPE_LIST = {AnomalyType.WAKE_LOCK, AnomalyType.WAKEUP_ALARM}; /** * Type of this this anomaly Loading
src/com/android/settings/fuelgauge/anomaly/checker/WakeLockAnomalyDetector.java +1 −7 Original line number Diff line number Diff line Loading @@ -84,7 +84,7 @@ public class WakeLockAnomalyDetector implements AnomalyDetector { // TODO: add more attributes to detect wakelock anomaly if (maxPartialWakeLockMs > WAKE_LOCK_THRESHOLD_MS && !mBatteryUtils.shouldHideSipper(sipper)) { final String packageName = getPackageName(uid.getUid()); final String packageName = mBatteryUtils.getPackageName(uid.getUid()); final CharSequence displayName = Utils.getApplicationLabel(mContext, packageName); Loading @@ -101,12 +101,6 @@ public class WakeLockAnomalyDetector implements AnomalyDetector { return anomalies; } private String getPackageName(int uid) { final String[] packageNames = mPackageManager.getPackagesForUid(uid); return packageNames == null ? null : packageNames[0]; } @VisibleForTesting long getTotalDurationMs(BatteryStats.Timer timer, long rawRealtime) { if (timer == null) { Loading
src/com/android/settings/fuelgauge/anomaly/checker/WakeupAlarmAnomalyDetector.java 0 → 100644 +107 −0 Original line number Diff line number Diff line /* * Copyright (C) 2017 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.settings.fuelgauge.anomaly.checker; import android.content.Context; import android.content.pm.PackageManager; import android.os.BatteryStats; import android.os.SystemClock; import android.support.annotation.VisibleForTesting; import android.text.format.DateUtils; import android.util.ArrayMap; import com.android.internal.os.BatterySipper; import com.android.internal.os.BatteryStatsHelper; import com.android.settings.Utils; import com.android.settings.fuelgauge.BatteryUtils; import com.android.settings.fuelgauge.anomaly.Anomaly; import com.android.settings.fuelgauge.anomaly.AnomalyDetectionPolicy; import java.util.ArrayList; import java.util.List; /** * Check whether apps has too many wakeup alarms */ public class WakeupAlarmAnomalyDetector implements AnomalyDetector { private static final String TAG = "WakeupAlarmAnomalyDetector"; //TODO: add this threshold into AnomalyDetectionPolicy private static final int WAKEUP_ALARM_THRESHOLD = 60; private Context mContext; @VisibleForTesting BatteryUtils mBatteryUtils; public WakeupAlarmAnomalyDetector(Context context) { mContext = context; mBatteryUtils = BatteryUtils.getInstance(context); } @Override public List<Anomaly> detectAnomalies(BatteryStatsHelper batteryStatsHelper) { final List<BatterySipper> batterySippers = batteryStatsHelper.getUsageList(); final List<Anomaly> anomalies = new ArrayList<>(); final long totalRunningHours = mBatteryUtils.calculateRunningTimeBasedOnStatsType( batteryStatsHelper, BatteryStats.STATS_SINCE_CHARGED) / DateUtils.HOUR_IN_MILLIS; if (totalRunningHours != 0) { for (int i = 0, size = batterySippers.size(); i < size; i++) { final BatterySipper sipper = batterySippers.get(i); final BatteryStats.Uid uid = sipper.uidObj; if (uid == null || mBatteryUtils.shouldHideSipper(sipper)) { continue; } final int wakeups = getWakeupAlarmCountFromUid(uid); if ((wakeups / totalRunningHours) > WAKEUP_ALARM_THRESHOLD) { final String packageName = mBatteryUtils.getPackageName(uid.getUid()); final CharSequence displayName = Utils.getApplicationLabel(mContext, packageName); Anomaly anomaly = new Anomaly.Builder() .setUid(uid.getUid()) .setType(Anomaly.AnomalyType.WAKEUP_ALARM) .setDisplayName(displayName) .setPackageName(packageName) .build(); anomalies.add(anomaly); } } } return anomalies; } @VisibleForTesting int getWakeupAlarmCountFromUid(BatteryStats.Uid uid) { int wakeups = 0; final ArrayMap<String, ? extends BatteryStats.Uid.Pkg> packageStats = uid.getPackageStats(); for (int ipkg = packageStats.size() - 1; ipkg >= 0; ipkg--) { final BatteryStats.Uid.Pkg ps = packageStats.valueAt(ipkg); final ArrayMap<String, ? extends BatteryStats.Counter> alarms = ps.getWakeupAlarmStats(); for (int iwa = alarms.size() - 1; iwa >= 0; iwa--) { int count = alarms.valueAt(iwa).getCountLocked(BatteryStats.STATS_SINCE_CHARGED); wakeups += count; } } return wakeups; } }