笔记: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编写)

posted @ 2017-01-03 22:36  everhad  阅读(554)  评论(0编辑  收藏  举报