话不多说,先贴上测试提出来的bug
尽管我极力说,这个不算bug,但是人家就是不相信,只好给测试萌妹写一个分析过程了。
这句log在logcat 中的输出如下:
26780 19882 I ActivityManager: Low on memory:
26780 19882 I ActivityManager: ntv ?? 172100: idps_sc (pid 2257) native
26780 19882 I ActivityManager: ntv ?? 34873: surfaceflinger (pid 1643) nativ
...
说明是 ActivityManagerService打印出来的,那么我们看一下代码打印的地方
void reportMemUsage(ArrayList<ProcessMemInfo> memInfos) {
...省略
tag.append("Low on memory -- ");
appendMemBucket(tag, totalPss, "total", false);
appendMemBucket(stack, totalPss, "total", true);
...省略
}
调用这个方法地方在
case REPORT_MEM_USAGE_MSG: {
final ArrayList<ProcessMemInfo> memInfos = (ArrayList<ProcessMemInfo>)msg.obj;
Thread thread = new Thread() {
@Override public void run() {
reportMemUsage(memInfos);
}
};
thread.start();
break;
}
REPORT_MEM_USAGE_MSG这个这个消息是在
final void doLowMemReportIfNeededLocked(ProcessRecord dyingProc) {
...省略
if (!haveBg) {
// 1.只有当ro.debuggable 为1的时候 doReport才为true ,大概率是在userdebug版本
boolean doReport = "1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
...省略
}
if (doReport) {
// 2. 当doReport为true的时候才会发出REPORT_MEM_USAGE_MSG 这条消息
Message msg = mHandler.obtainMessage(REPORT_MEM_USAGE_MSG, memInfos);
mHandler.sendMessage(msg);
}
scheduleAppGcsLocked();
}
}
而doLowMemReportIfNeededLocked这个方法的调用:
1、在killAllBackgroundProcesses里面
2、在appDiedLocked里面,在appDiedLocked中会先判断app.killedByAm,如果是am kill的,则不会report信息,但是日志中的是lmk杀死的,则会report这条信息
如果要看appDiedLocked这个方法,首先要知道在ActivityThread.main()中,从这里开始进程创建之后会从这个方法开始绑定AMS,在AMS中通过调用AMS.attachApplicationLocked()这个方法开始绑定,在这个方法中会有对ApplicationThreadProxy绑定通知,见代码:
private final boolean attachApplicationLocked(IApplicationThread thread,
int pid) {
//绑定死亡通知,此处thread真实数据类型为ApplicationThreadProxy
AppDeathRecipient adr = new AppDeathRecipient(app, pid, thread);
thread.asBinder().linkToDeath(adr, 0);
app.deathRecipient = adr;
}
在这个过程中,当我们binder server挂掉后,会回调AppDeathRecipient.binderDied()方法通知client端。
那到这里我们的server端是指应用进程的ApplicationThread,其中ApplicationThread是在ActivityThread中创建的此时属于新建的进程(比如新建app的进程)。client就是ApplicationThreadProxy对象,这个对象是在AMS中,AMS是在system_server中。所以当我们binder server端死亡的时候(app进程死亡)我们system_server进程就会收到通知,然后做一些处理。在这盗用一波别人花的流程图:
然后我们看一下appDiedLocked这个方法
@GuardedBy("this")
final void appDiedLocked(ProcessRecord app) {
appDiedLocked(app, app.pid, app.thread, false);
}
@GuardedBy("this")
final void appDiedLocked(ProcessRecord app, int pid, IApplicationThread thread,
boolean fromBinderDied) {
// First check if this ProcessRecord is actually active for the pid.
synchronized (mPidsSelfLocked) {
ProcessRecord curProc = mPidsSelfLocked.get(pid);
if (curProc != app) {
Slog.w(TAG, "Spurious death for " + app + ", curProc for " + pid + ": "