script-astra/Android/Sdk/sources/android-35/com/android/internal/os/CpuScalingPolicyReader.java
localadmin 4380f00a78 init
2025-01-20 18:15:20 +03:00

149 lines
5.5 KiB
Java

/*
* Copyright (C) 2023 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.NonNull;
import android.os.FileUtils;
import android.util.IntArray;
import android.util.Slog;
import android.util.SparseArray;
import com.android.internal.annotations.VisibleForTesting;
import libcore.util.EmptyArray;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Captures a CPU scaling policies such as available scaling frequencies as well as
* CPUs (cores) for each policy.
*
* See <a
* href="https://www.kernel.org/doc/html/latest/admin-guide/pm/cpufreq.html
* #policy-interface-in-sysfs">Policy Interface in sysfs</a>
*/
@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class CpuScalingPolicyReader {
private static final String TAG = "CpuScalingPolicyReader";
private static final String CPUFREQ_DIR = "/sys/devices/system/cpu/cpufreq";
private static final Pattern POLICY_PATTERN = Pattern.compile("policy(\\d+)");
private static final String FILE_NAME_RELATED_CPUS = "related_cpus";
private static final String FILE_NAME_SCALING_AVAILABLE_FREQUENCIES =
"scaling_available_frequencies";
private static final String FILE_NAME_SCALING_BOOST_FREQUENCIES = "scaling_boost_frequencies";
private static final String FILE_NAME_CPUINFO_CUR_FREQ = "cpuinfo_cur_freq";
private final String mCpuFreqDir;
public CpuScalingPolicyReader() {
this(CPUFREQ_DIR);
}
@VisibleForTesting
public CpuScalingPolicyReader(String cpuFreqDir) {
mCpuFreqDir = cpuFreqDir;
}
/**
* Reads scaling policy info from sysfs files in /sys/devices/system/cpu/cpufreq
*/
@NonNull
public CpuScalingPolicies read() {
SparseArray<int[]> cpusByPolicy = new SparseArray<>();
SparseArray<int[]> freqsByPolicy = new SparseArray<>();
File cpuFreqDir = new File(mCpuFreqDir);
File[] policyDirs = cpuFreqDir.listFiles();
if (policyDirs != null) {
for (File policyDir : policyDirs) {
Matcher matcher = POLICY_PATTERN.matcher(policyDir.getName());
if (matcher.matches()) {
int[] relatedCpus = readIntsFromFile(
new File(policyDir, FILE_NAME_RELATED_CPUS));
if (relatedCpus.length == 0) {
continue;
}
int[] availableFreqs = readIntsFromFile(
new File(policyDir, FILE_NAME_SCALING_AVAILABLE_FREQUENCIES));
int[] boostFreqs = readIntsFromFile(
new File(policyDir, FILE_NAME_SCALING_BOOST_FREQUENCIES));
int[] freqs;
if (boostFreqs.length == 0) {
freqs = availableFreqs;
} else {
freqs = Arrays.copyOf(availableFreqs,
availableFreqs.length + boostFreqs.length);
System.arraycopy(boostFreqs, 0, freqs, availableFreqs.length,
boostFreqs.length);
}
if (freqs.length == 0) {
freqs = readIntsFromFile(new File(policyDir, FILE_NAME_CPUINFO_CUR_FREQ));
if (freqs.length == 0) {
freqs = new int[]{0}; // Unknown frequency
}
}
int policy = Integer.parseInt(matcher.group(1));
cpusByPolicy.put(policy, relatedCpus);
freqsByPolicy.put(policy, freqs);
}
}
}
if (cpusByPolicy.size() == 0) {
// There just has to be at least one CPU - otherwise, what's executing this code?
cpusByPolicy.put(0, new int[]{0});
freqsByPolicy.put(0, new int[]{0});
}
return new CpuScalingPolicies(cpusByPolicy, freqsByPolicy);
}
@NonNull
private static int[] readIntsFromFile(File file) {
if (!file.exists()) {
return EmptyArray.INT;
}
IntArray intArray = new IntArray(16);
try {
String contents = FileUtils.readTextFile(file, 0, null).trim();
String[] strings = contents.split(" ");
intArray.clear();
for (String s : strings) {
if (s.isBlank()) {
continue;
}
try {
intArray.add(Integer.parseInt(s));
} catch (NumberFormatException e) {
Slog.e(TAG, "Unexpected file format " + file
+ ": " + contents, e);
}
}
return intArray.toArray();
} catch (IOException e) {
Slog.e(TAG, "Cannot read " + file, e);
return EmptyArray.INT;
}
}
}