Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 23ac0f8f authored by Rafal Slawik's avatar Rafal Slawik Committed by Android (Google) Code Review
Browse files

Merge "Measure total time in state"

parents a1435cb6 f278e21a
Loading
Loading
Loading
Loading
+43 −0
Original line number Diff line number Diff line
/*
 * 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);
    }
}
+1 −0
Original line number Diff line number Diff line
@@ -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",
+2 −0
Original line number Diff line number Diff line
@@ -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),
+57 −0
Original line number Diff line number Diff line
/*
 * 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
+32 −0
Original line number Diff line number Diff line
@@ -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()