Activity 启动流程(四)—— ActivityThread 初始化阶段

393 阅读6分钟

前言

Activity 启动过程文章系列中,首先会先对启动流程从头到尾进行简要梳理,后续文章会对其中重要细节进行详细展开。

启动流程梳理:

  1. Activity 启动流程(一)—— Launcher 阶段
  2. Activity 启动流程(二)—— AMS 处理阶段
  3. Activity 启动流程(三)—— 应用程序进程启动阶段
  4. Activity 启动流程(四)—— ActivityThread 初始化阶段
  5. Activity 启动流程(五)—— Activity 启动阶段

1. ActivityThread 初始化

1.1 ActivityThread 入口

应用程序进程创建后,会反射调用 ActivityThread 的 main 方法,ActivityThread 运行在主线程中:

public final class ActivityThread extends ClientTransactionHandler
        implements ActivityThreadInternal {
        
    // 初始化 ApplicationThread
    @UnsupportedAppUsage
    final ApplicationThread mAppThread = new ApplicationThread();
    
    @UnsupportedAppUsage
    final Looper mLooper = Looper.myLooper();
    
    // 初始化 Handler,给 ApplicationThread 与 ActivityThread 通信使用
    @UnsupportedAppUsage
    final H mH = new H();
    
    public static void main(String[] args) {
        ...
        // 主线程 Looper
        Looper.prepareMainLooper();

        // 初始化 ActivityThread
        ActivityThread thread = new ActivityThread();
        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);
        // 开启主线程 Looper 循环
        Looper.loop();

        throw new RuntimeException("Main thread loop unexpectedly exited");
    }
    
    @UnsupportedAppUsage
    private void attach(boolean system, long startSeq) {
        ...
        if (!system) {
            ...
            final IActivityManager mgr = ActivityManager.getService();
            try {
                mgr.attachApplication(mAppThread, startSeq);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
            ...
        }
    }
}

ActivityThread 的 attach 方法中使用 Binder 通信跨进程调用了 AMS 的 attachApplication() 方法,并将ApplicationThread 作为参数传递过去。

1.2 AMS attachApplication

下面执行 AMS 的 attachApplication 绑定 ApplicationThread,ApplicationThread 对象作为 IApplicationThread 接口的服务端,AMS 作为客户端进行调用:

// services/core/java/com/android/server/am/ActivityManagerService.java
@Override
public final void attachApplication(IApplicationThread thread, long startSeq) {
    if (thread == null) {
        throw new SecurityException("Invalid application interface");
    }
    synchronized (this) {
        int callingPid = Binder.getCallingPid();
        final int callingUid = Binder.getCallingUid();
        final long origId = Binder.clearCallingIdentity();
        attachApplicationLocked(thread, callingPid, callingUid, startSeq);
        Binder.restoreCallingIdentity(origId);
    }
}

