Activity启动流程源码分析

Android窗口机制之由setContentView引发的Window,PhoneWindow,DecorView源码理解

Activity启动流程源码分析

简单分析Binder工作机制

开始之前看一下从Luanch启动一个主Activity的流程图,也就是从ActivityThread的main方法开始,都知道App的启动就是从ActivityThread的main方法开始:


app启动流程.png

也就说在从Luanch开始调用了ActivityThread的main方法,当然在这之前还有很多的初始化操作,暂时不分析,从main方法开始,其中包括创建Application和进程信息的初始化操作,当然这是和普通的启动Activity有一定的区别。

此文章基于AIP25源码,既然我们Activity启动流程源码分析,那么在开始之前我们应该认识一下与Activity启动相关的类,先看类图:

activity启动流程相关类图.png

图画的有点乱,但不影响我们分析Activity启动流程,可以看到图中涉及到的类并不多,其中涉及了Binder的相关的知识点,毕竟应用需要和系统服务进程交互,这是Android给我们提供的跨进程通信的机制,当然如果对AIDL和Binder不是很熟悉的话,可以去脑补一下。

  • IBinder 是一个接口,Binder类实现了它,而Binder是一个抽象类。

  • IInterface 是一个接口,AIDL接口必须实现它。

  • asInterface() 从BinderProxy获取一个IInterface对象(Stub$Proxy);

  • asBinder() 获取IInteface接口所关联的得BinderProxy;

  • Binder是一个抽象类实现了IBinder,Binder是Android中跨进程通讯的方式,AIDL是最常用的夸进程通讯方式,它是对Binder的封装,AIDL是App和系统基础宁通信的基石,消息机制和AIDL构成Android系统中最核心的两个部分,Binder会和一个BinderProxy对象相关联,

  • IActivityManager 用于与AMS交互的系统级私有API, 提供了从应用程序返回活动管理器的调用。简单说就是定义操作四大组件相关的的API。

  • ActivityManagerNative 继承了Binder类并且实现IActivityManager,这里的IActivityManager实际上和ActivityManager并没有太大的联系,不过ActivityManager里面有些操作会用到ActivityManagerNative ,而ActivityManagerNative 是操作Activity的主要类,可以这么说ActivityManager封装了ActivityManagerNative 的部分功能。

  • ActivityManager它主要对运行中的Activity进行管理,这些管理工作并不是由ActivityManager来处理的, 而是交由AMS来处理,ActivityManager中的方法会通过ActivityManagerNative(简称AMN)的getDefault方法来得到ActivityManagerProxy(简称AMP),通过AMP就可以和AMN进行通信,而AMN是一个抽象类,它会将功能交由它的子类AMS来处理,所以AMP就是AMS的代理类,这句话一定要记住。AMS作为系统核心服务,很多API是不会暴露给ActivityManager的,因此ActivityManager并不算是AMS家族一份子。

  • ActivityManagerService 作为系统核心服务,并且它继承了ActivityManagerNative,AMS其实是一个Binder类,既然ActivityManagerNative是抽象基类,所以基本操作已经做完了,其余就交给子类完成,比如:AMN做了Binder的机制的操作,而AMS即不需要再做这些,只要关注自己的业务就行了,这样的好处是职责明确。

  • IApplicationThread、ApplicationThreadNative、ApplicationThreadProxy和ApplicationThread,ApplicationThread是ActivityThread的内部类,其实这些的作用是和AMS族的机制是一样的,比如IApplicationThread,定义了基本的接口,而其他的就是Binder相关的,最后ApplicationThread也是ApplicationThreadNative的子类,ApplicationThreadNative主要负责Binder相关的处理,而ApplicationThread则做自己的逻辑,即:ApplicationThread是Client的Bider,服务如果要操作Client端需要通过ApplicationThread去操作,毕竟是夸进程的通讯嘛,在捋一下,IApplicationThread继承了IInterface接口,它实现类是ApplicationThreadNative继承了Binder类,他是一个抽象类,它仅仅只做了和Binder相关的操作,而 它的子类是ApplicationThread,就是说如果系统服务如AMS想要通知启动Activity,那就要调用ApplicationThread客户端的Binder通信。

  • Instrumentation 监控应用程序和系统服务的交互

给大家先讲解这些类,是给大家有个印象,看下去就不会很蒙圈接下来就正是开始吧,先从Activity.startActivity开始。

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

