MTK平臺CPU/GPU動態調頻的實現之PerfService的原始碼分析
Zygote程序啟動後會啟動System程序,在System程序啟動過程中會啟動系統中的關鍵服務,如AMS、PMS以及這裡要分析的PerfService。先看下流程圖:
SystemServer啟動PerfService服務是通過例項化PerfServiceImpl的物件perfService,並把該服務的Binder物件新增到ServiceManager中。
先看SystemServer類中的startOtherServices方法:
再看PerfServiceStateNotifier類,先看下它實現的介面IActivityStateNotifier:private void startOtherServices() { . . . PerfServiceStateNotifier perfServiceNotifier = null; IPerfServiceManager perfServiceMgr = null; . . . if (mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL) { . . . /// M: add for PerfService feature @{ if (SystemProperties.get("ro.mtk_perfservice_support").equals("1")) { try { Slog.i(TAG, "PerfService state notifier"); // 例項化PerfService的狀態通知者 perfServiceNotifier = new PerfServiceStateNotifier(); // 把通知者註冊到AMS的觀察者中,有狀態變化時會通知所有註冊過的通知者 mActivityManagerService.registerActivityStateNotifier(perfServiceNotifier); } catch (Throwable e) { Slog.e(TAG, "FAIL starting PerfServiceStateNotifier", e); } // Create PerfService manager thread and add service try { // 例項化PerfServiceManager執行緒 perfServiceMgr = new PerfServiceManager(context); IPerfService perfService = null; // 例項化服務 perfService = new PerfServiceImpl(context, perfServiceMgr); Slog.d("perfservice", "perfService=" + perfService); if (perfService != null) { // 把服務新增到ServiceManager中 ServiceManager.addService(Context.MTK_PERF_SERVICE, perfService.asBinder()); } } catch (Throwable e) { Slog.e(TAG, "perfservice Failure starting PerfService", e); } } /// @} . . . } . . . /// M: add for hdmi feature final IPerfServiceManager perfServiceF = perfServiceMgr; // We now tell the activity manager it is okay to run third party // code. It will call back into us once it has gotten to the state // where third party code can really run (but before it has actually // started launching the initial applications), for us to complete our // initialization. mActivityManagerService.systemReady(new Runnable() { @Override public void run() { Slog.i(TAG, "Making services ready"); . . . /// M: add for PerfService feature @{ if (SystemProperties.get("ro.mtk_perfservice_support").equals("1")) { // Notify PerfService manager of system ready try { Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "MakePerfServiceReady"); // 系統啟動後回撥IPerfServiceManager的systemReady方法 if (perfServiceF != null) perfServiceF.systemReady(); Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER); } catch (Throwable e) { reportWtf("making PerfServiceManager ready", e); } } /// @} . . . } }); . . . }
public interface IActivityStateNotifier { public enum ActivityState { Paused, Resumed, Destroyed, Stopped } /** * Notify activity state change. * * @param packageName The target package name. * @param pid The process id package belongs to. * @param className The class name of the package. * @param actState Current lifecycle state of the package. */ public void notifyActivityState(String packageName, int pid, String className, ActivityState actState); /** * Notify the process of activity has died. * * @param pid The process id has died. * @param packageList The whole packages runs on the process. */ public void notifyAppDied(int pid, HashSet<String> packageList); }
再看PerfServiceStateNotifier類的實現:
// 觀察者模式的使用 public final class PerfServiceStateNotifier implements IActivityStateNotifier { static final String TAG = "PerfServiceStateNotifier"; IPerfServiceWrapper mPerfService; public PerfServiceStateNotifier() { // 例項化PerfServiceWrapper mPerfService = new PerfServiceWrapper(null); } /** * Notify activity state change * Activity狀態變化時回撥該方法 */ public void notifyActivityState(String packageName, int pid, String className, IActivityStateNotifier.ActivityState actState) { int state; //Slog.i(TAG,"[notifyActivityState] "+ packageName+ ", "+ className+ ", "+ actState); switch(actState) { case Paused: state = IPerfServiceWrapper.STATE_PAUSED; break; case Resumed: state = IPerfServiceWrapper.STATE_RESUMED; break; case Destroyed: state = IPerfServiceWrapper.STATE_DESTROYED; break; case Stopped: state = IPerfServiceWrapper.STATE_STOPPED; break; default: return; } // 呼叫mPerfService的狀態變化方法 mPerfService.notifyAppState(packageName, className, state, pid); } /** * Notify the process of activity has died * Activity銷燬時回撥該方法 */ public void notifyAppDied(int pid, HashSet<String> packageList) { Iterator i = packageList.iterator(); while (i.hasNext()) { String packageName = (String) i.next(); // 呼叫mPerfService的狀態變化方法 mPerfService.notifyAppState(packageName, null, IPerfServiceWrapper.STATE_DEAD, pid); } } }
當所監聽的Activity生命週期方法被呼叫時會呼叫PerfServiceWrapper類的notifyAppState方法,那麼下面先看下PerfServiceWrapper實現的介面IPerfServiceWrapper:
public interface IPerfServiceWrapper {
// 已經實現的場景
public static final int SCN_NONE = 0;
public static final int SCN_APP_SWITCH = 1; /* apply for both launch/exit */ // 切換應用
public static final int SCN_APP_ROTATE = 2; // 旋轉應用
public static final int SCN_APP_TOUCH = 3; // 觸控應用,即點選螢幕
public static final int SCN_DONT_USE1 = 4; // 空閒???
public static final int SCN_SW_FRAME_UPDATE = 5; // 重新整理幀率
public static final int SCN_APP_LAUNCH = 6; // 應用啟動 同SCN_APP_SWITCH
public static final int SCN_GAMING = 7; // 遊戲中。。。
public static final int SCN_MAX = 8; /* should be (last scenario + 1) */
public static final int STATE_PAUSED = 0;
public static final int STATE_RESUMED = 1;
public static final int STATE_DESTROYED = 2;
public static final int STATE_DEAD = 3;
public static final int STATE_STOPPED = 4;
public static final int DISPLAY_TYPE_GAME = 0; // 遊戲模式顯示型別
public static final int DISPLAY_TYPE_OTHERS = 1; // 非遊戲模式
public static final int NOTIFY_USER_TYPE_PID = 0;
public static final int NOTIFY_USER_TYPE_FRAME_UPDATE = 1;
public static final int NOTIFY_USER_TYPE_DISPLAY_TYPE = 2;
public static final int NOTIFY_USER_TYPE_SCENARIO_ON = 3;
public static final int NOTIFY_USER_TYPE_SCENARIO_OFF = 4;
public static final int CMD_GET_CPU_FREQ_LEVEL_COUNT = 0; // 獲取CPU頻率級別總數
public static final int CMD_GET_CPU_FREQ_LITTLE_LEVEL_COUNT = 1; // 獲取小核CPU頻率級別總數
public static final int CMD_GET_CPU_FREQ_BIG_LEVEL_COUNT = 2; // 獲取大核CPU頻率級別總數
public static final int CMD_GET_GPU_FREQ_LEVEL_COUNT = 3; // 獲取GPU頻率級別總數
public static final int CMD_GET_MEM_FREQ_LEVEL_COUNT = 4; // 獲取記憶體頻率級別總數
public static final int CMD_GET_PERF_INDEX_MIN = 5; // 獲取效能優化最小索引值
public static final int CMD_GET_PERF_INDEX_MAX = 6; // 獲取效能優化最大索引值
public static final int CMD_GET_PERF_NORMALIZED_INDEX_MAX = 7; // 獲取普通效能優化最大索引值
public static final int CMD_SET_CPU_CORE_MIN = 0; // 設定CPU最少核數
public static final int CMD_SET_CPU_CORE_MAX = 1; // 設定CPU最多核數
public static final int CMD_SET_CPU_CORE_BIG_LITTLE_MIN = 2; // 設定大核小核的最少核數
public static final int CMD_SET_CPU_CORE_BIG_LITTLE_MAX = 3; // 設定大核小核的最多核數
public static final int CMD_SET_CPU_FREQ_MIN = 4; // 設定CPU的最低頻率值
public static final int CMD_SET_CPU_FREQ_MAX = 5; // 設定CPU的最高頻率值
public static final int CMD_SET_CPU_FREQ_BIG_LITTLE_MIN = 6; // 設定大核小核的最低頻率值
public static final int CMD_SET_CPU_FREQ_BIG_LITTLE_MAX = 7; // 設定大核小核的最高頻率值
public static final int CMD_SET_GPU_FREQ_MIN = 8; // 設定GPU的最低頻率值
public static final int CMD_SET_GPU_FREQ_MAX = 9; // 設定GPU的最高頻率值
public static final int CMD_SET_VCORE = 10; // 設定圖形模式,0/2:預設模式,1:低功耗模式,3:高效能模式
public static final int CMD_SET_SCREEN_OFF_STATE = 11; // 設定鎖屏時狀態,0:鎖屏無效,1:鎖屏有效,2:鎖屏暫停,開屏恢復
public static final int CMD_SET_CPUFREQ_HISPEED_FREQ = 12; // 設定CPU高速頻率
public static final int CMD_SET_CPUFREQ_MIN_SAMPLE_TIME = 13; // 設定取樣CPU頻率值的最小間隔時間
public static final int CMD_SET_CPUFREQ_ABOVE_HISPEED_DELAY = 14; // 設定CPU超高速頻率延遲時間
public static final int CMD_SET_CLUSTER_CPU_CORE_MIN = 15; // 設定CPU簇的最少核數
public static final int CMD_SET_CLUSTER_CPU_CORE_MAX = 16; // 設定CPU簇的最多核數
public static final int CMD_SET_CLUSTER_CPU_FREQ_MIN = 17; // 設定CPU簇的最低頻率值
public static final int CMD_SET_CLUSTER_CPU_FREQ_MAX = 18; // 設定CPU簇的最高頻率值
public static final int CMD_SET_ROOT_CLUSTER = 19; // 設定root簇
public static final int CMD_SET_CPU_UP_THRESHOLD = 20; // 設定CPU溫度的最高閾值
public static final int CMD_SET_CPU_DOWN_THRESHOLD = 21; // 設定CPU溫度的最低閾值
public static final int CMD_SET_PERF_INDEX = 22; // 設定效能優化的索引值
public static final int CMD_SET_NORMALIZED_PERF_INDEX = 23; // 設定普通效能優化的索引值
// 其他方法的宣告
. . .
public void notifyAppState(String packName, String className, int state, int pid);
// 其他方法的宣告
. . .
}
再看PerfServiceWrapper類的實現:
public class PerfServiceWrapper implements IPerfServiceWrapper {
private static final String TAG = "PerfServiceWrapper";
private IPerfService sService = null;
private Context mContext;
private int inited = 0;
private int setTid = 0;
private long mPreviousTime = 0;
private static final int RENDER_THREAD_UPDATE_DURATION = 400;
public static native int nativeGetPid();
public static native int nativeGetTid();
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..");
}
}
}
public PerfServiceWrapper(Context context) {
mContext = context;
init();
}
// 其他介面中宣告方法的實現
. . .
public void notifyAppState(String packName, String className, int state, int pid) {
//log("boostEnable");
try {
init();
if (sService != null)
// 呼叫sService的notifyAppState方法
sService.notifyAppState(packName, className, state, pid);
} catch (RemoteException e) {
loge("ERR: RemoteException in notifyAppState:" + e);
}
}
// 其他介面中宣告方法的實現
. . .
private void log(String info) {
Log.d("@M_" + TAG, "[PerfServiceWrapper] " + info + " ");
}
private void loge(String info) {
Log.e("@M_" + TAG, "[PerfServiceWrapper] ERR: " + info + " ");
}
}
該類中的方法都是通過Binder程序間通訊方式呼叫PerfServiceImpl中的方法實現的。由下面分析知,最後呼叫的是PerfServiceManager中的方法。
下面看PerfServiceManager的例項化過程,該類實現了IPerfServiceManager介面:
public class PerfServiceManager implements IPerfServiceManager {
private static final String TAG = "PerfServiceManager";
private HandlerThread mHandlerThread;
private PerfServiceThreadHandler mHandler;
private Context mContext;
final List<Integer> mTimeList;
private boolean bDuringTouch;
private boolean bRenderAwareValid; // render aware is only valid within 3 sec.渲染只在3秒內有效
private static final int RENDER_AWARE_DURATION_MS = 3000;
private static final int UI_UPDATE_DURATION_MS = 500;
private static final int RENDER_BIT = 0x800000;
private static final float HEAP_UTILIZATION_DURING_FRAME_UPDATE = 0.5f; // 重新整理幀時的堆疊利用率
private int mDisplayType;
private VMRuntime mRuntime;
private float mDefaultUtilization;
// 宣告的一些native方法,追蹤到native層後,MTK只提供了一個so庫,具體實現是看不到的。。。
. . .
public static native int nativePerfNotifyAppState(String packName, String className,
int state, int pid);
// 宣告的一些native方法
. . .
public class PerfServiceAppState {
private String mPackName;
private String mClassName;
private int mState;
private int mPid;
PerfServiceAppState(String packName, String className, int state, int pid) {
mPackName = packName;
mClassName = className;
mState = state;
mPid = pid;
}
}
//static
//{
// Log.w(TAG, "load libperfservice_jni.so");
// System.loadLibrary("perfservice_jni");
//}
public PerfServiceManager(Context context) {
super();
mContext = context;
// 建立並開啟名為PerfServiceManager的執行緒
mHandlerThread = new HandlerThread("PerfServiceManager", Process.THREAD_PRIORITY_FOREGROUND);
mHandlerThread.start();
Looper looper = mHandlerThread.getLooper();
if (looper != null) {
// 初始化Handler
mHandler = new PerfServiceThreadHandler(looper);
}
mTimeList = new ArrayList<Integer>();
bDuringTouch = false;
bRenderAwareValid = false;
// 預設顯示型別:非遊戲模式
mDisplayType = IPerfServiceWrapper.DISPLAY_TYPE_OTHERS;
mRuntime = VMRuntime.getRuntime();
mDefaultUtilization = mRuntime.getTargetHeapUtilization();
log("Created and started PerfService thread");
}
// 介面中其他方法的實現
. . .
public void notifyAppState(String packName, String className, int state, int pid) {
//log("notifyAppState");
Message msg = mHandler.obtainMessage();
msg.what = PerfServiceThreadHandler.MESSAGE_NOTIFY_APP_STATE;
msg.obj = new PerfServiceAppState(packName, className, state, pid);
msg.sendToTarget();
}
. . .
private class PerfServiceThreadHandler extends Handler {
. . .
private static final int MESSAGE_NOTIFY_APP_STATE = 4;
. . .
public PerfServiceThreadHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
try {
switch (msg.what) {
. . .
case MESSAGE_NOTIFY_APP_STATE:
{
PerfServiceAppState passedObject = (PerfServiceAppState) msg.obj;
//log("MESSAGE_NOTIFY_APP_STATE");
// 通過呼叫native方法實現
nativePerfNotifyAppState(passedObject.mPackName, passedObject.mClassName,
passedObject.mState, passedObject.mPid);
passedObject = null;
msg.obj = null;
break;
}
. . .
default:
{
. . .
}
}
} catch (NullPointerException e) {
loge("Exception in PerfServiceThreadHandler.handleMessage: " + e);
}
}
. . .
}
private void log(String info) {
Log.d("@M_" + TAG, "[PerfService] " + info + " ");
}
private void loge(String info) {
Log.e("@M_" + TAG, "[PerfService] ERR: " + info + " ");
}
}
再看PerfServiceImpl類的實現:
public class PerfServiceImpl extends IPerfService.Stub {
private static final String TAG = "PerfService";
private IPerfServiceManager perfServiceMgr;
final Context mContext;
// 接收鎖屏/開屏的廣播
class PerfServiceBroadcastReceiver extends android.content.BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (Intent.ACTION_SCREEN_OFF.equals(action)) {
log("Intent.ACTION_SCREEN_OFF");
perfServiceMgr.userDisableAll();
return;
}
else if (Intent.ACTION_SCREEN_ON.equals(action)) {
log("Intent.ACTION_SCREEN_ON");
perfServiceMgr.userRestoreAll();
return;
}
else {
log("Unexpected intent " + intent);
}
}
}
public PerfServiceImpl(Context context, IPerfServiceManager pm) {
perfServiceMgr = pm;
mContext = context;
final IntentFilter broadcastFilter = new IntentFilter();
broadcastFilter.addAction(Intent.ACTION_SCREEN_OFF);
broadcastFilter.addAction(Intent.ACTION_SCREEN_ON);
mContext.registerReceiver(new PerfServiceBroadcastReceiver(), broadcastFilter);
}
// aidl中宣告的其他方法
. . .
public void notifyAppState(java.lang.String packName, java.lang.String className,
int state, int pid) {
//log("notifyAppState");
// 呼叫PerfServiceManager中的方法,最後呼叫的是native方法
perfServiceMgr.notifyAppState(packName, className, state, pid);
}
. . .
private void log(String info) {
Log.d("@M_" + TAG, "[PerfService] " + info + " ");
}
private void loge(String info) {
Log.e("@M_" + TAG, "[PerfService] ERR: " + info + " ");
}
}
另外:
在vendor\mediatek\proprietary\hardware\perfservice\mt**\app_list目錄下的perfservapplist.txt檔案中可以自定義應用白名單,預設值為:
CMD_SET_CPU_CORE_MIN com.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