Android Activity 的详细启动过程分析

Posted 严振杰

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android Activity 的详细启动过程分析相关的知识,希望对你有一定的参考价值。

android Activity 的详细启动过程分析

版权声明:转载必须注明本文转自严振杰的博客:http://blog.yanzhenjie.com

在正式内容开始之前,我建议读者朋友下载platform/framework/base源代码备用,我们可以到 Android 源码托管站下载:https://android.googlesource.com/,可以下载具体某个模块源代码,可以指定分支或者 tag,需要翻阅 GFW。

另外如果你没有翻阅 GFW 的条件的话,可以使用清华大学镜像源:
https://mirrors.tuna.tsinghua.edu.cn/help/AOSP/

例如,现在我们从 Terminal 进入~/Workspance/Android目录下,然后下载framework/base模块的oreo-release分支源代码:

$ git clone -b oreo-release https://aosp.tuna.tsinghua.edu.cn/platform/frameworks/base framework_base

特别声明:本文出现的源代码,为了更加简洁清晰,部分代码经过大量的精简,读者阅读本文时,如果有条件,最好配合源代码,以免产生误解。


本应该从 Launcher 如何启动一个 App 开始讲起,但是 Launcher 启动一个 App 时也是启动这个 App 的 Luancher Activity,例如:

 <activity
  android:name=".WelcomeActivity">
    <intent-filter>
      <action android:name="android.intent.action.MAIN"/>
      <category android:name="android.intent.category.LAUNCHER"/>
    </intent-filter>
 </activity>

本文包含 App 的启动流程、新进程的启动流程。其实启动一个 App 和启动普通 Activity 一样,如果发现这个 Activity 的进程未启动的话,会启动对应的进程,然后由新的进程来启动这个 Activity,当然这可以单独写一篇文章来分析。但是本文为了降低耦合性让读者更加容易理解 Activity 的启动过程,直接从如何启动一个 Activity 开始讲起。

阅读并理解本文需要读者了解以下知识:

  1. Android 中的消息机制
  2. Binder 的原理和用法
  3. zygote 进程 和 system_server 进程的启动过程
  4. Android 消息机制之同步屏障

Android 消息机制请参考:https://yanzhenjie.blog.csdn.net/article/details/89218745
zygote 进程的启动请参考:https://yanzhenjie.blog.csdn.net/article/details/95539904
Android 消息机制之同步屏障请参考:https://yanzhenjie.blog.csdn.net/article/details/96497153


本文内容

  • AMS 的启动过程
  • startActivity 的执行过程
  • AMS 中 startActivity 的执行过程
  • 启动新进程并运行 ActivityThread
  • AMS 和 ApplicationThread 的通信
  • Application 的初始化
  • 启动 Activity 的流程
  • 执行 Activity 的生命周期
  • Activity 的绘制三连

读完本文后可以了解到的主要内容:

  1. AMS 是什么时候启动的?做了些什么事情?
  2. 普通 App 的进程如何启动的?
  3. ActivityThread 是在那里被执行的?
  4. Application 是什么时候执行的?
  5. Activity 的生命周期是如何在Looper#loop()死循环之外执行的?
  6. Activity 的onCreate()onResume()中为什么不能获取到 View 的宽高?

本文所有章节都配给了相应的流程图辅助理解,极大的提高了读者的理解效率。

来研究本文内容的同学,我相信基础都不会差,至少应该听说过 AMS 吧,AMS 意如其名,是管理 Activity 的系统服务,既然是系统服务,那么应该是在系统启动的时候启动的吧,我们下面来具体看看。

因为 Activity 的启动需要依赖 AMS,所以我们得先了解 AMS 是什么时候启动的,这样才能更加清晰理解 Activity 的启动。

AMS 的启动过程

Linux 系统的所有进程都是init进程的子进程,在 Android 中也不例外,包括zygote也是从init进程 fork 来的,我在Android zygote 进程的启动过程分析一文中详细分析了zygote进程的启动流程,如果不清楚zygote进程启动过流程的同学建议先看看这篇文章,虽然如此,接下来我还是会进行一个简述,方便一些读者会回忆这个过程。

init进程启动后执行位于platform/system/core/init.cpp代码对应的程序,该程序会解析位于platform/system/core/rootdir/init.rc处的配置文件,该配置文件会做一些初始化工作,同时会告诉init进程接着解析init.zygote32.rc或者init.zygote64.rc(具体和设备 CPU 有关),而init.zygote*.rc文件会告诉init进程 fork 一个名为zygote的进程,并指定了其要执行的程序是platform/frameworks/base/cmds/app_process/app_main.cpp代码对应的程序,该程序中最终反射调用了位于 Java 层的com.android.internal.os.ZygoteInit#main()方法,该方法用来初始化zygote进程,在ZygoteInit#main()方法中调用了Zygote#forkSystemServer()创建了system_server进程,并指定system_server进程要执行com.android.sever.SystemServer#main()方法,该方法做的主要的事情如下:

  1. 创建system_server进程的Context(System Context)
  2. 启动 AMS 和 WMS 等系统核心服务
  3. 调用Looper#prepareMainLooper()准备MainLooper
  4. 调用Looper#loop()MainLooper无限循环运行,使system_server进程持续运行