startActivity根据options选择调用startActivityForResult函数,其中第二个参数requestCode为-1,表示Launcher不需要知道Activity启动的结果,也就是当requestCode>0时,当activity退出时会回调onActivityResult方法,startActivityForResult函数的代码如下所示。

 public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
        @Nullable Bundle options) {
    if (mParent == null) {
        options = transferSpringboardActivityOptions(options);

        Instrumentation.ActivityResult ar =
            mInstrumentation.execStartActivity(
                this, mMainThread.getApplicationThread(), mToken, this,
                intent, requestCode, options);

    //............
    } else {
      //..........
    }
}

为了简介我把部分代码删掉,只留下比较重要的,mParent是Activity类型的,表示当前Activity的父类。因为当前的Activity还没有创建出来,mParent == null成立。接着调用Instrumentation的execStartActivity方法, Instrumentation主要用来监控应用程序和系统服务的交互。

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

    //注意这里contextThread,是从Activity中传进来的ApplicationThread,后面就是使用它发送消息启动Activity的
    IApplicationThread whoThread = (IApplicationThread) contextThread;
    try {
        intent.migrateExtraStreamToClipData();
        intent.prepareToLeaveProcess(who);

        //获取AMS的代理对象
        IActivityManager aDefault = ActivityManagerNative.getDefault();

        //调用代理对象的startActivity,执行transact执行RPC操作
        int result = aDefault.startActivity(whoThread, who.getBasePackageName(), intent,
                intent.resolveTypeIfNeeded(who.getContentResolver()),
                token, target != null ? target.mEmbeddedID : null,
                requestCode, 0, null, options);
        //检查启动Activity的结果
        checkStartActivityResult(result, intent);
    } catch (RemoteException e) {
        throw new RuntimeException("Failure from system", e);
    }
    return null;
}

首先会调用ActivityManagerNative的getDefault来获取ActivityManageService(后面简称为AMS)的代理对象AMN,接着调用它的startActivity方法。首先我们先来查看ActivityManagerNative的getDefault方法做了什么:

 static public IActivityManager getDefault() {
    return gDefault.get();
}
private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
    protected IActivityManager create() {

        //通过名称获取一个service的应用,这里就是AMS
        IBinder b = ServiceManager.getService("activity");//1
        //返回的是一个持有AMS的引用的代理对象
        IActivityManager am = asInterface(b);//2
        return am;
    }
};
static public IActivityManager asInterface(IBinder obj) {
    if (obj == null) {
        return null;
    }
    //AMS
    IActivityManager in = (IActivityManager) obj.queryLocalInterface(descriptor);
    if (in != null) {
        //返回当前ActivityManagerNative
        return in;
    }
    //服务端的代理,返回ActivityManagerProxy,执行transat
    //将返回的AMS的封装成代理
    return new ActivityManagerProxy(obj);
}

getDefault方法调用了gDefault的get方法,gDefault 是一个Singleton类的实例。在1处获取名子为”activity”的Service引用,也就是IBinder类型的ActivityManagerService的引用。接着在2处将它封装成ActivityManagerProxy类型对象,getService方法是有缓存的,此后调用ActivityManagerNative的getDefault方法就会直接获得AMS的代理AMP对象。
回到Instrumentation类的execStartActivity方法中,从上面得知就是调用AMP的startActivity,其中AMP是ActivityManagerNative的内部类,代码如下所示。

/**
 * 首先会将传入的参数写入到Parcel类型的data中。
 * 通过IBinder类型对象mRemote(AMS的引用)向服务端的AMS发送一个START_ACTIVITY_TRANSACTION类型的进程间通信请求。
 * 那么服务端AMS就会从Binder线程池中读取我们客户端发来的数据,最终会调用AMN的onTransact方法,onTransact中会调用AMS的startActivity方法,
 */
