基于上面的问题,我决定翻翻activity和service的启动过程。
直接翻android O源码!先看源码然,然后写一个程序看看打印出对应的PID和TID验证阅读代码的正确性。
先看startActivity启动过程,因为这个部分网上很多资料,依据资料,只作简单过程分析,了解启动过程中进程的启动和分离。
ContextImpl.startActivity------>Instrumentation.execStartActivity--------->ActivityManager.getService().startActivity(10)---->
ActivityManagerService.startActivityAsUser------>ActivityStarter.startActivityMayWait----->*.startActivityLocked-->*.startActivity(看了一个ActivityRecord类,做什么的呢?)----->ActivityStarter.startActivityUnchecked---->ActivityStack.startActivityLocked---->ActivityStackSupervisor.resumeFocusedStackTopActivityLocked-->ActivityStack.resumeTopActivityUncheckedLocked-->ActivityStack.resumeTopActivityInnerLocked-->ActivityStackSupervisor.startSpecificActivityLocked----
ActivityStarter.startActivityUnchecked---->ActivityStarter.postStartActivityProcessing(socket消息发送完成后返回这里继续处理ams的逻辑)
ActivityStackSupervisor.startSpecificActivityLocked---->ActivityManagerService.startProcessLocked---->Process.start--->ZygoteProcess.start----->*.zygoteSendArgsAndGetResult(通过socket发生消息给zygote发送启动命令)---->ZygoteServer.runSelectLoop(接受socket消息)--->ZygoteConnection.runOnce---->Zygote.forkAndSpecialize---->ZygoteConnection.handleChildProc--->ZygoteInit.zygoteInit(初始化runtime虚拟机)------>RuntimeInit.applicationInit(启动activityhread主线程,这里可以看出app的进程启动的main函数在这里)----->*.invokeStaticMain---->ActivityThread.attach()------>ActivityManagerService.attachApplication--->ActivityStackSupervisor.attachApplicationLocked---->ActivityStackSupervisor.realStartActivityLocked--->IApplicationThread.scheduleLauncherActivity---->ActivityThread.sendMessage---->ActivityThread.H.sendMessage----->ActivityThread.H.handleMessage----->ActivityThread.handleLauncherActivity---->ActivityThread.performLauncherActivity---->Instrumentation.callActivityOnCreate---->Activity.onCreate--->ActivityThread.handleResumeActivity--->ActivityThread.performResumeActivity---->Activity.performResume---->Instrumentation.callActivityOnResume--->Activity.onResume---->ActivityManagerNative.getDefault().activityResumed(token)
总结下:启动一个app包含多个进程交互,进程A,ams进程,zygote进程,目标启动进程B:
1.由A启动activity,由于activity由ams维护,由于启动新的activity,因此给ams服务处理多个activity切换的逻辑;(binder进程通信)
2.ams发现需要启动一个新的进程,维护好当前的activity stack后,通过socket发送消息给zygote进程,让zygote进程启动新进程(socket进程通信)
3.zygote启动了新进程,由新进程通过binder调用ams的attachApplication方法,将启动进程前保存的activity信息取出,用来启动activity,进入activity的生命周期,activity启动完成后,新的进程在mainthread中不断loop执行消息
参考信息:http://blog.csdn.net/qq_23547831/article/details/51224992
http://blog.csdn.net/xutao20170209/article/details/61925689
service的启动:
ActiveServices.startServiceLocked---->startServiceInnerLocked--->bringUpServiceLocked
bringUpServiceLocked这个方法中:
final boolea isolated = (r.serviceInfo.flags&ServiceInfo.FLAG_ISOLATED_PROCESS) != 0;
realStartServiceLocked(r, app, execInFg);--->这接当前进程启动service。
app=mAm.startProcessLocked---->新进程启动service
realStartServiceLocked:
1.启动新进程也会调用这个函数,启动新进程基本操作流程就是在loop消息函数运行起来前,调用attach函数,最后到realStartServiceLocked函数,消息进入消息队列结束,然后消息循环loop开始工作,处理进入消息队列的消息。
2.在当前进程创建服务时,直接执行realStartServiceLocked,消息进入消息队列,处理消息即可,
有发现一个问题,都是消息机制在运行,那么activity和service在一个mainthread消息循环里面处理消息,activity的ANR超时时间是5s,service的超时时间是15S,那么在service中一个10秒的任务处理,理论上会导致activity ANR,而不会导致service ANR。是不是呢?
稍后代码验证。
ANR代码验证结果:
1. activity和service在同一个进程和线程中时;service的ANR超时时间变为5秒和activity时间一致,因为此时service和activity在同一个loop中处理消息队列,
2. 在不同进程中,service的超时时间变长相比较于activity,时间更加充裕。
找了下ANR的时间限制,这个和android的进程管理机制相关,关于进程的:
Activity----->5秒
Broadcast----->10秒
Service----->20秒
稍后看看ANR的实现原理,网上大致看了下这个超时时间可能会根据进程的状态不同ANR的时间也会存在差异。