学习笔记--Launcher应用的桌面启动流程

Launcher应用的桌面启动流程

注意事项写在前头:
Launcher HomeActivity启动流程图
Launcher HomeActivity启动流程图
首先来看下ApplicationThread类
public final class ActivityThread extends ClientTransactionHandler {
    ...
    
    // ApplicationThread是ActivityThread的内部类,是一个Binder,用于AMS远程服务对本地应用的生命周期的调度
    private class ApplicationThread extends IApplicationThread.Stub {
        ...
    }
    
    ...
}

来看下ApplicationThread的系列方法:


ApplicationThread
  • scheduleReceiver用来创建BroadcastREceiver
  • scheduleCreateService顾名思义是创建Service
  • scheduleBindService绑定Service服务
  • bindApplication创建我们熟知的Application对象并且执行它的生命周期
  • scheduleInstallProvider执行创建ContentProvider并且执行它生命周期的方法
  • ...

可以看到,ApplicationThread类中没有Activity生命周期调度的方法,那AMS怎么调度本地应用的Activity生命周期呢,别着急,接着看。

Activitythread整体

既然ApplicationThread类是ActivityThread的内部类,那我们来看看ActivityThread类:


ActivityThread持有的成员变量
  • ArrayMap<IBinder, ActivityClientRecord> mActivities: 存放本应用进程创建的Activity实例,其中ActivityClientRecord是ActivityThread的内部类,是对Activity信息的封装
  • ArrayMap<ProviderKey, ProviderClientRecord> mProviderMap: 存放本应用进程创建的ContentProvider实例,ProviderClientRecord是ActivityThread的内部类,是对ContentProvider信息的封装
  • ArrayMap<IBinder, Service> mServices:存放本应用进程创建的Service实例
  • BroadcastReceiver:之所以不用ArrayMap集合存储,是因为ActivityThread只负责BroadcastReceiver的创建,BroadcastReceiver的分发还是由ActivityManagerService管理的
  • Looper mLooper:主进程消息队列循环的驱动器,由它提供主线程消息分发的能力
  • Handler mH:从子线程发消息到主线程的Handler对象
  • Application mInitialApplication:应用层熟知的Application对象,该Application对象也是在ActivityThread中创建并调度的
  • Instrumentation mInstrumentation:该类的作用是在应用进程中执行Activity的创建和跳转,跳转结果的判断,生命周期传递的类
  • ApplicationThread mAppThread:很重要的类,ActivityThread的内部类,是一个IBinder接口,定义了许多方法,ActivityManagerService之所以能够调度应用进程的四大组件就是通过该类完成的
// 显然Activitythread继承自ClientTransactionHandler
public final class ActivityThread extends ClientTransactionHandler
ClientTransactionHandler结构

从ClientTransactionHandler类结构图可以看到,它定义了非常多和Activity生命周期调度相关的方法如handleDestroyActivity,handlePauseActivity,handleResumeActivity,handleStopActivity,还有非常重要的handleLaunchActivity方法,也就是启动和创建Activity生命周期的方法
为什么方法转移到ClientTransactionHandler类中(这是Android10.0对ActivityManagerService重构的一部分,将Activity相关的工作转移到一个单一职能的类中),并且由于ClientTransactionHandler是抽象类,真正的实现和调用在ActivityThread中。

ActivityThread细剖

上篇Launcher应用的进程启动流程我们分析得到,ActivityThread是应用进程的入口类,而Java进程的入口方法,众所周知是main()方法,所以直接从main方法开始分析

//------------------------------ActivityThread.java------------------------------

public static void main(String[] args) {
    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");

    // Install selective syscall interception
    AndroidOs.install();

    // CloseGuard defaults to true and can be quite spammy.  We
    // disable it here, but selectively enable it later (via
    // StrictMode) on debug builds, but using DropBox, not logs.
    CloseGuard.setEnabled(false);

    Environment.initForCurrentUser();

    // Make sure TrustedCertificateStore looks in the right place for CA certificates
    final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
    TrustedCertificateStore.setDefaultUserDirectory(configDir);

    Process.setArgV0("<pre-initialized>");
    
    // 重点1:准备一个消息循环驱动器Looper
    Looper.prepareMainLooper();

    // Find the value for {@link #PROC_START_SEQ_IDENT} if provided on the command line.
    // It will be in the format "seq=114"
    long startSeq = 0;
    if (args != null) {
        for (int i = args.length - 1; i >= 0; --i) {
            if (args[i] != null && args[i].startsWith(PROC_START_SEQ_IDENT)) {
                startSeq = Long.parseLong(
                        args[i].substring(PROC_START_SEQ_IDENT.length()));
            }
        }
    }
    ActivityThread thread = new ActivityThread();
    // 重点2:调用了ActivityThread#attach方法
    // 关注传递第一参数(传参名system)为false
    // 跟进
    thread.attach(false, startSeq);

    if (sMainThreadHandler == null) {
        sMainThreadHandler = thread.getHandler();
    }

    if (false) {
        Looper.myLooper().setMessageLogging(new
                LogPrinter(Log.DEBUG, "ActivityThread"));
    }

    // End of event ActivityThreadMain.
    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    // 重点1后续:开启Looper的循环工作,从而使主线程具有消息分发的能力
    // 正因为此ActivityThread被称为主线程
    Looper.loop();

    throw new RuntimeException("Main thread loop unexpectedly exited");
}

