• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.settings.fuelgauge;
18 
19 import android.annotation.UserIdInt;
20 import android.app.Activity;
21 import android.app.ActivityManager;
22 import android.app.settings.SettingsEnums;
23 import android.content.Context;
24 import android.content.Intent;
25 import android.content.pm.PackageManager;
26 import android.os.Bundle;
27 import android.os.UserHandle;
28 import android.text.TextUtils;
29 import android.text.format.DateUtils;
30 import android.util.Log;
31 import android.util.Pair;
32 import android.view.View;
33 
34 import androidx.annotation.VisibleForTesting;
35 import androidx.preference.Preference;
36 
37 import com.android.settings.R;
38 import com.android.settings.SettingsActivity;
39 import com.android.settings.Utils;
40 import com.android.settings.applications.appinfo.AppButtonsPreferenceController;
41 import com.android.settings.applications.appinfo.ButtonActionDialogFragment;
42 import com.android.settings.core.InstrumentedPreferenceFragment;
43 import com.android.settings.core.SubSettingLauncher;
44 import com.android.settings.dashboard.DashboardFragment;
45 import com.android.settings.fuelgauge.batterytip.BatteryTipPreferenceController;
46 import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
47 import com.android.settings.overlay.FeatureFactory;
48 import com.android.settings.widget.EntityHeaderController;
49 import com.android.settingslib.HelpUtils;
50 import com.android.settingslib.applications.AppUtils;
51 import com.android.settingslib.applications.ApplicationsState;
52 import com.android.settingslib.core.AbstractPreferenceController;
53 import com.android.settingslib.utils.StringUtil;
54 import com.android.settingslib.widget.FooterPreference;
55 import com.android.settingslib.widget.LayoutPreference;
56 import com.android.settingslib.widget.RadioButtonPreference;
57 
58 import java.util.ArrayList;
59 import java.util.List;
60 
61 /**
62  * Power usage detail fragment for each app, this fragment contains
63  *
64  * 1. Detail battery usage information for app(i.e. usage time, usage amount)
65  * 2. Battery related controls for app(i.e uninstall, force stop)
66  */
67 public class AdvancedPowerUsageDetail extends DashboardFragment implements
68         ButtonActionDialogFragment.AppButtonsDialogListener,
69         BatteryTipPreferenceController.BatteryTipListener, RadioButtonPreference.OnClickListener {
70 
71     public static final String TAG = "AdvancedPowerDetail";
72     public static final String EXTRA_UID = "extra_uid";
73     public static final String EXTRA_PACKAGE_NAME = "extra_package_name";
74     public static final String EXTRA_FOREGROUND_TIME = "extra_foreground_time";
75     public static final String EXTRA_BACKGROUND_TIME = "extra_background_time";
76     public static final String EXTRA_SLOT_TIME = "extra_slot_time";
77     public static final String EXTRA_LABEL = "extra_label";
78     public static final String EXTRA_ICON_ID = "extra_icon_id";
79     public static final String EXTRA_POWER_USAGE_PERCENT = "extra_power_usage_percent";
80     public static final String EXTRA_POWER_USAGE_AMOUNT = "extra_power_usage_amount";
81 
82     private static final String KEY_PREF_FOREGROUND = "app_usage_foreground";
83     private static final String KEY_PREF_BACKGROUND = "app_usage_background";
84     private static final String KEY_PREF_HEADER = "header_view";
85     private static final String KEY_PREF_UNRESTRICTED = "unrestricted_pref";
86     private static final String KEY_PREF_OPTIMIZED = "optimized_pref";
87     private static final String KEY_PREF_RESTRICTED = "restricted_pref";
88     private static final String KEY_FOOTER_PREFERENCE = "app_usage_footer_preference";
89 
90     private static final int REQUEST_UNINSTALL = 0;
91     private static final int REQUEST_REMOVE_DEVICE_ADMIN = 1;
92 
93     @VisibleForTesting
94     LayoutPreference mHeaderPreference;
95     @VisibleForTesting
96     ApplicationsState mState;
97     @VisibleForTesting
98     ApplicationsState.AppEntry mAppEntry;
99     @VisibleForTesting
100     BatteryUtils mBatteryUtils;
101     @VisibleForTesting
102     BatteryOptimizeUtils mBatteryOptimizeUtils;
103     @VisibleForTesting
104     Preference mForegroundPreference;
105     @VisibleForTesting
106     Preference mBackgroundPreference;
107     @VisibleForTesting
108     FooterPreference mFooterPreference;
109     @VisibleForTesting
110     RadioButtonPreference mRestrictedPreference;
111     @VisibleForTesting
112     RadioButtonPreference mOptimizePreference;
113     @VisibleForTesting
114     RadioButtonPreference mUnrestrictedPreference;
115     @VisibleForTesting
116     boolean enableTriState = true;
117 
118     private AppButtonsPreferenceController mAppButtonsPreferenceController;
119     private BackgroundActivityPreferenceController mBackgroundActivityPreferenceController;
120 
121     // A wrapper class to carry LaunchBatteryDetailPage required arguments.
122     private static final class LaunchBatteryDetailPageArgs {
123         private String mUsagePercent;
124         private String mPackageName;
125         private String mAppLabel;
126         private String mSlotInformation;
127         private int mUid;
128         private int mIconId;
129         private int mConsumedPower;
130         private long mForegroundTimeMs;
131         private long mBackgroundTimeMs;
132         private boolean mIsUserEntry;
133     }
134 
135     /** Launches battery details page for an individual battery consumer. */
startBatteryDetailPage( Activity caller, InstrumentedPreferenceFragment fragment, BatteryDiffEntry diffEntry, String usagePercent, boolean isValidToShowSummary, String slotInformation)136     public static void startBatteryDetailPage(
137             Activity caller, InstrumentedPreferenceFragment fragment,
138             BatteryDiffEntry diffEntry, String usagePercent,
139             boolean isValidToShowSummary, String slotInformation) {
140         final BatteryHistEntry histEntry = diffEntry.mBatteryHistEntry;
141         final LaunchBatteryDetailPageArgs launchArgs = new LaunchBatteryDetailPageArgs();
142         // configure the launch argument.
143         launchArgs.mUsagePercent = usagePercent;
144         launchArgs.mPackageName = diffEntry.getPackageName();
145         launchArgs.mAppLabel = diffEntry.getAppLabel();
146         launchArgs.mSlotInformation = slotInformation;
147         launchArgs.mUid = (int) histEntry.mUid;
148         launchArgs.mIconId = diffEntry.getAppIconId();
149         launchArgs.mConsumedPower = (int) diffEntry.mConsumePower;
150         launchArgs.mForegroundTimeMs =
151             isValidToShowSummary ? diffEntry.mForegroundUsageTimeInMs : 0;
152         launchArgs.mBackgroundTimeMs =
153             isValidToShowSummary ? diffEntry.mBackgroundUsageTimeInMs : 0;
154         launchArgs.mIsUserEntry = histEntry.isUserEntry();
155         startBatteryDetailPage(caller, fragment, launchArgs);
156     }
157 
158     /** Launches battery details page for an individual battery consumer. */
startBatteryDetailPage(Activity caller, InstrumentedPreferenceFragment fragment, BatteryEntry entry, String usagePercent, boolean isValidToShowSummary)159     public static void startBatteryDetailPage(Activity caller,
160             InstrumentedPreferenceFragment fragment, BatteryEntry entry, String usagePercent,
161             boolean isValidToShowSummary) {
162         final LaunchBatteryDetailPageArgs launchArgs = new LaunchBatteryDetailPageArgs();
163         // configure the launch argument.
164         launchArgs.mUsagePercent = usagePercent;
165         launchArgs.mPackageName = entry.getDefaultPackageName();
166         launchArgs.mAppLabel = entry.getLabel();
167         launchArgs.mUid = entry.getUid();
168         launchArgs.mIconId = entry.iconId;
169         launchArgs.mConsumedPower = (int) entry.getConsumedPower();
170         launchArgs.mForegroundTimeMs = isValidToShowSummary ? entry.getTimeInForegroundMs() : 0;
171         launchArgs.mBackgroundTimeMs = isValidToShowSummary ? entry.getTimeInBackgroundMs() : 0;
172         launchArgs.mIsUserEntry = entry.isUserEntry();
173         startBatteryDetailPage(caller, fragment, launchArgs);
174     }
175 
startBatteryDetailPage(Activity caller, InstrumentedPreferenceFragment fragment, LaunchBatteryDetailPageArgs launchArgs)176     private static void startBatteryDetailPage(Activity caller,
177             InstrumentedPreferenceFragment fragment, LaunchBatteryDetailPageArgs launchArgs) {
178         final Bundle args = new Bundle();
179         if (launchArgs.mPackageName == null) {
180             // populate data for system app
181             args.putString(EXTRA_LABEL, launchArgs.mAppLabel);
182             args.putInt(EXTRA_ICON_ID, launchArgs.mIconId);
183             args.putString(EXTRA_PACKAGE_NAME, null);
184         } else {
185             // populate data for normal app
186             args.putString(EXTRA_PACKAGE_NAME, launchArgs.mPackageName);
187         }
188 
189         args.putInt(EXTRA_UID, launchArgs.mUid);
190         args.putLong(EXTRA_BACKGROUND_TIME, launchArgs.mBackgroundTimeMs);
191         args.putLong(EXTRA_FOREGROUND_TIME, launchArgs.mForegroundTimeMs);
192         args.putString(EXTRA_SLOT_TIME, launchArgs.mSlotInformation);
193         args.putString(EXTRA_POWER_USAGE_PERCENT, launchArgs.mUsagePercent);
194         args.putInt(EXTRA_POWER_USAGE_AMOUNT, launchArgs.mConsumedPower);
195         final int userId = launchArgs.mIsUserEntry ? ActivityManager.getCurrentUser()
196             : UserHandle.getUserId(launchArgs.mUid);
197 
198         new SubSettingLauncher(caller)
199                 .setDestination(AdvancedPowerUsageDetail.class.getName())
200                 .setTitleRes(R.string.battery_details_title)
201                 .setArguments(args)
202                 .setSourceMetricsCategory(fragment.getMetricsCategory())
203                 .setUserHandle(new UserHandle(userId))
204                 .launch();
205     }
206 
getUserIdToLaunchAdvancePowerUsageDetail( BatteryEntry batteryEntry)207     private static @UserIdInt int getUserIdToLaunchAdvancePowerUsageDetail(
208             BatteryEntry batteryEntry) {
209         if (batteryEntry.isUserEntry()) {
210             return ActivityManager.getCurrentUser();
211         }
212         return UserHandle.getUserId(batteryEntry.getUid());
213     }
214 
startBatteryDetailPage(Activity caller, InstrumentedPreferenceFragment fragment, String packageName)215     public static void startBatteryDetailPage(Activity caller,
216             InstrumentedPreferenceFragment fragment, String packageName) {
217         final Bundle args = new Bundle(3);
218         final PackageManager packageManager = caller.getPackageManager();
219         args.putString(EXTRA_PACKAGE_NAME, packageName);
220         args.putString(EXTRA_POWER_USAGE_PERCENT, Utils.formatPercentage(0));
221         try {
222             args.putInt(EXTRA_UID, packageManager.getPackageUid(packageName, 0 /* no flag */));
223         } catch (PackageManager.NameNotFoundException e) {
224             Log.w(TAG, "Cannot find package: " + packageName, e);
225         }
226 
227         new SubSettingLauncher(caller)
228                 .setDestination(AdvancedPowerUsageDetail.class.getName())
229                 .setTitleRes(R.string.battery_details_title)
230                 .setArguments(args)
231                 .setSourceMetricsCategory(fragment.getMetricsCategory())
232                 .launch();
233     }
234 
235     @Override
onAttach(Activity activity)236     public void onAttach(Activity activity) {
237         super.onAttach(activity);
238 
239         mState = ApplicationsState.getInstance(getActivity().getApplication());
240         mBatteryUtils = BatteryUtils.getInstance(getContext());
241     }
242 
243     @Override
onCreate(Bundle icicle)244     public void onCreate(Bundle icicle) {
245         super.onCreate(icicle);
246 
247         final String packageName = getArguments().getString(EXTRA_PACKAGE_NAME);
248         if (enableTriState) {
249             onCreateForTriState(packageName);
250         } else {
251             mForegroundPreference = findPreference(KEY_PREF_FOREGROUND);
252             mBackgroundPreference = findPreference(KEY_PREF_BACKGROUND);
253         }
254         mHeaderPreference = findPreference(KEY_PREF_HEADER);
255 
256         if (packageName != null) {
257             mAppEntry = mState.getEntry(packageName, UserHandle.myUserId());
258         }
259     }
260 
261     @Override
onResume()262     public void onResume() {
263         super.onResume();
264 
265         initHeader();
266         if (enableTriState) {
267             initPreferenceForTriState(getContext());
268             final String packageName = mBatteryOptimizeUtils.getPackageName();
269             FeatureFactory.getFactory(getContext()).getMetricsFeatureProvider()
270                 .action(
271                     getContext(),
272                     SettingsEnums.OPEN_APP_BATTERY_USAGE,
273                     packageName);
274         } else {
275             initPreference(getContext());
276         }
277     }
278 
279     @VisibleForTesting
initHeader()280     void initHeader() {
281         final View appSnippet = mHeaderPreference.findViewById(R.id.entity_header);
282         final Activity context = getActivity();
283         final Bundle bundle = getArguments();
284         EntityHeaderController controller = EntityHeaderController
285                 .newInstance(context, this, appSnippet)
286                 .setRecyclerView(getListView(), getSettingsLifecycle())
287                 .setButtonActions(EntityHeaderController.ActionType.ACTION_NONE,
288                         EntityHeaderController.ActionType.ACTION_NONE);
289 
290         if (mAppEntry == null) {
291             controller.setLabel(bundle.getString(EXTRA_LABEL));
292 
293             final int iconId = bundle.getInt(EXTRA_ICON_ID, 0);
294             if (iconId == 0) {
295                 controller.setIcon(context.getPackageManager().getDefaultActivityIcon());
296             } else {
297                 controller.setIcon(context.getDrawable(bundle.getInt(EXTRA_ICON_ID)));
298             }
299         } else {
300             mState.ensureIcon(mAppEntry);
301             controller.setLabel(mAppEntry);
302             controller.setIcon(mAppEntry);
303             controller.setIsInstantApp(AppUtils.isInstant(mAppEntry.info));
304         }
305 
306         if (enableTriState) {
307             final long foregroundTimeMs = bundle.getLong(EXTRA_FOREGROUND_TIME);
308             final long backgroundTimeMs = bundle.getLong(EXTRA_BACKGROUND_TIME);
309             final String slotTime = bundle.getString(EXTRA_SLOT_TIME, null);
310             controller.setSummary(getAppActiveTime(foregroundTimeMs, backgroundTimeMs, slotTime));
311         }
312 
313         controller.done(context, true /* rebindActions */);
314     }
315 
316     @VisibleForTesting
initPreference(Context context)317     void initPreference(Context context) {
318         final Bundle bundle = getArguments();
319         final long foregroundTimeMs = bundle.getLong(EXTRA_FOREGROUND_TIME);
320         final long backgroundTimeMs = bundle.getLong(EXTRA_BACKGROUND_TIME);
321         mForegroundPreference.setSummary(
322                 TextUtils.expandTemplate(getText(R.string.battery_used_for),
323                         StringUtil.formatElapsedTime(
324                                 context,
325                                 foregroundTimeMs,
326                                 /* withSeconds */ false,
327                                 /* collapseTimeUnit */ false)));
328         mBackgroundPreference.setSummary(
329                 TextUtils.expandTemplate(getText(R.string.battery_active_for),
330                         StringUtil.formatElapsedTime(
331                                 context,
332                                 backgroundTimeMs,
333                                 /* withSeconds */ false,
334                                 /* collapseTimeUnit */ false)));
335     }
336 
337     @VisibleForTesting
initPreferenceForTriState(Context context)338     void initPreferenceForTriState(Context context) {
339         final String stateString;
340         final String footerString;
341 
342         if (!mBatteryOptimizeUtils.isValidPackageName()) {
343             //Present optimized only string when the package name is invalid.
344             stateString = context.getString(R.string.manager_battery_usage_optimized_only);
345             footerString = context.getString(
346                     R.string.manager_battery_usage_footer_limited, stateString);
347         } else if (mBatteryOptimizeUtils.isSystemOrDefaultApp()) {
348             //Present unrestricted only string when the package is system or default active app.
349             stateString = context.getString(R.string.manager_battery_usage_unrestricted_only);
350             footerString = context.getString(
351                     R.string.manager_battery_usage_footer_limited, stateString);
352         } else {
353             //Present default string to normal app.
354             footerString = context.getString(R.string.manager_battery_usage_footer);
355         }
356         mFooterPreference.setTitle(footerString);
357         mFooterPreference.setLearnMoreAction(v ->
358                 startActivityForResult(HelpUtils.getHelpIntent(context,
359                         context.getString(R.string.help_url_app_usage_settings),
360                         /*backupContext=*/ ""), /*requestCode=*/ 0));
361         mFooterPreference.setLearnMoreContentDescription(
362                 context.getString(R.string.manager_battery_usage_link_a11y));
363     }
364 
365     @Override
getMetricsCategory()366     public int getMetricsCategory() {
367         return SettingsEnums.FUELGAUGE_POWER_USAGE_DETAIL;
368     }
369 
370     @Override
getLogTag()371     protected String getLogTag() {
372         return TAG;
373     }
374 
375     @Override
getPreferenceScreenResId()376     protected int getPreferenceScreenResId() {
377         return enableTriState ? R.xml.power_usage_detail : R.xml.power_usage_detail_legacy;
378     }
379 
380     @Override
createPreferenceControllers(Context context)381     protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
382         final List<AbstractPreferenceController> controllers = new ArrayList<>();
383         final Bundle bundle = getArguments();
384         final int uid = bundle.getInt(EXTRA_UID, 0);
385         final String packageName = bundle.getString(EXTRA_PACKAGE_NAME);
386 
387         mAppButtonsPreferenceController = new AppButtonsPreferenceController(
388                 (SettingsActivity) getActivity(), this, getSettingsLifecycle(), packageName,
389                 mState, REQUEST_UNINSTALL, REQUEST_REMOVE_DEVICE_ADMIN);
390         controllers.add(mAppButtonsPreferenceController);
391         if (enableTriState) {
392             controllers.add(new UnrestrictedPreferenceController(context, uid, packageName));
393             controllers.add(new OptimizedPreferenceController(context, uid, packageName));
394             controllers.add(new RestrictedPreferenceController(context, uid, packageName));
395         } else {
396             mBackgroundActivityPreferenceController = new BackgroundActivityPreferenceController(
397                     context, this, uid, packageName);
398             controllers.add(mBackgroundActivityPreferenceController);
399             controllers.add(new BatteryOptimizationPreferenceController(
400                     (SettingsActivity) getActivity(), this, packageName));
401         }
402 
403         return controllers;
404     }
405 
406     @Override
onActivityResult(int requestCode, int resultCode, Intent data)407     public void onActivityResult(int requestCode, int resultCode, Intent data) {
408         super.onActivityResult(requestCode, resultCode, data);
409         if (mAppButtonsPreferenceController != null) {
410             mAppButtonsPreferenceController.handleActivityResult(requestCode, resultCode, data);
411         }
412     }
413 
414     @Override
handleDialogClick(int id)415     public void handleDialogClick(int id) {
416         if (mAppButtonsPreferenceController != null) {
417             mAppButtonsPreferenceController.handleDialogClick(id);
418         }
419     }
420 
421     @Override
onBatteryTipHandled(BatteryTip batteryTip)422     public void onBatteryTipHandled(BatteryTip batteryTip) {
423         mBackgroundActivityPreferenceController.updateSummary(
424                 findPreference(mBackgroundActivityPreferenceController.getPreferenceKey()));
425     }
426 
427     @Override
onRadioButtonClicked(RadioButtonPreference selected)428     public void onRadioButtonClicked(RadioButtonPreference selected) {
429         final String selectedKey = selected.getKey();
430         updatePreferenceState(mUnrestrictedPreference, selectedKey);
431         updatePreferenceState(mOptimizePreference, selectedKey);
432         updatePreferenceState(mRestrictedPreference, selectedKey);
433 
434         // Logs metric.
435         int metricCategory = 0;
436         if (selectedKey.equals(mUnrestrictedPreference.getKey())) {
437             metricCategory = SettingsEnums.ACTION_APP_BATTERY_USAGE_UNRESTRICTED;
438         } else if (selectedKey.equals(mOptimizePreference.getKey())) {
439             metricCategory = SettingsEnums.ACTION_APP_BATTERY_USAGE_OPTIMIZED;
440         } else if (selectedKey.equals(mRestrictedPreference.getKey())) {
441             metricCategory = SettingsEnums.ACTION_APP_BATTERY_USAGE_RESTRICTED;
442         }
443         if (metricCategory != 0) {
444             FeatureFactory.getFactory(getContext()).getMetricsFeatureProvider()
445                 .action(
446                     getContext(),
447                     metricCategory,
448                     new Pair(ConvertUtils.METRIC_KEY_PACKAGE,
449                             mBatteryOptimizeUtils.getPackageName()),
450                     new Pair(ConvertUtils.METRIC_KEY_BATTERY_USAGE,
451                             getArguments().getString(EXTRA_POWER_USAGE_PERCENT)));
452         }
453     }
454 
updatePreferenceState(RadioButtonPreference preference, String selectedKey)455     private void updatePreferenceState(RadioButtonPreference preference, String selectedKey) {
456         preference.setChecked(selectedKey.equals(preference.getKey()));
457     }
458 
onCreateForTriState(String packageName)459     private void onCreateForTriState(String packageName) {
460         mUnrestrictedPreference = findPreference(KEY_PREF_UNRESTRICTED);
461         mOptimizePreference = findPreference(KEY_PREF_OPTIMIZED);
462         mRestrictedPreference = findPreference(KEY_PREF_RESTRICTED);
463         mFooterPreference = findPreference(KEY_FOOTER_PREFERENCE);
464         mUnrestrictedPreference.setOnClickListener(this);
465         mOptimizePreference.setOnClickListener(this);
466         mRestrictedPreference.setOnClickListener(this);
467 
468         mBatteryOptimizeUtils = new BatteryOptimizeUtils(
469                 getContext(), getArguments().getInt(EXTRA_UID), packageName);
470     }
471 
getAppActiveTime( long foregroundTimeMs, long backgroundTimeMs, String slotTime)472     private CharSequence getAppActiveTime(
473             long foregroundTimeMs, long backgroundTimeMs, String slotTime) {
474         final long totalTimeMs = foregroundTimeMs + backgroundTimeMs;
475         final CharSequence usageTimeSummary;
476         final PowerUsageFeatureProvider powerFeatureProvider =
477                 FeatureFactory.getFactory(getContext()).getPowerUsageFeatureProvider(getContext());
478 
479         if (totalTimeMs == 0) {
480             usageTimeSummary = getText(powerFeatureProvider.isChartGraphEnabled(getContext())
481                     ? R.string.battery_not_usage_24hr : R.string.battery_not_usage);
482         } else if (slotTime == null) {
483             // Shows summary text with past 24 hr or full charge if slot time is null.
484             usageTimeSummary = powerFeatureProvider.isChartGraphEnabled(getContext())
485                     ? getAppPast24HrActiveSummary(foregroundTimeMs, backgroundTimeMs, totalTimeMs)
486                     : getAppFullChargeActiveSummary(
487                             foregroundTimeMs, backgroundTimeMs, totalTimeMs);
488         } else {
489             // Shows summary text with slot time.
490             usageTimeSummary = getAppActiveSummaryWithSlotTime(
491                     foregroundTimeMs, backgroundTimeMs, totalTimeMs, slotTime);
492         }
493         return usageTimeSummary;
494     }
495 
getAppFullChargeActiveSummary( long foregroundTimeMs, long backgroundTimeMs, long totalTimeMs)496     private CharSequence getAppFullChargeActiveSummary(
497             long foregroundTimeMs, long backgroundTimeMs, long totalTimeMs) {
498         // Shows background summary only if we don't have foreground usage time.
499         if (foregroundTimeMs == 0 && backgroundTimeMs != 0) {
500             return backgroundTimeMs < DateUtils.MINUTE_IN_MILLIS ?
501                     getText(R.string.battery_bg_usage_less_minute) :
502                     TextUtils.expandTemplate(getText(R.string.battery_bg_usage),
503                             StringUtil.formatElapsedTime(
504                                     getContext(),
505                                     backgroundTimeMs,
506                                     /* withSeconds */ false,
507                                     /* collapseTimeUnit */ false));
508         // Shows total usage summary only if total usage time is small.
509         } else if (totalTimeMs < DateUtils.MINUTE_IN_MILLIS) {
510             return getText(R.string.battery_total_usage_less_minute);
511         // Shows different total usage summary when background usage time is small.
512         } else if (backgroundTimeMs < DateUtils.MINUTE_IN_MILLIS) {
513             return TextUtils.expandTemplate(
514                     getText(backgroundTimeMs == 0 ?
515                             R.string.battery_total_usage :
516                             R.string.battery_total_usage_and_bg_less_minute_usage),
517                     StringUtil.formatElapsedTime(
518                             getContext(),
519                             totalTimeMs,
520                             /* withSeconds */ false,
521                             /* collapseTimeUnit */ false));
522         // Shows default summary.
523         } else {
524             return TextUtils.expandTemplate(
525                     getText(R.string.battery_total_and_bg_usage),
526                     StringUtil.formatElapsedTime(
527                             getContext(),
528                             totalTimeMs,
529                             /* withSeconds */ false,
530                             /* collapseTimeUnit */ false),
531                     StringUtil.formatElapsedTime(
532                             getContext(),
533                             backgroundTimeMs,
534                             /* withSeconds */ false,
535                             /* collapseTimeUnit */ false));
536         }
537     }
538 
getAppPast24HrActiveSummary( long foregroundTimeMs, long backgroundTimeMs, long totalTimeMs)539     private CharSequence getAppPast24HrActiveSummary(
540             long foregroundTimeMs, long backgroundTimeMs, long totalTimeMs) {
541         // Shows background summary only if we don't have foreground usage time.
542         if (foregroundTimeMs == 0 && backgroundTimeMs != 0) {
543             return backgroundTimeMs < DateUtils.MINUTE_IN_MILLIS
544                     ? getText(R.string.battery_bg_usage_less_minute_24hr)
545                     : TextUtils.expandTemplate(getText(R.string.battery_bg_usage_24hr),
546                             StringUtil.formatElapsedTime(
547                                     getContext(),
548                                     backgroundTimeMs,
549                                     /* withSeconds */ false,
550                                     /* collapseTimeUnit */ false));
551         // Shows total usage summary only if total usage time is small.
552         } else if (totalTimeMs < DateUtils.MINUTE_IN_MILLIS) {
553             return getText(R.string.battery_total_usage_less_minute_24hr);
554         // Shows different total usage summary when background usage time is small.
555         } else if (backgroundTimeMs < DateUtils.MINUTE_IN_MILLIS) {
556             return TextUtils.expandTemplate(
557                     getText(backgroundTimeMs == 0
558                             ? R.string.battery_total_usage_24hr
559                             : R.string.battery_total_usage_and_bg_less_minute_usage_24hr),
560                     StringUtil.formatElapsedTime(
561                             getContext(),
562                             totalTimeMs,
563                             /* withSeconds */ false,
564                             /* collapseTimeUnit */ false));
565         // Shows default summary.
566         } else {
567             return TextUtils.expandTemplate(
568                     getText(R.string.battery_total_and_bg_usage_24hr),
569                     StringUtil.formatElapsedTime(
570                             getContext(),
571                             totalTimeMs,
572                             /* withSeconds */ false,
573                             /* collapseTimeUnit */ false),
574                     StringUtil.formatElapsedTime(
575                             getContext(),
576                             backgroundTimeMs,
577                             /* withSeconds */ false,
578                             /* collapseTimeUnit */ false));
579         }
580     }
581 
getAppActiveSummaryWithSlotTime( long foregroundTimeMs, long backgroundTimeMs, long totalTimeMs, String slotTime)582     private CharSequence getAppActiveSummaryWithSlotTime(
583             long foregroundTimeMs, long backgroundTimeMs, long totalTimeMs, String slotTime) {
584         // Shows background summary only if we don't have foreground usage time.
585         if (foregroundTimeMs == 0 && backgroundTimeMs != 0) {
586             return backgroundTimeMs < DateUtils.MINUTE_IN_MILLIS ?
587                     TextUtils.expandTemplate(
588                             getText(R.string.battery_bg_usage_less_minute_with_period),
589                             slotTime) :
590                     TextUtils.expandTemplate(getText(R.string.battery_bg_usage_with_period),
591                             StringUtil.formatElapsedTime(
592                                     getContext(),
593                                     backgroundTimeMs,
594                                     /* withSeconds */ false,
595                                     /* collapseTimeUnit */ false), slotTime);
596         // Shows total usage summary only if total usage time is small.
597         } else if (totalTimeMs < DateUtils.MINUTE_IN_MILLIS) {
598             return TextUtils.expandTemplate(
599                     getText(R.string.battery_total_usage_less_minute_with_period), slotTime);
600         // Shows different total usage summary when background usage time is small.
601         } else if (backgroundTimeMs < DateUtils.MINUTE_IN_MILLIS) {
602             return TextUtils.expandTemplate(
603                     getText(backgroundTimeMs == 0 ?
604                             R.string.battery_total_usage_with_period :
605                             R.string.battery_total_usage_and_bg_less_minute_usage_with_period),
606                     StringUtil.formatElapsedTime(
607                             getContext(),
608                             totalTimeMs,
609                             /* withSeconds */ false,
610                             /* collapseTimeUnit */ false), slotTime);
611         // Shows default summary.
612         } else {
613             return TextUtils.expandTemplate(
614                     getText(R.string.battery_total_and_bg_usage_with_period),
615                     StringUtil.formatElapsedTime(
616                             getContext(),
617                             totalTimeMs,
618                             /* withSeconds */ false,
619                             /* collapseTimeUnit */ false),
620                     StringUtil.formatElapsedTime(
621                             getContext(),
622                             backgroundTimeMs,
623                             /* withSeconds */ false,
624                             /* collapseTimeUnit */ false), slotTime);
625         }
626     }
627 }
628