曾经反编译过某厂商的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文件页,个人感觉比较合理