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

Commit 59da7ab7 authored by ykhung's avatar ykhung Committed by YUKAI HUNG
Browse files

Load application icon and label for UID battery consumer type

Bug: 185187669
Test: make SettingsRoboTests
Test: make SettingsGoogleRoboTests
Change-Id: Idb77a1bd48f7f4b66b86ff12c166a204d17bd9ec
parent 42f81804
Loading
Loading
Loading
Loading
+68 −6
Original line number Diff line number Diff line
@@ -22,6 +22,8 @@ import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.drawable.Drawable;
import android.util.Log;

import androidx.annotation.VisibleForTesting;

import java.time.Duration;
import java.util.Comparator;

@@ -42,9 +44,11 @@ public final class BatteryDiffEntry {
    private double mPercentOfTotal;

    private Context mContext;
    private String mAppLabel = null;
    private Drawable mAppIcon = null;
    private boolean mIsLoaded = false;
    private String mDefaultPackageName = null;

    @VisibleForTesting String mAppLabel = null;
    @VisibleForTesting Drawable mAppIcon = null;
    @VisibleForTesting boolean mIsLoaded = false;

    public BatteryDiffEntry(
            Context context,
@@ -84,14 +88,29 @@ public final class BatteryDiffEntry {
    /** Gets the app label name for this entry. */
    public String getAppLabel() {
        loadLabelAndIcon();
        return mAppLabel;
        // Returns default applicationn label if we cannot find it.
        return mAppLabel == null || mAppLabel.length() == 0
            ? mBatteryHistEntry.mAppLabel
            : mAppLabel;
    }

    /** Gets the app icon {@link Drawable} for this entry. */
    public Drawable getAppIcon() {
        loadLabelAndIcon();
        if (mBatteryHistEntry.mConsumerType !=
                ConvertUtils.CONSUMER_TYPE_UID_BATTERY) {
            return mAppIcon;
        }
        // Returns default application icon if UID_BATTERY icon is null.
        return mAppIcon == null
            ? mContext.getPackageManager().getDefaultActivityIcon()
            : mAppIcon;
    }

    /** Gets the searching package name for UID battery type. */
    public String getPackageName() {
        return mDefaultPackageName;
    }

    private void loadLabelAndIcon() {
        if (mIsLoaded) {
@@ -127,7 +146,46 @@ public final class BatteryDiffEntry {
    }

    private void loadNameAndIconForUid() {
        // TODO(b/185187669) fetch label and icon for UID battery type
        final String packageName = mBatteryHistEntry.mPackageName;
        final PackageManager packageManager = mContext.getPackageManager();
        // Gets the application label from PackageManager.
        if (packageName != null && packageName.length() != 0) {
            try {
                final ApplicationInfo appInfo =
                    packageManager.getApplicationInfo(packageName, /*no flags*/ 0);
                mAppLabel = packageManager.getApplicationLabel(appInfo).toString();
            } catch (NameNotFoundException e) {
                Log.e(TAG, "failed to retrieve ApplicationInfo for: " + packageName);
                mAppLabel = packageName;
            }
        }

        final int uid = (int) mBatteryHistEntry.mUid;
        final String[] packages = packageManager.getPackagesForUid(uid);
        // Loads special defined application label and icon if available.
        if (packages == null || packages.length == 0) {
            final BatteryEntry.NameAndIcon nameAndIcon =
                BatteryEntry.getNameAndIconFromUid(mContext, mAppLabel, uid);
            mAppLabel = nameAndIcon.name;
            mAppIcon = nameAndIcon.icon;
        }

        final BatteryEntry.NameAndIcon nameAndIcon =
            BatteryEntry.loadNameAndIcon(
                mContext, uid, /*uid=*/ null, /*batteryEntry=*/ null,
                packageName, mAppLabel, mAppIcon);
        // Clears BatteryEntry internal cache since we will have another one.
        BatteryEntry.clearUidCache();
        if (nameAndIcon != null) {
            mAppLabel = getNonNull(mAppLabel, nameAndIcon.name);
            mAppIcon = getNonNull(mAppIcon, nameAndIcon.icon);
            mDefaultPackageName = nameAndIcon.packageName;
            if (mDefaultPackageName != null
                    && !mDefaultPackageName.equals(nameAndIcon.packageName)) {
                Log.w(TAG, String.format("found different package: %s | %s",
                    mDefaultPackageName, nameAndIcon.packageName));
            }
        }
    }

    @Override
@@ -144,4 +202,8 @@ public final class BatteryDiffEntry {
                  mBatteryHistEntry.mPackageName, mBatteryHistEntry.mUid));
        return builder.toString();
    }

    private static <T> T getNonNull(T originalObj, T newObj) {
        return newObj != null ? newObj : originalObj;
    }
}
+6 −4
Original line number Diff line number Diff line
@@ -111,7 +111,8 @@ public class BatteryEntry {
                }
                final NameAndIcon nameAndIcon =
                    BatteryEntry.loadNameAndIcon(
                        be.mContext, be.getUid(), sHandler, be, be.mDefaultPackageName);
                        be.mContext, be.getUid(), sHandler, be,
                        be.mDefaultPackageName, be.name, be.icon);
                if (nameAndIcon != null) {
                    be.icon = getNonNull(be.icon, nameAndIcon.icon);
                    be.name = getNonNull(be.name, nameAndIcon.name);
@@ -274,6 +275,7 @@ public class BatteryEntry {
            icon = mContext.getPackageManager().getDefaultActivityIcon();
        }

        // Avoids post the loading icon and label in the background request.
        if (sHandler != null && loadDataInBackground) {
            synchronized (sRequestQueue) {
                sRequestQueue.add(this);
@@ -289,9 +291,9 @@ public class BatteryEntry {
            int uid,
            Handler handler,
            BatteryEntry batteryEntry,
            String defaultPackageName) {
        String name = null;
        Drawable icon = null;
            String defaultPackageName,
            String name,
            Drawable icon) {
        // Bail out if the current sipper is not an App sipper.
        if (uid == 0 || uid == Process.INVALID_UID) {
            return null;
+90 −8
Original line number Diff line number Diff line
@@ -22,6 +22,9 @@ import static org.mockito.Mockito.spy;

import android.content.Context;
import android.content.ContentValues;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
import android.os.SystemBatteryConsumer;
import android.os.UserManager;

@@ -41,14 +44,18 @@ import java.util.List;
public final class BatteryDiffEntryTest {

    private Context mContext;
    @Mock
    private UserManager mockUserManager;

    @Mock private ApplicationInfo mockAppInfo;
    @Mock private PackageManager mockPackageManager;
    @Mock private UserManager mockUserManager;
    @Mock private Drawable mockDrawable;

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
        mContext = spy(RuntimeEnvironment.application);
        doReturn(mockUserManager).when(mContext).getSystemService(UserManager.class);
        doReturn(mockPackageManager).when(mContext).getPackageManager();
    }

    @Test
@@ -96,9 +103,8 @@ public final class BatteryDiffEntryTest {
    @Test
    public void testLoadLabelAndIcon_forSystemBattery_returnExpectedResult() {
        // Generates fake testing data.
        final ContentValues values = new ContentValues();
        values.put("consumerType",
            Integer.valueOf(ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY));
        final ContentValues values = getContentValuesWithType(
            ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY);
        values.put("drainType",
            Integer.valueOf(SystemBatteryConsumer.DRAIN_TYPE_AMBIENT_DISPLAY));
        final BatteryHistEntry batteryHistEntry = new BatteryHistEntry(values);
@@ -112,9 +118,8 @@ public final class BatteryDiffEntryTest {
    public void testLoadLabelAndIcon_forUserBattery_returnExpectedResult() {
        doReturn(null).when(mockUserManager).getUserInfo(1001);
        // Generates fake testing data.
        final ContentValues values = new ContentValues();
        values.put("consumerType",
            Integer.valueOf(ConvertUtils.CONSUMER_TYPE_USER_BATTERY));
        final ContentValues values = getContentValuesWithType(
            ConvertUtils.CONSUMER_TYPE_USER_BATTERY);
        values.put("userId", Integer.valueOf(1001));
        final BatteryHistEntry batteryHistEntry = new BatteryHistEntry(values);

@@ -124,6 +129,77 @@ public final class BatteryDiffEntryTest {
        assertThat(entry.getAppIcon()).isNull();
    }

    @Test
    public void testGetAppLabel_loadDataFromApplicationInfo() throws Exception {
        final String expectedAppLabel = "fake app label";
        final String fakePackageName = "com.fake.google.com";
        final ContentValues values = getContentValuesWithType(
            ConvertUtils.CONSUMER_TYPE_UID_BATTERY);
        values.put("uid", /*invalid uid*/ 10001);
        values.put("packageName", fakePackageName);
        doReturn(mockAppInfo).when(mockPackageManager)
            .getApplicationInfo(fakePackageName, 0);
        doReturn(expectedAppLabel).when(mockPackageManager)
            .getApplicationLabel(mockAppInfo);
        final BatteryHistEntry batteryHistEntry = new BatteryHistEntry(values);

        final BatteryDiffEntry entry = createBatteryDiffEntry(10, batteryHistEntry);

        assertThat(entry.getAppLabel()).isEqualTo(expectedAppLabel);
    }

    @Test
    public void testGetAppLabel_loadDataFromPreDefinedNameAndUid() {
        final ContentValues values = getContentValuesWithType(
            ConvertUtils.CONSUMER_TYPE_UID_BATTERY);
        final BatteryHistEntry batteryHistEntry = new BatteryHistEntry(values);

        final BatteryDiffEntry entry = createBatteryDiffEntry(10, batteryHistEntry);

        assertThat(entry.getAppLabel()).isEqualTo("Android OS");
    }

    @Test
    public void testGetAppLabel_nullAppLabel_returnAppLabelInBatteryHistEntry() {
        final String expectedAppLabel = "fake app label";
        final ContentValues values = getContentValuesWithType(
            ConvertUtils.CONSUMER_TYPE_UID_BATTERY);
        values.put("appLabel", expectedAppLabel);
        final BatteryHistEntry batteryHistEntry = new BatteryHistEntry(values);

        final BatteryDiffEntry entry = createBatteryDiffEntry(10, batteryHistEntry);

        entry.mIsLoaded = true;
        assertThat(entry.getAppLabel()).isEqualTo(expectedAppLabel);
    }

    @Test
    public void testGetAppIcon_nonUidConsumer_returnAppIconInBatteryDiffEntry() {
        final ContentValues values = getContentValuesWithType(
            ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY);
        final BatteryHistEntry batteryHistEntry = new BatteryHistEntry(values);

        final BatteryDiffEntry entry = createBatteryDiffEntry(10, batteryHistEntry);

        entry.mIsLoaded = true;
        entry.mAppIcon = mockDrawable;
        assertThat(entry.getAppIcon()).isEqualTo(mockDrawable);
    }

    @Test
    public void testGetAppIcon_uidConsumerWithNullIcon_returnDefaultActivityIcon() {
        final ContentValues values = getContentValuesWithType(
            ConvertUtils.CONSUMER_TYPE_UID_BATTERY);
        final BatteryHistEntry batteryHistEntry = new BatteryHistEntry(values);
        doReturn(mockDrawable).when(mockPackageManager).getDefaultActivityIcon();

        final BatteryDiffEntry entry = createBatteryDiffEntry(10, batteryHistEntry);

        entry.mIsLoaded = true;
        entry.mAppIcon = null;
        assertThat(entry.getAppIcon()).isEqualTo(mockDrawable);
    }

    private BatteryDiffEntry createBatteryDiffEntry(
        double consumePower, BatteryHistEntry batteryHistEntry) {
        final BatteryDiffEntry entry = new BatteryDiffEntry(
@@ -135,4 +211,10 @@ public final class BatteryDiffEntryTest {
        entry.setTotalConsumePower(100.0);
        return entry;
    }

    private static ContentValues getContentValuesWithType(int consumerType) {
        final ContentValues values = new ContentValues();
        values.put("consumerType", Integer.valueOf(consumerType));
        return values;
    }
}