public int startActivity(IApplicationThread caller, String callingPackage, Intent intent,
                         String resolvedType, IBinder resultTo, String resultWho, int requestCode,
                         int startFlags, ProfilerInfo profilerInfo, Bundle options) throws RemoteException {
    Parcel data = Parcel.obtain();
    Parcel reply = Parcel.obtain();
    data.writeInterfaceToken(IActivityManager.descriptor);
    data.writeStrongBinder(caller != null ? caller.asBinder() : null);
    data.writeString(callingPackage);
    intent.writeToParcel(data, 0);
    data.writeString(resolvedType);
    data.writeStrongBinder(resultTo);
    data.writeString(resultWho);
    data.writeInt(requestCode);
    data.writeInt(startFlags);
    if (profilerInfo != null) {
        data.writeInt(1);
        profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
    } else {
        data.writeInt(0);
    }
    if (options != null) {
        data.writeInt(1);
        options.writeToParcel(data, 0);
    } else {
        data.writeInt(0);
    }


    //首先会将传入的参数写入到Parcel类型的data中。
    // 在注释1处通过IBinder类型对象mRemote向AMS发送一个START_ACTIVITY_TRANSACTION类型的进程间通信请求。
    // 那么服务端AMS就会从Binder线程池中读取我们客户端发来的数据,
    // 最终会调用ActivityManagerNative的onTransact方法中执行

    //发起RPC过程 ,这里是会阻塞的,等待transact结束


    //实际上会调用ActivityManagerService的onTransact,之后又回调ActivityManagerNative的onTransact,然后在onTransact中有调用ActivityManagerService的startActivity方法
    mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);//1
    //  接着从_reply中取出RPC过程返回的结果
    reply.readException();
    //  最后返回_reply中的数据
    int result = reply.readInt();

    reply.recycle();
    data.recycle();
    return result;
}

其实注释写得也是还可以的,首先会将传入的参数写入到Parcel类型的data中,大家知道Binder支持的类型也就那几种。在1处通过IBinder类型对象mRemote向AMS发送一个START_ACTIVITY_TRANSACTION类型的进程间通信请求。那么服务端AMS就会从Binder线程池中读取我们客户端发来的数据,最终会调用ActivityManagerNative的onTransact方法中执行。如下所示。

 @Override
public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
        throws RemoteException {
    switch (code) {

        //通过code知道client调用的目标方法
        case START_ACTIVITY_TRANSACTION: {
            data.enforceInterface(IActivityManager.descriptor);
            IBinder b = data.readStrongBinder();


            //这行代码也是获取到了持有ApplicationThread引用的代理对象,然后传给AMS,以便启动Activity,如:scheduleLaunchActivity
            IApplicationThread app = ApplicationThreadNative.asInterface(b);


            //获取Client传过来的数据
            String callingPackage = data.readString();
            Intent intent = Intent.CREATOR.createFromParcel(data);
            ..........................................
            //调用ActivityNamagerService,具体实现在AMS中,启动ACtivity
            int result = startActivity(app, callingPackage, intent, resolvedType,
                    resultTo, resultWho, requestCode, startFlags, profilerInfo, options);

            //启动完成将结果写入reply,通过Client的启动activity的结果
            reply.writeNoException();
            reply.writeInt(result);
            return true;
        }

}

onTransact中会调用AMS的startActivity方法不是AMN中的startActivity了,我刚开始看得时候就是这想的哈哈,如下所示。

  @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);
    // TODO: Switch to user app stacks here.
    return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,
            resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
            profilerInfo, null, null, bOptions, false, userId, null, null);
}

在AMS中startActivity有再次调用startActivityAsUser方法,startActivityAsUser方法中又调用了mActivityStarter的startActivityMayWait方法:这里的调用关系非常多,我直接写得简洁的,就看重点:AMS.startActivity->AMS.startActivityAsUser
->ActivityStack.startActivityMayWait->ActivityStack.startActivityLocked
->ActivityStack.doPendingActivityLaunchesLocked
->ActivityStack.startActivityUnchecked
->ActivityStackSupervisor.resumeFocusedStackTopActivityLocked
->ActivityStackSupervisor.resumeFocusedStackTopActivityLocked
->ActivityStack.resumeTopActivityUncheckedLocked
->ActivityStack.resumeTopActivityInnerLocked
->ActivityStackSupervisor.startSpecificActivityLocked
->ActivityStackSupervisor.realStartActivityLocked

最后看看ActivityStackSupervisor.realStartActivityLocked方法的代码:

final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
        boolean andResume, boolean checkConfig) throws RemoteException {

  ........................


  app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
                System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),
                new Configuration(task.mOverrideConfig), r.compat, r.launchedFromPackage,
                task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results,
                newIntents, !andResume, mService.isNextTransitionForward(), profilerInfo);

...................

return true;
}

