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);
}
目录
相关文章
|
Android开发 芯片 开发者
Android MediaTek bootloader 的序列号长度 & 移除非字母和数字限制 SN-Writer工具支持写入
Android MediaTek bootloader 的序列号长度 & 移除非字母和数字限制 SN-Writer工具支持写入
419 0
|
SQL 安全 数据库
数据库系统的ACL
【8月更文挑战第13天】
540 1
|
调度 Android开发 UED
Android经典实战之Android 14前台服务适配
本文介绍了在Android 14中适配前台服务的关键步骤与最佳实践,包括指定服务类型、请求权限、优化用户体验及使用WorkManager等。通过遵循这些指南,确保应用在新系统上顺畅运行并提升用户体验。
1241 6
|
前端开发 JavaScript 测试技术
android做中大型项目完美的架构模式是什么?是MVVM吗?如果不是,是什么?
在 Android 开发中,选择合适的架构模式对于构建中大型项目至关重要。常见的架构模式有 MVVM、MVP、MVI、Clean Architecture 和 Flux/Redux。每种模式都有其优缺点和适用场景,例如 MVVM 适用于复杂 UI 状态和频繁更新,而 Clean Architecture 适合大型项目和多平台开发。选择合适的架构应考虑项目需求、团队熟悉度和可维护性。
584 6
|
Android开发
jack-server导致 Android 编译 出现异常
jack-server导致 Android 编译 出现异常
502 6
|
存储 安全 Shell
Android系统 adb shell auth授权使用
Android系统 adb shell auth授权使用
2157 2
|
Android开发
App Inventor 2 Activity启动器技巧:如何查看并启动其他App
Activity启动器(ActivityStarter)如何查看并启动其他App,可以通过解压源码查看,或使用“包名查看器”App查看,不同品牌手机可能略有不同。
683 1
|
运维 网络协议 Linux
Android 双网卡配置为连接到Android主机的PC提供外网访问(1)
Android 双网卡配置为连接到Android主机的PC提供外网访问(1)
1324 0
|
Android开发
Android Mediatek 禁用 UART 日志输出
Android Mediatek 禁用 UART 日志输出
519 0
|
Shell Android开发
Android11.0(R) MTK平台添加新分区
Android11.0(R) MTK平台添加新分区
3426 0