blob: 9846b310c9174cbe8210c9add930a4dcb919cd47 [file] [log] [blame]
/*
* Copyright (C) 2018 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.server.am;
import android.os.PowerManagerInternal;
import android.os.Process;
import android.os.SystemClock;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.os.BackgroundThread;
import com.android.internal.os.ProcessCpuTracker;
import com.android.internal.util.RingBuffer;
import com.android.internal.util.function.pooled.PooledLambda;
import java.io.PrintWriter;
public class OomAdjProfiler {
// Disable profiling for Q. Re-enable once b/130635979 is fixed.
private static final boolean PROFILING_DISABLED = true;
@GuardedBy("this")
private boolean mOnBattery;
@GuardedBy("this")
private boolean mScreenOff;
@GuardedBy("this")
private long mOomAdjStartTimeMs;
@GuardedBy("this")
private boolean mOomAdjStarted;
@GuardedBy("this")
private CpuTimes mOomAdjRunTime = new CpuTimes();
@GuardedBy("this")
private CpuTimes mSystemServerCpuTime = new CpuTimes();
@GuardedBy("this")
private long mLastSystemServerCpuTimeMs;
@GuardedBy("this")
private boolean mSystemServerCpuTimeUpdateScheduled;
private final ProcessCpuTracker mProcessCpuTracker = new ProcessCpuTracker(false);
@GuardedBy("this")
final RingBuffer<CpuTimes> mOomAdjRunTimesHist = new RingBuffer<>(CpuTimes.class, 10);
@GuardedBy("this")
final RingBuffer<CpuTimes> mSystemServerCpuTimesHist = new RingBuffer<>(CpuTimes.class, 10);
void batteryPowerChanged(boolean onBattery) {
if (PROFILING_DISABLED) {
return;
}
synchronized (this) {
scheduleSystemServerCpuTimeUpdate();
mOnBattery = onBattery;
}
}
void onWakefulnessChanged(int wakefulness) {
if (PROFILING_DISABLED) {
return;
}
synchronized (this) {
scheduleSystemServerCpuTimeUpdate();
mScreenOff = wakefulness != PowerManagerInternal.WAKEFULNESS_AWAKE;
}
}
void oomAdjStarted() {
if (PROFILING_DISABLED) {
return;
}
synchronized (this) {
mOomAdjStartTimeMs = SystemClock.currentThreadTimeMillis();
mOomAdjStarted = true;
}
}
void oomAdjEnded() {
if (PROFILING_DISABLED) {
return;
}
synchronized (this) {
if (!mOomAdjStarted) {
return;
}
mOomAdjRunTime.addCpuTimeMs(SystemClock.currentThreadTimeMillis() - mOomAdjStartTimeMs);
}
}
private void scheduleSystemServerCpuTimeUpdate() {
if (PROFILING_DISABLED) {
return;
}
synchronized (this) {
if (mSystemServerCpuTimeUpdateScheduled) {
return;
}
mSystemServerCpuTimeUpdateScheduled = true;
BackgroundThread.getHandler().sendMessage(PooledLambda.obtainMessage(
OomAdjProfiler::updateSystemServerCpuTime,
this, mOnBattery, mScreenOff));
}
}
private void updateSystemServerCpuTime(boolean onBattery, boolean screenOff) {
if (PROFILING_DISABLED) {
return;
}
final long cpuTimeMs = mProcessCpuTracker.getCpuTimeForPid(Process.myPid());
synchronized (this) {
mSystemServerCpuTime.addCpuTimeMs(
cpuTimeMs - mLastSystemServerCpuTimeMs, onBattery, screenOff);
mLastSystemServerCpuTimeMs = cpuTimeMs;
mSystemServerCpuTimeUpdateScheduled = false;
notifyAll();
}
}
void reset() {
synchronized (this) {
if (mSystemServerCpuTime.isEmpty()) {
return;
}
mOomAdjRunTimesHist.append(mOomAdjRunTime);
mSystemServerCpuTimesHist.append(mSystemServerCpuTime);
mOomAdjRunTime = new CpuTimes();
mSystemServerCpuTime = new CpuTimes();
}
}
void dump(PrintWriter pw) {
if (PROFILING_DISABLED) {
return;
}
synchronized (this) {
if (mSystemServerCpuTimeUpdateScheduled) {
while (mSystemServerCpuTimeUpdateScheduled) {
try {
wait();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
} else {
updateSystemServerCpuTime(mOnBattery, mScreenOff);
}
pw.println("System server and oomAdj runtimes (ms) in recent battery sessions "
+ "(most recent first):");
if (!mSystemServerCpuTime.isEmpty()) {
pw.print(" ");
pw.print("system_server=");
pw.print(mSystemServerCpuTime);
pw.print(" ");
pw.print("oom_adj=");
pw.println(mOomAdjRunTime);
}
final CpuTimes[] systemServerCpuTimes = mSystemServerCpuTimesHist.toArray();
final CpuTimes[] oomAdjRunTimes = mOomAdjRunTimesHist.toArray();
for (int i = oomAdjRunTimes.length - 1; i >= 0; --i) {
pw.print(" ");
pw.print("system_server=");
pw.print(systemServerCpuTimes[i]);
pw.print(" ");
pw.print("oom_adj=");
pw.println(oomAdjRunTimes[i]);
}
}
}
private class CpuTimes {
private long mOnBatteryTimeMs;
private long mOnBatteryScreenOffTimeMs;
public void addCpuTimeMs(long cpuTimeMs) {
addCpuTimeMs(cpuTimeMs, mOnBattery, mScreenOff);
}
public void addCpuTimeMs(long cpuTimeMs, boolean onBattery, boolean screenOff) {
if (onBattery) {
mOnBatteryTimeMs += cpuTimeMs;
if (screenOff) {
mOnBatteryScreenOffTimeMs += cpuTimeMs;
}
}
}
public boolean isEmpty() {
return mOnBatteryTimeMs == 0 && mOnBatteryScreenOffTimeMs == 0;
}
public String toString() {
return "[" + mOnBatteryTimeMs + "," + mOnBatteryScreenOffTimeMs + "]";
}
}
}