基于android10.0源码分析Activity的启动流程

Posted hymKing

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于android10.0源码分析Activity的启动流程相关的知识,希望对你有一定的参考价值。

一、梳理源码流程干什么

Activity是四大组件中最重要的组件之一,下面来分析Activity的启动过程,了解Activity的启动过程能帮助我们更好的对组件Activity的理解,也能帮助我们更好的把控Activity生命周期的变化过程。

当然Activity作为四大组件之首,10.0版本的Activity的代码函数在8000行,关联的一些类Instrumentation、ActivityTaskManager、ActivityStarter等等,怎么也是几万行的代码,一次完全分析起来会很困难,这里面主要通过启动的核心流程源码分析,帮我们理清楚Activity的启动流程,内部其实有很多细节,这些细节和我们的日常开发也都非常相关,关于这部分细节性的代码,由于篇幅问题,本文并不会全部体现。

先上Activity启动流程梳理图:

上图非完整的启动流程,在后续源码分析中,还有第二条分支,就是当application未创建的情况下,会去创建进程,fork应用进程等,后文的源码分析中会简单提到,详细流程也适合做专题分析。

通过这样的一个梳理图,主要是清晰系统进程和应用进程中的代码调用流程,建议先初步看一下梳理图,在看后面的源码分析过程中不断的回到图中来,加深自己的理解和印象,在文章末尾,源码分析之后,也会对梳理图中的核心类进行说明。

二、源码流程分析

下面主要从源码角度来进行分析,分析的入口就是startActivity(),分析源码中的Activity.java中的startActivity()方法

2.1 应用进程StartActivity

public void startActivity(Intent intent, @Nullable Bundle options) {
        ......
        if (options != null) {
            startActivityForResult(intent, -1, options);
        } else {
            // Note we want to go through this call for compatibility with
            // applications that may have overridden the method.
            startActivityForResult(intent, -1);
        }
    }

从上述代码来看startActivity的方法体来看,最终都会调用startActivityForResult()方法,接下来看startActivityForResult方法源码:

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

            cancelInputsAndStartExitTransition(options);
            // TODO Consider clearing/flushing other event sources and events for child windows.
        } else {//标注3
            if (options != null) {
                mParent.startActivityFromChild(this, intent, requestCode, options);
            } else {
                // Note we want to go through this method for compatibility with
                // existing applications that may have overridden it.
                mParent.startActivityFromChild(this, intent, requestCode);
            }
        }
    }

在startActivityForResult方法体中,先看到了标注1的位置是一个条件判断mParent==null。mParent代表的是ActivityGroup,Api13已经被废弃,这里面其实我们标注3的内容就不用太多去关注了,当然从方法名上mParent.startActivityFromChild也能看出来,的确是子Activity来启动Activity。我们把关注点仍然回到标注2的位置

mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode, options);

mInstumentation好像很面熟,当然这个类比我们想象的要强大的多,Instrumentation为仪表盘,管理着Activity和Application的生命周期,一个进程对应了一个Instrumentation。

在后续的分析过程中,我们会看到Instrumentation在整个Activity启动过程中的强大作用,接下来我们继续分析execStartActivity的核心流程

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);
            //这块的代码和8.0的是有区别,这块也是我们启动流程里面的核心代码
            //8.0里面的源码:ActivityManagerNative.getDefault()
            int result = ActivityTaskManager.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;
    }

上述标注1的位置,可以看到启动activity的真正实现交给了ActivityTaskManager.getService()的startActivity的方法了。

 public static IActivityTaskManager getService() {
        return IActivityTaskManagerSingleton.get();
    }
 private static final Singleton<IActivityTaskManager> IActivityTaskManagerSingleton =
            new Singleton<IActivityTaskManager>() {
                @Override
                protected IActivityTaskManager create() {
                  //获得Binder对象实例
                    final IBinder b = ServiceManager.getService(Context.ACTIVITY_TASK_SERVICE);
                    return IActivityTaskManager.Stub.asInterface(b);
                }
            };

从这里可以推测,此处把application启动的过程要转交给通过ActivityTaskManager获得IActivityTaskManagerSingleton的单例对象去处理,上述备注部分,可以看出返回的是一个Aidl的接口实例。

我们也查看IActivityTaskManager的实现类,通过源码我们找到了ActivityTaskManagerService继承了IActivityTaskManager。

public class ActivityTaskManagerService extends IActivityTaskManager.Stub{...省去...}

从这里,也可以印证:同一个应用A activity启动一个B activity 本质上也是一个跨进程调用的过程。