如果读者朋友不清楚zygote进程的启动流程的话,上面的这一段话看起来也许会特别难以理解,因此我还是建议读者先去阅读Android zygote 进程的启动过程分析

在上述总结处第二步的时候就启动了 AMS,如果读者实在不想看 zogyte 进程启动分析,那么我为这些读者朋友准备了一张 AMS 启动时机的流程图:

接下来我们看看 AMS 启动后做了一些什么事情,这样我们才能更加清楚 AMS 角色在系统中的任务。

首先我们看看 AMS 在system_server进程中是如何启动的,代码位于com.android.server.SystemServer#main()

private SystemServiceManager mServiceManager;
private ActivityManagerService mActivityManagerService;

...

private void startBootstrapServices() 
    ...

    // 启动AMS
    SystemService service =
      mServiceManager.startService(ActivityManagerService.Lifecycle.class);

    // 启动AMS后,获取AMS实例
    mActivityManagerService = service.getService();

    ...

    // 注册为系统服务
    mActivityManagerService.setSystemProcess();

  ...

可以看到先调用了SystemServiceManager#startService(Class)方法去启动了 AMS,然后把 AMS 注册为系统服务了,下面我们具体看看SystemServiceManager是如何启动 AMS 的。

/**
 * 根据传入的类名启动对应的服务。
 */
public <T extends SystemService> T startService(Class<T> serviceClass) 
    Constructor<T> constructor = serviceClass.getConstructor(Context.class);
    final T service = constructor.newInstance(mContext);

    startService(service);
    return service;


/**
 * 根据传入的服务实例,启动服务。
 */
public void startService(@NonNull final SystemService service) 
    mServices.add(service);

    service.onStart();

在上述代码中,使用反射获取了ActivityManagerServer中的Lifrcycle类的实例,然后调用了Lifycycle#onStart()方法启动了服务,其实这里是使用了适配器模式,因为系统要管理的服务太多了,每一个服务的启动方法不一定相同,因此系统中其他的服务也是使用适配器模式来管理:

public static final class Lifecycle extends SystemService 

    private final ActivityManagerService mService;

    public Lifecycle(Context context) 
        super(context);
        mService = new ActivityManagerService(context);
    

    @Override
    public void onStart() 
        mService.start();
    

    public ActivityManagerService getService() 
        return mService;
    

接下来我们把目光的焦点回到SystemServer#main()

// 注册为系统服务
mActivityManagerService.setSystemProcess();

注册到系统服务的时候做了些什么事情呢?

public void setSystemProcess() 
    // 把AMS添加到ServiceManager中
    ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true);

    ServiceManager.addService(ProcessStats.SERVICE_NAME, mProcessStats);
    ServiceManager.addService("meminfo", new MemBinder(this));
    ServiceManager.addService("gfxinfo", new GraphicsBinder(this));
    ServiceManager.addService("dbinfo", new DbBinder(this));
    if (MONITOR_CPU_USAGE) 
      ServiceManager.addService("cpuinfo", new CpuBinder(this));
    

    ServiceManager.addService("permission", new PermissionController(this));
    ServiceManager.addService("processinfo", new ProcessInfoService(this));

    ApplicationInfo info = mContext.getPackageManager().getApplicationInfo(
        "android", STOCK_PM_FLAGS | MATCH_SYSTEM_ONLY);
    mSystemThread.installSystemApplicationInfo(info, getClass().getClassLoader());

    synchronized (this) 
        ProcessRecord app = newProcessRecordLocked(info, info.processName, false, 0);
        app.persistent = true;
        app.pid = MY_PID;
        app.maxAdj = ProcessList.SYSTEM_ADJ;
        app.makeActive(mSystemThread.getApplicationThread(), mProcessStats);
        synchronized (mPidsSelfLocked) 
            mPidsSelfLocked.put(app.pid, app);
        
        updateLruProcessLocked(app, false, null);
        updateOomAdjLocked();
    

这里除了把 AMS 添加到ServiceManager中,也添加了一些必要的或者依赖的服务到ServiceManager中,这样系统和开发者就可以很方便的在任何地方获取到 AMS 服务了。

其实 AMS 的启动流程到这里就差不多了,但是为了辅助我们理解的更加深刻,我们还是来看看ServiceManager是如何注册和获取服务的:

