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);
}
目录
相关文章
|
编译器 Shell Android开发
工具技能学习(一):前置技能-makfile、make、.mk
工具技能学习(一):前置技能-makfile、make、.mk
466 0
|
网络协议 网络性能优化 算法
iptables深入解析-mangle篇
      讲了filter、ct、nat 现在剩下最后一个知名模块mangle,但是自身虽然知道内核支持修改数据包的信息,它主要用在策略路由和qos上.我们就具体分析一下.      mangle表主要用于修改数据包的TOS(Type Of Service,服务类型)、TTL(T...
7773 0
|
5月前
|
Linux 开发工具 git
Gitea Enterprise 23.8.0 发布 - 本地部署的企业级 Git 服务
Gitea Enterprise 23.8.0 (Linux, macOS, Windows) - 本地部署的企业级 Git 服务
89 0
Gitea Enterprise 23.8.0 发布 - 本地部署的企业级 Git 服务
|
SQL 安全 数据库
数据库系统的ACL
【8月更文挑战第13天】
304 1
|
机器学习/深度学习 算法 C#
C# | 凸包算法之Andrew‘s,获取围绕一组点的凸多边形的轮廓点
这篇关于凸包算法的文章,本文使用C#和Andrew’s算法来实现凸包算法。 首先消除两个最基本的问题: 什么是凸包呢? 凸包是一个包围一组点的凸多边形。凸多边形是指多边形中的每个内角都小于180度的多边形。 凸包算法有什么用呢? 凸包算法的作用是找到这个凸多边形,并且使用最少的点来绘制出它的轮廓。凸包算法在计算机图形学、计算几何和机器学习等领域中有着广泛的应用。
354 0
|
调度 Android开发 UED
Android经典实战之Android 14前台服务适配
本文介绍了在Android 14中适配前台服务的关键步骤与最佳实践,包括指定服务类型、请求权限、优化用户体验及使用WorkManager等。通过遵循这些指南,确保应用在新系统上顺畅运行并提升用户体验。
742 6
|
Ubuntu
蓝易云 - 解决ubuntu文件系统变成只读的方法
请注意,上述操作可能会导致数据丢失,所以在操作前最好备份重要数据。如果问题依然存在,可能需要考虑更深入的系统诊断或者重装系统。
587 1
|
存储 芯片 块存储
计算机组成原理(2)-----存储芯片与CPU的连接
计算机组成原理(2)-----存储芯片与CPU的连接
851 1
|
运维 网络协议 Linux
Android 双网卡配置为连接到Android主机的PC提供外网访问(1)
Android 双网卡配置为连接到Android主机的PC提供外网访问(1)
767 0
|
编译器 Android开发
Android S内置APK时AndroidManifest使用uses-library编译报错
Android S内置APK时AndroidManifest使用uses-library编译报错
786 0