Android应用进程的创建 — Activity的启动流程

如需转载请评论或简信,并注明出处,未经允许不得转载

目录

前言

Android世界的起源 — Zygote我们讲了Android系统的启动过程,了解了Zygote进程的作用,其中最重要的作用就是孵化应用进程,那我们本节就来详细讲讲Zygote是如何孵化应用进程的

注意:本文采用的是API28(Android 9)来进行源码分析

两种启动进程的方式

在上文中我们说了一个结论:

每个应用进程不仅有自己的数据资源和需要执行的代码,还需要用到Android框架中通用的资源和代码,由于这些资源和代码是大部分应用都需要调用到的,并且比较重量级,所以安卓把它们都放在Zygote进程的空间中,而应用进程又是继承于Zygote进程,所以当应用需要的时候就直接到里面去找就行了

是不是会有人有点好奇,应用进程为什么能拿到Zygote进程中的资源呢?进程中的这种“继承”关系(注意这里说的不是java中的继承,只是一个比喻)是如何设计的呢?接下来我们来看一下进程的启动方式

首先创建进程都是通过fork()函数,fork() 函数是一次执行,两次返回。说的更严谨一点是 两个进程对用一个程序的两次执行。当 pid == 0 时,说明现在处于子进程,当 pid > 0 时,说明处于父进程

fork()进程后,接下来会分为两种类型的子进程启动方式

第一种:

pid_t pid = fork();
if(pid == 0){
        //child process
}else{
        //parent process
}

通过这种方式创建的子进程,默认继承了父进程的所有资源,这就是应用进程的启动方式

第二种:

pid_t pid = fork();
if(pid == 0){
        //child process
        execve(path,argv,env);
}else{
        //parent process
}

这种方式在子进程中调用了execve(path,argv,env)函数,会去加载另一个可执行程序,那么子进程所继承的资源都会被清除,这就是Zygote进程的启动方式

path:可执行程序的路径

argvs:附带的参数

env:环境变量

应用进程的启动时机

在应用层当中,我们可以通过startActivity()启动我们应用内部的页面,也可以按照约定的协议跳转到其他的应用的Activity,当我们的应用启动了其他应用的Activity时(不仅仅是Activity,启动四大组件都是同样的道理),也就意味着这个Activity所对应的应用进程也启动了。实际上startActivity()内部并没有直接启动进程的逻辑,Android系统也没有给我们的应用层中暴露启动进程相关的接口,那么这个新的进程是如何被启动的呢?

我们来看一下调用startActivity()后经历了哪些过程:(代码这里就省略了,有兴趣的可以自己跟一下代码)

第一部分:当前进程与AMS进程建立Binder通信,发起startActivity请求

  1. Activity#startActivity()

  2. Activity#startActivityForResult()

  3. Instrumentation#execStartActivity()

  4. Instrumentation#execStartActivitiesAsUser()

  5. ActivityManager.getService().startActivities()getService()会返回IActivityManagerIActivityManager实际上就是跨进程通信AIDL中的Client持有的Server句柄,也就是说,Client可以通过IActivityManager接口向Server发送请求,而这里的Server就是ActivityServiceManager ,因为它继承了 IActivityManager.Stub

第二部分:AMS处理startActivity请求,通过Socket向Zygote进程请求创建应用进程

  1. ActivityServiceManager#startActivities()
  2. ActivityStarter#execute()
  3. ActivityStarter#startActivityMayWait()
  4. ActivityStarter#startActivity()
  5. ActivityStarter#startActivityUnchecked()
  6. ActivityStackSupervisor#resumeFocusedStackTopActivityLocked()
  7. ActivityStack#resumeTopActivityUncheckedLocked()
  8. ActivityStack#resumeTopActivityInnerLocked()
  9. ActivityStackSupervisor#startSpecificActivityLocked()
