Loading res/drawable/ic_battery_uninstalled.xml 0 → 100644 +33 −0 Original line number Diff line number Diff line <!-- Copyright (C) 2023 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. --> <vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="24.0dp" android:height="24.0dp" android:tint="@color/battery_usage_system_icon_color" android:viewportWidth="24.0" android:viewportHeight="24.0"> <path android:fillColor="@android:color/white" android:pathData="M15,4V3H9v1H4v2h1v13c0,1.1 0.9,2 2,2h10c1.1,0 2,-0.9 2,-2V6h1V4H15zM17,19H7V6h10V19z" /> <path android:fillColor="@android:color/white" android:pathData="M9,8h2v9h-2z" /> <path android:fillColor="@android:color/white" android:pathData="M13,8h2v9h-2z" /> </vector> res/values/strings.xml +3 −1 Original line number Diff line number Diff line Loading @@ -5569,6 +5569,8 @@ <string name="battery_usage_since_last_full_charge">since last full charge</string> <!-- Description for system apps aggregated battery usage data [CHAR LIMIT=120] --> <string name="battery_usage_system_apps">System apps</string> <!-- Description for uninstalled apps aggregated battery usage data [CHAR LIMIT=120] --> <string name="battery_usage_uninstalled_apps">Uninstalled apps</string> <!-- Description for others battery usage data [CHAR LIMIT=120] --> <string name="battery_usage_others">Others</string> Loading src/com/android/settings/fuelgauge/batteryusage/BatteryDiffData.java +53 −16 Original line number Diff line number Diff line Loading @@ -131,14 +131,14 @@ public class BatteryDiffData { final PowerUsageFeatureProvider featureProvider, final @NonNull Set<String> systemAppsPackageNames, final @NonNull Set<Integer> systemAppsUids) { combineIntoUninstalledApps(context, mAppEntries); combineIntoSystemApps( context, featureProvider, systemAppsPackageNames, systemAppsUids, mAppEntries); combineSystemItemsIntoOthers(context, featureProvider, mSystemEntries); } private static void purgeBatteryDiffData( final PowerUsageFeatureProvider featureProvider, final List<BatteryDiffEntry> entries) { final PowerUsageFeatureProvider featureProvider, final List<BatteryDiffEntry> entries) { final double screenOnTimeThresholdInMs = featureProvider.getBatteryUsageListScreenOnTimeThresholdInMs(); final double consumePowerThreshold = Loading Loading @@ -178,18 +178,23 @@ public class BatteryDiffData { final Iterator<BatteryDiffEntry> appListIterator = appEntries.iterator(); while (appListIterator.hasNext()) { final BatteryDiffEntry batteryDiffEntry = appListIterator.next(); if (needsCombineInSystemApp(batteryDiffEntry, systemAppsAllowlist, systemAppsPackageNames, systemAppsUids)) { if (needsCombineInSystemApp( batteryDiffEntry, systemAppsAllowlist, systemAppsPackageNames, systemAppsUids)) { if (systemAppsDiffEntry == null) { systemAppsDiffEntry = new BatteryDiffEntry(context, BatteryDiffEntry.SYSTEM_APPS_KEY, BatteryDiffEntry.SYSTEM_APPS_KEY, systemAppsDiffEntry = new BatteryDiffEntry( context, BatteryDiffEntry.SYSTEM_APPS_KEY, BatteryDiffEntry.SYSTEM_APPS_KEY, ConvertUtils.CONSUMER_TYPE_UID_BATTERY); } systemAppsDiffEntry.mConsumePower += batteryDiffEntry.mConsumePower; systemAppsDiffEntry.mForegroundUsageTimeInMs += batteryDiffEntry.mForegroundUsageTimeInMs; systemAppsDiffEntry.setTotalConsumePower( batteryDiffEntry.getTotalConsumePower()); systemAppsDiffEntry.setTotalConsumePower(batteryDiffEntry.getTotalConsumePower()); appListIterator.remove(); } } Loading @@ -198,6 +203,35 @@ public class BatteryDiffData { } } private static void combineIntoUninstalledApps( final Context context, final @NonNull List<BatteryDiffEntry> appEntries) { BatteryDiffEntry uninstalledAppDiffEntry = null; final Iterator<BatteryDiffEntry> appListIterator = appEntries.iterator(); while (appListIterator.hasNext()) { final BatteryDiffEntry batteryDiffEntry = appListIterator.next(); if (!batteryDiffEntry.isUninstalledEntry()) { continue; } if (uninstalledAppDiffEntry == null) { uninstalledAppDiffEntry = new BatteryDiffEntry( context, BatteryDiffEntry.UNINSTALLED_APPS_KEY, BatteryDiffEntry.UNINSTALLED_APPS_KEY, ConvertUtils.CONSUMER_TYPE_UID_BATTERY); } uninstalledAppDiffEntry.mConsumePower += batteryDiffEntry.mConsumePower; uninstalledAppDiffEntry.mForegroundUsageTimeInMs += batteryDiffEntry.mForegroundUsageTimeInMs; uninstalledAppDiffEntry.setTotalConsumePower(batteryDiffEntry.getTotalConsumePower()); appListIterator.remove(); } if (uninstalledAppDiffEntry != null) { appEntries.add(uninstalledAppDiffEntry); } } private static void combineSystemItemsIntoOthers( final Context context, final PowerUsageFeatureProvider featureProvider, Loading @@ -210,17 +244,20 @@ public class BatteryDiffData { while (systemListIterator.hasNext()) { final BatteryDiffEntry batteryDiffEntry = systemListIterator.next(); final int componentId = batteryDiffEntry.mComponentId; if (othersSystemComponentSet.contains(componentId) || ( componentId >= BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID if (othersSystemComponentSet.contains(componentId) || (componentId >= BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID && othersCustomComponentNameSet.contains( batteryDiffEntry.getAppLabel()))) { if (othersDiffEntry == null) { othersDiffEntry = new BatteryDiffEntry(context, BatteryDiffEntry.OTHERS_KEY, BatteryDiffEntry.OTHERS_KEY, ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY); othersDiffEntry = new BatteryDiffEntry( context, BatteryDiffEntry.OTHERS_KEY, BatteryDiffEntry.OTHERS_KEY, ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY); } othersDiffEntry.mConsumePower += batteryDiffEntry.mConsumePower; othersDiffEntry.setTotalConsumePower( batteryDiffEntry.getTotalConsumePower()); othersDiffEntry.setTotalConsumePower(batteryDiffEntry.getTotalConsumePower()); systemListIterator.remove(); } } Loading src/com/android/settings/fuelgauge/batteryusage/BatteryDiffEntry.java +77 −31 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import android.content.pm.PackageManager.NameNotFoundException; import android.graphics.drawable.Drawable; import android.os.UserHandle; import android.os.UserManager; import android.text.TextUtils; import android.util.Log; import android.util.Pair; Loading @@ -43,21 +44,32 @@ public class BatteryDiffEntry { static Locale sCurrentLocale = null; // Caches app label and icon to improve loading performance. static final Map<String, BatteryEntry.NameAndIcon> sResourceCache = new HashMap<>(); // Whether a specific item is valid to launch restriction page? @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE) static final Map<String, Boolean> sValidForRestriction = new HashMap<>(); /** A comparator for {@link BatteryDiffEntry} based on the sorting key. */ static final Comparator<BatteryDiffEntry> COMPARATOR = (a, b) -> Double.compare(b.getSortingKey(), a.getSortingKey()); static final String SYSTEM_APPS_KEY = "A|SystemApps"; static final String UNINSTALLED_APPS_KEY = "A|UninstalledApps"; static final String OTHERS_KEY = "S|Others"; // key -> (label_id, icon_id) private static final Map<String, Pair<Integer, Integer>> SPECIAL_ENTRY_MAP = Map.of( private static final Map<String, Pair<Integer, Integer>> SPECIAL_ENTRY_MAP = Map.of( SYSTEM_APPS_KEY, Pair.create(R.string.battery_usage_system_apps, R.drawable.ic_power_system), Pair.create( R.string.battery_usage_system_apps, R.drawable.ic_power_system), UNINSTALLED_APPS_KEY, Pair.create( R.string.battery_usage_uninstalled_apps, R.drawable.ic_battery_uninstalled), OTHERS_KEY, Pair.create(R.string.battery_usage_others, Pair.create( R.string.battery_usage_others, R.drawable.ic_settings_battery_usage_others)); public long mUid; Loading Loading @@ -146,8 +158,7 @@ public class BatteryDiffEntry { /** Sets the total consumed power in a specific time slot. */ public void setTotalConsumePower(double totalConsumePower) { mTotalConsumePower = totalConsumePower; mPercentage = totalConsumePower == 0 ? 0 : (mConsumePower / mTotalConsumePower) * 100.0; mPercentage = totalConsumePower == 0 ? 0 : (mConsumePower / mTotalConsumePower) * 100.0; mAdjustPercentageOffset = 0; } Loading @@ -173,8 +184,21 @@ public class BatteryDiffEntry { /** Gets the key for sorting */ public double getSortingKey() { return getKey() != null && SPECIAL_ENTRY_MAP.containsKey(getKey()) ? -1 : getPercentage() + getAdjustPercentageOffset(); String key = getKey(); if (key == null) { return getPercentage() + getAdjustPercentageOffset(); } // For special entries, put them to the end of the list. switch (key) { case UNINSTALLED_APPS_KEY: case OTHERS_KEY: return -1; case SYSTEM_APPS_KEY: return -2; default: return getPercentage() + getAdjustPercentageOffset(); } } /** Clones a new instance. */ Loading Loading @@ -222,8 +246,8 @@ public class BatteryDiffEntry { /** Gets the searching package name for UID battery type. */ public String getPackageName() { final String packageName = mDefaultPackageName != null ? mDefaultPackageName : mLegacyPackageName; final String packageName = mDefaultPackageName != null ? mDefaultPackageName : mLegacyPackageName; if (packageName == null) { return packageName; } Loading @@ -231,7 +255,8 @@ public class BatteryDiffEntry { // From "com.opera.browser:privileged_process0" to "com.opera.browser" final String[] splitPackageNames = packageName.split(":"); return splitPackageNames != null && splitPackageNames.length > 0 ? splitPackageNames[0] : packageName; ? splitPackageNames[0] : packageName; } /** Whether this item is valid for users to launch restriction page? */ Loading @@ -255,6 +280,17 @@ public class BatteryDiffEntry { } } /** Whether the current BatteryDiffEntry is uninstalled app or not. */ public boolean isUninstalledEntry() { final String packageName = getPackageName(); if (TextUtils.isEmpty(packageName) || isSystemEntry()) { return false; } final int uid = BatteryUtils.getInstance(mContext).getPackageUid(packageName); return uid == BatteryUtils.UID_REMOVED_APPS || uid == BatteryUtils.UID_NULL; } void loadLabelAndIcon() { if (mIsLoaded) { return; Loading Loading @@ -286,8 +322,7 @@ public class BatteryDiffEntry { mAppIconId = pair.second; mAppIcon = mContext.getDrawable(mAppIconId); sResourceCache.put( getKey(), new BatteryEntry.NameAndIcon(mAppLabel, mAppIcon, mAppIconId)); getKey(), new BatteryEntry.NameAndIcon(mAppLabel, mAppIcon, mAppIconId)); return; } Loading Loading @@ -354,7 +389,8 @@ public class BatteryDiffEntry { } try { mValidForRestriction = mContext.getPackageManager().getPackageInfo( mContext.getPackageManager() .getPackageInfo( getPackageName(), PackageManager.MATCH_DISABLED_COMPONENTS | PackageManager.MATCH_ANY_USER Loading @@ -362,7 +398,10 @@ public class BatteryDiffEntry { | PackageManager.GET_PERMISSIONS) != null; } catch (Exception e) { Log.e(TAG, String.format("getPackageInfo() error %s for package=%s", Log.e( TAG, String.format( "getPackageInfo() error %s for package=%s", e.getCause(), getPackageName())); mValidForRestriction = false; } Loading @@ -371,7 +410,10 @@ public class BatteryDiffEntry { private BatteryEntry.NameAndIcon getCache() { final Locale locale = Locale.getDefault(); if (sCurrentLocale != locale) { Log.d(TAG, String.format("clearCache() locale is changed from %s to %s", Log.d( TAG, String.format( "clearCache() locale is changed from %s to %s", sCurrentLocale, locale)); sCurrentLocale = locale; clearCache(); Loading Loading @@ -421,7 +463,10 @@ public class BatteryDiffEntry { mDefaultPackageName = nameAndIcon.mPackageName; if (mDefaultPackageName != null && !mDefaultPackageName.equals(nameAndIcon.mPackageName)) { Log.w(TAG, String.format("found different package: %s | %s", Log.w( TAG, String.format( "found different package: %s | %s", mDefaultPackageName, nameAndIcon.mPackageName)); } } Loading Loading @@ -459,7 +504,8 @@ public class BatteryDiffEntry { private Drawable getBadgeIconForUser(Drawable icon) { final int userId = UserHandle.getUserId((int) mUid); return userId == UserHandle.USER_OWNER ? icon : mUserManager.getBadgedIconForUser(icon, new UserHandle(userId)); return userId == UserHandle.USER_OWNER ? icon : mUserManager.getBadgedIconForUser(icon, new UserHandle(userId)); } } tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryDiffDataTest.java +98 −37 Original line number Diff line number Diff line Loading @@ -62,7 +62,8 @@ public class BatteryDiffDataTest { final BatteryDiffEntry hiddenDiffEntry = createBatteryDiffEntry(mContext, /* consumePower= */ 0, /* isHidden= */ true); final boolean needsCombineInSystemApp = BatteryDiffData.needsCombineInSystemApp( final boolean needsCombineInSystemApp = BatteryDiffData.needsCombineInSystemApp( hiddenDiffEntry, List.of(), Set.of(), Set.of()); assertThat(needsCombineInSystemApp).isTrue(); Loading @@ -76,8 +77,12 @@ public class BatteryDiffDataTest { mAppEntry.info = mApplicationInfo; mApplicationInfo.flags = ApplicationInfo.FLAG_SYSTEM; final boolean needsCombineInSystemApp = BatteryDiffData.needsCombineInSystemApp( batteryDiffEntry, List.of(), Set.of(ConvertUtils.FAKE_PACKAGE_NAME), Set.of()); final boolean needsCombineInSystemApp = BatteryDiffData.needsCombineInSystemApp( batteryDiffEntry, List.of(), Set.of(ConvertUtils.FAKE_PACKAGE_NAME), Set.of()); assertThat(needsCombineInSystemApp).isTrue(); } Loading @@ -90,7 +95,8 @@ public class BatteryDiffDataTest { mAppEntry.info = mApplicationInfo; mApplicationInfo.flags = 0; final boolean needsCombineInSystemApp = BatteryDiffData.needsCombineInSystemApp( final boolean needsCombineInSystemApp = BatteryDiffData.needsCombineInSystemApp( batteryDiffEntry, List.of(), Set.of(), Set.of()); assertThat(needsCombineInSystemApp).isFalse(); Loading Loading @@ -136,20 +142,69 @@ public class BatteryDiffDataTest { assertThat(batteryDiffEntries.get(2).getAdjustPercentageOffset()).isEqualTo(0); } @Test public void processPercentsAndSort_uninstalledApps_sortAsExpected() { List<BatteryDiffEntry> batteryDiffEntries = new ArrayList<>(); batteryDiffEntries.add( createBatteryDiffEntry(mContext, /* consumePower= */ 28.5, /* key= */ "APP_1")); batteryDiffEntries.add( createBatteryDiffEntry( mContext, /* consumePower= */ 20, BatteryDiffEntry.UNINSTALLED_APPS_KEY)); batteryDiffEntries.add( createBatteryDiffEntry(mContext, /* consumePower= */ 3, /* key= */ "APP_2")); batteryDiffEntries.add( createBatteryDiffEntry( mContext, /* consumePower= */ 28.5, BatteryDiffEntry.SYSTEM_APPS_KEY)); batteryDiffEntries.add( createBatteryDiffEntry(mContext, /* consumePower= */ 20, /* key= */ "APP_3")); BatteryDiffData.processAndSortEntries(batteryDiffEntries); assertThat(batteryDiffEntries.get(0).getKey()).isEqualTo("APP_1"); assertThat(batteryDiffEntries.get(1).getKey()).isEqualTo("APP_3"); assertThat(batteryDiffEntries.get(2).getKey()).isEqualTo("APP_2"); assertThat(batteryDiffEntries.get(3).getKey()) .isEqualTo(BatteryDiffEntry.UNINSTALLED_APPS_KEY); assertThat(batteryDiffEntries.get(4).getKey()).isEqualTo(BatteryDiffEntry.SYSTEM_APPS_KEY); } private static BatteryDiffEntry createBatteryDiffEntry( Context context, double consumePower, boolean isHidden) { return createBatteryDiffEntry(context, consumePower, isHidden, /* key= */ null); } private static BatteryDiffEntry createBatteryDiffEntry( Context context, double consumePower, String key) { return createBatteryDiffEntry(context, consumePower, /* isHidden= */ false, key); } private static BatteryDiffEntry createBatteryDiffEntry( Context context, double consumePower, boolean isHidden, String key) { final int currentUserId = context.getUserId(); final BatteryHistEntry batteryHistEntry = createBatteryHistEntry( ConvertUtils.FAKE_PACKAGE_NAME, "fake_label", consumePower, /*foregroundUsageConsumePower=*/ 0, /*foregroundServiceUsageConsumePower=*/ 0, /*backgroundUsageConsumePower=*/ 0, /*cachedUsageConsumePower=*/ 0, /*uid=*/ 0L, currentUserId, ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 0L, /*backgroundUsageTimeInMs=*/ 0L, isHidden); final BatteryHistEntry batteryHistEntry = createBatteryHistEntry( ConvertUtils.FAKE_PACKAGE_NAME, "fake_label", consumePower, /* foregroundUsageConsumePower= */ 0, /* foregroundServiceUsageConsumePower= */ 0, /* backgroundUsageConsumePower= */ 0, /* cachedUsageConsumePower= */ 0, /* uid= */ 0L, currentUserId, ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /* foregroundUsageTimeInMs= */ 0L, /* backgroundUsageTimeInMs= */ 0L, isHidden); return new BatteryDiffEntry( context, batteryHistEntry.mUid, batteryHistEntry.mUserId, batteryHistEntry.getKey(), key == null ? batteryHistEntry.getKey() : key, batteryHistEntry.mIsHidden, batteryHistEntry.mDrainType, batteryHistEntry.mPackageName, Loading @@ -158,7 +213,7 @@ public class BatteryDiffDataTest { /* foregroundUsageTimeInMs= */ 0, /* backgroundUsageTimeInMs= */ 0, /* screenOnTimeInMs= */ 0, /*consumePower=*/ consumePower, consumePower, /* foregroundUsageConsumePower= */ 0, /* foregroundServiceUsageConsumePower= */ 0, /* backgroundUsageConsumePower= */ 0, Loading @@ -166,17 +221,22 @@ public class BatteryDiffDataTest { } private static BatteryHistEntry createBatteryHistEntry( final String packageName, final String appLabel, final double consumePower, final String packageName, final String appLabel, final double consumePower, final double foregroundUsageConsumePower, final double foregroundServiceUsageConsumePower, final double backgroundUsageConsumePower, final double cachedUsageConsumePower, final long uid, final long userId, final int consumerType, final long foregroundUsageTimeInMs, final long backgroundUsageTimeInMs, final double backgroundUsageConsumePower, final double cachedUsageConsumePower, final long uid, final long userId, final int consumerType, final long foregroundUsageTimeInMs, final long backgroundUsageTimeInMs, final boolean isHidden) { // Only insert required fields. final BatteryInformation batteryInformation = BatteryInformation .newBuilder() BatteryInformation.newBuilder() .setAppLabel(appLabel) .setConsumePower(consumePower) .setForegroundUsageConsumePower(foregroundUsageConsumePower) Loading @@ -192,7 +252,8 @@ public class BatteryDiffDataTest { values.put(BatteryHistEntry.KEY_UID, uid); values.put(BatteryHistEntry.KEY_USER_ID, userId); values.put(BatteryHistEntry.KEY_CONSUMER_TYPE, consumerType); values.put(BatteryHistEntry.KEY_BATTERY_INFORMATION, values.put( BatteryHistEntry.KEY_BATTERY_INFORMATION, ConvertUtils.convertBatteryInformationToString(batteryInformation)); return new BatteryHistEntry(values); } Loading Loading
res/drawable/ic_battery_uninstalled.xml 0 → 100644 +33 −0 Original line number Diff line number Diff line <!-- Copyright (C) 2023 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. --> <vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="24.0dp" android:height="24.0dp" android:tint="@color/battery_usage_system_icon_color" android:viewportWidth="24.0" android:viewportHeight="24.0"> <path android:fillColor="@android:color/white" android:pathData="M15,4V3H9v1H4v2h1v13c0,1.1 0.9,2 2,2h10c1.1,0 2,-0.9 2,-2V6h1V4H15zM17,19H7V6h10V19z" /> <path android:fillColor="@android:color/white" android:pathData="M9,8h2v9h-2z" /> <path android:fillColor="@android:color/white" android:pathData="M13,8h2v9h-2z" /> </vector>
res/values/strings.xml +3 −1 Original line number Diff line number Diff line Loading @@ -5569,6 +5569,8 @@ <string name="battery_usage_since_last_full_charge">since last full charge</string> <!-- Description for system apps aggregated battery usage data [CHAR LIMIT=120] --> <string name="battery_usage_system_apps">System apps</string> <!-- Description for uninstalled apps aggregated battery usage data [CHAR LIMIT=120] --> <string name="battery_usage_uninstalled_apps">Uninstalled apps</string> <!-- Description for others battery usage data [CHAR LIMIT=120] --> <string name="battery_usage_others">Others</string> Loading
src/com/android/settings/fuelgauge/batteryusage/BatteryDiffData.java +53 −16 Original line number Diff line number Diff line Loading @@ -131,14 +131,14 @@ public class BatteryDiffData { final PowerUsageFeatureProvider featureProvider, final @NonNull Set<String> systemAppsPackageNames, final @NonNull Set<Integer> systemAppsUids) { combineIntoUninstalledApps(context, mAppEntries); combineIntoSystemApps( context, featureProvider, systemAppsPackageNames, systemAppsUids, mAppEntries); combineSystemItemsIntoOthers(context, featureProvider, mSystemEntries); } private static void purgeBatteryDiffData( final PowerUsageFeatureProvider featureProvider, final List<BatteryDiffEntry> entries) { final PowerUsageFeatureProvider featureProvider, final List<BatteryDiffEntry> entries) { final double screenOnTimeThresholdInMs = featureProvider.getBatteryUsageListScreenOnTimeThresholdInMs(); final double consumePowerThreshold = Loading Loading @@ -178,18 +178,23 @@ public class BatteryDiffData { final Iterator<BatteryDiffEntry> appListIterator = appEntries.iterator(); while (appListIterator.hasNext()) { final BatteryDiffEntry batteryDiffEntry = appListIterator.next(); if (needsCombineInSystemApp(batteryDiffEntry, systemAppsAllowlist, systemAppsPackageNames, systemAppsUids)) { if (needsCombineInSystemApp( batteryDiffEntry, systemAppsAllowlist, systemAppsPackageNames, systemAppsUids)) { if (systemAppsDiffEntry == null) { systemAppsDiffEntry = new BatteryDiffEntry(context, BatteryDiffEntry.SYSTEM_APPS_KEY, BatteryDiffEntry.SYSTEM_APPS_KEY, systemAppsDiffEntry = new BatteryDiffEntry( context, BatteryDiffEntry.SYSTEM_APPS_KEY, BatteryDiffEntry.SYSTEM_APPS_KEY, ConvertUtils.CONSUMER_TYPE_UID_BATTERY); } systemAppsDiffEntry.mConsumePower += batteryDiffEntry.mConsumePower; systemAppsDiffEntry.mForegroundUsageTimeInMs += batteryDiffEntry.mForegroundUsageTimeInMs; systemAppsDiffEntry.setTotalConsumePower( batteryDiffEntry.getTotalConsumePower()); systemAppsDiffEntry.setTotalConsumePower(batteryDiffEntry.getTotalConsumePower()); appListIterator.remove(); } } Loading @@ -198,6 +203,35 @@ public class BatteryDiffData { } } private static void combineIntoUninstalledApps( final Context context, final @NonNull List<BatteryDiffEntry> appEntries) { BatteryDiffEntry uninstalledAppDiffEntry = null; final Iterator<BatteryDiffEntry> appListIterator = appEntries.iterator(); while (appListIterator.hasNext()) { final BatteryDiffEntry batteryDiffEntry = appListIterator.next(); if (!batteryDiffEntry.isUninstalledEntry()) { continue; } if (uninstalledAppDiffEntry == null) { uninstalledAppDiffEntry = new BatteryDiffEntry( context, BatteryDiffEntry.UNINSTALLED_APPS_KEY, BatteryDiffEntry.UNINSTALLED_APPS_KEY, ConvertUtils.CONSUMER_TYPE_UID_BATTERY); } uninstalledAppDiffEntry.mConsumePower += batteryDiffEntry.mConsumePower; uninstalledAppDiffEntry.mForegroundUsageTimeInMs += batteryDiffEntry.mForegroundUsageTimeInMs; uninstalledAppDiffEntry.setTotalConsumePower(batteryDiffEntry.getTotalConsumePower()); appListIterator.remove(); } if (uninstalledAppDiffEntry != null) { appEntries.add(uninstalledAppDiffEntry); } } private static void combineSystemItemsIntoOthers( final Context context, final PowerUsageFeatureProvider featureProvider, Loading @@ -210,17 +244,20 @@ public class BatteryDiffData { while (systemListIterator.hasNext()) { final BatteryDiffEntry batteryDiffEntry = systemListIterator.next(); final int componentId = batteryDiffEntry.mComponentId; if (othersSystemComponentSet.contains(componentId) || ( componentId >= BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID if (othersSystemComponentSet.contains(componentId) || (componentId >= BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID && othersCustomComponentNameSet.contains( batteryDiffEntry.getAppLabel()))) { if (othersDiffEntry == null) { othersDiffEntry = new BatteryDiffEntry(context, BatteryDiffEntry.OTHERS_KEY, BatteryDiffEntry.OTHERS_KEY, ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY); othersDiffEntry = new BatteryDiffEntry( context, BatteryDiffEntry.OTHERS_KEY, BatteryDiffEntry.OTHERS_KEY, ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY); } othersDiffEntry.mConsumePower += batteryDiffEntry.mConsumePower; othersDiffEntry.setTotalConsumePower( batteryDiffEntry.getTotalConsumePower()); othersDiffEntry.setTotalConsumePower(batteryDiffEntry.getTotalConsumePower()); systemListIterator.remove(); } } Loading
src/com/android/settings/fuelgauge/batteryusage/BatteryDiffEntry.java +77 −31 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import android.content.pm.PackageManager.NameNotFoundException; import android.graphics.drawable.Drawable; import android.os.UserHandle; import android.os.UserManager; import android.text.TextUtils; import android.util.Log; import android.util.Pair; Loading @@ -43,21 +44,32 @@ public class BatteryDiffEntry { static Locale sCurrentLocale = null; // Caches app label and icon to improve loading performance. static final Map<String, BatteryEntry.NameAndIcon> sResourceCache = new HashMap<>(); // Whether a specific item is valid to launch restriction page? @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE) static final Map<String, Boolean> sValidForRestriction = new HashMap<>(); /** A comparator for {@link BatteryDiffEntry} based on the sorting key. */ static final Comparator<BatteryDiffEntry> COMPARATOR = (a, b) -> Double.compare(b.getSortingKey(), a.getSortingKey()); static final String SYSTEM_APPS_KEY = "A|SystemApps"; static final String UNINSTALLED_APPS_KEY = "A|UninstalledApps"; static final String OTHERS_KEY = "S|Others"; // key -> (label_id, icon_id) private static final Map<String, Pair<Integer, Integer>> SPECIAL_ENTRY_MAP = Map.of( private static final Map<String, Pair<Integer, Integer>> SPECIAL_ENTRY_MAP = Map.of( SYSTEM_APPS_KEY, Pair.create(R.string.battery_usage_system_apps, R.drawable.ic_power_system), Pair.create( R.string.battery_usage_system_apps, R.drawable.ic_power_system), UNINSTALLED_APPS_KEY, Pair.create( R.string.battery_usage_uninstalled_apps, R.drawable.ic_battery_uninstalled), OTHERS_KEY, Pair.create(R.string.battery_usage_others, Pair.create( R.string.battery_usage_others, R.drawable.ic_settings_battery_usage_others)); public long mUid; Loading Loading @@ -146,8 +158,7 @@ public class BatteryDiffEntry { /** Sets the total consumed power in a specific time slot. */ public void setTotalConsumePower(double totalConsumePower) { mTotalConsumePower = totalConsumePower; mPercentage = totalConsumePower == 0 ? 0 : (mConsumePower / mTotalConsumePower) * 100.0; mPercentage = totalConsumePower == 0 ? 0 : (mConsumePower / mTotalConsumePower) * 100.0; mAdjustPercentageOffset = 0; } Loading @@ -173,8 +184,21 @@ public class BatteryDiffEntry { /** Gets the key for sorting */ public double getSortingKey() { return getKey() != null && SPECIAL_ENTRY_MAP.containsKey(getKey()) ? -1 : getPercentage() + getAdjustPercentageOffset(); String key = getKey(); if (key == null) { return getPercentage() + getAdjustPercentageOffset(); } // For special entries, put them to the end of the list. switch (key) { case UNINSTALLED_APPS_KEY: case OTHERS_KEY: return -1; case SYSTEM_APPS_KEY: return -2; default: return getPercentage() + getAdjustPercentageOffset(); } } /** Clones a new instance. */ Loading Loading @@ -222,8 +246,8 @@ public class BatteryDiffEntry { /** Gets the searching package name for UID battery type. */ public String getPackageName() { final String packageName = mDefaultPackageName != null ? mDefaultPackageName : mLegacyPackageName; final String packageName = mDefaultPackageName != null ? mDefaultPackageName : mLegacyPackageName; if (packageName == null) { return packageName; } Loading @@ -231,7 +255,8 @@ public class BatteryDiffEntry { // From "com.opera.browser:privileged_process0" to "com.opera.browser" final String[] splitPackageNames = packageName.split(":"); return splitPackageNames != null && splitPackageNames.length > 0 ? splitPackageNames[0] : packageName; ? splitPackageNames[0] : packageName; } /** Whether this item is valid for users to launch restriction page? */ Loading @@ -255,6 +280,17 @@ public class BatteryDiffEntry { } } /** Whether the current BatteryDiffEntry is uninstalled app or not. */ public boolean isUninstalledEntry() { final String packageName = getPackageName(); if (TextUtils.isEmpty(packageName) || isSystemEntry()) { return false; } final int uid = BatteryUtils.getInstance(mContext).getPackageUid(packageName); return uid == BatteryUtils.UID_REMOVED_APPS || uid == BatteryUtils.UID_NULL; } void loadLabelAndIcon() { if (mIsLoaded) { return; Loading Loading @@ -286,8 +322,7 @@ public class BatteryDiffEntry { mAppIconId = pair.second; mAppIcon = mContext.getDrawable(mAppIconId); sResourceCache.put( getKey(), new BatteryEntry.NameAndIcon(mAppLabel, mAppIcon, mAppIconId)); getKey(), new BatteryEntry.NameAndIcon(mAppLabel, mAppIcon, mAppIconId)); return; } Loading Loading @@ -354,7 +389,8 @@ public class BatteryDiffEntry { } try { mValidForRestriction = mContext.getPackageManager().getPackageInfo( mContext.getPackageManager() .getPackageInfo( getPackageName(), PackageManager.MATCH_DISABLED_COMPONENTS | PackageManager.MATCH_ANY_USER Loading @@ -362,7 +398,10 @@ public class BatteryDiffEntry { | PackageManager.GET_PERMISSIONS) != null; } catch (Exception e) { Log.e(TAG, String.format("getPackageInfo() error %s for package=%s", Log.e( TAG, String.format( "getPackageInfo() error %s for package=%s", e.getCause(), getPackageName())); mValidForRestriction = false; } Loading @@ -371,7 +410,10 @@ public class BatteryDiffEntry { private BatteryEntry.NameAndIcon getCache() { final Locale locale = Locale.getDefault(); if (sCurrentLocale != locale) { Log.d(TAG, String.format("clearCache() locale is changed from %s to %s", Log.d( TAG, String.format( "clearCache() locale is changed from %s to %s", sCurrentLocale, locale)); sCurrentLocale = locale; clearCache(); Loading Loading @@ -421,7 +463,10 @@ public class BatteryDiffEntry { mDefaultPackageName = nameAndIcon.mPackageName; if (mDefaultPackageName != null && !mDefaultPackageName.equals(nameAndIcon.mPackageName)) { Log.w(TAG, String.format("found different package: %s | %s", Log.w( TAG, String.format( "found different package: %s | %s", mDefaultPackageName, nameAndIcon.mPackageName)); } } Loading Loading @@ -459,7 +504,8 @@ public class BatteryDiffEntry { private Drawable getBadgeIconForUser(Drawable icon) { final int userId = UserHandle.getUserId((int) mUid); return userId == UserHandle.USER_OWNER ? icon : mUserManager.getBadgedIconForUser(icon, new UserHandle(userId)); return userId == UserHandle.USER_OWNER ? icon : mUserManager.getBadgedIconForUser(icon, new UserHandle(userId)); } }
tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryDiffDataTest.java +98 −37 Original line number Diff line number Diff line Loading @@ -62,7 +62,8 @@ public class BatteryDiffDataTest { final BatteryDiffEntry hiddenDiffEntry = createBatteryDiffEntry(mContext, /* consumePower= */ 0, /* isHidden= */ true); final boolean needsCombineInSystemApp = BatteryDiffData.needsCombineInSystemApp( final boolean needsCombineInSystemApp = BatteryDiffData.needsCombineInSystemApp( hiddenDiffEntry, List.of(), Set.of(), Set.of()); assertThat(needsCombineInSystemApp).isTrue(); Loading @@ -76,8 +77,12 @@ public class BatteryDiffDataTest { mAppEntry.info = mApplicationInfo; mApplicationInfo.flags = ApplicationInfo.FLAG_SYSTEM; final boolean needsCombineInSystemApp = BatteryDiffData.needsCombineInSystemApp( batteryDiffEntry, List.of(), Set.of(ConvertUtils.FAKE_PACKAGE_NAME), Set.of()); final boolean needsCombineInSystemApp = BatteryDiffData.needsCombineInSystemApp( batteryDiffEntry, List.of(), Set.of(ConvertUtils.FAKE_PACKAGE_NAME), Set.of()); assertThat(needsCombineInSystemApp).isTrue(); } Loading @@ -90,7 +95,8 @@ public class BatteryDiffDataTest { mAppEntry.info = mApplicationInfo; mApplicationInfo.flags = 0; final boolean needsCombineInSystemApp = BatteryDiffData.needsCombineInSystemApp( final boolean needsCombineInSystemApp = BatteryDiffData.needsCombineInSystemApp( batteryDiffEntry, List.of(), Set.of(), Set.of()); assertThat(needsCombineInSystemApp).isFalse(); Loading Loading @@ -136,20 +142,69 @@ public class BatteryDiffDataTest { assertThat(batteryDiffEntries.get(2).getAdjustPercentageOffset()).isEqualTo(0); } @Test public void processPercentsAndSort_uninstalledApps_sortAsExpected() { List<BatteryDiffEntry> batteryDiffEntries = new ArrayList<>(); batteryDiffEntries.add( createBatteryDiffEntry(mContext, /* consumePower= */ 28.5, /* key= */ "APP_1")); batteryDiffEntries.add( createBatteryDiffEntry( mContext, /* consumePower= */ 20, BatteryDiffEntry.UNINSTALLED_APPS_KEY)); batteryDiffEntries.add( createBatteryDiffEntry(mContext, /* consumePower= */ 3, /* key= */ "APP_2")); batteryDiffEntries.add( createBatteryDiffEntry( mContext, /* consumePower= */ 28.5, BatteryDiffEntry.SYSTEM_APPS_KEY)); batteryDiffEntries.add( createBatteryDiffEntry(mContext, /* consumePower= */ 20, /* key= */ "APP_3")); BatteryDiffData.processAndSortEntries(batteryDiffEntries); assertThat(batteryDiffEntries.get(0).getKey()).isEqualTo("APP_1"); assertThat(batteryDiffEntries.get(1).getKey()).isEqualTo("APP_3"); assertThat(batteryDiffEntries.get(2).getKey()).isEqualTo("APP_2"); assertThat(batteryDiffEntries.get(3).getKey()) .isEqualTo(BatteryDiffEntry.UNINSTALLED_APPS_KEY); assertThat(batteryDiffEntries.get(4).getKey()).isEqualTo(BatteryDiffEntry.SYSTEM_APPS_KEY); } private static BatteryDiffEntry createBatteryDiffEntry( Context context, double consumePower, boolean isHidden) { return createBatteryDiffEntry(context, consumePower, isHidden, /* key= */ null); } private static BatteryDiffEntry createBatteryDiffEntry( Context context, double consumePower, String key) { return createBatteryDiffEntry(context, consumePower, /* isHidden= */ false, key); } private static BatteryDiffEntry createBatteryDiffEntry( Context context, double consumePower, boolean isHidden, String key) { final int currentUserId = context.getUserId(); final BatteryHistEntry batteryHistEntry = createBatteryHistEntry( ConvertUtils.FAKE_PACKAGE_NAME, "fake_label", consumePower, /*foregroundUsageConsumePower=*/ 0, /*foregroundServiceUsageConsumePower=*/ 0, /*backgroundUsageConsumePower=*/ 0, /*cachedUsageConsumePower=*/ 0, /*uid=*/ 0L, currentUserId, ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 0L, /*backgroundUsageTimeInMs=*/ 0L, isHidden); final BatteryHistEntry batteryHistEntry = createBatteryHistEntry( ConvertUtils.FAKE_PACKAGE_NAME, "fake_label", consumePower, /* foregroundUsageConsumePower= */ 0, /* foregroundServiceUsageConsumePower= */ 0, /* backgroundUsageConsumePower= */ 0, /* cachedUsageConsumePower= */ 0, /* uid= */ 0L, currentUserId, ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /* foregroundUsageTimeInMs= */ 0L, /* backgroundUsageTimeInMs= */ 0L, isHidden); return new BatteryDiffEntry( context, batteryHistEntry.mUid, batteryHistEntry.mUserId, batteryHistEntry.getKey(), key == null ? batteryHistEntry.getKey() : key, batteryHistEntry.mIsHidden, batteryHistEntry.mDrainType, batteryHistEntry.mPackageName, Loading @@ -158,7 +213,7 @@ public class BatteryDiffDataTest { /* foregroundUsageTimeInMs= */ 0, /* backgroundUsageTimeInMs= */ 0, /* screenOnTimeInMs= */ 0, /*consumePower=*/ consumePower, consumePower, /* foregroundUsageConsumePower= */ 0, /* foregroundServiceUsageConsumePower= */ 0, /* backgroundUsageConsumePower= */ 0, Loading @@ -166,17 +221,22 @@ public class BatteryDiffDataTest { } private static BatteryHistEntry createBatteryHistEntry( final String packageName, final String appLabel, final double consumePower, final String packageName, final String appLabel, final double consumePower, final double foregroundUsageConsumePower, final double foregroundServiceUsageConsumePower, final double backgroundUsageConsumePower, final double cachedUsageConsumePower, final long uid, final long userId, final int consumerType, final long foregroundUsageTimeInMs, final long backgroundUsageTimeInMs, final double backgroundUsageConsumePower, final double cachedUsageConsumePower, final long uid, final long userId, final int consumerType, final long foregroundUsageTimeInMs, final long backgroundUsageTimeInMs, final boolean isHidden) { // Only insert required fields. final BatteryInformation batteryInformation = BatteryInformation .newBuilder() BatteryInformation.newBuilder() .setAppLabel(appLabel) .setConsumePower(consumePower) .setForegroundUsageConsumePower(foregroundUsageConsumePower) Loading @@ -192,7 +252,8 @@ public class BatteryDiffDataTest { values.put(BatteryHistEntry.KEY_UID, uid); values.put(BatteryHistEntry.KEY_USER_ID, userId); values.put(BatteryHistEntry.KEY_CONSUMER_TYPE, consumerType); values.put(BatteryHistEntry.KEY_BATTERY_INFORMATION, values.put( BatteryHistEntry.KEY_BATTERY_INFORMATION, ConvertUtils.convertBatteryInformationToString(batteryInformation)); return new BatteryHistEntry(values); } Loading