@GuardedBy("this")
private boolean attachApplicationLocked(@NonNull IApplicationThread thread,
        int pid, int callingUid, long startSeq) {

    // 保存当前正在运行的进程的所有信息
    ProcessRecord app;
    ...
    try {
        ...
        if (app.getIsolatedEntryPoint() != null) {
            // This is an isolated process which should just call an entry point instead of
            // being bound to an application.
            thread.runIsolatedEntryPoint(
                    app.getIsolatedEntryPoint(), app.getIsolatedEntryPointArgs());
        } else if (instr2 != null) {
            // 跨进程调用 ApplicationThread 的 bindApplication 创建绑定 Application
            thread.bindApplication(processName, appInfo, providerList,
                    instr2.mClass,
                    profilerInfo, instr2.mArguments,
                    instr2.mWatcher,
                    instr2.mUiAutomationConnection, testMode,
                    mBinderTransactionTrackingEnabled, enableTrackAllocation,
                    isRestrictedBackupMode || !normalMode, app.isPersistent(),
                    new Configuration(app.getWindowProcessController().getConfiguration()),
                    app.getCompat(), getCommonServicesLocked(app.isolated),
                    mCoreSettingsObserver.getCoreSettingsLocked(),
                    buildSerial, autofillOptions, contentCaptureOptions,
                    app.getDisabledCompatChanges(), serializedSystemFontMap);
        ...
        // 给WindowProcessController中的变量mThread赋值
        synchronized (mProcLock) {
            app.makeActive(thread, mProcessStats);
            checkTime(startTime, "attachApplicationLocked: immediately after bindApplication");
        }
        ...
        if (!mConstants.mEnableWaitForFinishAttachApplication) {
            finishAttachApplicationInner(startSeq, callingUid, pid);
        }
    } catch (Exception e) {
        // We need kill the process group here. (b/148588589)
        Slog.wtf(TAG, "Exception thrown during bind of " + app, e);
        app.resetPackageList(mProcessStats);
        app.unlinkDeathRecipient();
        app.killLocked("error during bind", ApplicationExitInfo.REASON_INITIALIZATION_FAILURE,
                true);
        handleAppDiedLocked(app, pid, false, true, false /* fromBinderDied */);
        return;
    }
}

AMS 的 attachApplication 方法在获取到 pid、uid 后继续调用 AMS 的 attachApplicationLocked 方法。AMS的 attachApplicationLocked 方法中关注以下流程:

  1. 通过跨进程通信调用应用进程中 ApplicationThread 的 bindApplication 创建并绑定 Application。
  2. ProcessRecord 调用 makeActive 方法给 WindowProcessController 中的变量 mThread 赋值。
  3. 通过 finishAttachApplicationInner 本地服务过渡到 ATMS 启动根 Activity。

先来看看 makeActive 方法代码如下:

// services/core/java/com/android/server/am/ProcessRecord.java
@GuardedBy({"mService", "mProcLock"})
public void makeActive(IApplicationThread thread, ProcessStatsService tracker) {
    mProfile.onProcessActive(thread, tracker);
    mThread = thread;
    mWindowProcessController.setThread(thread);
}    

里面调用了 WindowProcessController 的 setThread 方法存储 IApplicationThread 实例,代码如下:

// services/core/java/com/android/server/wm/WindowProcessController.java
@HotPath(caller = HotPath.PROCESS_CHANGE)
public void setThread(IApplicationThread thread) {
    synchronized (mAtm.mGlobalLockWithoutBoost) {
        mThread = thread;
        if (thread != null) {
            setLastReportedConfiguration(getConfiguration());
        } else {
            mAtm.mVisibleActivityProcessTracker.removeProcess(this);
        }
    }
}

WindowProcessController 的 setThread 方法中将传入的 IApplicationThread 实例赋值给 mThread 保存,前面进程不存在的情况下,startSpecificActivity 方法中通过 wpc.hasThread 拿到的值为 false,因为进程创建完成后才给 WindowProcessController 中的 mThread 赋值。

1.3 App bindApplication

IApplicationThread 的 bindApplication 方法调用的是应用进程中的实现类 ApplicationThread 的bindApplication 方法代码如下:

// core/java/android/app/ActivityThread.java
@Override
public final void bindApplication(String processName, ApplicationInfo appInfo,
        ProviderInfoList providerList, 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, long[] disabledCompatChanges,
        SharedMemory serializedSystemFontMap) {
    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 data = new AppBindData();
    data.processName = processName;
    data.appInfo = appInfo;
    data.providers = providerList.getList();
    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;
    data.disabledCompatChanges = disabledCompatChanges;
    data.mSerializedSystemFontMap = serializedSystemFontMap;
    sendMessage(H.BIND_APPLICATION, data);
}

bindApplication 方法中通过内部类 H 发送 Handler 消息,进而调用到 ActivityThread 的 handleBindApplication 方法:

@UnsupportedAppUsage
// core/java/android/app/ActivityThread.java
private void handleBindApplication(AppBindData data) {
   ...
    final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
    mConfigurationController.updateLocaleListFromAppContext(appContext);

    ...
    if (ii != null) {
        initInstrumentation(ii, data, appContext);
    } else {
        mInstrumentation = new Instrumentation();
        mInstrumentation.basicInit(this);
    }

    ...
    Application app;
    ...
    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);
        sendMessage(H.SET_CONTENT_CAPTURE_OPTIONS_CALLBACK, data.appInfo.packageName);

        mInitialApplication = app;
        final boolean updateHttpProxy;
        synchronized (this) {
            updateHttpProxy = mUpdateHttpProxyOnBind;
            // This synchronized block ensures that any subsequent call to updateHttpProxy()
            // will see a non-null mInitialApplication.
        }
        if (updateHttpProxy) {
            ActivityThread.updateHttpProxy(app);
        }

        // don't bring up providers in restricted mode; they may depend on the
        // app's custom Application class
        // 初始化ContentProvider,里面会构建ContentProvider实例并调用其onCreate()方法
        if (!data.restrictedBackupMode) {
            if (!ArrayUtils.isEmpty(data.providers)) {
                installContentProviders(app, data.providers);
            }
        }

        // Do this after providers, since instrumentation tests generally start their
        // test thread at this point, and we don't want that racing.
        try {
            mInstrumentation.onCreate(data.instrumentationArgs);
        }
        ...
        try {
            mInstrumentation.callApplicationOnCreate(app);
        } 
        ...
    }

    ...
}