可以看到main方法的两个重点:

  1. 开启了消息循环器Looper,让主线程(ActivityThread)具有消息分发和处理的能力
  2. 调用ActivityThread#attach方法,继续跟进。
//------------------------------ActivityThread.java------------------------------

// 参数system: 标记当前进程是否是应用进程,显然不是,所以在前面的main方法中传递了false
private void attach(boolean system, long startSeq) {
    sCurrentActivityThread = this;
    mSystemThread = system;
    if (!system) {
        android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",
                                                UserHandle.myUserId());
        RuntimeInit.setApplicationObject(mAppThread.asBinder());
        // 关注重点:此处 ActivityManager.getService()返回的是IActivityManager的AIDL接口
        // 在运行的过程中,mgr实例其实就是AMS的对应对象
        final IActivityManager mgr = ActivityManager.getService();
        try {
            // 获取了AMS的对应对象后调用attachApplication,并传递了mAppThread对象
            // mAppThread对象是在ActivityThread初始化的时候就实例化了的ApplicationThread对象,上文已分析,一个Binder接口实例
            // attachApplication方法相当于向远程服务AMS注册本地应用进程,方便AMS能够调度本进程的四大组件以及生命周期
            // 在这里实际上应用就和系统Framework关联起来了
            mgr.attachApplication(mAppThread, startSeq);
        } catch (RemoteException ex) {
            throw ex.rethrowFromSystemServer();
        }
        // Watch for getting close to heap limit.
        BinderInternal.addGcWatcher(new Runnable() {
            @Override public void run() {
                if (!mSomeActivitiesChanged) {
                    return;
                }
                Runtime runtime = Runtime.getRuntime();
                long dalvikMax = runtime.maxMemory();
                long dalvikUsed = runtime.totalMemory() - runtime.freeMemory();
                if (dalvikUsed > ((3*dalvikMax)/4)) {
                    if (DEBUG_MEMORY_TRIM) Slog.d(TAG, "Dalvik max=" + (dalvikMax/1024)
                            + " total=" + (runtime.totalMemory()/1024)
                            + " used=" + (dalvikUsed/1024));
                    mSomeActivitiesChanged = false;
                    try {
                       // ActivityTaskManager.getService()实际返回的是ATMS对应的对象,并调用其releaseSomeActivities方法
                       // 此处的作用其实是OOM监控,当监控到内存占用达到最大值的3/4时,就会去释放一些页面
                      // 这就是为什么当打开多个页面再回退时发现前面的页面已经丢失,需要重新加载的原因
                      ActivityTaskManager.getService().releaseSomeActivities(mAppThread);
                    } catch (RemoteException e) {
                        throw e.rethrowFromSystemServer();
                    }
                }
            }
        });
    } else {
        // Don't set application object here -- if the system crashes,
        // we can't display an alert, we just want to die die die.
        android.ddm.DdmHandleAppName.setAppName("system_process",
                UserHandle.myUserId());
        try {
            mInstrumentation = new Instrumentation();
            mInstrumentation.basicInit(this);
            ContextImpl context = ContextImpl.createAppContext(
                    this, getSystemContext().mPackageInfo);
            mInitialApplication = context.mPackageInfo.makeApplication(true, null);
            mInitialApplication.onCreate();
        } catch (Exception e) {
            throw new RuntimeException(
                    "Unable to instantiate Application():" + e.toString(), e);
        }
    }

    ViewRootImpl.ConfigChangedCallback configChangedCallback
            = (Configuration globalConfig) -> {
        synchronized (mResourcesManager) {
            // We need to apply this change to the resources immediately, because upon returning
            // the view hierarchy will be informed about it.
            if (mResourcesManager.applyConfigurationToResourcesLocked(globalConfig,
                    null /* compat */)) {
                updateLocaleListFromAppContext(mInitialApplication.getApplicationContext(),
                        mResourcesManager.getConfiguration().getLocales());

                // This actually changed the resources! Tell everyone about it.
                if (mPendingConfiguration == null
                        || mPendingConfiguration.isOtherSeqNewer(globalConfig)) {
                    mPendingConfiguration = globalConfig;
                    sendMessage(H.CONFIGURATION_CHANGED, globalConfig);
                }
            }
        }
    };
    ViewRootImpl.addConfigCallback(configChangedCallback);
}

重点已在注释中表明,在attach方法中:

  • mgr.attachApplication关联AMS和本地应用进程,便于Framework跨进程调度本地应用进程声明周期
  • BinderInternal.addGcWatcher监控内存,ActivityTaskManager.getService().releaseSomeActivities(mAppThread)根据方法名就知道,会在内存不足时释放部分Activity

继续跟进AMS#attachApplication方法

//------------------------------ActivityManagerService.java------------------------------

public final void attachApplication(IApplicationThread thread, long startSeq) {
    synchronized (this) {
        int callingPid = Binder.getCallingPid();
        final int callingUid = Binder.getCallingUid();
        final long origId = Binder.clearCallingIdentity();
        // 紧接着调用attachApplicationLocked方法,并将ApplicationThread对象传递了过去
        attachApplicationLocked(thread, callingPid, callingUid, startSeq);
        Binder.restoreCallingIdentity(origId);
    }
}

没有发现关键的代码,而是转而调用attachApplicationLocked方法,并将ApplicationThread对象传递了过去

//------------------------------ActivityManagerService.java------------------------------

