blob: 71f0db52ce5f8abf37a4812fa5efbc4791b71291 [file] [log] [blame]
Sudheer Shankae2f3edf2018-07-12 10:30:38 -07001/*
2 * Copyright (C) 2018 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 */
16
17package com.android.server.am;
18
19import android.os.PowerManagerInternal;
20import android.os.Process;
21import android.os.SystemClock;
22
23import com.android.internal.annotations.GuardedBy;
24import com.android.internal.os.BackgroundThread;
25import com.android.internal.os.ProcessCpuTracker;
26import com.android.internal.util.RingBuffer;
27import com.android.internal.util.function.pooled.PooledLambda;
28
29import java.io.PrintWriter;
30
31public class OomAdjProfiler {
32 @GuardedBy("this")
33 private boolean mOnBattery;
34 @GuardedBy("this")
35 private boolean mScreenOff;
36
37 @GuardedBy("this")
38 private long mOomAdjStartTimeMs;
39 @GuardedBy("this")
40 private boolean mOomAdjStarted;
41
42 @GuardedBy("this")
43 private CpuTimes mOomAdjRunTime = new CpuTimes();
44 @GuardedBy("this")
45 private CpuTimes mSystemServerCpuTime = new CpuTimes();
46
47 @GuardedBy("this")
48 private long mLastSystemServerCpuTimeMs;
49 @GuardedBy("this")
50 private boolean mSystemServerCpuTimeUpdateScheduled;
51 private final ProcessCpuTracker mProcessCpuTracker = new ProcessCpuTracker(false);
52
53 @GuardedBy("this")
54 final RingBuffer<CpuTimes> mOomAdjRunTimesHist = new RingBuffer<>(CpuTimes.class, 10);
55 @GuardedBy("this")
56 final RingBuffer<CpuTimes> mSystemServerCpuTimesHist = new RingBuffer<>(CpuTimes.class, 10);
57
58 void batteryPowerChanged(boolean onBattery) {
59 synchronized (this) {
60 scheduleSystemServerCpuTimeUpdate();
61 mOnBattery = onBattery;
62 }
63 }
64
65 void onWakefulnessChanged(int wakefulness) {
66 synchronized (this) {
67 scheduleSystemServerCpuTimeUpdate();
68 mScreenOff = wakefulness != PowerManagerInternal.WAKEFULNESS_AWAKE;
69 }
70 }
71
72 void oomAdjStarted() {
73 synchronized (this) {
74 mOomAdjStartTimeMs = SystemClock.currentThreadTimeMillis();
75 mOomAdjStarted = true;
76 }
77 }
78
79 void oomAdjEnded() {
80 synchronized (this) {
81 if (!mOomAdjStarted) {
82 return;
83 }
84 mOomAdjRunTime.addCpuTimeMs(SystemClock.currentThreadTimeMillis() - mOomAdjStartTimeMs);
85 }
86 }
87
88 private void scheduleSystemServerCpuTimeUpdate() {
89 synchronized (this) {
90 if (mSystemServerCpuTimeUpdateScheduled) {
91 return;
92 }
93 mSystemServerCpuTimeUpdateScheduled = true;
Yohei Yukawae2fa39e2018-09-22 13:13:10 -070094 BackgroundThread.getHandler().sendMessage(PooledLambda.obtainMessage(
Sudheer Shankae2f3edf2018-07-12 10:30:38 -070095 OomAdjProfiler::updateSystemServerCpuTime,
Yohei Yukawae2fa39e2018-09-22 13:13:10 -070096 this, mOnBattery, mScreenOff));
Sudheer Shankae2f3edf2018-07-12 10:30:38 -070097 }
98 }
99
100 private void updateSystemServerCpuTime(boolean onBattery, boolean screenOff) {
101 final long cpuTimeMs = mProcessCpuTracker.getCpuTimeForPid(Process.myPid());
102 synchronized (this) {
103 mSystemServerCpuTime.addCpuTimeMs(
104 cpuTimeMs - mLastSystemServerCpuTimeMs, onBattery, screenOff);
105 mLastSystemServerCpuTimeMs = cpuTimeMs;
106 mSystemServerCpuTimeUpdateScheduled = false;
107 notifyAll();
108 }
109 }
110
111 void reset() {
112 synchronized (this) {
113 if (mSystemServerCpuTime.isEmpty()) {
114 return;
115 }
116 mOomAdjRunTimesHist.append(mOomAdjRunTime);
117 mSystemServerCpuTimesHist.append(mSystemServerCpuTime);
118 mOomAdjRunTime = new CpuTimes();
119 mSystemServerCpuTime = new CpuTimes();
120 }
121 }
122
123 void dump(PrintWriter pw) {
124 synchronized (this) {
125 if (mSystemServerCpuTimeUpdateScheduled) {
126 while (mSystemServerCpuTimeUpdateScheduled) {
127 try {
128 wait();
129 } catch (InterruptedException e) {
130 Thread.currentThread().interrupt();
131 }
132 }
133 } else {
134 updateSystemServerCpuTime(mOnBattery, mScreenOff);
135 }
136
137 pw.println("System server and oomAdj runtimes (ms) in recent battery sessions "
138 + "(most recent first):");
139 if (!mSystemServerCpuTime.isEmpty()) {
140 pw.print(" ");
141 pw.print("system_server=");
142 pw.print(mSystemServerCpuTime);
143 pw.print(" ");
144 pw.print("oom_adj=");
145 pw.println(mOomAdjRunTime);
146 }
147 final CpuTimes[] systemServerCpuTimes = mSystemServerCpuTimesHist.toArray();
148 final CpuTimes[] oomAdjRunTimes = mOomAdjRunTimesHist.toArray();
149 for (int i = oomAdjRunTimes.length - 1; i >= 0; --i) {
150 pw.print(" ");
151 pw.print("system_server=");
152 pw.print(systemServerCpuTimes[i]);
153 pw.print(" ");
154 pw.print("oom_adj=");
155 pw.println(oomAdjRunTimes[i]);
156 }
157 }
158 }
159
160 private class CpuTimes {
161 private long mOnBatteryTimeMs;
162 private long mOnBatteryScreenOffTimeMs;
163
164 public void addCpuTimeMs(long cpuTimeMs) {
165 addCpuTimeMs(cpuTimeMs, mOnBattery, mScreenOff);
166 }
167
168 public void addCpuTimeMs(long cpuTimeMs, boolean onBattery, boolean screenOff) {
169 if (onBattery) {
170 mOnBatteryTimeMs += cpuTimeMs;
171 if (screenOff) {
172 mOnBatteryScreenOffTimeMs += cpuTimeMs;
173 }
174 }
175 }
176
177 public boolean isEmpty() {
178 return mOnBatteryTimeMs == 0 && mOnBatteryScreenOffTimeMs == 0;
179 }
180
181 public String toString() {
182 return "[" + mOnBatteryTimeMs + "," + mOnBatteryScreenOffTimeMs + "]";
183 }
184 }
185}