为什么这里面需要用AMS的Binder对象呢?

看到Binder,有些android知识储备的应该能想到这是跨进程通信,那么到底哪两个进程进行了跨进程的通信?这里面需要了解到ActivityManagerService实际上是在android系统启动的时候,这个服务就被开启了,这个服务被运行在系统进程中,即ActivityMangerService是运行在android system进程中的,并且系统一启动,这个service就会被启动。这里面显然是我们自己的app进程和system进程之间进行了ipc调用。

2.2进入到ATMS进程startActivity

ATMS,即ActivityTaskServiceManager,运行在系统服务进程中,继续看ActivityTaskManagerService中的源码:

@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());
}

实际会调用startActivityAsUser()。startActvityAsUser()的实现:

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) {
    ...
    // TODO: Switch to user app stacks here.
    return getActivityStartController().obtainStarter(intent, "startActivityAsUser")
            .setCaller(caller)
            .setCallingPackage(callingPackage)
            .setResolvedType(resolvedType)
            .setResultTo(resultTo)
            .setResultWho(resultWho)
            .setRequestCode(requestCode)
            .setStartFlags(startFlags)
            .setProfilerInfo(profilerInfo)
            .setActivityOptions(bOptions)
            .setMayWait(userId)
            .execute();//实际调用的是ActivityStarter的excute的方法

}

execute的方法实际ActivityStarter类在执行,之后再调用到startActivityUnchecked(),再调用到RootActivityContainer类中resumeFocusedStacksTopActivities(),最终会调用到ActivityStack的resumeTopActivityUncheckdeLocked(),RootActivityContainer类中的代码调用如下

if (!resumedOnDisplay) {
    // 查找符合条件的任务栈
    final ActivityStack focusedStack = display.getFocusedStack();
    if (focusedStack != null) {
        focusedStack.resumeTopActivityUncheckedLocked(target, targetOptions);
    }
}

ActivityStack中的resumeTopActivityUncheckedLocked()的源码:

/**
 * 确定栈顶Activity是否是resumed
 */
@GuardedBy("mService")
boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
    if (mInResumeTopActivity) {
        // Don't even start recursing.
        return false;
    }
    boolean result = false;
    try {
        mInResumeTopActivity = true;
        //核心代码:
        result = resumeTopActivityInnerLocked(prev, options);
        // 栈顶有resuming的activity,有必要进行pause 
        final ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */);
        if (next == null || !next.canTurnScreenOn()) {
            checkReadyForSleep();
        }
    } finally {
        mInResumeTopActivity = false;
    }

    return result;
}

可以看到在ActivityStack的resumeTopActivityUncheckeLocked方法中个,继续调用了resumeTopActivityInnerLocked();在此方法中,针对于activity启动流程环节,要使得栈中的resume的Activity进行暂停:

private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
  .....
	if (mResumedActivity != null) {
    if (DEBUG_STATES) Slog.d(TAG_STATES,
            "resumeTopActivityLocked: Pausing " + mResumedActivity);
    pausing |= startPausingLocked(userLeaving, false, next, false);
	}
  ....
}

关于pause栈顶Activity的内部流程,这块不做详细分析(在源码分析Activity生命周期专题中再做分析)。我们要继续回调启动Activity的核心流程里面来,在上述方法中,通过一系列的处理,最终会调用到启动Activity的方法里面来:

if (next.attachedToProcess()) {
		...
		 mService.getLifecycleManager().scheduleTransaction(transaction);
		....
}else{
     // Whoops, need to restart this activity!
     if (!next.hasBeenLaunched) {
            next.hasBeenLaunched = true;
      } else {
            if (SHOW_APP_STARTING_PREVIEW) {
              next.showStartingWindow(null /* prev */, false /* newTask */,
                            false /* taskSwich */);
             }
            if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Restarting: " + next);
      }
      if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Restarting " + next);
            mStackSupervisor.startSpecificActivityLocked(next, true, true);
}

如上代码片段,一堆处理后,同样在resumeTopActivityInnerLocked方法中,会调用mStackSupervisor.startSpecificActivityLocked()。此方法的源码:

