zoukankan      html  css  js  c++  java
  • 笔记:Activity的启动过程

    Activity的创建特点

    作为四大组件之一的Activity,它不像普通java对像那样,可以new出来,然后去使用。而是调用
    startActivity()这样的方式启动。那么Android系统是如何创建并启动Activity的呢?本文就来
    一探究竟。

    NOTE:本文内容就是对老罗《Android系统源代码情景分析》章节的简化笔记。
    因为涉及到不同进程间的通信,所以分析流程的过程中会在不同的源代码文件之间跳转,源码为Android 2.3版本,下载系统源码后,可以使用像Everything这样的软件根据类名对文件进行快速查找。

    Launcher启动App

    任何安装的应用几乎都是点击桌面上的图标被启动。
    接下来以Launcher程序启动一个App的过程作为案例。要启动的App的包名为com.idlestar.bot
    ,其入口Activity为MainActivity。

    Task和Back Stack

    即便没有了解过Activity的启动过程、ActivityManagerService(简称AMS,它是运行在系统进程SystemServer中的系统关键服务)这些知识点,对任务(Task)和回退栈(Back Stack)的概念、Activity启动模式等多少都回了解。接下来可以在源码级稍微感受到它们的真实表现。

    Task

    用户完成一个任务时,可能和若干相关的Activity组件进行交互,这些相关的Activity的集合被称作一个Task,由TaskRecord对象表示。Task中所有Activity形成一个stack结构,以它们的启动顺序被添加。

    ActivityStack

    实际上在系统中,每一个Activity组件实例被使用一个ActivityRecord对像表示,所有的Activity组件都保存在一个ActivityStack对象的字段ArrayList mHistory中。ActivityRecord.task字段表示其所在Task。假设把所有Activities指定编号:a0,a1,a2...an,表示mHistory中从第0,1,2...n个Activity,那么,Task就是从a0到an中连续的一个个“子序列”,一个Task包括1或多个Activity。Task中的Activity的“栈结构”是通过ArrayList间接实现的

    命令adb shell dumpsys activity可以查看当前系统中运行的Activities的信息。在启动MainActivity的前后,可以运行命令来查看有关的Activities的信息。

    启动MainActivity前,显示Launcher时:

    ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)
      Stack #0:
        Task id #1
          TaskRecord{529e7460 #1 A=com.android.launcher U=0 sz=1}
          ...
            ProcessRecord{529e7b24 735:com.android.launcher/u0a8}
    
        Running activities (most recent first):
          TaskRecord{529e7460 #1 A=com.android.launcher U=0 sz=1}
            Run #0: ActivityRecord{529e66bc u0 com.android.launcher/com.android.launcher2.Launcher t1}
        ...
    
      Recent tasks:
      * Recent #0: TaskRecord{529e7460 #1 A=com.android.launcher U=0 sz=1}
    

    上面的信息有点像Json那种格式,缩进表示了信息的分组。
    先是Stack #0这种划分,#跟数字表示序号。Stack #0是整个ActivityStack中的第一个Task。
    此时,只有一个Task——Stack #0
    Task id为#1,即任务id=1。
    而Running activities是Task所包含的运行中的Activity的信息,最近使用的排在前面。Run #0显示了正在运行的第一个也是唯一一个ActivityRecord,就是Launcher组件。

    点击App图标,打开MainActivity之后:

    ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)
      Stack #0:
        Task id #1
          TaskRecord{529e7460 #1 A=com.android.launcher U=0 sz=1}
          ...
              ProcessRecord{529e7b24 735:com.android.launcher/u0a8}
    
        Running activities (most recent first):
          TaskRecord{529e7460 #1 A=com.android.launcher U=0 sz=1}
            Run #0: ActivityRecord{529e66bc u0 com.android.launcher/com.android.launcher2.Launcher t1}
    
      Stack #1:
        Task id #2
          TaskRecord{52a203f8 #2 A=com.idlestar.bot U=0 sz=1}
          ...
              ProcessRecord{529704e8 3307:com.idlestar.bot/u0a82}
          ...    
        Running activities (most recent first):
          TaskRecord{52a203f8 #2 A=com.idlestar.bot U=0 sz=1}
            Run #0: ActivityRecord{5296eea0 u0 com.idlestar.bot/.MainActivity t2}
      ...
    
      Recent tasks:
      * Recent #0: TaskRecord{52a203f8 #2 A=com.idlestar.bot U=0 sz=1}
      * Recent #1: TaskRecord{529e7460 #1 A=com.android.launcher U=0 sz=1}
    
    

    可以看到此时多了一个Task Stack #1,它在是栈顶位置(#序号最大的),它对应的ActivityRecord为MainActivity,正是当前处在前台(foreground)被显示的Activity。

    上面启动MainActivity前后,看到Launcher和MainActivity属于不同的Task,因为Launcher为启动的MainActivity指定了NEW_TASK。

    启动过程跟踪

    自己的App会运行在一个包名对应的进程中,这点常识这里不去解释。
    MainActivity是Launcher启动的,而Launcher是通过AMS来启动MainActivity的。它们分别运行在不同的进程中,整个过程中它们之间使用Binder完成跨进程通信。

    NOTE:源代码为android系统2.3。
    下面是完整的过程,非重要部分会很简单地描述下,保证流程完整性。

    阶段1:Launcher通知AMS启动MainActivity。

    Launcher向ActivityManagerService发送一个启动MainActivity组件的进程间通信请求。

    系统启动时,会启动PackageManagerService服务,简称PMS,通过它安装系统中的应用程序。
    第一个启动的就是Launcher,Launcher向PMS查询所有App的AndroidManifest.xml获得所有App
    的图标,启动Activity组件(Action为Intent.ACTION_MAIN,Category为Intent.CATEGORY_LAUNCHER)的全名。

    用户点击桌面App图标后,Launcher根据对应App的信息,创建一个启动它的intent,并调用startActivity()来启动它。

    不同android版本中Launcher的代码会稍有差异,但基本过程是类似的。
    方法调用过程,对传递调用不加说明,直接继续给出所调用的方法:

    step 1:Launcher.startActivitySafely()

    void startActivitySafely(Intent intent, Object tag) {
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        try {
            startActivity(intent);
        } catch (ActivityNotFoundException e) {
        ...
    

    默认为intent添加了FLAG_ACTIVITY_NEW_TASK标志。

    step 2:Activity.startActivity(intent)

    step 3:Activity.startActivityForResult(intent, -1)

    参数requestCode = -1表示不处理onActivityResult()

    // set by the thread after the constructor and before onCreate(Bundle savedInstanceState) is called.
    private Instrumentation mInstrumentation;
    
    void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) {
      ...
      Instrumentation.ActivityResult ar =
         mInstrumentation.execStartActivity(
             this, mMainThread.getApplicationThread(), mToken, this,
             intent, requestCode, options);
      ...
    }    
    

    step 4:Instrumentation.execStartActivity()

    public ActivityResult execStartActivity(
    Context who, IBinder contextThread, IBinder token, Activity target,
    Intent intent, int requestCode) {
      ...
      try {
          int result = ActivityManagerNative.getDefault()
              .startActivity(whoThread, intent,
                      intent.resolveTypeIfNeeded(who.getContentResolver()),
                      null, 0, token, target != null ? target.mEmbeddedID : null,
                      requestCode, false, false);
      ...
    }
    

    ActivityManagerNative.getDefault()获得的是AMS的一个代理对像,类型为IActivityManager。

    /**
    * Retrieve the system's default/global activity manager.
    */
    static public IActivityManager getDefault()
    {
       if (gDefault != null) {
           //if (Config.LOGV) Log.v(
           //    "ActivityManager", "returning cur default = " + gDefault);
           return gDefault;
       }
       IBinder b = ServiceManager.getService("activity");
       if (Config.LOGV) Log.v(
           "ActivityManager", "default service binder = " + b);
       gDefault = asInterface(b);
       if (Config.LOGV) Log.v(
           "ActivityManager", "default service = " + gDefault);
       return gDefault;
    }
    

    asInterface(b):

    /**
     * Cast a Binder object into an activity manager interface, generating
     * a proxy if needed.
     */
    static public IActivityManager asInterface(IBinder obj)
    {
        if (obj == null) {
            return null;
        }
        IActivityManager in =
            (IActivityManager)obj.queryLocalInterface(descriptor);
        if (in != null) {
            return in;
        }
    
        return new ActivityManagerProxy(obj);
    }
    

    以上2个方法是典型的Binder通信方式,将一个和远程进程通信的IBinder转为通信定义的接口类型。最终getDefault()返回的就是ActivityManagerProxy对像。

    step 5:ActivityManagerProxy.startActivity()

    public int startActivity(IApplicationThread caller, Intent intent,
                String resolvedType, Uri[] grantedUriPermissions, int grantedMode,
                IBinder resultTo, String resultWho,
                int requestCode, boolean onlyIfNeeded,
                boolean debug) throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
        data.writeStrongBinder(caller != null ? caller.asBinder() : null);
        intent.writeToParcel(data, 0);
        data.writeStrongBinder(resultTo);
        ...
        mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
        reply.readException();
        int result = reply.readInt();
        reply.recycle();
        data.recycle();
        return result;    
    }
    

    上面使用IBinder.transact()对系统进程中的AMS执行远程调用:START_ACTIVITY_TRANSACTION。

    • 参数
      caller:指向Launcher组件所在的应用程序进程的ApplicationThread对像。
      intent:包含了要启动的MainActivity组件的信息。
      resultTo:指向AMS内部的一个ActivityRecord对像,它保存了Launcher组件的信息。
    /**
     * An entry in the history stack, representing an activity.
     */
    class ActivityRecord extends IApplicationToken.Stub {
    }
    

    NOTE:在多进程交互的环境下,IBinder对像可以是一个进程中供其它进程访问的“可远程访问”对像的一个BinderProxy代理。跨进程引用一个对象的作用。

    以上step操作发生在Launcher应用中,其方法调用流程图:

    Activity启动流程-阶段1

    阶段2:AMS保存启动信息,通知caller进入stop

    接下来的操作在AMS中进行,处理Launcher发起的START_ACTIVITY_TRANSACTION请求。
    AMS首先将要启动的MainActivity组件的信息保存起来,然后再向Launcher组件发送一个进入中止状态的进程间通信请求。

    step 6:ActivityManagerService.startActivity()

    AMS继承ActivityManagerNative,其onTransact()方法中,对code = START_ACTIVITY_TRANSACTION的处理是调用接口方法IActivityManager.startActivity(),AMS实现了startActivity():

    public ActivityStack mMainStack;
    
    public final int startActivity(IApplicationThread caller,
           Intent intent, String resolvedType, Uri[] grantedUriPermissions,
           int grantedMode, IBinder resultTo,
           String resultWho, int requestCode, boolean onlyIfNeeded,
           boolean debug) {
       return mMainStack.startActivityMayWait(caller, intent, resolvedType,
               grantedUriPermissions, grantedMode, resultTo, resultWho,
               requestCode, onlyIfNeeded, debug, null, null);
    }
    

    step 7:ActivityStack.startActivityMayWait()

    final int startActivityMayWait(IApplicationThread caller,
                Intent intent, String resolvedType, Uri[] grantedUriPermissions,
                int grantedMode, IBinder resultTo,
                String resultWho, int requestCode, boolean onlyIfNeeded,
                boolean debug, WaitResult outResult, Configuration config) {
    
       ...
    
        // Collect information about the target of the Intent.
       ActivityInfo aInfo;
       try {
           ResolveInfo rInfo =
               AppGlobals.getPackageManager().resolveIntent(
                       intent, resolvedType,
                       PackageManager.MATCH_DEFAULT_ONLY
                       | ActivityManagerService.STOCK_PM_FLAGS);
           aInfo = rInfo != null ? rInfo.activityInfo : null;
    
        ...
    
        int res = startActivityLocked(caller, intent, resolvedType,
                grantedUriPermissions, grantedMode, aInfo,
                resultTo, resultWho, requestCode, callingPid, callingUid,
                onlyIfNeeded, componentSpecified);
        ...
    }
    

    方法先通过PackageManager根据启动intent获得关于MainActivity组件的更多信息,保存在变量ActivityInfo aInfo中。继续调用startActivityLocked()。

    step 8:ActivityStack.startActivityLocked()

    final ActivityManagerService mService;
    /**
     * The back history of all previous (and possibly still
     * running) activities.  It contains HistoryRecord objects.
     */
    final ArrayList mHistory = new ArrayList();
    ...
    final int startActivityLocked(IApplicationThread caller,
                Intent intent, String resolvedType,
                Uri[] grantedUriPermissions,
                int grantedMode, ActivityInfo aInfo, IBinder resultTo,
                String resultWho, int requestCode,
                int callingPid, int callingUid, boolean onlyIfNeeded,
                boolean componentSpecified) {
        ...
        ProcessRecord callerApp = null;
        if (caller != null) {
            callerApp = mService.getRecordForAppLocked(caller);
            if (callerApp != null) {
                callingPid = callerApp.pid;
                callingUid = callerApp.info.uid;
            } else {
        ...
    
        ActivityRecord sourceRecord = null;
        ...
        int index = indexOfTokenLocked(resultTo);
        ...
        sourceRecord = (ActivityRecord)mHistory.get(index);
    
        ActivityRecord r = new ActivityRecord(mService, this, callerApp,         
            callingUid,intent, resolvedType, aInfo, mService.mConfiguration,
            resultRecord, resultWho, requestCode, componentSpecified);
        ...
    
        return startActivityUncheckedLocked(r, sourceRecord,
            grantedUriPermissions, grantedMode, onlyIfNeeded, true);    
    }
    

    AMS内部使用ProcessRecord对象表示每一个应用程序进程,getRecordForAppLocked获得caller对应的ProcessRecord callerApp,也就是Launcher的进程信息。
    mHistory正是用来保存所有已启动的Activity组件,每个Activity组件使用ActivityRecord表示。sourceRecord就是Launcher组件对应的信息,启动操作的源组件。
    之后创建一个ActivityRecord r变量,它表示要启动的MainActivity组件的信息,启动操作的目标组件。

    step 9:ActivityStack.startActivityUncheckedLocked()

    根据启动intent获得launchFlags。
    用户是点击Launcher中的图标手动启动,所以Intent.FLAG_ACTIVITY_NO_USER_ACTION不成立,之后会向源Activity Launcher发送一个“用户离开”的事件通知。
    标志FLAG_ACTIVITY_NEW_TASK说明需要将要启动的MainActivity放在一个新Task中——就是和当前的Launcher组件不在一个Task中,而在AndroidManifest.xml中可以使用
    android:taskAffinity来指定组件所在任务id,所以AMS检查此Task是否存在,不存在就创建它,把MainActivity放到此Task中。每个新创建的Task有一个int id,是AMS维护的一个自增字段。

    最后紧接着执行重载的另一个方法
    startActivityLocked(r, newTask, doResume);

    如果newTask为true,也就是要启动的Activity组件在新Task中,那么它会被放在mHistory栈的顶部。
    然后doResume = true,就对mHistory最后的Activity执行resume。

    这里就是MainActivity被添加到栈顶,然后会被执行resume。

    step 10:ActivityStack.resumeTopActivityLocked()

    在启动MainActivity的ActivityRecord之前,会通知MainActivity的上一个prev处在前台的Activity组件——也就是Launcher用户离开。

    step 11:ActivityStack.startPausingLocked()

    ActivityRecord有一个字段ProcessRecord app,表示其Activity组件所在的进程。ProcessRecord有一个字段ApplicationThreadProxy thread,就是另一个应用程序进程中ApplicationThread的Binder代理对象。

    startPausingLocked()会执行代表Launcher组件所在进程的ProcessRecord变量的方法app.thread.schedulePauseActivity()来通知Launcher组件进入pause状态。

    ActivityRecord prev = mResumedActivity;
    ...
    prev.app.thread.schedulePauseActivity(prev, prev.finishing, userLeaving,
                            prev.configChangeFlags);
    

    上面代码片段中prev就是Launcher对应的组件信息。它是一个IBinder实例,对应Launcher组件。

    因为app.thread.schedulePauseActivity()的执行是一个Binder通信,但指定为FLAG_ONEWAY,所以方法调用会立即返回。当前方法中会使用mHandler发送一个PAUSE_TIMEOUT_MSG的消息:

    // Schedule a pause timeout in case the app doesn't respond.
    // We don't give it much time because this directly impacts the
    // responsiveness seen by the user.
    Message msg = mHandler.obtainMessage(PAUSE_TIMEOUT_MSG);
    msg.obj = prev;
    mHandler.sendMessageDelayed(msg, PAUSE_TIMEOUT);
    

    作为系统进程中的服务,此处AMS没有以同步的Binder通信方式等待Launcher执行pause完成,而是异步地通知Launcher进入pause,然后,它内部使用Handler发送一个延迟消息,在延迟消息收到前若Launcher没有通知AMS已经进入pause,那么AMS做其它处理——认为Launcher未响应。

    step 12:ApplicationThreadProxy.schedulePauseActivity()

    public final void schedulePauseActivity(IBinder token, boolean finished,
           boolean userLeaving, int configChanges) throws RemoteException {
       Parcel data = Parcel.obtain();
       data.writeInterfaceToken(IApplicationThread.descriptor);
       data.writeStrongBinder(token);
       data.writeInt(finished ? 1 : 0);
       data.writeInt(userLeaving ? 1 :0);
       data.writeInt(configChanges);
       mRemote.transact(SCHEDULE_PAUSE_ACTIVITY_TRANSACTION, data, null,
               IBinder.FLAG_ONEWAY);
       data.recycle();
    }
    

    它执行了一个Binder-IPC操作,发送命令code = SCHEDULE_PAUSE_ACTIVITY_TRANSACTION。
    这个进程间操作是FLAG_ONEWAY的,它会立即返回。
    参数token就是AMS中Launcher对应的ActivityRecord对象。

    注意Binder的通信默认是同步的,更多为什么可以先了解下Binder通信。

    以上操作都是在AMS中执行的,AMS在系统进程SystemServer中。所有方法的调用流程图:

    Activity启动流程阶段2

    阶段3:Launcher处理SCHEDULE_PAUSE_ACTIVITY_TRANSACTION

    接下来地的几步操作在Launcher中进行,执行处理AMS发送的SCHEDULE_PAUSE_ACTIVITY_TRANSACTION通信请求。

    方法调用流程如下:

    Activity启动流程阶段3

    Step 13:ApplicationThread.schedulePauseActivity()

    注意系统源码在Binder通信的设计,如果了解AIDL生成的通信接口的实现类和Proxy内部类等,这些Binder-IPC相关的类型都很容易理解。
    类似AMS和ActivityManagerNative等,ApplicationThreadNative在onTransact()中对code = SCHEDULE_PAUSE_ACTIVITY_TRANSACTION的处理是调用接口方法IApplicationThread.schedulePauseActivity()。

    case SCHEDULE_PAUSE_ACTIVITY_TRANSACTION:
    {
        data.enforceInterface(IApplicationThread.descriptor);
        IBinder b = data.readStrongBinder();
        boolean finished = data.readInt() != 0;
        boolean userLeaving = data.readInt() != 0;
        int configChanges = data.readInt();
        schedulePauseActivity(b, finished, userLeaving, configChanges);
        return true;
    }
    

    变量IBinder b就是AMS中Launcher对应的ActivityRecord对象。

    ApplicationThread是ActivityThread的内部类,它继承ApplicationThreadNative,实现了schedulePauseActivity()。

    public final class ActivityThread {
      ...
      private final class ApplicationThread extends ApplicationThreadNative {
        ...
        public final void schedulePauseActivity(IBinder token, boolean finished,
                boolean userLeaving, int configChanges) {
            queueOrSendMessage(
                    finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY,
                    token,
                    (userLeaving ? 1 : 0),
                    configChanges);
        }
      }
    }
    

    可以看到,方法执行queueOrSendMessage()向应用程序Launcher的主线程的消息队列发送一个类型为PAUSE_ACTIVITY的消息。

    Step 14:ActivityThread.queueOrSendMessage()

    public final class ActivityThread {
      ...
      final H mH = new H();
      ...
      private final void queueOrSendMessage(int what, Object obj, int arg1, int arg2) {
         synchronized (this) {
             Message msg = Message.obtain();
             msg.what = what;
             msg.obj = obj;
             msg.arg1 = arg1;
             msg.arg2 = arg2;
             mH.sendMessage(msg);
         }
      }  
    }
    

    ActivityThread的字段mH是在进程主线程中创建的,用来处理应用程序进程中的主线程消息,类H继承Handler。
    因为对Binder方法onTransact()的执行基本是(当跨进程时)在Binder线程池中的线程中执行的,可见这里定义mH就是为了供其它非主线程的操作转到主线程中执行。

    TODO:ActivityThread的创建及其相关知识后面会小结下。

    Step 15:H.handleMessage()

    /**
     * This manages the execution of the main thread in an
     * application process, scheduling and executing activities,
     * broadcasts, and other operations on it as the activity
     * manager requests.
     */
    public final class ActivityThread {
      ...
      private final class H extends Handler {
        ...
        public static final int PAUSE_ACTIVITY          = 101;
    
        public void handleMessage(Message msg) {
           switch (msg.what) {
             ...
             case PAUSE_ACTIVITY:
                handlePauseActivity((IBinder)msg.obj, false, msg.arg1 != 0, msg.arg2);
                ...
                break;
             ...
           }
      }
    }
    

    msg.obj就是AMS中执行ApplicationThreadProxy.schedulePauseActivity()时传递的代表IBinder的ActivityRecord对象。

    Step 16:ActivityThread.handlePauseActivity()

    应用程序进程中启动的每一个Activity组件都使用一个ActivityClientRecord对象描述,其对应AMS中的ActivityRecord对象。ActivityThread的字段mActivities就是。
    方法中,根据AMS传递的表示Launcher组件的token从mActivities获得Launcher对应的ActivityClientRecord对象,通知它执行onUserLeaveHint(),然后是onPause()。
    最后,ActivityManagerNative.getDefault()获得AMS代理对象,通知AMS已经完成对Launcher的pause。

    Step 17:ActivityManagerProxy.activityPaused()

    public void activityPaused(IBinder token, Bundle state) throws RemoteException
    {
       Parcel data = Parcel.obtain();
       Parcel reply = Parcel.obtain();
       data.writeInterfaceToken(IActivityManager.descriptor);
       data.writeStrongBinder(token);
       data.writeBundle(state);
       mRemote.transact(ACTIVITY_PAUSED_TRANSACTION, data, reply, 0);
       reply.readException();
       data.recycle();
       reply.recycle();
    }
    

    执行Binder通信,通知AMS事件code = ACTIVITY_PAUSED_TRANSACTION。

    阶段4 AMS处理ACTIVITY_PAUSED_TRANSACTION

    接下来的操作又转到AMS中进行,从响应ACTIVITY_PAUSED_TRANSACTION事件开始。
    方法调用时序图:

    Activity启动流程阶段4

    Step 18:ActivityManagerService.activityPaused()

    在onTransact()中响应ACTIVITY_PAUSED_TRANSACTION执行的方法。
    请求转给ActivityStack:
    mMainStack.activityPaused(token, icicle, false);
    参数token指向Launcher组件对应的ActivityRecord对象。

    Step 19:ActivityStack.activityPaused()

    根据token从字段mHistory中找到Launcher的ActivityRecord对象,然后设置其为paused。
    继续启动MainActivity。

    Step 20:ActivityStack.completePauseLocked()

    对ActivityRecord prev = mPausingActivity,也就是Launcher的pause完成。
    执行resumeTopActivityLocked(prev)。
    前面的执行中,mHistory中的topActivity就是MainActivity。

    Step 21:ActivityStack.resumeTopActivityLocked()

    此时的topActivity就是MainActivity,其ActivityRecord.app字段为null,因为还未为它创建进程。

    Step 22:ActivityStack.startSpecificActivityLocked()

    在AMS中,每一个Activity组件都有userId和进程名,用户ID是安装该Activity组件的App时由PackageManagerService分配的,进程名由该组件的android:process决定的。
    方法中,AMS检查对应用户ID和进程名的进程是否存在,ProcessRecord app = mService.getProcessRecordLocked(r.processName, r.info.applicationInfo.uid)
    若app为null,就先启动一个App进程,然后通知该进程启动MainActivity。

    Step 23:AMS.startProcessLocked()

    AMS用字段mProcessNames记录已经运行的App进程的信息:

    /**
     * All of the applications we currently have running organized by name.
     * The keys are strings of the application package name (as
     * returned by the package manager), and the keys are ApplicationRecord
     * objects.
     */
    final ProcessMap<ProcessRecord> mProcessNames
            = new ProcessMap<ProcessRecord>();
    

    再次检查对应app进程是否存在:
    ProcessRecord app = getProcessRecordLocked(processName, info.uid)

    如果app为null:

    app = newProcessRecordLocked(null, info, processName);
    mProcessNames.put(processName, info.uid, app);
    

    最后,方法调用一个重载版本继续完成MainActivity的进程的创建。
    startProcessLocked(app, hostingType, hostingNameStr);

    方法首先得到要创建的进程的用户ID和用户组ID,然后执行Process.start()静态函数启动一个新的应用程序进程:

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

    得到的返回值pid是对应启动的App进程的大于0的进程ID。然后将参数app指向的ProcessRecord对象保存在AMS的以pid为key的字典字段mPidsSelfLocked中:

    /**
     * All of the processes we currently have running organized by pid.
     * The keys are the pid running the application.
     *
     * <p>NOTE: This object is protected by its own lock, NOT the global
     * activity manager lock!
     */
    final SparseArray<ProcessRecord> mPidsSelfLocked
            = new SparseArray<ProcessRecord>();
    ....
    
    this.mPidsSelfLocked.put(pid, app);
    

    进程的启动还是异步的,所以这里向AMS使用Handler发送延迟消息PROC_START_TIMEOUT_MSG。
    如果延迟时间后新启动的App进程未通知AMS它启动完成,否则AMS不再继续处理MainActivity的启动。

    阶段5

    接下来就是android应用程序进程启动的过程。
    AMS中执行的Process.start()方法所启动的新进程的程序入口方法是android.app.ActivityThread的静态成员函数main()。
    接下来的方法执行流程如:

    Activity启动流程阶段5

    Step 24:ActivityThread.main

    public final class ActivityThread {
      ...
      final ApplicationThread mAppThread = new ApplicationThread();
      ...
      private final void attach(boolean system) {
        ....
        mSystemThread = system;
        if (!system) {
          ...
          IActivityManager mgr = ActivityManagerNative.getDefault();
          try {
            mgr.attachApplication(mAppThread);
          } catch (RemoteException e) {
          }
        }
        ...
      }
      ...
    
      public static final void main(String[] args) {
        ..
        Looper.prepareMainLooper();
        ...
        ActivityThread thread = new ActivityThread();
        thread.attach(this);
        ...
        Looper.loop();
        ...
      }
    }
    

    创建一个ActivityThread对象,调用其attach()向AMS发送进程启动完成通知。
    开启主线程消息循环。

    ApplicationThread是一个Binder本地对象,AMS使用它的代理和当前App进程通信。
    attachApplication()向AMS通知进程创建完成。

    Step 25:ActivityManagerProxy.attachApplication

    public void attachApplication(IApplicationThread app) throws RemoteException
    {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
        data.writeStrongBinder(app.asBinder());
        mRemote.transact(ATTACH_APPLICATION_TRANSACTION, data, reply, 0);
        reply.readException();
        data.recycle();
        reply.recycle();
    }
    

    向AMS发送ATTACH_APPLICATION_TRANSACTION事件,IApplicationThread app的Binder代理作为AMS对当前ApplicationThread的标识。

    阶段6 AMS响应App进程创建完成通知

    接下来是AMS处理ATTACH_APPLICATION_TRANSACTION事件。
    方法时序图:
    Activity启动流程阶段6

    Step 26:AMS.attachApplication

    public final void attachApplication(IApplicationThread thread) {
       synchronized (this) {
           int callingPid = Binder.getCallingPid();
           final long origId = Binder.clearCallingIdentity();
           attachApplicationLocked(thread, callingPid);
           Binder.restoreCallingIdentity(origId);
       }
    }
    

    callingPid就是为MainActivity创建的新进程的pid。

    Step 27:AMS.attachApplicationLocked

    根据pid得到mPidsSelfLocked中的ProcessRecord app对象。
    得到AMS管理的栈顶topActivity:

    ActivityRecord hr = mMainStack.topRunningActivityLocked(null);
    

    将app设置给MainActivity对应的hr。
    执行mMainStack.realStartActivityLocked(hr, app, true, true)继续启动MainActivity。

    Step 28:ActivityStack.realStartActivityLocked

    这时MainActivity的ActivityRecord r的app字段就是设置过的,不为null。
    topActivity.app.thread就是所创建MainActivity进程中ApplicationThread mAppThread的Binder代理。
    使用topActivity.app.thread.scheduleLaunchActivity()跨进程通知创建的App进程启动MainActivity组件。

    Step 29:ApplicationThreadProxy.scheduleLaunchActivity

    使用IBinder向MainActivity对应进程的mAppThread发送SCHEDULE_LAUNCH_ACTIVITY_TRANSACTION通知。
    消息中记录了要启动的MainActivity的ActivityInfo info。

    阶段7 ActivityThread处理启动MainActivity的请求

    接下来的操作就在为MainActivity所创建的新的App进程中执行。
    前面的ActivityThread.main()的执行使得进程中已经存在mAppThread和创建的ActivityThread thread。
    main方法进入Looper循环。

    将要执行的方法时序图:

    Activity启动流程阶段7

    Step 30:ApplicationThread.scheduleLaunchActivity

    ApplicationThreadNative的onTransact()将对SCHEDULE_LAUNCH_ACTIVITY_TRANSACTION的响应转为ApplicationThread.scheduleLaunchActivity()的调用。

    方法继续使用queueOrSendMessage()将处理打包为msg传给ActivityThread.mH。

    ActivityClientRecord r = new ActivityClientRecord();
    ...
    queueOrSendMessage(H.LAUNCH_ACTIVITY, r);
    

    r就是从AMS端传递过来的MainActivity的信息。

    Step 31:ActivityThread.queueOrSendMessage

    handleMessage()中对消息LAUNCH_ACTIVITY的处理:

    case LAUNCH_ACTIVITY: {
       ActivityClientRecord r = (ActivityClientRecord)msg.obj;
    
       r.packageInfo = getPackageInfoNoCheck(
               r.activityInfo.applicationInfo);
       handleLaunchActivity(r, null);
    

    Step 32:ActivityThread.handleLaunchActivity

    private final void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
      Activity a = performLaunchActivity(r, customIntent);
      ...
      if (a != null) {
              r.createdConfig = new Configuration(mConfiguration);
              Bundle oldState = r.state;
              handleResumeActivity(r.token, false, r.isForward);
      ...
    }
    

    启动MainActivity,然后设置它为resume。

    Step 34:ActivityThread.performLaunchActivity

    原型:
    private final Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent)

    获得关于MainActivity的组件信息:

    ComponentName component = r.intent.getComponent();
    

    然后根据component,使用类加载器实例化Activity对象:

    Activity activity = null;
            try {
                java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
                activity = mInstrumentation.newActivity(
                        cl, component.getClassName(), r.intent);
                r.intent.setExtrasClassLoader(cl);
                if (r.state != null) {
                    r.state.setClassLoader(cl);
                }
            } catch (Exception e) {
            ...
    

    然后创建一个ContextImpl appContext,作为activity的运行上下文环境。

    ContextImpl appContext = new ContextImpl();
    appContext.init(r.packageInfo, r.token, this);
    appContext.setOuterContext(activity);
    

    使用appContext和参数r对activity执行初始化:

    activity.attach(appContext, this, getInstrumentation(), r.token,
         r.ident, app, r.intent, r.activityInfo, title, r.parent,
         r.embeddedID, r.lastNonConfigurationInstance,
         r.lastNonConfigurationChildInstances, config);
    

    然后执行onCreate:

    mInstrumentation.callActivityOnCreate(activity, r.state);
    

    callActivityOnCreate()会调用Activity.onCreate(),这时自定义MainActivity中的setContentView()等逻辑就会被调用。

    activity创建完毕后,对应记录被添加到ActivityThread中:
    mActivities.put(r.token, r);

    ActivityClientRecord r是AMS中对应MainActivity的ActivityRecord对象的Binder代理,它们分别是MainActivity在AMS中和App进程ActivityThread中的描述。

    总结

    经过以上步骤,从Launcher.startActivitySafely()开始到Activity.onCreate()得以执行,可以认为MainActivity组件及其进程已经启动完毕。

    启动的各个阶段

    1. Launcher组件向AMS发送启动MainActivity组件的进程间通信。
    2. AMS首先保存要启动的MainActivity的信息,然后向Launcher发送进入pause状态的进车间通信。
    3. Launcher进入中止状态后,向AMS发送已经进入中止状态的进程间通信请求。这样AMS就继续执行启动MainActivity的操作。
    4. AMS检查用来运行MainActivity的进程不存在,创建并启动一个App进程。
    5. 新进程启动完成后,向AMS发送启动完成的进程间通信请求。
    6. AMS将保存的MainActivity组件的信息发送给创建的新进程。
    7. 新进程启动MainActivity。

    ActivityThread.mH

    ActivityThread的main方法就是整个App进程的入口函数,它执行结束那么App进程就结束了。
    main()中开启了Looper消息循环。

    ActivityThread.mH把很多Binder操作从Binder线程中转到UI线程中执行。

    (本文使用Atom编写)

  • 相关阅读:
    关于Unity中调试C#的方法
    关于Unity的C#基础学习(二)
    关于代码命名规范
    关于Unity的C#基础学习(一)
    关于Unity的游戏的运行模式
    关于Unity的组件和作用
    关于Unity的开发模式
    关于Unity的坐标系
    关于Unity中场景视图的使用
    sql 追踪 神器
  • 原文地址:https://www.cnblogs.com/everhad/p/6246795.html
Copyright © 2011-2022 走看看