Activity发动流程因为篇幅较长,将分述两篇文章进行解说。

上文主要进行概念提要和流程总述,下文主要从源码视点逐步探寻流程经过

一文搞定面试 | Activity发动流程之冷热发动(上)

一文搞定面试 | Activity发动流程之冷热发动(下)

一图看懂

在上一篇中,已经大致将流程从概念上进行梳理了一遍,在结束中给出了这么一张图,那么本文将从源码视点还原这张图的全部流程和细节。本文依据Android 31源码进行解析

一文搞定面试 | Activity启动流程之冷热启动(下)

图片取自 # Android Application 发动流程剖析及其源码调用探求

源码深入

startActivity的起点

关于Launcher点击使用图标来说,也是startActivity的调用。终究均经过Instrumentation这个工具类,向AMS建议startActivity的Binder通讯行为

// Activity.java
public void startActivity(Intent intent) {
    this.startActivity(intent, null);
}
startActivity
    >>>startActivityForResult(这儿有许多分支,但终究都会走下一路径)
        >>>Instrumentation.execStartActivity
// Instrumentation.java
public ActivityResult execStartActivity(
        Context who, IBinder contextThread, IBinder token, Activity target,
        Intent intent, int requestCode, Bundle options) {
    // ……
    IApplicationThread whoThread = (IApplicationThread) contextThread;
    // ……
    // 留意下面的ActivityTaskManager.getService()
    // 这儿即相当于调用了AMS的startActivity()
    // 同时重视下第一个参数,whoThread,传入的是IApplicationThread目标,而这个来源于Activity对应的ActivityThread里的mAppThread
    // 也便是使用进程创立之初创立的主线程,而IApplicationThread是Stub,即Binder的服务端
    // 这儿留个心眼,后边有呼应
    int result = ActivityTaskManager.getService().startActivity(whoThread,
            who.getOpPackageName(), who.getAttributionTag(), intent,
            intent.resolveTypeIfNeeded(who.getContentResolver()), token,
            target != null ? target.mEmbeddedID : null, requestCode, 0, null, options);
    // ……
}
public static IActivityTaskManager getService() {
    return IActivityTaskManagerSingleton.get();
}
@UnsupportedAppUsage(trackingBug = 129726065)
private static final Singleton<IActivityTaskManager> IActivityTaskManagerSingleton =
        new Singleton<IActivityTaskManager>() {
            @Override
            protected IActivityTaskManager create() {
                // 这儿从ServiceManager中获取到了ACTIVITY_TASK_SERVICE即AMS的Binder目标,并终究将其包装成Proxy回来供外部调用
                final IBinder b = ServiceManager.getService(Context.ACTIVITY_TASK_SERVICE);
                return IActivityTaskManager.Stub.asInterface(b);
            }
        };

AMS创立Activity环节

AMS中的startActivity现在均交由ActivityTaskManagerService进行代理,当时已进入System Server进程,在该流程return前,Client即建议startActivity的使用进程均处于挂起状态

// ActivityTaskManagerService.java
public final int startActivity(IApplicationThread caller, String callingPackage,
        String callingFeatureId, Intent intent, String resolvedType, IBinder resultTo,
        String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo,
        Bundle bOptions) {
    return startActivityAsUser(caller, callingPackage, callingFeatureId, intent, resolvedType,
            resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions,
            UserHandle.getCallingUserId());
}
ActivityTaskManagerService.startActivity() >>> startActivityAsUser()
        >>> ActivityStarter.execute() >>> executeRequest() >>> startActivityUnchecked() >>> startActivityInner()
            >>> RootWindowContainer.resumeFocusedTasksTopActivities()
                >>> Task.resumeTopActivityUncheckedLocked() >>> resumeTopActivityInnerLocked()
                    >>> ActivityTaskSupervisor.startSpecificActivity()
