diff --git a/src/com/android/settings/fuelgauge/BatteryChartPreferenceController.java b/src/com/android/settings/fuelgauge/BatteryChartPreferenceController.java index c676bd36bc8..f12de01df4a 100644 --- a/src/com/android/settings/fuelgauge/BatteryChartPreferenceController.java +++ b/src/com/android/settings/fuelgauge/BatteryChartPreferenceController.java @@ -55,6 +55,8 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll private static final String TAG = "BatteryChartPreferenceController"; private static final int CHART_KEY_ARRAY_SIZE = 25; private static final int CHART_LEVEL_ARRAY_SIZE = 13; + private static final long VALID_USAGE_TIME_DURATION = DateUtils.HOUR_IN_MILLIS * 2; + private static final long VALID_DIFF_DURATION = DateUtils.MINUTE_IN_MILLIS * 3; @VisibleForTesting Map> mBatteryIndexedMap; @@ -179,6 +181,7 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll final List batteryHistoryKeyList = new ArrayList(batteryHistoryMap.keySet()); Collections.sort(batteryHistoryKeyList); + validateSlotTimestamp(batteryHistoryKeyList); mBatteryHistoryKeys = new long[CHART_KEY_ARRAY_SIZE]; final int elementSize = Math.min(batteryHistoryKeyList.size(), CHART_KEY_ARRAY_SIZE); final int offset = CHART_KEY_ARRAY_SIZE - elementSize; @@ -270,6 +273,10 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll } else { appEntries.add(entry); } + // Validates the usage time if users click a specific slot. + if (mTrapezoidIndex >= 0) { + validateUsageTime(entry); + } }); Collections.sort(appEntries, BatteryDiffEntry.COMPARATOR); Collections.sort(systemEntries, BatteryDiffEntry.COMPARATOR); @@ -289,7 +296,7 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll final String appLabel = entry.getAppLabel(); final Drawable appIcon = entry.getAppIcon(); if (TextUtils.isEmpty(appLabel) || appIcon == null) { - Log.w(TAG, "cannot find app resource:" + entry.mBatteryHistEntry); + Log.w(TAG, "cannot find app resource for\n" + entry); continue; } final String prefKey = entry.mBatteryHistEntry.getKey(); @@ -389,4 +396,39 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll } return builder.toString(); } + + @VisibleForTesting + static boolean validateUsageTime(BatteryDiffEntry entry) { + final long foregroundUsageTimeInMs = entry.mForegroundUsageTimeInMs; + final long backgroundUsageTimeInMs = entry.mBackgroundUsageTimeInMs; + final long totalUsageTimeInMs = foregroundUsageTimeInMs + backgroundUsageTimeInMs; + if (foregroundUsageTimeInMs > VALID_USAGE_TIME_DURATION + || backgroundUsageTimeInMs > VALID_USAGE_TIME_DURATION + || totalUsageTimeInMs > VALID_USAGE_TIME_DURATION) { + Log.e(TAG, "validateUsageTime() fail for\n" + entry); + return false; + } + return true; + } + + @VisibleForTesting + static boolean validateSlotTimestamp(List batteryHistoryKeys) { + // Whether the nearest two slot time diff is valid or not? + final int size = batteryHistoryKeys.size(); + for (int index = 0; index < size - 1; index++) { + final long currentTime = batteryHistoryKeys.get(index); + final long nextTime = batteryHistoryKeys.get(index + 1); + final long diffTime = Math.abs( + DateUtils.HOUR_IN_MILLIS - Math.abs(currentTime - nextTime)); + if (currentTime == 0) { + continue; + } else if (diffTime > VALID_DIFF_DURATION) { + Log.e(TAG, String.format("validateSlotTimestamp() %s > %s", + ConvertUtils.utcToLocalTime(currentTime), + ConvertUtils.utcToLocalTime(nextTime))); + return false; + } + } + return true; + } } diff --git a/src/com/android/settings/fuelgauge/BatteryDiffEntry.java b/src/com/android/settings/fuelgauge/BatteryDiffEntry.java index d48c92f6cf0..9a199bf9cda 100644 --- a/src/com/android/settings/fuelgauge/BatteryDiffEntry.java +++ b/src/com/android/settings/fuelgauge/BatteryDiffEntry.java @@ -27,6 +27,8 @@ import android.util.Log; import androidx.annotation.VisibleForTesting; +import com.android.settingslib.utils.StringUtil; + import java.time.Duration; import java.util.Comparator; import java.util.HashMap; @@ -254,14 +256,17 @@ public class BatteryDiffEntry { public String toString() { final StringBuilder builder = new StringBuilder() .append("BatteryDiffEntry{") - .append("\n\tname=" + mBatteryHistEntry.mAppLabel) + .append("\n\tname=" + getAppLabel()) .append(String.format("\n\tconsume=%.2f%% %f/%f", mPercentOfTotal, mConsumePower, mTotalConsumePower)) - .append(String.format("\n\tforeground:%d background:%d", - Duration.ofMillis(mForegroundUsageTimeInMs).getSeconds(), - Duration.ofMillis(mBackgroundUsageTimeInMs).getSeconds())) - .append(String.format("\n\tpackage:%s uid:%s", - mBatteryHistEntry.mPackageName, mBatteryHistEntry.mUid)); + .append(String.format("\n\tforeground:%s background:%s", + StringUtil.formatElapsedTime(mContext, mForegroundUsageTimeInMs, + /*withSeconds=*/ true, /*collapseTimeUnit=*/ false), + StringUtil.formatElapsedTime(mContext, mBackgroundUsageTimeInMs, + /*withSeconds=*/ true, /*collapseTimeUnit=*/ false))) + .append(String.format("\n\tpackage:%s|%s uid:%d userId:%d", + mBatteryHistEntry.mPackageName, getPackageName(), + mBatteryHistEntry.mUid, mBatteryHistEntry.mUserId)); return builder.toString(); } diff --git a/src/com/android/settings/fuelgauge/BatteryHistEntry.java b/src/com/android/settings/fuelgauge/BatteryHistEntry.java index 43078e9548b..be8a845eebd 100644 --- a/src/com/android/settings/fuelgauge/BatteryHistEntry.java +++ b/src/com/android/settings/fuelgauge/BatteryHistEntry.java @@ -123,6 +123,11 @@ public class BatteryHistEntry { return mConsumerType == ConvertUtils.CONSUMER_TYPE_UID_BATTERY; } + /** Whether this {@link BatteryHistEntry} is system consumer or not. */ + public boolean isSystemEntry() { + return mConsumerType == ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY; + } + /** Gets an identifier to represent this {@link BatteryHistEntry}. */ public String getKey() { if (mKey == null) { diff --git a/src/com/android/settings/fuelgauge/PowerUsageAdvanced.java b/src/com/android/settings/fuelgauge/PowerUsageAdvanced.java index 99a72abf013..98cbc8aa567 100644 --- a/src/com/android/settings/fuelgauge/PowerUsageAdvanced.java +++ b/src/com/android/settings/fuelgauge/PowerUsageAdvanced.java @@ -99,6 +99,13 @@ public class PowerUsageAdvanced extends PowerUsageBase { return R.xml.power_usage_advanced; } + @Override + public void onPause() { + super.onPause(); + // Resets the flag to reload usage data in onResume() callback. + mIsChartDataLoaded = false; + } + @Override protected List createPreferenceControllers(Context context) { refreshFeatureFlag(context); diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryChartPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryChartPreferenceControllerTest.java index d811726c1b6..c8bbba3623c 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryChartPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryChartPreferenceControllerTest.java @@ -381,6 +381,58 @@ public final class BatteryChartPreferenceControllerTest { assertThat(pref.getSummary()).isNull(); } + @Test + public void testValidateUsageTime_returnTrueIfBatteryDiffEntryIsValid() { + assertThat(BatteryChartPreferenceController.validateUsageTime( + createBatteryDiffEntry( + /*foregroundUsageTimeInMs=*/ DateUtils.MINUTE_IN_MILLIS, + /*backgroundUsageTimeInMs=*/ DateUtils.MINUTE_IN_MILLIS))) + .isTrue(); + } + + @Test + public void testValidateUsageTime_foregroundTimeExceedThreshold_returnFalse() { + assertThat(BatteryChartPreferenceController.validateUsageTime( + createBatteryDiffEntry( + /*foregroundUsageTimeInMs=*/ DateUtils.HOUR_IN_MILLIS * 3, + /*backgroundUsageTimeInMs=*/ 0))) + .isFalse(); + } + + @Test + public void testValidateUsageTime_backgroundTimeExceedThreshold_returnFalse() { + assertThat(BatteryChartPreferenceController.validateUsageTime( + createBatteryDiffEntry( + /*foregroundUsageTimeInMs=*/ 0, + /*backgroundUsageTimeInMs=*/ DateUtils.HOUR_IN_MILLIS * 3))) + .isFalse(); + } + + @Test + public void testValidateSlotTimestamp_emptyContent_returnTrue() { + assertThat(BatteryChartPreferenceController.validateSlotTimestamp( + new ArrayList())).isTrue(); + } + + @Test + public void testValidateSlotTimestamp_returnExpectedResult() { + final List slotTimestampList = + Arrays.asList( + Long.valueOf(0), + Long.valueOf(DateUtils.HOUR_IN_MILLIS), + Long.valueOf(DateUtils.HOUR_IN_MILLIS * 2 + DateUtils.MINUTE_IN_MILLIS), + Long.valueOf(DateUtils.HOUR_IN_MILLIS * 3 + DateUtils.MINUTE_IN_MILLIS * 2)); + // Verifies the testing data is correct before we added invalid data into it. + assertThat(BatteryChartPreferenceController.validateSlotTimestamp(slotTimestampList)) + .isTrue(); + + // Insert invalid timestamp into the list. + slotTimestampList.add( + Long.valueOf(DateUtils.HOUR_IN_MILLIS * 4 + DateUtils.MINUTE_IN_MILLIS * 3)); + assertThat(BatteryChartPreferenceController.validateSlotTimestamp(slotTimestampList)) + .isFalse(); + } + private static Map> createBatteryHistoryMap(int size) { final Map> batteryHistoryMap = new HashMap<>(); for (int index = 0; index < size; index++) { diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryHistEntryTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryHistEntryTest.java index 819a223f292..e4a86b107d6 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryHistEntryTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryHistEntryTest.java @@ -187,6 +187,16 @@ public final class BatteryHistEntryTest { .isFalse(); } + @Test + public void testIsSystemEntry_returnExpectedResult() { + assertThat(createEntry(ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY).isSystemEntry()) + .isTrue(); + assertThat(createEntry(ConvertUtils.CONSUMER_TYPE_USER_BATTERY).isSystemEntry()) + .isFalse(); + assertThat(createEntry(ConvertUtils.CONSUMER_TYPE_UID_BATTERY).isSystemEntry()) + .isFalse(); + } + private static BatteryHistEntry createEntry(int consumerType) { return new BatteryHistEntry(getContentValuesWithType(consumerType)); }