在 handleBindApplication 方法中创建了 Instrumentation 实例和 Application 实例。

ActivityThread 的 performLaunchActivity 方法中也有创建 Application 实例的操作,里面会先判断Application 是否已存在。

也就是说,正常情况下 Application 的初始化是在 handleBindApplication 方法中的,并且是创建进程后调用的。performLaunchActivity 中只是做了一个检测,异常情况 Application 不存在时才会创建。

2. Activity 启动

2.1 ATMS attachApplication

App 端 bindApplication 运行完之后,回到前面的 AMS attachApplication 方法,继续调用 finishAttachApplicationInner 方法:

private void finishAttachApplicationInner(long startSeq, int uid, int pid) {
    ...
    synchronized (this) {
        ...

        // See if the top visible activity is waiting to run in this process...
        if (normalMode) {
            try {
                // 继续调用。获取了 WindowProcessController 对象,AMS 与 WMS 通信的桥梁。
                // ActivityTaskManagerInternal 是一个抽象类,实现类是 ATMS 的内部类 LocalService。
                didSomething = mAtmInternal.attachApplication(app.getWindowProcessController());
            } catch (Exception e) {
                Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
                badApp = true;
            }
        }

        ...
    }
}

ActivityTaskManagerInternal 是一个抽象类,实现类是 ATMS 的内部类 LocalService。看一下 ATMS 中的 attachApplication 方法:

// services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@HotPath(caller = HotPath.PROCESS_CHANGE)
@Override
public boolean attachApplication(WindowProcessController wpc) throws RemoteException {
    synchronized (mGlobalLockWithoutBoost) {
        if (Trace.isTagEnabled(TRACE_TAG_WINDOW_MANAGER)) {
            Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "attachApplication:" + wpc.mName);
        }
        try {
            return mRootWindowContainer.attachApplication(wpc);
        } finally {
            Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
        }
    }
}

该方法继续调用 RootWindowContainer 的 attachApplication 方法:

// services/core/java/com/android/server/wm/RootWindowContainer.java
boolean attachApplication(WindowProcessController app) throws RemoteException {
    try {
        return mAttachApplicationHelper.process(app);
    } finally {
        mAttachApplicationHelper.reset();
    }
}

2.2 通过 AttachApplicationHelper 启动 Activity

继续调用 AttachApplicationHelper 的 process 方法,AttachApplicationHelper 是 RootWindowContainer 的内部类:

private class AttachApplicationHelper implements Consumer<Task>, Predicate<ActivityRecord> {
    private boolean mHasActivityStarted;
    private RemoteException mRemoteException;
    private WindowProcessController mApp;
    private ActivityRecord mTop;

    void reset() {
        mHasActivityStarted = false;
        mRemoteException = null;
        mApp = null;
        mTop = null;
    }

    boolean process(WindowProcessController app) throws RemoteException {
        // 将 WindowProcessController 对象传递给 AttachApplicationHelper
        mApp = app;
        // RootWindowContainer extends WindowContainer<DisplayContent>
        // DisplayContent
        for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
            // DisplayContent.forAllRootTasks
            getChildAt(displayNdx).forAllRootTasks(this);
            if (mRemoteException != null) {
                throw mRemoteException;
            }
        }
        if (!mHasActivityStarted) {
            ensureActivitiesVisible(null /* starting */, 0 /* configChanges */,
                    false /* preserveWindows */);
        }
        return mHasActivityStarted;
    }

    @Override
    public void accept(Task rootTask) {
        if (mRemoteException != null) {
            return;
        }
        if (rootTask.getVisibility(null /* starting */)
                == TASK_FRAGMENT_VISIBILITY_INVISIBLE) {
            return;
        }
        mTop = rootTask.topRunningActivity();
        rootTask.forAllActivities(this);
    }

    @Override
    public boolean test(ActivityRecord r) {
        if (r.finishing || !r.showToCurrentUser() || !r.visibleIgnoringKeyguard
                || r.app != null || mApp.mUid != r.info.applicationInfo.uid
                || !mApp.mName.equals(r.processName)) {
            return false;
        }

        try {
            // 启动 Activity
            if (mTaskSupervisor.realStartActivityLocked(r, mApp,
                    mTop == r && r.getTask().canBeResumed(r) /* andResume */,
                    true /* checkConfig */)) {
                mHasActivityStarted = true;
            }
        } catch (RemoteException e) {
            Slog.w(TAG, "Exception in new application when starting activity " + mTop, e);
            mRemoteException = e;
            return true;
        }
        return false;
    }
}

