基于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();
//ClientTransaction中的全局对象mClien以上是关于基于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解析)