diff options
| -rw-r--r-- | core/java/com/android/internal/os/BatteryStatsImpl.java | 666 |
1 files changed, 366 insertions, 300 deletions
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index 76f9a8d5f8e8..bc0d51f274b4 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -36,7 +36,6 @@ import android.net.wifi.WifiManager; import android.os.BatteryManager; import android.os.BatteryStats; import android.os.Build; -import android.os.FileUtils; import android.os.Handler; import android.os.IBatteryPropertiesRegistrar; import android.os.Looper; @@ -109,7 +108,9 @@ import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; +import java.util.Collection; import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import java.util.List; @@ -623,11 +624,11 @@ public class BatteryStatsImpl extends BatteryStats { // These are the objects that will want to do something when the device // is unplugged from power. - protected final TimeBase mOnBatteryTimeBase = new TimeBase(); + protected final TimeBase mOnBatteryTimeBase = new TimeBase(true); // These are the objects that will want to do something when the device // is unplugged from power *and* the screen is off or doze. - protected final TimeBase mOnBatteryScreenOffTimeBase = new TimeBase(); + protected final TimeBase mOnBatteryScreenOffTimeBase = new TimeBase(true); // Set to true when we want to distribute CPU across wakelocks for the next // CPU update, even if we aren't currently running wake locks. @@ -1054,15 +1055,29 @@ public class BatteryStatsImpl extends BatteryStats { mClocks = clocks; } + /** + * TimeBase observer. + */ public interface TimeBaseObs { void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime); void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime); + + /** + * Reset the observer's state, returns true if the timer/counter is inactive + * so can be completely dropped. + * @param detachIfReset detach if true, no-op if false. + * @return Returns true if the timer/counter is inactive. + */ + boolean reset(boolean detachIfReset); + /** + * Detach the observer from TimeBase. + */ + void detach(); } // methods are protected not private to be VisibleForTesting public static class TimeBase { - protected final ArrayList<TimeBaseObs> mObservers = new ArrayList<>(); - + protected final Collection<TimeBaseObs> mObservers; protected long mUptime; protected long mRealtime; @@ -1103,15 +1118,33 @@ public class BatteryStatsImpl extends BatteryStats { sb.append("mUnpluggedRealtime="); formatTimeMs(sb, mUnpluggedRealtime / 1000); pw.println(sb.toString()); } + /** + * The mObservers of TimeBase in BatteryStatsImpl object can contain up to 20k entries. + * The mObservers of TimeBase in BatteryStatsImpl.Uid object only contains a few or tens of + * entries. + * mObservers must have good performance on add(), remove(), also be memory efficient. + * This is why we provide isLongList parameter for long and short list user cases. + * @param isLongList If true, use HashSet for mObservers list. + * If false, use ArrayList for mObservers list. + */ + public TimeBase(boolean isLongList) { + if (isLongList) { + mObservers = new HashSet<TimeBaseObs>(); + } else { + mObservers = new ArrayList<TimeBaseObs>(); + } + } + + public TimeBase() { + this(false); + } public void add(TimeBaseObs observer) { mObservers.add(observer); } public void remove(TimeBaseObs observer) { - if (!mObservers.remove(observer)) { - Slog.wtf(TAG, "Removed unknown observer: " + observer); - } + mObservers.remove(observer); } public boolean hasObserver(TimeBaseObs observer) { @@ -1196,6 +1229,11 @@ public class BatteryStatsImpl extends BatteryStats { return mRunning; } + /** + * Normally we do not use Iterator in framework code to avoid alloc/dealloc + * Iterator object, here is an exception because mObservers' type is Collection + * instead of list. + */ public boolean setRunning(boolean running, long uptime, long realtime) { if (mRunning != running) { mRunning = running; @@ -1204,19 +1242,18 @@ public class BatteryStatsImpl extends BatteryStats { mRealtimeStart = realtime; long batteryUptime = mUnpluggedUptime = getUptime(uptime); long batteryRealtime = mUnpluggedRealtime = getRealtime(realtime); - - for (int i = mObservers.size() - 1; i >= 0; i--) { - mObservers.get(i).onTimeStarted(realtime, batteryUptime, batteryRealtime); + final Iterator<TimeBaseObs> iter = mObservers.iterator(); + while (iter.hasNext()) { + iter.next().onTimeStarted(realtime, batteryUptime, batteryRealtime); } } else { mPastUptime += uptime - mUptimeStart; mPastRealtime += realtime - mRealtimeStart; - long batteryUptime = getUptime(uptime); long batteryRealtime = getRealtime(realtime); - - for (int i = mObservers.size() - 1; i >= 0; i--) { - mObservers.get(i).onTimeStopped(realtime, batteryUptime, batteryRealtime); + final Iterator<TimeBaseObs> iter = mObservers.iterator(); + while (iter.hasNext()) { + iter.next().onTimeStopped(realtime, batteryUptime, batteryRealtime); } } return true; @@ -1364,15 +1401,18 @@ public class BatteryStatsImpl extends BatteryStats { /** * Clear state of this counter. */ - void reset(boolean detachIfReset) { + @Override + public boolean reset(boolean detachIfReset) { mCount.set(0); mLoadedCount = mPluggedCount = mUnpluggedCount = 0; if (detachIfReset) { detach(); } + return true; } - void detach() { + @Override + public void detach() { mTimeBase.remove(this); } @@ -1468,15 +1508,18 @@ public class BatteryStatsImpl extends BatteryStats { /** * Clear state of this counter. */ - public void reset(boolean detachIfReset) { + @Override + public boolean reset(boolean detachIfReset) { fillArray(mCounts, 0); fillArray(mLoadedCounts, 0); fillArray(mUnpluggedCounts, 0); if (detachIfReset) { detach(); } + return true; } + @Override public void detach() { mTimeBase.remove(this); } @@ -1639,14 +1682,17 @@ public class BatteryStatsImpl extends BatteryStats { /** * Clear state of this counter. */ - public void reset(boolean detachIfReset) { + @Override + public boolean reset(boolean detachIfReset) { mCount = 0; mLoadedCount = mUnpluggedCount = 0; if (detachIfReset) { detach(); } + return true; } + @Override public void detach() { mTimeBase.remove(this); } @@ -1747,6 +1793,7 @@ public class BatteryStatsImpl extends BatteryStats { * Clear state of this timer. Returns true if the timer is inactive * so can be completely dropped. */ + @Override public boolean reset(boolean detachIfReset) { mTotalTime = mLoadedTime = mLastTime = mTimeBeforeMark = 0; mCount = mLoadedCount = mLastCount = 0; @@ -1756,6 +1803,7 @@ public class BatteryStatsImpl extends BatteryStats { return true; } + @Override public void detach() { mTimeBase.remove(this); } @@ -6547,37 +6595,68 @@ public class BatteryStatsImpl extends BatteryStats { return mUidStats; } - private static void detachTimerIfNotNull(BatteryStatsImpl.Timer timer) { - if (timer != null) { - timer.detach(); + private static <T extends TimeBaseObs> boolean resetIfNotNull(T t, boolean detachIfReset) { + if (t != null) { + return t.reset(detachIfReset); } + return true; } - private static boolean resetTimerIfNotNull(BatteryStatsImpl.Timer timer, - boolean detachIfReset) { - if (timer != null) { - return timer.reset(detachIfReset); + private static <T extends TimeBaseObs> boolean resetIfNotNull(T[] t, boolean detachIfReset) { + if (t != null) { + boolean ret = true; + for (int i = 0; i < t.length; i++) { + ret &= resetIfNotNull(t[i], detachIfReset); + } + return ret; } return true; } - private static boolean resetTimerIfNotNull(DualTimer timer, boolean detachIfReset) { - if (timer != null) { - return timer.reset(detachIfReset); + private static <T extends TimeBaseObs> boolean resetIfNotNull(T[][] t, boolean detachIfReset) { + if (t != null) { + boolean ret = true; + for (int i = 0; i < t.length; i++) { + ret &= resetIfNotNull(t[i], detachIfReset); + } + return ret; } return true; } - private static void detachLongCounterIfNotNull(LongSamplingCounter counter) { + + private static boolean resetIfNotNull(ControllerActivityCounterImpl counter, boolean detachIfReset) { if (counter != null) { - counter.detach(); + counter.reset(detachIfReset); + } + return true; + } + + private static <T extends TimeBaseObs> void detachIfNotNull(T t) { + if (t != null) { + t.detach(); + } + } + + private static <T extends TimeBaseObs> void detachIfNotNull(T[] t) { + if (t != null) { + for (int i = 0; i < t.length; i++) { + detachIfNotNull(t[i]); + } } } - private static void resetLongCounterIfNotNull(LongSamplingCounter counter, - boolean detachIfReset) { + private static <T extends TimeBaseObs> void detachIfNotNull(T[][] t) { + if (t != null) { + for (int i = 0; i < t.length; i++) { + detachIfNotNull(t[i]); + } + } + } + + private static void detachIfNotNull(ControllerActivityCounterImpl counter) { if (counter != null) { - counter.reset(detachIfReset); + counter.detach(); } } @@ -6758,11 +6837,12 @@ public class BatteryStatsImpl extends BatteryStats { mBsi = bsi; mUid = uid; - mOnBatteryBackgroundTimeBase = new TimeBase(); + /* Observer list of TimeBase object in Uid is short */ + mOnBatteryBackgroundTimeBase = new TimeBase(false); mOnBatteryBackgroundTimeBase.init(mBsi.mClocks.uptimeMillis() * 1000, mBsi.mClocks.elapsedRealtime() * 1000); - - mOnBatteryScreenOffBackgroundTimeBase = new TimeBase(); + /* Observer list of TimeBase object in Uid is short */ + mOnBatteryScreenOffBackgroundTimeBase = new TimeBase(false); mOnBatteryScreenOffBackgroundTimeBase.init(mBsi.mClocks.uptimeMillis() * 1000, mBsi.mClocks.elapsedRealtime() * 1000); @@ -6914,6 +6994,7 @@ public class BatteryStatsImpl extends BatteryStats { } if (mProcStateScreenOffTimeMs[procState] == null || mProcStateScreenOffTimeMs[procState].getSize() != cpuTimesMs.length) { + detachIfNotNull(mProcStateScreenOffTimeMs[procState]); mProcStateScreenOffTimeMs[procState] = new LongSamplingCounterArray( mBsi.mOnBatteryScreenOffTimeBase); } @@ -7518,6 +7599,7 @@ public class BatteryStatsImpl extends BatteryStats { void makeProcessState(int i, Parcel in) { if (i < 0 || i >= NUM_PROCESS_STATE) return; + detachIfNotNull(mProcessStateTimer[i]); if (in == null) { mProcessStateTimer[i] = new StopwatchTimer(mBsi.mClocks, this, PROCESS_STATE, null, mBsi.mOnBatteryTimeBase); @@ -7581,6 +7663,7 @@ public class BatteryStatsImpl extends BatteryStats { collected = new ArrayList<StopwatchTimer>(); mBsi.mWifiBatchedScanTimers.put(i, collected); } + detachIfNotNull(mWifiBatchedScanTimer[i]); if (in == null) { mWifiBatchedScanTimer[i] = new StopwatchTimer(mBsi.mClocks, this, WIFI_BATCHED_SCAN, collected, mBsi.mOnBatteryTimeBase); @@ -7760,13 +7843,17 @@ public class BatteryStatsImpl extends BatteryStats { } void initNetworkActivityLocked() { + detachIfNotNull(mNetworkByteActivityCounters); mNetworkByteActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES]; + detachIfNotNull(mNetworkPacketActivityCounters); mNetworkPacketActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES]; for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) { mNetworkByteActivityCounters[i] = new LongSamplingCounter(mBsi.mOnBatteryTimeBase); mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mBsi.mOnBatteryTimeBase); } + detachIfNotNull(mMobileRadioActiveTime); mMobileRadioActiveTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase); + detachIfNotNull(mMobileRadioActiveCount); mMobileRadioActiveCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase); } @@ -7806,27 +7893,22 @@ public class BatteryStatsImpl extends BatteryStats { active |= mWifiMulticastEnabled; } - active |= !resetTimerIfNotNull(mAudioTurnedOnTimer, false); - active |= !resetTimerIfNotNull(mVideoTurnedOnTimer, false); - active |= !resetTimerIfNotNull(mFlashlightTurnedOnTimer, false); - active |= !resetTimerIfNotNull(mCameraTurnedOnTimer, false); - active |= !resetTimerIfNotNull(mForegroundActivityTimer, false); - active |= !resetTimerIfNotNull(mForegroundServiceTimer, false); - active |= !resetTimerIfNotNull(mAggregatedPartialWakelockTimer, false); - active |= !resetTimerIfNotNull(mBluetoothScanTimer, false); - active |= !resetTimerIfNotNull(mBluetoothUnoptimizedScanTimer, false); - if (mBluetoothScanResultCounter != null) { - mBluetoothScanResultCounter.reset(false); - } - if (mBluetoothScanResultBgCounter != null) { - mBluetoothScanResultBgCounter.reset(false); - } + active |= !resetIfNotNull(mAudioTurnedOnTimer, false); + active |= !resetIfNotNull(mVideoTurnedOnTimer, false); + active |= !resetIfNotNull(mFlashlightTurnedOnTimer, false); + active |= !resetIfNotNull(mCameraTurnedOnTimer, false); + active |= !resetIfNotNull(mForegroundActivityTimer, false); + active |= !resetIfNotNull(mForegroundServiceTimer, false); + active |= !resetIfNotNull(mAggregatedPartialWakelockTimer, false); + active |= !resetIfNotNull(mBluetoothScanTimer, false); + active |= !resetIfNotNull(mBluetoothUnoptimizedScanTimer, false); + + resetIfNotNull(mBluetoothScanResultCounter, false); + resetIfNotNull(mBluetoothScanResultBgCounter, false); if (mProcessStateTimer != null) { for (int i = 0; i < NUM_PROCESS_STATE; i++) { - if (mProcessStateTimer[i] != null) { - active |= !mProcessStateTimer[i].reset(false); - } + active |= !resetIfNotNull(mProcessStateTimer[i], false); } active |= (mProcessState != ActivityManager.PROCESS_STATE_NONEXISTENT); } @@ -7839,75 +7921,37 @@ public class BatteryStatsImpl extends BatteryStats { } } - if (mUserActivityCounters != null) { - for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) { - mUserActivityCounters[i].reset(false); - } - } + resetIfNotNull(mUserActivityCounters, false); - if (mNetworkByteActivityCounters != null) { - for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) { - mNetworkByteActivityCounters[i].reset(false); - mNetworkPacketActivityCounters[i].reset(false); - } - mMobileRadioActiveTime.reset(false); - mMobileRadioActiveCount.reset(false); - } + resetIfNotNull(mNetworkByteActivityCounters, false); + resetIfNotNull(mNetworkPacketActivityCounters, false); + resetIfNotNull(mMobileRadioActiveTime, false); + resetIfNotNull(mMobileRadioActiveCount, false); - if (mWifiControllerActivity != null) { - mWifiControllerActivity.reset(false); - } + resetIfNotNull(mWifiControllerActivity, false); + resetIfNotNull(mBluetoothControllerActivity, false); + resetIfNotNull(mModemControllerActivity, false); - if (mBluetoothControllerActivity != null) { - mBluetoothControllerActivity.reset(false); - } + resetIfNotNull(mUserCpuTime, false); + resetIfNotNull(mSystemCpuTime, false); - if (mModemControllerActivity != null) { - mModemControllerActivity.reset(false); - } + resetIfNotNull(mCpuClusterSpeedTimesUs, false); - mUserCpuTime.reset(false); - mSystemCpuTime.reset(false); + resetIfNotNull(mCpuFreqTimeMs, false); + resetIfNotNull(mScreenOffCpuFreqTimeMs, false); - if (mCpuClusterSpeedTimesUs != null) { - for (LongSamplingCounter[] speeds : mCpuClusterSpeedTimesUs) { - if (speeds != null) { - for (LongSamplingCounter speed : speeds) { - if (speed != null) { - speed.reset(false); - } - } - } - } - } - if (mCpuFreqTimeMs != null) { - mCpuFreqTimeMs.reset(false); - } - if (mScreenOffCpuFreqTimeMs != null) { - mScreenOffCpuFreqTimeMs.reset(false); - } + resetIfNotNull(mCpuActiveTimeMs, false); + resetIfNotNull(mCpuClusterTimesMs, false); - mCpuActiveTimeMs.reset(false); - mCpuClusterTimesMs.reset(false); + resetIfNotNull(mProcStateTimeMs, false); - if (mProcStateTimeMs != null) { - for (LongSamplingCounterArray counters : mProcStateTimeMs) { - if (counters != null) { - counters.reset(false); - } - } - } - if (mProcStateScreenOffTimeMs != null) { - for (LongSamplingCounterArray counters : mProcStateScreenOffTimeMs) { - if (counters != null) { - counters.reset(false); - } - } - } + resetIfNotNull(mProcStateScreenOffTimeMs, false); + + resetIfNotNull(mMobileRadioApWakeupCount, false); + + resetIfNotNull(mWifiRadioApWakeupCount, false); - resetLongCounterIfNotNull(mMobileRadioApWakeupCount, false); - resetLongCounterIfNotNull(mWifiRadioApWakeupCount, false); final ArrayMap<String, Wakelock> wakeStats = mWakelockStats.getMap(); for (int iw=wakeStats.size()-1; iw>=0; iw--) { @@ -7943,16 +7987,12 @@ public class BatteryStatsImpl extends BatteryStats { mJobStats.cleanup(); mJobCompletions.clear(); - mJobsDeferredEventCount.reset(false); - mJobsDeferredCount.reset(false); - mJobsFreshnessTimeMs.reset(false); - for (int ij = 0; ij < JOB_FRESHNESS_BUCKETS.length; ij++) { - if (mJobsFreshnessBuckets[ij] != null) { - mJobsFreshnessBuckets[ij].reset(false); - } - } + resetIfNotNull(mJobsDeferredEventCount, false); + resetIfNotNull(mJobsDeferredCount, false); + resetIfNotNull(mJobsFreshnessTimeMs, false); + resetIfNotNull(mJobsFreshnessBuckets, false); - for (int ise=mSensorStats.size()-1; ise>=0; ise--) { + for (int ise = mSensorStats.size() - 1; ise >= 0; ise--) { Sensor s = mSensorStats.valueAt(ise); if (s.reset()) { mSensorStats.removeAt(ise); @@ -7961,173 +8001,135 @@ public class BatteryStatsImpl extends BatteryStats { } } - for (int ip=mProcessStats.size()-1; ip>=0; ip--) { + for (int ip = mProcessStats.size() - 1; ip >= 0; ip--) { Proc proc = mProcessStats.valueAt(ip); proc.detach(); } mProcessStats.clear(); - if (mPids.size() > 0) { - for (int i=mPids.size()-1; i>=0; i--) { - Pid pid = mPids.valueAt(i); - if (pid.mWakeNesting > 0) { - active = true; - } else { - mPids.removeAt(i); - } + + for (int i = mPids.size() - 1; i >= 0; i--) { + Pid pid = mPids.valueAt(i); + if (pid.mWakeNesting > 0) { + active = true; + } else { + mPids.removeAt(i); } } - if (mPackageStats.size() > 0) { - Iterator<Map.Entry<String, Pkg>> it = mPackageStats.entrySet().iterator(); - while (it.hasNext()) { - Map.Entry<String, Pkg> pkgEntry = it.next(); - Pkg p = pkgEntry.getValue(); - p.detach(); - if (p.mServiceStats.size() > 0) { - Iterator<Map.Entry<String, Pkg.Serv>> it2 - = p.mServiceStats.entrySet().iterator(); - while (it2.hasNext()) { - Map.Entry<String, Pkg.Serv> servEntry = it2.next(); - servEntry.getValue().detach(); - } - } - } - mPackageStats.clear(); + + + for(int i = mPackageStats.size() - 1; i >= 0; i--) { + Pkg p = mPackageStats.valueAt(i); + p.detach(); } + mPackageStats.clear(); mLastStepUserTime = mLastStepSystemTime = 0; mCurStepUserTime = mCurStepSystemTime = 0; - if (!active) { - if (mWifiRunningTimer != null) { - mWifiRunningTimer.detach(); - } - if (mFullWifiLockTimer != null) { - mFullWifiLockTimer.detach(); - } - if (mWifiScanTimer != null) { - mWifiScanTimer.detach(); - } - for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) { - if (mWifiBatchedScanTimer[i] != null) { - mWifiBatchedScanTimer[i].detach(); - } - } - if (mWifiMulticastTimer != null) { - mWifiMulticastTimer.detach(); - } - if (mAudioTurnedOnTimer != null) { - mAudioTurnedOnTimer.detach(); - mAudioTurnedOnTimer = null; - } - if (mVideoTurnedOnTimer != null) { - mVideoTurnedOnTimer.detach(); - mVideoTurnedOnTimer = null; - } - if (mFlashlightTurnedOnTimer != null) { - mFlashlightTurnedOnTimer.detach(); - mFlashlightTurnedOnTimer = null; - } - if (mCameraTurnedOnTimer != null) { - mCameraTurnedOnTimer.detach(); - mCameraTurnedOnTimer = null; - } - if (mForegroundActivityTimer != null) { - mForegroundActivityTimer.detach(); - mForegroundActivityTimer = null; - } - if (mForegroundServiceTimer != null) { - mForegroundServiceTimer.detach(); - mForegroundServiceTimer = null; - } - if (mAggregatedPartialWakelockTimer != null) { - mAggregatedPartialWakelockTimer.detach(); - mAggregatedPartialWakelockTimer = null; - } - if (mBluetoothScanTimer != null) { - mBluetoothScanTimer.detach(); - mBluetoothScanTimer = null; - } - if (mBluetoothUnoptimizedScanTimer != null) { - mBluetoothUnoptimizedScanTimer.detach(); - mBluetoothUnoptimizedScanTimer = null; - } - if (mBluetoothScanResultCounter != null) { - mBluetoothScanResultCounter.detach(); - mBluetoothScanResultCounter = null; - } - if (mBluetoothScanResultBgCounter != null) { - mBluetoothScanResultBgCounter.detach(); - mBluetoothScanResultBgCounter = null; - } - if (mUserActivityCounters != null) { - for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) { - mUserActivityCounters[i].detach(); - } - } - if (mNetworkByteActivityCounters != null) { - for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) { - mNetworkByteActivityCounters[i].detach(); - mNetworkPacketActivityCounters[i].detach(); - } - } + return !active; + } - if (mWifiControllerActivity != null) { - mWifiControllerActivity.detach(); - } + /** + * This method MUST be called whenever the Uid object is destructed, otherwise it is a + * memory leak in {@link TimeBase#mObservers} list. + * Typically the Uid object is destructed when it is removed from + * {@link BatteryStatsImpl#mUidStats} + */ + void detachFromTimeBase() { + detachIfNotNull(mWifiRunningTimer); + detachIfNotNull(mFullWifiLockTimer); + detachIfNotNull(mWifiScanTimer); + detachIfNotNull(mWifiBatchedScanTimer); + detachIfNotNull(mWifiMulticastTimer); + detachIfNotNull(mAudioTurnedOnTimer); + detachIfNotNull(mVideoTurnedOnTimer); + detachIfNotNull(mFlashlightTurnedOnTimer); - if (mBluetoothControllerActivity != null) { - mBluetoothControllerActivity.detach(); - } + detachIfNotNull(mCameraTurnedOnTimer); + detachIfNotNull(mForegroundActivityTimer); + detachIfNotNull(mForegroundServiceTimer); - if (mModemControllerActivity != null) { - mModemControllerActivity.detach(); - } + detachIfNotNull(mAggregatedPartialWakelockTimer); - mPids.clear(); + detachIfNotNull(mBluetoothScanTimer); + detachIfNotNull(mBluetoothUnoptimizedScanTimer); + detachIfNotNull(mBluetoothScanResultCounter); + detachIfNotNull(mBluetoothScanResultBgCounter); - mUserCpuTime.detach(); - mSystemCpuTime.detach(); + detachIfNotNull(mProcessStateTimer); - if (mCpuClusterSpeedTimesUs != null) { - for (LongSamplingCounter[] cpuSpeeds : mCpuClusterSpeedTimesUs) { - if (cpuSpeeds != null) { - for (LongSamplingCounter c : cpuSpeeds) { - if (c != null) { - c.detach(); - } - } - } - } - } + detachIfNotNull(mVibratorOnTimer); - if (mCpuFreqTimeMs != null) { - mCpuFreqTimeMs.detach(); - } - if (mScreenOffCpuFreqTimeMs != null) { - mScreenOffCpuFreqTimeMs.detach(); - } - mCpuActiveTimeMs.detach(); - mCpuClusterTimesMs.detach(); + detachIfNotNull(mUserActivityCounters); - if (mProcStateTimeMs != null) { - for (LongSamplingCounterArray counters : mProcStateTimeMs) { - if (counters != null) { - counters.detach(); - } - } - } - if (mProcStateScreenOffTimeMs != null) { - for (LongSamplingCounterArray counters : mProcStateScreenOffTimeMs) { - if (counters != null) { - counters.detach(); - } - } - } - detachLongCounterIfNotNull(mMobileRadioApWakeupCount); - detachLongCounterIfNotNull(mWifiRadioApWakeupCount); + detachIfNotNull(mNetworkByteActivityCounters); + detachIfNotNull(mNetworkPacketActivityCounters); + + detachIfNotNull(mMobileRadioActiveTime); + detachIfNotNull(mMobileRadioActiveCount); + detachIfNotNull(mMobileRadioApWakeupCount); + detachIfNotNull(mWifiRadioApWakeupCount); + + detachIfNotNull(mWifiControllerActivity); + detachIfNotNull(mBluetoothControllerActivity); + detachIfNotNull(mModemControllerActivity); + + mPids.clear(); + + detachIfNotNull(mUserCpuTime); + detachIfNotNull(mSystemCpuTime); + + detachIfNotNull(mCpuClusterSpeedTimesUs); + + detachIfNotNull(mCpuActiveTimeMs); + detachIfNotNull(mCpuFreqTimeMs); + + detachIfNotNull(mScreenOffCpuFreqTimeMs); + + detachIfNotNull(mCpuClusterTimesMs); + + detachIfNotNull(mProcStateTimeMs); + + detachIfNotNull(mProcStateScreenOffTimeMs); + + final ArrayMap<String, Wakelock> wakeStats = mWakelockStats.getMap(); + for (int iw = wakeStats.size() - 1; iw >= 0; iw--) { + Wakelock wl = wakeStats.valueAt(iw); + wl.detachFromTimeBase(); + } + final ArrayMap<String, DualTimer> syncStats = mSyncStats.getMap(); + for (int is = syncStats.size() - 1; is >= 0; is--) { + DualTimer timer = syncStats.valueAt(is); + detachIfNotNull(timer); + } + final ArrayMap<String, DualTimer> jobStats = mJobStats.getMap(); + for (int ij = jobStats.size() - 1; ij >= 0; ij--) { + DualTimer timer = jobStats.valueAt(ij); + detachIfNotNull(timer); } - return !active; + detachIfNotNull(mJobsDeferredEventCount); + detachIfNotNull(mJobsDeferredCount); + detachIfNotNull(mJobsFreshnessTimeMs); + detachIfNotNull(mJobsFreshnessBuckets); + + + for (int ise = mSensorStats.size() - 1; ise >= 0; ise--) { + Sensor s = mSensorStats.valueAt(ise); + s.detachFromTimeBase(); + } + + for (int ip= mProcessStats.size() - 1; ip >= 0; ip--) { + Proc proc = mProcessStats.valueAt(ip); + proc.detach(); + } + mProcessStats.clear(); + + for(int i = mPackageStats.size() - 1; i >= 0; i--) { + Pkg p = mPackageStats.valueAt(i); + p.detach(); + } + mPackageStats.clear(); } void writeJobCompletionsToParcelLocked(Parcel out) { @@ -8850,35 +8852,24 @@ public class BatteryStatsImpl extends BatteryStats { boolean reset() { boolean wlactive = false; - if (mTimerFull != null) { - wlactive |= !mTimerFull.reset(false); - } - if (mTimerPartial != null) { - wlactive |= !mTimerPartial.reset(false); - } - if (mTimerWindow != null) { - wlactive |= !mTimerWindow.reset(false); - } - if (mTimerDraw != null) { - wlactive |= !mTimerDraw.reset(false); - } + + wlactive |= !resetIfNotNull(mTimerFull,false); + wlactive |= !resetIfNotNull(mTimerPartial,false); + wlactive |= !resetIfNotNull(mTimerWindow,false); + wlactive |= !resetIfNotNull(mTimerDraw,false); + if (!wlactive) { - if (mTimerFull != null) { - mTimerFull.detach(); - mTimerFull = null; - } - if (mTimerPartial != null) { - mTimerPartial.detach(); - mTimerPartial = null; - } - if (mTimerWindow != null) { - mTimerWindow.detach(); - mTimerWindow = null; - } - if (mTimerDraw != null) { - mTimerDraw.detach(); - mTimerDraw = null; - } + detachIfNotNull(mTimerFull); + mTimerFull = null; + + detachIfNotNull(mTimerPartial); + mTimerPartial = null; + + detachIfNotNull(mTimerWindow); + mTimerWindow = null; + + detachIfNotNull(mTimerDraw); + mTimerDraw = null; } return !wlactive; } @@ -8912,6 +8903,13 @@ public class BatteryStatsImpl extends BatteryStats { default: throw new IllegalArgumentException("type = " + type); } } + + public void detachFromTimeBase() { + detachIfNotNull(mTimerPartial); + detachIfNotNull(mTimerFull); + detachIfNotNull(mTimerWindow); + detachIfNotNull(mTimerDraw); + } } public static class Sensor extends BatteryStats.Uid.Sensor { @@ -8981,6 +8979,10 @@ public class BatteryStatsImpl extends BatteryStats { public int getHandle() { return mHandle; } + + public void detachFromTimeBase() { + detachIfNotNull(mTimer); + } } /** @@ -9112,7 +9114,16 @@ public class BatteryStatsImpl extends BatteryStats { public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) { } - void detach() { + @Override + public boolean reset(boolean detachIfReset) { + if (detachIfReset) { + this.detach(); + } + return true; + } + + @Override + public void detach() { mActive = false; mBsi.mOnBatteryTimeBase.remove(this); } @@ -9351,8 +9362,23 @@ public class BatteryStatsImpl extends BatteryStats { public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) { } - void detach() { + @Override + public boolean reset(boolean detachIfReset) { + if (detachIfReset) { + this.detach(); + } + return true; + } + + @Override + public void detach() { mBsi.mOnBatteryScreenOffTimeBase.remove(this); + for (int j = mWakeupAlarms.size() - 1; j >= 0; j--) { + detachIfNotNull(mWakeupAlarms.valueAt(j)); + } + for (int j = mServiceStats.size() - 1; j >= 0; j--) { + detachIfNotNull(mServiceStats.valueAt(j)); + } } void readFromParcelLocked(Parcel in) { @@ -9533,9 +9559,18 @@ public class BatteryStatsImpl extends BatteryStats { long baseRealtime) { } + @Override + public boolean reset(boolean detachIfReset) { + if (detachIfReset) { + this.detach(); + } + return true; + } + /** * Remove this Serv as a listener from the time base. */ + @Override public void detach() { mBsi.mOnBatteryTimeBase.remove(this); } @@ -9852,6 +9887,7 @@ public class BatteryStatsImpl extends BatteryStats { } t = new DualTimer(mBsi.mClocks, this, BatteryStats.SENSOR, timers, mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase); + detachIfNotNull(se.mTimer); se.mTimer = t; return t; } @@ -10795,6 +10831,7 @@ public class BatteryStatsImpl extends BatteryStats { for (int i=0; i<mUidStats.size(); i++) { if (mUidStats.valueAt(i).reset(uptimeMillis * 1000, elapsedRealtimeMillis * 1000)) { + mUidStats.valueAt(i).detachFromTimeBase(); mUidStats.remove(mUidStats.keyAt(i)); i--; } @@ -12101,11 +12138,13 @@ public class BatteryStatsImpl extends BatteryStats { } final Uid u = getUidStatsLocked(uid); if (u.mCpuFreqTimeMs == null || u.mCpuFreqTimeMs.getSize() != cpuFreqTimeMs.length) { + detachIfNotNull(u.mCpuFreqTimeMs); u.mCpuFreqTimeMs = new LongSamplingCounterArray(mOnBatteryTimeBase); } u.mCpuFreqTimeMs.addCountLocked(cpuFreqTimeMs, onBattery); if (u.mScreenOffCpuFreqTimeMs == null || u.mScreenOffCpuFreqTimeMs.getSize() != cpuFreqTimeMs.length) { + detachIfNotNull(u.mScreenOffCpuFreqTimeMs); u.mScreenOffCpuFreqTimeMs = new LongSamplingCounterArray( mOnBatteryScreenOffTimeBase); } @@ -12114,6 +12153,7 @@ public class BatteryStatsImpl extends BatteryStats { if (perClusterTimesAvailable) { if (u.mCpuClusterSpeedTimesUs == null || u.mCpuClusterSpeedTimesUs.length != numClusters) { + detachIfNotNull(u.mCpuClusterSpeedTimesUs); u.mCpuClusterSpeedTimesUs = new LongSamplingCounter[numClusters][]; } if (numWakelocks > 0 && mWakeLockAllocationsUs == null) { @@ -12125,6 +12165,7 @@ public class BatteryStatsImpl extends BatteryStats { final int speedsInCluster = mPowerProfile.getNumSpeedStepsInCpuCluster(cluster); if (u.mCpuClusterSpeedTimesUs[cluster] == null || u.mCpuClusterSpeedTimesUs[cluster].length != speedsInCluster) { + detachIfNotNull(u.mCpuClusterSpeedTimesUs[cluster]); u.mCpuClusterSpeedTimesUs[cluster] = new LongSamplingCounter[speedsInCluster]; } @@ -12162,6 +12203,7 @@ public class BatteryStatsImpl extends BatteryStats { final Uid u = partialTimers.get(i).mUid; if (u.mCpuClusterSpeedTimesUs == null || u.mCpuClusterSpeedTimesUs.length != numClusters) { + detachIfNotNull(u.mCpuClusterSpeedTimesUs); u.mCpuClusterSpeedTimesUs = new LongSamplingCounter[numClusters][]; } @@ -12169,6 +12211,7 @@ public class BatteryStatsImpl extends BatteryStats { final int speedsInCluster = mPowerProfile.getNumSpeedStepsInCpuCluster(cluster); if (u.mCpuClusterSpeedTimesUs[cluster] == null || u.mCpuClusterSpeedTimesUs[cluster].length != speedsInCluster) { + detachIfNotNull(u.mCpuClusterSpeedTimesUs[cluster]); u.mCpuClusterSpeedTimesUs[cluster] = new LongSamplingCounter[speedsInCluster]; } @@ -13106,6 +13149,12 @@ public class BatteryStatsImpl extends BatteryStats { mUidStats.put(lastUidForUser, null); final int firstIndex = mUidStats.indexOfKey(firstUidForUser); final int lastIndex = mUidStats.indexOfKey(lastUidForUser); + for (int i = firstIndex; i <= lastIndex; i++) { + final Uid uid = mUidStats.valueAt(i); + if (uid != null) { + uid.detachFromTimeBase(); + } + } mUidStats.removeAtRange(firstIndex, lastIndex - firstIndex + 1); } @@ -13113,6 +13162,10 @@ public class BatteryStatsImpl extends BatteryStats { * Remove the statistics object for a particular uid. */ public void removeUidStatsLocked(int uid) { + final Uid u = mUidStats.get(uid); + if (u != null) { + u.detachFromTimeBase(); + } mUidStats.remove(uid); mPendingRemovedUids.add(new UidToRemove(uid, mClocks.elapsedRealtime())); } @@ -13978,7 +14031,7 @@ public class BatteryStatsImpl extends BatteryStats { if (mPowerProfile != null && mPowerProfile.getNumCpuClusters() != numClusters) { throw new ParcelFormatException("Incompatible cpu cluster arrangement"); } - + detachIfNotNull(u.mCpuClusterSpeedTimesUs); u.mCpuClusterSpeedTimesUs = new LongSamplingCounter[numClusters][]; for (int cluster = 0; cluster < numClusters; cluster++) { if (in.readInt() != 0) { @@ -14002,11 +14055,14 @@ public class BatteryStatsImpl extends BatteryStats { } } } else { + detachIfNotNull(u.mCpuClusterSpeedTimesUs); u.mCpuClusterSpeedTimesUs = null; } + detachIfNotNull(u.mCpuFreqTimeMs); u.mCpuFreqTimeMs = LongSamplingCounterArray.readSummaryFromParcelLocked( in, mOnBatteryTimeBase); + detachIfNotNull(u.mScreenOffCpuFreqTimeMs); u.mScreenOffCpuFreqTimeMs = LongSamplingCounterArray.readSummaryFromParcelLocked( in, mOnBatteryScreenOffTimeBase); @@ -14015,6 +14071,7 @@ public class BatteryStatsImpl extends BatteryStats { int length = in.readInt(); if (length == Uid.NUM_PROCESS_STATE) { + detachIfNotNull(u.mProcStateTimeMs); u.mProcStateTimeMs = new LongSamplingCounterArray[length]; for (int procState = 0; procState < length; ++procState) { u.mProcStateTimeMs[procState] @@ -14022,10 +14079,12 @@ public class BatteryStatsImpl extends BatteryStats { in, mOnBatteryTimeBase); } } else { + detachIfNotNull(u.mProcStateTimeMs); u.mProcStateTimeMs = null; } length = in.readInt(); if (length == Uid.NUM_PROCESS_STATE) { + detachIfNotNull(u.mProcStateScreenOffTimeMs); u.mProcStateScreenOffTimeMs = new LongSamplingCounterArray[length]; for (int procState = 0; procState < length; ++procState) { u.mProcStateScreenOffTimeMs[procState] @@ -14033,20 +14092,25 @@ public class BatteryStatsImpl extends BatteryStats { in, mOnBatteryScreenOffTimeBase); } } else { + detachIfNotNull(u.mProcStateScreenOffTimeMs); u.mProcStateScreenOffTimeMs = null; } if (in.readInt() != 0) { + detachIfNotNull(u.mMobileRadioApWakeupCount); u.mMobileRadioApWakeupCount = new LongSamplingCounter(mOnBatteryTimeBase); u.mMobileRadioApWakeupCount.readSummaryFromParcelLocked(in); } else { + detachIfNotNull(u.mMobileRadioApWakeupCount); u.mMobileRadioApWakeupCount = null; } if (in.readInt() != 0) { + detachIfNotNull(u.mWifiRadioApWakeupCount); u.mWifiRadioApWakeupCount = new LongSamplingCounter(mOnBatteryTimeBase); u.mWifiRadioApWakeupCount.readSummaryFromParcelLocked(in); } else { + detachIfNotNull(u.mWifiRadioApWakeupCount); u.mWifiRadioApWakeupCount = null; } @@ -14082,6 +14146,7 @@ public class BatteryStatsImpl extends BatteryStats { u.mJobsDeferredEventCount.readSummaryFromParcelLocked(in); u.mJobsDeferredCount.readSummaryFromParcelLocked(in); u.mJobsFreshnessTimeMs.readSummaryFromParcelLocked(in); + detachIfNotNull(u.mJobsFreshnessBuckets); for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) { if (in.readInt() != 0) { u.mJobsFreshnessBuckets[i] = new Counter(u.mBsi.mOnBatteryTimeBase); @@ -14123,6 +14188,7 @@ public class BatteryStatsImpl extends BatteryStats { for (int ip = 0; ip < NP; ip++) { String pkgName = in.readString(); Uid.Pkg p = u.getPackageStatsLocked(pkgName); + p.detach(); final int NWA = in.readInt(); if (NWA > 10000) { throw new ParcelFormatException("File corrupt: too many wakeup alarms " + NWA); |