forAllRootTasks 遍历所有子节点:

// frameworks/base/services/core/java/com/android/server/wm/WindowContainer.java
void forAllRootTasks(Consumer<Task> callback) {
    forAllRootTasks(callback, true /* traverseTopToBottom */);
}

void forAllRootTasks(Consumer<Task> callback, boolean traverseTopToBottom) {
    int count = mChildren.size();
    if (traverseTopToBottom) {
        for (int i = count - 1; i >= 0; --i) {
            // 1. //  只有 Task 重新了该方法
            mChildren.get(i).forAllRootTasks(callback, traverseTopToBottom);
        }
    } else {
        for (int i = 0; i < count; i++) {
            mChildren.get(i).forAllRootTasks(callback, traverseTopToBottom);
            // Root tasks may be removed from this display. Ensure each task will be processed
            // and the loop will end.
            int newCount = mChildren.size();
            i -= count - newCount;
            count = newCount;
        }
    }
}

递归遍历到 Task 节点:

@Override
void forAllRootTasks(Consumer<Task> callback, boolean traverseTopToBottom) {
    if (isRootTask()) {
        // AttachApplicationHelper.accept
        callback.accept(this);
    }
}

接着执行回调方法:

@Override
public void accept(Task rootTask) {
    if (mRemoteException != null) {
        return;
    }
    if (rootTask.getVisibility(null /* starting */)
            == TASK_FRAGMENT_VISIBILITY_INVISIBLE) {
        return;
    }
    mTop = rootTask.topRunningActivity();
    rootTask.forAllActivities(this);
}

继续调用 Task 的 forAllActivities 方法,遍历所有的 ActivityRecord 节点:


boolean forAllActivities(Predicate<ActivityRecord> callback) {
    return forAllActivities(callback, true /*traverseTopToBottom*/);
}

boolean forAllActivities(Predicate<ActivityRecord> callback, boolean traverseTopToBottom) {
    if (traverseTopToBottom) {
        for (int i = mChildren.size() - 1; i >= 0; --i) {
            // ActivityRecord
            if (mChildren.get(i).forAllActivities(callback, traverseTopToBottom)) return true;
        }
    } else {
        final int count = mChildren.size();
        for (int i = 0; i < count; i++) {
            if (mChildren.get(i).forAllActivities(callback, traverseTopToBottom)) return true;
        }
    }

    return false;
}

调用到 ActivityRecord 的 forAllActivities 方法:

@Override
boolean forAllActivities(Predicate<ActivityRecord> callback, boolean traverseTopToBottom) {
    return callback.test(this);
}

回调 test 方法:

@Override
public boolean test(ActivityRecord r) {
    if (r.finishing || !r.showToCurrentUser() || !r.visibleIgnoringKeyguard
            || r.app != null || mApp.mUid != r.info.applicationInfo.uid
            || !mApp.mName.equals(r.processName)) {
        return false;
    }

    try {
        // 启动 Activity
        if (mTaskSupervisor.realStartActivityLocked(r, mApp,
                mTop == r && r.getTask().canBeResumed(r) /* andResume */,
                true /* checkConfig */)) {
            mHasActivityStarted = true;
        }
    } catch (RemoteException e) {
        Slog.w(TAG, "Exception in new application when starting activity " + mTop, e);
        mRemoteException = e;
        return true;
    }
    return false;
}

继续调用 ActivityStackSupervisor 的 realStartActivityLocked 方法。从这里开始,跟普通 Activity 的启动流程一样了。