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

Commit b34a6011 authored by Rafal Slawik's avatar Rafal Slawik
Browse files

Track surfaceflinger CPU usage

Use the same approach that is used to track system server thread group
CPU usage: KernelSingleProcessCpuThreadReader which uses the eBPF
time_in_state program to record CPU usage for selected pids and tids.

Test: cmd stats pull-source 10098
Test: atest CpuStatsTests
Bug: 181232205
Change-Id: I84d46409547f92e410fd3b4f8b8ccb823bcee98b
parent b7138470
Loading
Loading
Loading
Loading
+57 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.internal.os;

import android.annotation.Nullable;
import android.os.Process;

/**
 * Reads CPU usage statistics about a selected process identified by its cmdline.
 *
 * Handles finding the pid for the process and delegates CPU usage reading from the eBPF map to
 * KernelSingleProcessCpuThreadReader. Exactly one long-lived instance of the process is expected.
 * Otherwise, no statistics are returned.
 *
 * See also SystemServerCpuThreadReader.
 */
public final class SelectedProcessCpuThreadReader {
    private final String[] mCmdline;

    private int mPid;
    private KernelSingleProcessCpuThreadReader mKernelCpuThreadReader;

    public SelectedProcessCpuThreadReader(String cmdline) {
        mCmdline = new String[] { cmdline };
    }

    /** Returns CPU times, per thread group, since tracking started. */
    @Nullable
    public KernelSingleProcessCpuThreadReader.ProcessCpuUsage readAbsolute() {
        int[] pids = Process.getPidsForCommands(mCmdline);
        if (pids == null || pids.length != 1) {
            return null;
        }
        int pid = pids[0];
        if (mPid == pid) {
            return mKernelCpuThreadReader.getProcessCpuUsage();
        }
        mPid = pid;
        mKernelCpuThreadReader = KernelSingleProcessCpuThreadReader.create(mPid);
        mKernelCpuThreadReader.startTrackingThreadCpuTimes();
        return null;
    }
}
+19 −0
Original line number Diff line number Diff line
@@ -148,11 +148,13 @@ 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.KernelSingleProcessCpuThreadReader.ProcessCpuUsage;
import com.android.internal.os.KernelWakelockReader;
import com.android.internal.os.KernelWakelockStats;
import com.android.internal.os.LooperStats;
import com.android.internal.os.PowerProfile;
import com.android.internal.os.ProcessCpuTracker;
import com.android.internal.os.SelectedProcessCpuThreadReader;
import com.android.internal.os.StoragedUidIoStatsReader;
import com.android.internal.os.SystemServerCpuThreadReader.SystemServiceCpuThreadTimes;
import com.android.internal.util.CollectionUtils;
@@ -351,6 +353,8 @@ public class StatsPullAtomService extends SystemService {
    @GuardedBy("mDataBytesTransferLock")
    private final ArrayList<SubInfo> mHistoricalSubs = new ArrayList<>();

    private SelectedProcessCpuThreadReader mSurfaceFlingerProcessCpuThreadReader;

    // Puller locks
    private final Object mDataBytesTransferLock = new Object();
    private final Object mBluetoothBytesTransferLock = new Object();
@@ -753,6 +757,9 @@ public class StatsPullAtomService extends SystemService {
                }
            }
        }

        mSurfaceFlingerProcessCpuThreadReader =
                new SelectedProcessCpuThreadReader("/system/bin/surfaceflinger");
    }

    void registerEventListeners() {
@@ -1678,6 +1685,18 @@ public class StatsPullAtomService extends SystemService {
                FrameworkStatsLog.CPU_CYCLES_PER_THREAD_GROUP_CLUSTER__THREAD_GROUP__SYSTEM_SERVER_BINDER,
                times.binderThreadCpuTimesUs);

        ProcessCpuUsage surfaceFlingerTimes = mSurfaceFlingerProcessCpuThreadReader.readAbsolute();
        if (surfaceFlingerTimes != null && surfaceFlingerTimes.threadCpuTimesMillis != null) {
            long[] surfaceFlingerTimesUs =
                    new long[surfaceFlingerTimes.threadCpuTimesMillis.length];
            for (int i = 0; i < surfaceFlingerTimesUs.length; ++i) {
                surfaceFlingerTimesUs[i] = surfaceFlingerTimes.threadCpuTimesMillis[i] * 1_000;
            }
            addCpuCyclesPerThreadGroupClusterAtoms(atomTag, pulledData,
                    FrameworkStatsLog.CPU_CYCLES_PER_THREAD_GROUP_CLUSTER__THREAD_GROUP__SURFACE_FLINGER,
                    surfaceFlingerTimesUs);
        }

        return StatsManager.PULL_SUCCESS;
    }