This repository has been archived by the owner on Oct 5, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 369
/
CpuStateMonitor.java
executable file
·220 lines (187 loc) · 6.29 KB
/
CpuStateMonitor.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
//-----------------------------------------------------------------------------
//
// (C) Brandon Valosek, 2011 <bvalosek@gmail.com>
// (C) Willi Ye, 2015 <williye97@gmail.com>
//
//-----------------------------------------------------------------------------
// Modified by Willi Ye to work with big.LITTLE
package com.bvalosek.cpuspy;
import android.os.SystemClock;
import android.support.annotation.NonNull;
import android.util.SparseArray;
import com.grarak.kerneladiutor.utils.Utils;
import com.grarak.kerneladiutor.utils.kernel.cpu.CPUFreq;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* CpuStateMonitor is a class responsible for querying the system and getting
* the time-in-state information, as well as allowing the user to set/reset
* offsets to "restart" the state timers
*/
public class CpuStateMonitor {
private final int mCore;
private final List<CpuState> mStates = new ArrayList<>();
private final SparseArray<Long> mOffsets = new SparseArray<>();
CpuStateMonitor(int core) {
mCore = core;
}
/**
* exception class
*/
public static class CpuStateMonitorException extends Exception {
private CpuStateMonitorException(String s) {
super(s);
}
}
/**
* simple struct for states/time
*/
public static class CpuState implements Comparable<CpuState> {
private int mFreq = 0;
private long mDuration = 0;
/**
* init with freq and duration
*/
private CpuState(int a, long b) {
mFreq = a;
mDuration = b;
}
public int getFreq() {
return mFreq;
}
public long getDuration() {
return mDuration;
}
/**
* for sorting, compare the freqs
*/
@Override
public int compareTo(@NonNull CpuState another) {
return ((Integer) mFreq).compareTo(another.mFreq);
}
}
/**
* @return List of CpuState with the offsets applied
*/
public List<CpuState> getStates() {
List<CpuState> states = new ArrayList<>();
/*
* check for an existing offset, and if it's not too big, subtract it
* from the duration, otherwise just add it to the return List
*/
for (CpuState state : mStates) {
long duration = state.getDuration();
if (mOffsets.indexOfKey(state.getFreq()) >= 0) {
long offset = mOffsets.get(state.getFreq());
if (offset <= duration) {
duration -= offset;
} else {
/*
* offset > duration implies our offsets are now invalid, so
* clear and recall this function
*/
mOffsets.clear();
return getStates();
}
}
states.add(new CpuState(state.getFreq(), duration));
}
return states;
}
/**
* @return Sum of all state durations including deep sleep, accounting for
* offsets
*/
public long getTotalStateTime() {
long sum = 0;
for (CpuState state : mStates) {
sum += state.getDuration();
}
return sum;
}
/**
* @return Map of freq->duration of all the offsets
*/
SparseArray<Long> getOffsets() {
return mOffsets;
}
/**
* Sets the offset map (freq->duration offset)
*/
void setOffsets(SparseArray<Long> offsets) {
mOffsets.clear();
for (int i = 0; i < offsets.size(); i++) {
mOffsets.put(offsets.keyAt(i), offsets.valueAt(i));
}
}
/**
* Updates the current time in states and then sets the offset map to the
* current duration, effectively "zeroing out" the timers
*/
public void setOffsets() throws CpuStateMonitorException {
mOffsets.clear();
updateStates();
for (CpuState state : mStates) {
mOffsets.put(state.getFreq(), state.getDuration());
}
}
/**
* removes state offsets
*/
public void removeOffsets() {
mOffsets.clear();
}
/**
* list of all the CPU frequency states, which contains both a
* frequency and a duration (time spent in that state
*/
public void updateStates() throws CpuStateMonitorException {
CPUFreq cpuFreq = CPUFreq.getInstance();
mStates.clear();
try {
String file;
if (Utils.existFile(Utils.strFormat(CPUFreq.TIME_STATE, mCore))) {
file = Utils.strFormat(CPUFreq.TIME_STATE, mCore);
} else {
file = Utils.strFormat(CPUFreq.TIME_STATE_2, mCore);
}
boolean offline = cpuFreq.isOffline(mCore);
if (offline) {
cpuFreq.onlineCpu(mCore, true, false, null);
}
String states = Utils.readFile(file);
if (offline) {
cpuFreq.onlineCpu(mCore, false, false, null);
}
if (states.isEmpty()) {
throw new CpuStateMonitorException("Problem opening time-in-states file");
}
readInStates(states.split("\\r?\\n"));
} catch (Exception e) {
throw new CpuStateMonitorException("Problem opening time-in-states file");
}
/*
* deep sleep time determined by difference between elapsed (total) boot
* time and the system uptime (awake)
*/
long sleepTime = (SystemClock.elapsedRealtime() - SystemClock.uptimeMillis()) / 10;
mStates.add(new CpuState(0, sleepTime));
Collections.sort(mStates, Collections.reverseOrder());
}
/**
* read from a provided BufferedReader the state lines into the States
* member field
*/
private void readInStates(String[] states) throws CpuStateMonitorException {
try {
// split open line and convert to Integers
for (String line : states) {
String[] nums = line.split(" ");
mStates.add(new CpuState(Utils.strToInt(nums[0]), Utils.strToLong(nums[1])));
}
} catch (Exception e) {
throw new CpuStateMonitorException("Problem processing time-in-states file");
}
}
}