分析Activity启动过程
Android6.0
Activity启动的过程
本质上,apk只是一个资源包,所以我们说的,启动app,启动activity,启动server的主要执行者都是system_server。以activity的启动为例子,有几个步骤
system_server process
1,ActivityManagerService.startActivity
向AMS(ActivityManagerService)发起startActivity/Intent
不管是从桌面点击lunch,还是用脚本敲入am start
,还是应用内或者应用间的Intent
@Override
public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle options, int userId) {
enforceNotIsolatedCaller("startActivity");
userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
false, ALLOW_FULL_ONLY, "startActivity", null);
// TODO: Switch to user app stacks here.
return mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent,
resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
profilerInfo, null, null, options, false, userId, null, null);
}
system_server process
2,ActivityStackSupervisor.startSpecificActivity
ActivityStackSupervisor会从AppGlobals.getPackageManager().activitySupportsIntent
查询启动的Activity的信息,这里会检查启动者(caller)的权限信息,caller在这里很重要。
ActivityStackSupervisor中持有了许多ActivityDisplay ,它的数据结构很有意思,有几个信息,显示设备,还有ActivityStack。ActivityDisplay是什么东西呢,我觉得是分了一层,方便多物理屏幕的扩展。
int mDisplayId;
Display mDisplay;
DisplayInfo mDisplayInfo = new DisplayInfo();
final ArrayList<ActivityStack> mStacks = new ArrayList<ActivityStack>();
ActivityRecord mVisibleBehindActivity;
ActivityStack就是我们通常说的Activity栈,还记得几种启动模式吗?就是这个feature。ActivityStack会和Window、Process相关联,所以这里要独立出来成为一个对象。
接上一步的说,startActivityMayWait会handle到ActivityStack中,ActivityStack继续发起 ActivityStackSupervisor.startSpecificActivityLocked
。
ActivityStackSupervisor中通过AMS.getProcessRecordLocked
已经知道当前有没有Application存在。
如果不存在
system_server
3.1 AMS.startProcessLocked
Process.ProcessStartResult startResult = Process.start(...);
所以java层/system_server的创建进程就是在Process中。Process发指令给zygote的
zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);
argsForZygote就是新建进程的一堆指令,通过socket,把这些参数传递给zygote。为什么要这么麻烦的弄一个zygote呢?一个是它是创世者,所以android上层封装都是它的子进程。另外一个是有一个统一的初始化的地方,可以控制进程属性/能力。为什么用socket呢?是为了最大程度的解耦合。
java层的ZygoteInit.java是这样的
public static void main(String argv[]) {
...
startSystemServer(abiList, socketName);
...
runSelectLoop(abiList);
closeServerSocket();
}
看到有个 runSelectLoop
就是在这里等socket发过来的新建指令
ZygoteConnection.runOnce
ZygoteConnection.handleChildProc
RuntimeInit.zygoteInit
RuntimeInit.applicationInit
private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) {
...
// Remaining arguments are passed to the start class's static main
invokeStaticMain(args.startClass, args.startArgs, classLoader);
}
这个时候就新建了一个进程,然后反射执行了ActivityThread中的main方法(invokeStaticMain)。这时候再继续走callActivity的流程。
如果存在
user process
3.2 ActivityStackSupervisor.realStartActivityLocked
调用到ActivityStackSupervisor.realStartActivityLocked
注意的是,进程优先级的概念就是在这里给proc下的一个节点赋的值。在这里通过binder跨进程,跨完之后在
ActivityThread.ApplicationThread.scheduleLaunchActivity
看ActivityThread的代码可以发现
final ApplicationThread mAppThread
mAppThread是ActivityThread的内部类&&成员变量,那么他们再不在一个进程呢?当然是在的,这就是我们ps出来看到的包名的进程。这里应该叫process更好一点。单进程,和线程几乎没一点点关系。
这个时候打开Activity的信息就被Handle到H中去处理
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
final ActivityClientRecord r = (ActivityClientRecord) msg.obj;
r.packageInfo = getPackageInfoNoCheck(
r.activityInfo.applicationInfo, r.compatInfo);
handleLaunchActivity(r, null);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
Trace.traceBegin、Trace.traceEnd是两个钩子,留作性能分析用。所以到了ActivityThread就两个步骤:
一个是解析资源getPackageInfoNoCheck,加载类,大部分的动态补丁和什么多开就是去hook
getPackageInfoNoCheck相关的方法
二是handleLaunchActivity 准备好窗口。performLaunchActivity,一个重点是这里会把appContext挂到Activity中,之后就是喜闻乐见的onCreate
上一篇: (一)MyWeChat
推荐阅读
-
Android入门之Activity四种启动模式(standard、singleTop、singleTask、singleInstance)
-
Android编程之Activity中onDestroy()调用分析
-
Activity 四种启动模式详细介绍
-
Android编程中activity启动时出现白屏、黑屏问题的解决方法
-
Android编程四大组件之Activity用法实例分析
-
详解spring boot应用启动原理分析
-
关于Spring启动时Context加载源码分析
-
深入理解SpringCloud之Eureka注册过程分析
-
MySQL redo死锁问题排查及解决过程分析
-
关于Android中点击通知栏的通知启动Activity问题解决