diff --git a/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java b/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java index f28ae00860e..6d733593ef4 100644 --- a/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java +++ b/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java @@ -116,37 +116,82 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements private String mPackageName; - /** - * Launches battery details page for an individual battery consumer. - */ + // A wrapper class to carry LaunchBatteryDetailPage required arguments. + private static final class LaunchBatteryDetailPageArgs { + private String mUsagePercent; + private String mPackageName; + private String mAppLabel; + private int mUid; + private int mIconId; + private int mConsumedPower; + private long mForegroundTimeMs; + private long mBackgroundTimeMs; + private boolean mIsUserEntry; + } + + /** Launches battery details page for an individual battery consumer. */ + public static void startBatteryDetailPage( + Activity caller, InstrumentedPreferenceFragment fragment, + BatteryDiffEntry diffEntry, String usagePercent) { + final BatteryHistEntry histEntry = diffEntry.mBatteryHistEntry; + final LaunchBatteryDetailPageArgs launchArgs = new LaunchBatteryDetailPageArgs(); + // configure the launch argument. + launchArgs.mUsagePercent = usagePercent; + launchArgs.mPackageName = diffEntry.getPackageName(); + launchArgs.mAppLabel = diffEntry.getAppLabel(); + launchArgs.mUid = (int) histEntry.mUid; + launchArgs.mIconId = diffEntry.getAppIconId(); + launchArgs.mConsumedPower = (int) diffEntry.mConsumePower; + launchArgs.mForegroundTimeMs = diffEntry.mForegroundUsageTimeInMs; + launchArgs.mBackgroundTimeMs = diffEntry.mBackgroundUsageTimeInMs; + launchArgs.mIsUserEntry = histEntry.isUserEntry(); + startBatteryDetailPage(caller, fragment, launchArgs); + } + + /** Launches battery details page for an individual battery consumer. */ public static void startBatteryDetailPage(Activity caller, InstrumentedPreferenceFragment fragment, BatteryEntry entry, String usagePercent) { + final LaunchBatteryDetailPageArgs launchArgs = new LaunchBatteryDetailPageArgs(); + // configure the launch argument. + launchArgs.mUsagePercent = usagePercent; + launchArgs.mPackageName = entry.getDefaultPackageName(); + launchArgs.mAppLabel = entry.getLabel(); + launchArgs.mUid = entry.getUid(); + launchArgs.mIconId = entry.iconId; + launchArgs.mConsumedPower = (int) entry.getConsumedPower(); + launchArgs.mForegroundTimeMs = entry.getTimeInForegroundMs(); + launchArgs.mBackgroundTimeMs = entry.getTimeInBackgroundMs(); + launchArgs.mIsUserEntry = entry.isUserEntry(); + startBatteryDetailPage(caller, fragment, launchArgs); + } + + private static void startBatteryDetailPage(Activity caller, + InstrumentedPreferenceFragment fragment, LaunchBatteryDetailPageArgs launchArgs) { final Bundle args = new Bundle(); - final long foregroundTimeMs = entry.getTimeInForegroundMs(); - final long backgroundTimeMs = entry.getTimeInBackgroundMs(); - final String packageName = entry.getDefaultPackageName(); - if (packageName == null) { + if (launchArgs.mPackageName == null) { // populate data for system app - args.putString(EXTRA_LABEL, entry.getLabel()); - args.putInt(EXTRA_ICON_ID, entry.iconId); + args.putString(EXTRA_LABEL, launchArgs.mAppLabel); + args.putInt(EXTRA_ICON_ID, launchArgs.mIconId); args.putString(EXTRA_PACKAGE_NAME, null); } else { // populate data for normal app - args.putString(EXTRA_PACKAGE_NAME, packageName); + args.putString(EXTRA_PACKAGE_NAME, launchArgs.mPackageName); } - args.putInt(EXTRA_UID, entry.getUid()); - args.putLong(EXTRA_BACKGROUND_TIME, backgroundTimeMs); - args.putLong(EXTRA_FOREGROUND_TIME, foregroundTimeMs); - args.putString(EXTRA_POWER_USAGE_PERCENT, usagePercent); - args.putInt(EXTRA_POWER_USAGE_AMOUNT, (int) entry.getConsumedPower()); + args.putInt(EXTRA_UID, launchArgs.mUid); + args.putLong(EXTRA_BACKGROUND_TIME, launchArgs.mBackgroundTimeMs); + args.putLong(EXTRA_FOREGROUND_TIME, launchArgs.mForegroundTimeMs); + args.putString(EXTRA_POWER_USAGE_PERCENT, launchArgs.mUsagePercent); + args.putInt(EXTRA_POWER_USAGE_AMOUNT, launchArgs.mConsumedPower); + final int userId = launchArgs.mIsUserEntry ? ActivityManager.getCurrentUser() + : UserHandle.getUserId(launchArgs.mUid); new SubSettingLauncher(caller) .setDestination(AdvancedPowerUsageDetail.class.getName()) .setTitleRes(R.string.battery_details_title) .setArguments(args) .setSourceMetricsCategory(fragment.getMetricsCategory()) - .setUserHandle(new UserHandle(getUserIdToLaunchAdvancePowerUsageDetail(entry))) + .setUserHandle(new UserHandle(userId)) .launch(); } diff --git a/src/com/android/settings/fuelgauge/BatteryChartPreferenceController.java b/src/com/android/settings/fuelgauge/BatteryChartPreferenceController.java index eca2bf3d34e..54591af4bd0 100644 --- a/src/com/android/settings/fuelgauge/BatteryChartPreferenceController.java +++ b/src/com/android/settings/fuelgauge/BatteryChartPreferenceController.java @@ -58,6 +58,7 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll Map> mBatteryIndexedMap; @VisibleForTesting Context mPrefContext; + @VisibleForTesting BatteryUtils mBatteryUtils; @VisibleForTesting PreferenceGroup mAppListPrefGroup; @VisibleForTesting BatteryChartView mBatteryChartView; @@ -98,6 +99,9 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll } mHandler.removeCallbacksAndMessages(/*token=*/ null); mPreferenceCache.clear(); + if (mAppListPrefGroup != null) { + mAppListPrefGroup.removeAll(); + } } @Override @@ -120,6 +124,28 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll @Override public boolean handlePreferenceTreeClick(Preference preference) { + if (!(preference instanceof PowerGaugePreference)) { + return false; + } + final PowerGaugePreference powerPref = (PowerGaugePreference) preference; + final BatteryDiffEntry diffEntry = powerPref.getBatteryDiffEntry(); + final BatteryHistEntry histEntry = diffEntry.mBatteryHistEntry; + // Checks whether the package is installed or not. + boolean isValidPackage = true; + if (histEntry.isAppEntry()) { + if (mBatteryUtils == null) { + mBatteryUtils = BatteryUtils.getInstance(mPrefContext); + } + isValidPackage = mBatteryUtils.getPackageUid(histEntry.mPackageName) + != BatteryUtils.UID_NULL; + } + Log.d(TAG, String.format("handleClick() label=%s key=%s isValid:%b", + diffEntry.getAppLabel(), histEntry.getKey(), isValidPackage)); + if (isValidPackage) { + AdvancedPowerUsageDetail.startBatteryDetailPage( + mActivity, mFragment, diffEntry, powerPref.getPercent()); + return true; + } return false; } @@ -273,6 +299,8 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll pref.setTitle(appLabel); pref.setOrder(prefIndex); pref.setPercent(entry.getPercentOfTotal()); + // Sets the BatteryDiffEntry to preference for launching detailed page. + pref.setBatteryDiffEntry(entry); mAppListPrefGroup.addPreference(pref); prefIndex++; } diff --git a/src/com/android/settings/fuelgauge/BatteryDiffEntry.java b/src/com/android/settings/fuelgauge/BatteryDiffEntry.java index 652b54c8b2d..92731b75d38 100644 --- a/src/com/android/settings/fuelgauge/BatteryDiffEntry.java +++ b/src/com/android/settings/fuelgauge/BatteryDiffEntry.java @@ -57,6 +57,7 @@ public class BatteryDiffEntry { private UserManager mUserManager; private String mDefaultPackageName = null; + @VisibleForTesting int mAppIconId; @VisibleForTesting String mAppLabel = null; @VisibleForTesting Drawable mAppIcon = null; @VisibleForTesting boolean mIsLoaded = false; @@ -112,9 +113,16 @@ public class BatteryDiffEntry { return mAppIcon; } + /** Gets the app icon id for this entry. */ + public int getAppIconId() { + loadLabelAndIcon(); + return mAppIconId; + } + /** Gets the searching package name for UID battery type. */ public String getPackageName() { - return mDefaultPackageName; + return mDefaultPackageName != null + ? mDefaultPackageName : mBatteryHistEntry.mPackageName; } /** Whether the current BatteryDiffEntry is system component or not. */ @@ -153,6 +161,7 @@ public class BatteryDiffEntry { if (nameAndIconForSystem != null) { mAppLabel = nameAndIconForSystem.name; if (nameAndIconForSystem.iconId != 0) { + mAppIconId = nameAndIconForSystem.iconId; mAppIcon = mContext.getDrawable(nameAndIconForSystem.iconId); } } @@ -225,8 +234,8 @@ public class BatteryDiffEntry { // 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); + mAppLabel = nameAndIcon.name; + mAppIcon = nameAndIcon.icon; mDefaultPackageName = nameAndIcon.packageName; if (mDefaultPackageName != null && !mDefaultPackageName.equals(nameAndIcon.packageName)) { @@ -265,8 +274,4 @@ public class BatteryDiffEntry { final int appUid = UserHandle.getAppId(uid); return appUid >= Process.SYSTEM_UID && appUid < Process.FIRST_APPLICATION_UID; } - - private static T getNonNull(T originalObj, T newObj) { - return newObj != null ? newObj : originalObj; - } } diff --git a/src/com/android/settings/fuelgauge/BatteryEntry.java b/src/com/android/settings/fuelgauge/BatteryEntry.java index 151284a30ae..f9c4b288e89 100644 --- a/src/com/android/settings/fuelgauge/BatteryEntry.java +++ b/src/com/android/settings/fuelgauge/BatteryEntry.java @@ -113,10 +113,9 @@ public class BatteryEntry { 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); - be.mDefaultPackageName = getNonNull( - be.mDefaultPackageName, nameAndIcon.packageName); + be.icon = nameAndIcon.icon; + be.name = nameAndIcon.name; + be.mDefaultPackageName = nameAndIcon.packageName; } } } @@ -589,8 +588,4 @@ public class BatteryEntry { } return new NameAndIcon(name, null /* icon */, iconId); } - - private static T getNonNull(T originalObj, T newObj) { - return newObj != null ? newObj : originalObj; - } } diff --git a/src/com/android/settings/fuelgauge/BatteryHistEntry.java b/src/com/android/settings/fuelgauge/BatteryHistEntry.java index 41fd55fcffb..43078e9548b 100644 --- a/src/com/android/settings/fuelgauge/BatteryHistEntry.java +++ b/src/com/android/settings/fuelgauge/BatteryHistEntry.java @@ -113,6 +113,16 @@ public class BatteryHistEntry { return mIsValidEntry; } + /** Whether this {@link BatteryHistEntry} is user consumer or not. */ + public boolean isUserEntry() { + return mConsumerType == ConvertUtils.CONSUMER_TYPE_USER_BATTERY; + } + + /** Whether this {@link BatteryHistEntry} is app consumer or not. */ + public boolean isAppEntry() { + return mConsumerType == ConvertUtils.CONSUMER_TYPE_UID_BATTERY; + } + /** Gets an identifier to represent this {@link BatteryHistEntry}. */ public String getKey() { if (mKey == null) { diff --git a/src/com/android/settings/fuelgauge/PowerGaugePreference.java b/src/com/android/settings/fuelgauge/PowerGaugePreference.java index b75acc62c93..ea79d111cc3 100644 --- a/src/com/android/settings/fuelgauge/PowerGaugePreference.java +++ b/src/com/android/settings/fuelgauge/PowerGaugePreference.java @@ -37,6 +37,7 @@ import com.android.settingslib.widget.AppPreference; public class PowerGaugePreference extends AppPreference { private BatteryEntry mInfo; + private BatteryDiffEntry mBatteryDiffEntry; private CharSequence mContentDescription; private CharSequence mProgress; private boolean mShowAnomalyIcon; @@ -98,10 +99,18 @@ public class PowerGaugePreference extends AppPreference { return mShowAnomalyIcon; } + public void setBatteryDiffEntry(BatteryDiffEntry entry) { + mBatteryDiffEntry = entry; + } + BatteryEntry getInfo() { return mInfo; } + BatteryDiffEntry getBatteryDiffEntry() { + return mBatteryDiffEntry; + } + @Override public void onBindViewHolder(PreferenceViewHolder view) { super.onBindViewHolder(view); diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryChartPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryChartPreferenceControllerTest.java index 66ef2d207f9..bef250b1ca9 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryChartPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryChartPreferenceControllerTest.java @@ -63,6 +63,7 @@ public final class BatteryChartPreferenceControllerTest { @Mock private BatteryHistEntry mBatteryHistEntry; @Mock private BatteryChartView mBatteryChartView; @Mock private PowerGaugePreference mPowerGaugePreference; + @Mock private BatteryUtils mBatteryUtils; private Context mContext; private BatteryDiffEntry mBatteryDiffEntry; @@ -127,6 +128,12 @@ public final class BatteryChartPreferenceControllerTest { assertThat(mBatteryChartPreferenceController.mPreferenceCache).isEmpty(); } + @Test + public void testOnDestroy_removeAllPreferenceFromPreferenceGroup() { + mBatteryChartPreferenceController.onDestroy(); + verify(mAppListGroup).removeAll(); + } + @Test public void testSetBatteryHistoryMap_createExpectedKeysAndLevels() { mBatteryChartPreferenceController.setBatteryHistoryMap( @@ -266,6 +273,34 @@ public final class BatteryChartPreferenceControllerTest { assertThat(pref.getTitle()).isEqualTo(appLabel); assertThat(pref.getIcon()).isEqualTo(mDrawable); assertThat(pref.getOrder()).isEqualTo(1); + assertThat(pref.getBatteryDiffEntry()).isSameInstanceAs(mBatteryDiffEntry); + } + + @Test + public void testHandlePreferenceTreeClick_notPowerGaugePreference_returnFalse() { + assertThat(mBatteryChartPreferenceController.handlePreferenceTreeClick(mAppListGroup)) + .isFalse(); + } + + @Test + public void testHandlePreferenceTreeClick_validPackageName_returnTrue() { + doReturn(false).when(mBatteryHistEntry).isAppEntry(); + doReturn(mBatteryDiffEntry).when(mPowerGaugePreference).getBatteryDiffEntry(); + + assertThat(mBatteryChartPreferenceController.handlePreferenceTreeClick( + mPowerGaugePreference)).isTrue(); + } + + @Test + public void testHandlePreferenceTreeClick_appEntryWithInvalidPackage_returnFalse() { + mBatteryChartPreferenceController.mBatteryUtils = mBatteryUtils; + doReturn(true).when(mBatteryHistEntry).isAppEntry(); + doReturn(BatteryUtils.UID_NULL).when(mBatteryUtils) + .getPackageUid(mBatteryHistEntry.mPackageName); + doReturn(mBatteryDiffEntry).when(mPowerGaugePreference).getBatteryDiffEntry(); + + assertThat(mBatteryChartPreferenceController.handlePreferenceTreeClick( + mPowerGaugePreference)).isFalse(); } private Map> createBatteryHistoryMap(int size) { diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryDiffEntryTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryDiffEntryTest.java index d1bd19f6c2e..c536b061e24 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryDiffEntryTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryDiffEntryTest.java @@ -30,6 +30,8 @@ import android.os.SystemBatteryConsumer; import android.os.UserManager; import android.os.UserHandle; +import com.android.settings.R; + import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -118,6 +120,7 @@ public final class BatteryDiffEntryTest { final BatteryDiffEntry entry = createBatteryDiffEntry(10, batteryHistEntry); assertThat(entry.getAppLabel()).isEqualTo("Ambient display"); + assertThat(entry.getAppIconId()).isEqualTo(R.drawable.ic_settings_aod); assertThat(BatteryDiffEntry.sResourceCache).isEmpty(); } @@ -134,6 +137,7 @@ public final class BatteryDiffEntryTest { assertThat(entry.getAppLabel()).isEqualTo("Removed user"); assertThat(entry.getAppIcon()).isNull(); + assertThat(entry.getAppIconId()).isEqualTo(0); assertThat(BatteryDiffEntry.sResourceCache).isEmpty(); } @@ -154,6 +158,7 @@ public final class BatteryDiffEntryTest { final BatteryDiffEntry entry = createBatteryDiffEntry(10, batteryHistEntry); assertThat(entry.getAppLabel()).isEqualTo(expectedAppLabel); + assertThat(entry.getAppIconId()).isEqualTo(0); assertThat(BatteryDiffEntry.sResourceCache).hasSize(1); // Verifies the app label in the cache. final BatteryEntry.NameAndIcon nameAndIcon = diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryHistEntryTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryHistEntryTest.java index 72ccebe1b43..819a223f292 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryHistEntryTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryHistEntryTest.java @@ -167,6 +167,30 @@ public final class BatteryHistEntryTest { assertThat(batteryHistEntry.getKey()).isEqualTo("S|1"); } + @Test + public void testIsAppEntry_returnExpectedResult() { + assertThat(createEntry(ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY).isAppEntry()) + .isFalse(); + assertThat(createEntry(ConvertUtils.CONSUMER_TYPE_USER_BATTERY).isAppEntry()) + .isFalse(); + assertThat(createEntry(ConvertUtils.CONSUMER_TYPE_UID_BATTERY).isAppEntry()) + .isTrue(); + } + + @Test + public void testIsUserEntry_returnExpectedResult() { + assertThat(createEntry(ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY).isUserEntry()) + .isFalse(); + assertThat(createEntry(ConvertUtils.CONSUMER_TYPE_USER_BATTERY).isUserEntry()) + .isTrue(); + assertThat(createEntry(ConvertUtils.CONSUMER_TYPE_UID_BATTERY).isUserEntry()) + .isFalse(); + } + + private static BatteryHistEntry createEntry(int consumerType) { + return new BatteryHistEntry(getContentValuesWithType(consumerType)); + } + private static ContentValues getContentValuesWithType(int consumerType) { final ContentValues values = new ContentValues(); values.put("consumerType", Integer.valueOf(consumerType));