void startSpecificActivityLocked(ActivityRecord r,
        boolean andResume, boolean checkConfig) {
    ProcessRecord app = mService.getProcessRecordLocked(r.processName,
            r.info.applicationInfo.uid, true);

    getLaunchTimeTracker().setLaunchTime(r);

    if (app != null && app.thread != null) {
        //进程已经启动
        try {
            if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0
                    || !"android".equals(r.info.packageName)) {
                app.addPackage(r.info.packageName, r.info.applicationInfo.longVersionCode,
                        mService.mProcessStats);
            }
            //启动组件,return
            realStartActivityLocked(r, app, andResume, checkConfig);
            return;
        } catch (RemoteException e) {
            Slog.w(TAG, "Exception when starting activity "
                    + r.intent.getComponent().flattenToShortString(), e);
        }
    }
        
    //进程没有启动,去启动进程
    mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
            "activity", r.intent.getComponent(), false, false, true);
}
  1. ActivityManagerService#startProcessLocked(),四种启动组件的方式,startActivitystartServicesendBroadcastContentResolver.query,都会执行到这个方法,这就是AMS请求创建进程的入口
  2. ActivityManagerService#startProcess
  3. Process.start()
  4. ZygoteProcess#start()
  5. ZygoteProcess#startViaZygote()
  6. ZygoteProcess.openZygoteSocketIfNeeded(),打开本地Socket,AMS作为Client
  7. ZygoteProcess.zygoteSendArgsAndGetResult(),通过Socket向Zygote进程发送一个参数列表,然后就进入阻塞状态,直到远程Socket服务端返回新创建的进程pid

第三部分:Zygote处理Socket请求,创建子进程并反射调用ActivityThread

Android世界的起源 — Zygote中我们分析了ZygoteInit.main()函数,这里面会创建一个ZygoteServer,并调用ZygoteServer#runSelectLoop来死循环监听Socket的Client(AMS)发来的消息

  1. ZygoteServer#runSelectLoop
  2. ZygoteConnection#processOneCommand()
  3. Zygote.forkAndSpecialize()
Runnable processOneCommand(ZygoteServer zygoteServer) {
    String args[];
    Arguments parsedArgs = null;
    FileDescriptor[] descriptors;
  
    //....
        
    //fork进程
    pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
            parsedArgs.runtimeFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
            parsedArgs.niceName, fdsToClose, fdsToIgnore, parsedArgs.startChildZygote,
            parsedArgs.instructionSet, parsedArgs.appDataDir);

    try {
        if (pid == 0) {
            //子进程执行
            zygoteServer.setForkChild();

            zygoteServer.closeServerSocket();
            IoUtils.closeQuietly(serverPipeFd);
            serverPipeFd = null;
                        //进入子进程流程
            //parsedArgs.startClass就是ActivityThread类,是前面AMS通过Socket发送过来的
            return handleChildProc(parsedArgs, descriptors, childPipeFd,
                    parsedArgs.startChildZygote);
        } else {
            //父进程执行
            IoUtils.closeQuietly(childPipeFd);
            childPipeFd = null;
            handleParentProc(pid, descriptors, serverPipeFd);
            return null;
        }
    } finally {
        IoUtils.closeQuietly(childPipeFd);
        IoUtils.closeQuietly(serverPipeFd);
    }
}
  1. ZygoteInite.zygoteInit()
  2. RuntimeInit.applicationInit()
  3. RuntimeInit.findStaticMain(),反射调用ActivityThread

第四部分:进入ActivityThread.main(),并将Application绑定到AMS

ActivityThread,本身不是一个线程,但它管理着应用进程中主线程的执行,在ActivityManager请求时调度和执行ActivityServiceBroadcast和其它操作

  1. ActivityThread.main()
public static void main(String[] args) {
        ......
        //创建主线程的Looper
    Looper.prepareMainLooper();
        //关联AMS
    ActivityThread thread = new ActivityThread();
    thread.attach(false);

        //初始化主线程Handler
    if (sMainThreadHandler == null) {
        sMainThreadHandler = thread.getHandler();
    }

    // 进行主线程消息循环
    Looper.loop();

    throw new RuntimeException("Main thread loop unexpectedly exited");
}
  1. ActivityThread#attach(),这个方法会通过Binder与AMS通信,调用AMS的attachApplication()接口
