Add battery usage time summary to usage list item
Insert app foregound and background usage time information into the preference item summary based on the different scenarios. Bug: 177406865 Test: make SettingsRoboTests Test: make SettingsGoogleRoboTests Change-Id: I13ba357666adfb7b57f52ffae18d09aed8dd0773
This commit is contained in:
@@ -6361,7 +6361,14 @@
|
|||||||
<string name="battery_usage_time_am">am</string>
|
<string name="battery_usage_time_am">am</string>
|
||||||
<!-- [CHAR_LIMIT=NONE] Battery usage section header for a specific time slot -->
|
<!-- [CHAR_LIMIT=NONE] Battery usage section header for a specific time slot -->
|
||||||
<string name="battery_usage_time_pm">pm</string>
|
<string name="battery_usage_time_pm">pm</string>
|
||||||
|
<!-- [CHAR_LIMIT=NONE] Battery usage item for total usage time less than a minute -->
|
||||||
|
<string name="battery_usage_total_less_than_one_minute">Total: less than a min</string>
|
||||||
|
<!-- [CHAR_LIMIT=NONE] Battery usage item for total background time less than a minute -->
|
||||||
|
<string name="battery_usage_background_less_than_one_minute">Background: less than a min</string>
|
||||||
|
<!-- [CHAR_LIMIT=NONE] Battery usage item for total usage time -->
|
||||||
|
<string name="battery_usage_for_total_time">Total: <xliff:g id="time">%s</xliff:g></string>
|
||||||
|
<!-- [CHAR_LIMIT=NONE] Battery usage item for background usage time -->
|
||||||
|
<string name="battery_usage_for_background_time">Background: <xliff:g id="time">%s</xliff:g></string>
|
||||||
<!-- Process Stats strings -->
|
<!-- Process Stats strings -->
|
||||||
<skip />
|
<skip />
|
||||||
|
|
||||||
|
@@ -22,6 +22,7 @@ import android.graphics.drawable.Drawable;
|
|||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
import android.text.format.DateUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import androidx.annotation.VisibleForTesting;
|
import androidx.annotation.VisibleForTesting;
|
||||||
@@ -38,6 +39,7 @@ import com.android.settingslib.core.lifecycle.Lifecycle;
|
|||||||
import com.android.settingslib.core.lifecycle.LifecycleObserver;
|
import com.android.settingslib.core.lifecycle.LifecycleObserver;
|
||||||
import com.android.settingslib.core.lifecycle.events.OnDestroy;
|
import com.android.settingslib.core.lifecycle.events.OnDestroy;
|
||||||
import com.android.settingslib.core.lifecycle.events.OnPause;
|
import com.android.settingslib.core.lifecycle.events.OnPause;
|
||||||
|
import com.android.settingslib.utils.StringUtil;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -70,6 +72,7 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
|
|||||||
private final SettingsActivity mActivity;
|
private final SettingsActivity mActivity;
|
||||||
private final InstrumentedPreferenceFragment mFragment;
|
private final InstrumentedPreferenceFragment mFragment;
|
||||||
private final Handler mHandler = new Handler(Looper.getMainLooper());
|
private final Handler mHandler = new Handler(Looper.getMainLooper());
|
||||||
|
private final CharSequence[] mNotAllowShowSummaryPackages;
|
||||||
|
|
||||||
// Preference cache to avoid create new instance each time.
|
// Preference cache to avoid create new instance each time.
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
@@ -83,6 +86,8 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
|
|||||||
mActivity = activity;
|
mActivity = activity;
|
||||||
mFragment = fragment;
|
mFragment = fragment;
|
||||||
mPreferenceKey = preferenceKey;
|
mPreferenceKey = preferenceKey;
|
||||||
|
mNotAllowShowSummaryPackages = context.getResources()
|
||||||
|
.getTextArray(R.array.allowlist_hide_summary_in_battery_usage);
|
||||||
if (lifecycle != null) {
|
if (lifecycle != null) {
|
||||||
lifecycle.addObserver(this);
|
lifecycle.addObserver(this);
|
||||||
}
|
}
|
||||||
@@ -139,8 +144,9 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
|
|||||||
isValidPackage = mBatteryUtils.getPackageUid(histEntry.mPackageName)
|
isValidPackage = mBatteryUtils.getPackageUid(histEntry.mPackageName)
|
||||||
!= BatteryUtils.UID_NULL;
|
!= BatteryUtils.UID_NULL;
|
||||||
}
|
}
|
||||||
Log.d(TAG, String.format("handleClick() label=%s key=%s isValid:%b",
|
Log.d(TAG, String.format("handleClick() label=%s key=%s isValid:%b %s",
|
||||||
diffEntry.getAppLabel(), histEntry.getKey(), isValidPackage));
|
diffEntry.getAppLabel(), histEntry.getKey(), isValidPackage,
|
||||||
|
histEntry.mPackageName));
|
||||||
if (isValidPackage) {
|
if (isValidPackage) {
|
||||||
AdvancedPowerUsageDetail.startBatteryDetailPage(
|
AdvancedPowerUsageDetail.startBatteryDetailPage(
|
||||||
mActivity, mFragment, diffEntry, powerPref.getPercent());
|
mActivity, mFragment, diffEntry, powerPref.getPercent());
|
||||||
@@ -299,8 +305,10 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
|
|||||||
pref.setTitle(appLabel);
|
pref.setTitle(appLabel);
|
||||||
pref.setOrder(prefIndex);
|
pref.setOrder(prefIndex);
|
||||||
pref.setPercent(entry.getPercentOfTotal());
|
pref.setPercent(entry.getPercentOfTotal());
|
||||||
|
pref.setSingleLineTitle(true);
|
||||||
// Sets the BatteryDiffEntry to preference for launching detailed page.
|
// Sets the BatteryDiffEntry to preference for launching detailed page.
|
||||||
pref.setBatteryDiffEntry(entry);
|
pref.setBatteryDiffEntry(entry);
|
||||||
|
setPreferenceSummary(pref, entry);
|
||||||
mAppListPrefGroup.addPreference(pref);
|
mAppListPrefGroup.addPreference(pref);
|
||||||
prefIndex++;
|
prefIndex++;
|
||||||
}
|
}
|
||||||
@@ -322,6 +330,57 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
|
|||||||
mAppListPrefGroup.removeAll();
|
mAppListPrefGroup.removeAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
void setPreferenceSummary(
|
||||||
|
PowerGaugePreference preference, BatteryDiffEntry entry) {
|
||||||
|
final long foregroundUsageTimeInMs = entry.mForegroundUsageTimeInMs;
|
||||||
|
final long backgroundUsageTimeInMs = entry.mBackgroundUsageTimeInMs;
|
||||||
|
final long totalUsageTimeInMs = foregroundUsageTimeInMs + backgroundUsageTimeInMs;
|
||||||
|
// Checks whether the package is allowed to show summary or not.
|
||||||
|
for (CharSequence notAllowPackageName : mNotAllowShowSummaryPackages) {
|
||||||
|
if (TextUtils.equals(entry.getPackageName(), notAllowPackageName)) {
|
||||||
|
preference.setSummary(null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
String usageTimeSummary = null;
|
||||||
|
// Not shows summary for some system components without usage time.
|
||||||
|
if (totalUsageTimeInMs == 0) {
|
||||||
|
preference.setSummary(null);
|
||||||
|
// Shows background summary only if we don't have foreground usage time.
|
||||||
|
} else if (foregroundUsageTimeInMs == 0 && backgroundUsageTimeInMs != 0) {
|
||||||
|
usageTimeSummary = buildUsageTimeInfo(backgroundUsageTimeInMs, true);
|
||||||
|
// Shows total usage summary only if total usage time is small.
|
||||||
|
} else if (totalUsageTimeInMs < DateUtils.MINUTE_IN_MILLIS) {
|
||||||
|
usageTimeSummary = buildUsageTimeInfo(totalUsageTimeInMs, false);
|
||||||
|
} else {
|
||||||
|
usageTimeSummary = buildUsageTimeInfo(totalUsageTimeInMs, false);
|
||||||
|
// Shows background usage time if it is larger than a minute.
|
||||||
|
if (backgroundUsageTimeInMs >= DateUtils.MINUTE_IN_MILLIS) {
|
||||||
|
usageTimeSummary +=
|
||||||
|
"\n" + buildUsageTimeInfo(backgroundUsageTimeInMs, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
preference.setSummary(usageTimeSummary);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String buildUsageTimeInfo(long usageTimeInMs, boolean isBackground) {
|
||||||
|
if (usageTimeInMs < DateUtils.MINUTE_IN_MILLIS) {
|
||||||
|
return mPrefContext.getString(
|
||||||
|
isBackground
|
||||||
|
? R.string.battery_usage_background_less_than_one_minute
|
||||||
|
: R.string.battery_usage_total_less_than_one_minute);
|
||||||
|
}
|
||||||
|
final CharSequence timeSequence =
|
||||||
|
StringUtil.formatElapsedTime(mPrefContext, usageTimeInMs,
|
||||||
|
/*withSeconds=*/ false, /*collapseTimeUnit=*/ false);
|
||||||
|
final int resourceId =
|
||||||
|
isBackground
|
||||||
|
? R.string.battery_usage_for_background_time
|
||||||
|
: R.string.battery_usage_for_total_time;
|
||||||
|
return mPrefContext.getString(resourceId, timeSequence);
|
||||||
|
}
|
||||||
|
|
||||||
private static String utcToLocalTime(long[] timestamps) {
|
private static String utcToLocalTime(long[] timestamps) {
|
||||||
final StringBuilder builder = new StringBuilder();
|
final StringBuilder builder = new StringBuilder();
|
||||||
for (int index = 0; index < timestamps.length; index++) {
|
for (int index = 0; index < timestamps.length; index++) {
|
||||||
|
@@ -210,12 +210,17 @@ public class BatteryDiffEntry {
|
|||||||
packageManager.getApplicationInfo(packageName, /*no flags*/ 0);
|
packageManager.getApplicationInfo(packageName, /*no flags*/ 0);
|
||||||
if (appInfo != null) {
|
if (appInfo != null) {
|
||||||
mAppLabel = packageManager.getApplicationLabel(appInfo).toString();
|
mAppLabel = packageManager.getApplicationLabel(appInfo).toString();
|
||||||
|
mAppIcon = packageManager.getApplicationIcon(appInfo);
|
||||||
}
|
}
|
||||||
} catch (NameNotFoundException e) {
|
} catch (NameNotFoundException e) {
|
||||||
Log.e(TAG, "failed to retrieve ApplicationInfo for: " + packageName);
|
Log.e(TAG, "failed to retrieve ApplicationInfo for: " + packageName);
|
||||||
mAppLabel = packageName;
|
mAppLabel = packageName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Early return if we found the app label and icon resource.
|
||||||
|
if (mAppLabel != null && mAppIcon != null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
final int uid = (int) mBatteryHistEntry.mUid;
|
final int uid = (int) mBatteryHistEntry.mUid;
|
||||||
final String[] packages = packageManager.getPackagesForUid(uid);
|
final String[] packages = packageManager.getPackagesForUid(uid);
|
||||||
|
@@ -30,7 +30,9 @@ import android.content.Context;
|
|||||||
import android.content.ContentValues;
|
import android.content.ContentValues;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.text.format.DateUtils;
|
||||||
|
|
||||||
|
import androidx.preference.Preference;
|
||||||
import androidx.preference.PreferenceGroup;
|
import androidx.preference.PreferenceGroup;
|
||||||
|
|
||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
@@ -274,6 +276,7 @@ public final class BatteryChartPreferenceControllerTest {
|
|||||||
assertThat(pref.getIcon()).isEqualTo(mDrawable);
|
assertThat(pref.getIcon()).isEqualTo(mDrawable);
|
||||||
assertThat(pref.getOrder()).isEqualTo(1);
|
assertThat(pref.getOrder()).isEqualTo(1);
|
||||||
assertThat(pref.getBatteryDiffEntry()).isSameInstanceAs(mBatteryDiffEntry);
|
assertThat(pref.getBatteryDiffEntry()).isSameInstanceAs(mBatteryDiffEntry);
|
||||||
|
assertThat(pref.isSingleLineTitle()).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -303,7 +306,82 @@ public final class BatteryChartPreferenceControllerTest {
|
|||||||
mPowerGaugePreference)).isFalse();
|
mPowerGaugePreference)).isFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<Long, List<BatteryHistEntry>> createBatteryHistoryMap(int size) {
|
@Test
|
||||||
|
public void testSetPreferenceSummary_setNullContentIfTotalUsageTimeIsZero() {
|
||||||
|
final PowerGaugePreference pref = new PowerGaugePreference(mContext);
|
||||||
|
pref.setSummary("fake preference summary");
|
||||||
|
|
||||||
|
mBatteryChartPreferenceController.setPreferenceSummary(
|
||||||
|
pref, createBatteryDiffEntry(
|
||||||
|
/*foregroundUsageTimeInMs=*/ 0,
|
||||||
|
/*backgroundUsageTimeInMs=*/ 0));
|
||||||
|
assertThat(pref.getSummary()).isNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSetPreferenceSummary_setBackgroundUsageTimeOnly() {
|
||||||
|
final PowerGaugePreference pref = new PowerGaugePreference(mContext);
|
||||||
|
pref.setSummary("fake preference summary");
|
||||||
|
|
||||||
|
mBatteryChartPreferenceController.setPreferenceSummary(
|
||||||
|
pref, createBatteryDiffEntry(
|
||||||
|
/*foregroundUsageTimeInMs=*/ 0,
|
||||||
|
/*backgroundUsageTimeInMs=*/ DateUtils.MINUTE_IN_MILLIS));
|
||||||
|
assertThat(pref.getSummary()).isEqualTo("Background: 1 min");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSetPreferenceSummary_setTotalUsageTimeLessThanAMinute() {
|
||||||
|
final PowerGaugePreference pref = new PowerGaugePreference(mContext);
|
||||||
|
pref.setSummary("fake preference summary");
|
||||||
|
|
||||||
|
mBatteryChartPreferenceController.setPreferenceSummary(
|
||||||
|
pref, createBatteryDiffEntry(
|
||||||
|
/*foregroundUsageTimeInMs=*/ 100,
|
||||||
|
/*backgroundUsageTimeInMs=*/ 200));
|
||||||
|
assertThat(pref.getSummary()).isEqualTo("Total: less than a min");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSetPreferenceSummary_setTotalTimeIfBackgroundTimeLessThanAMinute() {
|
||||||
|
final PowerGaugePreference pref = new PowerGaugePreference(mContext);
|
||||||
|
pref.setSummary("fake preference summary");
|
||||||
|
|
||||||
|
mBatteryChartPreferenceController.setPreferenceSummary(
|
||||||
|
pref, createBatteryDiffEntry(
|
||||||
|
/*foregroundUsageTimeInMs=*/ DateUtils.MINUTE_IN_MILLIS,
|
||||||
|
/*backgroundUsageTimeInMs=*/ 200));
|
||||||
|
assertThat(pref.getSummary()).isEqualTo("Total: 1 min");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSetPreferenceSummary_setTotalAndBackgroundUsageTime() {
|
||||||
|
final PowerGaugePreference pref = new PowerGaugePreference(mContext);
|
||||||
|
pref.setSummary("fake preference summary");
|
||||||
|
|
||||||
|
mBatteryChartPreferenceController.setPreferenceSummary(
|
||||||
|
pref, createBatteryDiffEntry(
|
||||||
|
/*foregroundUsageTimeInMs=*/ DateUtils.MINUTE_IN_MILLIS,
|
||||||
|
/*backgroundUsageTimeInMs=*/ DateUtils.MINUTE_IN_MILLIS));
|
||||||
|
assertThat(pref.getSummary()).isEqualTo("Total: 2 min\nBackground: 1 min");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSetPreferenceSummary_notAllowShownPackage_setSummayAsNull() {
|
||||||
|
final PowerGaugePreference pref = new PowerGaugePreference(mContext);
|
||||||
|
pref.setSummary("fake preference summary");
|
||||||
|
final BatteryDiffEntry batteryDiffEntry =
|
||||||
|
spy(createBatteryDiffEntry(
|
||||||
|
/*foregroundUsageTimeInMs=*/ DateUtils.MINUTE_IN_MILLIS,
|
||||||
|
/*backgroundUsageTimeInMs=*/ DateUtils.MINUTE_IN_MILLIS));
|
||||||
|
doReturn("com.google.android.googlequicksearchbox").when(batteryDiffEntry)
|
||||||
|
.getPackageName();
|
||||||
|
|
||||||
|
mBatteryChartPreferenceController.setPreferenceSummary(pref, batteryDiffEntry);
|
||||||
|
assertThat(pref.getSummary()).isNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Map<Long, List<BatteryHistEntry>> createBatteryHistoryMap(int size) {
|
||||||
final Map<Long, List<BatteryHistEntry>> batteryHistoryMap = new HashMap<>();
|
final Map<Long, List<BatteryHistEntry>> batteryHistoryMap = new HashMap<>();
|
||||||
for (int index = 0; index < size; index++) {
|
for (int index = 0; index < size; index++) {
|
||||||
final ContentValues values = new ContentValues();
|
final ContentValues values = new ContentValues();
|
||||||
@@ -313,4 +391,11 @@ public final class BatteryChartPreferenceControllerTest {
|
|||||||
}
|
}
|
||||||
return batteryHistoryMap;
|
return batteryHistoryMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private BatteryDiffEntry createBatteryDiffEntry(
|
||||||
|
long foregroundUsageTimeInMs, long backgroundUsageTimeInMs) {
|
||||||
|
return new BatteryDiffEntry(
|
||||||
|
mContext, foregroundUsageTimeInMs, backgroundUsageTimeInMs,
|
||||||
|
/*consumePower=*/ 0, mBatteryHistEntry);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user