Loading core/java/android/os/BatteryStats.java +84 −10 Original line number Diff line number Diff line Loading @@ -53,6 +53,8 @@ public abstract class BatteryStats implements Parcelable { private static final String TAG = "BatteryStats"; private static final boolean LOCAL_LOGV = false; /** Fetching RPM stats is too slow to do each time screen changes, so disable it. */ protected static final boolean SCREEN_OFF_RPM_STATS_ENABLED = false; /** @hide */ public static final String SERVICE_NAME = "batterystats"; Loading Loading @@ -213,8 +215,10 @@ public abstract class BatteryStats implements Parcelable { * - Fixed bugs in background timers and BLE scan time * New in version 25: * - Package wakeup alarms are now on screen-off timebase * New in version 26: * - Resource power manager (rpm) states [but screenOffRpm is disabled from working properly] */ static final String CHECKIN_VERSION = "25"; static final String CHECKIN_VERSION = "26"; /** * Old version, we hit 9 and ran out of room, need to remove. Loading @@ -233,6 +237,10 @@ public abstract class BatteryStats implements Parcelable { private static final String CPU_DATA = "cpu"; private static final String GLOBAL_CPU_FREQ_DATA = "gcf"; private static final String CPU_TIMES_AT_FREQ_DATA = "ctf"; // rpm line is: // BATTERY_STATS_CHECKIN_VERSION, uid, which, "rpm", state/voter name, total time, total count, // screen-off time, screen-off count private static final String RESOURCE_POWER_MANAGER_DATA = "rpm"; private static final String SENSOR_DATA = "sr"; private static final String VIBRATOR_DATA = "vib"; private static final String FOREGROUND_ACTIVITY_DATA = "fg"; Loading Loading @@ -2648,6 +2656,16 @@ public abstract class BatteryStats implements Parcelable { public abstract Map<String, ? extends Timer> getKernelWakelockStats(); /** * Returns Timers tracking the total time of each Resource Power Manager state and voter. */ public abstract Map<String, ? extends Timer> getRpmStats(); /** * Returns Timers tracking the screen-off time of each Resource Power Manager state and voter. */ public abstract Map<String, ? extends Timer> getScreenOffRpmStats(); public abstract LongSparseArray<? extends Timer> getKernelMemoryStats(); public abstract void writeToParcelWithoutUids(Parcel out, int flags); Loading Loading @@ -3309,6 +3327,30 @@ public abstract class BatteryStats implements Parcelable { } } final Map<String, ? extends Timer> rpmStats = getRpmStats(); final Map<String, ? extends Timer> screenOffRpmStats = getScreenOffRpmStats(); if (rpmStats.size() > 0) { for (Map.Entry<String, ? extends Timer> ent : rpmStats.entrySet()) { sb.setLength(0); Timer totalTimer = ent.getValue(); long timeMs = (totalTimer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000; int count = totalTimer.getCountLocked(which); Timer screenOffTimer = screenOffRpmStats.get(ent.getKey()); long screenOffTimeMs = screenOffTimer != null ? (screenOffTimer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000 : 0; int screenOffCount = screenOffTimer != null ? screenOffTimer.getCountLocked(which) : 0; if (SCREEN_OFF_RPM_STATS_ENABLED) { dumpLine(pw, 0 /* uid */, category, RESOURCE_POWER_MANAGER_DATA, "\"" + ent.getKey() + "\"", timeMs, count, screenOffTimeMs, screenOffCount); } else { dumpLine(pw, 0 /* uid */, category, RESOURCE_POWER_MANAGER_DATA, "\"" + ent.getKey() + "\"", timeMs, count); } } } final BatteryStatsHelper helper = new BatteryStatsHelper(context, false, wifiOnly); helper.create(this); helper.refreshStats(which, UserHandle.USER_ALL); Loading Loading @@ -4570,6 +4612,7 @@ public abstract class BatteryStats implements Parcelable { } final LongSparseArray<? extends Timer> mMemoryStats = getKernelMemoryStats(); if (mMemoryStats.size() > 0) { pw.println(" Memory Stats"); for (int i = 0; i < mMemoryStats.size(); i++) { sb.setLength(0); Loading @@ -4579,6 +4622,36 @@ public abstract class BatteryStats implements Parcelable { sb.append(mMemoryStats.valueAt(i).getTotalTimeLocked(rawRealtime, which)); pw.println(sb.toString()); } pw.println(); } final Map<String, ? extends Timer> rpmStats = getRpmStats(); if (rpmStats.size() > 0) { pw.print(prefix); pw.println(" Resource Power Manager Stats"); if (rpmStats.size() > 0) { for (Map.Entry<String, ? extends Timer> ent : rpmStats.entrySet()) { final String timerName = ent.getKey(); final Timer timer = ent.getValue(); printTimer(pw, sb, timer, rawRealtime, which, prefix, timerName); } } pw.println(); } if (SCREEN_OFF_RPM_STATS_ENABLED) { final Map<String, ? extends Timer> screenOffRpmStats = getScreenOffRpmStats(); if (screenOffRpmStats.size() > 0) { pw.print(prefix); pw.println(" Resource Power Manager Stats for when screen was off"); if (screenOffRpmStats.size() > 0) { for (Map.Entry<String, ? extends Timer> ent : screenOffRpmStats.entrySet()) { final String timerName = ent.getKey(); final Timer timer = ent.getValue(); printTimer(pw, sb, timer, rawRealtime, which, prefix, timerName); } } pw.println(); } } final long[] cpuFreqs = getCpuFreqs(); if (cpuFreqs != null) { Loading @@ -4588,6 +4661,7 @@ public abstract class BatteryStats implements Parcelable { sb.append(" " + cpuFreqs[i]); } pw.println(sb.toString()); pw.println(); } for (int iu=0; iu<NU; iu++) { Loading core/java/com/android/internal/os/BatteryStatsImpl.java +201 −2 Original line number Diff line number Diff line Loading @@ -119,7 +119,7 @@ public class BatteryStatsImpl extends BatteryStats { private static final int MAGIC = 0xBA757475; // 'BATSTATS' // Current on-disk Parcel version private static final int VERSION = 165 + (USE_OLD_HISTORY ? 1000 : 0); private static final int VERSION = 166 + (USE_OLD_HISTORY ? 1000 : 0); // Maximum number of items we will record in the history. private static final int MAX_HISTORY_ITEMS; Loading Loading @@ -183,6 +183,9 @@ public class BatteryStatsImpl extends BatteryStats { return mKernelMemoryStats; } /** Temporary container for Resource Power Manager stats. */ private final RpmStats mTmpRpmStats = new RpmStats(); public interface BatteryCallback { public void batteryNeedsCpuUpdate(); public void batteryPowerChanged(boolean onBattery); Loading @@ -190,6 +193,7 @@ public class BatteryStatsImpl extends BatteryStats { } public interface PlatformIdleStateCallback { public void fillLowPowerStats(RpmStats rpmStats); public String getPlatformLowPowerStats(); public String getSubsystemLowPowerStats(); } Loading Loading @@ -265,7 +269,8 @@ public class BatteryStatsImpl extends BatteryStats { int UPDATE_WIFI = 0x02; int UPDATE_RADIO = 0x04; int UPDATE_BT = 0x08; int UPDATE_ALL = UPDATE_CPU | UPDATE_WIFI | UPDATE_RADIO | UPDATE_BT; int UPDATE_RPM = 0x10; // 16 int UPDATE_ALL = UPDATE_CPU | UPDATE_WIFI | UPDATE_RADIO | UPDATE_BT | UPDATE_RPM; Future<?> scheduleSync(String reason, int flags); Future<?> scheduleCpuSyncDueToRemovedUid(int uid); Loading Loading @@ -608,6 +613,25 @@ public class BatteryStatsImpl extends BatteryStats { private PowerProfile mPowerProfile; /* * Holds a SamplingTimer associated with each Resource Power Manager state and voter, * recording their times when on-battery (regardless of screen state). */ private final HashMap<String, SamplingTimer> mRpmStats = new HashMap<>(); /** Times for each Resource Power Manager state and voter when screen-off and on-battery. */ private final HashMap<String, SamplingTimer> mScreenOffRpmStats = new HashMap<>(); @Override public Map<String, ? extends Timer> getRpmStats() { return mRpmStats; } // TODO: Note: screenOffRpmStats has been disabled via SCREEN_OFF_RPM_STATS_ENABLED. @Override public Map<String, ? extends Timer> getScreenOffRpmStats() { return mScreenOffRpmStats; } /* * Holds a SamplingTimer associated with each kernel wakelock name being tracked. */ Loading Loading @@ -2628,6 +2652,26 @@ public class BatteryStatsImpl extends BatteryStats { } } /** Get Resource Power Manager stats. Create a new one if it doesn't already exist. */ public SamplingTimer getRpmTimerLocked(String name) { SamplingTimer rpmt = mRpmStats.get(name); if (rpmt == null) { rpmt = new SamplingTimer(mClocks, mOnBatteryTimeBase); mRpmStats.put(name, rpmt); } return rpmt; } /** Get Screen-off Resource Power Manager stats. Create new one if it doesn't already exist. */ public SamplingTimer getScreenOffRpmTimerLocked(String name) { SamplingTimer rpmt = mScreenOffRpmStats.get(name); if (rpmt == null) { rpmt = new SamplingTimer(mClocks, mOnBatteryScreenOffTimeBase); mScreenOffRpmStats.put(name, rpmt); } return rpmt; } /* * Get the wakeup reason counter, and create a new one if one * doesn't already exist. Loading Loading @@ -3516,6 +3560,12 @@ public class BatteryStatsImpl extends BatteryStats { updateKernelWakelocksLocked(); updateBatteryPropertiesLocked(); } // This if{} is only necessary due to SCREEN_OFF_RPM_STATS_ENABLED, which exists because // updateRpmStatsLocked is too slow to run each screen change. When the speed is // improved, remove the surrounding if{}. if (SCREEN_OFF_RPM_STATS_ENABLED || updateOnBatteryTimeBase) { updateRpmStatsLocked(); // if either OnBattery or OnBatteryScreenOff timebase changes. } if (DEBUG_ENERGY_CPU) { Slog.d(TAG, "Updating cpu time because screen is now " + (screenOff ? "off" : "on") + " and battery is " + (unplugged ? "on" : "off")); Loading Loading @@ -9481,6 +9531,19 @@ public class BatteryStatsImpl extends BatteryStats { } } if (mRpmStats.size() > 0) { for (SamplingTimer timer : mRpmStats.values()) { mOnBatteryTimeBase.remove(timer); } mRpmStats.clear(); } if (mScreenOffRpmStats.size() > 0) { for (SamplingTimer timer : mScreenOffRpmStats.values()) { mOnBatteryScreenOffTimeBase.remove(timer); } mScreenOffRpmStats.clear(); } if (mKernelWakelockStats.size() > 0) { for (SamplingTimer timer : mKernelWakelockStats.values()) { mOnBatteryScreenOffTimeBase.remove(timer); Loading Loading @@ -10182,6 +10245,55 @@ public class BatteryStatsImpl extends BatteryStats { } } /** * Read and record Resource Power Manager state and voter times. */ public void updateRpmStatsLocked() { if (mPlatformIdleStateCallback == null) return; mPlatformIdleStateCallback.fillLowPowerStats(mTmpRpmStats); for (Map.Entry<String, RpmStats.PowerStatePlatformSleepState> pstate : mTmpRpmStats.mPlatformLowPowerStats.entrySet()) { // Update values for this platform state. final String pName = pstate.getKey(); final long pTimeUs = pstate.getValue().mTimeMs * 1000; final int pCount = pstate.getValue().mCount; getRpmTimerLocked(pName).update(pTimeUs, pCount); if (SCREEN_OFF_RPM_STATS_ENABLED) { getScreenOffRpmTimerLocked(pName).update(pTimeUs, pCount); } // Update values for each voter of this platform state. for (Map.Entry<String, RpmStats.PowerStateElement> voter : pstate.getValue().mVoters.entrySet()) { final String vName = pName + "." + voter.getKey(); final long vTimeUs = voter.getValue().mTimeMs * 1000; final int vCount = voter.getValue().mCount; getRpmTimerLocked(vName).update(vTimeUs, vCount); if (SCREEN_OFF_RPM_STATS_ENABLED) { getScreenOffRpmTimerLocked(vName).update(vTimeUs, vCount); } } } for (Map.Entry<String, RpmStats.PowerStateSubsystem> subsys : mTmpRpmStats.mSubsystemLowPowerStats.entrySet()) { final String subsysName = subsys.getKey(); for (Map.Entry<String, RpmStats.PowerStateElement> sstate : subsys.getValue().mStates.entrySet()) { final String name = subsysName + "." + sstate.getKey(); final long timeUs = sstate.getValue().mTimeMs * 1000; final int count = sstate.getValue().mCount; getRpmTimerLocked(name).update(timeUs, count); if (SCREEN_OFF_RPM_STATS_ENABLED) { getScreenOffRpmTimerLocked(name).update(timeUs, count); } } } } /** * Read and distribute kernel wake lock use across apps. */ Loading Loading @@ -11627,6 +11739,27 @@ public class BatteryStatsImpl extends BatteryStats { mBluetoothScanNesting = 0; mBluetoothScanTimer.readSummaryFromParcelLocked(in); int NRPMS = in.readInt(); if (NRPMS > 10000) { throw new ParcelFormatException("File corrupt: too many rpm stats " + NRPMS); } for (int irpm = 0; irpm < NRPMS; irpm++) { if (in.readInt() != 0) { String rpmName = in.readString(); getRpmTimerLocked(rpmName).readSummaryFromParcelLocked(in); } } int NSORPMS = in.readInt(); if (NSORPMS > 10000) { throw new ParcelFormatException("File corrupt: too many screen-off rpm stats " + NSORPMS); } for (int irpm = 0; irpm < NSORPMS; irpm++) { if (in.readInt() != 0) { String rpmName = in.readString(); getScreenOffRpmTimerLocked(rpmName).readSummaryFromParcelLocked(in); } } int NKW = in.readInt(); if (NKW > 10000) { throw new ParcelFormatException("File corrupt: too many kernel wake locks " + NKW); Loading Loading @@ -12015,6 +12148,29 @@ public class BatteryStatsImpl extends BatteryStats { mCameraOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS); mBluetoothScanTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS); out.writeInt(mRpmStats.size()); for (Map.Entry<String, SamplingTimer> ent : mRpmStats.entrySet()) { Timer rpmt = ent.getValue(); if (rpmt != null) { out.writeInt(1); out.writeString(ent.getKey()); rpmt.writeSummaryFromParcelLocked(out, NOWREAL_SYS); } else { out.writeInt(0); } } out.writeInt(mScreenOffRpmStats.size()); for (Map.Entry<String, SamplingTimer> ent : mScreenOffRpmStats.entrySet()) { Timer rpmt = ent.getValue(); if (rpmt != null) { out.writeInt(1); out.writeString(ent.getKey()); rpmt.writeSummaryFromParcelLocked(out, NOWREAL_SYS); } else { out.writeInt(0); } } out.writeInt(mKernelWakelockStats.size()); for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) { Timer kwlt = ent.getValue(); Loading Loading @@ -12474,6 +12630,25 @@ public class BatteryStatsImpl extends BatteryStats { mDischargeScreenOffCounter = new LongSamplingCounter(mOnBatteryTimeBase, in); mLastWriteTime = in.readLong(); mRpmStats.clear(); int NRPMS = in.readInt(); for (int irpm = 0; irpm < NRPMS; irpm++) { if (in.readInt() != 0) { String rpmName = in.readString(); SamplingTimer rpmt = new SamplingTimer(mClocks, mOnBatteryTimeBase, in); mRpmStats.put(rpmName, rpmt); } } mScreenOffRpmStats.clear(); int NSORPMS = in.readInt(); for (int irpm = 0; irpm < NSORPMS; irpm++) { if (in.readInt() != 0) { String rpmName = in.readString(); SamplingTimer rpmt = new SamplingTimer(mClocks, mOnBatteryScreenOffTimeBase, in); mScreenOffRpmStats.put(rpmName, rpmt); } } mKernelWakelockStats.clear(); int NKW = in.readInt(); for (int ikw = 0; ikw < NKW; ikw++) { Loading Loading @@ -12639,6 +12814,29 @@ public class BatteryStatsImpl extends BatteryStats { mDischargeScreenOffCounter.writeToParcel(out); out.writeLong(mLastWriteTime); out.writeInt(mRpmStats.size()); for (Map.Entry<String, SamplingTimer> ent : mRpmStats.entrySet()) { SamplingTimer rpmt = ent.getValue(); if (rpmt != null) { out.writeInt(1); out.writeString(ent.getKey()); rpmt.writeToParcel(out, uSecRealtime); } else { out.writeInt(0); } } out.writeInt(mScreenOffRpmStats.size()); for (Map.Entry<String, SamplingTimer> ent : mScreenOffRpmStats.entrySet()) { SamplingTimer rpmt = ent.getValue(); if (rpmt != null) { out.writeInt(1); out.writeString(ent.getKey()); rpmt.writeToParcel(out, uSecRealtime); } else { out.writeInt(0); } } if (inclUids) { out.writeInt(mKernelWakelockStats.size()); for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) { Loading @@ -12663,6 +12861,7 @@ public class BatteryStatsImpl extends BatteryStats { } } } else { // TODO: There should be two 0's printed here, not just one. out.writeInt(0); } Loading core/java/com/android/internal/os/RpmStats.java 0 → 100644 +112 −0 Original line number Diff line number Diff line /* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.internal.os; import android.util.ArrayMap; import java.util.Map; /** * Container for Resource Power Manager states and their data. * Values can be populated by the BatteryStatsService.fillLowPowerStats jni function. */ public final class RpmStats { public Map<String, PowerStatePlatformSleepState> mPlatformLowPowerStats = new ArrayMap<>(); public Map<String, PowerStateSubsystem> mSubsystemLowPowerStats = new ArrayMap<>(); /** * Finds the PowerStatePlatformSleepState with the given name (creating it if it doesn't exist), * updates its timeMs and count, and returns it. */ @SuppressWarnings("unused") public PowerStatePlatformSleepState getAndUpdatePlatformState( String name, long timeMs, int count) { PowerStatePlatformSleepState e = mPlatformLowPowerStats.get(name); if (e == null) { e = new PowerStatePlatformSleepState(); mPlatformLowPowerStats.put(name, e); } e.mTimeMs = timeMs; e.mCount = count; return e; } /** * Returns the PowerStateSubsystem with the given name (creating it if it doesn't exist). */ public PowerStateSubsystem getSubsystem(String name) { PowerStateSubsystem e = mSubsystemLowPowerStats.get(name); if (e == null) { e = new PowerStateSubsystem(); mSubsystemLowPowerStats.put(name, e); } return e; } /** Represents a subsystem state or a platform voter. */ public static class PowerStateElement { public long mTimeMs; // totalTimeInMsecVotedForSinceBoot public int mCount; // totalNumberOfTimesVotedSinceBoot private PowerStateElement(long timeMs, int count) { this.mTimeMs = timeMs; this.mCount = count; } } /** Represents a PowerStatePlatformSleepState, per hardware/interfaces/power/1.0/types.hal */ public static class PowerStatePlatformSleepState { public long mTimeMs; // residencyInMsecSinceBoot public int mCount; // totalTransitions public Map<String, PowerStateElement> mVoters = new ArrayMap<>(); // voters for this platform-level sleep state /** * Updates (creating if necessary) the voter with the given name, with the given timeMs and * count. */ @SuppressWarnings("unused") public void putVoter(String name, long timeMs, int count) { PowerStateElement e = mVoters.get(name); if (e == null) { mVoters.put(name, new PowerStateElement(timeMs, count)); } else { e.mTimeMs = timeMs; e.mCount = count; } } } /** Represents a PowerStateSubsystem, per hardware/interfaces/power/1.1/types.hal */ public static class PowerStateSubsystem { public Map<String, PowerStateElement> mStates = new ArrayMap<>(); // sleep states supported by this susbsystem /** * Updates (creating if necessary) the subsystem state with the given name, with the given * timeMs and count. */ @SuppressWarnings("unused") public void putState(String name, long timeMs, int count) { PowerStateElement e = mStates.get(name); if (e == null) { mStates.put(name, new PowerStateElement(timeMs, count)); } else { e.mTimeMs = timeMs; e.mCount = count; } } } } services/core/java/com/android/server/am/BatteryExternalStatsWorker.java +4 −0 Original line number Diff line number Diff line Loading @@ -264,6 +264,10 @@ class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStatsSync { mStats.updateKernelMemoryBandwidthLocked(); } if ((updateFlags & UPDATE_RPM) != 0) { mStats.updateRpmStatsLocked(); } if (bluetoothInfo != null) { if (bluetoothInfo.isValid()) { mStats.updateBluetoothStateLocked(bluetoothInfo); Loading services/core/java/com/android/server/am/BatteryStatsService.java +17 −2 Original line number Diff line number Diff line Loading @@ -49,6 +49,7 @@ import com.android.internal.app.IBatteryStats; import com.android.internal.os.BatteryStatsHelper; import com.android.internal.os.BatteryStatsImpl; import com.android.internal.os.PowerProfile; import com.android.internal.os.RpmStats; import com.android.internal.util.DumpUtils; import com.android.server.LocalServices; import com.android.server.power.BatterySaverPolicy.ServiceType; Loading Loading @@ -84,6 +85,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub private final Context mContext; private final BatteryExternalStatsWorker mWorker; private native void getLowPowerStats(RpmStats rpmStats); private native int getPlatformLowPowerStats(ByteBuffer outBuffer); private native int getSubsystemLowPowerStats(ByteBuffer outBuffer); private CharsetDecoder mDecoderStat = StandardCharsets.UTF_8 Loading @@ -95,6 +97,19 @@ public final class BatteryStatsService extends IBatteryStats.Stub private CharBuffer mUtf16BufferStat = CharBuffer.allocate(MAX_LOW_POWER_STATS_SIZE); private static final int MAX_LOW_POWER_STATS_SIZE = 512; /** * Replaces the information in the given rpmStats with up-to-date information. */ @Override public void fillLowPowerStats(RpmStats rpmStats) { if (DBG) Slog.d(TAG, "begin getLowPowerStats"); try { getLowPowerStats(rpmStats); } finally { if (DBG) Slog.d(TAG, "end getLowPowerStats"); } } @Override public String getPlatformLowPowerStats() { if (DBG) Slog.d(TAG, "begin getPlatformLowPowerStats"); Loading @@ -119,7 +134,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub @Override public String getSubsystemLowPowerStats() { Slog.d(TAG, "begin getSubsystemLowPowerStats"); if (DBG) Slog.d(TAG, "begin getSubsystemLowPowerStats"); try { mUtf8BufferStat.clear(); mUtf16BufferStat.clear(); Loading @@ -135,7 +150,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub mUtf16BufferStat.flip(); return mUtf16BufferStat.toString(); } finally { Slog.d(TAG, "end getSubsystemLowPowerStats"); if (DBG) Slog.d(TAG, "end getSubsystemLowPowerStats"); } } Loading Loading
core/java/android/os/BatteryStats.java +84 −10 Original line number Diff line number Diff line Loading @@ -53,6 +53,8 @@ public abstract class BatteryStats implements Parcelable { private static final String TAG = "BatteryStats"; private static final boolean LOCAL_LOGV = false; /** Fetching RPM stats is too slow to do each time screen changes, so disable it. */ protected static final boolean SCREEN_OFF_RPM_STATS_ENABLED = false; /** @hide */ public static final String SERVICE_NAME = "batterystats"; Loading Loading @@ -213,8 +215,10 @@ public abstract class BatteryStats implements Parcelable { * - Fixed bugs in background timers and BLE scan time * New in version 25: * - Package wakeup alarms are now on screen-off timebase * New in version 26: * - Resource power manager (rpm) states [but screenOffRpm is disabled from working properly] */ static final String CHECKIN_VERSION = "25"; static final String CHECKIN_VERSION = "26"; /** * Old version, we hit 9 and ran out of room, need to remove. Loading @@ -233,6 +237,10 @@ public abstract class BatteryStats implements Parcelable { private static final String CPU_DATA = "cpu"; private static final String GLOBAL_CPU_FREQ_DATA = "gcf"; private static final String CPU_TIMES_AT_FREQ_DATA = "ctf"; // rpm line is: // BATTERY_STATS_CHECKIN_VERSION, uid, which, "rpm", state/voter name, total time, total count, // screen-off time, screen-off count private static final String RESOURCE_POWER_MANAGER_DATA = "rpm"; private static final String SENSOR_DATA = "sr"; private static final String VIBRATOR_DATA = "vib"; private static final String FOREGROUND_ACTIVITY_DATA = "fg"; Loading Loading @@ -2648,6 +2656,16 @@ public abstract class BatteryStats implements Parcelable { public abstract Map<String, ? extends Timer> getKernelWakelockStats(); /** * Returns Timers tracking the total time of each Resource Power Manager state and voter. */ public abstract Map<String, ? extends Timer> getRpmStats(); /** * Returns Timers tracking the screen-off time of each Resource Power Manager state and voter. */ public abstract Map<String, ? extends Timer> getScreenOffRpmStats(); public abstract LongSparseArray<? extends Timer> getKernelMemoryStats(); public abstract void writeToParcelWithoutUids(Parcel out, int flags); Loading Loading @@ -3309,6 +3327,30 @@ public abstract class BatteryStats implements Parcelable { } } final Map<String, ? extends Timer> rpmStats = getRpmStats(); final Map<String, ? extends Timer> screenOffRpmStats = getScreenOffRpmStats(); if (rpmStats.size() > 0) { for (Map.Entry<String, ? extends Timer> ent : rpmStats.entrySet()) { sb.setLength(0); Timer totalTimer = ent.getValue(); long timeMs = (totalTimer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000; int count = totalTimer.getCountLocked(which); Timer screenOffTimer = screenOffRpmStats.get(ent.getKey()); long screenOffTimeMs = screenOffTimer != null ? (screenOffTimer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000 : 0; int screenOffCount = screenOffTimer != null ? screenOffTimer.getCountLocked(which) : 0; if (SCREEN_OFF_RPM_STATS_ENABLED) { dumpLine(pw, 0 /* uid */, category, RESOURCE_POWER_MANAGER_DATA, "\"" + ent.getKey() + "\"", timeMs, count, screenOffTimeMs, screenOffCount); } else { dumpLine(pw, 0 /* uid */, category, RESOURCE_POWER_MANAGER_DATA, "\"" + ent.getKey() + "\"", timeMs, count); } } } final BatteryStatsHelper helper = new BatteryStatsHelper(context, false, wifiOnly); helper.create(this); helper.refreshStats(which, UserHandle.USER_ALL); Loading Loading @@ -4570,6 +4612,7 @@ public abstract class BatteryStats implements Parcelable { } final LongSparseArray<? extends Timer> mMemoryStats = getKernelMemoryStats(); if (mMemoryStats.size() > 0) { pw.println(" Memory Stats"); for (int i = 0; i < mMemoryStats.size(); i++) { sb.setLength(0); Loading @@ -4579,6 +4622,36 @@ public abstract class BatteryStats implements Parcelable { sb.append(mMemoryStats.valueAt(i).getTotalTimeLocked(rawRealtime, which)); pw.println(sb.toString()); } pw.println(); } final Map<String, ? extends Timer> rpmStats = getRpmStats(); if (rpmStats.size() > 0) { pw.print(prefix); pw.println(" Resource Power Manager Stats"); if (rpmStats.size() > 0) { for (Map.Entry<String, ? extends Timer> ent : rpmStats.entrySet()) { final String timerName = ent.getKey(); final Timer timer = ent.getValue(); printTimer(pw, sb, timer, rawRealtime, which, prefix, timerName); } } pw.println(); } if (SCREEN_OFF_RPM_STATS_ENABLED) { final Map<String, ? extends Timer> screenOffRpmStats = getScreenOffRpmStats(); if (screenOffRpmStats.size() > 0) { pw.print(prefix); pw.println(" Resource Power Manager Stats for when screen was off"); if (screenOffRpmStats.size() > 0) { for (Map.Entry<String, ? extends Timer> ent : screenOffRpmStats.entrySet()) { final String timerName = ent.getKey(); final Timer timer = ent.getValue(); printTimer(pw, sb, timer, rawRealtime, which, prefix, timerName); } } pw.println(); } } final long[] cpuFreqs = getCpuFreqs(); if (cpuFreqs != null) { Loading @@ -4588,6 +4661,7 @@ public abstract class BatteryStats implements Parcelable { sb.append(" " + cpuFreqs[i]); } pw.println(sb.toString()); pw.println(); } for (int iu=0; iu<NU; iu++) { Loading
core/java/com/android/internal/os/BatteryStatsImpl.java +201 −2 Original line number Diff line number Diff line Loading @@ -119,7 +119,7 @@ public class BatteryStatsImpl extends BatteryStats { private static final int MAGIC = 0xBA757475; // 'BATSTATS' // Current on-disk Parcel version private static final int VERSION = 165 + (USE_OLD_HISTORY ? 1000 : 0); private static final int VERSION = 166 + (USE_OLD_HISTORY ? 1000 : 0); // Maximum number of items we will record in the history. private static final int MAX_HISTORY_ITEMS; Loading Loading @@ -183,6 +183,9 @@ public class BatteryStatsImpl extends BatteryStats { return mKernelMemoryStats; } /** Temporary container for Resource Power Manager stats. */ private final RpmStats mTmpRpmStats = new RpmStats(); public interface BatteryCallback { public void batteryNeedsCpuUpdate(); public void batteryPowerChanged(boolean onBattery); Loading @@ -190,6 +193,7 @@ public class BatteryStatsImpl extends BatteryStats { } public interface PlatformIdleStateCallback { public void fillLowPowerStats(RpmStats rpmStats); public String getPlatformLowPowerStats(); public String getSubsystemLowPowerStats(); } Loading Loading @@ -265,7 +269,8 @@ public class BatteryStatsImpl extends BatteryStats { int UPDATE_WIFI = 0x02; int UPDATE_RADIO = 0x04; int UPDATE_BT = 0x08; int UPDATE_ALL = UPDATE_CPU | UPDATE_WIFI | UPDATE_RADIO | UPDATE_BT; int UPDATE_RPM = 0x10; // 16 int UPDATE_ALL = UPDATE_CPU | UPDATE_WIFI | UPDATE_RADIO | UPDATE_BT | UPDATE_RPM; Future<?> scheduleSync(String reason, int flags); Future<?> scheduleCpuSyncDueToRemovedUid(int uid); Loading Loading @@ -608,6 +613,25 @@ public class BatteryStatsImpl extends BatteryStats { private PowerProfile mPowerProfile; /* * Holds a SamplingTimer associated with each Resource Power Manager state and voter, * recording their times when on-battery (regardless of screen state). */ private final HashMap<String, SamplingTimer> mRpmStats = new HashMap<>(); /** Times for each Resource Power Manager state and voter when screen-off and on-battery. */ private final HashMap<String, SamplingTimer> mScreenOffRpmStats = new HashMap<>(); @Override public Map<String, ? extends Timer> getRpmStats() { return mRpmStats; } // TODO: Note: screenOffRpmStats has been disabled via SCREEN_OFF_RPM_STATS_ENABLED. @Override public Map<String, ? extends Timer> getScreenOffRpmStats() { return mScreenOffRpmStats; } /* * Holds a SamplingTimer associated with each kernel wakelock name being tracked. */ Loading Loading @@ -2628,6 +2652,26 @@ public class BatteryStatsImpl extends BatteryStats { } } /** Get Resource Power Manager stats. Create a new one if it doesn't already exist. */ public SamplingTimer getRpmTimerLocked(String name) { SamplingTimer rpmt = mRpmStats.get(name); if (rpmt == null) { rpmt = new SamplingTimer(mClocks, mOnBatteryTimeBase); mRpmStats.put(name, rpmt); } return rpmt; } /** Get Screen-off Resource Power Manager stats. Create new one if it doesn't already exist. */ public SamplingTimer getScreenOffRpmTimerLocked(String name) { SamplingTimer rpmt = mScreenOffRpmStats.get(name); if (rpmt == null) { rpmt = new SamplingTimer(mClocks, mOnBatteryScreenOffTimeBase); mScreenOffRpmStats.put(name, rpmt); } return rpmt; } /* * Get the wakeup reason counter, and create a new one if one * doesn't already exist. Loading Loading @@ -3516,6 +3560,12 @@ public class BatteryStatsImpl extends BatteryStats { updateKernelWakelocksLocked(); updateBatteryPropertiesLocked(); } // This if{} is only necessary due to SCREEN_OFF_RPM_STATS_ENABLED, which exists because // updateRpmStatsLocked is too slow to run each screen change. When the speed is // improved, remove the surrounding if{}. if (SCREEN_OFF_RPM_STATS_ENABLED || updateOnBatteryTimeBase) { updateRpmStatsLocked(); // if either OnBattery or OnBatteryScreenOff timebase changes. } if (DEBUG_ENERGY_CPU) { Slog.d(TAG, "Updating cpu time because screen is now " + (screenOff ? "off" : "on") + " and battery is " + (unplugged ? "on" : "off")); Loading Loading @@ -9481,6 +9531,19 @@ public class BatteryStatsImpl extends BatteryStats { } } if (mRpmStats.size() > 0) { for (SamplingTimer timer : mRpmStats.values()) { mOnBatteryTimeBase.remove(timer); } mRpmStats.clear(); } if (mScreenOffRpmStats.size() > 0) { for (SamplingTimer timer : mScreenOffRpmStats.values()) { mOnBatteryScreenOffTimeBase.remove(timer); } mScreenOffRpmStats.clear(); } if (mKernelWakelockStats.size() > 0) { for (SamplingTimer timer : mKernelWakelockStats.values()) { mOnBatteryScreenOffTimeBase.remove(timer); Loading Loading @@ -10182,6 +10245,55 @@ public class BatteryStatsImpl extends BatteryStats { } } /** * Read and record Resource Power Manager state and voter times. */ public void updateRpmStatsLocked() { if (mPlatformIdleStateCallback == null) return; mPlatformIdleStateCallback.fillLowPowerStats(mTmpRpmStats); for (Map.Entry<String, RpmStats.PowerStatePlatformSleepState> pstate : mTmpRpmStats.mPlatformLowPowerStats.entrySet()) { // Update values for this platform state. final String pName = pstate.getKey(); final long pTimeUs = pstate.getValue().mTimeMs * 1000; final int pCount = pstate.getValue().mCount; getRpmTimerLocked(pName).update(pTimeUs, pCount); if (SCREEN_OFF_RPM_STATS_ENABLED) { getScreenOffRpmTimerLocked(pName).update(pTimeUs, pCount); } // Update values for each voter of this platform state. for (Map.Entry<String, RpmStats.PowerStateElement> voter : pstate.getValue().mVoters.entrySet()) { final String vName = pName + "." + voter.getKey(); final long vTimeUs = voter.getValue().mTimeMs * 1000; final int vCount = voter.getValue().mCount; getRpmTimerLocked(vName).update(vTimeUs, vCount); if (SCREEN_OFF_RPM_STATS_ENABLED) { getScreenOffRpmTimerLocked(vName).update(vTimeUs, vCount); } } } for (Map.Entry<String, RpmStats.PowerStateSubsystem> subsys : mTmpRpmStats.mSubsystemLowPowerStats.entrySet()) { final String subsysName = subsys.getKey(); for (Map.Entry<String, RpmStats.PowerStateElement> sstate : subsys.getValue().mStates.entrySet()) { final String name = subsysName + "." + sstate.getKey(); final long timeUs = sstate.getValue().mTimeMs * 1000; final int count = sstate.getValue().mCount; getRpmTimerLocked(name).update(timeUs, count); if (SCREEN_OFF_RPM_STATS_ENABLED) { getScreenOffRpmTimerLocked(name).update(timeUs, count); } } } } /** * Read and distribute kernel wake lock use across apps. */ Loading Loading @@ -11627,6 +11739,27 @@ public class BatteryStatsImpl extends BatteryStats { mBluetoothScanNesting = 0; mBluetoothScanTimer.readSummaryFromParcelLocked(in); int NRPMS = in.readInt(); if (NRPMS > 10000) { throw new ParcelFormatException("File corrupt: too many rpm stats " + NRPMS); } for (int irpm = 0; irpm < NRPMS; irpm++) { if (in.readInt() != 0) { String rpmName = in.readString(); getRpmTimerLocked(rpmName).readSummaryFromParcelLocked(in); } } int NSORPMS = in.readInt(); if (NSORPMS > 10000) { throw new ParcelFormatException("File corrupt: too many screen-off rpm stats " + NSORPMS); } for (int irpm = 0; irpm < NSORPMS; irpm++) { if (in.readInt() != 0) { String rpmName = in.readString(); getScreenOffRpmTimerLocked(rpmName).readSummaryFromParcelLocked(in); } } int NKW = in.readInt(); if (NKW > 10000) { throw new ParcelFormatException("File corrupt: too many kernel wake locks " + NKW); Loading Loading @@ -12015,6 +12148,29 @@ public class BatteryStatsImpl extends BatteryStats { mCameraOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS); mBluetoothScanTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS); out.writeInt(mRpmStats.size()); for (Map.Entry<String, SamplingTimer> ent : mRpmStats.entrySet()) { Timer rpmt = ent.getValue(); if (rpmt != null) { out.writeInt(1); out.writeString(ent.getKey()); rpmt.writeSummaryFromParcelLocked(out, NOWREAL_SYS); } else { out.writeInt(0); } } out.writeInt(mScreenOffRpmStats.size()); for (Map.Entry<String, SamplingTimer> ent : mScreenOffRpmStats.entrySet()) { Timer rpmt = ent.getValue(); if (rpmt != null) { out.writeInt(1); out.writeString(ent.getKey()); rpmt.writeSummaryFromParcelLocked(out, NOWREAL_SYS); } else { out.writeInt(0); } } out.writeInt(mKernelWakelockStats.size()); for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) { Timer kwlt = ent.getValue(); Loading Loading @@ -12474,6 +12630,25 @@ public class BatteryStatsImpl extends BatteryStats { mDischargeScreenOffCounter = new LongSamplingCounter(mOnBatteryTimeBase, in); mLastWriteTime = in.readLong(); mRpmStats.clear(); int NRPMS = in.readInt(); for (int irpm = 0; irpm < NRPMS; irpm++) { if (in.readInt() != 0) { String rpmName = in.readString(); SamplingTimer rpmt = new SamplingTimer(mClocks, mOnBatteryTimeBase, in); mRpmStats.put(rpmName, rpmt); } } mScreenOffRpmStats.clear(); int NSORPMS = in.readInt(); for (int irpm = 0; irpm < NSORPMS; irpm++) { if (in.readInt() != 0) { String rpmName = in.readString(); SamplingTimer rpmt = new SamplingTimer(mClocks, mOnBatteryScreenOffTimeBase, in); mScreenOffRpmStats.put(rpmName, rpmt); } } mKernelWakelockStats.clear(); int NKW = in.readInt(); for (int ikw = 0; ikw < NKW; ikw++) { Loading Loading @@ -12639,6 +12814,29 @@ public class BatteryStatsImpl extends BatteryStats { mDischargeScreenOffCounter.writeToParcel(out); out.writeLong(mLastWriteTime); out.writeInt(mRpmStats.size()); for (Map.Entry<String, SamplingTimer> ent : mRpmStats.entrySet()) { SamplingTimer rpmt = ent.getValue(); if (rpmt != null) { out.writeInt(1); out.writeString(ent.getKey()); rpmt.writeToParcel(out, uSecRealtime); } else { out.writeInt(0); } } out.writeInt(mScreenOffRpmStats.size()); for (Map.Entry<String, SamplingTimer> ent : mScreenOffRpmStats.entrySet()) { SamplingTimer rpmt = ent.getValue(); if (rpmt != null) { out.writeInt(1); out.writeString(ent.getKey()); rpmt.writeToParcel(out, uSecRealtime); } else { out.writeInt(0); } } if (inclUids) { out.writeInt(mKernelWakelockStats.size()); for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) { Loading @@ -12663,6 +12861,7 @@ public class BatteryStatsImpl extends BatteryStats { } } } else { // TODO: There should be two 0's printed here, not just one. out.writeInt(0); } Loading
core/java/com/android/internal/os/RpmStats.java 0 → 100644 +112 −0 Original line number Diff line number Diff line /* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.internal.os; import android.util.ArrayMap; import java.util.Map; /** * Container for Resource Power Manager states and their data. * Values can be populated by the BatteryStatsService.fillLowPowerStats jni function. */ public final class RpmStats { public Map<String, PowerStatePlatformSleepState> mPlatformLowPowerStats = new ArrayMap<>(); public Map<String, PowerStateSubsystem> mSubsystemLowPowerStats = new ArrayMap<>(); /** * Finds the PowerStatePlatformSleepState with the given name (creating it if it doesn't exist), * updates its timeMs and count, and returns it. */ @SuppressWarnings("unused") public PowerStatePlatformSleepState getAndUpdatePlatformState( String name, long timeMs, int count) { PowerStatePlatformSleepState e = mPlatformLowPowerStats.get(name); if (e == null) { e = new PowerStatePlatformSleepState(); mPlatformLowPowerStats.put(name, e); } e.mTimeMs = timeMs; e.mCount = count; return e; } /** * Returns the PowerStateSubsystem with the given name (creating it if it doesn't exist). */ public PowerStateSubsystem getSubsystem(String name) { PowerStateSubsystem e = mSubsystemLowPowerStats.get(name); if (e == null) { e = new PowerStateSubsystem(); mSubsystemLowPowerStats.put(name, e); } return e; } /** Represents a subsystem state or a platform voter. */ public static class PowerStateElement { public long mTimeMs; // totalTimeInMsecVotedForSinceBoot public int mCount; // totalNumberOfTimesVotedSinceBoot private PowerStateElement(long timeMs, int count) { this.mTimeMs = timeMs; this.mCount = count; } } /** Represents a PowerStatePlatformSleepState, per hardware/interfaces/power/1.0/types.hal */ public static class PowerStatePlatformSleepState { public long mTimeMs; // residencyInMsecSinceBoot public int mCount; // totalTransitions public Map<String, PowerStateElement> mVoters = new ArrayMap<>(); // voters for this platform-level sleep state /** * Updates (creating if necessary) the voter with the given name, with the given timeMs and * count. */ @SuppressWarnings("unused") public void putVoter(String name, long timeMs, int count) { PowerStateElement e = mVoters.get(name); if (e == null) { mVoters.put(name, new PowerStateElement(timeMs, count)); } else { e.mTimeMs = timeMs; e.mCount = count; } } } /** Represents a PowerStateSubsystem, per hardware/interfaces/power/1.1/types.hal */ public static class PowerStateSubsystem { public Map<String, PowerStateElement> mStates = new ArrayMap<>(); // sleep states supported by this susbsystem /** * Updates (creating if necessary) the subsystem state with the given name, with the given * timeMs and count. */ @SuppressWarnings("unused") public void putState(String name, long timeMs, int count) { PowerStateElement e = mStates.get(name); if (e == null) { mStates.put(name, new PowerStateElement(timeMs, count)); } else { e.mTimeMs = timeMs; e.mCount = count; } } } }
services/core/java/com/android/server/am/BatteryExternalStatsWorker.java +4 −0 Original line number Diff line number Diff line Loading @@ -264,6 +264,10 @@ class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStatsSync { mStats.updateKernelMemoryBandwidthLocked(); } if ((updateFlags & UPDATE_RPM) != 0) { mStats.updateRpmStatsLocked(); } if (bluetoothInfo != null) { if (bluetoothInfo.isValid()) { mStats.updateBluetoothStateLocked(bluetoothInfo); Loading
services/core/java/com/android/server/am/BatteryStatsService.java +17 −2 Original line number Diff line number Diff line Loading @@ -49,6 +49,7 @@ import com.android.internal.app.IBatteryStats; import com.android.internal.os.BatteryStatsHelper; import com.android.internal.os.BatteryStatsImpl; import com.android.internal.os.PowerProfile; import com.android.internal.os.RpmStats; import com.android.internal.util.DumpUtils; import com.android.server.LocalServices; import com.android.server.power.BatterySaverPolicy.ServiceType; Loading Loading @@ -84,6 +85,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub private final Context mContext; private final BatteryExternalStatsWorker mWorker; private native void getLowPowerStats(RpmStats rpmStats); private native int getPlatformLowPowerStats(ByteBuffer outBuffer); private native int getSubsystemLowPowerStats(ByteBuffer outBuffer); private CharsetDecoder mDecoderStat = StandardCharsets.UTF_8 Loading @@ -95,6 +97,19 @@ public final class BatteryStatsService extends IBatteryStats.Stub private CharBuffer mUtf16BufferStat = CharBuffer.allocate(MAX_LOW_POWER_STATS_SIZE); private static final int MAX_LOW_POWER_STATS_SIZE = 512; /** * Replaces the information in the given rpmStats with up-to-date information. */ @Override public void fillLowPowerStats(RpmStats rpmStats) { if (DBG) Slog.d(TAG, "begin getLowPowerStats"); try { getLowPowerStats(rpmStats); } finally { if (DBG) Slog.d(TAG, "end getLowPowerStats"); } } @Override public String getPlatformLowPowerStats() { if (DBG) Slog.d(TAG, "begin getPlatformLowPowerStats"); Loading @@ -119,7 +134,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub @Override public String getSubsystemLowPowerStats() { Slog.d(TAG, "begin getSubsystemLowPowerStats"); if (DBG) Slog.d(TAG, "begin getSubsystemLowPowerStats"); try { mUtf8BufferStat.clear(); mUtf16BufferStat.clear(); Loading @@ -135,7 +150,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub mUtf16BufferStat.flip(); return mUtf16BufferStat.toString(); } finally { Slog.d(TAG, "end getSubsystemLowPowerStats"); if (DBG) Slog.d(TAG, "end getSubsystemLowPowerStats"); } } Loading