private void attach(boolean system, long startSeq) {
  //...
  final IActivityManager mgr = ActivityManager.getService();
  mgr.attachApplication(mAppThread, startSeq);
  //...
}
  1. ActivityManagerService#attachApplication()
  2. ActivityManagerService#attachApplicationLocked()
private final boolean attachApplicationLocked(IApplicationThread thread,
        int pid, int callingUid, long startSeq) {
    //根据进程id查出对应app
    ProcessRecord app = mPidsSelfLocked.get(pid);
    ...
    //thread是ActivityThread对象
    thread.bindApplication()
    ...
      
    // 启动Actiivty
    if (normalMode) {
        mStackSupervisor.attachApplicationLocked(app)
    }

    // 启动Service
    if (!badApp) {
         didSomething |= mServices.attachApplicationLocked(app, processName);
    }

    // 启动BroadcastReceiver 
    if (!badApp && isPendingBroadcastProcessLocked(pid)) {
         didSomething |= sendPendingBroadcastsLocked(app);
    }

    ...
    return true;
}

至此,进程创建完毕,并且也有了主线程,剩下的便是启动Activity,执行Activity生命周期和一些初始化操作了

第五部分:启动Activity,执行Activity生命周期

  1. ActivityStackSupervisor#attachApplicationLocked(),从ActivityStack中取出Activity准备启动
  2. ActivityStackSupervisor#realStartActivityLocked(),真正开始启动Activity。这里基于API28的源码,所以和API27发生了较大的变化,API28新增了个管理类来控制生命周期变化
    // 创建activity启动的事务
    final ClientTransaction clientTransaction = ClientTransaction.obtain(app.thread,
            r.appToken);
    clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),
            System.identityHashCode(r), r.info,
            mergedConfiguration.getGlobalConfiguration(),
            mergedConfiguration.getOverrideConfiguration(), r.compat,
            r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,
            r.persistentState, results, newIntents, mService.isNextTransitionForward(),
            profilerInfo));

    // 设置最终期望到达的状态(resume状态)到事务当中去
    final ActivityLifecycleItem lifecycleItem;
    if (andResume) {
        lifecycleItem = ResumeActivityItem.obtain(mService.isNextTransitionForward());
    } else {
        lifecycleItem = PauseActivityItem.obtain();
    }
    clientTransaction.setLifecycleStateRequest(lifecycleItem);

    // 执行事务
    mService.getLifecycleManager().scheduleTransaction(clientTransaction);
  1. ClientLifecycleManager#getLifecycleManager().scheduleTransaction()
  2. ClientTransaction#schedule()IApplicationThread就是ActivtiyThread对象,所以最终又回到了ActivityThread
   public class ClientTransaction implements Parcelable, ObjectPoolItem {

    private IApplicationThread mClient;

    public void schedule() throws RemoteException {
        mClient.scheduleTransaction(this);
    }

    ....
}
  1. ActivityThread#scheduleTransaction(),发送EXECUTE_TRANSACTION消息
    void scheduleTransaction(ClientTransaction transaction) {
        transaction.preExecute(this);
        sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
    }
case EXECUTE_TRANSACTION:
    final ClientTransaction transaction = (ClientTransaction) msg.obj;
    mTransactionExecutor.execute(transaction);
    if (isSystem()) {
        transaction.recycle();
    }
    break;
  1. TransactionExecutor#execute()
