Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3c797794 authored by Suprabh Shukla's avatar Suprabh Shukla Committed by Automerger Merge Worker
Browse files

Merge "Add uid proc state to cpu wakeup stats" into udc-dev am: 313c1696

parents d8b3008b 313c1696
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -654,6 +654,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub
        synchronized (mLock) {
            final long elapsedRealtime = SystemClock.elapsedRealtime();
            mHandler.post(() -> {
                mCpuWakeupStats.onUidRemoved(uid);
                synchronized (mStats) {
                    mStats.removeUidStatsLocked(uid, elapsedRealtime);
                }
@@ -764,6 +765,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub
            final long elapsedRealtime = SystemClock.elapsedRealtime();
            final long uptime = SystemClock.uptimeMillis();
            mHandler.post(() -> {
                mCpuWakeupStats.noteUidProcessState(uid, state);
                synchronized (mStats) {
                    mStats.noteUidProcessStateLocked(uid, state, elapsedRealtime, uptime);
                }
+115 −59
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import static android.os.BatteryStatsInternal.CPU_WAKEUP_SUBSYSTEM_ALARM;
import static android.os.BatteryStatsInternal.CPU_WAKEUP_SUBSYSTEM_UNKNOWN;
import static android.os.BatteryStatsInternal.CPU_WAKEUP_SUBSYSTEM_WIFI;

import android.app.ActivityManager;
import android.content.Context;
import android.os.Handler;
import android.os.HandlerExecutor;
@@ -27,11 +28,10 @@ import android.os.Trace;
import android.os.UserHandle;
import android.provider.DeviceConfig;
import android.util.IndentingPrintWriter;
import android.util.IntArray;
import android.util.LongSparseArray;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
import android.util.SparseIntArray;
import android.util.SparseLongArray;
import android.util.TimeSparseArray;
import android.util.TimeUtils;
@@ -59,7 +59,7 @@ public class CpuWakeupStats {
    private static final String TRACE_TRACK_WAKEUP_ATTRIBUTION = "wakeup_attribution";
    @VisibleForTesting
    static final long WAKEUP_REASON_HALF_WINDOW_MS = 500;
    private static final long WAKEUP_WRITE_DELAY_MS = TimeUnit.MINUTES.toMillis(2);
    private static final long WAKEUP_WRITE_DELAY_MS = TimeUnit.SECONDS.toMillis(30);

    private final Handler mHandler;
    private final IrqDeviceMap mIrqDeviceMap;
@@ -69,10 +69,15 @@ public class CpuWakeupStats {

    @VisibleForTesting
    final TimeSparseArray<Wakeup> mWakeupEvents = new TimeSparseArray<>();

    /* Maps timestamp -> {subsystem  -> {uid -> procState}} */
    @VisibleForTesting
    final TimeSparseArray<SparseArray<SparseBooleanArray>> mWakeupAttribution =
    final TimeSparseArray<SparseArray<SparseIntArray>> mWakeupAttribution =
            new TimeSparseArray<>();

    final SparseIntArray mUidProcStates = new SparseIntArray();
    private final SparseIntArray mReusableUidProcStates = new SparseIntArray(4);

    public CpuWakeupStats(Context context, int mapRes, Handler handler) {
        mIrqDeviceMap = IrqDeviceMap.getInstance(context, mapRes);
        mHandler = handler;
@@ -102,13 +107,14 @@ public class CpuWakeupStats {
                    FrameworkStatsLog.KERNEL_WAKEUP_ATTRIBUTED__TYPE__TYPE_UNKNOWN,
                    FrameworkStatsLog.KERNEL_WAKEUP_ATTRIBUTED__REASON__UNKNOWN,
                    null,
                    wakeupToLog.mElapsedMillis);
                    wakeupToLog.mElapsedMillis,
                    null);
            Trace.instantForTrack(Trace.TRACE_TAG_POWER, TRACE_TRACK_WAKEUP_ATTRIBUTION,
                    wakeupToLog.mElapsedMillis + " --");
            return;
        }

        final SparseArray<SparseBooleanArray> wakeupAttribution = mWakeupAttribution.get(
        final SparseArray<SparseIntArray> wakeupAttribution = mWakeupAttribution.get(
                wakeupToLog.mElapsedMillis);
        if (wakeupAttribution == null) {
            // This is not expected but can theoretically happen in extreme situations, e.g. if we
@@ -121,24 +127,28 @@ public class CpuWakeupStats {

        for (int i = 0; i < wakeupAttribution.size(); i++) {
            final int subsystem = wakeupAttribution.keyAt(i);
            final SparseBooleanArray uidMap = wakeupAttribution.valueAt(i);
            final SparseIntArray uidProcStates = wakeupAttribution.valueAt(i);
            final int[] uids;
            if (uidMap == null || uidMap.size() == 0) {
                uids = new int[0];
            final int[] procStatesProto;

            if (uidProcStates == null || uidProcStates.size() == 0) {
                uids = procStatesProto = new int[0];
            } else {
                final IntArray tmp = new IntArray(uidMap.size());
                for (int j = 0; j < uidMap.size(); j++) {
                    if (uidMap.valueAt(j)) {
                        tmp.add(uidMap.keyAt(j));
                    }
                final int numUids = uidProcStates.size();
                uids = new int[numUids];
                procStatesProto = new int[numUids];
                for (int j = 0; j < numUids; j++) {
                    uids[j] = uidProcStates.keyAt(j);
                    procStatesProto[j] = ActivityManager.processStateAmToProto(
                            uidProcStates.valueAt(j));
                }
                uids = tmp.toArray();
            }
            FrameworkStatsLog.write(FrameworkStatsLog.KERNEL_WAKEUP_ATTRIBUTED,
                    FrameworkStatsLog.KERNEL_WAKEUP_ATTRIBUTED__TYPE__TYPE_IRQ,
                    subsystemToStatsReason(subsystem),
                    uids,
                    wakeupToLog.mElapsedMillis);
                    wakeupToLog.mElapsedMillis,
                    procStatesProto);

            if (Trace.isTagEnabled(Trace.TRACE_TAG_POWER)) {
                if (i == 0) {
@@ -154,6 +164,20 @@ public class CpuWakeupStats {
                traceEventBuilder.toString().trim());
    }

    /**
     * Clean up data for a uid that is being removed.
     */
    public synchronized void onUidRemoved(int uid) {
        mUidProcStates.delete(uid);
    }

    /**
     * Notes a procstate change for the given uid to maintain the mapping internally.
     */
    public synchronized void noteUidProcessState(int uid, int state) {
        mUidProcStates.put(uid, state);
    }

    /** Notes a wakeup reason as reported by SuspendControlService to battery stats. */
    public synchronized void noteWakeupTimeAndReason(long elapsedRealtime, long uptime,
            String rawReason) {
@@ -184,8 +208,17 @@ public class CpuWakeupStats {

    /** Notes a waking activity that could have potentially woken up the CPU. */
    public synchronized void noteWakingActivity(int subsystem, long elapsedRealtime, int... uids) {
        if (!attemptAttributionWith(subsystem, elapsedRealtime, uids)) {
            mRecentWakingActivity.recordActivity(subsystem, elapsedRealtime, uids);
        if (uids == null) {
            return;
        }
        mReusableUidProcStates.clear();
        for (int i = 0; i < uids.length; i++) {
            mReusableUidProcStates.put(uids[i],
                    mUidProcStates.get(uids[i], ActivityManager.PROCESS_STATE_UNKNOWN));
        }
        if (!attemptAttributionWith(subsystem, elapsedRealtime, mReusableUidProcStates)) {
            mRecentWakingActivity.recordActivity(subsystem, elapsedRealtime,
                    mReusableUidProcStates);
        }
    }

@@ -196,7 +229,7 @@ public class CpuWakeupStats {
            return;
        }

        SparseArray<SparseBooleanArray> attribution = mWakeupAttribution.get(wakeup.mElapsedMillis);
        SparseArray<SparseIntArray> attribution = mWakeupAttribution.get(wakeup.mElapsedMillis);
        if (attribution == null) {
            attribution = new SparseArray<>();
            mWakeupAttribution.put(wakeup.mElapsedMillis, attribution);
@@ -210,14 +243,14 @@ public class CpuWakeupStats {
            final long startTime = wakeup.mElapsedMillis - WAKEUP_REASON_HALF_WINDOW_MS;
            final long endTime = wakeup.mElapsedMillis + WAKEUP_REASON_HALF_WINDOW_MS;

            final SparseBooleanArray uidsToBlame = mRecentWakingActivity.removeBetween(subsystem,
            final SparseIntArray uidsToBlame = mRecentWakingActivity.removeBetween(subsystem,
                    startTime, endTime);
            attribution.put(subsystem, uidsToBlame);
        }
    }

    private synchronized boolean attemptAttributionWith(int subsystem, long activityElapsed,
            int... uids) {
            SparseIntArray uidProcStates) {
        final int startIdx = mWakeupEvents.closestIndexOnOrAfter(
                activityElapsed - WAKEUP_REASON_HALF_WINDOW_MS);
        final int endIdx = mWakeupEvents.closestIndexOnOrBefore(
@@ -233,19 +266,19 @@ public class CpuWakeupStats {
            if (subsystems.get(subsystem)) {
                // We don't expect more than one wakeup to be found within such a short window, so
                // just attribute this one and exit
                SparseArray<SparseBooleanArray> attribution = mWakeupAttribution.get(
                SparseArray<SparseIntArray> attribution = mWakeupAttribution.get(
                        wakeup.mElapsedMillis);
                if (attribution == null) {
                    attribution = new SparseArray<>();
                    mWakeupAttribution.put(wakeup.mElapsedMillis, attribution);
                }
                SparseBooleanArray uidsToBlame = attribution.get(subsystem);
                SparseIntArray uidsToBlame = attribution.get(subsystem);
                if (uidsToBlame == null) {
                    uidsToBlame = new SparseBooleanArray(uids.length);
                    attribution.put(subsystem, uidsToBlame);
                    attribution.put(subsystem, uidProcStates.clone());
                } else {
                    for (int i = 0; i < uidProcStates.size(); i++) {
                        uidsToBlame.put(uidProcStates.keyAt(i), uidProcStates.valueAt(i));
                    }
                for (final int uid : uids) {
                    uidsToBlame.put(uid, true);
                }
                return true;
            }
@@ -267,6 +300,19 @@ public class CpuWakeupStats {
        mRecentWakingActivity.dump(pw, nowElapsed);
        pw.println();

        pw.println("Current proc-state map (" + mUidProcStates.size() + "):");
        pw.increaseIndent();
        for (int i = 0; i < mUidProcStates.size(); i++) {
            if (i > 0) {
                pw.print(", ");
            }
            UserHandle.formatUid(pw, mUidProcStates.keyAt(i));
            pw.print(":" + ActivityManager.procStateToString(mUidProcStates.valueAt(i)));
        }
        pw.println();
        pw.decreaseIndent();
        pw.println();

        final SparseLongArray attributionStats = new SparseLongArray();
        pw.println("Wakeup events:");
        pw.increaseIndent();
@@ -278,7 +324,7 @@ public class CpuWakeupStats {
            final Wakeup wakeup = mWakeupEvents.valueAt(i);
            pw.println(wakeup);
            pw.print("Attribution: ");
            final SparseArray<SparseBooleanArray> attribution = mWakeupAttribution.get(
            final SparseArray<SparseIntArray> attribution = mWakeupAttribution.get(
                    wakeup.mElapsedMillis);
            if (attribution == null) {
                pw.println("N/A");
@@ -292,15 +338,17 @@ public class CpuWakeupStats {
                    int attributed = IntPair.first(counters);
                    final int total = IntPair.second(counters) + 1;

                    pw.print("subsystem: " + subsystemToString(attribution.keyAt(subsystemIdx)));
                    pw.print(", uids: [");
                    final SparseBooleanArray uids = attribution.valueAt(subsystemIdx);
                    if (uids != null) {
                        for (int uidIdx = 0; uidIdx < uids.size(); uidIdx++) {
                    pw.print(subsystemToString(attribution.keyAt(subsystemIdx)));
                    pw.print(" [");
                    final SparseIntArray uidProcStates = attribution.valueAt(subsystemIdx);
                    if (uidProcStates != null) {
                        for (int uidIdx = 0; uidIdx < uidProcStates.size(); uidIdx++) {
                            if (uidIdx > 0) {
                                pw.print(", ");
                            }
                            UserHandle.formatUid(pw, uids.keyAt(uidIdx));
                            UserHandle.formatUid(pw, uidProcStates.keyAt(uidIdx));
                            pw.print(" " + ActivityManager.procStateToString(
                                    uidProcStates.valueAt(uidIdx)));
                        }
                        attributed++;
                    }
@@ -330,28 +378,38 @@ public class CpuWakeupStats {
        pw.println();
    }

    /**
     * This class stores recent unattributed activity history per subsystem.
     * The activity is stored as a mapping of subsystem to timestamp to uid to procstate.
     */
    private static final class WakingActivityHistory {
        private static final long WAKING_ACTIVITY_RETENTION_MS = TimeUnit.MINUTES.toMillis(10);

        private SparseArray<TimeSparseArray<SparseBooleanArray>> mWakingActivity =
        private SparseArray<TimeSparseArray<SparseIntArray>> mWakingActivity =
                new SparseArray<>();

        void recordActivity(int subsystem, long elapsedRealtime, int... uids) {
            if (uids == null) {
        void recordActivity(int subsystem, long elapsedRealtime, SparseIntArray uidProcStates) {
            if (uidProcStates == null) {
                return;
            }
            TimeSparseArray<SparseBooleanArray> wakingActivity = mWakingActivity.get(subsystem);
            TimeSparseArray<SparseIntArray> wakingActivity = mWakingActivity.get(subsystem);
            if (wakingActivity == null) {
                wakingActivity = new TimeSparseArray<>();
                mWakingActivity.put(subsystem, wakingActivity);
            }
            SparseBooleanArray uidsToBlame = wakingActivity.get(elapsedRealtime);
            final SparseIntArray uidsToBlame = wakingActivity.get(elapsedRealtime);
            if (uidsToBlame == null) {
                uidsToBlame = new SparseBooleanArray(uids.length);
                wakingActivity.put(elapsedRealtime, uidsToBlame);
                wakingActivity.put(elapsedRealtime, uidProcStates.clone());
            } else {
                for (int i = 0; i < uidProcStates.size(); i++) {
                    final int uid = uidProcStates.keyAt(i);
                    // Just in case there are duplicate uids reported with the same timestamp,
                    // keep the processState which was reported first.
                    if (uidsToBlame.indexOfKey(uid) < 0) {
                        uidsToBlame.put(uid, uidProcStates.valueAt(i));
                    }
            for (int i = 0; i < uids.length; i++) {
                uidsToBlame.put(uids[i], true);
                }
                wakingActivity.put(elapsedRealtime, uidsToBlame);
            }
            // Limit activity history per subsystem to the last WAKING_ACTIVITY_RETENTION_MS.
            // Note that the last activity is always present, even if it occurred before
@@ -365,7 +423,7 @@ public class CpuWakeupStats {

        void clearAllBefore(long elapsedRealtime) {
            for (int subsystemIdx = mWakingActivity.size() - 1; subsystemIdx >= 0; subsystemIdx--) {
                final TimeSparseArray<SparseBooleanArray> activityPerSubsystem =
                final TimeSparseArray<SparseIntArray> activityPerSubsystem =
                        mWakingActivity.valueAt(subsystemIdx);
                final int endIdx = activityPerSubsystem.closestIndexOnOrBefore(elapsedRealtime);
                for (int removeIdx = endIdx; removeIdx >= 0; removeIdx--) {
@@ -377,20 +435,20 @@ public class CpuWakeupStats {
            }
        }

        SparseBooleanArray removeBetween(int subsystem, long startElapsed, long endElapsed) {
            final SparseBooleanArray uidsToReturn = new SparseBooleanArray();
        SparseIntArray removeBetween(int subsystem, long startElapsed, long endElapsed) {
            final SparseIntArray uidsToReturn = new SparseIntArray();

            final TimeSparseArray<SparseBooleanArray> activityForSubsystem =
            final TimeSparseArray<SparseIntArray> activityForSubsystem =
                    mWakingActivity.get(subsystem);
            if (activityForSubsystem != null) {
                final int startIdx = activityForSubsystem.closestIndexOnOrAfter(startElapsed);
                final int endIdx = activityForSubsystem.closestIndexOnOrBefore(endElapsed);
                for (int i = endIdx; i >= startIdx; i--) {
                    final SparseBooleanArray uidsForTime = activityForSubsystem.valueAt(i);
                    final SparseIntArray uidsForTime = activityForSubsystem.valueAt(i);
                    for (int j = 0; j < uidsForTime.size(); j++) {
                        if (uidsForTime.valueAt(j)) {
                            uidsToReturn.put(uidsForTime.keyAt(j), true);
                        }
                        // In case the same uid appears in different uidsForTime maps, there is no
                        // good way to choose one processState, so just arbitrarily pick any.
                        uidsToReturn.put(uidsForTime.keyAt(j), uidsForTime.valueAt(j));
                    }
                }
                // More efficient to remove in a separate loop as it avoids repeatedly calling gc().
@@ -409,25 +467,23 @@ public class CpuWakeupStats {
            pw.increaseIndent();
            for (int i = 0; i < mWakingActivity.size(); i++) {
                pw.println("Subsystem " + subsystemToString(mWakingActivity.keyAt(i)) + ":");
                final LongSparseArray<SparseBooleanArray> wakingActivity =
                        mWakingActivity.valueAt(i);
                final TimeSparseArray<SparseIntArray> wakingActivity = mWakingActivity.valueAt(i);
                if (wakingActivity == null) {
                    continue;
                }
                pw.increaseIndent();
                for (int j = wakingActivity.size() - 1; j >= 0; j--) {
                    TimeUtils.formatDuration(wakingActivity.keyAt(j), nowElapsed, pw);
                    final SparseBooleanArray uidsToBlame = wakingActivity.valueAt(j);
                    final SparseIntArray uidsToBlame = wakingActivity.valueAt(j);
                    if (uidsToBlame == null) {
                        pw.println();
                        continue;
                    }
                    pw.print(": ");
                    for (int k = 0; k < uidsToBlame.size(); k++) {
                        if (uidsToBlame.valueAt(k)) {
                        UserHandle.formatUid(pw, uidsToBlame.keyAt(k));
                            pw.print(", ");
                        }
                        pw.print(" [" + ActivityManager.procStateToString(uidsToBlame.valueAt(k)));
                        pw.print("], ");
                    }
                    pw.println();
                }
+98 −27

File changed.

Preview size limit exceeded, changes collapsed.