void startSpecificActivityLocked(ActivityRecord r, boolean andResume, boolean checkConfig) {
        // 判断当前要启动的Activity的application是否已经存在
        final WindowProcessController wpc =
                mService.getProcessController(r.processName, r.info.applicationInfo.uid);

        boolean knownToBeDead = false;
        // 如果已经存在,主线程也正常
        if (wpc != null && wpc.hasThread()) {
            try {
                //调用真实启动Activity的方法
                realStartActivityLocked(r, wpc, andResume, checkConfig);
                //return 后续的逻辑都不会走
                return;
            } catch (RemoteException e) {
                ... //出现异常
            }

            //出现异常重启application(现在好多手机,应用奔溃后,都能自启,待验证)
            knownToBeDead = true;
        }
        if (getKeyguardController().isKeyguardLocked()) {
            r.notifyUnknownVisibilityLaunched();
        }

        try {
            ...
            // 走到这里,说明进程未创建,意义启动进程的消息
            final Message msg = PooledLambda.obtainMessage(
                    ActivityManagerInternal::startProcess, 	mService.mAmInternal,r.processName,r.info.applicationInfo, knownToBeDead, "activity",r.intent.getComponent());
            //通过ActivityTaskManagerService中的Handler发送消息,创建一个新的进程
            mService.mH.sendMessage(msg);
        } finally {
            Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
        }
    }

在这个流程中,实际存在两个分支逻辑,一条分支是在当前的application中去启动Activity,另一个分支先创建当前要启动的Activity所需要的进程。先看mStackSupervisor.realStartActivityLocked():

boolean realStartActivityLocked(ActivityRecord r, WindowProcessController proc,
        boolean andResume, boolean checkConfig) throws RemoteException {
  ...
    try {
                if (!proc.hasThread()) {
                    //远程调用异常
                    throw new RemoteException();
                }
      					......
      					// 创建Activity启动事务.proc.getThread()是applicationThread
                final ClientTransaction clientTransaction = ClientTransaction.obtain(
                        proc.getThread(), r.appToken);

                final DisplayContent dc = r.getDisplay().mDisplayContent;
                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));

                // 设置预期的最终状态
                final ActivityLifecycleItem lifecycleItem;
                if (andResume) {
                    lifecycleItem = ResumeActivityItem.obtain(dc.isNextTransitionForward());
                } else {
                    lifecycleItem = PauseActivityItem.obtain();
                }
                clientTransaction.setLifecycleStateRequest(lifecycleItem);

                // 启动事务
                mService.getLifecycleManager().scheduleTransaction(clientTransaction);
    } catch (RemoteException e) {
           //远程调用异常     
    }

ClientTransaction是啥呢,简单看一下这个例的文档注释:

/**
 * 持有一系列消息,用于和client交互(app进程)
 * This includes a list of callbacks and a final lifecycle state.
 */
public class ClientTransaction implements Parcelable, ObjectPoolItem {}

回到realStartActivityLocked()方法的源码中来,也特地贴出了catch的异常,很显然这部分代码的执行,仍然是在系统进程中执行。上述代码中添加了核心代码的中文注释,可以看到这段代码中,主要是创建事务,同时传入ApplicationThread,而ApplicationThread继承于Binder,传入的目的就是后面要和目标App进程进行通信。mService.getLifecycleManager().scheduleTransaction(clientTransaction);这句代码,是计划启动事务。继续看这部分的源码:

/**
 * 计划一个事务,包含多个callbacks和lifecycle request
 */
void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
    final IApplicationThread client = transaction.getClient();
    //核心代码
    transaction.schedule();
    if (!(client instanceof Binder)) {
        transaction.recycle();
    }
}

接下来就是ClientTransaction:

public void schedule() throws RemoteException {
    mClient.scheduleTransaction(this);
}

实际调用额是mClient.scheduleTransaction(),mClient这个全局变量是什么呢?

在上述代码片段中有创建ClientTransaction的方法调用:

final ClientTransaction clientTransaction = ClientTransaction.obtain(
        proc.getThread(), r.appToken);

追一下这个obtain方法的源码:

/** Obtain an instance initialized with provided params. */
public static ClientTransaction obtain(IApplicationThread client, IBinder activityToken) {
    ClientTransaction instance = ObjectPool.obtain(ClientTransaction.class);
    if (instance == null) {
        instance = new ClientTransaction(以上是关于基于android10.0源码分析Activity的启动流程的主要内容,如果未能解决你的问题,请参考以下文章

基于android10.0源码分析Activity的启动流程

Android的PackageManagerService10.0源码解读(AndroidManifest.xml解析)

Android的PackageManagerService10.0源码解读(AndroidManifest.xml解析)

Android的PackageManagerService10.0源码解读(AndroidManifest.xml解析)

Android的PackageManagerService10.0源码解读(AndroidManifest.xml解析)

Android判断Activity是否在AndroidManifest.xml里面注册(源码分析)