Add sources for API 35

Downloaded from https://dl.google.com/android/repository/source-35_r01.zip
using SdkManager in Studio

Test: None
Change-Id: I83f78aa820b66edfdc9f8594d17bc7b6cacccec1
diff --git a/android-35/com/android/internal/os/CpuScalingPolicyReader.java b/android-35/com/android/internal/os/CpuScalingPolicyReader.java
new file mode 100644
index 0000000..720577e
--- /dev/null
+++ b/android-35/com/android/internal/os/CpuScalingPolicyReader.java
@@ -0,0 +1,148 @@
+/*
+ * 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>
+ */
[email protected]
+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;
+        }
+    }
+}