Loading src/com/android/settings/fuelgauge/BatteryInfo.java +1 −1 Original line number Diff line number Diff line Loading @@ -272,7 +272,7 @@ public class BatteryInfo { void onParsingDone(); } private static void parse(BatteryStats stats, BatteryDataParser... parsers) { public static void parse(BatteryStats stats, BatteryDataParser... parsers) { long startWalltime = 0; long endWalltime = 0; long historyStart = 0; Loading src/com/android/settings/fuelgauge/batterytip/BatteryTipPolicy.java +26 −0 Original line number Diff line number Diff line Loading @@ -19,9 +19,12 @@ package com.android.settings.fuelgauge.batterytip; import android.content.Context; import android.provider.Settings; import android.support.annotation.VisibleForTesting; import android.text.format.DateUtils; import android.util.KeyValueListParser; import android.util.Log; import java.time.Duration; /** * Class to store the policy for battery tips, which comes from * {@link Settings.Global} Loading @@ -34,6 +37,8 @@ public class BatteryTipPolicy { private static final String KEY_BATTERY_SAVER_TIP_ENABLED = "battery_saver_tip_enabled"; private static final String KEY_HIGH_USAGE_ENABLED = "high_usage_enabled"; private static final String KEY_HIGH_USAGE_APP_COUNT = "high_usage_app_count"; private static final String KEY_HIGH_USAGE_PERIOD_MS = "high_usage_period_ms"; private static final String KEY_HIGH_USAGE_BATTERY_DRAINING = "high_usage_battery_draining"; private static final String KEY_APP_RESTRICTION_ENABLED = "app_restriction_enabled"; private static final String KEY_REDUCED_BATTERY_ENABLED = "reduced_battery_enabled"; private static final String KEY_REDUCED_BATTERY_PERCENT = "reduced_battery_percent"; Loading Loading @@ -80,6 +85,24 @@ public class BatteryTipPolicy { */ public final int highUsageAppCount; /** * The size of the window(milliseconds) for checking if the device is being heavily used * * @see Settings.Global#BATTERY_TIP_CONSTANTS * @see #KEY_HIGH_USAGE_PERIOD_MS */ public final long highUsagePeriodMs; /** * The battery draining threshold to detect whether device is heavily used. * If battery drains more than {@link #highUsageBatteryDraining} in last {@link * #highUsagePeriodMs}, treat device as heavily used. * * @see Settings.Global#BATTERY_TIP_CONSTANTS * @see #KEY_HIGH_USAGE_BATTERY_DRAINING */ public final int highUsageBatteryDraining; /** * {@code true} if app restriction tip is enabled * Loading Loading @@ -143,6 +166,9 @@ public class BatteryTipPolicy { batterySaverTipEnabled = mParser.getBoolean(KEY_BATTERY_SAVER_TIP_ENABLED, true); highUsageEnabled = mParser.getBoolean(KEY_HIGH_USAGE_ENABLED, true); highUsageAppCount = mParser.getInt(KEY_HIGH_USAGE_APP_COUNT, 3); highUsagePeriodMs = mParser.getLong(KEY_HIGH_USAGE_PERIOD_MS, Duration.ofHours(2).toMillis()); highUsageBatteryDraining = mParser.getInt(KEY_HIGH_USAGE_BATTERY_DRAINING, 25); appRestrictionEnabled = mParser.getBoolean(KEY_APP_RESTRICTION_ENABLED, true); reducedBatteryEnabled = mParser.getBoolean(KEY_REDUCED_BATTERY_ENABLED, false); reducedBatteryPercent = mParser.getInt(KEY_REDUCED_BATTERY_PERCENT, 50); Loading src/com/android/settings/fuelgauge/batterytip/HighUsageDataParser.java 0 → 100644 +79 −0 Original line number Diff line number Diff line /* * Copyright (C) 2018 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.batterytip; import android.os.BatteryStats; import com.android.settings.fuelgauge.BatteryInfo; /** * DataParser used to go through battery data and detect whether battery is * heavily used. */ public class HighUsageDataParser implements BatteryInfo.BatteryDataParser { /** * time period to check the battery usage */ private final long mTimePeriodMs; /** * treat device as heavily used if battery usage is more than {@code threshold}. 1 means 1% * battery usage. */ private int mThreshold; private long mEndTimeMs; private byte mEndBatteryLevel; private byte mLastPeriodBatteryLevel; private int mBatteryDrain; public HighUsageDataParser(long timePeriodMs, int threshold) { mTimePeriodMs = timePeriodMs; mThreshold = threshold; } @Override public void onParsingStarted(long startTime, long endTime) { mEndTimeMs = endTime; } @Override public void onDataPoint(long time, BatteryStats.HistoryItem record) { if (record.currentTime <= mEndTimeMs - mTimePeriodMs) { // Since onDataPoint is invoked sorted by time, so we could use this way to get the // closet battery level 'mTimePeriodMs' time ago. mLastPeriodBatteryLevel = record.batteryLevel; } mEndBatteryLevel = record.batteryLevel; } @Override public void onDataGap() { // do nothing } @Override public void onParsingDone() { mBatteryDrain = mLastPeriodBatteryLevel - mEndBatteryLevel; } /** * Return {@code true} if the battery drain in {@link #mTimePeriodMs} is too much */ public boolean isDeviceHeavilyUsed() { return mBatteryDrain > mThreshold; } } src/com/android/settings/fuelgauge/batterytip/detectors/HighUsageDetector.java +31 −18 Original line number Diff line number Diff line Loading @@ -19,13 +19,14 @@ package com.android.settings.fuelgauge.batterytip.detectors; import android.content.Context; import android.os.BatteryStats; import android.support.annotation.VisibleForTesting; import android.text.format.DateUtils; import com.android.internal.os.BatterySipper; import com.android.internal.os.BatteryStatsHelper; import com.android.settings.fuelgauge.BatteryUtils; import com.android.settings.fuelgauge.batterytip.BatteryTipPolicy; import com.android.settings.fuelgauge.batterytip.AppInfo; import com.android.settings.fuelgauge.BatteryInfo; import com.android.settings.fuelgauge.batterytip.HighUsageDataParser; import com.android.settings.fuelgauge.batterytip.tips.BatteryTip; import com.android.settings.fuelgauge.batterytip.tips.HighUsageTip; Loading @@ -43,6 +44,8 @@ public class HighUsageDetector implements BatteryTipDetector { private List<AppInfo> mHighUsageAppList; private Context mContext; @VisibleForTesting HighUsageDataParser mDataParser; @VisibleForTesting BatteryUtils mBatteryUtils; public HighUsageDetector(Context context, BatteryTipPolicy policy, Loading @@ -52,13 +55,16 @@ public class HighUsageDetector implements BatteryTipDetector { mBatteryStatsHelper = batteryStatsHelper; mHighUsageAppList = new ArrayList<>(); mBatteryUtils = BatteryUtils.getInstance(context); mDataParser = new HighUsageDataParser(mPolicy.highUsagePeriodMs, mPolicy.highUsageBatteryDraining); } @Override public BatteryTip detect() { final long screenUsageTimeMs = mBatteryUtils.calculateScreenUsageTime(mBatteryStatsHelper); //TODO(b/70570352): Change it to detect whether battery drops 25% in last 2 hours if (mPolicy.highUsageEnabled && screenUsageTimeMs > DateUtils.HOUR_IN_MILLIS) { if (mPolicy.highUsageEnabled) { parseBatteryData(); if (mDataParser.isDeviceHeavilyUsed()) { final List<BatterySipper> batterySippers = mBatteryStatsHelper.getUsageList(); for (int i = 0, size = batterySippers.size(); i < size; i++) { final BatterySipper batterySipper = batterySippers.get(i); Loading @@ -67,7 +73,8 @@ public class HighUsageDetector implements BatteryTipDetector { BatteryUtils.StatusType.FOREGROUND, batterySipper.uidObj, BatteryStats.STATS_SINCE_CHARGED); mHighUsageAppList.add(new AppInfo.Builder() .setPackageName(mBatteryUtils.getPackageName(batterySipper.getUid())) .setPackageName( mBatteryUtils.getPackageName(batterySipper.getUid())) .setScreenOnTimeMs(foregroundTimeMs) .build()); } Loading @@ -77,7 +84,13 @@ public class HighUsageDetector implements BatteryTipDetector { Math.min(mPolicy.highUsageAppCount, mHighUsageAppList.size())); Collections.sort(mHighUsageAppList, Collections.reverseOrder()); } } return new HighUsageTip(screenUsageTimeMs, mHighUsageAppList); } @VisibleForTesting void parseBatteryData() { BatteryInfo.parse(mBatteryStatsHelper.getStats(), mDataParser); } } tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipLoaderTest.java +2 −1 Original line number Diff line number Diff line Loading @@ -37,6 +37,7 @@ import com.android.settings.testutils.SettingsRobolectricTestRunner; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Answers; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.RuntimeEnvironment; Loading @@ -54,7 +55,7 @@ public class BatteryTipLoaderTest { BatteryTip.TipType.BATTERY_SAVER, BatteryTip.TipType.LOW_BATTERY, BatteryTip.TipType.SUMMARY}; @Mock @Mock(answer = Answers.RETURNS_DEEP_STUBS) private BatteryStatsHelper mBatteryStatsHelper; @Mock private PowerManager mPowerManager; Loading Loading
src/com/android/settings/fuelgauge/BatteryInfo.java +1 −1 Original line number Diff line number Diff line Loading @@ -272,7 +272,7 @@ public class BatteryInfo { void onParsingDone(); } private static void parse(BatteryStats stats, BatteryDataParser... parsers) { public static void parse(BatteryStats stats, BatteryDataParser... parsers) { long startWalltime = 0; long endWalltime = 0; long historyStart = 0; Loading
src/com/android/settings/fuelgauge/batterytip/BatteryTipPolicy.java +26 −0 Original line number Diff line number Diff line Loading @@ -19,9 +19,12 @@ package com.android.settings.fuelgauge.batterytip; import android.content.Context; import android.provider.Settings; import android.support.annotation.VisibleForTesting; import android.text.format.DateUtils; import android.util.KeyValueListParser; import android.util.Log; import java.time.Duration; /** * Class to store the policy for battery tips, which comes from * {@link Settings.Global} Loading @@ -34,6 +37,8 @@ public class BatteryTipPolicy { private static final String KEY_BATTERY_SAVER_TIP_ENABLED = "battery_saver_tip_enabled"; private static final String KEY_HIGH_USAGE_ENABLED = "high_usage_enabled"; private static final String KEY_HIGH_USAGE_APP_COUNT = "high_usage_app_count"; private static final String KEY_HIGH_USAGE_PERIOD_MS = "high_usage_period_ms"; private static final String KEY_HIGH_USAGE_BATTERY_DRAINING = "high_usage_battery_draining"; private static final String KEY_APP_RESTRICTION_ENABLED = "app_restriction_enabled"; private static final String KEY_REDUCED_BATTERY_ENABLED = "reduced_battery_enabled"; private static final String KEY_REDUCED_BATTERY_PERCENT = "reduced_battery_percent"; Loading Loading @@ -80,6 +85,24 @@ public class BatteryTipPolicy { */ public final int highUsageAppCount; /** * The size of the window(milliseconds) for checking if the device is being heavily used * * @see Settings.Global#BATTERY_TIP_CONSTANTS * @see #KEY_HIGH_USAGE_PERIOD_MS */ public final long highUsagePeriodMs; /** * The battery draining threshold to detect whether device is heavily used. * If battery drains more than {@link #highUsageBatteryDraining} in last {@link * #highUsagePeriodMs}, treat device as heavily used. * * @see Settings.Global#BATTERY_TIP_CONSTANTS * @see #KEY_HIGH_USAGE_BATTERY_DRAINING */ public final int highUsageBatteryDraining; /** * {@code true} if app restriction tip is enabled * Loading Loading @@ -143,6 +166,9 @@ public class BatteryTipPolicy { batterySaverTipEnabled = mParser.getBoolean(KEY_BATTERY_SAVER_TIP_ENABLED, true); highUsageEnabled = mParser.getBoolean(KEY_HIGH_USAGE_ENABLED, true); highUsageAppCount = mParser.getInt(KEY_HIGH_USAGE_APP_COUNT, 3); highUsagePeriodMs = mParser.getLong(KEY_HIGH_USAGE_PERIOD_MS, Duration.ofHours(2).toMillis()); highUsageBatteryDraining = mParser.getInt(KEY_HIGH_USAGE_BATTERY_DRAINING, 25); appRestrictionEnabled = mParser.getBoolean(KEY_APP_RESTRICTION_ENABLED, true); reducedBatteryEnabled = mParser.getBoolean(KEY_REDUCED_BATTERY_ENABLED, false); reducedBatteryPercent = mParser.getInt(KEY_REDUCED_BATTERY_PERCENT, 50); Loading
src/com/android/settings/fuelgauge/batterytip/HighUsageDataParser.java 0 → 100644 +79 −0 Original line number Diff line number Diff line /* * Copyright (C) 2018 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.batterytip; import android.os.BatteryStats; import com.android.settings.fuelgauge.BatteryInfo; /** * DataParser used to go through battery data and detect whether battery is * heavily used. */ public class HighUsageDataParser implements BatteryInfo.BatteryDataParser { /** * time period to check the battery usage */ private final long mTimePeriodMs; /** * treat device as heavily used if battery usage is more than {@code threshold}. 1 means 1% * battery usage. */ private int mThreshold; private long mEndTimeMs; private byte mEndBatteryLevel; private byte mLastPeriodBatteryLevel; private int mBatteryDrain; public HighUsageDataParser(long timePeriodMs, int threshold) { mTimePeriodMs = timePeriodMs; mThreshold = threshold; } @Override public void onParsingStarted(long startTime, long endTime) { mEndTimeMs = endTime; } @Override public void onDataPoint(long time, BatteryStats.HistoryItem record) { if (record.currentTime <= mEndTimeMs - mTimePeriodMs) { // Since onDataPoint is invoked sorted by time, so we could use this way to get the // closet battery level 'mTimePeriodMs' time ago. mLastPeriodBatteryLevel = record.batteryLevel; } mEndBatteryLevel = record.batteryLevel; } @Override public void onDataGap() { // do nothing } @Override public void onParsingDone() { mBatteryDrain = mLastPeriodBatteryLevel - mEndBatteryLevel; } /** * Return {@code true} if the battery drain in {@link #mTimePeriodMs} is too much */ public boolean isDeviceHeavilyUsed() { return mBatteryDrain > mThreshold; } }
src/com/android/settings/fuelgauge/batterytip/detectors/HighUsageDetector.java +31 −18 Original line number Diff line number Diff line Loading @@ -19,13 +19,14 @@ package com.android.settings.fuelgauge.batterytip.detectors; import android.content.Context; import android.os.BatteryStats; import android.support.annotation.VisibleForTesting; import android.text.format.DateUtils; import com.android.internal.os.BatterySipper; import com.android.internal.os.BatteryStatsHelper; import com.android.settings.fuelgauge.BatteryUtils; import com.android.settings.fuelgauge.batterytip.BatteryTipPolicy; import com.android.settings.fuelgauge.batterytip.AppInfo; import com.android.settings.fuelgauge.BatteryInfo; import com.android.settings.fuelgauge.batterytip.HighUsageDataParser; import com.android.settings.fuelgauge.batterytip.tips.BatteryTip; import com.android.settings.fuelgauge.batterytip.tips.HighUsageTip; Loading @@ -43,6 +44,8 @@ public class HighUsageDetector implements BatteryTipDetector { private List<AppInfo> mHighUsageAppList; private Context mContext; @VisibleForTesting HighUsageDataParser mDataParser; @VisibleForTesting BatteryUtils mBatteryUtils; public HighUsageDetector(Context context, BatteryTipPolicy policy, Loading @@ -52,13 +55,16 @@ public class HighUsageDetector implements BatteryTipDetector { mBatteryStatsHelper = batteryStatsHelper; mHighUsageAppList = new ArrayList<>(); mBatteryUtils = BatteryUtils.getInstance(context); mDataParser = new HighUsageDataParser(mPolicy.highUsagePeriodMs, mPolicy.highUsageBatteryDraining); } @Override public BatteryTip detect() { final long screenUsageTimeMs = mBatteryUtils.calculateScreenUsageTime(mBatteryStatsHelper); //TODO(b/70570352): Change it to detect whether battery drops 25% in last 2 hours if (mPolicy.highUsageEnabled && screenUsageTimeMs > DateUtils.HOUR_IN_MILLIS) { if (mPolicy.highUsageEnabled) { parseBatteryData(); if (mDataParser.isDeviceHeavilyUsed()) { final List<BatterySipper> batterySippers = mBatteryStatsHelper.getUsageList(); for (int i = 0, size = batterySippers.size(); i < size; i++) { final BatterySipper batterySipper = batterySippers.get(i); Loading @@ -67,7 +73,8 @@ public class HighUsageDetector implements BatteryTipDetector { BatteryUtils.StatusType.FOREGROUND, batterySipper.uidObj, BatteryStats.STATS_SINCE_CHARGED); mHighUsageAppList.add(new AppInfo.Builder() .setPackageName(mBatteryUtils.getPackageName(batterySipper.getUid())) .setPackageName( mBatteryUtils.getPackageName(batterySipper.getUid())) .setScreenOnTimeMs(foregroundTimeMs) .build()); } Loading @@ -77,7 +84,13 @@ public class HighUsageDetector implements BatteryTipDetector { Math.min(mPolicy.highUsageAppCount, mHighUsageAppList.size())); Collections.sort(mHighUsageAppList, Collections.reverseOrder()); } } return new HighUsageTip(screenUsageTimeMs, mHighUsageAppList); } @VisibleForTesting void parseBatteryData() { BatteryInfo.parse(mBatteryStatsHelper.getStats(), mDataParser); } }
tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipLoaderTest.java +2 −1 Original line number Diff line number Diff line Loading @@ -37,6 +37,7 @@ import com.android.settings.testutils.SettingsRobolectricTestRunner; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Answers; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.RuntimeEnvironment; Loading @@ -54,7 +55,7 @@ public class BatteryTipLoaderTest { BatteryTip.TipType.BATTERY_SAVER, BatteryTip.TipType.LOW_BATTERY, BatteryTip.TipType.SUMMARY}; @Mock @Mock(answer = Answers.RETURNS_DEEP_STUBS) private BatteryStatsHelper mBatteryStatsHelper; @Mock private PowerManager mPowerManager; Loading