Loading src/com/android/settings/fuelgauge/BatteryDiffEntry.java +68 −6 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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, Loading Loading @@ -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) { Loading Loading @@ -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 Loading @@ -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; } } src/com/android/settings/fuelgauge/BatteryEntry.java +6 −4 Original line number Diff line number Diff line Loading @@ -110,7 +110,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); Loading Loading @@ -273,6 +274,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); Loading @@ -288,9 +290,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; Loading tests/robotests/src/com/android/settings/fuelgauge/BatteryDiffEntryTest.java +90 −8 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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 Loading Loading @@ -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); Loading @@ -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); Loading @@ -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( Loading @@ -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; } } Loading
src/com/android/settings/fuelgauge/BatteryDiffEntry.java +68 −6 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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, Loading Loading @@ -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) { Loading Loading @@ -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 Loading @@ -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; } }
src/com/android/settings/fuelgauge/BatteryEntry.java +6 −4 Original line number Diff line number Diff line Loading @@ -110,7 +110,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); Loading Loading @@ -273,6 +274,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); Loading @@ -288,9 +290,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; Loading
tests/robotests/src/com/android/settings/fuelgauge/BatteryDiffEntryTest.java +90 −8 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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 Loading Loading @@ -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); Loading @@ -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); Loading @@ -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( Loading @@ -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; } }