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

Commit 0e5688a4 authored by Jun Lan's avatar Jun Lan Committed by Android (Google) Code Review
Browse files

Merge "Fix uninstalled app issue on battery usage page" into main

parents 73baa330 c617e3c6
Loading
Loading
Loading
Loading
+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>
+3 −1
Original line number Diff line number Diff line
@@ -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>
+53 −16
Original line number Diff line number Diff line
@@ -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 =
@@ -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();
            }
        }
@@ -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,
@@ -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();
            }
        }
+77 −31
Original line number Diff line number Diff line
@@ -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;

@@ -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;
@@ -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;
    }

@@ -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. */
@@ -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;
        }
@@ -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? */
@@ -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;
@@ -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;
        }

@@ -354,7 +389,8 @@ public class BatteryDiffEntry {
        }
        try {
            mValidForRestriction =
                    mContext.getPackageManager().getPackageInfo(
                    mContext.getPackageManager()
                                    .getPackageInfo(
                                            getPackageName(),
                                            PackageManager.MATCH_DISABLED_COMPONENTS
                                                    | PackageManager.MATCH_ANY_USER
@@ -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;
        }
@@ -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();
@@ -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));
            }
        }
@@ -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));
    }
}
+98 −37
Original line number Diff line number Diff line
@@ -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();
@@ -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();
    }
@@ -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();
@@ -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,
@@ -158,7 +213,7 @@ public class BatteryDiffDataTest {
                /* foregroundUsageTimeInMs= */ 0,
                /* backgroundUsageTimeInMs= */ 0,
                /* screenOnTimeInMs= */ 0,
                /*consumePower=*/ consumePower,
                consumePower,
                /* foregroundUsageConsumePower= */ 0,
                /* foregroundServiceUsageConsumePower= */ 0,
                /* backgroundUsageConsumePower= */ 0,
@@ -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)
@@ -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