Loading src/com/android/settings/fuelgauge/BatteryDiffEntry.java +72 −2 Original line number Diff line number Diff line Loading @@ -13,29 +13,49 @@ */ package com.android.settings.fuelgauge; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.IPackageManager; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.graphics.drawable.Drawable; import android.util.Log; import java.time.Duration; import java.util.Comparator; /** A container class to carry battery data in a specific time slot. */ public final class BatteryDiffEntry { private static final String TAG = "BatteryDiffEntry"; /** A comparator for {@link BatteryDiffEntry} based on consumed percentage. */ public static final Comparator<BatteryDiffEntry> COMPARATOR = (a, b) -> Double.compare(b.getPercentOfTotal(), a.getPercentOfTotal()); public long mForegroundUsageTimeInMs; public long mBackgroundUsageTimeInMs; public double mConsumePower; // A BatteryHistEntry corresponding to this diff usage data. public final BatteryHistEntry mBatteryHistEntry; private double mTotalConsumePower; private double mPercentOfTotal; private Context mContext; private String mAppLabel = null; private Drawable mAppIcon = null; private boolean mIsLoaded = false; public BatteryDiffEntry( Context context, long foregroundUsageTimeInMs, long backgroundUsageTimeInMs, double consumePower, BatteryHistEntry batteryHistEntry) { mContext = context; mConsumePower = consumePower; mForegroundUsageTimeInMs = foregroundUsageTimeInMs; mBackgroundUsageTimeInMs = backgroundUsageTimeInMs; mConsumePower = consumePower; mBatteryHistEntry = batteryHistEntry; } Loading @@ -54,12 +74,62 @@ public final class BatteryDiffEntry { /** Clones a new instance. */ public BatteryDiffEntry clone() { return new BatteryDiffEntry( this.mContext, this.mForegroundUsageTimeInMs, this.mBackgroundUsageTimeInMs, this.mConsumePower, this.mBatteryHistEntry /*same instance*/); } /** Gets the app label name for this entry. */ public String getAppLabel() { loadLabelAndIcon(); return mAppLabel; } /** Gets the app icon {@link Drawable} for this entry. */ public Drawable getAppIcon() { loadLabelAndIcon(); return mAppIcon; } private void loadLabelAndIcon() { if (mIsLoaded) { return; } mIsLoaded = true; // Loads application icon and label based on consumer type. switch (mBatteryHistEntry.mConsumerType) { case ConvertUtils.CONSUMER_TYPE_USER_BATTERY: final BatteryEntry.NameAndIcon nameAndIconForUser = BatteryEntry.getNameAndIconFromUserId( mContext, (int) mBatteryHistEntry.mUserId); if (nameAndIconForUser != null) { mAppIcon = nameAndIconForUser.icon; mAppLabel = nameAndIconForUser.name; } break; case ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY: final BatteryEntry.NameAndIcon nameAndIconForSystem = BatteryEntry.getNameAndIconFromDrainType( mContext, mBatteryHistEntry.mDrainType); if (nameAndIconForSystem != null) { mAppLabel = nameAndIconForSystem.name; if (nameAndIconForSystem.iconId != 0) { mAppIcon = mContext.getDrawable(nameAndIconForSystem.iconId); } } break; case ConvertUtils.CONSUMER_TYPE_UID_BATTERY: loadNameAndIconForUid(); break; } } private void loadNameAndIconForUid() { // TODO(b/185187669) fetch label and icon for UID battery type } @Override public String toString() { final StringBuilder builder = new StringBuilder() Loading src/com/android/settings/fuelgauge/ConvertUtils.java +3 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ import android.annotation.IntDef; import android.content.ContentValues; import android.os.BatteryConsumer; import android.os.BatteryUsageStats; import android.content.Context; import android.os.SystemBatteryConsumer; import android.os.UidBatteryConsumer; import android.os.UserBatteryConsumer; Loading Loading @@ -138,6 +139,7 @@ public final class ConvertUtils { /** Gets indexed battery usage data for each corresponding time slot. */ public static Map<Integer, List<BatteryDiffEntry>> getIndexedUsageMap( final Context context, final int timeSlotSize, final long[] batteryHistoryKeys, final Map<Long, List<BatteryHistEntry>> batteryHistoryMap) { Loading Loading @@ -234,6 +236,7 @@ public final class ConvertUtils { } batteryDiffEntryList.add( new BatteryDiffEntry( context, foregroundUsageTimeInMs, backgroundUsageTimeInMs, consumePower, Loading tests/robotests/src/com/android/settings/fuelgauge/BatteryDiffEntryTest.java +86 −0 Original line number Diff line number Diff line Loading @@ -17,17 +17,45 @@ package com.android.settings.fuelgauge; import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.spy; import android.content.Context; import android.content.ContentValues; import android.os.SystemBatteryConsumer; import android.os.UserManager; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; import java.util.ArrayList; import java.util.Collections; import java.util.List; @RunWith(RobolectricTestRunner.class) public final class BatteryDiffEntryTest { private Context mContext; @Mock private UserManager mockUserManager; @Before public void setUp() { MockitoAnnotations.initMocks(this); mContext = spy(RuntimeEnvironment.application); doReturn(mockUserManager).when(mContext).getSystemService(UserManager.class); } @Test public void testSetTotalConsumePower_returnExpectedResult() { final BatteryDiffEntry entry = new BatteryDiffEntry( mContext, /*foregroundUsageTimeInMs=*/ 10001L, /*backgroundUsageTimeInMs=*/ 20002L, /*consumePower=*/ 22.0, Loading @@ -41,6 +69,7 @@ public final class BatteryDiffEntryTest { public void testSetTotalConsumePower_setZeroValue_returnsZeroValue() { final BatteryDiffEntry entry = new BatteryDiffEntry( mContext, /*foregroundUsageTimeInMs=*/ 10001L, /*backgroundUsageTimeInMs=*/ 20002L, /*consumePower=*/ 22.0, Loading @@ -49,4 +78,61 @@ public final class BatteryDiffEntryTest { assertThat(entry.getPercentOfTotal()).isEqualTo(0); } @Test public void testComparator_sortCollectionsInDescOrder() { final List<BatteryDiffEntry> entryList = new ArrayList<>(); // Generates fake testing data. entryList.add(createBatteryDiffEntry(30, /*batteryHistEntry=*/ null)); entryList.add(createBatteryDiffEntry(20, /*batteryHistEntry=*/ null)); entryList.add(createBatteryDiffEntry(10, /*batteryHistEntry=*/ null)); Collections.sort(entryList, BatteryDiffEntry.COMPARATOR); assertThat(entryList.get(0).getPercentOfTotal()).isEqualTo(30); assertThat(entryList.get(1).getPercentOfTotal()).isEqualTo(20); assertThat(entryList.get(2).getPercentOfTotal()).isEqualTo(10); } @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)); values.put("drainType", Integer.valueOf(SystemBatteryConsumer.DRAIN_TYPE_AMBIENT_DISPLAY)); final BatteryHistEntry batteryHistEntry = new BatteryHistEntry(values); final BatteryDiffEntry entry = createBatteryDiffEntry(10, batteryHistEntry); assertThat(entry.getAppLabel()).isEqualTo("Ambient display"); } @Test 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)); values.put("userId", Integer.valueOf(1001)); final BatteryHistEntry batteryHistEntry = new BatteryHistEntry(values); final BatteryDiffEntry entry = createBatteryDiffEntry(10, batteryHistEntry); assertThat(entry.getAppLabel()).isEqualTo("Removed user"); assertThat(entry.getAppIcon()).isNull(); } private BatteryDiffEntry createBatteryDiffEntry( double consumePower, BatteryHistEntry batteryHistEntry) { final BatteryDiffEntry entry = new BatteryDiffEntry( mContext, /*foregroundUsageTimeInMs=*/ 0, /*backgroundUsageTimeInMs=*/ 0, consumePower, batteryHistEntry); entry.setTotalConsumePower(100.0); return entry; } } tests/robotests/src/com/android/settings/fuelgauge/ConvertUtilsTest.java +5 −1 Original line number Diff line number Diff line Loading @@ -19,8 +19,10 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.when; import static org.mockito.Mockito.spy; import android.content.ContentValues; import android.content.Context; import android.os.BatteryConsumer; import android.os.BatteryManager; import android.os.BatteryUsageStats; Loading @@ -47,6 +49,7 @@ import java.util.TimeZone; @RunWith(RobolectricTestRunner.class) public final class ConvertUtilsTest { private Context mContext; @Mock private BatteryUsageStats mBatteryUsageStats; @Mock Loading @@ -63,6 +66,7 @@ public final class ConvertUtilsTest { @Before public void setUp() { MockitoAnnotations.initMocks(this); mContext = spy(RuntimeEnvironment.application); } @Test Loading Loading @@ -208,7 +212,7 @@ public final class ConvertUtilsTest { final Map<Integer, List<BatteryDiffEntry>> resultMap = ConvertUtils.getIndexedUsageMap( timeSlotSize, batteryHistoryKeys, batteryHistoryMap); mContext, timeSlotSize, batteryHistoryKeys, batteryHistoryMap); assertThat(resultMap).hasSize(3); // Verifies the first timestamp result. Loading Loading
src/com/android/settings/fuelgauge/BatteryDiffEntry.java +72 −2 Original line number Diff line number Diff line Loading @@ -13,29 +13,49 @@ */ package com.android.settings.fuelgauge; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.IPackageManager; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.graphics.drawable.Drawable; import android.util.Log; import java.time.Duration; import java.util.Comparator; /** A container class to carry battery data in a specific time slot. */ public final class BatteryDiffEntry { private static final String TAG = "BatteryDiffEntry"; /** A comparator for {@link BatteryDiffEntry} based on consumed percentage. */ public static final Comparator<BatteryDiffEntry> COMPARATOR = (a, b) -> Double.compare(b.getPercentOfTotal(), a.getPercentOfTotal()); public long mForegroundUsageTimeInMs; public long mBackgroundUsageTimeInMs; public double mConsumePower; // A BatteryHistEntry corresponding to this diff usage data. public final BatteryHistEntry mBatteryHistEntry; private double mTotalConsumePower; private double mPercentOfTotal; private Context mContext; private String mAppLabel = null; private Drawable mAppIcon = null; private boolean mIsLoaded = false; public BatteryDiffEntry( Context context, long foregroundUsageTimeInMs, long backgroundUsageTimeInMs, double consumePower, BatteryHistEntry batteryHistEntry) { mContext = context; mConsumePower = consumePower; mForegroundUsageTimeInMs = foregroundUsageTimeInMs; mBackgroundUsageTimeInMs = backgroundUsageTimeInMs; mConsumePower = consumePower; mBatteryHistEntry = batteryHistEntry; } Loading @@ -54,12 +74,62 @@ public final class BatteryDiffEntry { /** Clones a new instance. */ public BatteryDiffEntry clone() { return new BatteryDiffEntry( this.mContext, this.mForegroundUsageTimeInMs, this.mBackgroundUsageTimeInMs, this.mConsumePower, this.mBatteryHistEntry /*same instance*/); } /** Gets the app label name for this entry. */ public String getAppLabel() { loadLabelAndIcon(); return mAppLabel; } /** Gets the app icon {@link Drawable} for this entry. */ public Drawable getAppIcon() { loadLabelAndIcon(); return mAppIcon; } private void loadLabelAndIcon() { if (mIsLoaded) { return; } mIsLoaded = true; // Loads application icon and label based on consumer type. switch (mBatteryHistEntry.mConsumerType) { case ConvertUtils.CONSUMER_TYPE_USER_BATTERY: final BatteryEntry.NameAndIcon nameAndIconForUser = BatteryEntry.getNameAndIconFromUserId( mContext, (int) mBatteryHistEntry.mUserId); if (nameAndIconForUser != null) { mAppIcon = nameAndIconForUser.icon; mAppLabel = nameAndIconForUser.name; } break; case ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY: final BatteryEntry.NameAndIcon nameAndIconForSystem = BatteryEntry.getNameAndIconFromDrainType( mContext, mBatteryHistEntry.mDrainType); if (nameAndIconForSystem != null) { mAppLabel = nameAndIconForSystem.name; if (nameAndIconForSystem.iconId != 0) { mAppIcon = mContext.getDrawable(nameAndIconForSystem.iconId); } } break; case ConvertUtils.CONSUMER_TYPE_UID_BATTERY: loadNameAndIconForUid(); break; } } private void loadNameAndIconForUid() { // TODO(b/185187669) fetch label and icon for UID battery type } @Override public String toString() { final StringBuilder builder = new StringBuilder() Loading
src/com/android/settings/fuelgauge/ConvertUtils.java +3 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ import android.annotation.IntDef; import android.content.ContentValues; import android.os.BatteryConsumer; import android.os.BatteryUsageStats; import android.content.Context; import android.os.SystemBatteryConsumer; import android.os.UidBatteryConsumer; import android.os.UserBatteryConsumer; Loading Loading @@ -138,6 +139,7 @@ public final class ConvertUtils { /** Gets indexed battery usage data for each corresponding time slot. */ public static Map<Integer, List<BatteryDiffEntry>> getIndexedUsageMap( final Context context, final int timeSlotSize, final long[] batteryHistoryKeys, final Map<Long, List<BatteryHistEntry>> batteryHistoryMap) { Loading Loading @@ -234,6 +236,7 @@ public final class ConvertUtils { } batteryDiffEntryList.add( new BatteryDiffEntry( context, foregroundUsageTimeInMs, backgroundUsageTimeInMs, consumePower, Loading
tests/robotests/src/com/android/settings/fuelgauge/BatteryDiffEntryTest.java +86 −0 Original line number Diff line number Diff line Loading @@ -17,17 +17,45 @@ package com.android.settings.fuelgauge; import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.spy; import android.content.Context; import android.content.ContentValues; import android.os.SystemBatteryConsumer; import android.os.UserManager; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; import java.util.ArrayList; import java.util.Collections; import java.util.List; @RunWith(RobolectricTestRunner.class) public final class BatteryDiffEntryTest { private Context mContext; @Mock private UserManager mockUserManager; @Before public void setUp() { MockitoAnnotations.initMocks(this); mContext = spy(RuntimeEnvironment.application); doReturn(mockUserManager).when(mContext).getSystemService(UserManager.class); } @Test public void testSetTotalConsumePower_returnExpectedResult() { final BatteryDiffEntry entry = new BatteryDiffEntry( mContext, /*foregroundUsageTimeInMs=*/ 10001L, /*backgroundUsageTimeInMs=*/ 20002L, /*consumePower=*/ 22.0, Loading @@ -41,6 +69,7 @@ public final class BatteryDiffEntryTest { public void testSetTotalConsumePower_setZeroValue_returnsZeroValue() { final BatteryDiffEntry entry = new BatteryDiffEntry( mContext, /*foregroundUsageTimeInMs=*/ 10001L, /*backgroundUsageTimeInMs=*/ 20002L, /*consumePower=*/ 22.0, Loading @@ -49,4 +78,61 @@ public final class BatteryDiffEntryTest { assertThat(entry.getPercentOfTotal()).isEqualTo(0); } @Test public void testComparator_sortCollectionsInDescOrder() { final List<BatteryDiffEntry> entryList = new ArrayList<>(); // Generates fake testing data. entryList.add(createBatteryDiffEntry(30, /*batteryHistEntry=*/ null)); entryList.add(createBatteryDiffEntry(20, /*batteryHistEntry=*/ null)); entryList.add(createBatteryDiffEntry(10, /*batteryHistEntry=*/ null)); Collections.sort(entryList, BatteryDiffEntry.COMPARATOR); assertThat(entryList.get(0).getPercentOfTotal()).isEqualTo(30); assertThat(entryList.get(1).getPercentOfTotal()).isEqualTo(20); assertThat(entryList.get(2).getPercentOfTotal()).isEqualTo(10); } @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)); values.put("drainType", Integer.valueOf(SystemBatteryConsumer.DRAIN_TYPE_AMBIENT_DISPLAY)); final BatteryHistEntry batteryHistEntry = new BatteryHistEntry(values); final BatteryDiffEntry entry = createBatteryDiffEntry(10, batteryHistEntry); assertThat(entry.getAppLabel()).isEqualTo("Ambient display"); } @Test 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)); values.put("userId", Integer.valueOf(1001)); final BatteryHistEntry batteryHistEntry = new BatteryHistEntry(values); final BatteryDiffEntry entry = createBatteryDiffEntry(10, batteryHistEntry); assertThat(entry.getAppLabel()).isEqualTo("Removed user"); assertThat(entry.getAppIcon()).isNull(); } private BatteryDiffEntry createBatteryDiffEntry( double consumePower, BatteryHistEntry batteryHistEntry) { final BatteryDiffEntry entry = new BatteryDiffEntry( mContext, /*foregroundUsageTimeInMs=*/ 0, /*backgroundUsageTimeInMs=*/ 0, consumePower, batteryHistEntry); entry.setTotalConsumePower(100.0); return entry; } }
tests/robotests/src/com/android/settings/fuelgauge/ConvertUtilsTest.java +5 −1 Original line number Diff line number Diff line Loading @@ -19,8 +19,10 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.when; import static org.mockito.Mockito.spy; import android.content.ContentValues; import android.content.Context; import android.os.BatteryConsumer; import android.os.BatteryManager; import android.os.BatteryUsageStats; Loading @@ -47,6 +49,7 @@ import java.util.TimeZone; @RunWith(RobolectricTestRunner.class) public final class ConvertUtilsTest { private Context mContext; @Mock private BatteryUsageStats mBatteryUsageStats; @Mock Loading @@ -63,6 +66,7 @@ public final class ConvertUtilsTest { @Before public void setUp() { MockitoAnnotations.initMocks(this); mContext = spy(RuntimeEnvironment.application); } @Test Loading Loading @@ -208,7 +212,7 @@ public final class ConvertUtilsTest { final Map<Integer, List<BatteryDiffEntry>> resultMap = ConvertUtils.getIndexedUsageMap( timeSlotSize, batteryHistoryKeys, batteryHistoryMap); mContext, timeSlotSize, batteryHistoryKeys, batteryHistoryMap); assertThat(resultMap).hasSize(3); // Verifies the first timestamp result. Loading