public void execute(ClientTransaction transaction) {
    final IBinder token = transaction.getActivityToken();
    executeCallbacks(transaction);
    executeLifecycleState(transaction);
    mPendingActions.clear();
}
  1. TransactionExecutor#executeCallbacks()
  2. LaunchActivityItem#execute()
  3. ActivityThread#handleLaunchActivity()
  4. ActivityThread#performLaunchActivity()
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    ...
    //创建activity
    Activity activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);;
    ...
   //拿到之前创建好的application
   Application app = r.packageInfo.makeApplication(false, mInstrumentation);
  
   //创建ContextImpl对象
   ContextImpl appContext = createBaseContextForActivity(r);
  
   ...
   //把appContext赋给activity,并做一些初始化操作(Window就是在这里创建的)
   activity.attach(appContext, this, getInstrumentation(), r.token,
                    r.ident, app, r.intent, r.activityInfo, title, r.parent,
                    r.embeddedID, r.lastNonConfigurationInstances, config,
                    r.referrer, r.voiceInteractor, window, r.configCallback);
  
  ...
   
  //调用activity.onCreate()
   mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);

    ...
      
   return activity;
}
  1. 现在activity.onCreate()已经执行完了,那么onResume()在哪呢?我们回到TransactionExecutor#execute(),这个方法中还有一个executeLifecycleState(transaction)
private void executeLifecycleState(ClientTransaction transaction) {
    final ActivityLifecycleItem lifecycleItem = transaction.getLifecycleStateRequest();
    if (lifecycleItem == null) {
        return;
    }
    log("Resolving lifecycle state: " + lifecycleItem);

    final IBinder token = transaction.getActivityToken();
    final ActivityClientRecord r = mTransactionHandler.getActivityClient(token);

    if (r == null) {
        return;
    }

    cycleToPath(r, lifecycleItem.getTargetState(), true /* excludeLastState */);

    lifecycleItem.execute(mTransactionHandler, token, mPendingActions);
    lifecycleItem.postExecute(mTransactionHandler, token, mPendingActions);
}
  1. TransactionExecutor#cycleToPath(),将起始状态和期望状态中间的状态通过一定的计算得出然后放到一个数组中返回
  2. TransactionExecutor#performLifecycleSequence(),调用数组里面的所有生命周期状态
private void performLifecycleSequence(ActivityClientRecord r, IntArray path) {
    final int size = path.size();
    for (int i = 0, state; i < size; i++) {
        state = path.get(i);
        log("Transitioning to state: " + state);
        switch (state) {
            case ON_CREATE:
                mTransactionHandler.handleLaunchActivity(r, mPendingActions,
                        null /* customIntent */);
                break;
            case ON_START:
                mTransactionHandler.handleStartActivity(r, mPendingActions);
                break;
            case ON_RESUME:
                mTransactionHandler.handleResumeActivity(r.token, false /* finalStateRequest */,
                        r.isForward, "LIFECYCLER_RESUME_ACTIVITY");
                break;
            case ON_PAUSE:
                mTransactionHandler.handlePauseActivity(r.token, false /* finished */,
                        false /* userLeaving */, 0 /* configChanges */, mPendingActions,
                        "LIFECYCLER_PAUSE_ACTIVITY");
                break;
            case ON_STOP:
                mTransactionHandler.handleStopActivity(r.token, false /* show */,
                        0 /* configChanges */, mPendingActions, false /* finalStateRequest */,
                        "LIFECYCLER_STOP_ACTIVITY");
                break;
            case ON_DESTROY:
                mTransactionHandler.handleDestroyActivity(r.token, false /* finishing */,
                        0 /* configChanges */, false /* getNonConfigInstance */,
                        "performLifecycleSequence. cycling to:" + path.get(size - 1));
                break;
            case ON_RESTART:
                mTransactionHandler.performRestartActivity(r.token, false /* start */);
                break;
            default:
                throw new IllegalArgumentException("Unexpected lifecycle state: " + state);
        }
    }
}

总结

本文主要为了重点讲解应用进程的创建过程,所以过程中一些细节代码就没有罗列出来,如果对更多的细节感兴趣,这里推荐两篇我觉得写得还不错的文章
https://blog.csdn.net/qq_30993595/article/details/82747738
https://blog.csdn.net/luoshengyang/article/details/6689748

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
禁止转载,如需转载请通过简信或评论联系作者。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342