// 该方法的代码量大:line 4763-5173,所以我们只关注重点
// 重点1: 调度ActivityThread创建Application
// 重点2: 继续启动进程创建之前已经加入任务栈的Activity也就是应用的第一个Activity,也就是Launcher应用的第一个Activity
private final boolean attachApplicationLocked(IApplicationThread thread,
        int pid, int callingUid, long startSeq) {
    ...
    // 重点1: 调用传递进来的ApplicationThread对象的bindApplication方法,
    // 由于ApplicationThread对象是在ActivityThread的内部类,并且是它传递进来的,所以要回到ActivityThread中分析
    thread.bindApplication(processName, appInfo, providers, null, profilerInfo,
                        null, null, null, testMode,
                        mBinderTransactionTrackingEnabled, enableTrackAllocation,
                        isRestrictedBackupMode || !normalMode, app.isPersistent(),
                        new Configuration(app.getWindowProcessController().getConfiguration()),
                        app.compat, getCommonServicesLocked(app.isolated),
                        mCoreSettingsObserver.getCoreSettingsLocked(),
                        buildSerial, autofillOptions, contentCaptureOptions);
    ...
    // See if the top visible activity is waiting to run in this process...
    if (normalMode) {
        try {
            // 调用ATMS的attachApplication方法
            // 该方法的作用是继续启动Launcher应用进程创建之前已经加入任务栈的Activity
            didSomething = mAtmInternal.attachApplication(app.getWindowProcessController());
        } catch (Exception e) {
            Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
            badApp = true;
        }
    }
    ...
}
  1. 注释一处:AMS远程服务又通过ApplicationThread这个Binder接口的回调到的bindApplication方法中。
  2. 注释二处: 则是通过ATMS的attachApplication去启动Launcher应用进程创建之前已经加入任务栈的Activity。
注释一

注意这里开始注释一和注释二分开分析,先追踪注释一流程。

//------------------------------ActivityThread.java------------------------------

// 该方法将传入的参数进行了包装,包装成AppBindData对象
// 并向主线程的Handler对象(H mH)发送H.BIND_APPLICATION消息,将包装好的AppBindData对象传递过去
public final void bindApplication(String processName, ApplicationInfo appInfo,
        List<ProviderInfo> providers, ComponentName instrumentationName,
        ProfilerInfo profilerInfo, Bundle instrumentationArgs,
        IInstrumentationWatcher instrumentationWatcher,
        IUiAutomationConnection instrumentationUiConnection, int debugMode,
        boolean enableBinderTracking, boolean trackAllocation,
        boolean isRestrictedBackupMode, boolean persistent, Configuration config,
        CompatibilityInfo compatInfo, Map services, Bundle coreSettings,
        String buildSerial, AutofillOptions autofillOptions,
        ContentCaptureOptions contentCaptureOptions) {
    if (services != null) {
        if (false) {
            // Test code to make sure the app could see the passed-in services.
            for (Object oname : services.keySet()) {
                if (services.get(oname) == null) {
                    continue; // AM just passed in a null service.
                }
                String name = (String) oname;

                // See b/79378449 about the following exemption.
                switch (name) {
                    case "package":
                    case Context.WINDOW_SERVICE:
                        continue;
                }

                if (ServiceManager.getService(name) == null) {
                    Log.wtf(TAG, "Service " + name + " should be accessible by this app");
                }
            }
        }

        // Setup the service cache in the ServiceManager
        ServiceManager.initServiceCache(services);
    }

    setCoreSettings(coreSettings);
    
    // 将传入参数包装成AppBindData对象
    AppBindData data = new AppBindData();
    data.processName = processName;
    data.appInfo = appInfo;
    data.providers = providers;
    data.instrumentationName = instrumentationName;
    data.instrumentationArgs = instrumentationArgs;
    data.instrumentationWatcher = instrumentationWatcher;
    data.instrumentationUiAutomationConnection = instrumentationUiConnection;
    data.debugMode = debugMode;
    data.enableBinderTracking = enableBinderTracking;
    data.trackAllocation = trackAllocation;
    data.restrictedBackupMode = isRestrictedBackupMode;
    data.persistent = persistent;
    data.config = config;
    data.compatInfo = compatInfo;
    data.initProfilerInfo = profilerInfo;
    data.buildSerial = buildSerial;
    data.autofillOptions = autofillOptions;
    data.contentCaptureOptions = contentCaptureOptions;
    // 往主线程的Handler(也就是前面提到的H mH)发送H.BIND_APPLICATION消息,并且将包装好的AppBindData对象传递过去
    sendMessage(H.BIND_APPLICATION, data);
}

可以看到方法将传入的参数进行了包装,包装成AppBindData对象,然后向主线程的Handler对象发送消息。

思考一个问题????
为什么要向主线程的Handler对象发送消息呢?
因为AMS等系统服务都在Server端,运行在Binder线程池,当AMS通过传递的ApplicationThread对象调用它bindApplication方法时,此时还是运行在子线程中,所以此处使用了MainHandler发送消息,发送到应用进程的主线程中。

H mH处理BIND_APPLICATION消息

//------------------------------ActivityThread.java------------------------------