/**
 * 获取服务
 */
public static IBinder getService(String name) 
  try 
      IBinder service = sCache.get(name);
      if (service != null) 
          return service;
       else 
          IBinder iBinder = getIServiceManager().getService(name)
          return Binder.allowBlocking(iBinder);
      
     catch (RemoteException e) 
        Log.e(TAG, "error in getService", e);
    
    return null;


/**
 * 注册服务
 */
public static void addService(String name, IBinder service) 
  try 
      getIServiceManager().addService(name, service, false);
   catch (RemoteException e) 
      Log.e(TAG, "error in addService", e);
  

到这里还可以继续深入,但是会脱离本文的中心内容,因此到这里就不再深入。此时,就可以获取 AMS 服务了:

IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
IActivityManager am = IActivityManager.Stub.asInterface(b);

其实在ActivityManager中就是这样做的:

/**
 * 获取AMS服务。
 */
public static IActivityManager getService() 
  return IActivityManagerSingleton.get();


private static final Singleton<IActivityManager> IActivityManagerSingleton =
    new Singleton<IActivityManager>() 
    @Override
    protected IActivityManager create() 
        final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
        final IActivityManager am = IActivityManager.Stub.asInterface(b);
        return am;
    
;

这里使用了单利模式来获取 AMS 服务,AMS 的启动过程到这里就结束了,下面就正式开始分析Activity的启动过程了。

startActivity 的执行过程

我们启动一个Activity时一般都是使用Context这样调用:

Intent intent = new Intent(context, XActivity.class);
context.startActivity(intent);

我们常用的ContextApplicationActivityService,其中ApplicationService直接继承ContextWrapper,而Activity涉及到View所以通过继承ContextThemeWrapper间接的继承了ContextWrapperContextWrapper包装的Context的实现类是ContextImpl。因此我们基本都是调用ContextImple的实现方法去执行startActivity的。

这里面的Activity比较特殊,我们知道Activity中有个startActivityResult()方法,为了扩展这些用法,Activity中重写了startActivity()的几个相关方法:

Instrumentation mInstrumentation;

...

@Override
public void startActivity(Intent intent) 
    startActivityForResult(intent, -1);


@Override
public void startActivity(Intent intent, @Nullable Bundle options) 
    if (options != null) 
        startActivityForResult(intent, -1, options);
     else 
        startActivityForResult(intent, -1);
    


public void startActivityForResult(Intent intent, int requestCode, Bundle options) 
    if (mParent == null) 
        options = transferSpringboardActivityOptions(options);
        ApplicationThread at = mMainThread.getApplicationThread();
        Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity(
          this, at, mToken, this, intent, requestCode, options);
        if (ar != null) 
            mMainThread.sendActivityResult(
              mToken, mEmbeddedID, requestCode,
              ar.getResultCode(), ar.getResultData());
        
        if (requestCode >= 0) 
            mStartedActivity = true;
        

        cancelInputsAndStartExitTransition(options);
     else 
        if (options != null) 
            mParent.startActivityFromChild(this, intent, requestCode, options);
         else 
            mParent.startActivityFromChild(this, intent, requestCode);
        
    

可以看到Activity中调用了Instrumentation#execStartActivity(),不过到这里就会发现我们在startActivityForResult()requestCode的值不能使用-1哦,如果使用-1就接受不到回调啦,这也是很多同学都遇到过的问题。

接下来再看看Context的默认实现是怎么样的,首先要知道的是Context的实现类文件是ContextImpl。还记得文章开头我建议读者朋友下载platform/framework/base代码吧,现在我们打开这个项目,再打开ContextImpl.java文件,可以看到Context#startActivity()的代码:

ActivityThread mMainThread;
Instrumentation mInstrumentation;

...

@Override
public void startActivity(Intent intent) 
    warnIfCallingFromSystemProcess();
    startActivity(intent, null);


@Override
public void startActivity(Intent intent, Bundle options) 
    warnIfCallingFromSystemProcess();

    if ((intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) == 0
        && options != null
        && ActivityOptions.fromBundle(options).getLaunchTaskId() == -1) 
            throw new AndroidRuntimeException(
                "Calling startActivity() from outside of an Activity "
                + " context requires the FLAG_ACTIVITY_NEW_TASK flag."
                + " Is this really what you want?");
    

    Instrumentation instrumentation = mMainThread.getInstrumentation();
    ApplicationThread at = mMainThread.getApplicationThread();
    instrumentation.execStartActivity(getOuterContext(), at, null,
        (Activity) null, intent, -1, options);

