Merge "Fix KernelCpuUidUserSysTimeReaderTest#testThrottler by injecting a mock clock"

This commit is contained in:
Dmitri Plotnikov
2021-07-23 01:35:00 +00:00
committed by Android (Google) Code Review
23 changed files with 624 additions and 561 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -256,7 +256,7 @@ public class BatteryUsageStatsProvider {
private long elapsedRealtime() {
if (mStats instanceof BatteryStatsImpl) {
return ((BatteryStatsImpl) mStats).mClocks.elapsedRealtime();
return ((BatteryStatsImpl) mStats).mClock.elapsedRealtime();
} else {
return SystemClock.elapsedRealtime();
}
@@ -264,7 +264,7 @@ public class BatteryUsageStatsProvider {
private long uptimeMillis() {
if (mStats instanceof BatteryStatsImpl) {
return ((BatteryStatsImpl) mStats).mClocks.uptimeMillis();
return ((BatteryStatsImpl) mStats).mClock.uptimeMillis();
} else {
return SystemClock.uptimeMillis();
}
@@ -272,7 +272,7 @@ public class BatteryUsageStatsProvider {
private long currentTimeMillis() {
if (mStats instanceof BatteryStatsImpl) {
return ((BatteryStatsImpl) mStats).mClocks.currentTimeMillis();
return ((BatteryStatsImpl) mStats).mClock.currentTimeMillis();
} else {
return System.currentTimeMillis();
}

View File

@@ -0,0 +1,57 @@
/*
* Copyright (C) 2021 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.internal.os;
import android.os.SystemClock;
/**
* A wrapper for SystemClock, intended for mocking in unit tests.
*/
public abstract class Clock {
/** Elapsed Realtime, see SystemClock.elapsedRealtime() */
public long elapsedRealtime() {
throw new UnsupportedOperationException();
}
/** Uptime, see SystemClock.uptimeMillis() */
public long uptimeMillis() {
throw new UnsupportedOperationException();
}
/** Wall-clock time as per System.currentTimeMillis() */
public long currentTimeMillis() {
throw new UnsupportedOperationException();
}
public static final Clock SYSTEM_CLOCK = new Clock() {
@Override
public long elapsedRealtime() {
return SystemClock.elapsedRealtime();
}
@Override
public long uptimeMillis() {
return SystemClock.uptimeMillis();
}
@Override
public long currentTimeMillis() {
return System.currentTimeMillis();
}
};
}

View File

@@ -17,7 +17,6 @@
package com.android.internal.os;
import android.os.StrictMode;
import android.os.SystemClock;
import android.util.Slog;
import java.io.BufferedReader;
@@ -89,6 +88,7 @@ public class KernelCpuProcStringReader {
private int mErrors = 0;
private final Path mFile;
private final Clock mClock;
private char[] mBuf;
private int mSize;
private long mLastReadTime = 0;
@@ -97,7 +97,12 @@ public class KernelCpuProcStringReader {
private final ReentrantReadWriteLock.WriteLock mWriteLock = mLock.writeLock();
public KernelCpuProcStringReader(String file) {
this(file, Clock.SYSTEM_CLOCK);
}
public KernelCpuProcStringReader(String file, Clock clock) {
mFile = Paths.get(file);
mClock = clock;
}
/**
@@ -168,7 +173,7 @@ public class KernelCpuProcStringReader {
}
}
mSize = total;
mLastReadTime = SystemClock.elapsedRealtime();
mLastReadTime = mClock.elapsedRealtime();
// ReentrantReadWriteLock allows lock downgrading.
mReadLock.lock();
return new ProcFileIterator(total);
@@ -186,7 +191,7 @@ public class KernelCpuProcStringReader {
}
private boolean dataValid() {
return mSize > 0 && (SystemClock.elapsedRealtime() - mLastReadTime < FRESHNESS);
return mSize > 0 && (mClock.elapsedRealtime() - mLastReadTime < FRESHNESS);
}
/**

View File

@@ -21,7 +21,6 @@ import static com.android.internal.util.Preconditions.checkNotNull;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.StrictMode;
import android.os.SystemClock;
import android.util.IntArray;
import android.util.Slog;
import android.util.SparseArray;
@@ -60,6 +59,7 @@ public abstract class KernelCpuUidTimeReader<T> {
final boolean mThrottle;
protected boolean mBpfTimesAvailable;
final KernelCpuUidBpfMapReader mBpfReader;
private final Clock mClock;
private long mMinTimeBetweenRead = DEFAULT_MIN_TIME_BETWEEN_READ;
private long mLastReadTimeMs = 0;
@@ -76,15 +76,17 @@ public abstract class KernelCpuUidTimeReader<T> {
void onUidCpuTime(int uid, T time);
}
KernelCpuUidTimeReader(KernelCpuProcStringReader reader, @Nullable KernelCpuUidBpfMapReader bpfReader, boolean throttle) {
KernelCpuUidTimeReader(KernelCpuProcStringReader reader,
@Nullable KernelCpuUidBpfMapReader bpfReader, boolean throttle, Clock clock) {
mReader = reader;
mThrottle = throttle;
mBpfReader = bpfReader;
mClock = clock;
mBpfTimesAvailable = (mBpfReader != null);
}
KernelCpuUidTimeReader(KernelCpuProcStringReader reader, boolean throttle) {
this(reader, null, throttle);
KernelCpuUidTimeReader(KernelCpuProcStringReader reader, boolean throttle, Clock clock) {
this(reader, null, throttle, clock);
}
/**
@@ -104,17 +106,17 @@ public abstract class KernelCpuUidTimeReader<T> {
*/
public void readDelta(boolean force, @Nullable Callback<T> cb) {
if (!mThrottle) {
readDeltaImpl(cb);
readDeltaImpl(cb, force);
return;
}
final long currTimeMs = SystemClock.elapsedRealtime();
final long currTimeMs = mClock.elapsedRealtime();
if (!force && currTimeMs < mLastReadTimeMs + mMinTimeBetweenRead) {
if (DEBUG) {
Slog.d(mTag, "Throttle readDelta");
}
return;
}
readDeltaImpl(cb);
readDeltaImpl(cb, force);
mLastReadTimeMs = currTimeMs;
}
@@ -128,7 +130,7 @@ public abstract class KernelCpuUidTimeReader<T> {
readAbsoluteImpl(cb);
return;
}
final long currTimeMs = SystemClock.elapsedRealtime();
final long currTimeMs = mClock.elapsedRealtime();
if (currTimeMs < mLastReadTimeMs + mMinTimeBetweenRead) {
if (DEBUG) {
Slog.d(mTag, "Throttle readAbsolute");
@@ -139,7 +141,7 @@ public abstract class KernelCpuUidTimeReader<T> {
mLastReadTimeMs = currTimeMs;
}
abstract void readDeltaImpl(@Nullable Callback<T> cb);
abstract void readDeltaImpl(@Nullable Callback<T> cb, boolean forceRead);
abstract void readAbsoluteImpl(Callback<T> callback);
@@ -216,17 +218,22 @@ public abstract class KernelCpuUidTimeReader<T> {
private final long[] mUsrSysTime = new long[2];
public KernelCpuUidUserSysTimeReader(boolean throttle) {
super(KernelCpuProcStringReader.getUserSysTimeReaderInstance(), throttle);
this(throttle, Clock.SYSTEM_CLOCK);
}
public KernelCpuUidUserSysTimeReader(boolean throttle, Clock clock) {
super(KernelCpuProcStringReader.getUserSysTimeReaderInstance(), throttle, clock);
}
@VisibleForTesting
public KernelCpuUidUserSysTimeReader(KernelCpuProcStringReader reader, boolean throttle) {
super(reader, throttle);
public KernelCpuUidUserSysTimeReader(KernelCpuProcStringReader reader, boolean throttle,
Clock clock) {
super(reader, throttle, clock);
}
@Override
void readDeltaImpl(@Nullable Callback<long[]> cb) {
try (ProcFileIterator iter = mReader.open(!mThrottle)) {
void readDeltaImpl(@Nullable Callback<long[]> cb, boolean forceRead) {
try (ProcFileIterator iter = mReader.open(!mThrottle || forceRead)) {
if (iter == null) {
return;
}
@@ -348,14 +355,23 @@ public abstract class KernelCpuUidTimeReader<T> {
private boolean mAllUidTimesAvailable = true;
public KernelCpuUidFreqTimeReader(boolean throttle) {
this(throttle, Clock.SYSTEM_CLOCK);
}
public KernelCpuUidFreqTimeReader(boolean throttle, Clock clock) {
this(UID_TIMES_PROC_FILE, KernelCpuProcStringReader.getFreqTimeReaderInstance(),
KernelCpuUidBpfMapReader.getFreqTimeReaderInstance(), throttle);
KernelCpuUidBpfMapReader.getFreqTimeReaderInstance(), throttle, clock);
}
@VisibleForTesting
public KernelCpuUidFreqTimeReader(String procFile, KernelCpuProcStringReader reader,
KernelCpuUidBpfMapReader bpfReader, boolean throttle) {
super(reader, bpfReader, throttle);
this(procFile, reader, bpfReader, throttle, Clock.SYSTEM_CLOCK);
}
private KernelCpuUidFreqTimeReader(String procFile, KernelCpuProcStringReader reader,
KernelCpuUidBpfMapReader bpfReader, boolean throttle, Clock clock) {
super(reader, bpfReader, throttle, clock);
mProcFilePath = Paths.get(procFile);
}
@@ -496,7 +512,7 @@ public abstract class KernelCpuUidTimeReader<T> {
}
@Override
void readDeltaImpl(@Nullable Callback<long[]> cb) {
void readDeltaImpl(@Nullable Callback<long[]> cb, boolean forceRead) {
if (mBpfTimesAvailable) {
try (BpfMapIterator iter = mBpfReader.open(!mThrottle)) {
if (checkPrecondition(iter)) {
@@ -628,13 +644,18 @@ public abstract class KernelCpuUidTimeReader<T> {
private long[] mBuffer;
public KernelCpuUidActiveTimeReader(boolean throttle) {
this(throttle, Clock.SYSTEM_CLOCK);
}
public KernelCpuUidActiveTimeReader(boolean throttle, Clock clock) {
super(KernelCpuProcStringReader.getActiveTimeReaderInstance(),
KernelCpuUidBpfMapReader.getActiveTimeReaderInstance(), throttle);
KernelCpuUidBpfMapReader.getActiveTimeReaderInstance(), throttle, clock);
}
@VisibleForTesting
public KernelCpuUidActiveTimeReader(KernelCpuProcStringReader reader, KernelCpuUidBpfMapReader bpfReader, boolean throttle) {
super(reader, bpfReader, throttle);
public KernelCpuUidActiveTimeReader(KernelCpuProcStringReader reader,
KernelCpuUidBpfMapReader bpfReader, boolean throttle) {
super(reader, bpfReader, throttle, Clock.SYSTEM_CLOCK);
}
private void processUidDelta(@Nullable Callback<Long> cb) {
@@ -655,7 +676,7 @@ public abstract class KernelCpuUidTimeReader<T> {
}
@Override
void readDeltaImpl(@Nullable Callback<Long> cb) {
void readDeltaImpl(@Nullable Callback<Long> cb, boolean forceRead) {
if (mBpfTimesAvailable) {
try (BpfMapIterator iter = mBpfReader.open(!mThrottle)) {
if (checkPrecondition(iter)) {
@@ -800,14 +821,18 @@ public abstract class KernelCpuUidTimeReader<T> {
private long[] mDeltaTime;
public KernelCpuUidClusterTimeReader(boolean throttle) {
this(throttle, Clock.SYSTEM_CLOCK);
}
public KernelCpuUidClusterTimeReader(boolean throttle, Clock clock) {
super(KernelCpuProcStringReader.getClusterTimeReaderInstance(),
KernelCpuUidBpfMapReader.getClusterTimeReaderInstance(), throttle);
KernelCpuUidBpfMapReader.getClusterTimeReaderInstance(), throttle, clock);
}
@VisibleForTesting
public KernelCpuUidClusterTimeReader(KernelCpuProcStringReader reader,
KernelCpuUidBpfMapReader bpfReader, boolean throttle) {
super(reader, bpfReader, throttle);
KernelCpuUidBpfMapReader bpfReader, boolean throttle) {
super(reader, bpfReader, throttle, Clock.SYSTEM_CLOCK);
}
void processUidDelta(@Nullable Callback<long[]> cb) {
@@ -838,7 +863,7 @@ public abstract class KernelCpuUidTimeReader<T> {
}
@Override
void readDeltaImpl(@Nullable Callback<long[]> cb) {
void readDeltaImpl(@Nullable Callback<long[]> cb, boolean forceRead) {
if (mBpfTimesAvailable) {
try (BpfMapIterator iter = mBpfReader.open(!mThrottle)) {
if (checkPrecondition(iter)) {