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

Commit 4661d6aa authored by Rafal Slawik's avatar Rafal Slawik
Browse files

Read CPU usage for system server thread groups

Add a statsd puller to record CPU usage of system server threads: all
and binder.

Bug: 173227907
Test: cmd stats pull-source 10098
Test: atest CpuStatsTests
Change-Id: I0d5c6e1e8d772bae6efdcbe62767932cc2fefe02
parent 8ce6b9fb
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -104,6 +104,7 @@ import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidActiveTimeRead
import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidClusterTimeReader;
import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidFreqTimeReader;
import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidUserSysTimeReader;
import com.android.internal.os.SystemServerCpuThreadReader.SystemServiceCpuThreadTimes;
import com.android.internal.power.MeasuredEnergyStats;
import com.android.internal.power.MeasuredEnergyStats.StandardEnergyBucket;
import com.android.internal.util.ArrayUtils;
@@ -10842,6 +10843,10 @@ public class BatteryStatsImpl extends BatteryStats {
        mSystemServerCpuThreadReader.startTrackingThreadCpuTime();
    }
    public SystemServiceCpuThreadTimes getSystemServiceCpuThreadTimes() {
        return mSystemServerCpuThreadReader.readAbsolute();
    }
    public void setCallback(BatteryCallback cb) {
        mCallback = cb;
    }
+20 −0
Original line number Diff line number Diff line
@@ -110,4 +110,24 @@ public class SystemServerCpuThreadReader {

        return mDeltaCpuThreadTimes;
    }

    /** Returns CPU times, per thread group, since tracking started. */
    @Nullable
    public SystemServiceCpuThreadTimes readAbsolute() {
        final int numCpuFrequencies = mKernelCpuThreadReader.getCpuFrequencyCount();
        final KernelSingleProcessCpuThreadReader.ProcessCpuUsage processCpuUsage =
                mKernelCpuThreadReader.getProcessCpuUsage();
        if (processCpuUsage == null) {
            return null;
        }
        final SystemServiceCpuThreadTimes result = new SystemServiceCpuThreadTimes();
        result.threadCpuTimesUs = new long[numCpuFrequencies];
        result.binderThreadCpuTimesUs = new long[numCpuFrequencies];
        for (int i = 0; i < numCpuFrequencies; ++i) {
            result.threadCpuTimesUs[i] = processCpuUsage.threadCpuTimesMillis[i] * 1_000;
            result.binderThreadCpuTimesUs[i] =
                    processCpuUsage.selectedThreadCpuTimesMillis[i] * 1_000;
        }
        return result;
    }
}
+4 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package android.os;

import com.android.internal.os.BinderCallsStats;
import com.android.internal.os.SystemServerCpuThreadReader.SystemServiceCpuThreadTimes;

import java.util.Collection;

