Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2f4ae2a0 authored by YUKAI HUNG's avatar YUKAI HUNG Committed by Android (Google) Code Review
Browse files

Merge "Add data validator to verify and log abnormal queried history data" into sc-dev

parents d3cc241c 70bef104
Loading
Loading
Loading
Loading
+43 −1
Original line number Diff line number Diff line
@@ -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<Integer, List<BatteryDiffEntry>> mBatteryIndexedMap;
@@ -179,6 +181,7 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
        final List<Long> batteryHistoryKeyList =
            new ArrayList<Long>(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<Long> 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;
    }
}
+11 −6
Original line number Diff line number Diff line
@@ -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();
    }

+5 −0
Original line number Diff line number Diff line
@@ -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) {
+7 −0
Original line number Diff line number Diff line
@@ -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<AbstractPreferenceController> createPreferenceControllers(Context context) {
        refreshFeatureFlag(context);
+52 −0
Original line number Diff line number Diff line
@@ -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<Long>())).isTrue();
    }

    @Test
    public void testValidateSlotTimestamp_returnExpectedResult() {
        final List<Long> 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<Long, List<BatteryHistEntry>> createBatteryHistoryMap(int size) {
        final Map<Long, List<BatteryHistEntry>> batteryHistoryMap = new HashMap<>();
        for (int index = 0; index < size; index++) {
Loading