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);
}