// ActivityThread内部类H 继承自Handler,它处理BIND_APPLICATION消息是进而调用handleBindApplication方法
public void handleMessage(Message msg) {
    ...
    if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
    switch (msg.what) {
        case BIND_APPLICATION:
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
            AppBindData data = (AppBindData)msg.obj;
            handleBindApplication(data);
            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
            break;
    ...
}

可以看到ActivityThread内部类H 是一个Handler对象,它会直接调用handleBindApplication方法,继续往下看。

//------------------------------ActivityThread.java------------------------------

// 该方法的代码量大,line 6122-6498,所以我们只关注重点
// 重点1:对Application对象进行创建
private void handleBindApplication(AppBindData data) {
    ...
    // 对Application对象的定义
    Application app;
    final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskWrites();
    final StrictMode.ThreadPolicy writesAllowedPolicy = StrictMode.getThreadPolicy();
    try {
        // If the app is being launched for full backup or restore, bring it up in
        // a restricted environment with the base application class.
        // 这里对Application对象进行赋值,跟进
        app = data.info.makeApplication(data.restrictedBackupMode, null);
        
        // Propagate autofill compat state
        app.setAutofillOptions(data.autofillOptions);

        // Propagate Content Capture options
        app.setContentCaptureOptions(data.contentCaptureOptions);

        // 创建好的Application对象赋值给mInitialApplication
        // 所以就像上面说的ActivityThread是持有了应用的Application对象(也就是mInitialApplication)的
        mInitialApplication = app;
    ...
    // 在Instrumentation#callApplicationOnCreate方法中进而调用Application的onCreate方法,就到了熟悉的Application#onCreate
    mInstrumentation.callApplicationOnCreate(app);
    ...
}

ActivityThread中handleBindApplication方法对持有的mInitialApplication对象进行了定义和赋值,我们继续分析下注释处mInitialApplication = app;中的app对象,app对象是通过data.info.makeApplication(data.restrictedBackupMode, null)创建的,追踪直接跳转到LoadedApk.java中,我们来看看LoadedApk这个类是做了什么?

//------------------------------LoadedApk.java------------------------------

// LoadedApk这个类相当于是Apk在运行时的一个抽象映射
public Application makeApplication(boolean forceDefaultAppClass,
        Instrumentation instrumentation) {
    if (mApplication != null) {
        return mApplication;
    }

    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "makeApplication");

    Application app = null;
    
    // mApplicationInfo其实是应用在AndroidManifest清单文件中配置的属性解析而成的对象
    // 此处获取appClass其实是应用在AndroidManifest清单文件中配置的Application的class全类名
    String appClass = mApplicationInfo.className;
    if (forceDefaultAppClass || (appClass == null)) {
        // 如果没有指定那就是默认的android.app.Application
        appClass = "android.app.Application";
    }

    try {
        java.lang.ClassLoader cl = getClassLoader();
        if (!mPackageName.equals("android")) {
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
                    "initializeJavaContextClassLoader");
            initializeJavaContextClassLoader();
            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        }
        ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
        // 得到Application全类名之后,调用mActivityThread.mInstrumentation.newApplication
        // mInstrumentation在前面介绍了,就是用来创建Application,创建Activity以及对Activity生命周期调度的工具类
        app = mActivityThread.mInstrumentation.newApplication(
                cl, appClass, appContext);
        appContext.setOuterContext(app);
    } catch (Exception e) {
        if (!mActivityThread.mInstrumentation.onException(app, e)) {
            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
            throw new RuntimeException(
                "Unable to instantiate application " + appClass
                + ": " + e.toString(), e);
        }
    }
    mActivityThread.mAllApplications.add(app);
    mApplication = app;

    if (instrumentation != null) {
        try {
            instrumentation.callApplicationOnCreate(app);
        } catch (Exception e) {
            if (!instrumentation.onException(app, e)) {
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                throw new RuntimeException(
                    "Unable to create application " + app.getClass().getName()
                    + ": " + e.toString(), e);
            }
        }
    }

    // Rewrite the R 'constants' for all library apks.
    SparseArray<String> packageIdentifiers = getAssets().getAssignedPackageIdentifiers();
    final int N = packageIdentifiers.size();
    for (int i = 0; i < N; i++) {
        final int id = packageIdentifiers.keyAt(i);
        if (id == 0x01 || id == 0x7f) {
            continue;
        }

        rewriteRValues(getClassLoader(), packageIdentifiers.valueAt(i), id);
    }

    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);

    return app;
}

配合源码中的注释,可以看到LoadedApk中根据AndroidManifest清单文件中配置的属性解析而成的对象mApplicationInfo对象,获取创建Application所需的属性,并将创建工作又交给了mActivityThread.mInstrumentation,也就是Instrumentation这个类。
接着分析Instrumentation

//------------------------------Instrumentation.java------------------------------

/**
 * Perform instantiation of the process's {@link Application} object.  The
 * default implementation provides the normal system behavior.
 * 
 * @param cl The ClassLoader with which to instantiate the object.
 * @param className The name of the class implementing the Application
 *                  object.
 * @param context The context to initialize the application with
 * 
 * @return The newly instantiated Application object.
 */
public Application newApplication(ClassLoader cl, String className, Context context)
        throws InstantiationException, IllegalAccessException, 
        ClassNotFoundException {
    // getFactory方法获取的是AppComponentFactory类,然后通过instantiateApplication方法创建Application对象
    Application app = getFactory(context.getPackageName())
            .instantiateApplication(cl, className);
    // Application对象调用成功后,紧接着调用自身的attach方法
    app.attach(context);
    return app;
}

在Instrumentation#newApplication方法中:

  • 通过getFactory(context.getPackageName()).instantiateApplication(cl, className);完成了Application的创建
  • 执行了Application的attach方法,并返回了Application

