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