blob: ae13ea4b9d18323f4349c6181aa5ab0df461de02 [file] [log] [blame]
Adam Lesinski06af1fa2015-05-05 17:35:35 -07001/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package com.android.internal.os;
17
Tobias Thierer6217e372017-10-17 20:26:20 +010018import android.system.Os;
Adam Lesinski06af1fa2015-05-05 17:35:35 -070019import android.text.TextUtils;
Joe LaPennad1d80c22016-04-27 09:25:15 -070020import android.os.StrictMode;
Thierry Strudelb786aaa2016-01-21 16:31:21 -080021import android.system.OsConstants;
Adam Lesinski06af1fa2015-05-05 17:35:35 -070022import android.util.Slog;
23
24import java.io.BufferedReader;
25import java.io.FileReader;
26import java.io.IOException;
27import java.util.Arrays;
28
29/**
Adam Lesinski6832f392015-09-05 18:05:40 -070030 * Reads CPU time of a specific core spent at various frequencies and provides a delta from the
31 * last call to {@link #readDelta}. Each line in the proc file has the format:
Adam Lesinski06af1fa2015-05-05 17:35:35 -070032 *
33 * freq time
34 *
Thierry Strudelb786aaa2016-01-21 16:31:21 -080035 * where time is measured in jiffies.
Adam Lesinski06af1fa2015-05-05 17:35:35 -070036 */
37public class KernelCpuSpeedReader {
38 private static final String TAG = "KernelCpuSpeedReader";
Adam Lesinski06af1fa2015-05-05 17:35:35 -070039
Adam Lesinski6832f392015-09-05 18:05:40 -070040 private final String mProcFile;
41 private final long[] mLastSpeedTimes;
42 private final long[] mDeltaSpeedTimes;
43
Thierry Strudelb786aaa2016-01-21 16:31:21 -080044 // How long a CPU jiffy is in milliseconds.
45 private final long mJiffyMillis;
46
Adam Lesinski6832f392015-09-05 18:05:40 -070047 /**
48 * @param cpuNumber The cpu (cpu0, cpu1, etc) whose state to read.
49 */
50 public KernelCpuSpeedReader(int cpuNumber, int numSpeedSteps) {
51 mProcFile = String.format("/sys/devices/system/cpu/cpu%d/cpufreq/stats/time_in_state",
52 cpuNumber);
53 mLastSpeedTimes = new long[numSpeedSteps];
54 mDeltaSpeedTimes = new long[numSpeedSteps];
Tobias Thierer6217e372017-10-17 20:26:20 +010055 long jiffyHz = Os.sysconf(OsConstants._SC_CLK_TCK);
Thierry Strudelb786aaa2016-01-21 16:31:21 -080056 mJiffyMillis = 1000/jiffyHz;
Adam Lesinski6832f392015-09-05 18:05:40 -070057 }
Adam Lesinski06af1fa2015-05-05 17:35:35 -070058
59 /**
60 * The returned array is modified in subsequent calls to {@link #readDelta}.
61 * @return The time (in milliseconds) spent at different cpu speeds since the last call to
62 * {@link #readDelta}.
63 */
64 public long[] readDelta() {
Joe LaPennad1d80c22016-04-27 09:25:15 -070065 StrictMode.ThreadPolicy policy = StrictMode.allowThreadDiskReads();
Adam Lesinski6832f392015-09-05 18:05:40 -070066 try (BufferedReader reader = new BufferedReader(new FileReader(mProcFile))) {
Adam Lesinski06af1fa2015-05-05 17:35:35 -070067 TextUtils.SimpleStringSplitter splitter = new TextUtils.SimpleStringSplitter(' ');
68 String line;
69 int speedIndex = 0;
Adam Lesinski80571332015-09-18 14:56:34 -070070 while (speedIndex < mLastSpeedTimes.length && (line = reader.readLine()) != null) {
Adam Lesinski06af1fa2015-05-05 17:35:35 -070071 splitter.setString(line);
72 Long.parseLong(splitter.next());
73
Thierry Strudelb786aaa2016-01-21 16:31:21 -080074 long time = Long.parseLong(splitter.next()) * mJiffyMillis;
Adam Lesinski6832f392015-09-05 18:05:40 -070075 if (time < mLastSpeedTimes[speedIndex]) {
76 // The stats reset when the cpu hotplugged. That means that the time
77 // we read is offset from 0, so the time is the delta.
78 mDeltaSpeedTimes[speedIndex] = time;
79 } else {
80 mDeltaSpeedTimes[speedIndex] = time - mLastSpeedTimes[speedIndex];
81 }
Adam Lesinski06af1fa2015-05-05 17:35:35 -070082 mLastSpeedTimes[speedIndex] = time;
83 speedIndex++;
84 }
85 } catch (IOException e) {
Adam Lesinski6832f392015-09-05 18:05:40 -070086 Slog.e(TAG, "Failed to read cpu-freq: " + e.getMessage());
Adam Lesinski06af1fa2015-05-05 17:35:35 -070087 Arrays.fill(mDeltaSpeedTimes, 0);
Joe LaPennad1d80c22016-04-27 09:25:15 -070088 } finally {
89 StrictMode.setThreadPolicy(policy);
Adam Lesinski06af1fa2015-05-05 17:35:35 -070090 }
91 return mDeltaSpeedTimes;
92 }
93}