activity启动流程

120 阅读4分钟

在系统启动过程中,通过zygote进程fork了一个SystemServer进程,而在这个进程中,启动了系统所必须的各种核心服务,其中AMS就是其中的重要的一个。 AMS会调用一个systemReady()函数来启动桌面 Home Activity。

调用的方法是:startHomeOnAllDisplays

紧接着会执行到:startHomeOnTaskDisplayArea

RootWindowContainer.java
boolean startHomeOnDisplay(int userId, String reason, int displayId) {
    return startHomeOnDisplay(userId, reason, displayId, false /* allowInstrumenting */, false /* fromHomeKey */);
}

boolean startHomeOnDisplay(int userId, String reason, int displayId, boolean allowInstrumenting, boolean fromHomeKey) {
    // Fallback to top focused display or default display if the displayId is invalid.
    // 由于DisplayManagerService中获取到的displayId部位INVALID_DISPLAY,因此此处判断条件不满足
    if (displayId == INVALID_DISPLAY) {
        final ActivityStack stack = getTopDisplayFocusedStack();
        displayId = stack != null ? stack.getDisplayId() : DEFAULT_DISPLAY;
    }
    
    final DisplayContent display = getDisplayContent(displayId);
    boolean result = false;
    for (int tcNdx = display.getTaskDisplayAreaCount() - 1; tcNdx >= 0; --tcNdx) {
        final TaskDisplayArea taskDisplayArea = display.getTaskDisplayAreaAt(tcNdx);
        // 最终会调用startHomeOnTaskDisplayArea函数
        result |= startHomeOnTaskDisplayArea(userId, reason, taskDisplayArea,
                allowInstrumenting, fromHomeKey);
    }
    return result;
}

boolean startHomeOnTaskDisplayArea(int userId, String reason, TaskDisplayArea taskDisplayArea,
            boolean allowInstrumenting, boolean fromHomeKey) {
    // ...... 功能无关代码,此处省略
    if (taskDisplayArea == getDefaultTaskDisplayArea()) {
        // 1. 通过ATMS的getHomeIntent函数,获取一个Intent对象
        // 这个Intent对象
        // homeIntent.action = Intent.ACTION_MAIN
        // homeIntent的flags包含Intent.FLAG_DEBUG_TRIAGED_MISSING
        // homeIntent的category包含Intent.CATEGORY_HOME
        homeIntent = mService.getHomeIntent();
        // 2. 获取包含启动信息的一个ActivityInfo对象
        aInfo = resolveHomeActivity(userId, homeIntent);
    }
    // ...... 功能无关代码,此处省略

    // Updates the home component of the intent.
    homeIntent.setComponent(new ComponentName(aInfo.applicationInfo.packageName, aInfo.name));
    homeIntent.setFlags(homeIntent.getFlags() | FLAG_ACTIVITY_NEW_TASK);
    // ...... 条件判断无法满足,代码省略
    // Update the reason for ANR debugging to verify if the user activity is the one that
    // actually launched.
    final String myReason = reason + ":" + userId + ":" + UserHandle.getUserId(
            aInfo.applicationInfo.uid) + ":" + taskDisplayArea.getDisplayId();
    // 3. 通过ActivityStartController对象的startHomeActivity函数
    mService.getActivityStartController().startHomeActivity(homeIntent, aInfo, myReason,
            taskDisplayArea);
    return true;
}
> ActivityStartController.java
void startHomeActivity(Intent intent, ActivityInfo aInfo, String reason) {
        mSupervisor.moveHomeStackTaskToTop(reason);

        mLastHomeActivityStartResult = obtainStarter(intent, "startHomeActivity: " + reason)
                .setOutActivity(tmpOutRecord)
                .setCallingUid(0)
                .setActivityInfo(aInfo)
                .execute();
        mLastHomeActivityStartRecord = tmpOutRecord[0];
        if (mSupervisor.inResumeTopActivity) {
            mSupervisor.scheduleResumeTopActivities();
        }
    }

从上述这段代码可以看到,这边主要是依次做了三件事情

  • 通过ATMS的getHomeIntent函数,获取启动Activity的一个Intent对象。

  • 通过resolveHomeActivity函数获取启动界面的ActivityInfo对象。

  • 通过ActivityStartController对象的startHomeActivity函数来启动对应的Activity。

  • obtainStarter() 方法返回的是 ActivityStarter 对象,最后的 execute() 是真正的启动逻辑。

