美文网首页
根Activity的启动过程简述

根Activity的启动过程简述

作者: passerbywhu | 来源:发表于2018-02-27 13:03 被阅读116次

    参照《Android系统源代码情景分析》中的例子。

    有三个Activity:

    1. MainActivity 根Activity

    2.SubActivityInProcess  与根Activity运行在同一个进程的Activity

    3.SubActivityInNewProcess 运行在新进程中的Activity

    两个重要的结构体:

    1.ActivityRecord 每个启动的Activity在ActivityManagerService中都有唯一一个对应的ActivityRecord对象。该对象是Binder本地对象。同时Activity所在的ActivityThread会持有该ActivityRecord的binder代理对象。在Activity和ActivityManagerService进行远程通信的时候,该binder代理对象会被传输以被ActivityManagerService用来识别当前与自己通信的Activity的具体信息。

    2.ApplicationThread 每个app都含有这样一个Binder本地对象。每个运行的app进程在ActivityManagerService中都有一个唯一的ProcessRecord对象。该对象保存了ApplicationThread的Binder代理对象。从而ActivityManagerService可以主动与Activity所在的进程进行通信。

    3.ActivityClientRecord 每个启动的Activity在自身进程中都有唯一一个对应的ActivityClientRecord对象。它和Activity进程所持有的ActivityManagerService中的ActivityRecord的代理对象是一一对应的。

    重要变量:

    ActivityStack类有三个成员变量mResumedActivity, mLastPausedActivity和mPausingActivity,它们的类型均为ActivityRecord,分别用来描述系统当前激活的Activity组件、上一次被中止的Activity组件,以及正在被中止的Activity组件。

    从Launcher启动MainActivity

    1.Launcher-->startActivitySafely

    2.Activity-->startActivity

    3.Activity-->startActivityForResult

    Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity(

        this, mMainThread.getApplicationThread(), mToken, this, intent, requestCode

    );

    mMainThread.getApplicationThread()就是Launcher Activity所属进程的ApplicationThread本地对象。

    mToken是Launcher Activity在ActivityManagerService中的ActivityRecord对应的代理对象。

    4.Instrumentation-->execStartActivity

    5.ActivityManagerProxy-->startActivity

    将需要启动的intent信息以及自身的一些信息写入Parcel中进行远程通信

    ...

    //caller是IApplicationThread

    data.writeStrongBinder(caller != null ? caller.asBinder() : null);

    //intent是需要启动的MainActivity的相关信息

    intent.writeToParcel(data, 0);

    //resultTo是Launcher Activity对应的ActivityRecord代理对象

    data.writeStrongBinder(resultTo);

    mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);

    ...

    接下来在ActivityManagerService进程中执行

    6.ActivityManagerService-->startActivity

    7.ActivityStack-->startActivityMayWait

    通过PackageManager解析需要启动的intent信息,获取对应的ActivityInfo

    ActivityInfo aInfo;

    ResolveInfo rInfo = AppGlobals.getPackageManager().resolveIntent(intent, resolvedType, PackageManager.MATCH_DEFAULT_ONLY | ActivityManagerService.STOCK_PM_FLAGS);

    aInfo = rInfo != null ? rInfo.activityInfo : null;

    8.ActivityStack-->startActivityLocked

    通过Launcher传过来的ActivityRecord代理对象获取其在ActivityManagerService中对应的ActivityRecord  sourceRecord

    通过Launcher传过来的IApplicationThread对象获取Launcher进程在ActivityManagerService中对应的ProcessRecord对象 callerApp,以及进程id callingPid和用户id  callingUid。

    用callerApp callingUid以及第7步得到的aInfo构造需要启动的MainActivity对应的ActivityRecord r。

    9. ActivityStack-->startActivityUncheckedLocked

    检测到MainActivity所在的Task不存在,新建一个TaskRecord。将该TaskRecord赋给MainActivity对应的ActivityRecord的task变量中。并将该TaskRecord加入到ActivityManagerService的recentTask中。

       ActivityStack-->startActivityLocked

    将MainActivity对应的ActivityRecord加入到ActivityStack的mHistory中。

    10.ActivityStack.resumeTopActivityLocked

    获取当前运行的top Activity的ActivityRecord(就是MainActivity)。和mResumedActivity(即Launcher Activity)相比较。发现不一致。于是需要告诉mResumedActivity需要执行pause操作。

    11.ActivityStack-->startPausingLocked

    通过Launcher Activity对应的ActivityRecord所保存的ProcessRecord的thread对象获取Launcher Activity所在进程的IApplicationThread代理对象。从而进行远程通信。

    //prev是Launcher Activity对应的ActivityRecord。 app是ProcessRecord类型。thread是IApplicationThread类型。

    prev.app.thread.schedulePauseActivity(prev, prev.finishing, userLeaving, prev.configChangFlags);

    同时发送一个PAUSE_TIMEOUT_MSG延迟消息。如果PAUSE_TIMEOUT时间之后这个消息没有被取消掉,说明Launcher Activity的pause操作无响应了。

    12.ApplicationThreadProxy.schedultePauseActivity

    ...

    //token是Launcher Activity对应的ActivityRecord

    data.writeStrongBinder(token)

    mRemote.transact(SCHEDULE_PAUSE_ACTIVITY_TRANSACTION, data, null, IBinder.FLAG_ONEWAY);

    ...

    接下来在Launcher Activity的进程中执行

    13.ApplicationThread-->schedulePauseActivity

    14.ActivityThread-->queueOrSendMessage

    15.H-->handleMessage

    16.ActivityThread-->handlePauseActivity

    //token是Launcher Activity的ActivityRecord代理对象。

    Bundle state = performPauseActivity(token, finished, true);

    17. ActivityManagerProxy-->activityPaused

    ...

    //token是Launcher Activity的ActivityRecord代理对象

    data.writeStrongBinder(token);

    data.writeBundle(state);

    mRemote.transact(ACTIVITY_PAUSED_TRANSACTION, data, reply, 0);

    ...

    接下来在ActivityManagerService进程中执行

    18.ActivityManagerService-->activityPaused

    19.ActivityStack-->activityPaused

    移除之前发送的PAUSE_TIMEOUT_MSG延时信息

    修改Launcher Activity的ActivityRecord的状态。

    int index = indexOfTokenLocked(token);

    ActivityRecord r = mHistory.get(index);

    20. ActivityStack-->completePauseLocked

    将mPausingActivity置为null

    21.ActivityStack-->resumeTopActivityLocked

    上一次进入这个函数的时候由于resumedActivity不等于top running Activity.所以进入了pause流程。

    这次由于已经pause过了。所以直接进入start流程。

    22.ActivityStack-->startSpecificActivityLocked

    检测到MainActivity对应的进程并没有起来。也即MainActivity对应的ActivityRecord的app (ProcessRecord类型)以及app.thread(IApplicationThread类型)为null。启动进程。

    23.ActivityManagerService.startProcessLocked

    为MainActivity所在进程创建ProcessRecordLocked对象。启动进程

    int[] gids = mContext.getPackageManager().getPackageGids(app.info.packageName);

    int pid = Process.start("android.app.ActivityThread", mSimpleProcessManageMent ? app.processName : null, uid, uid, gids, debugFlags, null);

    发送一个延时消息PROC_START_TIMEOUT_MSG,如果PROC_START_TIMEOUT之后,该消息没有被取消。则判断为启动进程无响应。

    接下来在MainActivity的进程中运行

    24.ActivityThread-->main

    创建ActivityThread。创建ApplicationThread。

    25.ActivityManagerProxy-->attachApplication

    //app是IApplicationThread类型

    data.writeStrongBinder(app.asBinder());

    mRemote.transact(ATTACH_APPLICATION_TRANSACTION, data, reply, 0);

    接下来在ActivityManagerService的进程中运行

    26.ActivityManagerService.attachApplication

    27.ActivityManagerService.attachApplicationLocked

    通过Binder驱动告知的pid获取当前attach的进程在ActivityManagerService中对应的ProcessRecord。第23步创建的。

    将ApplicationThread代理对象保存在ProcessRecord中。供之后ActivityManagerService与Activity进程通信用。

    移除之前发送的延迟消息PROC_START_TIMEOUT_MSG

    检测到top running Activity需要运行,且其ActivityRecord的app为null,且进程名等于当前attach的进程名。于是启动MainActivity.

    28.ActivityStack.realStartActivityLocked

    ProcessRecord有activities变量保存有所有在该进程中运行的Activity

    29.ApplicationThreadProxy-->scheduleLaunchActivity

    ...

    //intent是MainActivity的intent

    intent.writeToParcel(data, 0);

    //token是MainActivity对应的ActivityRecord本地对象

    data.writeStrongBinder(token);

    //info是MainActivity对应的ActivityInfo

    info.writeToParcel(data, 0);

    mRemote.transact(SCHEDULE_LAUNCH_ACTIVITY_TRANSACTION, data, null, IBinder.FLAG_ONEWAY);

    ...

    接下来是在MainActivity的进程中运行的

    30.ApplicationThread-->scheduleLaunchActivity

    为MainActivity创建ActivityClientRecord。将其和ActivityRecord关联起来。

    31.ActivityThread-->queueOrSendMessage

    32.H-->handleMessage

    调用ActivityThread类的getPackageInfoNoCheck获取LoadedApk对象。赋给ActivityClientRecord的packageInfo成员变量中。

    33.ActivityThread-->handleLaunchActivity

    34.ActivityThread.performLaunchActivity

    调用Instrumentation.newActivity创建MainActivity的实例。

    创建MainActivity的Application。

    为MainActivity的实例赋予需要用到的变量。

    35.MainActivity.onCreate

    相关文章

      网友评论

          本文标题:根Activity的启动过程简述

          本文链接:https://www.haomeiwen.com/subject/sknbzxtx.html