Merge "Disable app usage item if this item is not clickable" into sc-dev
diff --git a/src/com/android/settings/fuelgauge/BatteryChartPreferenceController.java b/src/com/android/settings/fuelgauge/BatteryChartPreferenceController.java
index dbbafe6..ffbd2d9 100644
--- a/src/com/android/settings/fuelgauge/BatteryChartPreferenceController.java
+++ b/src/com/android/settings/fuelgauge/BatteryChartPreferenceController.java
@@ -189,6 +189,8 @@
mPrefContext = screen.getContext();
mAppListPrefGroup = screen.findPreference(mPreferenceKey);
mAppListPrefGroup.setOrderingAsAdded(false);
+ mAppListPrefGroup.setTitle(
+ mPrefContext.getString(R.string.battery_app_usage_for_past_24));
mFooterPreference = screen.findPreference(KEY_FOOTER_PREF);
// Removes footer first until usage data is loaded to avoid flashing.
if (mFooterPreference != null) {
@@ -216,15 +218,6 @@
final BatteryHistEntry histEntry = diffEntry.mBatteryHistEntry;
final String packageName = histEntry.mPackageName;
final boolean isAppEntry = histEntry.isAppEntry();
- // Checks whether the package is installed or not.
- boolean isValidPackage = true;
- if (isAppEntry) {
- if (mBatteryUtils == null) {
- mBatteryUtils = BatteryUtils.getInstance(mPrefContext);
- }
- isValidPackage = mBatteryUtils.getPackageUid(packageName)
- != BatteryUtils.UID_NULL;
- }
mMetricsFeatureProvider.action(
mPrefContext,
isAppEntry
@@ -233,15 +226,12 @@
new Pair(ConvertUtils.METRIC_KEY_PACKAGE, packageName),
new Pair(ConvertUtils.METRIC_KEY_BATTERY_LEVEL, histEntry.mBatteryLevel),
new Pair(ConvertUtils.METRIC_KEY_BATTERY_USAGE, powerPref.getPercent()));
- Log.d(TAG, String.format("handleClick() label=%s key=%s isValid:%b\n%s",
- diffEntry.getAppLabel(), histEntry.getKey(), isValidPackage, histEntry));
- if (isValidPackage) {
- AdvancedPowerUsageDetail.startBatteryDetailPage(
+ Log.d(TAG, String.format("handleClick() label=%s key=%s enntry=\n%s",
+ diffEntry.getAppLabel(), histEntry.getKey(), histEntry));
+ AdvancedPowerUsageDetail.startBatteryDetailPage(
mActivity, mFragment, diffEntry, powerPref.getPercent(),
isValidToShowSummary(packageName), getSlotInformation());
- return true;
- }
- return false;
+ return true;
}
@Override
@@ -434,6 +424,7 @@
pref.setSingleLineTitle(true);
// Sets the BatteryDiffEntry to preference for launching detailed page.
pref.setBatteryDiffEntry(entry);
+ pref.setEnabled(entry.validForRestriction());
setPreferenceSummary(pref, entry);
if (!isAdded) {
mAppListPrefGroup.addPreference(pref);
diff --git a/src/com/android/settings/fuelgauge/BatteryDiffEntry.java b/src/com/android/settings/fuelgauge/BatteryDiffEntry.java
index 9db29f3..c6b2d45 100644
--- a/src/com/android/settings/fuelgauge/BatteryDiffEntry.java
+++ b/src/com/android/settings/fuelgauge/BatteryDiffEntry.java
@@ -39,6 +39,8 @@
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?
+ static final Map<String, Boolean> sValidForRestriction = new HashMap<>();
/** A comparator for {@link BatteryDiffEntry} based on consumed percentage. */
public static final Comparator<BatteryDiffEntry> COMPARATOR =
@@ -60,6 +62,7 @@
@VisibleForTesting String mAppLabel = null;
@VisibleForTesting Drawable mAppIcon = null;
@VisibleForTesting boolean mIsLoaded = false;
+ @VisibleForTesting boolean mValidForRestriction = true;
public BatteryDiffEntry(
Context context,
@@ -129,6 +132,12 @@
? mDefaultPackageName : mBatteryHistEntry.mPackageName;
}
+ /** Whether this item is valid for users to launch restriction page? */
+ public boolean validForRestriction() {
+ loadLabelAndIcon();
+ return mValidForRestriction;
+ }
+
/** Whether the current BatteryDiffEntry is system component or not. */
public boolean isSystemEntry() {
switch (mBatteryHistEntry.mConsumerType) {
@@ -146,7 +155,29 @@
if (mIsLoaded) {
return;
}
+ // Checks whether we have cached data or not first before fetching.
+ final BatteryEntry.NameAndIcon nameAndIcon = getCache();
+ if (nameAndIcon != null) {
+ mAppLabel = nameAndIcon.name;
+ mAppIcon = nameAndIcon.icon;
+ mAppIconId = nameAndIcon.iconId;
+ }
+ final Boolean validForRestriction = sValidForRestriction.get(getKey());
+ if (validForRestriction != null) {
+ mValidForRestriction = validForRestriction;
+ }
+ // Both nameAndIcon and restriction configuration have cached data.
+ if (nameAndIcon != null && validForRestriction != null) {
+ Log.w(TAG, String.format("cannot find cache data nameAndIcon:%s "
+ + "validForRestriction:%s", nameAndIcon, validForRestriction));
+ return;
+ }
mIsLoaded = true;
+
+ // Configures whether we can launch restriction page or not.
+ updateRestrictionFlagState();
+ sValidForRestriction.put(getKey(), Boolean.valueOf(mValidForRestriction));
+
// Loads application icon and label based on consumer type.
switch (mBatteryHistEntry.mConsumerType) {
case ConvertUtils.CONSUMER_TYPE_USER_BATTERY:
@@ -156,6 +187,9 @@
if (nameAndIconForUser != null) {
mAppIcon = nameAndIconForUser.icon;
mAppLabel = nameAndIconForUser.name;
+ sResourceCache.put(
+ getKey(),
+ new BatteryEntry.NameAndIcon(mAppLabel, mAppIcon, /*iconId=*/ 0));
}
break;
case ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY:
@@ -168,15 +202,12 @@
mAppIconId = nameAndIconForSystem.iconId;
mAppIcon = mContext.getDrawable(nameAndIconForSystem.iconId);
}
+ sResourceCache.put(
+ getKey(),
+ new BatteryEntry.NameAndIcon(mAppLabel, mAppIcon, mAppIconId));
}
break;
case ConvertUtils.CONSUMER_TYPE_UID_BATTERY:
- final BatteryEntry.NameAndIcon nameAndIcon = getCache();
- if (nameAndIcon != null) {
- mAppLabel = nameAndIcon.name;
- mAppIcon = nameAndIcon.icon;
- break;
- }
loadNameAndIconForUid();
// Uses application default icon if we cannot find it from package.
if (mAppIcon == null) {
@@ -186,13 +217,47 @@
mAppIcon = getBadgeIconForUser(mAppIcon);
if (mAppLabel != null || mAppIcon != null) {
sResourceCache.put(
- mBatteryHistEntry.getKey(),
+ getKey(),
new BatteryEntry.NameAndIcon(mAppLabel, mAppIcon, /*iconId=*/ 0));
}
break;
}
}
+ @VisibleForTesting
+ String getKey() {
+ return mBatteryHistEntry.getKey();
+ }
+
+ @VisibleForTesting
+ void updateRestrictionFlagState() {
+ mValidForRestriction = true;
+ if (!mBatteryHistEntry.isAppEntry()) {
+ return;
+ }
+ final boolean isValidPackage =
+ BatteryUtils.getInstance(mContext).getPackageUid(getPackageName())
+ != BatteryUtils.UID_NULL;
+ if (!isValidPackage) {
+ mValidForRestriction = false;
+ return;
+ }
+ try {
+ mValidForRestriction =
+ mContext.getPackageManager().getPackageInfo(
+ getPackageName(),
+ PackageManager.MATCH_DISABLED_COMPONENTS
+ | PackageManager.MATCH_ANY_USER
+ | PackageManager.GET_SIGNATURES
+ | PackageManager.GET_PERMISSIONS)
+ != null;
+ } catch (Exception e) {
+ Log.e(TAG, String.format("getPackageInfo() error %s for package=%s",
+ e.getCause(), getPackageName()));
+ mValidForRestriction = false;
+ }
+ }
+
private BatteryEntry.NameAndIcon getCache() {
final Locale locale = Locale.getDefault();
if (sCurrentLocale != locale) {
@@ -201,7 +266,7 @@
sCurrentLocale = locale;
clearCache();
}
- return sResourceCache.get(mBatteryHistEntry.getKey());
+ return sResourceCache.get(getKey());
}
private void loadNameAndIconForUid() {
@@ -258,7 +323,8 @@
public String toString() {
final StringBuilder builder = new StringBuilder()
.append("BatteryDiffEntry{")
- .append("\n\tname=" + mAppLabel)
+ .append(String.format("\n\tname=%s restrictable=%b",
+ mAppLabel, mValidForRestriction))
.append(String.format("\n\tconsume=%.2f%% %f/%f",
mPercentOfTotal, mConsumePower, mTotalConsumePower))
.append(String.format("\n\tforeground:%s background:%s",
@@ -274,6 +340,7 @@
static void clearCache() {
sResourceCache.clear();
+ sValidForRestriction.clear();
}
private Drawable getBadgeIconForUser(Drawable icon) {
diff --git a/src/com/android/settings/fuelgauge/BatteryEntry.java b/src/com/android/settings/fuelgauge/BatteryEntry.java
index 636d265..125409c 100644
--- a/src/com/android/settings/fuelgauge/BatteryEntry.java
+++ b/src/com/android/settings/fuelgauge/BatteryEntry.java
@@ -241,7 +241,10 @@
mBatteryConsumer = null;
mIsHidden = false;
mPowerComponentId = powerComponentId;
- mConsumedPower = devicePowerMah;
+ mConsumedPower =
+ powerComponentId == BatteryConsumer.POWER_COMPONENT_SCREEN
+ ? devicePowerMah
+ : devicePowerMah - appsPowerMah;
mUsageDurationMs = usageDurationMs;
mConsumerType = ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY;
@@ -264,8 +267,10 @@
iconId = R.drawable.ic_power_system;
icon = context.getDrawable(iconId);
name = powerComponentName;
-
- mConsumedPower = devicePowerMah;
+ mConsumedPower =
+ powerComponentId == BatteryConsumer.POWER_COMPONENT_SCREEN
+ ? devicePowerMah
+ : devicePowerMah - appsPowerMah;
mConsumerType = ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY;
}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryChartPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryChartPreferenceControllerTest.java
index 9e2f65d..606dc19 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryChartPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryChartPreferenceControllerTest.java
@@ -307,6 +307,7 @@
doReturn(appLabel).when(mBatteryDiffEntry).getAppLabel();
doReturn(PREF_KEY).when(mBatteryHistEntry).getKey();
doReturn(null).when(mAppListGroup).findPreference(PREF_KEY);
+ doReturn(false).when(mBatteryDiffEntry).validForRestriction();
mBatteryChartPreferenceController.addPreferenceToScreen(
Arrays.asList(mBatteryDiffEntry));
@@ -324,6 +325,7 @@
assertThat(pref.getOrder()).isEqualTo(1);
assertThat(pref.getBatteryDiffEntry()).isSameInstanceAs(mBatteryDiffEntry);
assertThat(pref.isSingleLineTitle()).isTrue();
+ assertThat(pref.isEnabled()).isFalse();
}
@Test
@@ -353,7 +355,7 @@
}
@Test
- public void testHandlePreferenceTreeClick_validPackageName_returnTrue() {
+ public void testHandlePreferenceTreeClick_forAppEntry_returnTrue() {
doReturn(false).when(mBatteryHistEntry).isAppEntry();
doReturn(mBatteryDiffEntry).when(mPowerGaugePreference).getBatteryDiffEntry();
@@ -371,15 +373,13 @@
}
@Test
- public void testHandlePreferenceTreeClick_appEntryWithInvalidPackage_returnFalse() {
+ public void testHandlePreferenceTreeClick_forSystemEntry_returnTrue() {
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();
+ mPowerGaugePreference)).isTrue();
verify(mMetricsFeatureProvider)
.action(
mContext,
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryDiffEntryTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryDiffEntryTest.java
index 5860163..0df53f1 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryDiffEntryTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryDiffEntryTest.java
@@ -17,12 +17,15 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Matchers.anyInt;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import android.content.ContentValues;
import android.content.Context;
import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
import android.os.BatteryConsumer;
@@ -56,11 +59,13 @@
@Mock private Drawable mockDrawable2;
@Mock private Drawable mockBadgedDrawable;
@Mock private BatteryHistEntry mBatteryHistEntry;
+ @Mock private PackageInfo mockPackageInfo;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = spy(RuntimeEnvironment.application);
+ doReturn(mContext).when(mContext).getApplicationContext();
doReturn(mockUserManager).when(mContext).getSystemService(UserManager.class);
doReturn(mockPackageManager).when(mContext).getPackageManager();
BatteryDiffEntry.clearCache();
@@ -110,6 +115,7 @@
@Test
public void testLoadLabelAndIcon_forSystemBattery_returnExpectedResult() {
+ final String expectedName = "Ambient display";
// Generates fake testing data.
final ContentValues values = getContentValuesWithType(
ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY);
@@ -119,13 +125,22 @@
final BatteryDiffEntry entry = createBatteryDiffEntry(10, batteryHistEntry);
- assertThat(entry.getAppLabel()).isEqualTo("Ambient display");
+ assertThat(entry.getAppLabel()).isEqualTo(expectedName);
assertThat(entry.getAppIconId()).isEqualTo(R.drawable.ic_settings_aod);
- assertThat(BatteryDiffEntry.sResourceCache).isEmpty();
+ assertThat(BatteryDiffEntry.sResourceCache).hasSize(1);
+ // Verifies the app label in the cache.
+ final BatteryEntry.NameAndIcon nameAndIcon =
+ BatteryDiffEntry.sResourceCache.get(entry.getKey());
+ assertThat(nameAndIcon.name).isEqualTo(expectedName);
+ assertThat(nameAndIcon.iconId).isEqualTo(R.drawable.ic_settings_aod);
+ // Verifies the restrictable flag in the cache.
+ assertThat(entry.mValidForRestriction).isTrue();
+ assertThat(BatteryDiffEntry.sValidForRestriction.get(entry.getKey())).isTrue();
}
@Test
public void testLoadLabelAndIcon_forUserBattery_returnExpectedResult() {
+ final String expectedName = "Removed user";
doReturn(null).when(mockUserManager).getUserInfo(1001);
// Generates fake testing data.
final ContentValues values = getContentValuesWithType(
@@ -135,10 +150,18 @@
final BatteryDiffEntry entry = createBatteryDiffEntry(10, batteryHistEntry);
- assertThat(entry.getAppLabel()).isEqualTo("Removed user");
+ assertThat(entry.getAppLabel()).isEqualTo(expectedName);
assertThat(entry.getAppIcon()).isNull();
assertThat(entry.getAppIconId()).isEqualTo(0);
- assertThat(BatteryDiffEntry.sResourceCache).isEmpty();
+ assertThat(BatteryDiffEntry.sResourceCache).hasSize(1);
+ // Verifies the app label in the cache.
+ final BatteryEntry.NameAndIcon nameAndIcon =
+ BatteryDiffEntry.sResourceCache.get(entry.getKey());
+ assertThat(nameAndIcon.name).isEqualTo(expectedName);
+ assertThat(nameAndIcon.iconId).isEqualTo(0);
+ // Verifies the restrictable flag in the cache.
+ assertThat(entry.mValidForRestriction).isTrue();
+ assertThat(BatteryDiffEntry.sValidForRestriction.get(entry.getKey())).isTrue();
}
@Test
@@ -162,8 +185,11 @@
assertThat(BatteryDiffEntry.sResourceCache).hasSize(1);
// Verifies the app label in the cache.
final BatteryEntry.NameAndIcon nameAndIcon =
- BatteryDiffEntry.sResourceCache.get(batteryHistEntry.getKey());
+ BatteryDiffEntry.sResourceCache.get(entry.getKey());
assertThat(nameAndIcon.name).isEqualTo(expectedAppLabel);
+ // Verifies the restrictable flag in the cache.
+ assertThat(entry.mValidForRestriction).isFalse();
+ assertThat(BatteryDiffEntry.sValidForRestriction.get(entry.getKey())).isFalse();
}
@Test
@@ -179,7 +205,7 @@
assertThat(BatteryDiffEntry.sResourceCache).hasSize(1);
// Verifies the app label in the cache.
final BatteryEntry.NameAndIcon nameAndIcon =
- BatteryDiffEntry.sResourceCache.get(batteryHistEntry.getKey());
+ BatteryDiffEntry.sResourceCache.get(entry.getKey());
assertThat(nameAndIcon.name).isEqualTo(expectedAppLabel);
}
@@ -225,11 +251,25 @@
assertThat(BatteryDiffEntry.sResourceCache).hasSize(1);
// Verifies the app label in the cache.
final BatteryEntry.NameAndIcon nameAndIcon =
- BatteryDiffEntry.sResourceCache.get(entry.mBatteryHistEntry.getKey());
+ BatteryDiffEntry.sResourceCache.get(entry.getKey());
assertThat(nameAndIcon.icon).isEqualTo(mockBadgedDrawable);
}
@Test
+ public void testClearCache_clearDataForResourcesAndFlags() {
+ BatteryDiffEntry.sResourceCache.put(
+ "fake application key",
+ new BatteryEntry.NameAndIcon("app label", null, /*iconId=*/ 0));
+ BatteryDiffEntry.sValidForRestriction.put(
+ "fake application key", Boolean.valueOf(false));
+
+ BatteryDiffEntry.clearCache();
+
+ assertThat(BatteryDiffEntry.sResourceCache).isEmpty();
+ assertThat(BatteryDiffEntry.sValidForRestriction).isEmpty();
+ }
+
+ @Test
public void testClearCache_switchLocale_clearCacheIconAndLabel() throws Exception {
final int userId = UserHandle.getUserId(1001);
doReturn(mockBadgedDrawable).when(mockUserManager)
@@ -248,7 +288,7 @@
assertThat(entry2.getAppIcon()).isEqualTo(mockDrawable2);
// Verifies the cache is updated into the new drawable.
final BatteryEntry.NameAndIcon nameAndIcon =
- BatteryDiffEntry.sResourceCache.get(entry2.mBatteryHistEntry.getKey());
+ BatteryDiffEntry.sResourceCache.get(entry2.getKey());
assertThat(nameAndIcon.icon).isEqualTo(mockDrawable2);
}
@@ -297,6 +337,40 @@
assertThat(entry.isSystemEntry()).isTrue();
}
+ @Test
+ public void testUpdateRestrictionFlagState_updateFlagAsExpected() 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);
+ final BatteryDiffEntry entry =
+ createBatteryDiffEntry(10, new BatteryHistEntry(values));
+
+ entry.updateRestrictionFlagState();
+ // Sets false if the app entry cannot be found.
+ assertThat(entry.mValidForRestriction).isFalse();
+
+ doReturn(BatteryUtils.UID_NULL).when(mockPackageManager).getPackageUid(
+ entry.getPackageName(), PackageManager.GET_META_DATA);
+ entry.updateRestrictionFlagState();
+ // Sets false if the app is invalid package name.
+ assertThat(entry.mValidForRestriction).isFalse();
+
+ doReturn(1000).when(mockPackageManager).getPackageUid(
+ entry.getPackageName(), PackageManager.GET_META_DATA);
+ entry.updateRestrictionFlagState();
+ // Sets false if the app PackageInfo cannot be found.
+ assertThat(entry.mValidForRestriction).isFalse();
+
+ doReturn(mockPackageInfo).when(mockPackageManager).getPackageInfo(
+ eq(entry.getPackageName()), anyInt());
+ entry.updateRestrictionFlagState();
+ // Sets true if package is valid and PackageInfo can be found.
+ assertThat(entry.mValidForRestriction).isTrue();
+ }
+
private BatteryDiffEntry createBatteryDiffEntry(
int consumerType, long uid, boolean isHidden) {
final ContentValues values = getContentValuesWithType(consumerType);