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:
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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",
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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
|
||||
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user