同样可以看到Context中调用了Instrumentation#execStartActivity(),不过这里要注意的一点是,当我们使用非ActivityContext(例如 Application、Service 等)启动一个Activity时,如果没有添加Intent.FLAG_ACTIVITY_NEW_TASK标志的话,会抛出一个异常,具体原因后面分析到相应源码时会详细分析。

这里要注意到一点:

ActivityThread mMainThread;

...
ApplicationThread at = mMainThread.getApplicationThread();

ActivityThread是 App 进程对应的程序,它所在就是 App 的默认线程也就主线程,通过getApplicationThread()获取到的对象是主线程在实例化的时候被实例化的ApplicationThread对象,ApplicationThread是每一个 App 进程的 AIDL 服务端,用来管理四大组件的生命周期,具体后面分析到ActivityThread的启动过程时再说。

上述的调用逻辑都比较简单,我们跟踪到Instrumentation里面一步步看最终调用到了哪里:

public ActivityResult execStartActivity( Context who, IBinder contextThread,
    IBinder token, Activity target, Intent intent,
    int requestCode, Bundle options) 

    IApplicationThread whoThread = (IApplicationThread) contextThread;

    ...

    try 
        intent.migrateExtraStreamToClipData();
        intent.prepareToLeaveProcess(who);
        int result = ActivityManager.getService().startActivity(whoThread,
            who.getBasePackageName(), intent,
            intent.resolveTypeIfNeeded(who.getContentResolver()),
            token, target != null ? target.mEmbeddedID : null,
            requestCode, 0, null, options);
        checkStartActivityResult(result, intent);
     catch (RemoteException e) 
        throw new RuntimeException("Failure from system", e);
    
    return null;

可以看到这里最终调用了ActivityManager.getService().startActivity(),如果读者看了上文中AMS 的启动过程就知道,这里是获取了IActivityManager实例,IActivityManager基于 AIDL 实现 Binder,如果读者朋友了解 Binder 的话就会知道,因为 App 进程和 AMS 的进程system_server不是同一个进程,所以这里获取到的是 AMS 的IActivityManger在服务端代理,不过这里还会远程调用到 AMS 中去。

AMS 中 startActivity 的执行过程

AMS 作为系统服务,管理的不仅仅是某一个 App 的组件,因此它里面的逻辑是相当复杂的,在这里我们还是根据上文中的调用顺序继续查看源代码。

在看代码之前,我们要明白一点,此时调用已经是 App 进程在进行远程调用了,也就是 App 进程调用了是system_server进程里面的 AMS 服务的方法:

ActivityStarter mActivityStarter;

@Override
public final int startActivity(IApplicationThread caller, String callingPackage,
    Intent intent, String resolvedType, IBinder resultTo,
    String resultWho, int requestCode, int startFlags,
    ProfilerInfo profilerInfo, Bundle bOptions) 

    return startActivityAsUser(caller, callingPackage, intent, resolvedType,
        resultTo, resultWho, requestCode, startFlags, profilerInfo,
        bOptions, UserHandle.getCallingUserId());


@Override
public final int startActivityAsUser(IApplicationThread caller,
    String callingPackage, Intent intent, String resolvedType,
    IBinder resultTo, String resultWho, int requestCode, int startFlags,
    ProfilerInfo profilerInfo, Bundle bOptions, int userId) 

    enforceNotIsolatedCaller("startActivity");
    userId = mUserController.handleIncomingUser(Binder.getCallingPid(),
        Binder.getCallingUid(), userId, false, ALLOW_FULL_ONLY,
        "startActivity", null);

    // 调用了这里
    return mActivityStarter.startActivityMayWait(caller, -1,
        callingPackage, intent, resolvedType, null, null, resultTo,
        resultWho, requestCode, startFlags, profilerInfo, null, null,
        bOptions, false, userId, null, null, "startActivityAsUser");

我们知道 Linux 中 pid 表示进程 id,uid 用来表示用户 id,而 Android 是单用户系统,所以 uid 基本被用来标记应用,而一个应用中可能有多个进程,所以一个应用有一个 uid,但是可能有多个 pid。

在这里处理了 uid 之后从AMS中出来,走入了ActivityStarter,这列调用了ActivityStarter#startActivityMayWait()方法:

private final ActivityManagerService mService;

final int startActivityMayWait(IApplicationThread caller, int callingUid,
    String callingPackage, Intent intent, String resolvedType,
    IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
    IBinder resultTo, String resultWho, int req

以上是关于Android Activity 的详细启动过程分析的主要内容,如果未能解决你的问题,请参考以下文章

Android Activity 的详细启动过程分析

android6.0源码分析之Activity启动过程

android6.0源码分析之Activity启动过程

Android应用程序启动过程源代码分析

Android应用程序启动过程源代码分析

Android: Activity启动模式 FLAG_ACTIVITY_NEW_TASK 详细探索