曾經反編譯過某廠商的framework代碼,結合廠商機器的表現,發現了進程內存管理的部分邏輯,記錄如下:
之前一直懷疑某廠商的AMS.updateOomAdjLocked()方法中,添加了進程管理邏輯,
結果是進程管理的代碼還沒覈實,倒是找到了運行時proc reclaim邏輯,
在反編譯的AMS.updateOomAdjLocked()方法中,發現以下邏輯:
try
{
if ((ActivityManagerDebugConfig.DEBUG_SWITCH) || ( ActivityManagerDebugConfig.DEBUG_OOM_ADJ)) {
Slog.v(TAG_OOM_ADJ, "Trimming memory of " + localIndexOutOfBoundsException1.processName + " to " + i1);
}
SmartShrinker.reclaim(localIndexOutOfBoundsException1.pid, 4);
localIndexOutOfBoundsException1.thread.scheduleTrimMemory(i1);
}
catch (RemoteException localRemoteException5)
我看了下SmartShrinker的實現,主體邏輯:
public static final void reclaim(int paramInt1, int paramInt2)
{
if (ENABLE)
{
ProcessList.callProcReclaim(paramInt1, paramInt2);
Log.w("RMS.SmartShrinker", "SmartShrinker is runing in pid =" + paramInt1 + " reclaim mode = " + paramInt2);
}
}
再看下callProcReclaim方法:
public static final void callProcReclaim(int paramInt1, int paramInt2)
{
long l1 = SystemClock.elapsedRealtime();
ByteBuffer localByteBuffer = ByteBuffer.allocate(16);
localByteBuffer.putInt(54);
localByteBuffer.putInt(paramInt1);
localByteBuffer.putInt(paramInt2);
writeLmkd(localByteBuffer);
long l2 = SystemClock.elapsedRealtime();
if (l2 - l1 > 250L) {
Slog.w("ActivityManager", "SLOW call process reclaim: " + (l2 - l1));
}
}
由此可見這個策略是進程級別的proc reclaim,
運行時的proc reclaim由屬性ro.config.hw_smart_shrink控制,
boolean bool = SystemProperties.getBoolean(“ro.config.hw_smart_shrink”, false)
在高端機上沒有開,此屬性沒有設置,而在中低端機上設置爲true
[ro.config.hw_smart_shrink]: [true]
運行時的proc reclaim時機?
全局搜了下,在AMS的兩個接口中,updateOomAdjLocked和cleanUpRemovedTaskLocked
./com/android/server/am/ActivityManagerService.smali:12332: invoke-static {v13, v14}, Lcom/android/server/SmartShrinker;->reclaim(II)V
./com/android/server/am/ActivityManagerService.smali:115272: invoke-static {v6, v7}, Lcom/android/server/SmartShrinker;->reclaim(II)V
./com/android/server/am/ActivityManagerService.smali:115354: invoke-static {v2, v7}, Lcom/android/server/SmartShrinker;->reclaim(II)V
./com/android/server/am/ActivityManagerService.smali:121014: invoke-static {v5, v7}, Lcom/android/server/SmartShrinker;->reclaim(II)V
./com/android/server/pm/PackageManagerService$PackageHandler.smali:1605: invoke-static {v4, v10}, Lcom/android/server/SmartShrinker;->reclaim(II)V
./com/android/server/SystemServer.smali:1061: invoke-static {v2, v3}, Lcom/android/server/SmartShrinker;->reclaim(II)V
<1>ActivityManagerService.updateOomAdjLocked
在trim memory 操作時,對於重要性小於home的進程做process reclaim,基本都是不活躍的進程。
對應到代碼位置:
if (app.curProcState >= ActivityManager.PROCESS_STATE_HOME
&& !app.killedByAm) {
if (app.trimMemoryLevel < curLevel && app.thread != null) {
try {
if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG_OOM_ADJ,
"Trimming memory of " + app.processName + " to " + curLevel);
SmartShrinker.reclaim(app.pid, 4);
app.thread.scheduleTrimMemory(curLevel);
} catch (RemoteException e) {
}
<2>ActivityManagerService.cleanUpRemovedTaskLocked
看下smali文件,嘗試還原了下邏輯,並將代碼對應上,這個地方應該是有些進程不殺,只做trim memory 操作和proc reclaim操作
// Kill the running processes.
for (int i = 0; i < procsToKill.size(); i++) {
ProcessRecord pr = procsToKill.get(i);
if (pr != null && pr.curAdj >= 900 && pr.info.flags & 0x1) != 0 && pr.info.hwFlags & 0x2000000) == 0 ) {
Slog.d(TAG, " the process " + pr.processName + " adj >= " + 900);
try{
SmartShrinker.reclaim(pr.pid, 4);
pr.thread.scheduleTrimMemory(80);
} catch (RemoteException localRemoteException) {}
pr.trimMemoryLevel = 80;
} else if (pr.setSchedGroup == ProcessList.SCHED_GROUP_BACKGROUND
&& pr.curReceiver == null) {
pr.kill("remove task", true);
} else {
// We delay killing processes that are not in the background or running a receiver.
pr.waitingToKill = "remove task";
}
}
<3>ActivityManagerService.trimServicesAfterBoot
原生代碼上沒有此代碼,應該是廠商自己添加的接口,在ActivityManagerService.MainHandler的handleMessage()使用
反編譯邏輯比較多,暫不貼出
<4>SystemServer.run
根據smali文件還原邏輯,跟代碼對上,
// Loop forever.
Slog.i(TAG, "Entered the Android system server main thread loop.");
SmartShrinker.reclaim(Process.myPid(),0x3)
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
<5>PackageManagerService$PackageHandler.doHandleMessage
根據smali文件還原邏輯,跟代碼對上,在POST_INSTALL處理邏輯中
// Add the args.info.getLocation for install exception statistics
handlePackagePostInstall(childRes, grantPermissions, killApp,
grantedPermissions, false, args.installerPackageName,
args.observer, args.origin.getLocation());
}
SmartShrinker.reclaim(Process.myPid(),3)
// Log tracing if needed
if (args.traceMethod != null) {
Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, args.traceMethod,
args.traceCookie);
}
從上面的邏輯中看,往SmartShrinker傳參時,傳的3或者4,在SmarShrinker的定義爲:
public static final int RECLAIM_ALL_MODE = 2;
public static final int RECLAIM_ANON_MODE = 1;
public static final int RECLAIM_INACTIVE_MODE = 4;
public static final int RECLAIM_SOFT_MODE = 3;
整體看,proc reclaim的時機有:
1:updateOomAdj 對於不活躍的重要性小於home的進程進程proc reclaim
2:cleanUpRemovedTaskLocked 清除task時,有些進程不殺掉,只做trim和proc reclaim(一鍵清理有很多App是殺不掉的,不知道和這個地方是否有關)
3:trimServicesAfterBoot 開機啓動的時候,對service proc reclaim(看smali中,還有對zygote的proc reclaim,通過ro.config.reclaim_zygote控制)
4:system server啓動後,loop之前做一次proc reclaim
5:PMS的POST_INSTALL 消息處理邏輯,應該是安裝完成後做proc reclaim
感覺這套已成體系,做的比較完善,開機的時候模塊調用SmartShrinker進行進程的proc reclaim即可~
而且進程proc reclaim的內容分爲all, anon,inactive,soft四種,分的更細一些,比如運行時,proc reclaim的是INACTIVE文件頁,個人感覺比較合理