追踪getFactory(context.getPackageName()).instantiateApplication(cl, className)流程

//------------------------------Instrumentation.java------------------------------

private AppComponentFactory getFactory(String pkg) {
    if (pkg == null) {
        Log.e(TAG, "No pkg specified, disabling AppComponentFactory");
        return AppComponentFactory.DEFAULT;
    }
    if (mThread == null) {
        Log.e(TAG, "Uninitialized ActivityThread, likely app-created Instrumentation,"
                + " disabling AppComponentFactory", new Throwable());
        return AppComponentFactory.DEFAULT;
    }
    LoadedApk apk = mThread.peekPackageInfo(pkg, true);
    // This is in the case of starting up "android".
    if (apk == null) apk = mThread.getSystemContext().mPackageInfo;
    return apk.getAppFactory();
}

可以看到getFactory(String pkg)方法返回了AppComponentFactory对象,这个类是用来干嘛的呢?


AppComponentFactory类结构

看完AppComponentFactory类结构图,我们再来看下它的类头介绍

//------------------------------AppComponentFactory.java------------------------------

/**
 * Interface used to control the instantiation of manifest elements.
 *
 * @see #instantiateApplication
 * @see #instantiateActivity
 * @see #instantiateClassLoader
 * @see #instantiateService
 * @see #instantiateReceiver
 * @see #instantiateProvider
 */
// 解释: 用来创建AndroidManifest中定义的节点的创建
// instantiateApplication用来创建Application
// 其他方法类似
public class AppComponentFactory {
    ...
    
    /**
     * Allows application to override the creation of the application object. This can be used to
     * perform things such as dependency injection or class loader changes to these
     * classes.
     * <p>
     * This method is only intended to provide a hook for instantiation. It does not provide
     * earlier access to the Application object. The returned object will not be initialized
     * as a Context yet and should not be used to interact with other android APIs.
     *
     * @param cl        The default classloader to use for instantiation.
     * @param className The class to be instantiated.
     */
    public @NonNull Application instantiateApplication(@NonNull ClassLoader cl,
            @NonNull String className)
            throws InstantiationException, IllegalAccessException, ClassNotFoundException {
        return (Application) cl.loadClass(className).newInstance();
    }
    
    ...
}

AppComponentFactory类instantiateApplication方法,通过ClassLoader cl类加载器,String className全类名实例化出了Application对象。并且通过类头注释可以知道其它的在AndroidManifest中定义的节点的创建也是由AppComponentFactory类完成的。

回到注释二处

此处再放一次AMS#attachApplicationLocked源码,是为了让读者不至于忘记上文所说的注释一和注释2的分开分析

//------------------------------ActivityManagerService.java------------------------------

// 该方法的代码量大:line 4763-5173,所以我们只关注重点
// 重点1: 调度ActivityThread创建Application
// 重点2: 继续启动进程创建之前已经加入任务栈的Activity也就是应用的第一个Activity,也就是Launcher应用的第一个Activity
private final boolean attachApplicationLocked(IApplicationThread thread,
        int pid, int callingUid, long startSeq) {
    ...
    // 重点1: 调用传递进来的ApplicationThread对象的bindApplication方法,
    // 由于ApplicationThread对象是在ActivityThread的内部类,并且是它传递进来的,所以要回到ActivityThread中分析
    thread.bindApplication(processName, appInfo, providers, null, profilerInfo,
                        null, null, null, testMode,
                        mBinderTransactionTrackingEnabled, enableTrackAllocation,
                        isRestrictedBackupMode || !normalMode, app.isPersistent(),
                        new Configuration(app.getWindowProcessController().getConfiguration()),
                        app.compat, getCommonServicesLocked(app.isolated),
                        mCoreSettingsObserver.getCoreSettingsLocked(),
                        buildSerial, autofillOptions, contentCaptureOptions);
    ...
    // See if the top visible activity is waiting to run in this process...
    if (normalMode) {
        try {
            // 调用ATMS的attachApplication方法
            // 该方法的作用是继续启动Launcher应用进程创建之前已经加入任务栈的Activity
            didSomething = mAtmInternal.attachApplication(app.getWindowProcessController());
        } catch (Exception e) {
            Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
            badApp = true;
        }
    }
    ...
}

开始分析注释二处:调用ATMS的attachApplication方法继续启动Launcher应用进程创建之前已经加入任务栈的Activity.

//------------------------------ActivityTaskManagerService.java------------------------------

public boolean attachApplication(WindowProcessController wpc) throws RemoteException {
    synchronized (mGlobalLockWithoutBoost) {
        // ATMS继续将启动Activity任务委派给RootActivityContainer
        return mRootActivityContainer.attachApplication(wpc);
    }
}

ATMS会继续将启动Activity任务委派给RootActivityContainer的attachApplication方法

//------------------------------RootActivityContainer.java------------------------------

