1、在MTK芯片上如何控制CPU的核数和频率-MTK PerfService
一句话:PerfService就是用来调整CPU/GPU资源的。对于老的API,可以更简单地讲就是调CPU核数和CPU频率的。
1.1PerfService简介
kernel中实现了两个driver,一个负责控制开关CPU的核数,叫做hot-plug驱动,另一个负责调整CPU的频率,叫做DVFS驱动。
kernel中的driver会根据系统的负载情况下,自动调整使用几个CPU和调整CPU频率。如果负载高了,提高频率,或者多开几个核,或者开大核。如果负载降下去了,就可以关大核,关核,降频。
虽然现在的自动调频和调核的策略已经定义了很多,也在不断地完善,但是有两个问题:一是总有覆盖不到的情况,或者干脆就是互相矛盾的需求导致策略冲突。二是自动调度都是后知后觉的,只有发现负载上来了或者降下去了,才来做负载调节,需要一定的时间。这样,要么是效率不够,要么是功耗无谓地消耗掉。
PerfService就是一个在用户空间来主动调节系统能力的服务。
1.2C/C++调用PerfService
步骤
- 动态加载libperfservicenative.so
- 注册用户场景PerfServiceNative_userReg/PerfServiceNative_userRegBigLittle/PerfServiceNative_userRegScn
- 激活用户场景PerfServiceNative_userEnable
- 执行用户场景
- 反激活用户场景PerfServiceNative_userDisable
- 退出进程之前反注册PerfServiceNative_userUnreg/PerfServiceNative_userUnregScn
1.2.1老API的步骤
老API只能对CPU做调度,但是好处是可以直接指定开几个核,频率调到多少,还可以控制开大核还是小核。
- PerfServiceNative_userReg可以指定几个核和多高的频率
- PerfServiceNative_userRegBigLittle还可以用来指定调度大小核
- PerfServiceNative_userEnable用来激活上面注册的场景,PerfServiceNative_userEnableTimeout可以指定激活的超时时间
- PerfServiceNative_userDisable用来反激活
- PerfServiceNative_userUnreg反注册
1.2.2新API的步骤
新的API也可以调节GPU,但是采用的方式要复杂一些,就不再像老API一样直接指定核和频率了,需要定义配置
- PerfServiceNative_userRegScn:没有参数,直接注册就好
- PerfServiceNative_userRegScnConfig:用这个函数去真正指定配置
- PerfServiceNative_userEnable/PerfServiceNative_userEnableTimeout:跟老API没有区别
- PerfServiceNative_userDisable:还是老的API
- PerfServiceNative_userUnregScn:反注册
1.2.3老API开发指南
指定核和频率PerfServiceNative_userReg
定义一个需要scn_core个核,scn_freq频率运行的任务
原型:
intPerfServiceNative_userReg(
intscn_core,
intscn_freq);
定义于:/mediatek/proprietary/hardware/perfservice/perfservicenative/PerfServiceNative.h
参数:
* scn_core:开多少个核
* scn_freq:频率调整到多少。如果只是希望多开几个核或者少开几个核,并不关注频率的话,可以置成0.
返回值:
* -1:失败
* other:handler,用于后续的操作
注册指定大核小核PerfServiceNative_userRegBigLittle
定义一个需要scn_core个核,scn_freq频率运行的任务
原型:
intPerfServiceNative_userRegBigLittle(
intscn_core_big,
intscn_freq_big,
intscn_core_little,
intscn_freq_little);
定义于:/mediatek/proprietary/hardware/perfservice/perfservicenative/PerfServiceNative.h
参数:
* scn_core_big:开多少个核
* scn_freq_big:频率调整到多少
* scn_core_little:开多少个核
* scn_freq_little:频率调整到多少
返回值:
* -1:失败
* other:handler
反注册
在退出进程之前需要进行反注册
原型:
voidPerfServiceNative_userUnreg(
inthandle);
激活和反激活
注册了之后也不是一直用啊,用的时候再打开吧,使用PerfServiceNative_userEnable。如果一旦忧心有可能出exception之类的流程不能保证走到PerfServiceNative_userDisable的话,也可以加个超时,调用PerfServiceNative_userEnableTimeout.
原型:
voidPerfServiceNative_userEnable(
inthandle);
voidPerfServiceNative_userDisable(
inthandle);
voidPerfServiceNative_userEnableTimeout(
inthandle,
inttimeout);
voidPerfServiceNative_userEnableTimeoutMs(
inthandle,
inttimeout);
参数:
* handle: 注册成功后返回的那个
* timeout: PerfServiceNative_userEnableTimeout是以秒为单位的超时时间,PerfServiceNative_userEnableTimeoutMs则以毫秒为单位。
1.2.4新API开发指南
获取系统能力
intPerfServiceNative_userGetCapability(
intcmd);
参数:
* cmd: 请参见下面的枚举值:
enum {
CMD_GET_CPU_FREQ_LEVEL_COUNT =
0,
CMD_GET_CPU_FREQ_LITTLE_LEVEL_COUNT =
1,
CMD_GET_CPU_FREQ_BIG_LEVEL_COUNT =
2,
CMD_GET_GPU_FREQ_LEVEL_COUNT =
3,
CMD_GET_MEM_FREQ_LEVEL_COUNT =
4,
};
- CMD_GET_CPU_FREQ_LEVEL_COUNT:获取CPU频率级别
- CMD_GET_CPU_FREQ_LITTLE_LEVEL_COUNT:获取小核CPU频率级别
- CMD_GET_CPU_FREQ_BIG_LEVEL_COUNT:获取大核CPU频率级别
- CMD_GET_GPU_FREQ_LEVEL_COUNT:获取GPU频率级别
- CMD_GET_MEM_FREQ_LEVEL_COUNT:获取内存频率级别
注册
因为新的API还需要指定配置,所以注册获取handle就不需要参数了。
原型:
int PerfServiceNative_userRegScn();
反注册
反注册PerfServiceNative_userRegScn注册的handle。注意,跟PerfServiceNative_userUnreg不一样啊。
voidPerfServiceNative_userUnregScn(
inthandle);
配置
原型:
void PerfServiceNative_userRegScnConfig(
int handle,
int cmd,
int param_1,
int param_2,
int param_3,
int param_4);
参数:
* handle:PerfServiceNative_userRegScn注册的handle。
* cmd:命令
* param_1, param_2, param_3, param_4:根据命令不同的参数
命令请参见下面的枚举:
enum {
CMD_SET_CPU_CORE_MIN =0,
CMD_SET_CPU_CORE_MAX =1,
CMD_SET_CPU_CORE_BIG_LITTLE_MIN =2,
CMD_SET_CPU_CORE_BIG_LITTLE_MAX = 3,
CMD_SET_CPU_FREQ_MIN = 4,
CMD_SET_CPU_FREQ_MAX = 5,
CMD_SET_CPU_FREQ_BIG_LITTLE_MIN = 6,
CMD_SET_CPU_FREQ_BIG_LITTLE_MAX = 7,
CMD_SET_GPU_FREQ_MIN = 8,
CMD_SET_GPU_FREQ_MAX = 9,
CMD_SET_MEM_FREQ_MIN = 10,
CMD_SET_MEM_FREQ_MAX = 11,
CMD_SET_VCORE = 12,
CMD_SET_SCREEN_OFF_STATE = 13,
CMD_SET_CPUFREQ_HISPEED_FREQ = 14,
CMD_SET_CPUFREQ_MIN_SAMPLE_TIME = 15,
CMD_SET_CPUFREQ_ABOVE_HISPEED_DELAY =16,
};
- CMD_SET_CPU_CORE_MIN:设置最少核数.参数1个 - param_1:核数
- CMD_SET_CPU_CORE_MAX:设置最大核数.参数1个 - param_1:核数
- CMD_SET_CPU_CORE_BIG_LITTLE_MIN:设置最少大小核数.参数2个 - param_1:大核数,param_2:小核数
- CMD_SET_CPU_CORE_BIG_LITTLE_MAX:设置最大大小核数.参数2个 - param_1:大核数,param_2:小核数
- CMD_SET_CPU_FREQ_MIN:设置最低频率.参数1个 - param_1:频率
- CMD_SET_CPU_FREQ_MAX:设置最高频率.参数1个 - param_1:频率
- CMD_SET_CPU_FREQ_BIG_LITTLE_MIN:设置最低大小核数.参数2个 - param_1:大核频率,param_2:小核频率
- CMD_SET_CPU_FREQ_BIG_LITTLE_MAX:设置最高大小核数.参数2个 - param_1:大核频率,param_2:小核频率
- CMD_SET_GPU_FREQ_MIN:设置GPU最低频率级别,参数1个 - param_1:频率级别
- CMD_SET_GPU_FREQ_MAX:不支持
- CMD_SET_MEM_FREQ_MIN:不支持
- CMD_SET_MEM_FREQ_MAX:不支持
- CMD_SET_VCORE:设置图形模式,参数1个:DRAM模式:0-默认模式,1-低功耗模式,2-还是默认模式,3-高性能模式
- CMD_SET_SCREEN_OFF_STATE:设置关屏模式,一个参数,模式值。0-关屏无效,1-关屏有效,2-关屏暂停,打开恢复
- CMD_SET_CPUFREQ_HISPEED_FREQ:设置高速频率,一个参数。
- CMD_SET_CPUFREQ_MIN_SAMPLE_TIME:设置最小采样值,一个参数。
- CMD_SET_CPUFREQ_ABOVE_HISPEED_DELAY:设置above speed hispeed,一个参数。
开关屏的参数,请使用下面的枚举值:
enum {
SCREEN_OFF_DISABLE = 0,
SCREEN_OFF_ENABLE = 1,
SCREEN_OFF_WAIT_RESTORE = 2,
};
1.3Java调用PerfService
1.3.1步骤
- import IPerfServiceWrapper和PerfServiceWrapper
- 注册用户场景IPerfServiceWrapper.userReg
- 激活用户场景IPerfServiceWrapper.userEnable
- 执行用户场景
- 反激活用户场景IPerfServiceWrapper.userDisable
- 反注册用户场景IPerfServiceWrapper.userUnreg
IPerfServiceWrapper定义于
/frameworks/base/core/Java/com/mediatek/perfservice/IPerfServiceWrapper.java
1.3.2老API的步骤
老API只能对CPU做调度,但是好处是可以直接指定开几个核,频率调到多少,还可以控制开大核还是小核。
- IPerfServiceWrapper.userReg可以指定几个核和多高的频率
- IPerfServiceWrapper.userRegBigLittle还可以用来指定调度大小核
- IPerfServiceWrapper.userEnable用来激活上面注册的场景,IPerfServiceWrapper.userEnableTimeout可以指定激活的超时时间
- IPerfServiceWrapper.userDisable用来反激活
- IPerfServiceWrapper.userUnreg反注册
1.3.3新API的步骤
新的API也可以调节GPU,但是采用的方式要复杂一些,就不再像老API一样直接指定核和频率了,需要定义配置
- IPerfServiceWrapper.userRegScn:没有参数,直接注册就好
- IPerfServiceWrapper.userRegScnConfig:用这个函数去真正指定配置
- IPerfServiceWrapper.userEnable/IPerfServiceWrapper.userEnableTimeout:跟老API没有区别
- IPerfServiceWrapper.userDisable:还是老的API
- IPerfServiceWrapper.userUnregScn:反注册
1.3.4老API开发指南
指定核和频率PerfServiceNative_userReg
定义一个需要scn_core个核,scn_freq频率运行的任务
原型:
publicintuserReg(
int scn_core,
int scn_freq);
参数:
* scn_core:开多少个核
* scn_freq:频率调整到多少。如果只是希望多开几个核或者少开几个核,并不关注频率的话,可以置成0.
返回值:
* -1:失败
* other:handler,用于后续的操作
注册指定大核小核PerfServiceNative_userRegBigLittle
定义一个需要scn_core个核,scn_freq频率运行的任务
原型:
publicintuserRegBigLittle(
int scn_core_big,
int scn_freq_big,
int scn_core_little,
int scn_freq_little);
参数:
* scn_core_big:开多少个核
* scn_freq_big:频率调整到多少
* scn_core_little:开多少个核
* scn_freq_little:频率调整到多少
返回值:
* -1:失败
* other:handler
反注册
在退出进程之前需要进行反注册
原型:
publicvoiduserUnreg(
int handle);
激活和反激活
注册了之后也不是一直用啊,用的时候再打开吧,使用PerfServiceNative_userEnable。如果一旦忧心有可能出exception之类的流程不能保证走到PerfServiceNative_userDisable的话,也可以加个超时,调用PerfServiceNative_userEnableTimeout.
原型:
publicvoiduserEnable(int handle);
publicvoiduserEnableTimeout(int handle, int timeout);
publicvoiduserEnableTimeoutMs( int handle, int timeout_ms);
publicvoiduserDisable ( int handle);
参数:
* handle: 注册成功后返回的那个
* timeout: PerfServiceNative_userEnableTimeout是以秒为单位的超时时间,PerfServiceNative_userEnableTimeoutMs则以毫秒为单位。
1.3.5新API开发指南
获取系统能力
publicintuserGetCapability ( int cmd);
参数:
* cmd: 请参见下面的常量值:
publicstaticfinalint CMD_GET_CPU_FREQ_LEVEL_COUNT = 0 ;
publicstaticfinalint CMD_GET_CPU_FREQ_LITTLE_LEVEL_COUNT = 1 ;
publicstaticfinalint CMD_GET_CPU_FREQ_BIG_LEVEL_COUNT = 2 ;
publicstaticfinalint CMD_GET_GPU_FREQ_LEVEL_COUNT = 3 ;
publicstaticfinalint CMD_GET_MEM_FREQ_LEVEL_COUNT = 4 ;
- CMD_GET_CPU_FREQ_LEVEL_COUNT:获取CPU频率级别
- CMD_GET_CPU_FREQ_LITTLE_LEVEL_COUNT:获取小核CPU频率级别
- CMD_GET_CPU_FREQ_BIG_LEVEL_COUNT:获取大核CPU频率级别
- CMD_GET_GPU_FREQ_LEVEL_COUNT:获取GPU频率级别
- CMD_GET_MEM_FREQ_LEVEL_COUNT:获取内存频率级别
注册
因为新的API还需要指定配置,所以注册获取handle就不需要参数了。
原型:
publicintuserRegScn ();
反注册
反注册PerfServiceNative_userRegScn注册的handle。注意,跟PerfServiceNative_userUnreg不一样啊。
原型:
publicvoiduserUnregScn ( int handle);
配置
原型:
publicvoiduserRegScnConfig ( int handle, int cmd, int param_1, int param_2, int param_3, int param_4);
参数:
* handle:PerfServiceNative_userRegScn注册的handle。
* cmd:命令
* param_1, param_2, param_3, param_4:根据命令不同的参数
命令请参见下面的常量:
publicstaticfinalint CMD_SET_CPU_CORE_MIN = 0;
publicstaticfinalint CMD_SET_CPU_CORE_MAX = 1;
publicstaticfinalint CMD_SET_CPU_CORE_BIG_LITTLE_MIN = 2;
publicstaticfinalint CMD_SET_CPU_CORE_BIG_LITTLE_MAX =3;
publicstaticfinalint CMD_SET_CPU_FREQ_MIN = 4;
publicstaticfinalint CMD_SET_CPU_FREQ_MAX = 5;
publicstaticfinalint CMD_SET_CPU_FREQ_BIG_LITTLE_MIN = 6;
publicstaticfinalint CMD_SET_CPU_FREQ_BIG_LITTLE_MAX = 7;
publicstaticfinalint CMD_SET_GPU_FREQ_MIN = 8;
publicstaticfinalint CMD_SET_GPU_FREQ_MAX = 9;
publicstaticfinalint CMD_SET_MEM_FREQ_MIN = 10;
publicstaticfinalint CMD_SET_MEM_FREQ_MAX = 11;
publicstaticfinalint CMD_SET_SCREEN_OFF_STATE = 12;
publicstaticfinalint CMD_SET_CPUFREQ_HISPEED_FREQ = 13;
publicstaticfinalint CMD_SET_CPUFREQ_MIN_SAMPLE_TIME = 14;
publicstaticfinalint CMD_SET_CPUFREQ_ABOVE_HISPEED_DELAY = 15;
publicstaticfinalint CMD_SET_VCORE = 16;
- CMD_SET_CPU_CORE_MIN:设置最少核数.参数1个 - param_1:核数
- CMD_SET_CPU_CORE_MAX:设置最大核数.参数1个 - param_1:核数
- CMD_SET_CPU_CORE_BIG_LITTLE_MIN:设置最少大小核数.参数2个 - param_1:大核数,param_2:小核数
- CMD_SET_CPU_CORE_BIG_LITTLE_MAX:设置最大大小核数.参数2个 - param_1:大核数,param_2:小核数
- CMD_SET_CPU_FREQ_MIN:设置最低频率.参数1个 - param_1:频率
- CMD_SET_CPU_FREQ_MAX:设置最高频率.参数1个 - param_1:频率
- CMD_SET_CPU_FREQ_BIG_LITTLE_MIN:设置最低大小核数.参数2个 - param_1:大核频率,param_2:小核频率
- CMD_SET_CPU_FREQ_BIG_LITTLE_MAX:设置最高大小核数.参数2个 - param_1:大核频率,param_2:小核频率
- CMD_SET_GPU_FREQ_MIN:设置GPU最低频率级别,参数1个 - param_1:频率级别
- CMD_SET_GPU_FREQ_MAX:不支持
- CMD_SET_MEM_FREQ_MIN:不支持
- CMD_SET_MEM_FREQ_MAX:不支持
- CMD_SET_VCORE:设置图形模式,参数1个:DRAM模式:0-默认模式,1-低功耗模式,2-还是默认模式,3-高性能模式
- CMD_SET_SCREEN_OFF_STATE:设置关屏模式,一个参数,模式值。0-关屏无效,1-关屏有效,2-关屏暂停,打开恢复
- CMD_SET_CPUFREQ_HISPEED_FREQ:设置高速频率,一个参数。
- CMD_SET_CPUFREQ_MIN_SAMPLE_TIME:设置最小采样值,一个参数。
- CMD_SET_CPUFREQ_ABOVE_HISPEED_DELAY:设置above speed hispeed,一个参数。
1.3.6Java调用例
WebView中的应用例
例:
publicvoidloadData(String data, String mimeType, String encoding) {
checkThread();
if (TRACE) Log.d(LOGTAG, "loadData");
/// M:PerfBoost include @{
if (sFirstLoadData) {
int maxFreq = 0;
try {
String freqFile = "/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq";
RandomAccessFile reader = newRandomAccessFile(freqFile, "r");
String stringMaxFreq = reader.readLine();
reader.close();
maxFreq = Integer.parseInt(stringMaxFreq);
}
catch(IOException | NumberFormatException e) {
e.printStackTrace();
}
if (maxFreq != 0) {
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 = newHandler();
handler.postDelayed(new Runnable() {
@Override
publicvoidrun() {
sPerfService.userUnreg(sPerfHandle);
}
},
600);
}
}
}
sFirstLoadData = false
;
}
/// @}
mProvider.loadData(data, mimeType, encoding);
}
AmS和WmS中的应用例
下面是/frameworks/base/services/core/java/com/Android/server/am/ActivityStack.java中定义的perfBoost的两个方法,一个是perfBoostResume,另一个是perfBoostPause.
这个就是下节我们要介绍的SCN_APP_SWITCH场景。
privatevoidperfBoostResume() {
if (mPerfService == null) {
mPerfService = new PerfServiceWrapper(null);
}
if (mPerfService != null) {
Trace.asyncTraceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "amPerfBoost", 0);
if (DEBUG_PERFSRV) {Slog.d(TAG, "boostEnableTimeoutMs(" + IPerfServiceWrapper.SCN_APP_SWITCH + ") cross app");
}
mPerfService.boostEnableTimeoutMs(IPerfServiceWrapper.SCN_APP_SWITCH, BOOST_ENABLE_TIMEOUT);
}
else{Slog.e(TAG, "PerfService is not ready!");
}
}
publicvoidperfBoostPause() {
if (mPerfService == null) {
mPerfService = new PerfServiceWrapper(null);
}
if (mPerfService != null) {
if (DEBUG_PERFSRV) {Slog.d(TAG, "boostDisable(" + IPerfServiceWrapper.SCN_APP_SWITCH + ") cross app"); }
mPerfService.boostDisable(IPerfServiceWrapper.SCN_APP_SWITCH);
Trace.asyncTraceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER, "amPerfBoost", 0);
}
else{
Slog.e(TAG, "perfBoostPause, PerfService is not ready!");
}
}
我们再看一个
if (!mIsPerfBoostEnable) {
if (mPerfService == null) {
mPerfService = new PerfServiceWrapper(null);
}
mPerfService.boostEnable(IPerfServiceWrapper.SCN_APP_ROTATE);
mIsPerfBoostEnable = true;
}
1.4MTK预定义的一些场景
MediaTek预定义了这么多API,当然它自己也会有自己的预定义场景,这些场景就不需要再定义了。
1.4.1 libperfservice.so中预定义的场景
场景 | cpu核数 | cpu频率 | UI操作 |
SCN_APP_SWITCH | 2 | - | app启动、退出 |
SCN_APP_ROTATE | 2 | - | app rotate |
SCN_APP_TOUCH | 2 | 169000 | touch |
但是,这个值肯定不是在所有平台上都是最优的值啊,所以MTK也提供了客户定制化的机制。
1.4.2定制预定义场景
定义于/vendor/mediatek/proprietary/hardware/perfservice/mt[xxxx]/scn_tbl/perfservscntbl.txt中。
我们以MT6735为例,来看一看具体的内容,定义于/vendor/mediatek/proprietary/hardware/perfservice/mt6735/scn_tbl/perfservscntbl.txt中。
CMD_SET_CPU_CORE, SCN_APP_TOUCH, 3
CMD_SET_CPU_FREQ, SCN_APP_TOUCH, 819000
CMD_SET_CPU_CORE, SCN_SW_FRAME_UPDATE, 3
CMD_SET_CPU_FREQ, SCN_SW_FRAME_UPDATE, 819000
CMD_SET_CPU_CORE, SCN_APP_SWITCH, 4
CMD_SET_CPU_FREQ, SCN_APP_SWITCH, 1300000
CMD_SET_CPU_UP_THRESHOLD, SCN_SW_FRAME_UPDATE, 80
CMD_SET_CPU_DOWN_THRESHOLD, SCN_SW_FRAME_UPDATE, 65
CMD_SET_CPU_CORE, SCN_APP_LAUNCH, 4
CMD_SET_CPU_FREQ, SCN_APP_LAUNCH, 1300000
1.4.3白名单
定义于:/vendor/mediatek/proprietary/hardware/perfservice/mt[xxxx]/app_list/perfservapplist.txt
格式:包名核数
例:
com.imangi.templerun2
3
1.5MTK平台控制CPU核心和频率的程序(源代码)
之前的满血工具MTKboost,时间有限不打算研究下去了,正好也有人需要,就开源供有兴趣朋友试试
不root控制的原理是利用了MTK平台的perfservice服务
一般6595之后的机器都会支持(具体看/system/lib/下有没有libperfservice.so和libperfservicenative.so)
6595的话,Flyme5之后似乎是支持的,之前的旧版不行。
原理上参考https://yq.aliyun.com/articles/26696 这篇文章
个人只是做了一点微小的工作,抓log试了几个针对6797的参数
最近时间有限不打算研究下去了,正好也有人需要,就开源供有兴趣朋友试试
源码地址: http://pan.baidu.com/s/1hs0MAtm
其中Native文件夹是C写的原生代码部分。
说明:
*注意,频率单位均为kHz
Native界面的3个函数:
resetCPU();取消所有的profile设置
setCPU(intbigNum, int bigFreq, int littleNum, int littleFreq);
旧版API:设置CPU大小核上线数量和频率
对于三集群的MT6797,只能设置高频A53 cluster和低频A53cluster,无法控制A72
bigNum: 大核心上线数量
bigFreq:大核心频率
littleNum:小核心上线数量
littleFreq:小核心频率
对于MT6795这类,8个核心全部为小核心,则需要设置littleNum=8才能8核全开
setCluster(intcmd, int p1, int p2, int p3, int p4);
新版API:
cmd为命令,p1,p2,p3, p4为参数
cmd:2 设置最少大小核数,对于6797为高配A53和低频A53
参数2个 - param_1:大核数,param_2:小核数
例如: setCluster(2, bigNum, littleNum,0,0);
cmd:3 设置最多大小核数,对于6797为高配A53和低频A53
参数2个 - param_1:大核数,param_2:小核数
例如: setCluster(3, bigNum, littleNum,0,0);
cmd:8 设置GPU最低频率级别
参数1个 - param_1:频率级别,级别越大,频率越高
例如: setCluster(8, gpu, 0,0,0);
由于上述文章和目前可供下载到的代码不是很新,并不支持MT6797三丛集
下面几个参数是文章中没有提供的,个人通过在6797平台上抓log试出来的
cmd:17 设置特定cluster的最小频率
参数2个 - param_1:cluster序号,param_2:频率
对于MT6797:
低频A53: cluster 0
高频A53: cluster 1
A72: cluster 2
例如:
setCluster(17, 0, litteSFreq,0,0);
setCluster(17, 1, litteFreq,0,0);
setCluster(17, 2, bigFreq,0,0);
cmd:18 设置特定cluster的最大频率
参数2个 - param_1:cluster序号,param_2:频率
对于MT6797:
低频A53: cluster 0
高频A53: cluster 1
A72: cluster 2
例如:
setCluster(17, 0, litteSFreq,0,0);
setCluster(17, 1, litteFreq,0,0);
setCluster(17, 2, bigFreq,0,0);
cmd:23 设置整体系统性能
MT6797利用此命令去开启A72
参数1个 - param_1:系统性能级别,貌似是30到1000的整数
例如:
setCluster(23, 800, 0, 0, 0); //开启8个A53+1个A72,满频
setCluster(23, 1000, 0, 0, 0); //开启8个A53+2个A72,满频(安兔兔模式)
====
目前尚无发现直接对A72 cluster的核心数进行设置的命令
因此先采用cmd 23开启需要数量的A72,再对低频和高频A53的核心数进行限制
最后在对3个cluster的频率进行限制
例如:
//开启1个A72
if(bigN==1){
//强开8A53+1A72
setCluster(23, 800,0,0,0);
//设置低频高频A53最小核心数
setCluster(2, littleN,littleSN,0,0);
//设置低频高频A53最多核心数
setCluster(3, littleN,littleSN,0,0);
//18: 设置3个cluster的最大频率
setCluster(18, 0,litteSF* 1000,0,0);
setCluster(18, 1,litteF* 1000,0,0);
setCluster(18, 2,bigF* 1000,0,0);
//17: 设置3个cluster的最小频率
setCluster(17, 0,litteSF* 1000,0,0);
setCluster(17, 1,litteF* 1000,0,0);
setCluster(17, 2,bigF* 1000,0,0);
}
if(bigN ==2){
//强开8A53+2A72,安兔兔模式
setCluster(23, 1000,0,0,0);
//设置低频高频A53最小核心数
setCluster(2, littleN,littleSN,0,0);
//设置低频高频A53最多核心数
setCluster(3, littleN,littleSN,0,0);
//18: 设置3个cluster的最大频率
setCluster(18, 0,litteSF* 1000,0,0);
setCluster(18, 1,litteF* 1000,0,0);
setCluster(18, 2,bigF* 1000,0,0);
//17: 设置3个cluster的最小频率
setCluster(17, 0,litteSF* 1000,0,0);
setCluster(17, 1,litteF* 1000,0,0);
setCluster(17, 2,bigF* 1000,0,0);
}
====================================
目前的问题:
0. 关闭屏幕会进入低功耗模式,清除原有的设置,这是系统限制。
1. MTK或者厂家预先定义了部分场景,比如微博强制不开A72
在进入这些app后,perfservice的status会被该app的预定义场景覆盖
比如好好的满血状态,进微博A72就下线了,回桌面又会上线。
2. 经过测试,cmd:23设置整体系统性能中的参数=1000(安兔兔模式)具有最高优先级
因此满血状态可以有效保持。
但在MT6797上,通过新API设置成各个cluster的频率和上线数量后,在MTKboost APP内没有问题,但返回桌面时系统似乎会通过perfservice重新设置A53/A72的数量和频率,导致设置在MTKboost APP外变的无效。(优先级不如安兔兔模式来的高)
2.MTK平台CPU/GPU动态调频的实现之PerfService的源码分析
1.
}
再看PerfServiceImpl类的实现:
[java] view plain copy
1. public class PerfServiceImpl extends IPerfService.Stub {
2.
3. private static final String TAG = "PerfService";
4.
5. private IPerfServiceManager perfServiceMgr;
6. final Context mContext;
7.
8. // 接收锁屏/开屏的广播
9. class PerfServiceBroadcastReceiver extends android.content.BroadcastReceiver {
10. @Override
11. public void onReceive(Context context, Intent intent) {
12. final String action = intent.getAction();
13. if (Intent.ACTION_SCREEN_OFF.equals(action)) {
14. log("Intent.ACTION_SCREEN_OFF");
15. perfServiceMgr.userDisableAll();
16. return;
17. }
18. else if (Intent.ACTION_SCREEN_ON.equals(action)) {
19. log("Intent.ACTION_SCREEN_ON");
20. perfServiceMgr.userRestoreAll();
21. return;
22. }
23. else {
24. log("Unexpected intent " + intent);
25. }
26. }
27. }
28.
29. public PerfServiceImpl(Context context, IPerfServiceManager pm) {
30. perfServiceMgr = pm;
31. mContext = context;
32.
33. final IntentFilter broadcastFilter = new IntentFilter();
34. broadcastFilter.addAction(Intent.ACTION_SCREEN_OFF);
35. broadcastFilter.addAction(Intent.ACTION_SCREEN_ON);
36. mContext.registerReceiver(new PerfServiceBroadcastReceiver(), broadcastFilter);
37.
38. }
39.
40. // aidl中声明的其他方法
41. . . .
42.
43. public void notifyAppState(java.lang.String packName, java.lang.String className,
44. int state, int pid) {
45. //log("notifyAppState");
46. // 调用PerfServiceManager中的方法,最后调用的是native方法
47. perfServiceMgr.notifyAppState(packName, className, state, pid);
48. }
49.
50. . . .
51.
52. private void log(String info) {
53. Log.d("@M_" + TAG, "[PerfService] " + info + " ");
54. }
55.
56. private void loge(String info) {
57. Log.e("@M_" + TAG, "[PerfService] ERR: " + info + " ");
58. }
59. }
另外:
在vendor\mediatek\proprietary\hardware\perfservice\mt**\app_list目录下的perfservapplist.txt文件中可以自定义应用白名单,默认值为:
CMD_SET_CPU_CORE_MINcom.imangi.templerun2 3
意思是用户使用“神庙逃亡”应用时,CPU最少核心数为3
在vendor\mediatek\proprietary\hardware\perfservice\mt**\scn_tbl目录下的perfservscntbl.txt文件中可以自定义场景,默认场景有:
CMD_SET_CPU_CORE_MIN,SCN_APP_TOUCH, 3
CMD_SET_CPU_FREQ_MIN, SCN_APP_TOUCH, 1014000
CMD_SET_CPU_CORE_MIN, SCN_SW_FRAME_UPDATE, 3
CMD_SET_CPU_FREQ_MIN, SCN_SW_FRAME_UPDATE, 1014000
CMD_SET_CPU_UP_THRESHOLD, SCN_SW_FRAME_UPDATE, 80
CMD_SET_CPU_DOWN_THRESHOLD, SCN_SW_FRAME_UPDATE, 65
CMD_SET_CPU_FREQ_BIG_LITTLE_MIN, SCN_APP_SWITCH, 1950000, 1144000
CMD_SET_CPU_CORE_BIG_LITTLE_MIN, SCN_APP_SWITCH, 4, 0
CMD_SET_VCORE, SCN_APP_SWITCH, 3
CMD_SET_CPU_FREQ_BIG_LITTLE_MIN, SCN_APP_ROTATE, 1950000, 1144000
CMD_SET_VCORE, SCN_APP_ROTATE, 3
CMD_SET_VCORE, SCN_GAMING, 1