这里的 app.thread指的是IApplicationThread,它的实现是ActivityThread的内部类ApplicationThread,其中ApplicationThread继承了ApplicationThreadNative,而ApplicationThreadNative继承了Binder并实现了IApplicationThread接口,所以我们抓重点,去看看那ActivityThread的内部类ApplicationThread的scheduleLaunchActivity方法,代码如下所示:

    //ams最终回调这个方法启动Activity
    @Override
    public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
                                             ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
                                             CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,
                                             int procState, Bundle state, PersistableBundle persistentState,
                                             List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
                                             boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {

        ActivityClientRecord r = new ActivityClientRecord();

        //发送消息启动Activity
        sendMessage(H.LAUNCH_ACTIVITY, r);
    }

为了简介我删掉了很多无用的代码,所以AMS最终调用ActivityThread的内部类ApplicationThread的scheduleLaunchActivity方法sendMessage发消息启动Activity,sendMessage方法如下:

private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
    if (DEBUG_MESSAGES) Slog.v(
            TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
                    + ": " + arg1 + " / " + obj);
    Message msg = Message.obtain();
    msg.what = what;
    msg.obj = obj;
    msg.arg1 = arg1;
    msg.arg2 = arg2;
    if (async) {
        msg.setAsynchronous(true);
    }
    mH.sendMessage(msg);
}

可以看到最终调用mH的sendMessage,mH是Activity的内部类H,继承了Handler,看看handleMesage:

 public void handleMessage(Message msg) {
        if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
        switch (msg.what) {
            case LAUNCH_ACTIVITY: {
                //最终启动Activity
                final ActivityClientRecord r = (ActivityClientRecord) msg.obj;

                handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
            }
            break;
    .......................
}

最终调用了handleLaunchActivity。代码如下所示:

 //运行Activity开始的地方,就是Activity的生命周期的开始
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
    // If we are getting ready to gc after going to the background, well
    // we are back active so skip it.
    unscheduleGcIdler();
    mSomeActivitiesChanged = true;

    if (r.profilerInfo != null) {
        mProfiler.setProfiler(r.profilerInfo);
        mProfiler.startProfiling();
    }

    // Make sure we are running with the most recent config.
    handleConfigurationChanged(null, null);

    if (localLOGV) Slog.v(
            TAG, "Handling launch of " + r);

    // Initialize before creating the activity
    WindowManagerGlobal.initialize();

    Activity a = performLaunchActivity(r, customIntent);

    if (a != null) {
        r.createdConfig = new Configuration(mConfiguration);
        reportSizeConfigurations(r);
        Bundle oldState = r.state;
        handleResumeActivity(r.token, false, r.isForward,
                !r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);

        if (!r.activity.mFinished && r.startsNotResumed) {
            // The activity manager actually wants this one to start out paused, because it
            // needs to be visible but isn't in the foreground. We accomplish this by going
            // through the normal startup (because activities expect to go through onResume()
            // the first time they run, before their window is displayed), and then pausing it.
            // However, in this case we do -not- need to do the full pause cycle (of freezing
            // and such) because the activity manager assumes it can just retain the current
            // state it has.
            performPauseActivityIfNeeded(r, reason);

            // We need to keep around the original state, in case we need to be created again.
            // But we only do this for pre-Honeycomb apps, which always save their state when
            // pausing, so we can not have them save their state when restarting from a paused
            // state. For HC and later, we want to (and can) let the state be saved as the
            // normal part of stopping the activity.
            if (r.isPreHoneycomb()) {
                r.state = oldState;
            }
        }
    } else {
        // If there was an error, for any reason, tell the activity manager to stop us.
        try {
            ActivityManagerNative.getDefault()
                    .finishActivity(r.token, Activity.RESULT_CANCELED, null,
                            Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
        } catch (RemoteException ex) {
            throw ex.rethrowFromSystemServer();
        }
    }
}

到这一步实际上Activity的启动基本就结束了,接下来就是初始化Activity的窗口主题和视图,这些下篇文章讲解,最后看一下时序图,会更好理解,第一次画图,很丑:

activity启动流程.png

说一下代理模式:代理模式就是多一个代理类出来,替原对象进行一些操作,比如:ActivityManagerNative的代理类ActivityManagerProxy而它们俩都实现了IActivityManager接口,ActivityManagerService是ActivityManagerNative的子类,所以ActivityManagerProxy代理的是ActivityManagerService,在系统服务中大量使用了代理模式去实现Binder的通信,Android系统涉及到Binder的都大量用到了静态代理。

最后,我觉得看完Activity启动的流程,再看Android窗口机制之由setContentView引发的Window,PhoneWindow,DecorView源码理解这篇文章,基本上从Activity启动流程到Activity的初始化和窗口创建以及视图的填充基都会更加的深入。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335

推荐阅读更多精彩内容