boolean attachApplication(WindowProcessController app) throws RemoteException {
    final String processName = app.mName;
    boolean didSomething = false;
    for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
        final ActivityDisplay display = mActivityDisplays.get(displayNdx);
        // 获得可见的活跃的任务栈
        final ActivityStack stack = display.getFocusedStack();
        if (stack != null) {
            // 获取stack任务栈中所有Activity存储到mTmpActivityList中
            stack.getAllRunningVisibleActivitiesLocked(mTmpActivityList);
            // 获取stack任务栈中栈顶的ActivityRecord
            final ActivityRecord top = stack.topRunningActivityLocked();
            final int size = mTmpActivityList.size();
        
            for (int i = 0; i < size; i++) {
                final ActivityRecord activity = mTmpActivityList.get(i);
                // 遍历mTmpActivityList,判断其中的Activity的WindowProcessController是否为空
                // 如果为空,说明该Activity虽然已经入栈但还没关联到进程,也就是说该Activity还未在进程中运行
                if (activity.app == null && app.mUid == activity.info.applicationInfo.uid
                        && processName.equals(activity.processName)) {
                    try {
                        // 如果条件满足,就会真正去启动Activity,继续跟踪
                        if (mStackSupervisor.realStartActivityLocked(activity, app,
                                top == activity /* andResume */, true /* checkConfig */)) {
                            didSomething = true;
                        }
                    } catch (RemoteException e) {
                        Slog.w(TAG, "Exception in new application when starting activity "
                                + top.intent.getComponent().flattenToShortString(), e);
                        throw e;
                    }
                }
            }
        }
    }
    if (!didSomething) {
        ensureActivitiesVisible(null, 0, false /* preserve_windows */);
    }
    return didSomething;
}

RootActivityContainer的attachApplication方法中会遍历当前活跃的任务栈,并判断栈顶Activity与需要启动的Activity是否一致(当前情况下一致,因为Launcher是第一个应用进程,此时活跃的栈的栈顶Activity只可能时Launcher应用进程创建之前已经入栈了的HomeActivity,详情可以查看上篇Launcher应用的进程启动流程),若不是并且该activity.app == null,证明仍为关联到进程中,则真正去启动Activity

真正启动Activity的流程调用到了ActivityStackSupervisor的realStartActivityLocked方法,接着追踪

//------------------------------ActivityStackSupervisor.java------------------------------

boolean realStartActivityLocked(ActivityRecord r, WindowProcessController proc,
            boolean andResume, boolean checkConfig) throws RemoteException {
    ...
    // Create activity launch transaction.
    // 创建启动Activity的事务对象clientTransaction
    final ClientTransaction clientTransaction = ClientTransaction.obtain(
            proc.getThread(), r.appToken);
            
    final DisplayContent dc = r.getDisplay().mDisplayContent;
    // 接着向事务对象clientTransaction里添加了LaunchActivityItem
    clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),
            System.identityHashCode(r), r.info,
            // TODO: Have this take the merged configuration instead of separate global
            // and override configs.
            mergedConfiguration.getGlobalConfiguration(),
            mergedConfiguration.getOverrideConfiguration(), r.compat,
            r.launchedFromPackage, task.voiceInteractor, proc.getReportedProcState(),
            r.icicle, r.persistentState, results, newIntents,
            dc.isNextTransitionForward(), proc.createProfilerInfoIfNeeded(),
                    r.assistToken));
                    
    // Set desired final state.
    final ActivityLifecycleItem lifecycleItem;
    // 还会根据传递进来的参数andResume,决定向事务对象clientTransaction添加ResumeActivityItem还是PauseActivityItem
    if (andResume) {
        lifecycleItem = ResumeActivityItem.obtain(dc.isNextTransitionForward());
    } else {
        lifecycleItem = PauseActivityItem.obtain();
    }
    clientTransaction.setLifecycleStateRequest(lifecycleItem);

    // Schedule transaction.
    // 然后开始调度事务的执行
    // (这里也是Android10.0之后改动)把Activity各个生命周期的拆分ActivityLifeCycleItem,根据不同的状态由具体的ActivityLifecycleItem去执行
    // 这种模式有个术语叫状态机设计模式
    mService.getLifecycleManager().scheduleTransaction(clientTransaction);
    ...
}
  1. 首先需要解释的是,在Android10中把Activity生命周期拆分成几种生命周期状态的Item。LaunchActivityItem,ResumeActivityItem,PauseActivityItem,StopActivityItem,DestroyActivityItem.每个Item负责对Activity生命周期的具体的调度。
  2. 其次需要解释的是,mService.getLifecycleManager().scheduleTransaction(clientTransaction)这句代码。但这里我们就不详细追踪了。以后有时间会补充。可以参考我看过的文章源码解析之-基于Android10.0的startActivity来了解其中的这块流程。

我们现在只需要知道当开始调度事务(mService.getLifecycleManager().scheduleTransaction(clientTransaction)之后)的执行,会执行相应ActivityLifecycleItem的execute方法,所以这里我们先追踪LaunchActivityItem的execute方法

//------------------------------ActivityStackSupervisor.java------------------------------

public class LaunchActivityItem extends ClientTransactionItem {
    ...
    
    public void execute(ClientTransactionHandler client, IBinder token,
            PendingTransactionActions pendingActions) {
        Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
        ActivityClientRecord r = new ActivityClientRecord(token, mIntent, mIdent, mInfo,
                mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, mState, mPersistentState,
                mPendingResults, mPendingNewIntents, mIsForward,
                mProfilerInfo, client, mAssistToken);
        // execute方法会调用ClientTransactionHandler的handleLaunchActivity方法
        // 前面已经分析了ClientTransactionHandler是一个抽象类,真正实现类是ActivityThread类,所以调用ActivityThread#handleLaunchActivity方法
        client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
        Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
    }
    
    ...
}

可以看到execute方法会调用ClientTransactionHandler的handleLaunchActivity方法,ClientTransactionHandler是一个抽象类,真正实现类是ActivityThread类(ActivityThread整体中已分析),所以调用的是ActivityThread#handleLaunchActivity方法。

