Measure total time in state

Total CPU time in state added in https://r.android.com/1538886.

Bug: 174245730
Test: cmd stats pull-source 10095
Change-Id: I6cd27ac172e36d2e889429808bd4bd583795d7c9
This commit is contained in:
Rafal Slawik
2020-12-10 18:02:56 +00:00
parent d52f765a7f
commit f278e21a61
5 changed files with 135 additions and 0 deletions

View File

@@ -0,0 +1,43 @@
/*
* Copyright (C) 2020 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;
/**
* Reads total CPU time bpf map.
*/
public final class KernelCpuTotalBpfMapReader {
private KernelCpuTotalBpfMapReader() {
}
/** Returns whether total CPU time is measured. */
public static boolean isSupported() {
// TODO(b/174245730): Implement this check.
return true;
}
/** Reads total CPU time from bpf map. */
public static native boolean read(Callback callback);
/** Callback accepting values read from bpf map. */
public interface Callback {
/**
* Accepts values read from bpf map: cluster index, frequency in kilohertz and time in
* milliseconds that the cpu cluster spent at the frequency (excluding sleep).
*/
void accept(int cluster, int freqKhz, long timeMs);
}
}

View File

@@ -184,6 +184,7 @@ cc_library_shared {
"com_android_internal_net_NetworkUtilsInternal.cpp",
"com_android_internal_os_ClassLoaderFactory.cpp",
"com_android_internal_os_FuseAppLoop.cpp",
"com_android_internal_os_KernelCpuTotalBpfMapReader.cpp",
"com_android_internal_os_KernelCpuUidBpfMapReader.cpp",
"com_android_internal_os_KernelSingleProcessCpuThreadReader.cpp",
"com_android_internal_os_KernelSingleUidTimeReader.cpp",

View File

@@ -190,6 +190,7 @@ extern int register_com_android_internal_content_om_OverlayConfig(JNIEnv *env);
extern int register_com_android_internal_net_NetworkUtilsInternal(JNIEnv* env);
extern int register_com_android_internal_os_ClassLoaderFactory(JNIEnv* env);
extern int register_com_android_internal_os_FuseAppLoop(JNIEnv* env);
extern int register_com_android_internal_os_KernelCpuTotalBpfMapReader(JNIEnv* env);
extern int register_com_android_internal_os_KernelCpuUidBpfMapReader(JNIEnv *env);
extern int register_com_android_internal_os_KernelSingleProcessCpuThreadReader(JNIEnv* env);
extern int register_com_android_internal_os_KernelSingleUidTimeReader(JNIEnv *env);
@@ -1585,6 +1586,7 @@ static const RegJNIRec gRegJNI[] = {
REG_JNI(register_android_security_Scrypt),
REG_JNI(register_com_android_internal_content_NativeLibraryHelper),
REG_JNI(register_com_android_internal_os_FuseAppLoop),
REG_JNI(register_com_android_internal_os_KernelCpuTotalBpfMapReader),
REG_JNI(register_com_android_internal_os_KernelCpuUidBpfMapReader),
REG_JNI(register_com_android_internal_os_KernelSingleProcessCpuThreadReader),
REG_JNI(register_com_android_internal_os_KernelSingleUidTimeReader),

View File

@@ -0,0 +1,57 @@
/*
* Copyright (C) 2020 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.
*/
#include "core_jni_helpers.h"
#include <cputimeinstate.h>
namespace android {
static jboolean KernelCpuTotalBpfMapReader_read(JNIEnv *env, jobject, jobject callback) {
jclass callbackClass = env->GetObjectClass(callback);
jmethodID callbackMethod = env->GetMethodID(callbackClass, "accept", "(IIJ)V");
if (callbackMethod == 0) {
return JNI_FALSE;
}
auto freqs = android::bpf::getCpuFreqs();
if (!freqs) return JNI_FALSE;
auto freqTimes = android::bpf::getTotalCpuFreqTimes();
if (!freqTimes) return JNI_FALSE;
auto freqsClusterSize = (*freqs).size();
for (uint32_t clusterIndex = 0; clusterIndex < freqsClusterSize; ++clusterIndex) {
auto freqsSize = (*freqs)[clusterIndex].size();
for (uint32_t freqIndex = 0; freqIndex < freqsSize; ++freqIndex) {
env->CallVoidMethod(callback, callbackMethod, clusterIndex,
(*freqs)[clusterIndex][freqIndex],
(*freqTimes)[clusterIndex][freqIndex] / 1000000);
}
}
return JNI_TRUE;
}
static const JNINativeMethod methods[] = {
{"read", "(Lcom/android/internal/os/KernelCpuTotalBpfMapReader$Callback;)Z",
(void *)KernelCpuTotalBpfMapReader_read},
};
int register_com_android_internal_os_KernelCpuTotalBpfMapReader(JNIEnv *env) {
return RegisterMethodsOrDie(env, "com/android/internal/os/KernelCpuTotalBpfMapReader", methods,
NELEM(methods));
}
} // namespace android

View File

@@ -141,6 +141,7 @@ import com.android.internal.os.BinderCallsStats.ExportedCallStat;
import com.android.internal.os.KernelCpuThreadReader;
import com.android.internal.os.KernelCpuThreadReaderDiff;
import com.android.internal.os.KernelCpuThreadReaderSettingsObserver;
import com.android.internal.os.KernelCpuTotalBpfMapReader;
import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidActiveTimeReader;
import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidClusterTimeReader;
import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidFreqTimeReader;
@@ -350,6 +351,7 @@ public class StatsPullAtomService extends SystemService {
private final Object mDataBytesTransferLock = new Object();
private final Object mBluetoothBytesTransferLock = new Object();
private final Object mKernelWakelockLock = new Object();
private final Object mCpuTimePerClusterFreqLock = new Object();
private final Object mCpuTimePerUidLock = new Object();
private final Object mCpuTimePerUidFreqLock = new Object();
private final Object mCpuActiveTimeLock = new Object();
@@ -438,6 +440,10 @@ public class StatsPullAtomService extends SystemService {
synchronized (mKernelWakelockLock) {
return pullKernelWakelockLocked(atomTag, data);
}
case FrameworkStatsLog.CPU_TIME_PER_CLUSTER_FREQ:
synchronized (mCpuTimePerClusterFreqLock) {
return pullCpuTimePerClusterFreqLocked(atomTag, data);
}
case FrameworkStatsLog.CPU_TIME_PER_UID:
synchronized (mCpuTimePerUidLock) {
return pullCpuTimePerUidLocked(atomTag, data);
@@ -773,6 +779,7 @@ public class StatsPullAtomService extends SystemService {
mStatsCallbackImpl = new StatsPullAtomCallbackImpl();
registerBluetoothBytesTransfer();
registerKernelWakelock();
registerCpuTimePerClusterFreq();
registerCpuTimePerUid();
registerCpuCyclesPerUidCluster();
registerCpuTimePerUidFreq();
@@ -1444,6 +1451,31 @@ public class StatsPullAtomService extends SystemService {
return StatsManager.PULL_SUCCESS;
}
private void registerCpuTimePerClusterFreq() {
if (KernelCpuTotalBpfMapReader.isSupported()) {
int tagId = FrameworkStatsLog.CPU_TIME_PER_CLUSTER_FREQ;
PullAtomMetadata metadata = new PullAtomMetadata.Builder()
.setAdditiveFields(new int[] {3})
.build();
mStatsManager.setPullAtomCallback(
tagId,
metadata,
DIRECT_EXECUTOR,
mStatsCallbackImpl
);
}
}
int pullCpuTimePerClusterFreqLocked(int atomTag, List<StatsEvent> pulledData) {
boolean success = KernelCpuTotalBpfMapReader.read((cluster, freq, timeMs) -> {
pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag, cluster, freq, timeMs));
});
if (!success) {
return StatsManager.PULL_SKIP;
}
return StatsManager.PULL_SUCCESS;
}
private void registerCpuTimePerUid() {
int tagId = FrameworkStatsLog.CPU_TIME_PER_UID;
PullAtomMetadata metadata = new PullAtomMetadata.Builder()