// ActivityStarter.java 
// 这个类的含义很好了解,发动器嘛
private int executeRequest(Request request) {
    // ……这个办法内能够看到 确定Intent和flag应怎么转换为活动以及相关的使命和仓库
    // r是新build出来的ActivityRecord目标
    startActivityUnchecked(r, sourceRecord, voiceSession,
            request.voiceInteractor, startFlags, true /* doResume */, checkedOptions, inTask,
            restrictedBgActivity, intentGrants);
}
// ActivityTaskSupervisor.java
// 这是之前说到过的大管家
void startSpecificActivity(ActivityRecord r, boolean andResume, boolean checkConfig) {
    // Is this activity's application already running?
    final WindowProcessController wpc =
            mService.getProcessController(r.processName, r.info.applicationInfo.uid);
    boolean knownToBeDead = false;
    if (wpc != null && wpc.hasThread()) {
        // 热发动和暖发动流程,最后会一起说到,先不讲,先继续看冷发动fork进程
        try {
            realStartActivityLocked(r, wpc, andResume, checkConfig);
            return;
        } catch (RemoteException e) {
            Slog.w(TAG, "Exception when starting activity "
                    + r.intent.getComponent().flattenToShortString(), e);
        }
        // If a dead object exception was thrown -- fall through to
        // restart the application.
        knownToBeDead = true;
    }
    r.notifyUnknownVisibilityLaunchedForKeyguardTransition();
    // 冷发动,创立使用进程
    final boolean isTop = andResume && r.isTopRunningActivity();
    // 这一块关于socket是怎么发送的,待弥补
    mService.startProcessAsync(r, knownToBeDead, isTop, isTop ? "top-activity" : "activity");
}

Zygote孵化使用进程

Zygote的主要职责便是孵化进程,其间包含管理AMS的System Server进程也由它进行孵化。通讯选用Soceket Server继续监听。新的子使用进程孵化完成后,将会反射调用ActivityThread.main()

// ZygoteInit.java
// Zygote进程发动类
public static void main(String[] argv) {
    caller = zygoteServer.runSelectLoop(abiList);
}
// ZygoteServer.java
// Zygote Socket服务端
Runnable runSelectLoop(String abiList) {
    while (true) {
        // connect便是AMS Client建议的连接恳求
        try {
            ZygoteConnection connection = peers.get(pollIndex);
            final Runnable command =
                    connection.processCommand(this, multipleForksOK);
        } catch (Exception e) {
            // 这儿贴一段官方注释,留意processCommand将会履行ActivityThread的main办法
            // We're in the child so any exception caught here has happened post
            // fork and before we execute ActivityThread.main (or any other
            // main() method). Log the details of the exception and bring down
            // the process.
        }
    }
}
// ZygoteConnection.java
Runnable processCommand(ZygoteServer zygoteServer, boolean multipleOK) {
    // 我们的目的是为了看进程fork,所以找关键词:进程号pid
    // 这儿Zygote完成了子进程fork创立
    // 然后依据该办法内的注释,我们又重视到了handleChildProc()
    pid = Zygote.forkAndSpecialize(parsedArgs.mUid, parsedArgs.mGid,
            parsedArgs.mGids, parsedArgs.mRuntimeFlags, rlimits,
            parsedArgs.mMountExternal, parsedArgs.mSeInfo, parsedArgs.mNiceName,
            fdsToClose, fdsToIgnore, parsedArgs.mStartChildZygote,
            parsedArgs.mInstructionSet, parsedArgs.mAppDataDir,
            parsedArgs.mIsTopApp, parsedArgs.mPkgDataInfoList,
            parsedArgs.mAllowlistedDataInfoList, parsedArgs.mBindMountAppDataDirs,
            parsedArgs.mBindMountAppStorageDirs);
    // ……
    return handleChildProc(parsedArgs, childPipeFd,
            parsedArgs.mStartChildZygote);
}
private Runnable handleChildProc(ZygoteArguments parsedArgs,
        FileDescriptor pipeFd, boolean isZygote) {
    // 因为需求fork子进程,所以isZygote为true,走childZygoteInit
    if (!isZygote) {
        return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,
                parsedArgs.mDisabledCompatChanges,
                parsedArgs.mRemainingArgs, null /* classLoader */);
    } else {
        // 这儿的调用链就很简略了,就反射履行main办法,而class目标上面的注释里就说到了,是ActivityThread
        // 至于这块逻辑怎么就确认是ActivityThread,我解说不了hh
        return ZygoteInit.childZygoteInit(
                parsedArgs.mRemainingArgs  /* classLoader */);
    }
}

使用进程创立后

使用进程创立后,被反射履行了ActivityThread.main(),内容比较少,主体流程便是将自身ActivityThread实例attach给AMS

