AMS杀进程场景之汇总

Posted by Gityuan on April 23, 2016

基于Android 6.0源码剖析,统计AMS所有可能杀进程的场景.

一. 杀进程场景

理解杀进程的实现原理, 介绍了杀进程的过程, 接下来本文介绍系统framework层, ActivityManagerService在哪些场景会调用ProcessRecord.java中的kill()方法来杀进程.

void kill(String reason, boolean noisy) {
    if (!killedByAm) {
        if (noisy) {
            Slog.i(TAG, "Killing " + toShortString() + " (adj " + setAdj + "): " + reason);
        }
        //调用该方法,则会输出EventLog, 最后一个参数reason代表是通过何在方法触发kill
        EventLog.writeEvent(EventLogTags.AM_KILL, userId, pid, processName, setAdj, reason);
        Process.killProcessQuiet(pid);
        Process.killProcessGroup(info.uid, pid);
        if (!persistent) {
            killed = true;
            killedByAm = true;
        }
    }
}

reason对于分析问题很重要, 实例说明:

am_kill : [0,26328,com.gityuan.app,0,stop com.gityuan.app]

这是Eventlog,可知最后一个参数stop com.gityuan.app, 代表的是reason = stop packageName, 那么显然这个app是由于调用forceStopPackageLocked而被杀. 先看重点说说force-stop

1.1 force-stop

对于force-stop系统这把杀进程的利器, 还会额外出现一个reason来更详细的说明触发force-stop的原因.

Slog.i(TAG, "Force stopping " + packageName + " appid=" + appId + " user=" + userId + ": " + reason);

以下场景都会调用force-stop, 输出reason表格如下:

方法 reason 含义
AMS.forceStopPackage from pid callingPid  
AMS.finishUserStop finish user  
AMS.clearApplicationUserData clear data  
AMS.broadcastIntentLocked storage unmount  
AMS.finishBooting query restart  
AMS.finishInstrumentationLocked finished inst evenPersistent
AMS.setDebugApp set debug app evenPersistent
AMS.startInstrumentation start instr  
PKMS.deletePackageLI uninstall pkg  
PKMS.movePackageInternal move pkg  
PKMS.replaceSystemPackageLI replace sys pkg  
PKMS.scanPackageDirtyLI replace pkg  
PKMS.scanPackageDirtyLI update lib  
PKMS.setApplicationHiddenSettingAsUser hiding pkg  
MountService.killMediaProvider vold reset  

PKMS服务往往是调用killApplication从而间接调用forceStopPackage方法.

当然除了force-stop, 杀进程的原因(reason)有很多种形式, 如下:

1.2 异常杀进程

方法 reason 含义
appNotResponding anr ANR
appNotResponding bg anr ANR
handleAppCrashLocked crash CRASH
crashApplication crash CRASH
processStartTimedOutLocked start timeout  
processContentProviderPublishTimedOutLocked timeout publishing content providers  
removeDyingProviderLocked depends on provider cpr.name in dying proc processName  

1.3 主动杀进程

方法 reason 含义
forceStopPackageLocked stop user userId  
forceStopPackageLocked stop packageName  
killBackgroundProcesses kill background  
killAllBackgroundProcesses kill all background  
killAppAtUsersRequest user request after error FORCE_CLOSE
killUid kill uid PERMISSION
killUid Permission related app op changed PERMISSION
killProcessesBelowAdj setPermissionEnforcement  
killApplicationProcess - 直接杀
killPids Free memory  
killPids Unknown  
killPids 自定义 调用者自定义

1.4 调度杀进程

方法 reason 含义
trimApplications empty  
applyOomAdjLocked remove task  
updateOomAdjLocked cached #numCached  
updateOomAdjLocked empty #numEmpty  
updateOomAdjLocked empty for tableimes  
updateOomAdjLocked isolated not needed  

1.5 其他杀进程

方法 reason 含义
cleanUpRemovedTaskLocked remove task  
attachApplicationLocked error during init  
systemReady system update done  
getProcessRecordLocked lastCachedPssk from cached  
performIdleMaintenance idle maint (pss lastPss from initialIdlePss)  
checkExcessivePowerUsageLocked excessive wake held  
checkExcessivePowerUsageLocked excessive cpu  
scheduleCrash scheduleCrash for message failed  

二. 杀进程手段

以上介绍的所有杀进程都是调用ProcessRecord.kill()方法, 必然会输出相应的EventLog.那么还有哪些场景的杀进程不会输出log呢:

Process.killProcess(int pid) //可杀任何指定进程,或者直接发signal
adb shell kill -9 <pid>  //可杀任何指定的进程  
直接lmk杀进程

也就是说进程被杀而无log输出,那么可能是通过直接调用kill或者发信号, 再或许是lmk所杀.

三. 小结

杀进程log举例:

am_kill : [0,3226,com.android.quicksearchbox,13,empty #13]
Force stopping com.android.providers.media appid=10010 user=-1: vold reset
Killing 5769:com.android.mms/u0a21 (adj 15): empty #13
processes xxx at adjustment 1 //杀adj=1的进程

进程记录信息:

进程结构体 数据类型 说明
mProcessNames ProcessMap 根据进程名和uid查询
mPidsSelfLocked SparseArray 根据pid查询
mLruProcesses ArrayList foreach调用

评估:

  • killPids: 这个比较灵活,只需要指定pid即可杀进程, 也可定制kill reason.
  • forceStopPackage: 杀进程最为彻底;
  • killBackgroundProcesses: 只杀adj > SERVICE_ADJ(5)的进程;

未完待续…


微信公众号 Gityuan | 微博 weibo.com/gityuan | 博客 留言区交流