高通平台有自己的performance 模块, 常见的场景是加速响应用户的触控响应.
主要分为java 应用层,Native 层, 和私有库,以及Kernel的支持.
/** * Called to process touch screen events. You can override this to * intercept all touch screen events before they are dispatched to the * window. Be sure to call this implementation for touch screen events * that should be handled normally. * * @param ev The touch screen event. * * @return boolean Return true if this event was consumed. */
public boolean dispatchTouchEvent(MotionEvent ev) {
if(mDragBoostPossible == -1) {
mDragBoostPossible = 0;
String currentActivity = getPackageName();
String[] activityList = getResources().getStringArray(
com.android.internal.R.array.boost_activityList);
if(activityList != null){
for (String match : activityList) {
if (currentActivity.indexOf(match) != -1){
mDragBoostPossible = 1;
break;
}
}
}
}
if (mDragBoostPossible == 1) {
if (mPerf == null){
mPerf = new Performance();
}
if(mPerfLockDuration == -1){
mPerfLockDuration = getResources().getInteger(
com.android.internal.R.integer.ascrollboost_timeout);
mAsCpuBoost = getResources().getInteger(
com.android.internal.R.integer.ascrollboost_cpuboost);
mAsSchedBoost = getResources().getInteger(
com.android.internal.R.integer.ascrollboost_schedboost);
mAsPcDisblBoost = getResources().getInteger(
com.android.internal.R.integer.ascrollboost_pcdisbl);
}
mPerf.perfLockAcquireTouch(ev,
getResources().getDisplayMetrics(),
mPerfLockDuration,
mAsSchedBoost, mAsCpuBoost, mAsPcDisblBoost);
}
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
onUserInteraction();
}
if (getWindow().superDispatchTouchEvent(ev)) {
return true;
}
return onTouchEvent(ev);
}
定义的时间参数在这里.
base/core/res/res/values/config.xml
<!-- Activity scroll boost params -->
<integer name="ascrollboost_timeout">17</integer>
<integer name="ascrollboost_schedboost">0x1E01</integer>
<integer name="ascrollboost_cpuboost">0x20F</integer>
<integer name="ascrollboost_pcdisbl">0x101</integer>
获取相关的boots 时间参数后 就调用 下面的函数来进行加速.
/* The following two functions are the PerfLock APIs*/
/** &hide */
public int perfLockAcquireTouch(MotionEvent ev, DisplayMetrics metrics,
int duration, int... list) {
int rc = REQUEST_FAILED;
final int actionMasked = ev.getActionMasked();
final int pointerIndex = ev.getActionIndex();
final int pointerId = ev.getPointerId(pointerIndex);
final int y = (int) ev.getY(pointerIndex);
final int x = (int) ev.getX(pointerIndex);
int dx = (int)((x * 1f)/metrics.density);
int dy = (int)((y * 1f)/metrics.density);
boolean isBoostRequired = false;
switch (actionMasked) {
case MotionEvent.ACTION_DOWN: {
if(mVelocityTracker == null) {
// Retrieve a new VelocityTracker object to watch the velocity of a motion.
mVelocityTracker = VelocityTracker.obtain();
}
else {
// Reset the velocity tracker back to its initial state.
mVelocityTracker.clear();
}
if(mVelocityTracker != null) {
// Add a user's movement to the tracker.
mVelocityTracker.addMovement(ev);
}
if (mTouchInfo == null) {
mTouchInfo = new TouchInfo();
}
if (mTouchInfo != null) {
// Reset drag boost params
mTouchInfo.reset();
// set start, current position
mTouchInfo.setStartXY(dx, dy);
// set drag movement thresholds
mTouchInfo.setDragWH((int)(mWDragPix * 1f/metrics.density),
(int)(mHDragPix * 1f/metrics.density));
}
break;
}
case MotionEvent.ACTION_MOVE: {
if(mVelocityTracker != null) {
// Add a user's movement to the tracker.
mVelocityTracker.addMovement(ev);
}
if(mTouchInfo != null) {
int xdiff = Math.abs(dx - mTouchInfo.mCurX);
int ydiff = Math.abs(dy - mTouchInfo.mCurY);
//set current position
mTouchInfo.setXY(dx, dy);
if ((xdiff > mTouchInfo.mMinDragW) ||
(ydiff > mTouchInfo.mMinDragH)) {
//drag detected. Boost it.
isBoostRequired = true;
}
}
break;
}
case MotionEvent.ACTION_UP: {
if(mVelocityTracker != null) {
// Add a user's movement to the tracker
mVelocityTracker.addMovement(ev);
// compute velocity (pixel per second)
mVelocityTracker.computeCurrentVelocity(1000, mMaxVelocity);
final int initialVelocity =
Math.abs((int) mVelocityTracker.getYVelocity(pointerId));
if (initialVelocity > mMinVelocity) {
//Velocity is more than min velocity.Calculate fling boost duration.
duration *= ((1f * initialVelocity)/(1f * mMinVelocity));
//Enable boost
isBoostRequired = true;
break;
}
}
if(mTouchInfo != null) {
int xdiff = Math.abs(dx - mTouchInfo.mCurX);
int ydiff = Math.abs(dy - mTouchInfo.mCurY);
if ((xdiff > mTouchInfo.mMinDragW) ||
(ydiff > mTouchInfo.mMinDragH)) {
//Only drag boost. Boost it.
isBoostRequired = true;
}
}
break;
}
case MotionEvent.ACTION_CANCEL: {
if(mTouchInfo != null) {
mTouchInfo.reset();
}
break;
}
default:
break;
}
**if(isBoostRequired == true) {
handle = native_perf_lock_acq(handle, duration, list); // 执行boost 资源获取.
if (handle != 0) {
rc = REQUEST_SUCCEEDED;
}
}**
return rc;
}
3.JNI 层代码
frameworks/base/core/jni/org_codeaurora_Performance.cpp
static JNINativeMethod gMethods[] = {
{"native_perf_lock_acq", "(II[I)I", (int *)org_codeaurora_performance_native_perf_lock_acq},
{"native_perf_lock_rel", "(I)I", (int *)org_codeaurora_performance_native_perf_lock_rel},
{"native_deinit", "()V", (void *)org_codeaurora_performance_native_deinit},
};
int register_org_codeaurora_Performance(JNIEnv *env)
{
pthread_mutex_lock(&dl_mutex);
org_codeaurora_performance_native_init();
pthread_mutex_unlock(&dl_mutex);
return AndroidRuntime::registerNativeMethods(env,
"org/codeaurora/Performance", gMethods, NELEM(gMethods));// 注册提供的API函数. 只有3个方法. 比较简单.
}
device 目录下面有配置 property 库的路径.
PRODUCT_PROPERTY_OVERRIDES += \
ro.vendor.extension_library=libqti-perfd-client.so \
最重要的一个init函数, 打开私有库 ,调取里面的方法.
// ----------------------------------------------------------------------------
static void
org_codeaurora_performance_native_init()
{
const char *rc;
char buf[PROPERTY_VALUE_MAX];
int len;
/* Retrieve name of vendor extension library */
if (property_get("ro.vendor.extension_library", buf, NULL) <= 0) {
return;
}
/* Sanity check - ensure */
buf[PROPERTY_VALUE_MAX-1] = '\0';
if (strstr(buf, "/") != NULL) {
return;
}
dlhandle = dlopen(buf, RTLD_NOW | RTLD_LOCAL);
if (dlhandle == NULL) {
return;
}
dlerror();
----------
获取最关键的2个方法.
**perf_lock_acq = (int (*) (int, int, int[], int))dlsym(dlhandle, "perf_lock_acq");
if ((rc = dlerror()) != NULL) {
goto cleanup;
}
perf_lock_rel = (int (*) (int))dlsym(dlhandle, "perf_lock_rel");
if ((rc = dlerror()) != NULL) {
goto cleanup;
}**
----------
return;
cleanup:
perf_lock_acq = NULL;
perf_lock_rel = NULL;
if (dlhandle) {
dlclose(dlhandle);
dlhandle = NULL;
}
}
1.首先, 守护进程启动server—> mpctl_server_init()
2.client 发送服务请求到server.
mpctl_send(MPCTL_CMD_PERFLOCKREL, handle);
mpctl_send(MPCTL_CMD_PERFLOCKACQ, handle, duration, numArgs, list);
mpctl_send(MPCTL_CMD_PERFLOCKRESET);
3.server响应请求进行CPU底层操作.