// ActivityThread.java
public static void main(String[] args) {
    // 关于looper的内容就不多阐述了,对handler这块想要了解的就去翻下我前面的文章叭
    Looper.prepareMainLooper();
    // 这儿就要开端绑定了
    ActivityThread thread = new ActivityThread();
    thread.attach(false, startSeq);
    if (sMainThreadHandler == null) {
        sMainThreadHandler = thread.getHandler();
    }
    if (false) {
        Looper.myLooper().setMessageLogging(new
                LogPrinter(Log.DEBUG, "ActivityThread"));
    }
    Looper.loop();
    throw new RuntimeException("Main thread loop unexpectedly exited");
}
private void attach(boolean system, long startSeq) {
    if (!system) {
        // 因为传进来的是false,所以走这儿
        final IActivityManager mgr = ActivityManager.getService();
        try {
            // 那这个老生常谈了,那便是去AMS看下文喽
            // 所以当AMS完成attach后,该线程才会唤醒,去履行之后的loop()
            // 前面startActivity中调用AMS时,传入了同样的参数类型:IApplicationThread
            mgr.attachApplication(mAppThread, startSeq);
        } catch (RemoteException ex) {
            throw ex.rethrowFromSystemServer();
        }
    }
}

使用进程向AMS建议恳求时,经过ServiceManager得到AMS注册的Binder然后得到Proxy代理类,而AMS需求向使用进程建议调度时,则经过作为服务端时接受的IApplicationThread目标以进行工作

一文搞定面试 | Activity启动流程之冷热启动(下)
那不如看看IApplicationThread能做些什么吧?在ActivityThread中,mAppThread是ApplicationThread

// ActivityThread.java
private class ApplicationThread extends IApplicationThread.Stub {
    // 因为里边的办法大同小异,随意选取一个眼熟的,四大组件之一的Service
    // sendMessage经过外部类ActivityThread发送handler消息,终究会回调履行Service.onCreate()
    // 那把其他办法大致能够扫一眼,四大组件的一些处理皆需求经过这儿建议
    // 那建议的客户端应该便是AMS了,所以为什么说AMS是四大组件的集中管理者
    public final void scheduleCreateService(IBinder token,
            ServiceInfo info, CompatibilityInfo compatInfo, int processState) {
        updateProcessState(processState, false);
        CreateServiceData s = new CreateServiceData();
        s.token = token;
        s.info = info;
        s.compatInfo = compatInfo;
        sendMessage(H.CREATE_SERVICE, s);
    }
}
// handleMessage
case CREATE_SERVICE:
    if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
                ("serviceCreate: " + String.valueOf(msg.obj)));
    }
    handleCreateService((CreateServiceData)msg.obj);
    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    break;

AMS绑定使用进程

AMS完成了Application创立后,告诉ActivityThread进行生命周期回调

ActivityManagerService.attachApplication() >>> attachApplicationLocked() // 这儿对ProcessRecord进行了一些状态设置……
    >>> IApplicationThread.bindApplication() // 这儿又回去了,不用解说了吧,在ActivityThread里发送对应的handler消息
        >>> ActivityThread.handleBindApplication() 
            // 这儿就挨近尾声了,完成了application的创立,onCreate这块是在主线程,所以留意尽可能避免耗时操作
            >>> makeApplication() + mInstrumentation.callApplicationOnCreate

是不是觉得哪里不对劲?Activity还没发动呢!想一想一件事,Binder的挂机机制,回到AMS中调用bindApplication的后边

// ActivityManagerService.java
private boolean attachApplicationLocked(@NonNull IApplicationThread thread,
            int pid, int callingUid, long startSeq) {
    // ……
    thread.bindApplication()
    // ……
    // 这个时分,Application已经完成了onCreate()
    // 一开端我也找了好久,许多文章中也没有说到这一茬,直到我仔细看了官方注释
    // See if the top visible activity is waiting to run in this process...
    if (normalMode) {
        try {
            // attachApplication全局搜了下只剩下RootWindowContainer里还有了,去看看吧
            // 当然喔,这儿仅仅我的想法,可是他们的办法名、入参、回来值如出一辙,我也就不多想了
            didSomething = mAtmInternal.attachApplication(app.getWindowProcessController());
        } catch (Exception e) {
            Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
            badApp = true;
        }
    }
}
// RootWindowContainer
boolean attachApplication(WindowProcessController app) throws RemoteException {
    // 看来看去,startActivityForAttachedApplicationIfNeeded这个最顺眼
    final PooledFunction c = PooledLambda.obtainFunction(
            RootWindowContainer::startActivityForAttachedApplicationIfNeeded, this,
            PooledLambda.__(ActivityRecord.class), app,
            rootTask.topRunningActivity());
    rootTask.forAllActivities(c);
    c.recycle();
}
private boolean startActivityForAttachedApplicationIfNeeded(ActivityRecord r,
        WindowProcessController app, ActivityRecord top) {
    // realStartActivityLocked这个办法熟不熟悉
    if (mTaskSupervisor.realStartActivityLocked(r, app,
            top == r && r.isFocusable() /*andResume*/, true /*checkConfig*/)) {
        mTmpBoolean = true;
    }
}

