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

Commit 83ba985f authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Periodically read cpuset categories until boot complete." into main

parents 75ea2669 bfa1d713
Loading
Loading
Loading
Loading
+58 −8
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@ import java.nio.file.Files;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@@ -80,13 +81,14 @@ public final class CpuInfoReader {
    /** package **/ @interface CpusetCategory{}

    // TODO(b/242722241): Protect updatable variables with a local lock.
    private final File mCpusetDir;
    private final long mMinReadIntervalMillis;
    private final SparseIntArray mCpusetCategoriesByCpus = new SparseIntArray();
    private final SparseArray<File> mCpuFreqPolicyDirsById = new SparseArray<>();
    private final SparseArray<StaticPolicyInfo> mStaticPolicyInfoById = new SparseArray<>();
    private final SparseArray<LongSparseLongArray> mTimeInStateByPolicyId = new SparseArray<>();
    private final AtomicBoolean mShouldReadCpusetCategories;

    private File mCpusetDir;
    private File mCpuFreqDir;
    private File mProcStatFile;
    private SparseArray<CpuUsageStats> mCumulativeCpuUsageStats = new SparseArray<>();
@@ -106,10 +108,13 @@ public final class CpuInfoReader {
        mCpuFreqDir = cpuFreqDir;
        mProcStatFile = procStatFile;
        mMinReadIntervalMillis = minReadIntervalMillis;
        mShouldReadCpusetCategories = new AtomicBoolean(true);
    }

    /**
     * Initializes CpuInfoReader and returns a boolean to indicate whether the reader is enabled.
     *
     * <p>Returns {@code true} on success. Otherwise, returns {@code false}.
     */
    public boolean init() {
        if (mCpuFreqPolicyDirsById.size() > 0) {
@@ -139,8 +144,7 @@ public final class CpuInfoReader {
            Slogf.e(TAG, "Missing proc stat file at %s", mProcStatFile.getAbsolutePath());
            return false;
        }
        readCpusetCategories();
        if (mCpusetCategoriesByCpus.size() == 0) {
        if (!readCpusetCategories()) {
            Slogf.e(TAG, "Failed to read cpuset information from %s", mCpusetDir.getAbsolutePath());
            return false;
        }
@@ -163,10 +167,19 @@ public final class CpuInfoReader {
        return true;
    }

  public void stopPeriodicCpusetReading() {
        mShouldReadCpusetCategories.set(false);
        if (!readCpusetCategories()) {
            Slogf.e(TAG, "Failed to read cpuset information from %s",
                    mCpusetDir.getAbsolutePath());
            mIsEnabled = false;
        }
    }

    /**
     * Reads CPU information from proc and sys fs files exposed by the Kernel.
     *
     * @return SparseArray keyed by CPU core ID; {@code null} on error or when disabled.
     * <p>Returns SparseArray keyed by CPU core ID; {@code null} on error or when disabled.
     */
    @Nullable
    public SparseArray<CpuInfo> readCpuInfos() {
@@ -183,6 +196,12 @@ public final class CpuInfoReader {
        }
        mLastReadUptimeMillis = uptimeMillis;
        mLastReadCpuInfos = null;
        if (mShouldReadCpusetCategories.get() && !readCpusetCategories()) {
            Slogf.e(TAG, "Failed to read cpuset information from %s",
                    mCpusetDir.getAbsolutePath());
            mIsEnabled = false;
            return null;
        }
        SparseArray<CpuUsageStats> cpuUsageStatsByCpus = readLatestCpuUsageStats();
        if (cpuUsageStatsByCpus == null || cpuUsageStatsByCpus.size() == 0) {
            Slogf.e(TAG, "Failed to read latest CPU usage stats");
@@ -324,7 +343,7 @@ public final class CpuInfoReader {
    /**
     * Sets the CPU frequency for testing.
     *
     * <p>Return {@code true} on success. Otherwise, returns {@code false}.
     * <p>Returns {@code true} on success. Otherwise, returns {@code false}.
     */
    @VisibleForTesting
    boolean setCpuFreqDir(File cpuFreqDir) {
@@ -354,7 +373,7 @@ public final class CpuInfoReader {
    /**
     * Sets the proc stat file for testing.
     *
     * <p>Return true on success. Otherwise, returns false.
     * <p>Returns {@code true} on success. Otherwise, returns {@code false}.
     */
    @VisibleForTesting
    boolean setProcStatFile(File procStatFile) {
@@ -366,6 +385,21 @@ public final class CpuInfoReader {
        return true;
    }

    /**
     * Set the cpuset directory for testing.
     *
     * <p>Returns {@code true} on success. Otherwise, returns {@code false}.
     */
    @VisibleForTesting
    boolean setCpusetDir(File cpusetDir) {
        if (!cpusetDir.exists() && !cpusetDir.isDirectory()) {
            Slogf.e(TAG, "Missing or invalid cpuset directory at %s", cpusetDir.getAbsolutePath());
            return false;
        }
        mCpusetDir = cpusetDir;
        return true;
    }

    private void populateCpuFreqPolicyDirsById(File[] policyDirs) {
        mCpuFreqPolicyDirsById.clear();
        for (int i = 0; i < policyDirs.length; i++) {
@@ -381,12 +415,27 @@ public final class CpuInfoReader {
        }
    }

    private void readCpusetCategories() {
    /**
     * Reads cpuset categories by CPU.
     *
     * <p>The cpusets are read from the cpuset category specific directories
     * under the /dev/cpuset directory. The cpuset categories are subject to change at any point
     * during system bootup, as determined by the init rules specified within the init.rc files.
     * Therefore, it's necessary to read the cpuset categories each time before accessing CPU usage
     * statistics until the system boot completes. Once the boot is complete, the latest changes to
     * the cpuset categories will take a few seconds to propagate. Thus, on boot complete,
     * the periodic reading is stopped with a delay of
     * {@link CpuMonitorService#STOP_PERIODIC_CPUSET_READING_DELAY_MILLISECONDS}.
     *
     * <p>Returns {@code true} on success. Otherwise, returns {@code false}.
     */
    private boolean readCpusetCategories() {
        File[] cpusetDirs = mCpusetDir.listFiles(File::isDirectory);
        if (cpusetDirs == null) {
            Slogf.e(TAG, "Missing cpuset directories at %s", mCpusetDir.getAbsolutePath());
            return;
            return false;
        }
        mCpusetCategoriesByCpus.clear();
        for (int i = 0; i < cpusetDirs.length; i++) {
            File dir = cpusetDirs[i];
            @CpusetCategory int cpusetCategory;
@@ -418,6 +467,7 @@ public final class CpuInfoReader {
                }
            }
        }
        return mCpusetCategoriesByCpus.size() > 0;
    }

    private void readStaticPolicyInfo() {
+26 −2
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import static com.android.server.cpu.CpuAvailabilityMonitoringConfig.CPUSET_ALL;
import static com.android.server.cpu.CpuAvailabilityMonitoringConfig.CPUSET_BACKGROUND;
import static com.android.server.cpu.CpuInfoReader.FLAG_CPUSET_CATEGORY_BACKGROUND;
import static com.android.server.cpu.CpuInfoReader.FLAG_CPUSET_CATEGORY_TOP_APP;
import static com.android.server.SystemService.PHASE_BOOT_COMPLETED;

import android.annotation.Nullable;
import android.content.Context;
@@ -82,6 +83,15 @@ public final class CpuMonitorService extends SystemService {
    //  frequently. Should this duration be increased as well when this happens?
    private static final long LATEST_AVAILABILITY_DURATION_MILLISECONDS =
            TimeUnit.SECONDS.toMillis(30);
    /**
     * Delay to stop the periodic cpuset reading after boot complete.
     *
     * Device specific implementations can update cpuset on boot complete. This may take
     * a few seconds to propagate. So, wait for a few minutes before stopping the periodic cpuset
     * reading.
     */
    private static final long STOP_PERIODIC_CPUSET_READING_DELAY_MILLISECONDS =
            TimeUnit.MINUTES.toMillis(2);

    private final Context mContext;
    private final HandlerThread mHandlerThread;
@@ -90,6 +100,7 @@ public final class CpuMonitorService extends SystemService {
    private final long mNormalMonitoringIntervalMillis;
    private final long mDebugMonitoringIntervalMillis;
    private final long mLatestAvailabilityDurationMillis;
    private final long mStopPeriodicCpusetReadingDelayMillis;
    private final Object mLock = new Object();
    @GuardedBy("mLock")
    private final SparseArrayMap<CpuMonitorInternal.CpuAvailabilityCallback,
@@ -153,13 +164,15 @@ public final class CpuMonitorService extends SystemService {
        this(context, new CpuInfoReader(), new ServiceThread(TAG,
                        Process.THREAD_PRIORITY_BACKGROUND, /* allowIo= */ true),
                Build.IS_USERDEBUG || Build.IS_ENG, NORMAL_MONITORING_INTERVAL_MILLISECONDS,
                DEBUG_MONITORING_INTERVAL_MILLISECONDS, LATEST_AVAILABILITY_DURATION_MILLISECONDS);
                DEBUG_MONITORING_INTERVAL_MILLISECONDS, LATEST_AVAILABILITY_DURATION_MILLISECONDS,
                STOP_PERIODIC_CPUSET_READING_DELAY_MILLISECONDS);
    }

    @VisibleForTesting
    CpuMonitorService(Context context, CpuInfoReader cpuInfoReader, HandlerThread handlerThread,
            boolean shouldDebugMonitor, long normalMonitoringIntervalMillis,
            long debugMonitoringIntervalMillis, long latestAvailabilityDurationMillis) {
            long debugMonitoringIntervalMillis, long latestAvailabilityDurationMillis,
            long stopPeriodicCpusetReadingDelayMillis) {
        super(context);
        mContext = context;
        mHandlerThread = handlerThread;
@@ -167,6 +180,7 @@ public final class CpuMonitorService extends SystemService {
        mNormalMonitoringIntervalMillis = normalMonitoringIntervalMillis;
        mDebugMonitoringIntervalMillis = debugMonitoringIntervalMillis;
        mLatestAvailabilityDurationMillis = latestAvailabilityDurationMillis;
        mStopPeriodicCpusetReadingDelayMillis = stopPeriodicCpusetReadingDelayMillis;
        mCpuInfoReader = cpuInfoReader;
        mCpusetInfosByCpuset = new SparseArray<>(2);
        mCpusetInfosByCpuset.append(CPUSET_ALL, new CpusetInfo(CPUSET_ALL));
@@ -200,6 +214,16 @@ public final class CpuMonitorService extends SystemService {
        }
    }

    @Override
    public void onBootPhase(int phase) {
        if (phase != PHASE_BOOT_COMPLETED) {
            return;
        }
        Slogf.i(TAG, "Stopping periodic cpuset reading on boot complete");
        mHandler.postDelayed(() -> mCpuInfoReader.stopPeriodicCpusetReading(),
                mStopPeriodicCpusetReadingDelayMillis);
    }

    @VisibleForTesting
    long getCurrentMonitoringIntervalMillis() {
        synchronized (mLock) {
+1 −0
Original line number Diff line number Diff line
0-1
+1 −0
Original line number Diff line number Diff line
0-3
+191 −86

File changed.

Preview size limit exceeded, changes collapsed.

Loading