Loading core/java/android/os/BatteryStats.java +4 −2 Original line number Original line Diff line number Diff line Loading @@ -4017,8 +4017,10 @@ public abstract class BatteryStats implements Parcelable { if (userCpuTimeUs > 0 || systemCpuTimeUs > 0) { if (userCpuTimeUs > 0 || systemCpuTimeUs > 0) { sb.setLength(0); sb.setLength(0); sb.append(prefix); sb.append(prefix); sb.append(" Total cpu time: "); sb.append(" Total cpu time: u="); formatTimeMs(sb, (userCpuTimeUs + systemCpuTimeUs) / 1000); formatTimeMs(sb, userCpuTimeUs / 1000); sb.append("s="); formatTimeMs(sb, systemCpuTimeUs / 1000); pw.println(sb.toString()); pw.println(sb.toString()); } } Loading core/java/com/android/internal/os/BatteryStatsImpl.java +209 −127 Original line number Original line Diff line number Diff line Loading @@ -96,6 +96,7 @@ public final class BatteryStatsImpl extends BatteryStats { private static final String TAG = "BatteryStatsImpl"; private static final String TAG = "BatteryStatsImpl"; private static final boolean DEBUG = false; private static final boolean DEBUG = false; private static final boolean DEBUG_ENERGY = false; private static final boolean DEBUG_ENERGY = false; public static final boolean DEBUG_ENERGY_CPU = DEBUG_ENERGY || false; private static final boolean DEBUG_HISTORY = false; private static final boolean DEBUG_HISTORY = false; private static final boolean USE_OLD_HISTORY = false; // for debugging. private static final boolean USE_OLD_HISTORY = false; // for debugging. Loading Loading @@ -151,6 +152,9 @@ public final class BatteryStatsImpl extends BatteryStats { BatteryCallback cb = mCallback; BatteryCallback cb = mCallback; switch (msg.what) { switch (msg.what) { case MSG_UPDATE_WAKELOCKS: case MSG_UPDATE_WAKELOCKS: synchronized (BatteryStatsImpl.this) { updateCpuTimeLocked(); } if (cb != null) { if (cb != null) { cb.batteryNeedsCpuUpdate(); cb.batteryNeedsCpuUpdate(); } } Loading Loading @@ -2503,12 +2507,11 @@ public final class BatteryStatsImpl extends BatteryStats { boolean unpluggedScreenOff = unplugged && screenOff; boolean unpluggedScreenOff = unplugged && screenOff; if (unpluggedScreenOff != mOnBatteryScreenOffTimeBase.isRunning()) { if (unpluggedScreenOff != mOnBatteryScreenOffTimeBase.isRunning()) { updateKernelWakelocksLocked(); updateKernelWakelocksLocked(); requestWakelockCpuUpdate(); if (DEBUG_ENERGY_CPU) { if (!unpluggedScreenOff) { Slog.d(TAG, "Updating cpu time because screen is now " + // We are switching to no longer tracking wake locks, but we want (unpluggedScreenOff ? "off" : "on")); // the next CPU update we receive to take them in to account. mDistributeWakelockCpu = true; } } updateCpuTimeLocked(); mOnBatteryScreenOffTimeBase.setRunning(unpluggedScreenOff, uptime, realtime); mOnBatteryScreenOffTimeBase.setRunning(unpluggedScreenOff, uptime, realtime); } } } } Loading Loading @@ -2772,10 +2775,14 @@ public final class BatteryStatsImpl extends BatteryStats { mWakeLockNesting++; mWakeLockNesting++; } } if (uid >= 0) { if (uid >= 0) { //if (uid == 0) { if (mOnBatteryScreenOffTimeBase.isRunning()) { // Slog.wtf(TAG, "Acquiring wake lock from root: " + name); // We only update the cpu time when a wake lock is acquired if the screen is off. //} // If the screen is on, we don't distribute the power amongst partial wakelocks. if (DEBUG_ENERGY_CPU) { Slog.d(TAG, "Updating cpu time because of +wake_lock"); } requestWakelockCpuUpdate(); requestWakelockCpuUpdate(); } getUidStatsLocked(uid).noteStartWakeLocked(pid, name, type, elapsedRealtime); getUidStatsLocked(uid).noteStartWakeLocked(pid, name, type, elapsedRealtime); } } } } Loading Loading @@ -2805,7 +2812,12 @@ public final class BatteryStatsImpl extends BatteryStats { } } } } if (uid >= 0) { if (uid >= 0) { if (mOnBatteryScreenOffTimeBase.isRunning()) { if (DEBUG_ENERGY_CPU) { Slog.d(TAG, "Updating cpu time because of -wake_lock"); } requestWakelockCpuUpdate(); requestWakelockCpuUpdate(); } getUidStatsLocked(uid).noteStopWakeLocked(pid, name, type, elapsedRealtime); getUidStatsLocked(uid).noteStopWakeLocked(pid, name, type, elapsedRealtime); } } } } Loading Loading @@ -2874,46 +2886,14 @@ public final class BatteryStatsImpl extends BatteryStats { addHistoryRecordLocked(elapsedRealtime, uptime); addHistoryRecordLocked(elapsedRealtime, uptime); } } public int startAddingCpuLocked() { public boolean startAddingCpuLocked() { mHandler.removeMessages(MSG_UPDATE_WAKELOCKS); mHandler.removeMessages(MSG_UPDATE_WAKELOCKS); return mOnBatteryInternal; if (!mOnBatteryInternal) { return -1; } final int N = mPartialTimers.size(); if (N == 0) { mLastPartialTimers.clear(); mDistributeWakelockCpu = false; return 0; } if (!mOnBatteryScreenOffTimeBase.isRunning() && !mDistributeWakelockCpu) { return 0; } mDistributeWakelockCpu = false; // How many timers should consume CPU? Only want to include ones // that have already been in the list. for (int i=0; i<N; i++) { StopwatchTimer st = mPartialTimers.get(i); if (st.mInList) { Uid uid = st.mUid; // We don't include the system UID, because it so often // holds wake locks at one request or another of an app. if (uid != null && uid.mUid != Process.SYSTEM_UID) { return 50; } } } return 0; } } public void finishAddingCpuLocked(int perc, int remainUTime, int remainSTtime, public void finishAddingCpuLocked(int totalUTime, int totalSTime, int statUserTime, int totalUTime, int totalSTime, int statUserTime, int statSystemTime, int statSystemTime, int statIOWaitTime, int statIrqTime, int statIOWaitTime, int statIrqTime, int statSoftIrqTime, int statIdleTime) { int statSoftIrqTime, int statIdleTime) { if (DEBUG) Slog.d(TAG, "Adding cpu: tuser=" + totalUTime + " tsys=" + totalSTime if (DEBUG) Slog.d(TAG, "Adding cpu: tuser=" + totalUTime + " tsys=" + totalSTime + " user=" + statUserTime + " sys=" + statSystemTime + " user=" + statUserTime + " sys=" + statSystemTime + " io=" + statIOWaitTime + " irq=" + statIrqTime + " io=" + statIOWaitTime + " irq=" + statIrqTime Loading @@ -2926,70 +2906,6 @@ public final class BatteryStatsImpl extends BatteryStats { mCurStepStatIrqTime += statIrqTime; mCurStepStatIrqTime += statIrqTime; mCurStepStatSoftIrqTime += statSoftIrqTime; mCurStepStatSoftIrqTime += statSoftIrqTime; mCurStepStatIdleTime += statIdleTime; mCurStepStatIdleTime += statIdleTime; final int N = mPartialTimers.size(); if (perc != 0) { int num = 0; for (int i=0; i<N; i++) { StopwatchTimer st = mPartialTimers.get(i); if (st.mInList) { Uid uid = st.mUid; // We don't include the system UID, because it so often // holds wake locks at one request or another of an app. if (uid != null && uid.mUid != Process.SYSTEM_UID) { num++; } } } if (num != 0) { for (int i=0; i<N; i++) { StopwatchTimer st = mPartialTimers.get(i); if (st.mInList) { Uid uid = st.mUid; if (uid != null && uid.mUid != Process.SYSTEM_UID) { int myUTime = remainUTime/num; int mySTime = remainSTtime/num; remainUTime -= myUTime; remainSTtime -= mySTime; num--; Uid.Proc proc = uid.getProcessStatsLocked("*wakelock*"); proc.addCpuTimeLocked(myUTime, mySTime); } } } } // Just in case, collect any lost CPU time. if (remainUTime != 0 || remainSTtime != 0) { Uid uid = getUidStatsLocked(Process.SYSTEM_UID); if (uid != null) { Uid.Proc proc = uid.getProcessStatsLocked("*lost*"); proc.addCpuTimeLocked(remainUTime, remainSTtime); } } } final int NL = mLastPartialTimers.size(); boolean diff = N != NL; for (int i=0; i<NL && !diff; i++) { diff |= mPartialTimers.get(i) != mLastPartialTimers.get(i); } if (!diff) { for (int i=0; i<NL; i++) { mPartialTimers.get(i).mInList = true; } return; } for (int i=0; i<NL; i++) { mLastPartialTimers.get(i).mInList = false; } mLastPartialTimers.clear(); for (int i=0; i<N; i++) { StopwatchTimer st = mPartialTimers.get(i); st.mInList = true; mLastPartialTimers.add(st); } } } public void noteProcessDiedLocked(int uid, int pid) { public void noteProcessDiedLocked(int uid, int pid) { Loading Loading @@ -7959,20 +7875,101 @@ public final class BatteryStatsImpl extends BatteryStats { } } } } // We use an anonymous class to access these variables, // so they can't live on the stack or they'd have to be // final MutableLong objects (more allocations). // Used in updateCpuTimeLocked(). long mTempTotalCpuUserTimeUs; long mTempTotalCpuSystemTimeUs; /** /** * Read and distribute CPU usage across apps. * Read and distribute CPU usage across apps. If their are partial wakelocks being held * and we are on battery with screen off, we give more of the cpu time to those apps holding * wakelocks. If the screen is on, we just assign the actual cpu time an app used. */ */ public void updateCpuTimeLocked(boolean firstTime) { public void updateCpuTimeLocked() { if (DEBUG_ENERGY_CPU) { Slog.d(TAG, "!Cpu updating!"); } // Holding a wakelock costs more than just using the cpu. // Currently, we assign only half the cpu time to an app that is running but // not holding a wakelock. The apps holding wakelocks get the rest of the blame. // If no app is holding a wakelock, then the distribution is normal. final int wakelockWeight = 50; // Read the time spent at various cpu frequencies. final int cpuSpeedSteps = getCpuSpeedSteps(); final int cpuSpeedSteps = getCpuSpeedSteps(); final long[] cpuSpeeds = mKernelCpuSpeedReader.readDelta(); final long[] cpuSpeeds = mKernelCpuSpeedReader.readDelta(); KernelUidCpuTimeReader.Callback callback = null; if (mOnBatteryInternal && !firstTime) { int numWakelocks = 0; callback = new KernelUidCpuTimeReader.Callback() { // Calculate how many wakelocks we have to distribute amongst. The system is excluded. // Only distribute cpu power to wakelocks if the screen is off and we're on battery. final int numPartialTimers = mPartialTimers.size(); if (mOnBatteryScreenOffTimeBase.isRunning()) { for (int i = 0; i < numPartialTimers; i++) { final StopwatchTimer timer = mPartialTimers.get(i); if (timer.mInList && timer.mUid != null && timer.mUid.mUid != Process.SYSTEM_UID) { // Since the collection and blaming of wakelocks can be scheduled to run after // some delay, the mPartialTimers list may have new entries. We can't blame // the newly added timer for past cpu time, so we only consider timers that // were present for one round of collection. Once a timer has gone through // a round of collection, its mInList field is set to true. numWakelocks++; } } } final int numWakelocksF = numWakelocks; mTempTotalCpuUserTimeUs = 0; mTempTotalCpuSystemTimeUs = 0; // Read the CPU data for each UID. This will internally generate a snapshot so next time // we read, we get a delta. If we are to distribute the cpu time, then do so. Otherwise // we just ignore the data. final long startTimeMs = SystemClock.elapsedRealtime(); mKernelUidCpuTimeReader.readDelta(!mOnBatteryInternal ? null : new KernelUidCpuTimeReader.Callback() { @Override @Override public void onUidCpuTime(int uid, long userTimeUs, long systemTimeUs) { public void onUidCpuTime(int uid, long userTimeUs, long systemTimeUs) { final Uid u = getUidStatsLocked(mapUid(uid)); final Uid u = getUidStatsLocked(mapUid(uid)); // Accumulate the total system and user time. mTempTotalCpuUserTimeUs += userTimeUs; mTempTotalCpuSystemTimeUs += systemTimeUs; StringBuilder sb = null; if (DEBUG_ENERGY_CPU) { sb = new StringBuilder(); sb.append(" got time for uid=").append(u.mUid).append(": u="); TimeUtils.formatDuration(userTimeUs / 1000, sb); sb.append(" s="); TimeUtils.formatDuration(systemTimeUs / 1000, sb); sb.append("\n"); } if (numWakelocksF > 0) { // We have wakelocks being held, so only give a portion of the // time to the process. The rest will be distributed among wakelock // holders. userTimeUs = (userTimeUs * wakelockWeight) / 100; systemTimeUs = (systemTimeUs * wakelockWeight) / 100; } if (sb != null) { sb.append(" adding to uid=").append(u.mUid).append(": u="); TimeUtils.formatDuration(userTimeUs / 1000, sb); sb.append(" s="); TimeUtils.formatDuration(systemTimeUs / 1000, sb); Slog.d(TAG, sb.toString()); } u.mUserCpuTime.addCountLocked(userTimeUs); u.mUserCpuTime.addCountLocked(userTimeUs); u.mSystemCpuTime.addCountLocked(systemTimeUs); u.mSystemCpuTime.addCountLocked(systemTimeUs); // Add the cpu speeds to this UID. These are used as a ratio // for computing the power this UID used. for (int i = 0; i < cpuSpeedSteps; i++) { for (int i = 0; i < cpuSpeedSteps; i++) { if (u.mSpeedBins[i] == null) { if (u.mSpeedBins[i] == null) { u.mSpeedBins[i] = new LongSamplingCounter(mOnBatteryTimeBase); u.mSpeedBins[i] = new LongSamplingCounter(mOnBatteryTimeBase); Loading @@ -7980,9 +7977,94 @@ public final class BatteryStatsImpl extends BatteryStats { u.mSpeedBins[i].addCountLocked(cpuSpeeds[i]); u.mSpeedBins[i].addCountLocked(cpuSpeeds[i]); } } } } }; }); if (DEBUG_ENERGY_CPU) { Slog.d(TAG, "Reading cpu stats took " + (SystemClock.elapsedRealtime() - startTimeMs) + " ms"); } if (mOnBatteryInternal && numWakelocks > 0) { // Distribute a portion of the total cpu time to wakelock holders. mTempTotalCpuUserTimeUs = (mTempTotalCpuUserTimeUs * (100 - wakelockWeight)) / 100; mTempTotalCpuSystemTimeUs = (mTempTotalCpuSystemTimeUs * (100 - wakelockWeight)) / 100; for (int i = 0; i < numPartialTimers; i++) { final StopwatchTimer timer = mPartialTimers.get(i); // The system does not share any blame, as it is usually holding the wakelock // on behalf of an app. if (timer.mInList && timer.mUid != null && timer.mUid.mUid != Process.SYSTEM_UID) { int userTimeUs = (int) (mTempTotalCpuUserTimeUs / numWakelocks); int systemTimeUs = (int) (mTempTotalCpuSystemTimeUs / numWakelocks); if (DEBUG_ENERGY_CPU) { StringBuilder sb = new StringBuilder(); sb.append(" Distributing wakelock uid=").append(timer.mUid.mUid) .append(": u="); TimeUtils.formatDuration(userTimeUs / 1000, sb); sb.append(" s="); TimeUtils.formatDuration(systemTimeUs / 1000, sb); Slog.d(TAG, sb.toString()); } timer.mUid.mUserCpuTime.addCountLocked(userTimeUs); timer.mUid.mSystemCpuTime.addCountLocked(systemTimeUs); final Uid.Proc proc = timer.mUid.getProcessStatsLocked("*wakelock*"); proc.addCpuTimeLocked(userTimeUs, systemTimeUs); mTempTotalCpuUserTimeUs -= userTimeUs; mTempTotalCpuSystemTimeUs -= systemTimeUs; numWakelocks--; } } if (mTempTotalCpuUserTimeUs > 0 || mTempTotalCpuSystemTimeUs > 0) { // Anything left over is given to the system. if (DEBUG_ENERGY_CPU) { StringBuilder sb = new StringBuilder(); sb.append(" Distributing lost time to system: u="); TimeUtils.formatDuration(mTempTotalCpuUserTimeUs / 1000, sb); sb.append(" s="); TimeUtils.formatDuration(mTempTotalCpuSystemTimeUs / 1000, sb); Slog.d(TAG, sb.toString()); } final Uid u = getUidStatsLocked(Process.SYSTEM_UID); u.mUserCpuTime.addCountLocked(mTempTotalCpuUserTimeUs); u.mSystemCpuTime.addCountLocked(mTempTotalCpuSystemTimeUs); final Uid.Proc proc = u.getProcessStatsLocked("*lost*"); proc.addCpuTimeLocked((int) mTempTotalCpuUserTimeUs, (int) mTempTotalCpuSystemTimeUs); } } // See if there is a difference in wakelocks between this collection and the last // collection. if (ArrayUtils.referenceEquals(mPartialTimers, mLastPartialTimers)) { // No difference, so each timer is now considered for the next collection. for (int i = 0; i < numPartialTimers; i++) { mPartialTimers.get(i).mInList = true; } } else { // The lists are different, meaning we added (or removed a timer) since the last // collection. final int numLastPartialTimers = mLastPartialTimers.size(); for (int i = 0; i < numLastPartialTimers; i++) { mLastPartialTimers.get(i).mInList = false; } mLastPartialTimers.clear(); // Mark the current timers as gone through a collection. for (int i = 0; i < numPartialTimers; i++) { final StopwatchTimer timer = mPartialTimers.get(i); timer.mInList = true; mLastPartialTimers.add(timer); } } } mKernelUidCpuTimeReader.readDelta(callback); } } boolean setChargingLocked(boolean charging) { boolean setChargingLocked(boolean charging) { Loading core/java/com/android/internal/os/KernelUidCpuTimeReader.java +31 −4 Original line number Original line Diff line number Diff line Loading @@ -16,9 +16,11 @@ package com.android.internal.os; package com.android.internal.os; import android.annotation.Nullable; import android.annotation.Nullable; import android.os.SystemClock; import android.text.TextUtils; import android.text.TextUtils; import android.util.Slog; import android.util.Slog; import android.util.SparseLongArray; import android.util.SparseLongArray; import android.util.TimeUtils; import java.io.BufferedReader; import java.io.BufferedReader; import java.io.FileReader; import java.io.FileReader; Loading Loading @@ -49,6 +51,7 @@ public class KernelUidCpuTimeReader { private SparseLongArray mLastUserTimeUs = new SparseLongArray(); private SparseLongArray mLastUserTimeUs = new SparseLongArray(); private SparseLongArray mLastSystemTimeUs = new SparseLongArray(); private SparseLongArray mLastSystemTimeUs = new SparseLongArray(); private long mLastTimeRead = 0; /** /** * Reads the proc file, calling into the callback with a delta of time for each UID. * Reads the proc file, calling into the callback with a delta of time for each UID. Loading @@ -57,6 +60,7 @@ public class KernelUidCpuTimeReader { * a fresh delta. * a fresh delta. */ */ public void readDelta(@Nullable Callback callback) { public void readDelta(@Nullable Callback callback) { long now = SystemClock.elapsedRealtime(); try (BufferedReader reader = new BufferedReader(new FileReader(sProcFile))) { try (BufferedReader reader = new BufferedReader(new FileReader(sProcFile))) { TextUtils.SimpleStringSplitter splitter = new TextUtils.SimpleStringSplitter(' '); TextUtils.SimpleStringSplitter splitter = new TextUtils.SimpleStringSplitter(' '); String line; String line; Loading @@ -75,10 +79,32 @@ public class KernelUidCpuTimeReader { userTimeDeltaUs -= mLastUserTimeUs.valueAt(index); userTimeDeltaUs -= mLastUserTimeUs.valueAt(index); systemTimeDeltaUs -= mLastSystemTimeUs.valueAt(index); systemTimeDeltaUs -= mLastSystemTimeUs.valueAt(index); if (userTimeDeltaUs < 0 || systemTimeDeltaUs < 0) { final long timeDiffMs = (now - mLastTimeRead) * 1000; // The UID must have been removed from accounting, then added back. if (userTimeDeltaUs < 0 || systemTimeDeltaUs < 0 || userTimeDeltaUs = userTimeUs; userTimeDeltaUs > timeDiffMs || systemTimeDeltaUs > timeDiffMs ) { systemTimeDeltaUs = systemTimeUs; StringBuilder sb = new StringBuilder("Malformed cpu data!\n"); sb.append("Time between reads: "); TimeUtils.formatDuration(timeDiffMs, sb); sb.append("ms\n"); sb.append("Previous times: u="); TimeUtils.formatDuration(mLastUserTimeUs.valueAt(index) / 1000, sb); sb.append("ms s="); TimeUtils.formatDuration(mLastSystemTimeUs.valueAt(index) / 1000, sb); sb.append("ms\n"); sb.append("Current times: u="); TimeUtils.formatDuration(userTimeUs / 1000, sb); sb.append("ms s="); TimeUtils.formatDuration(systemTimeUs / 1000, sb); sb.append("ms\n"); sb.append("Delta for UID=").append(uid).append(": u="); TimeUtils.formatDuration(userTimeDeltaUs / 1000, sb); sb.append("ms s="); TimeUtils.formatDuration(systemTimeDeltaUs / 1000, sb); sb.append("ms"); Slog.wtf(TAG, sb.toString()); userTimeDeltaUs = 0; systemTimeDeltaUs = 0; } } } } Loading @@ -92,6 +118,7 @@ public class KernelUidCpuTimeReader { } catch (IOException e) { } catch (IOException e) { Slog.e(TAG, "Failed to read uid_cputime", e); Slog.e(TAG, "Failed to read uid_cputime", e); } } mLastTimeRead = now; } } /** /** Loading core/java/com/android/internal/util/ArrayUtils.java +22 −0 Original line number Original line Diff line number Diff line Loading @@ -387,4 +387,26 @@ public class ArrayUtils { public static <T> boolean contains(ArrayList<T> cur, T val) { public static <T> boolean contains(ArrayList<T> cur, T val) { return (cur != null) ? cur.contains(val) : false; return (cur != null) ? cur.contains(val) : false; } } /** * Returns true if the two ArrayLists are equal with respect to the objects they contain. * The objects must be in the same order and be reference equal (== not .equals()). */ public static <T> boolean referenceEquals(ArrayList<T> a, ArrayList<T> b) { if (a == b) { return true; } final int sizeA = a.size(); final int sizeB = b.size(); if (a == null || b == null || sizeA != sizeB) { return false; } boolean diff = false; for (int i = 0; i < sizeA && !diff; i++) { diff |= a.get(i) != b.get(i); } return !diff; } } } services/core/java/com/android/server/am/ActivityManagerService.java +5 −15 Original line number Original line Diff line number Diff line Loading @@ -2488,10 +2488,7 @@ public final class ActivityManagerService extends ActivityManagerNative synchronized(bstats) { synchronized(bstats) { synchronized(mPidsSelfLocked) { synchronized(mPidsSelfLocked) { if (haveNewCpuStats) { if (haveNewCpuStats) { final int perc = bstats.startAddingCpuLocked(); if (bstats.startAddingCpuLocked()) { if (perc >= 0) { int remainUTime = 0; int remainSTime = 0; int totalUTime = 0; int totalUTime = 0; int totalSTime = 0; int totalSTime = 0; final int N = mProcessCpuTracker.countStats(); final int N = mProcessCpuTracker.countStats(); Loading @@ -2501,10 +2498,6 @@ public final class ActivityManagerService extends ActivityManagerNative continue; continue; } } ProcessRecord pr = mPidsSelfLocked.get(st.pid); ProcessRecord pr = mPidsSelfLocked.get(st.pid); int otherUTime = (st.rel_utime*perc)/100; int otherSTime = (st.rel_stime*perc)/100; remainUTime += otherUTime; remainSTime += otherSTime; totalUTime += st.rel_utime; totalUTime += st.rel_utime; totalSTime += st.rel_stime; totalSTime += st.rel_stime; if (pr != null) { if (pr != null) { Loading @@ -2513,8 +2506,7 @@ public final class ActivityManagerService extends ActivityManagerNative pr.curProcBatteryStats = ps = bstats.getProcessStatsLocked( pr.curProcBatteryStats = ps = bstats.getProcessStatsLocked( pr.info.uid, pr.processName); pr.info.uid, pr.processName); } } ps.addCpuTimeLocked(st.rel_utime - otherUTime, ps.addCpuTimeLocked(st.rel_utime, st.rel_stime); st.rel_stime - otherSTime); pr.curCpuTime += st.rel_utime + st.rel_stime; pr.curCpuTime += st.rel_utime + st.rel_stime; } else { } else { BatteryStatsImpl.Uid.Proc ps = st.batteryStats; BatteryStatsImpl.Uid.Proc ps = st.batteryStats; Loading @@ -2522,8 +2514,7 @@ public final class ActivityManagerService extends ActivityManagerNative st.batteryStats = ps = bstats.getProcessStatsLocked( st.batteryStats = ps = bstats.getProcessStatsLocked( bstats.mapUid(st.uid), st.name); bstats.mapUid(st.uid), st.name); } } ps.addCpuTimeLocked(st.rel_utime - otherUTime, ps.addCpuTimeLocked(st.rel_utime, st.rel_stime); st.rel_stime - otherSTime); } } } } final int userTime = mProcessCpuTracker.getLastUserTime(); final int userTime = mProcessCpuTracker.getLastUserTime(); Loading @@ -2532,9 +2523,8 @@ public final class ActivityManagerService extends ActivityManagerNative final int irqTime = mProcessCpuTracker.getLastIrqTime(); final int irqTime = mProcessCpuTracker.getLastIrqTime(); final int softIrqTime = mProcessCpuTracker.getLastSoftIrqTime(); final int softIrqTime = mProcessCpuTracker.getLastSoftIrqTime(); final int idleTime = mProcessCpuTracker.getLastIdleTime(); final int idleTime = mProcessCpuTracker.getLastIdleTime(); bstats.finishAddingCpuLocked(perc, remainUTime, bstats.finishAddingCpuLocked(totalUTime, totalSTime, userTime, remainSTime, totalUTime, totalSTime, userTime, systemTime, systemTime, iowaitTime, irqTime, softIrqTime, idleTime); iowaitTime, irqTime, softIrqTime, idleTime); } } } } } } Loading Loading
core/java/android/os/BatteryStats.java +4 −2 Original line number Original line Diff line number Diff line Loading @@ -4017,8 +4017,10 @@ public abstract class BatteryStats implements Parcelable { if (userCpuTimeUs > 0 || systemCpuTimeUs > 0) { if (userCpuTimeUs > 0 || systemCpuTimeUs > 0) { sb.setLength(0); sb.setLength(0); sb.append(prefix); sb.append(prefix); sb.append(" Total cpu time: "); sb.append(" Total cpu time: u="); formatTimeMs(sb, (userCpuTimeUs + systemCpuTimeUs) / 1000); formatTimeMs(sb, userCpuTimeUs / 1000); sb.append("s="); formatTimeMs(sb, systemCpuTimeUs / 1000); pw.println(sb.toString()); pw.println(sb.toString()); } } Loading
core/java/com/android/internal/os/BatteryStatsImpl.java +209 −127 Original line number Original line Diff line number Diff line Loading @@ -96,6 +96,7 @@ public final class BatteryStatsImpl extends BatteryStats { private static final String TAG = "BatteryStatsImpl"; private static final String TAG = "BatteryStatsImpl"; private static final boolean DEBUG = false; private static final boolean DEBUG = false; private static final boolean DEBUG_ENERGY = false; private static final boolean DEBUG_ENERGY = false; public static final boolean DEBUG_ENERGY_CPU = DEBUG_ENERGY || false; private static final boolean DEBUG_HISTORY = false; private static final boolean DEBUG_HISTORY = false; private static final boolean USE_OLD_HISTORY = false; // for debugging. private static final boolean USE_OLD_HISTORY = false; // for debugging. Loading Loading @@ -151,6 +152,9 @@ public final class BatteryStatsImpl extends BatteryStats { BatteryCallback cb = mCallback; BatteryCallback cb = mCallback; switch (msg.what) { switch (msg.what) { case MSG_UPDATE_WAKELOCKS: case MSG_UPDATE_WAKELOCKS: synchronized (BatteryStatsImpl.this) { updateCpuTimeLocked(); } if (cb != null) { if (cb != null) { cb.batteryNeedsCpuUpdate(); cb.batteryNeedsCpuUpdate(); } } Loading Loading @@ -2503,12 +2507,11 @@ public final class BatteryStatsImpl extends BatteryStats { boolean unpluggedScreenOff = unplugged && screenOff; boolean unpluggedScreenOff = unplugged && screenOff; if (unpluggedScreenOff != mOnBatteryScreenOffTimeBase.isRunning()) { if (unpluggedScreenOff != mOnBatteryScreenOffTimeBase.isRunning()) { updateKernelWakelocksLocked(); updateKernelWakelocksLocked(); requestWakelockCpuUpdate(); if (DEBUG_ENERGY_CPU) { if (!unpluggedScreenOff) { Slog.d(TAG, "Updating cpu time because screen is now " + // We are switching to no longer tracking wake locks, but we want (unpluggedScreenOff ? "off" : "on")); // the next CPU update we receive to take them in to account. mDistributeWakelockCpu = true; } } updateCpuTimeLocked(); mOnBatteryScreenOffTimeBase.setRunning(unpluggedScreenOff, uptime, realtime); mOnBatteryScreenOffTimeBase.setRunning(unpluggedScreenOff, uptime, realtime); } } } } Loading Loading @@ -2772,10 +2775,14 @@ public final class BatteryStatsImpl extends BatteryStats { mWakeLockNesting++; mWakeLockNesting++; } } if (uid >= 0) { if (uid >= 0) { //if (uid == 0) { if (mOnBatteryScreenOffTimeBase.isRunning()) { // Slog.wtf(TAG, "Acquiring wake lock from root: " + name); // We only update the cpu time when a wake lock is acquired if the screen is off. //} // If the screen is on, we don't distribute the power amongst partial wakelocks. if (DEBUG_ENERGY_CPU) { Slog.d(TAG, "Updating cpu time because of +wake_lock"); } requestWakelockCpuUpdate(); requestWakelockCpuUpdate(); } getUidStatsLocked(uid).noteStartWakeLocked(pid, name, type, elapsedRealtime); getUidStatsLocked(uid).noteStartWakeLocked(pid, name, type, elapsedRealtime); } } } } Loading Loading @@ -2805,7 +2812,12 @@ public final class BatteryStatsImpl extends BatteryStats { } } } } if (uid >= 0) { if (uid >= 0) { if (mOnBatteryScreenOffTimeBase.isRunning()) { if (DEBUG_ENERGY_CPU) { Slog.d(TAG, "Updating cpu time because of -wake_lock"); } requestWakelockCpuUpdate(); requestWakelockCpuUpdate(); } getUidStatsLocked(uid).noteStopWakeLocked(pid, name, type, elapsedRealtime); getUidStatsLocked(uid).noteStopWakeLocked(pid, name, type, elapsedRealtime); } } } } Loading Loading @@ -2874,46 +2886,14 @@ public final class BatteryStatsImpl extends BatteryStats { addHistoryRecordLocked(elapsedRealtime, uptime); addHistoryRecordLocked(elapsedRealtime, uptime); } } public int startAddingCpuLocked() { public boolean startAddingCpuLocked() { mHandler.removeMessages(MSG_UPDATE_WAKELOCKS); mHandler.removeMessages(MSG_UPDATE_WAKELOCKS); return mOnBatteryInternal; if (!mOnBatteryInternal) { return -1; } final int N = mPartialTimers.size(); if (N == 0) { mLastPartialTimers.clear(); mDistributeWakelockCpu = false; return 0; } if (!mOnBatteryScreenOffTimeBase.isRunning() && !mDistributeWakelockCpu) { return 0; } mDistributeWakelockCpu = false; // How many timers should consume CPU? Only want to include ones // that have already been in the list. for (int i=0; i<N; i++) { StopwatchTimer st = mPartialTimers.get(i); if (st.mInList) { Uid uid = st.mUid; // We don't include the system UID, because it so often // holds wake locks at one request or another of an app. if (uid != null && uid.mUid != Process.SYSTEM_UID) { return 50; } } } return 0; } } public void finishAddingCpuLocked(int perc, int remainUTime, int remainSTtime, public void finishAddingCpuLocked(int totalUTime, int totalSTime, int statUserTime, int totalUTime, int totalSTime, int statUserTime, int statSystemTime, int statSystemTime, int statIOWaitTime, int statIrqTime, int statIOWaitTime, int statIrqTime, int statSoftIrqTime, int statIdleTime) { int statSoftIrqTime, int statIdleTime) { if (DEBUG) Slog.d(TAG, "Adding cpu: tuser=" + totalUTime + " tsys=" + totalSTime if (DEBUG) Slog.d(TAG, "Adding cpu: tuser=" + totalUTime + " tsys=" + totalSTime + " user=" + statUserTime + " sys=" + statSystemTime + " user=" + statUserTime + " sys=" + statSystemTime + " io=" + statIOWaitTime + " irq=" + statIrqTime + " io=" + statIOWaitTime + " irq=" + statIrqTime Loading @@ -2926,70 +2906,6 @@ public final class BatteryStatsImpl extends BatteryStats { mCurStepStatIrqTime += statIrqTime; mCurStepStatIrqTime += statIrqTime; mCurStepStatSoftIrqTime += statSoftIrqTime; mCurStepStatSoftIrqTime += statSoftIrqTime; mCurStepStatIdleTime += statIdleTime; mCurStepStatIdleTime += statIdleTime; final int N = mPartialTimers.size(); if (perc != 0) { int num = 0; for (int i=0; i<N; i++) { StopwatchTimer st = mPartialTimers.get(i); if (st.mInList) { Uid uid = st.mUid; // We don't include the system UID, because it so often // holds wake locks at one request or another of an app. if (uid != null && uid.mUid != Process.SYSTEM_UID) { num++; } } } if (num != 0) { for (int i=0; i<N; i++) { StopwatchTimer st = mPartialTimers.get(i); if (st.mInList) { Uid uid = st.mUid; if (uid != null && uid.mUid != Process.SYSTEM_UID) { int myUTime = remainUTime/num; int mySTime = remainSTtime/num; remainUTime -= myUTime; remainSTtime -= mySTime; num--; Uid.Proc proc = uid.getProcessStatsLocked("*wakelock*"); proc.addCpuTimeLocked(myUTime, mySTime); } } } } // Just in case, collect any lost CPU time. if (remainUTime != 0 || remainSTtime != 0) { Uid uid = getUidStatsLocked(Process.SYSTEM_UID); if (uid != null) { Uid.Proc proc = uid.getProcessStatsLocked("*lost*"); proc.addCpuTimeLocked(remainUTime, remainSTtime); } } } final int NL = mLastPartialTimers.size(); boolean diff = N != NL; for (int i=0; i<NL && !diff; i++) { diff |= mPartialTimers.get(i) != mLastPartialTimers.get(i); } if (!diff) { for (int i=0; i<NL; i++) { mPartialTimers.get(i).mInList = true; } return; } for (int i=0; i<NL; i++) { mLastPartialTimers.get(i).mInList = false; } mLastPartialTimers.clear(); for (int i=0; i<N; i++) { StopwatchTimer st = mPartialTimers.get(i); st.mInList = true; mLastPartialTimers.add(st); } } } public void noteProcessDiedLocked(int uid, int pid) { public void noteProcessDiedLocked(int uid, int pid) { Loading Loading @@ -7959,20 +7875,101 @@ public final class BatteryStatsImpl extends BatteryStats { } } } } // We use an anonymous class to access these variables, // so they can't live on the stack or they'd have to be // final MutableLong objects (more allocations). // Used in updateCpuTimeLocked(). long mTempTotalCpuUserTimeUs; long mTempTotalCpuSystemTimeUs; /** /** * Read and distribute CPU usage across apps. * Read and distribute CPU usage across apps. If their are partial wakelocks being held * and we are on battery with screen off, we give more of the cpu time to those apps holding * wakelocks. If the screen is on, we just assign the actual cpu time an app used. */ */ public void updateCpuTimeLocked(boolean firstTime) { public void updateCpuTimeLocked() { if (DEBUG_ENERGY_CPU) { Slog.d(TAG, "!Cpu updating!"); } // Holding a wakelock costs more than just using the cpu. // Currently, we assign only half the cpu time to an app that is running but // not holding a wakelock. The apps holding wakelocks get the rest of the blame. // If no app is holding a wakelock, then the distribution is normal. final int wakelockWeight = 50; // Read the time spent at various cpu frequencies. final int cpuSpeedSteps = getCpuSpeedSteps(); final int cpuSpeedSteps = getCpuSpeedSteps(); final long[] cpuSpeeds = mKernelCpuSpeedReader.readDelta(); final long[] cpuSpeeds = mKernelCpuSpeedReader.readDelta(); KernelUidCpuTimeReader.Callback callback = null; if (mOnBatteryInternal && !firstTime) { int numWakelocks = 0; callback = new KernelUidCpuTimeReader.Callback() { // Calculate how many wakelocks we have to distribute amongst. The system is excluded. // Only distribute cpu power to wakelocks if the screen is off and we're on battery. final int numPartialTimers = mPartialTimers.size(); if (mOnBatteryScreenOffTimeBase.isRunning()) { for (int i = 0; i < numPartialTimers; i++) { final StopwatchTimer timer = mPartialTimers.get(i); if (timer.mInList && timer.mUid != null && timer.mUid.mUid != Process.SYSTEM_UID) { // Since the collection and blaming of wakelocks can be scheduled to run after // some delay, the mPartialTimers list may have new entries. We can't blame // the newly added timer for past cpu time, so we only consider timers that // were present for one round of collection. Once a timer has gone through // a round of collection, its mInList field is set to true. numWakelocks++; } } } final int numWakelocksF = numWakelocks; mTempTotalCpuUserTimeUs = 0; mTempTotalCpuSystemTimeUs = 0; // Read the CPU data for each UID. This will internally generate a snapshot so next time // we read, we get a delta. If we are to distribute the cpu time, then do so. Otherwise // we just ignore the data. final long startTimeMs = SystemClock.elapsedRealtime(); mKernelUidCpuTimeReader.readDelta(!mOnBatteryInternal ? null : new KernelUidCpuTimeReader.Callback() { @Override @Override public void onUidCpuTime(int uid, long userTimeUs, long systemTimeUs) { public void onUidCpuTime(int uid, long userTimeUs, long systemTimeUs) { final Uid u = getUidStatsLocked(mapUid(uid)); final Uid u = getUidStatsLocked(mapUid(uid)); // Accumulate the total system and user time. mTempTotalCpuUserTimeUs += userTimeUs; mTempTotalCpuSystemTimeUs += systemTimeUs; StringBuilder sb = null; if (DEBUG_ENERGY_CPU) { sb = new StringBuilder(); sb.append(" got time for uid=").append(u.mUid).append(": u="); TimeUtils.formatDuration(userTimeUs / 1000, sb); sb.append(" s="); TimeUtils.formatDuration(systemTimeUs / 1000, sb); sb.append("\n"); } if (numWakelocksF > 0) { // We have wakelocks being held, so only give a portion of the // time to the process. The rest will be distributed among wakelock // holders. userTimeUs = (userTimeUs * wakelockWeight) / 100; systemTimeUs = (systemTimeUs * wakelockWeight) / 100; } if (sb != null) { sb.append(" adding to uid=").append(u.mUid).append(": u="); TimeUtils.formatDuration(userTimeUs / 1000, sb); sb.append(" s="); TimeUtils.formatDuration(systemTimeUs / 1000, sb); Slog.d(TAG, sb.toString()); } u.mUserCpuTime.addCountLocked(userTimeUs); u.mUserCpuTime.addCountLocked(userTimeUs); u.mSystemCpuTime.addCountLocked(systemTimeUs); u.mSystemCpuTime.addCountLocked(systemTimeUs); // Add the cpu speeds to this UID. These are used as a ratio // for computing the power this UID used. for (int i = 0; i < cpuSpeedSteps; i++) { for (int i = 0; i < cpuSpeedSteps; i++) { if (u.mSpeedBins[i] == null) { if (u.mSpeedBins[i] == null) { u.mSpeedBins[i] = new LongSamplingCounter(mOnBatteryTimeBase); u.mSpeedBins[i] = new LongSamplingCounter(mOnBatteryTimeBase); Loading @@ -7980,9 +7977,94 @@ public final class BatteryStatsImpl extends BatteryStats { u.mSpeedBins[i].addCountLocked(cpuSpeeds[i]); u.mSpeedBins[i].addCountLocked(cpuSpeeds[i]); } } } } }; }); if (DEBUG_ENERGY_CPU) { Slog.d(TAG, "Reading cpu stats took " + (SystemClock.elapsedRealtime() - startTimeMs) + " ms"); } if (mOnBatteryInternal && numWakelocks > 0) { // Distribute a portion of the total cpu time to wakelock holders. mTempTotalCpuUserTimeUs = (mTempTotalCpuUserTimeUs * (100 - wakelockWeight)) / 100; mTempTotalCpuSystemTimeUs = (mTempTotalCpuSystemTimeUs * (100 - wakelockWeight)) / 100; for (int i = 0; i < numPartialTimers; i++) { final StopwatchTimer timer = mPartialTimers.get(i); // The system does not share any blame, as it is usually holding the wakelock // on behalf of an app. if (timer.mInList && timer.mUid != null && timer.mUid.mUid != Process.SYSTEM_UID) { int userTimeUs = (int) (mTempTotalCpuUserTimeUs / numWakelocks); int systemTimeUs = (int) (mTempTotalCpuSystemTimeUs / numWakelocks); if (DEBUG_ENERGY_CPU) { StringBuilder sb = new StringBuilder(); sb.append(" Distributing wakelock uid=").append(timer.mUid.mUid) .append(": u="); TimeUtils.formatDuration(userTimeUs / 1000, sb); sb.append(" s="); TimeUtils.formatDuration(systemTimeUs / 1000, sb); Slog.d(TAG, sb.toString()); } timer.mUid.mUserCpuTime.addCountLocked(userTimeUs); timer.mUid.mSystemCpuTime.addCountLocked(systemTimeUs); final Uid.Proc proc = timer.mUid.getProcessStatsLocked("*wakelock*"); proc.addCpuTimeLocked(userTimeUs, systemTimeUs); mTempTotalCpuUserTimeUs -= userTimeUs; mTempTotalCpuSystemTimeUs -= systemTimeUs; numWakelocks--; } } if (mTempTotalCpuUserTimeUs > 0 || mTempTotalCpuSystemTimeUs > 0) { // Anything left over is given to the system. if (DEBUG_ENERGY_CPU) { StringBuilder sb = new StringBuilder(); sb.append(" Distributing lost time to system: u="); TimeUtils.formatDuration(mTempTotalCpuUserTimeUs / 1000, sb); sb.append(" s="); TimeUtils.formatDuration(mTempTotalCpuSystemTimeUs / 1000, sb); Slog.d(TAG, sb.toString()); } final Uid u = getUidStatsLocked(Process.SYSTEM_UID); u.mUserCpuTime.addCountLocked(mTempTotalCpuUserTimeUs); u.mSystemCpuTime.addCountLocked(mTempTotalCpuSystemTimeUs); final Uid.Proc proc = u.getProcessStatsLocked("*lost*"); proc.addCpuTimeLocked((int) mTempTotalCpuUserTimeUs, (int) mTempTotalCpuSystemTimeUs); } } // See if there is a difference in wakelocks between this collection and the last // collection. if (ArrayUtils.referenceEquals(mPartialTimers, mLastPartialTimers)) { // No difference, so each timer is now considered for the next collection. for (int i = 0; i < numPartialTimers; i++) { mPartialTimers.get(i).mInList = true; } } else { // The lists are different, meaning we added (or removed a timer) since the last // collection. final int numLastPartialTimers = mLastPartialTimers.size(); for (int i = 0; i < numLastPartialTimers; i++) { mLastPartialTimers.get(i).mInList = false; } mLastPartialTimers.clear(); // Mark the current timers as gone through a collection. for (int i = 0; i < numPartialTimers; i++) { final StopwatchTimer timer = mPartialTimers.get(i); timer.mInList = true; mLastPartialTimers.add(timer); } } } mKernelUidCpuTimeReader.readDelta(callback); } } boolean setChargingLocked(boolean charging) { boolean setChargingLocked(boolean charging) { Loading
core/java/com/android/internal/os/KernelUidCpuTimeReader.java +31 −4 Original line number Original line Diff line number Diff line Loading @@ -16,9 +16,11 @@ package com.android.internal.os; package com.android.internal.os; import android.annotation.Nullable; import android.annotation.Nullable; import android.os.SystemClock; import android.text.TextUtils; import android.text.TextUtils; import android.util.Slog; import android.util.Slog; import android.util.SparseLongArray; import android.util.SparseLongArray; import android.util.TimeUtils; import java.io.BufferedReader; import java.io.BufferedReader; import java.io.FileReader; import java.io.FileReader; Loading Loading @@ -49,6 +51,7 @@ public class KernelUidCpuTimeReader { private SparseLongArray mLastUserTimeUs = new SparseLongArray(); private SparseLongArray mLastUserTimeUs = new SparseLongArray(); private SparseLongArray mLastSystemTimeUs = new SparseLongArray(); private SparseLongArray mLastSystemTimeUs = new SparseLongArray(); private long mLastTimeRead = 0; /** /** * Reads the proc file, calling into the callback with a delta of time for each UID. * Reads the proc file, calling into the callback with a delta of time for each UID. Loading @@ -57,6 +60,7 @@ public class KernelUidCpuTimeReader { * a fresh delta. * a fresh delta. */ */ public void readDelta(@Nullable Callback callback) { public void readDelta(@Nullable Callback callback) { long now = SystemClock.elapsedRealtime(); try (BufferedReader reader = new BufferedReader(new FileReader(sProcFile))) { try (BufferedReader reader = new BufferedReader(new FileReader(sProcFile))) { TextUtils.SimpleStringSplitter splitter = new TextUtils.SimpleStringSplitter(' '); TextUtils.SimpleStringSplitter splitter = new TextUtils.SimpleStringSplitter(' '); String line; String line; Loading @@ -75,10 +79,32 @@ public class KernelUidCpuTimeReader { userTimeDeltaUs -= mLastUserTimeUs.valueAt(index); userTimeDeltaUs -= mLastUserTimeUs.valueAt(index); systemTimeDeltaUs -= mLastSystemTimeUs.valueAt(index); systemTimeDeltaUs -= mLastSystemTimeUs.valueAt(index); if (userTimeDeltaUs < 0 || systemTimeDeltaUs < 0) { final long timeDiffMs = (now - mLastTimeRead) * 1000; // The UID must have been removed from accounting, then added back. if (userTimeDeltaUs < 0 || systemTimeDeltaUs < 0 || userTimeDeltaUs = userTimeUs; userTimeDeltaUs > timeDiffMs || systemTimeDeltaUs > timeDiffMs ) { systemTimeDeltaUs = systemTimeUs; StringBuilder sb = new StringBuilder("Malformed cpu data!\n"); sb.append("Time between reads: "); TimeUtils.formatDuration(timeDiffMs, sb); sb.append("ms\n"); sb.append("Previous times: u="); TimeUtils.formatDuration(mLastUserTimeUs.valueAt(index) / 1000, sb); sb.append("ms s="); TimeUtils.formatDuration(mLastSystemTimeUs.valueAt(index) / 1000, sb); sb.append("ms\n"); sb.append("Current times: u="); TimeUtils.formatDuration(userTimeUs / 1000, sb); sb.append("ms s="); TimeUtils.formatDuration(systemTimeUs / 1000, sb); sb.append("ms\n"); sb.append("Delta for UID=").append(uid).append(": u="); TimeUtils.formatDuration(userTimeDeltaUs / 1000, sb); sb.append("ms s="); TimeUtils.formatDuration(systemTimeDeltaUs / 1000, sb); sb.append("ms"); Slog.wtf(TAG, sb.toString()); userTimeDeltaUs = 0; systemTimeDeltaUs = 0; } } } } Loading @@ -92,6 +118,7 @@ public class KernelUidCpuTimeReader { } catch (IOException e) { } catch (IOException e) { Slog.e(TAG, "Failed to read uid_cputime", e); Slog.e(TAG, "Failed to read uid_cputime", e); } } mLastTimeRead = now; } } /** /** Loading
core/java/com/android/internal/util/ArrayUtils.java +22 −0 Original line number Original line Diff line number Diff line Loading @@ -387,4 +387,26 @@ public class ArrayUtils { public static <T> boolean contains(ArrayList<T> cur, T val) { public static <T> boolean contains(ArrayList<T> cur, T val) { return (cur != null) ? cur.contains(val) : false; return (cur != null) ? cur.contains(val) : false; } } /** * Returns true if the two ArrayLists are equal with respect to the objects they contain. * The objects must be in the same order and be reference equal (== not .equals()). */ public static <T> boolean referenceEquals(ArrayList<T> a, ArrayList<T> b) { if (a == b) { return true; } final int sizeA = a.size(); final int sizeB = b.size(); if (a == null || b == null || sizeA != sizeB) { return false; } boolean diff = false; for (int i = 0; i < sizeA && !diff; i++) { diff |= a.get(i) != b.get(i); } return !diff; } } }
services/core/java/com/android/server/am/ActivityManagerService.java +5 −15 Original line number Original line Diff line number Diff line Loading @@ -2488,10 +2488,7 @@ public final class ActivityManagerService extends ActivityManagerNative synchronized(bstats) { synchronized(bstats) { synchronized(mPidsSelfLocked) { synchronized(mPidsSelfLocked) { if (haveNewCpuStats) { if (haveNewCpuStats) { final int perc = bstats.startAddingCpuLocked(); if (bstats.startAddingCpuLocked()) { if (perc >= 0) { int remainUTime = 0; int remainSTime = 0; int totalUTime = 0; int totalUTime = 0; int totalSTime = 0; int totalSTime = 0; final int N = mProcessCpuTracker.countStats(); final int N = mProcessCpuTracker.countStats(); Loading @@ -2501,10 +2498,6 @@ public final class ActivityManagerService extends ActivityManagerNative continue; continue; } } ProcessRecord pr = mPidsSelfLocked.get(st.pid); ProcessRecord pr = mPidsSelfLocked.get(st.pid); int otherUTime = (st.rel_utime*perc)/100; int otherSTime = (st.rel_stime*perc)/100; remainUTime += otherUTime; remainSTime += otherSTime; totalUTime += st.rel_utime; totalUTime += st.rel_utime; totalSTime += st.rel_stime; totalSTime += st.rel_stime; if (pr != null) { if (pr != null) { Loading @@ -2513,8 +2506,7 @@ public final class ActivityManagerService extends ActivityManagerNative pr.curProcBatteryStats = ps = bstats.getProcessStatsLocked( pr.curProcBatteryStats = ps = bstats.getProcessStatsLocked( pr.info.uid, pr.processName); pr.info.uid, pr.processName); } } ps.addCpuTimeLocked(st.rel_utime - otherUTime, ps.addCpuTimeLocked(st.rel_utime, st.rel_stime); st.rel_stime - otherSTime); pr.curCpuTime += st.rel_utime + st.rel_stime; pr.curCpuTime += st.rel_utime + st.rel_stime; } else { } else { BatteryStatsImpl.Uid.Proc ps = st.batteryStats; BatteryStatsImpl.Uid.Proc ps = st.batteryStats; Loading @@ -2522,8 +2514,7 @@ public final class ActivityManagerService extends ActivityManagerNative st.batteryStats = ps = bstats.getProcessStatsLocked( st.batteryStats = ps = bstats.getProcessStatsLocked( bstats.mapUid(st.uid), st.name); bstats.mapUid(st.uid), st.name); } } ps.addCpuTimeLocked(st.rel_utime - otherUTime, ps.addCpuTimeLocked(st.rel_utime, st.rel_stime); st.rel_stime - otherSTime); } } } } final int userTime = mProcessCpuTracker.getLastUserTime(); final int userTime = mProcessCpuTracker.getLastUserTime(); Loading @@ -2532,9 +2523,8 @@ public final class ActivityManagerService extends ActivityManagerNative final int irqTime = mProcessCpuTracker.getLastIrqTime(); final int irqTime = mProcessCpuTracker.getLastIrqTime(); final int softIrqTime = mProcessCpuTracker.getLastSoftIrqTime(); final int softIrqTime = mProcessCpuTracker.getLastSoftIrqTime(); final int idleTime = mProcessCpuTracker.getLastIdleTime(); final int idleTime = mProcessCpuTracker.getLastIdleTime(); bstats.finishAddingCpuLocked(perc, remainUTime, bstats.finishAddingCpuLocked(totalUTime, totalSTime, userTime, remainSTime, totalUTime, totalSTime, userTime, systemTime, systemTime, iowaitTime, irqTime, softIrqTime, idleTime); iowaitTime, irqTime, softIrqTime, idleTime); } } } } } } Loading