在继续看源码之前,先思考一下现在处于哪个进程?AMS 是在 system_server 进程中初始化的,所以上面的工作都是在 system_server 进程发生的。而我们通常在开发过程中使用的 startActivity() 方法显然是在应用进程调用的。那么,普通的 startActivity() 方法又是怎么样的调用链呢?

跟进 Activity.startActivity() 方法来看一下。

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

    public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
            @Nullable Bundle options) {
        if (mParent == null) {
            options = transferSpringboardActivityOptions(options);
            // 调用 Instrumentation.execStartActivity() 方法
            Instrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode, options);
            if (ar != null) {
              // 回调 ActivityResult
                mMainThread.sendActivityResult(
                    mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                    ar.getResultData());
            }
            if (requestCode >= 0) {
                mStartedActivity = true;
            }

            cancelInputsAndStartExitTransition(options);
        } else {
          // 最终也是调用 Instrumentation.execStartActivity() 方法
            if (options != null) {
                mParent.startActivityFromChild(this, intent, requestCode, options);
            } else {
                mParent.startActivityFromChild(this, intent, requestCode);
            }
        }
    }

最终都会调用 InstrumentationexecStartActivity() 方法。Instrumentation 是个非常重要的类,Activity 的启动,生命周期的回调都离不开它。后面会多次遇到这个类。

> Instrumentation.java
public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
        IApplicationThread whoThread = (IApplicationThread) contextThread;
 		    ......
        try {
            intent.migrateExtraStreamToClipData();
            intent.prepareToLeaveProcess(who);
            // Binder 调用 AMS 来启动 Activity
            int result = ActivityManager.getService()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target != null ? target.mEmbeddedID : null,
                        requestCode, 0, null, options);
            // 检测启动结果
            checkStartActivityResult(result, intent);
        } catch (RemoteException e) {
            throw new RuntimeException("Failure from system", e);
        }
        return null;
    }

这里通过 Binder 调用 AMS 的 startActivity() 方法。ActivityManager.getService() 不用多想肯定是获取 AMS 代理对象的。

> ActivityManager.java
public static IActivityManager getService() {
    return IActivityManagerSingleton.get();
}

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

接着就进入到 AMS 的 startActivity() 方法。

> ActivityManagerService.java    
@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) {setMayWait
        return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
                resultWho, requestCode, startFlags, profilerInfo, bOptions,
                UserHandle.getCallingUserId());
    }

    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,
            boolean validateIncomingUser) {
        enforceNotIsolatedCaller("startActivity");

        userId = mActivityStartController.checkTargetUser(userId, validateIncomingUser,
                Binder.getCallingPid(), Binder.getCallingUid(), "startActivityAsUser");

        // TODO: Switch to user app stacks here.
        return mActivityStartController.obtainStarter(intent, "startActivityAsUser") // 获取 ActivityStarter 对象
                .setCaller(caller)
                .setCallingPackage(callingPackage)
                .setResolvedType(resolvedType)
                .setResultTo(resultTo)
                .setResultWho(resultWho)
                .setRequestCode(requestCode)
                .setStartFlags(startFlags)
                .setProfilerInfo(profilerInfo)
                .setActivityOptions(bOptions)
                .setMayWait(userId)
                .execute();
    }

接下来和之前启动 Home Activity 比较相似了。获取 ActivityStarter 对象,提供参数,最后 execute()

综上:

  • 无论是launcher启动还是普通activity启动,都会执行到ActivityStarterexecute方法;

  • 通过ActivityStackSupervisor中的startSpecificActivity方法判断应用进程IApplicationThread是否启动;

  • 如果已启动,则直接通过ActivityStackSupervisorrealStartActivityLocked方法启动根activity。

  • 如果未启动,则AMS以Socket方式通知Zygote需要启动一个新进程。 Process.start()

    • fork出一个新的应用进程;

    • 进程启动之后,先创建一个Binder线程池,然后反射调用ActivityThreadmain方法;

    • main方法中,首先创建应用程序主线程的Looper及MessageQueue对象,并且最后调用主线程的Looper的loop方法启动消息循环;

    • 其中还会调用attach方法,告知AMS应用程序启动成功,AMS接收到通知,调用attachApplication方法,其中有两步:

      • 调用ApplicationThread对象的bindApplication方法,通知应用程序创建一个Application;

      • 调用ActivityStackSupervisorrealStartActivityLocked方法启动根activity。

  • 调用ApplicationThreadscheduleTransaction方法,一步一步的执行handleLaunchActivityhandleResumeActivityperformLaunchActivityperformResumeActivity等各个生命周期方法。

c0beee5907744caa99b942beb0403eef_tplv-k3u1fbpfcp-zoom-in-crop-mark_4536_0_0_0.png