欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

分析Activity启动过程

程序员文章站 2022-05-14 08:03:22
...

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

分析Activity启动过程

相关标签: activity