假如你忘了realStartActivityLocked在哪见过的话,我帮你回想回想。现在想起来了嘛

// ActivityTaskSupervisor.java
void startSpecificActivity(ActivityRecord r, boolean andResume, boolean checkConfig) {
    // Is this activity's application already running?
    final WindowProcessController wpc =
            mService.getProcessController(r.processName, r.info.applicationInfo.uid);
    boolean knownToBeDead = false;
    if (wpc != null && wpc.hasThread()) {
        // 热发动和暖发动流程
        try {
            realStartActivityLocked(r, wpc, andResume, checkConfig);
            return;
        } catch (RemoteException e) {
            Slog.w(TAG, "Exception when starting activity "
                    + r.intent.getComponent().flattenToShortString(), e);
        }
        // If a dead object exception was thrown -- fall through to
        // restart the application.
        knownToBeDead = true;
    }
    r.notifyUnknownVisibilityLaunchedForKeyguardTransition();
    // 冷发动,创立使用进程
    final boolean isTop = andResume && r.isTopRunningActivity();
    // 这一块关于socket是怎么发送的,待弥补
    mService.startProcessAsync(r, knownToBeDead, isTop, isTop ? "top-activity" : "activity");
}

Activity终究发动

关于这块的调用链,不同版本源码可能有所不同,但终究都将经过ActivityThread.performLaunchActivity或相似办法名展开。当然这儿举例的是冷发动状态下,Activity处于ON_CREATE阶段的状况,假如是热发动的话,只需求快速进行状态康复就好了

ActivityTaskSupervisor.realStartActivityLocked()
    >>> ClientLifecycleManager.scheduleTransaction() 
        >>> ClientTransaction.schedule()
            >>> IApplicationThread.scheduleTransaction()
                // 这儿在ActivityThread里没找到对应的办法,在其父类中找到
                >>> ActivityThread:ClientTransactionHandler.scheduleTransaction() // 发送了EXECUTE_TRANSACTION
                    >>> TransactionExecutor.execute() >>> executeCallbacks() >>> cycleToPath() >>> performLifecycleSequence()
                        // 这次是父类引证,子类实现了
                        // 当然这儿是依据lifecycle生命周期改变调度对应办法,热发动就不需求launchActivity了
                        >>> ActivityThread:ClientTransactionHandler.handleLaunchActivity()
                            >>> ActivityThread.performLaunchActivity()
                                // 包含其他生命周期分发也都能看到
                                >>> Instrumentation.callActivityOnCreate()
                                    >>> Activity.performCreate()

现在再来比照一下这张图,有所区别的便是14.1和14.2的办法名,但整体调用链却是如出一辙。关于Activity发动的整体流程,无论是冷发动仍是热发动,能够不用过于重视细节的办法调用链,应该关怀如图几个具有关键职能的类之间的调度流通。

在厘清这个之后,再回头去过一遍源码细节,相信你会有所收成

一文搞定面试 | Activity启动流程之冷热启动(下)

魂灵发问

暂无,等待大佬们供给面试问题……欢迎谈论

拜读

第一篇主攻源码流程,第二篇主攻概念及思路解析,两篇的阅读顺序能够不一定,但结合起来,十分有助于了解

# Android使用发动流程

# Android使用发动流程剖析

# Android Application 发动流程剖析及其源码调用探求

假如觉得本文对你有协助,不妨 点赞+保藏+重视 支持一波,感谢肯定和喜爱

当然,更希望初读点赞再读保藏三而重视

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。