MTK PerfService (2) - PerfService的落地

简介: 看看PerfService是如何落地的,提供一个完整的例子

MTK PerfService (2) - PerfService的落地

API讲完了之后,我们来看看如何落地。我们先从java层说起。

PerfServiceWrapper

PerfServiceWrapper调用例

我们上面曾经看到过WebView中调用PerfService的例子:

sPerfService = new PerfServiceWrapper(null);
if (sPerfService != null) {
    int minCPU = 2;
    if (maxFreq < 1100000)
        minCPU = 4;
    sPerfHandle = sPerfService.userReg(minCPU, maxFreq);
    if (sPerfHandle != -1) {
        sPerfService.userEnableTimeoutMs(sPerfHandle, 500);
        Handler handler = new Handler();
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                sPerfService.userUnreg(sPerfHandle);
            }
        }, 600);
    }
}

我们来看看userReg是如何调用的:

public int userReg(int scn_core, int scn_freq) {
    int handle = -1;
    //log("[userReg] - "+scn_core+", "+scn_freq);
    try {
        init();
        int pid = nativeGetPid();
        int tid = nativeGetTid();
        if (sService != null)
            handle = sService.userReg(scn_core, scn_freq, pid, tid);
    } catch (RemoteException e) {
        loge("ERR: RemoteException in userReg:" + e);
    }
    //log("[userReg] - handle:"+handle);
    return handle;
}

再来看看init是如何做的,通过Context.MTK_PERF_SERVICE来提供服务。

private void init() {
    if (inited == 0) {
        IBinder b = ServiceManager.checkService(Context.MTK_PERF_SERVICE);
        if (b != null) {
            sService = IPerfService.Stub.asInterface(b);
            if (sService != null)
                inited = 1;
            else
                log("ERR: getService() sService is still null..");
        }
    }
}

PerfServiceImpl

我们再看服务中是如何实现的,在/frameworks/base/services/core/java/com/mediatek/perfservice/PerfServiceImpl.java中:

public int userReg(int scn_core, int scn_freq, int pid, int tid) {
    //log("userReg");
    return perfServiceMgr.userReg(scn_core, scn_freq, pid, tid);
}

具体的实现在PerfServiceMgr中,

public int userGetCapability(int cmd) {
    return nativePerfUserGetCapability(cmd);
}

PerfService的落地还是靠JNI:

static int
android_server_PerfUserScnReg(JNIEnv *env, jobject thiz,
                                        jint scn_core, jint scn_freq, jint pid, jint tid)
{
#if defined(MTK_PERFSERVICE_SUPPORT)
    if (!inited)
        init();

    if (perfUserScnReg) {
        return perfUserScnReg(scn_core, scn_freq, pid, tid);
    }

    ALOGE("perfUserScnReg bypassed!");
#endif
    return -1;
}

com_mediatek_perfservice_PerfServiceManager.cpp

最终,终于落地在我们熟悉的Native API上了。定义于frameworks/base/services/core/jni/com_mediatek_perfservice_PerfServiceManager.cpp

#define LIB_FULL_NAME "libperfservice.so"