@@ -37,6 +38,9 @@ public abstract class BatteryStatsInternal {
     */
    public abstract String[] getMobileIfaces();

    /** Returns CPU times for system server thread groups. */
    public abstract SystemServiceCpuThreadTimes getSystemServiceCpuThreadTimes();

    /**
     * Inform battery stats how many deferred jobs existed when the app got launched and how
     * long ago was the last job execution for the app.
+6 −0
Original line number Diff line number Diff line
@@ -72,6 +72,7 @@ import com.android.internal.os.BinderCallsStats;
import com.android.internal.os.PowerProfile;
import com.android.internal.os.RailStats;
import com.android.internal.os.RpmStats;
import com.android.internal.os.SystemServerCpuThreadReader.SystemServiceCpuThreadTimes;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.FrameworkStatsLog;
import com.android.internal.util.ParseUtils;
@@ -356,6 +357,11 @@ public final class BatteryStatsService extends IBatteryStats.Stub
            return mStats.getMobileIfaces().clone();
        }

        @Override
        public SystemServiceCpuThreadTimes getSystemServiceCpuThreadTimes() {
            return mStats.getSystemServiceCpuThreadTimes();
        }

        @Override
        public void noteJobsDeferred(int uid, int numDeferred, long sinceLast) {
            if (DBG) Slog.d(TAG, "Jobs deferred " + uid + ": " + numDeferred + " " + sinceLast);
+81 −0
Original line number Diff line number Diff line
@@ -90,6 +90,7 @@ import android.net.NetworkTemplate;
import android.net.wifi.WifiManager;
import android.os.AsyncTask;
import android.os.BatteryStats;
import android.os.BatteryStatsInternal;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
@@ -152,6 +153,7 @@ import com.android.internal.os.LooperStats;
import com.android.internal.os.PowerProfile;
import com.android.internal.os.ProcessCpuTracker;
import com.android.internal.os.StoragedUidIoStatsReader;
import com.android.internal.os.SystemServerCpuThreadReader.SystemServiceCpuThreadTimes;
import com.android.internal.util.CollectionUtils;
import com.android.internal.util.FrameworkStatsLog;
import com.android.role.RoleManagerLocal;
@@ -457,6 +459,8 @@ public class StatsPullAtomService extends SystemService {
                        synchronized (mCpuTimePerUidFreqLock) {
                            return pullCpuTimePerUidFreqLocked(atomTag, data);
                        }
                    case FrameworkStatsLog.CPU_CYCLES_PER_THREAD_GROUP_CLUSTER:
                        return pullCpuCyclesPerThreadGroupCluster(atomTag, data);
                    case FrameworkStatsLog.CPU_ACTIVE_TIME:
                        synchronized (mCpuActiveTimeLock) {
                            return pullCpuActiveTimeLocked(atomTag, data);
@@ -781,6 +785,7 @@ public class StatsPullAtomService extends SystemService {
        registerCpuTimePerUid();
        registerCpuCyclesPerUidCluster();
        registerCpuTimePerUidFreq();
        registerCpuCyclesPerThreadGroupCluster();
        registerCpuActiveTime();
        registerCpuClusterTime();
        registerWifiActivityInfo();
@@ -1510,6 +1515,7 @@ public class StatsPullAtomService extends SystemService {
    }

    int pullCpuCyclesPerUidClusterLocked(int atomTag, List<StatsEvent> pulledData) {
        // TODO(b/179485697): Remove power profile dependency.
        PowerProfile powerProfile = new PowerProfile(mContext);
        // Frequency index to frequency mapping.
        long[] freqs = mCpuUidFreqTimeReader.readFreqs(powerProfile);
@@ -1653,6 +1659,81 @@ public class StatsPullAtomService extends SystemService {
        return StatsManager.PULL_SUCCESS;
    }

    private void registerCpuCyclesPerThreadGroupCluster() {
        // TODO(b/173227907): Register only when supported.
        int tagId = FrameworkStatsLog.CPU_CYCLES_PER_THREAD_GROUP_CLUSTER;
        PullAtomMetadata metadata = new PullAtomMetadata.Builder()
                .setAdditiveFields(new int[] {3, 4})
                .build();
        mStatsManager.setPullAtomCallback(
                tagId,
                metadata,
                DIRECT_EXECUTOR,
                mStatsCallbackImpl
        );
    }

    int pullCpuCyclesPerThreadGroupCluster(int atomTag, List<StatsEvent> pulledData) {
        // TODO(b/179485697): Remove power profile dependency.
        PowerProfile powerProfile = new PowerProfile(mContext);
        // Frequency index to frequency mapping.
        long[] freqs = mCpuUidFreqTimeReader.readFreqs(powerProfile);
        if (freqs == null) {
            return StatsManager.PULL_SKIP;
        }
        // Frequency index to cluster mapping.
        int[] freqClusters = new int[freqs.length];
        // Number of clusters.
        int clusters;

        // Initialize frequency mappings.
        {
            int cluster = 0;
            long lastFreq = -1;
            for (int freqIndex = 0; freqIndex < freqs.length; ++freqIndex) {
                long currFreq = freqs[freqIndex];
                if (currFreq <= lastFreq) {
                    cluster++;
                }
                freqClusters[freqIndex] = cluster;
                lastFreq = currFreq;
            }

            clusters = cluster + 1;
        }

        SystemServiceCpuThreadTimes times = LocalServices.getService(BatteryStatsInternal.class)
                .getSystemServiceCpuThreadTimes();
        if (times == null) {
            return StatsManager.PULL_SKIP;
        }

        addCpuCyclesPerThreadGroupClusterAtoms(atomTag, pulledData,
                FrameworkStatsLog.CPU_CYCLES_PER_THREAD_GROUP_CLUSTER__THREAD_GROUP__SYSTEM_SERVER,
                times.threadCpuTimesUs, clusters, freqs, freqClusters);
        addCpuCyclesPerThreadGroupClusterAtoms(atomTag, pulledData,
                FrameworkStatsLog.CPU_CYCLES_PER_THREAD_GROUP_CLUSTER__THREAD_GROUP__SYSTEM_SERVER_BINDER,
                times.binderThreadCpuTimesUs, clusters, freqs, freqClusters);

        return StatsManager.PULL_SUCCESS;
    }

    private static void addCpuCyclesPerThreadGroupClusterAtoms(
            int atomTag, List<StatsEvent> pulledData, int threadGroup, long[] cpuTimesUs,
            int clusters, long[] freqs, int[] freqClusters) {
        long[] aggregatedCycles = new long[clusters];
        long[] aggregatedTimesUs = new long[clusters];
        for (int i = 0; i < cpuTimesUs.length; ++i) {
            aggregatedCycles[freqClusters[i]] += freqs[i] * cpuTimesUs[i] / 1_000;
            aggregatedTimesUs[freqClusters[i]] += cpuTimesUs[i];
        }
        for (int cluster = 0; cluster < clusters; ++cluster) {
            pulledData.add(FrameworkStatsLog.buildStatsEvent(
                    atomTag, threadGroup, cluster, aggregatedCycles[cluster],
                    aggregatedTimesUs[cluster] / 1_000));
        }
    }

    private void registerCpuActiveTime() {
        // the throttling is 3sec, handled in
        // frameworks/base/core/java/com/android/internal/os/KernelCpuProcReader