From 3cdf60c01663ddb52b3dfb567e30a7e97b8f8cfc Mon Sep 17 00:00:00 2001 From: ykhung Date: Sat, 17 Apr 2021 00:47:48 +0800 Subject: [PATCH 1/2] Purge low percentage BatteryDiffEntry from indexed usage map Bug: 184807417 Test: make SettingsRoboTests Test: make SettingsGoogleRoboTests Change-Id: I943e224147ccbfa80578511d6cb0d6adf6f8da0f --- .../BatteryChartPreferenceController.java | 3 ++- .../settings/fuelgauge/ConvertUtils.java | 25 ++++++++++++++++++- .../settings/fuelgauge/ConvertUtilsTest.java | 23 ++++++++++++++++- 3 files changed, 48 insertions(+), 3 deletions(-) diff --git a/src/com/android/settings/fuelgauge/BatteryChartPreferenceController.java b/src/com/android/settings/fuelgauge/BatteryChartPreferenceController.java index 8b1c6b5e8bb..cc7f84553d7 100644 --- a/src/com/android/settings/fuelgauge/BatteryChartPreferenceController.java +++ b/src/com/android/settings/fuelgauge/BatteryChartPreferenceController.java @@ -152,7 +152,8 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll mBatteryIndexedMap = ConvertUtils.getIndexedUsageMap( mPrefContext, /*timeSlotSize=*/ CHART_LEVEL_ARRAY_SIZE - 1, - mBatteryHistoryKeys, batteryHistoryMap); + mBatteryHistoryKeys, batteryHistoryMap, + /*purgeLowPercentageData=*/ true); forceRefreshUi(); Log.d(TAG, String.format( diff --git a/src/com/android/settings/fuelgauge/ConvertUtils.java b/src/com/android/settings/fuelgauge/ConvertUtils.java index 015541295c3..30982da6c8d 100644 --- a/src/com/android/settings/fuelgauge/ConvertUtils.java +++ b/src/com/android/settings/fuelgauge/ConvertUtils.java @@ -24,6 +24,8 @@ import android.os.UserBatteryConsumer; import android.os.UserHandle; import android.util.Log; +import androidx.annotation.VisibleForTesting; + import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.text.SimpleDateFormat; @@ -31,6 +33,7 @@ import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.HashSet; +import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Map; @@ -44,6 +47,9 @@ public final class ConvertUtils { private static final BatteryHistEntry EMPTY_BATTERY_HIST_ENTRY = new BatteryHistEntry(new ContentValues()); + @VisibleForTesting + static double PERCENTAGE_OF_TOTAL_THRESHOLD = 1f; + /** Invalid system battery consumer drain type. */ public static final int INVALID_DRAIN_TYPE = -1; /** A fake package name to represent no BatteryEntry data. */ @@ -142,7 +148,8 @@ public final class ConvertUtils { final Context context, final int timeSlotSize, final long[] batteryHistoryKeys, - final Map> batteryHistoryMap) { + final Map> batteryHistoryMap, + final boolean purgeLowPercentageData) { final Map> resultMap = new HashMap<>(); // Generates a temporary map to calculate diff usage data, which converts the inputted // List into Map with the key comes from @@ -248,6 +255,9 @@ public final class ConvertUtils { } } insert24HoursData(BatteryChartView.SELECTED_INDEX_ALL, resultMap); + if (purgeLowPercentageData) { + purgeLowPercentageData(resultMap); + } return resultMap; } @@ -283,6 +293,19 @@ public final class ConvertUtils { indexedUsageMap.put(Integer.valueOf(desiredIndex), resultList); } + private static void purgeLowPercentageData( + final Map> indexedUsageMap) { + for (List entries : indexedUsageMap.values()) { + final Iterator iterator = entries.iterator(); + while (iterator.hasNext()) { + final BatteryDiffEntry entry = iterator.next(); + if (entry.getPercentOfTotal() < PERCENTAGE_OF_TOTAL_THRESHOLD) { + iterator.remove(); + } + } + } + } + private static long getDiffValue(long v1, long v2, long v3) { return (v2 > v1 ? v2 - v1 : 0) + (v3 > v2 ? v3 - v2 : 0); } diff --git a/tests/robotests/src/com/android/settings/fuelgauge/ConvertUtilsTest.java b/tests/robotests/src/com/android/settings/fuelgauge/ConvertUtilsTest.java index cfd23c9a410..e95b158391b 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/ConvertUtilsTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/ConvertUtilsTest.java @@ -212,7 +212,8 @@ public final class ConvertUtilsTest { final Map> resultMap = ConvertUtils.getIndexedUsageMap( - mContext, timeSlotSize, batteryHistoryKeys, batteryHistoryMap); + mContext, timeSlotSize, batteryHistoryKeys, batteryHistoryMap, + /*purgeLowPercentageData=*/ false); assertThat(resultMap).hasSize(3); // Verifies the first timestamp result. @@ -231,6 +232,26 @@ public final class ConvertUtilsTest { assertBatteryDiffEntry(entryList.get(1), 4, 5L, 5L); assertBatteryDiffEntry(entryList.get(2), 68, 40L, 50L); assertBatteryDiffEntry(entryList.get(0), 27, 30L, 40L); + + // Test getIndexedUsageMap() with purged data. + ConvertUtils.PERCENTAGE_OF_TOTAL_THRESHOLD = 50; + final Map> purgedResultMap = + ConvertUtils.getIndexedUsageMap( + mContext, timeSlotSize, batteryHistoryKeys, batteryHistoryMap, + /*purgeLowPercentageData=*/ true); + + assertThat(purgedResultMap).hasSize(3); + // Verifies the first timestamp result. + entryList = purgedResultMap.get(Integer.valueOf(0)); + assertThat(entryList).hasSize(1); + // Verifies the second timestamp result. + entryList = purgedResultMap.get(Integer.valueOf(1)); + assertThat(entryList).hasSize(1); + assertBatteryDiffEntry(entryList.get(0), 75, 40L, 50L); + // Verifies the last 24 hours aggregate result. + entryList = purgedResultMap.get(Integer.valueOf(-1)); + assertThat(entryList).hasSize(1); + assertBatteryDiffEntry(entryList.get(0), 68, 40L, 50L); } private static BatteryHistEntry createBatteryHistEntry( From 5aa3c235357d198de2e780170bd9a180e3dbc372 Mon Sep 17 00:00:00 2001 From: ykhung Date: Sat, 17 Apr 2021 19:07:36 +0800 Subject: [PATCH 2/2] Support badged icon for work profile mode and add system checking Bug: 184807417 Test: make SettingsRoboTests Test: make SettingsGoogleRoboTests Change-Id: Iebe458b364ab02eaf595bfc3b1a455e5be7d3d9d --- .../settings/fuelgauge/BatteryDiffEntry.java | 33 ++++++++- .../fuelgauge/BatteryDiffEntryTest.java | 74 ++++++++++++++++++- 2 files changed, 103 insertions(+), 4 deletions(-) diff --git a/src/com/android/settings/fuelgauge/BatteryDiffEntry.java b/src/com/android/settings/fuelgauge/BatteryDiffEntry.java index c57ee6fd869..7c27d7de3a0 100644 --- a/src/com/android/settings/fuelgauge/BatteryDiffEntry.java +++ b/src/com/android/settings/fuelgauge/BatteryDiffEntry.java @@ -20,6 +20,9 @@ import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.graphics.drawable.Drawable; +import android.os.Process; +import android.os.UserHandle; +import android.os.UserManager; import android.util.Log; import androidx.annotation.VisibleForTesting; @@ -51,6 +54,7 @@ public final class BatteryDiffEntry { private double mPercentOfTotal; private Context mContext; + private UserManager mUserManager; private String mDefaultPackageName = null; @VisibleForTesting String mAppLabel = null; @@ -68,6 +72,7 @@ public final class BatteryDiffEntry { mForegroundUsageTimeInMs = foregroundUsageTimeInMs; mBackgroundUsageTimeInMs = backgroundUsageTimeInMs; mBatteryHistEntry = batteryHistEntry; + mUserManager = context.getSystemService(UserManager.class); } /** Sets the total consumed power in a specific time slot. */ @@ -112,6 +117,19 @@ public final class BatteryDiffEntry { return mDefaultPackageName; } + /** Whether the current BatteryDiffEntry is system component or not. */ + public boolean isSystemEntry() { + switch (mBatteryHistEntry.mConsumerType) { + case ConvertUtils.CONSUMER_TYPE_USER_BATTERY: + case ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY: + return true; + case ConvertUtils.CONSUMER_TYPE_UID_BATTERY: + return isSystemUid((int) mBatteryHistEntry.mUid) + || mBatteryHistEntry.mIsHidden; + } + return false; + } + private void loadLabelAndIcon() { if (mIsLoaded) { return; @@ -151,7 +169,9 @@ public final class BatteryDiffEntry { if (mAppIcon == null) { mAppIcon = mContext.getPackageManager().getDefaultActivityIcon(); } - if (mAppLabel != null && mAppIcon != null) { + // Adds badge icon into app icon for work profile. + mAppIcon = getBadgeIconForUser(mAppIcon); + if (mAppLabel != null || mAppIcon != null) { sResourceCache.put( mBatteryHistEntry.getKey(), new BatteryEntry.NameAndIcon(mAppLabel, mAppIcon, /*iconId=*/ 0)); @@ -235,6 +255,17 @@ public final class BatteryDiffEntry { sResourceCache.clear(); } + private Drawable getBadgeIconForUser(Drawable icon) { + final int userId = UserHandle.getUserId((int) mBatteryHistEntry.mUid); + final UserHandle userHandle = new UserHandle(userId); + return mUserManager.getBadgedIconForUser(icon, userHandle); + } + + private static boolean isSystemUid(int uid) { + final int appUid = UserHandle.getAppId(uid); + return appUid >= Process.SYSTEM_UID && appUid < Process.FIRST_APPLICATION_UID; + } + private static T getNonNull(T originalObj, T newObj) { return newObj != null ? newObj : originalObj; } diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryDiffEntryTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryDiffEntryTest.java index 84ff07b3c2c..d1bd19f6c2e 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryDiffEntryTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryDiffEntryTest.java @@ -28,6 +28,7 @@ import android.content.pm.PackageManager; import android.graphics.drawable.Drawable; import android.os.SystemBatteryConsumer; import android.os.UserManager; +import android.os.UserHandle; import org.junit.Before; import org.junit.Test; @@ -52,6 +53,7 @@ public final class BatteryDiffEntryTest { @Mock private UserManager mockUserManager; @Mock private Drawable mockDrawable; @Mock private Drawable mockDrawable2; + @Mock private Drawable mockBadgedDrawable; @Before public void setUp() { @@ -209,21 +211,29 @@ public final class BatteryDiffEntryTest { public void testGetAppIcon_uidConsumerWithNullIcon_returnDefaultActivityIcon() throws Exception { final BatteryDiffEntry entry = createBatteryDiffEntry(mockDrawable); + final int userId = UserHandle.getUserId(1001); + doReturn(mockBadgedDrawable).when(mockUserManager) + .getBadgedIconForUser(mockDrawable, new UserHandle(userId)); entry.mAppIcon = null; - assertThat(entry.getAppIcon()).isEqualTo(mockDrawable); + assertThat(entry.getAppIcon()).isEqualTo(mockBadgedDrawable); assertThat(BatteryDiffEntry.sResourceCache).hasSize(1); // Verifies the app label in the cache. final BatteryEntry.NameAndIcon nameAndIcon = BatteryDiffEntry.sResourceCache.get(entry.mBatteryHistEntry.getKey()); - assertThat(nameAndIcon.icon).isEqualTo(mockDrawable); + assertThat(nameAndIcon.icon).isEqualTo(mockBadgedDrawable); } @Test public void testClearCache_switchLocale_clearCacheIconAndLabel() throws Exception { + final int userId = UserHandle.getUserId(1001); + doReturn(mockBadgedDrawable).when(mockUserManager) + .getBadgedIconForUser(mockDrawable, new UserHandle(userId)); + doReturn(mockDrawable2).when(mockUserManager) + .getBadgedIconForUser(mockDrawable2, new UserHandle(userId)); Locale.setDefault(new Locale("en_US")); final BatteryDiffEntry entry1 = createBatteryDiffEntry(mockDrawable); - assertThat(entry1.getAppIcon()).isEqualTo(mockDrawable); + assertThat(entry1.getAppIcon()).isEqualTo(mockBadgedDrawable); // Switch the locale into another one. Locale.setDefault(new Locale("zh_TW")); @@ -237,6 +247,64 @@ public final class BatteryDiffEntryTest { assertThat(nameAndIcon.icon).isEqualTo(mockDrawable2); } + @Test + public void testIsSystemEntry_userBattery_returnTrue() { + final BatteryDiffEntry entry = + createBatteryDiffEntry( + ConvertUtils.CONSUMER_TYPE_USER_BATTERY, + /*uid=*/ 0, /*isHidden=*/ false); + assertThat(entry.isSystemEntry()).isTrue(); + } + + @Test + public void testIsSystemEntry_systemBattery_returnTrue() { + final BatteryDiffEntry entry = + createBatteryDiffEntry( + ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY, + /*uid=*/ 0, /*isHidden=*/ false); + assertThat(entry.isSystemEntry()).isTrue(); + } + + @Test + public void testIsSystemEntry_uidBattery_returnFalse() { + final BatteryDiffEntry entry = + createBatteryDiffEntry( + ConvertUtils.CONSUMER_TYPE_UID_BATTERY, + /*uid=*/ 123, /*isHidden=*/ false); + assertThat(entry.isSystemEntry()).isFalse(); + } + + @Test + public void testIsSystemEntry_uidBatteryWithHiddenState_returnTrue() { + final BatteryDiffEntry entry = + createBatteryDiffEntry( + ConvertUtils.CONSUMER_TYPE_UID_BATTERY, + /*uid=*/ 123, /*isHidden=*/ true); + assertThat(entry.isSystemEntry()).isTrue(); + } + + @Test + public void testIsSystemEntry_uidBatteryWithSystemProcess_returnTrue() { + final BatteryDiffEntry entry = + createBatteryDiffEntry( + ConvertUtils.CONSUMER_TYPE_UID_BATTERY, + /*uid=*/ 1230, /*isHidden=*/ false); + assertThat(entry.isSystemEntry()).isTrue(); + } + + private BatteryDiffEntry createBatteryDiffEntry( + int consumerType, long uid, boolean isHidden) { + final ContentValues values = getContentValuesWithType(consumerType); + values.put("isHidden", isHidden); + values.put("uid", uid); + return new BatteryDiffEntry( + mContext, + /*foregroundUsageTimeInMs=*/ 0, + /*backgroundUsageTimeInMs=*/ 0, + /*consumePower=*/ 0, + new BatteryHistEntry(values)); + } + private BatteryDiffEntry createBatteryDiffEntry( double consumePower, BatteryHistEntry batteryHistEntry) { final BatteryDiffEntry entry = new BatteryDiffEntry(