1. 电池用量时间一直为0
2. 源码跟踪
2.1 字符串位置
<string name="battery_detail_foreground" msgid="3350401514602032183">"在前台运行时"</string><string name="battery_detail_background" msgid="1929644393553768999">"在后台运行时"</string>
2.2 布局文件
power_usage_detail.xml
<PreferenceCategoryandroid:title="@string/battery_detail_info_title"><Preference// 前台进程运行android:key="app_usage_foreground"android:title="@string/battery_detail_foreground"android:selectable="false"/><Preference// 后台进程运行android:key="app_usage_background"android:title="@string/battery_detail_background"android:selectable="false"/><Preference// 电池耗电量android:key="app_power_usage"android:title="@string/battery_detail_power_usage"android:selectable="false"/></PreferenceCategory>
2.3 控件定义
package com.android.settings.fuelgauge;/*** Power usage detail fragment for each app, this fragment contains** 1. Detail battery usage information for app(i.e. usage time, usage amount)* 2. Battery related controls for app(i.e uninstall, force stop)*/
public class AdvancedPowerUsageDetail extends DashboardFragment implementsButtonActionDialogFragment.AppButtonsDialogListener,AnomalyDialogFragment.AnomalyDialogListener,LoaderManager.LoaderCallbacks<List<Anomaly>> {private static final String KEY_PREF_FOREGROUND = "app_usage_foreground";private static final String KEY_PREF_BACKGROUND = "app_usage_background";private static final String KEY_PREF_POWER_USAGE = "app_power_usage";public void onCreate(Bundle icicle) {super.onCreate(icicle);mForegroundPreference = findPreference(KEY_PREF_FOREGROUND);mBackgroundPreference = findPreference(KEY_PREF_BACKGROUND);mPowerUsagePreference = findPreference(KEY_PREF_POWER_USAGE);
2.4 控件赋值
@VisibleForTestingvoid initPreference() {final Bundle bundle = getArguments();final Context context = getContext();final long foregroundTimeMs = bundle.getLong(EXTRA_FOREGROUND_TIME);final long backgroundTimeMs = bundle.getLong(EXTRA_BACKGROUND_TIME);final String usagePercent = bundle.getString(EXTRA_POWER_USAGE_PERCENT);final int powerMah = bundle.getInt(EXTRA_POWER_USAGE_AMOUNT);mForegroundPreference.setSummary(TextUtils.expandTemplate(getText(R.string.battery_used_for),Utils.formatElapsedTime(context, foregroundTimeMs, false)));mBackgroundPreference.setSummary(TextUtils.expandTemplate(getText(R.string.battery_active_for),Utils.formatElapsedTime(context, backgroundTimeMs, false)));mPowerUsagePreference.setSummary(getString(R.string.battery_detail_power_percentage, usagePercent, powerMah));}
2.5 运行时间获取 startBatteryDetailPage.args.putLong
package com.android.settings.fuelgauge;/*** Power usage detail fragment for each app, this fragment contains** 1. Detail battery usage information for app(i.e. usage time, usage amount)* 2. Battery related controls for app(i.e uninstall, force stop)*/
public class AdvancedPowerUsageDetail extends DashboardFragment implementsButtonActionDialogFragment.AppButtonsDialogListener,AnomalyDialogFragment.AnomalyDialogListener,LoaderManager.LoaderCallbacks<List<Anomaly>> {@VisibleForTestingstatic void startBatteryDetailPage(SettingsActivity caller, BatteryUtils batteryUtils,PreferenceFragment fragment, BatteryStatsHelper helper, int which, BatteryEntry entry,String usagePercent, List<Anomaly> anomalies) {......final Bundle args = new Bundle();final BatterySipper sipper = entry.sipper;final BatteryStats.Uid uid = sipper.uidObj;final boolean isTypeApp = sipper.drainType == BatterySipper.DrainType.APP;final long foregroundTimeMs = isTypeApp ? batteryUtils.getProcessTimeMs(BatteryUtils.StatusType.FOREGROUND, uid, which) : sipper.usageTimeMs;final long backgroundTimeMs = isTypeApp ? batteryUtils.getProcessTimeMs(BatteryUtils.StatusType.BACKGROUND, uid, which) : 0;......args.putInt(EXTRA_UID, sipper.getUid());args.putLong(EXTRA_BACKGROUND_TIME, backgroundTimeMs);args.putLong(EXTRA_FOREGROUND_TIME, foregroundTimeMs);args.putString(EXTRA_POWER_USAGE_PERCENT, usagePercent);args.putInt(EXTRA_POWER_USAGE_AMOUNT, (int) sipper.totalPowerMah);args.putParcelableList(EXTRA_ANOMALY_LIST, anomalies);
2.6 运行时间获取 batteryUtils.getProcessTimeMs
package com.android.settings.fuelgauge;/*** Utils for battery operation*/
public class BatteryUtils {public long getProcessTimeMs(@StatusType int type, @Nullable BatteryStats.Uid uid,int which) {if (uid == null) {return 0;}switch (type) {case StatusType.SCREEN_USAGE:return getScreenUsageTimeMs(uid, which);case StatusType.FOREGROUND:return getProcessForegroundTimeMs(uid, which);case StatusType.BACKGROUND:return getProcessBackgroundTimeMs(uid, which);case StatusType.ALL:return getProcessForegroundTimeMs(uid, which)+ getProcessBackgroundTimeMs(uid, which);}return 0;}
2.6 运行时间获取 BatteryUtils.getProcessForegroundTimeMs
adb shell logcat -s “BatteryUtils”
private static final String TAG = "BatteryUtils";private long getProcessForegroundTimeMs(BatteryStats.Uid uid, int which) {final long rawRealTimeUs = convertMsToUs(SystemClock.elapsedRealtime());return getScreenUsageTimeMs(uid, which, rawRealTimeUs)+ convertUsToMs(getForegroundServiceTotalTimeUs(uid, rawRealTimeUs));}// 屏幕使用时间private long getScreenUsageTimeMs(BatteryStats.Uid uid, int which, long rawRealTimeUs) {final int foregroundTypes[] = {BatteryStats.Uid.PROCESS_STATE_TOP};Log.v(TAG, "package: " + mPackageManager.getNameForUid(uid.getUid()));long timeUs = 0;for (int type : foregroundTypes) {final long localTime = uid.getProcessStateTime(type, rawRealTimeUs, which);Log.v(TAG, "type: " + type + " time(us): " + localTime);timeUs += localTime;}Log.v(TAG, "foreground time(us): " + timeUs);// Return the min value of STATE_TOP time and foreground activity time, since both of these// time have some errorsreturn convertUsToMs(Math.min(timeUs, getForegroundActivityTotalTimeUs(uid, rawRealTimeUs)));}// 进程前台运行时间@VisibleForTestinglong getForegroundServiceTotalTimeUs(BatteryStats.Uid uid, long rawRealtimeUs) {final BatteryStats.Timer timer = uid.getForegroundServiceTimer();if (timer != null) {return timer.getTotalTimeLocked(rawRealtimeUs, BatteryStats.STATS_SINCE_CHARGED);}return 0;}