前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >笔记:Activity的启动过程

笔记:Activity的启动过程

作者头像
用户1172465
发布2018-01-08 14:19:01
1.3K0
发布2018-01-08 14:19:01
举报
文章被收录于专栏:everhadeverhad

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时:

代码语言:javascript
复制
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之后:

代码语言:javascript
复制
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()

代码语言:javascript
复制
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()

代码语言:javascript
复制
// 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()

代码语言:javascript
复制
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。

代码语言:javascript
复制
/**
* 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):

代码语言:javascript
复制
/**
 * 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()

代码语言:javascript
复制
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组件的信息。
代码语言:javascript
复制
/**
 * An entry in the history stack, representing an activity.
 */
class ActivityRecord extends IApplicationToken.Stub {
}

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

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

Activity启动流程-阶段1
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():

代码语言:javascript
复制
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()

代码语言:javascript
复制
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()

代码语言:javascript
复制
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状态。

代码语言:javascript
复制
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的消息:

代码语言:javascript
复制
// 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()

代码语言:javascript
复制
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
Activity启动流程阶段2

阶段3:Launcher处理SCHEDULE_PAUSE_ACTIVITY_TRANSACTION

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

方法调用流程如下:

Activity启动流程阶段3
Activity启动流程阶段3

Step 13:ApplicationThread.schedulePauseActivity()

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

代码语言:javascript
复制
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()。

代码语言:javascript
复制
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()

代码语言:javascript
复制
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()

代码语言:javascript
复制
/**
 * 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()

代码语言:javascript
复制
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
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进程的信息:

代码语言:javascript
复制
/**
 * 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:

代码语言:javascript
复制
app = newProcessRecordLocked(null, info, processName);
mProcessNames.put(processName, info.uid, app);

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

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

代码语言:javascript
复制
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中:

代码语言:javascript
复制
/**
 * 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
Activity启动流程阶段5

Step 24:ActivityThread.main

代码语言:javascript
复制
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

代码语言:javascript
复制
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
Activity启动流程阶段6

Step 26:AMS.attachApplication

代码语言:javascript
复制
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:

代码语言:javascript
复制
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
Activity启动流程阶段7

Step 30:ApplicationThread.scheduleLaunchActivity

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

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

代码语言:javascript
复制
ActivityClientRecord r = new ActivityClientRecord();
...
queueOrSendMessage(H.LAUNCH_ACTIVITY, r);

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

Step 31:ActivityThread.queueOrSendMessage

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

代码语言:javascript
复制
case LAUNCH_ACTIVITY: {
   ActivityClientRecord r = (ActivityClientRecord)msg.obj;

   r.packageInfo = getPackageInfoNoCheck(
           r.activityInfo.applicationInfo);
   handleLaunchActivity(r, null);

Step 32:ActivityThread.handleLaunchActivity

代码语言:javascript
复制
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的组件信息:

代码语言:javascript
复制
ComponentName component = r.intent.getComponent();

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

代码语言:javascript
复制
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的运行上下文环境。

代码语言:javascript
复制
ContextImpl appContext = new ContextImpl();
appContext.init(r.packageInfo, r.token, this);
appContext.setOuterContext(activity);

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

代码语言:javascript
复制
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:

代码语言:javascript
复制
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线程中执行。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017-01-03 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Activity的创建特点
  • Launcher启动App
  • Task和Back Stack
    • Task
      • ActivityStack
      • 启动过程跟踪
        • 阶段1:Launcher通知AMS启动MainActivity。
          • step 1:Launcher.startActivitySafely()
          • step 2:Activity.startActivity(intent)
          • step 3:Activity.startActivityForResult(intent, -1)
          • step 4:Instrumentation.execStartActivity()
          • step 5:ActivityManagerProxy.startActivity()
        • 阶段2:AMS保存启动信息,通知caller进入stop
          • step 6:ActivityManagerService.startActivity()
          • step 7:ActivityStack.startActivityMayWait()
          • step 8:ActivityStack.startActivityLocked()
          • step 9:ActivityStack.startActivityUncheckedLocked()
          • step 10:ActivityStack.resumeTopActivityLocked()
          • step 11:ActivityStack.startPausingLocked()
          • step 12:ApplicationThreadProxy.schedulePauseActivity()
        • 阶段3:Launcher处理SCHEDULE_PAUSE_ACTIVITY_TRANSACTION
          • Step 13:ApplicationThread.schedulePauseActivity()
          • Step 14:ActivityThread.queueOrSendMessage()
          • Step 15:H.handleMessage()
          • Step 16:ActivityThread.handlePauseActivity()
          • Step 17:ActivityManagerProxy.activityPaused()
        • 阶段4 AMS处理ACTIVITY_PAUSED_TRANSACTION
          • Step 18:ActivityManagerService.activityPaused()
          • Step 19:ActivityStack.activityPaused()
          • Step 20:ActivityStack.completePauseLocked()
          • Step 21:ActivityStack.resumeTopActivityLocked()
          • Step 22:ActivityStack.startSpecificActivityLocked()
          • Step 23:AMS.startProcessLocked()
        • 阶段5
          • Step 24:ActivityThread.main
          • Step 25:ActivityManagerProxy.attachApplication
        • 阶段6 AMS响应App进程创建完成通知
          • Step 26:AMS.attachApplication
          • Step 27:AMS.attachApplicationLocked
          • Step 28:ActivityStack.realStartActivityLocked
          • Step 29:ApplicationThreadProxy.scheduleLaunchActivity
          • Step 30:ApplicationThread.scheduleLaunchActivity
          • Step 31:ActivityThread.queueOrSendMessage
          • Step 32:ActivityThread.handleLaunchActivity
          • Step 34:ActivityThread.performLaunchActivity
      • 阶段7 ActivityThread处理启动MainActivity的请求
      • 总结
        • 启动的各个阶段
          • ActivityThread.mH
          相关产品与服务
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档