//------------------------------ActivityThread.java------------------------------

public Activity handleLaunchActivity(ActivityClientRecord r,
        PendingTransactionActions pendingActions, Intent customIntent) {
    // 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
    if (!ThreadedRenderer.sRendererDisabled
            && (r.activityInfo.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0) {
        HardwareRenderer.preload();
    }
    WindowManagerGlobal.initialize();

    // Hint the GraphicsEnvironment that an activity is launching on the process.
    GraphicsEnvironment.hintActivityLaunch();

    // 进而调用performLaunchActivity,真正去启动Activity并返回一个Activity实例对象
    final Activity a = performLaunchActivity(r, customIntent);

    if (a != null) {
        r.createdConfig = new Configuration(mConfiguration);
        reportSizeConfigurations(r);
        if (!r.activity.mFinished && pendingActions != null) {
            pendingActions.setOldState(r.state);
            pendingActions.setRestoreInstanceState(true);
            pendingActions.setCallOnPostCreate(true);
        }
    } else {
        // If there was an error, for any reason, tell the activity manager to stop us.
        try {
            ActivityTaskManager.getService()
                    .finishActivity(r.token, Activity.RESULT_CANCELED, null,
                            Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
        } catch (RemoteException ex) {
            throw ex.rethrowFromSystemServer();
        }
    }

    return a;
}

handleLaunchActivity方法调用performLaunchActivity,真正去启动Activity并返回一个Activity实例对象,来看下performLaunchActivity方法

//------------------------------ActivityThread.java------------------------------

/**  Core implementation of activity launch. */
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    // 先得到ActivityInfo对象
    ActivityInfo aInfo = r.activityInfo;
    if (r.packageInfo == null) {
        r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
                Context.CONTEXT_INCLUDE_CODE);
    }

    // 其次得到ComponentName对象
    ComponentName component = r.intent.getComponent();
    if (component == null) {
        component = r.intent.resolveActivity(
            mInitialApplication.getPackageManager());
        r.intent.setComponent(component);
    }

    if (r.activityInfo.targetActivity != null) {
        component = new ComponentName(r.activityInfo.packageName,
                r.activityInfo.targetActivity);
    }

    ContextImpl appContext = createBaseContextForActivity(r);
    Activity activity = null;
    try {
        java.lang.ClassLoader cl = appContext.getClassLoader();
        // activity实例的创建也是通过Instrumentation#newActivity得到的
        activity = mInstrumentation.newActivity(
                cl, component.getClassName(), r.intent);
        StrictMode.incrementExpectedActivityCount(activity.getClass());
        r.intent.setExtrasClassLoader(cl);
        r.intent.prepareToEnterProcess();
        if (r.state != null) {
            r.state.setClassLoader(cl);
        }
    } catch (Exception e) {
        if (!mInstrumentation.onException(activity, e)) {
            throw new RuntimeException(
                "Unable to instantiate activity " + component
                + ": " + e.toString(), e);
        }
    }

    try {
        Application app = r.packageInfo.makeApplication(false, mInstrumentation);

        if (localLOGV) Slog.v(TAG, "Performing launch of " + r);
        if (localLOGV) Slog.v(
                TAG, r + ": app=" + app
                + ", appName=" + app.getPackageName()
                + ", pkg=" + r.packageInfo.getPackageName()
                + ", comp=" + r.intent.getComponent().toShortString()
                + ", dir=" + r.packageInfo.getAppDir());

        if (activity != null) {
            CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
            Configuration config = new Configuration(mCompatConfiguration);
            if (r.overrideConfig != null) {
                config.updateFrom(r.overrideConfig);
            }
            if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
                    + r.activityInfo.name + " with config " + config);
            Window window = null;
            if (r.mPendingRemoveWindow != null && r.mPreserveWindow) {
                window = r.mPendingRemoveWindow;
                r.mPendingRemoveWindow = null;
                r.mPendingRemoveWindowManager = null;
            }
            appContext.setOuterContext(activity);
            //  调用了Activity的attach方法,attach也是Activity的一个生命周期
            activity.attach(appContext, this, getInstrumentation(), r.token,
                    r.ident, app, r.intent, r.activityInfo, title, r.parent,
                    r.embeddedID, r.lastNonConfigurationInstances, config,
                    r.referrer, r.voiceInteractor, window, r.configCallback,
                    r.assistToken);

            if (customIntent != null) {
                activity.mIntent = customIntent;
            }
            r.lastNonConfigurationInstances = null;
            checkAndBlockForNetworkAccess();
            activity.mStartedActivity = false;
            int theme = r.activityInfo.getThemeResource();
            if (theme != 0) {
                activity.setTheme(theme);
            }

            activity.mCalled = false;
            if (r.isPersistable()) {
                mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
            } else {
               
               // 此处还会调用Instrumentation#callActivityOnCreate方法,这个方法作用在其Api文档注释已经表明,会去调度Activity的onCreate方法 mInstrumentation.callActivityOnCreate(activity, r.state);
            }
            if (!activity.mCalled) {
                throw new SuperNotCalledException(
                    "Activity " + r.intent.getComponent().toShortString() +
                    " did not call through to super.onCreate()");
            }
            r.activity = activity;
        }
        r.setState(ON_CREATE);

        // updatePendingActivityConfiguration() reads from mActivities to update
        // ActivityClientRecord which runs in a different thread. Protect modifications to
        // mActivities to avoid race.
        synchronized (mResourcesManager) {
            mActivities.put(r.token, r);
        }

    } catch (SuperNotCalledException e) {
        throw e;

    } catch (Exception e) {
        if (!mInstrumentation.onException(activity, e)) {
            throw new RuntimeException(
                "Unable to start activity " + component
                + ": " + e.toString(), e);
        }
    }

    return activity;
}

