blob: 9c7debb7d9c99b4a554c2bfd8d5f6d96d107f3ad [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
18import android.text.TextUtils;
Joe LaPennad1d80c22016-04-27 09:25:15 -070019import android.os.StrictMode;
Thierry Strudelb786aaa2016-01-21 16:31:21 -080020import android.system.OsConstants;
Adam Lesinski06af1fa2015-05-05 17:35:35 -070021import android.util.Slog;
22
Thierry Strudelb786aaa2016-01-21 16:31:21 -080023import libcore.io.Libcore;
24
Adam Lesinski06af1fa2015-05-05 17:35:35 -070025import java.io.BufferedReader;
26import java.io.FileReader;
27import java.io.IOException;
28import java.util.Arrays;
29
30/**
Adam Lesinski6832f392015-09-05 18:05:40 -070031 * Reads CPU time of a specific core spent at various frequencies and provides a delta from the
32 * last call to {@link #readDelta}. Each line in the proc file has the format:
Adam Lesinski06af1fa2015-05-05 17:35:35 -070033 *
34 * freq time
35 *
Thierry Strudelb786aaa2016-01-21 16:31:21 -080036 * where time is measured in jiffies.
Adam Lesinski06af1fa2015-05-05 17:35:35 -070037 */
38public class KernelCpuSpeedReader {
39 private static final String TAG = "KernelCpuSpeedReader";
Adam Lesinski06af1fa2015-05-05 17:35:35 -070040
Adam Lesinski6832f392015-09-05 18:05:40 -070041 private final String mProcFile;
42 private final long[] mLastSpeedTimes;
43 private final long[] mDeltaSpeedTimes;
44
Thierry Strudelb786aaa2016-01-21 16:31:21 -080045 // How long a CPU jiffy is in milliseconds.
46 private final long mJiffyMillis;
47
Adam Lesinski6832f392015-09-05 18:05:40 -070048 /**
49 * @param cpuNumber The cpu (cpu0, cpu1, etc) whose state to read.
50 */
51 public KernelCpuSpeedReader(int cpuNumber, int numSpeedSteps) {
52 mProcFile = String.format("/sys/devices/system/cpu/cpu%d/cpufreq/stats/time_in_state",
53 cpuNumber);
54 mLastSpeedTimes = new long[numSpeedSteps];
55 mDeltaSpeedTimes = new long[numSpeedSteps];
Thierry Strudelb786aaa2016-01-21 16:31:21 -080056 long jiffyHz = Libcore.os.sysconf(OsConstants._SC_CLK_TCK);
57 mJiffyMillis = 1000/jiffyHz;
Adam Lesinski6832f392015-09-05 18:05:40 -070058 }
Adam Lesinski06af1fa2015-05-05 17:35:35 -070059
60 /**
61 * The returned array is modified in subsequent calls to {@link #readDelta}.
62 * @return The time (in milliseconds) spent at different cpu speeds since the last call to
63 * {@link #readDelta}.
64 */
65 public long[] readDelta() {
Joe LaPennad1d80c22016-04-27 09:25:15 -070066 StrictMode.ThreadPolicy policy = StrictMode.allowThreadDiskReads();
Adam Lesinski6832f392015-09-05 18:05:40 -070067 try (BufferedReader reader = new BufferedReader(new FileReader(mProcFile))) {
Adam Lesinski06af1fa2015-05-05 17:35:35 -070068 TextUtils.SimpleStringSplitter splitter = new TextUtils.SimpleStringSplitter(' ');
69 String line;
70 int speedIndex = 0;
Adam Lesinski80571332015-09-18 14:56:34 -070071 while (speedIndex < mLastSpeedTimes.length && (line = reader.readLine()) != null) {
Adam Lesinski06af1fa2015-05-05 17:35:35 -070072 splitter.setString(line);
73 Long.parseLong(splitter.next());
74
Thierry Strudelb786aaa2016-01-21 16:31:21 -080075 long time = Long.parseLong(splitter.next()) * mJiffyMillis;
Adam Lesinski6832f392015-09-05 18:05:40 -070076 if (time < mLastSpeedTimes[speedIndex]) {
77 // The stats reset when the cpu hotplugged. That means that the time
78 // we read is offset from 0, so the time is the delta.
79 mDeltaSpeedTimes[speedIndex] = time;
80 } else {
81 mDeltaSpeedTimes[speedIndex] = time - mLastSpeedTimes[speedIndex];
82 }
Adam Lesinski06af1fa2015-05-05 17:35:35 -070083 mLastSpeedTimes[speedIndex] = time;
84 speedIndex++;
85 }
86 } catch (IOException e) {
Adam Lesinski6832f392015-09-05 18:05:40 -070087 Slog.e(TAG, "Failed to read cpu-freq: " + e.getMessage());
Adam Lesinski06af1fa2015-05-05 17:35:35 -070088 Arrays.fill(mDeltaSpeedTimes, 0);
Joe LaPennad1d80c22016-04-27 09:25:15 -070089 } finally {
90 StrictMode.setThreadPolicy(policy);
Adam Lesinski06af1fa2015-05-05 17:35:35 -070091 }
92 return mDeltaSpeedTimes;
93 }
94}