static void init()
{
#if defined(MTK_PERFSERVICE_SUPPORT)
    void *handle, *func;

    // only enter once
    inited = true;

    handle = dlopen(LIB_FULL_NAME, RTLD_NOW);
    if (handle == NULL) {
        ALOGE("Can't load library: %s", dlerror());
        return;
    }

...

    func = dlsym(handle, "perfUserScnReg");
    perfUserScnReg = reinterpret_cast<user_reg>(func);

    if (perfUserScnReg == NULL) {
        ALOGE("perfUserScnReg error: %s", dlerror());
        perfUserScnReg = NULL;
        dlclose(handle);
        return;
    }

超时的处理

超时并不是在libperfservice.so中实现的,直接在java层就搞定了:

public void userEnableTimeout(int handle, int timeout) {
    mHandler.stopCheckUserTimer(handle);
    nativePerfUserScnEnable(handle);

    Message msg = mHandler.obtainMessage();
    msg.what = PerfServiceThreadHandler.MESSAGE_USER_ENABLE_TIMEOUT;
    msg.arg1 = handle;
    msg.arg2 = timeout;
    msg.sendToTarget();
}

public void userEnableTimeoutMs(int handle, int timeout_ms) {
    mHandler.stopCheckUserTimer(handle);
    nativePerfUserScnEnable(handle);

    Message msg = mHandler.obtainMessage();
    msg.what = PerfServiceThreadHandler.MESSAGE_USER_ENABLE_TIMEOUT_MS;
    msg.arg1 = handle;
    msg.arg2 = timeout_ms;
    msg.sendToTarget();
}

Native API的调用方式

请注意,com_mediatek_perfservice_PerfServiceManager.cpp是调用libperfservice.so,而我们使用libperfservicenative.so.
所以我们也要做一些事情才可以调用

函数原型定义

我们先把可能用到的Native API的原型定义一下,这些函数方便后面调用。

static int  (*perfUserScnReg)(int, int) = nullptr;
static int  (*perfUserScnRegBigLittle)(int, int, int, int) = nullptr;
static void (*perfUserScnUnreg)(int) = nullptr;
static int  (*perfUserGetCapability)(int) = nullptr;
static int  (*perfUserRegScn)(void) = nullptr;
static void (*perfUserRegScnConfig)(int, int, int, int, int, int) = nullptr;
static void (*perfUserUnregScn)(int) = nullptr;
static void (*perfUserScnEnable)(int) = nullptr;
static void (*perfUserScnDisable)(int) = nullptr;
static void (*perfUserScnEnableTimeout)(int, int) = nullptr;
static void (*perfUserScnEnableTimeoutMs)(int, int) = nullptr;

然后再用typedef定义一些类型吧:

typedef int  (*user_reg)(int, int);
typedef int  (*user_reg_big_little)(int, int, int, int);
typedef void (*user_unreg)(int);
typedef int  (*user_get_capability)(int);
typedef int  (*user_reg_scn)(void);
typedef void (*user_reg_scn_config)(int, int, int, int, int, int);
typedef void (*user_unreg_scn)(int);
typedef void (*user_enable)(int);
typedef void (*user_disable)(int);
typedef void (*user_enable_timeout)(int, int);
typedef void (*user_enable_timeout_ms)(int, int);

引入libperfservicenative.so

 #define PERF_SERVICE_NATIVE_LIB "libperfservicenative.so"

    void *handle, *func;

    handle = dlopen(PERF_SERVICE_NATIVE_LIB, RTLD_NOW);
    if (handle == nullptr) {
        ALOGE("Can't load library: %s", dlerror());
        return;
    }

加载符号

    func = dlsym(handle, "PerfServiceNative_userReg");
    perfUserScnReg = reinterpret_cast<user_reg>(func);

    if (perfUserScnReg == nullptr) {
        ALOGE("perfUserScnReg error: %s", dlerror());
        dlclose(handle);
        return;
    }

    func = dlsym(handle, "PerfServiceNative_userRegBigLittle");
    perfUserScnRegBigLittle = reinterpret_cast<user_reg_big_little>(func);

    if (perfUserScnRegBigLittle == nullptr) {
        ALOGE("perfUserScnRegBigLittle error: %s", dlerror());
        dlclose(handle);
        return;
    }

    func = dlsym(handle, "PerfServiceNative_userUnreg");
    perfUserScnUnreg = reinterpret_cast<user_unreg>(func);

    if (perfUserScnUnreg == nullptr) {
        ALOGE("perfUserScnUnreg error: %s", dlerror());
        dlclose(handle);
        return;
    }
...

终于可以调用了

下面终于可以正式干活了:

老的API,开8个核!

    int handle;

    init();
    handle = perfUserScnReg(4,0);
    perfUserScnEnable(handle);

    //Do job!

    perfUserScnDisable(handle);
    perfUserScnUnreg(handle);

新的API:

    int handle2;
    handle2 = perfUserRegScn();
    perfUserRegScnConfig(handle2,CMD_SET_CPU_CORE_MIN,4,0,0,0);
    perfUserRegScnConfig(handle2,CMD_SET_CPU_FREQ_MIN,1469000,0,0,0);
    perfUserRegScnConfig(handle2,CMD_SET_CPU_FREQ_MAX,1469000,0,0,0);
    perfUserScnEnable(handle2);

    //Do job!

    perfUserScnDisable(handle2);
    perfUserUnregScn(handle2);

Native调用的完整例子

Android.mk

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SHARED_LIBRARIES += libdl liblog
LOCAL_C_INCLUDES += $(MTK_PATH_SOURCE)/hardware/perfservice/perfservicenative/

LOCAL_SRC_FILES := native_perf.cc
LOCAL_MODULE := nativeperf
include $(BUILD_EXECUTABLE)

native_perf.cc

#include <dlfcn.h>
#include <android/log.h>
#include "PerfServiceNative.h"

#define PERF_SERVICE_NATIVE_LIB "libperfservicenative.so"

#define  ALOGE(...)  __android_log_print(ANDROID_LOG_ERROR,"TestPerfNative",__VA_ARGS__)

static int  (*perfUserScnReg)(int, int) = nullptr;
static int  (*perfUserScnRegBigLittle)(int, int, int, int) = nullptr;
static void (*perfUserScnUnreg)(int) = nullptr;
static int  (*perfUserGetCapability)(int) = nullptr;
static int  (*perfUserRegScn)(void) = nullptr;
static void (*perfUserRegScnConfig)(int, int, int, int, int, int) = nullptr;
static void (*perfUserUnregScn)(int) = nullptr;
static void (*perfUserScnEnable)(int) = nullptr;
static void (*perfUserScnDisable)(int) = nullptr;
static void (*perfUserScnEnableTimeout)(int, int) = nullptr;
static void (*perfUserScnEnableTimeoutMs)(int, int) = nullptr;

typedef int  (*user_reg)(int, int);
typedef int  (*user_reg_big_little)(int, int, int, int);
typedef void (*user_unreg)(int);
typedef int  (*user_get_capability)(int);
typedef int  (*user_reg_scn)(void);
typedef void (*user_reg_scn_config)(int, int, int, int, int, int);
typedef void (*user_unreg_scn)(int);
typedef void (*user_enable)(int);
typedef void (*user_disable)(int);
typedef void (*user_enable_timeout)(int, int);
typedef void (*user_enable_timeout_ms)(int, int);

static void init()
{
    void *handle, *func;

    handle = dlopen(PERF_SERVICE_NATIVE_LIB, RTLD_NOW);
    if (handle == nullptr) {
        ALOGE("Can't load library: %s", dlerror());
        return;
    }

    func = dlsym(handle, "PerfServiceNative_userReg");
    perfUserScnReg = reinterpret_cast<user_reg>(func);

    if (perfUserScnReg == nullptr) {
        ALOGE("perfUserScnReg error: %s", dlerror());
        dlclose(handle);
        return;
    }

    func = dlsym(handle, "PerfServiceNative_userRegBigLittle");
    perfUserScnRegBigLittle = reinterpret_cast<user_reg_big_little>(func);

    if (perfUserScnRegBigLittle == nullptr) {
        ALOGE("perfUserScnRegBigLittle error: %s", dlerror());
        dlclose(handle);
        return;
    }

    func = dlsym(handle, "PerfServiceNative_userUnreg");
    perfUserScnUnreg = reinterpret_cast<user_unreg>(func);

    if (perfUserScnUnreg == nullptr) {
        ALOGE("perfUserScnUnreg error: %s", dlerror());
        dlclose(handle);
        return;
    }

    func = dlsym(handle, "PerfServiceNative_userGetCapability");
    perfUserGetCapability = reinterpret_cast<user_get_capability>(func);

    if (perfUserGetCapability == nullptr) {
        ALOGE("perfUserGetCapability error: %s", dlerror());
        dlclose(handle);
        return;
    }

    func = dlsym(handle, "PerfServiceNative_userRegScn");
    perfUserRegScn = reinterpret_cast<user_reg_scn>(func);

    if (perfUserRegScn == nullptr) {
        ALOGE("perfUserRegScn error: %s", dlerror());
        dlclose(handle);
        return;
    }

    func = dlsym(handle, "PerfServiceNative_userRegScnConfig");
    perfUserRegScnConfig = reinterpret_cast<user_reg_scn_config>(func);

    if (perfUserRegScnConfig == nullptr) {
        ALOGE("perfUserRegScnConfig error: %s", dlerror());
        dlclose(handle);
        return;
    }

    func = dlsym(handle, "PerfServiceNative_userUnregScn");
    perfUserUnregScn = reinterpret_cast<user_unreg_scn>(func);

    if (perfUserUnregScn == nullptr) {
        ALOGE("perfUserUnregScn error: %s", dlerror());
        dlclose(handle);
        return;
    }

    func = dlsym(handle, "PerfServiceNative_userEnable");
    perfUserScnEnable = reinterpret_cast<user_enable>(func);

    if (perfUserScnEnable == nullptr) {
        ALOGE("perfUserScnEnable error: %s", dlerror());
        dlclose(handle);
        return;
    }

    func = dlsym(handle, "PerfServiceNative_userDisable");
    perfUserScnDisable = reinterpret_cast<user_disable>(func);

    if (perfUserScnDisable == nullptr) {
        ALOGE("perfUserScnDisable error: %s", dlerror());
        dlclose(handle);
        return;
    }

    func = dlsym(handle, "PerfServiceNative_userEnableTimeout");
    perfUserScnEnableTimeout = reinterpret_cast<user_enable_timeout>(func);

    if (perfUserScnEnableTimeout == nullptr) {
        ALOGE("perfUserScnEnableTimeout error: %s", dlerror());
        dlclose(handle);
        return;
    }

    func = dlsym(handle, "PerfServiceNative_userEnableTimeoutMs");
    perfUserScnEnableTimeoutMs = reinterpret_cast<user_enable_timeout_ms>(func);

    if (perfUserScnEnableTimeoutMs == nullptr) {
        ALOGE("perfUserScnEnableTimeoutMs error: %s", dlerror());
        dlclose(handle);
        return;
    }
};

int main()
{
    int handle;

    init();
    handle = perfUserScnReg(4,0);
    perfUserScnEnable(handle);

    //Do job!

    perfUserScnDisable(handle);
    perfUserScnUnreg(handle);

    int handle2;
    handle2 = perfUserRegScn();
    perfUserRegScnConfig(handle2,CMD_SET_CPU_CORE_MIN,4,0,0,0);
    perfUserRegScnConfig(handle2,CMD_SET_CPU_FREQ_MIN,1469000,0,0,0);
    perfUserRegScnConfig(handle2,CMD_SET_CPU_FREQ_MAX,1469000,0,0,0);
    perfUserScnEnable(handle2);

    //Do job!

    perfUserScnDisable(handle2);
    perfUserUnregScn(handle2);
}
目录
相关文章
|
9月前
|
供应链 数据可视化 Java
国产技术迎来突破,14nm芯片横空出世,低代码也有好消息
国产技术迎来突破,14nm芯片横空出世,低代码也有好消息
126 0
|
芯片 开发者 SoC
平头哥发布最强RISC-V处理器,向AIoT时代迈出了一大步
去年的杭州云栖大会上,平头哥半导体公司正式诞生;时隔不到一年,这家芯片公司发布了首款处理器——玄铁910,据官方介绍,这款处理器基于开源RISC-V架构,同时也是该架构下性能最强的处理器,可以应用在5G、自动驾驶等AIoT场景。
2962 0
|
物联网 芯片
arm还是x86?未来在工业SBC数字谁可以脱颖而出
在过去的30年里,工业PC市场一直由x86处理器占据主导地位,考虑到其在台式PC中的应用,这应该不足为奇。从无风扇坚固的箱式计算机到PC / 104和Mini-ITX等工业板标准,x86架构提供了大量经过验证的接口,驱动程序和软件支持,可加速工业计算行业的发展。
1531 0
|
安全 物联网 芯片
|
机器学习/深度学习 监控 自动驾驶