performLaunchActivity做了什么?

  • 通过Instrumentation#newActivity得到的Activity实例的创建
  • 调用了Activity的attach生命周期方法
  • 调用Instrumentation#callActivityOnCreate方法,去调度Activity的onCreate方法
/**
 * Perform instantiation of the process's {@link Activity} object.  The
 * default implementation provides the normal system behavior.
 * 
 * @param cl The ClassLoader with which to instantiate the object.
 * @param className The name of the class implementing the Activity
 *                  object.
 * @param intent The Intent object that specified the activity class being
 *               instantiated.
 * 
 * @return The newly instantiated Activity object.
 */
public Activity newActivity(ClassLoader cl, String className,
        Intent intent)
        throws InstantiationException, IllegalAccessException,
        ClassNotFoundException {
    String pkg = intent != null && intent.getComponent() != null
            ? intent.getComponent().getPackageName() : null;
    // getFactory分析过了会得到AppComponentFactory对象,再通过该对象的instantiateActivity方法去实例出一个Activity实例对象
    return getFactory(pkg).instantiateActivity(cl, className, intent);
}

首先Instrumentation#newActivity会让我们想起先前分析的AppComponentFactory这个类,追踪就可知其确实直接调用AppComponentFactory的instantiateActivity方法获取Activity实例,和Application的创建一样,通过classLoader和全类名className创建Activity实例(跳过分析)。

接着可以根据上面的分析继续追踪下ResumeActivityItem的execute方法

public void execute(ClientTransactionHandler client, IBinder token,
        PendingTransactionActions pendingActions) {
    Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityResume");
    // 根据前面的分析可以知道会调用到ActivityThread的handleResumeActivity中
    client.handleResumeActivity(token, true /* finalStateRequest */, mIsForward,
            "RESUME_ACTIVITY");
    Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
public void handleResumeActivity(IBinder token, boolean finalStateRequest, boolean isForward,
            String reason) {
    ...
    // 进而调用performResumeActivity方法
    final ActivityClientRecord r = performResumeActivity(token, finalStateRequest, reason);
    ...
}
/**
 * Resume the activity.
 * @param token Target activity token.
 * @param finalStateRequest Flag indicating if this is part of final state resolution for a
 *                          transaction.
 * @param reason Reason for performing the action.
 *
 * @return The {@link ActivityClientRecord} that was resumed, {@code null} otherwise.
 */
// 该方法很明显就是去调度Activity的resume生命周期
@VisibleForTesting
public ActivityClientRecord performResumeActivity(IBinder token, boolean finalStateRequest,
        String reason) {
    final ActivityClientRecord r = mActivities.get(token);
    if (localLOGV) {
        Slog.v(TAG, "Performing resume of " + r + " finished=" + r.activity.mFinished);
    }
    if (r == null || r.activity.mFinished) {
        return null;
    }
    if (r.getLifecycleState() == ON_RESUME) {
        if (!finalStateRequest) {
            final RuntimeException e = new IllegalStateException(
                    "Trying to resume activity which is already resumed");
            Slog.e(TAG, e.getMessage(), e);
            Slog.e(TAG, r.getStateString());
            // TODO(lifecycler): A double resume request is possible when an activity
            // receives two consequent transactions with relaunch requests and "resumed"
            // final state requests and the second relaunch is omitted. We still try to
            // handle two resume requests for the final state. For cases other than this
            // one, we don't expect it to happen.
        }
        return null;
    }
    if (finalStateRequest) {
        r.hideForNow = false;
        r.activity.mStartedActivity = false;
    }
    try {
        r.activity.onStateNotSaved();
        r.activity.mFragments.noteStateNotSaved();
        checkAndBlockForNetworkAccess();
        if (r.pendingIntents != null) {
            deliverNewIntents(r, r.pendingIntents);
            r.pendingIntents = null;
        }
        if (r.pendingResults != null) {
            deliverResults(r, r.pendingResults, reason);
            r.pendingResults = null;
        }
        // 去调度Activity的Resume声明流程,界面也就可见了
        r.activity.performResume(r.startsNotResumed, reason);

        r.state = null;
        r.persistentState = null;
        r.setState(ON_RESUME);

        reportTopResumedActivityChanged(r, r.isTopResumedActivity, "topWhenResuming");
    } catch (Exception e) {
        if (!mInstrumentation.onException(r.activity, e)) {
            throw new RuntimeException("Unable to resume activity "
                    + r.intent.getComponent().toShortString() + ": " + e.toString(), e);
        }
    }
    return r;
}

可以看到流程基本一致是

ResumeActivityItem#execute
--|ActivityThread#handleResumeActivity
----|ActivityThread#performResumeActivity
-------|Activity#performResume
----------|Activity#onResume

在一开始的介绍中,就说明了不仅仅是Activity,Android的四大组件都是在ActivityThread,都是通过AppCompentFactory这个工厂类创建出来的。

至此系列的学习笔记就告一段落了(回顾复习的顺序如下):

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