Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7cc616e9 authored by ykhung's avatar ykhung Committed by YUKAI HUNG
Browse files

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
parent a3017822
Loading
Loading
Loading
Loading
+8 −1
Original line number Diff line number Diff line
@@ -6361,7 +6361,14 @@
    <string name="battery_usage_time_am">am</string>
    <!-- [CHAR_LIMIT=NONE] Battery usage section header for a specific time slot -->
    <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 -->
    <skip />
+61 −2
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;
import android.text.format.DateUtils;
import android.util.Log;

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.events.OnDestroy;
import com.android.settingslib.core.lifecycle.events.OnPause;
import com.android.settingslib.utils.StringUtil;

import java.util.Arrays;
import java.util.ArrayList;
@@ -70,6 +72,7 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
    private final SettingsActivity mActivity;
    private final InstrumentedPreferenceFragment mFragment;
    private final Handler mHandler = new Handler(Looper.getMainLooper());
    private final CharSequence[] mNotAllowShowSummaryPackages;

    // Preference cache to avoid create new instance each time.
    @VisibleForTesting
@@ -83,6 +86,8 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
        mActivity = activity;
        mFragment = fragment;
        mPreferenceKey = preferenceKey;
        mNotAllowShowSummaryPackages = context.getResources()
            .getTextArray(R.array.allowlist_hide_summary_in_battery_usage);
        if (lifecycle != null) {
            lifecycle.addObserver(this);
        }
@@ -139,8 +144,9 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
            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));
        Log.d(TAG, String.format("handleClick() label=%s key=%s isValid:%b %s",
            diffEntry.getAppLabel(), histEntry.getKey(), isValidPackage,
            histEntry.mPackageName));
        if (isValidPackage) {
            AdvancedPowerUsageDetail.startBatteryDetailPage(
                mActivity, mFragment, diffEntry, powerPref.getPercent());
@@ -299,8 +305,10 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
            pref.setTitle(appLabel);
            pref.setOrder(prefIndex);
            pref.setPercent(entry.getPercentOfTotal());
            pref.setSingleLineTitle(true);
            // Sets the BatteryDiffEntry to preference for launching detailed page.
            pref.setBatteryDiffEntry(entry);
            setPreferenceSummary(pref, entry);
            mAppListPrefGroup.addPreference(pref);
            prefIndex++;
        }
@@ -322,6 +330,57 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
        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) {
        final StringBuilder builder = new StringBuilder();
        for (int index = 0; index < timestamps.length; index++) {
+5 −0
Original line number Diff line number Diff line
@@ -210,12 +210,17 @@ public class BatteryDiffEntry {
                    packageManager.getApplicationInfo(packageName, /*no flags*/ 0);
                if (appInfo != null) {
                    mAppLabel = packageManager.getApplicationLabel(appInfo).toString();
                    mAppIcon = packageManager.getApplicationIcon(appInfo);
                }
            } catch (NameNotFoundException e) {
                Log.e(TAG, "failed to retrieve ApplicationInfo for: " + 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 String[] packages = packageManager.getPackagesForUid(uid);
+86 −1
Original line number Diff line number Diff line
@@ -30,7 +30,9 @@ import android.content.Context;
import android.content.ContentValues;
import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
import android.text.format.DateUtils;

import androidx.preference.Preference;
import androidx.preference.PreferenceGroup;

import com.android.settings.R;
@@ -274,6 +276,7 @@ public final class BatteryChartPreferenceControllerTest {
        assertThat(pref.getIcon()).isEqualTo(mDrawable);
        assertThat(pref.getOrder()).isEqualTo(1);
        assertThat(pref.getBatteryDiffEntry()).isSameInstanceAs(mBatteryDiffEntry);
        assertThat(pref.isSingleLineTitle()).isTrue();
    }

    @Test
@@ -303,7 +306,82 @@ public final class BatteryChartPreferenceControllerTest {
            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<>();
        for (int index = 0; index < size; index++) {
            final ContentValues values = new ContentValues();
@@ -313,4 +391,11 @@ public final class BatteryChartPreferenceControllerTest {
        }
        return batteryHistoryMap;
    }

    private BatteryDiffEntry createBatteryDiffEntry(
            long foregroundUsageTimeInMs, long backgroundUsageTimeInMs) {
        return new BatteryDiffEntry(
            mContext, foregroundUsageTimeInMs, backgroundUsageTimeInMs,
            /*consumePower=*/ 0, mBatteryHistEntry);
    }
}