本文简单分析一下activity的启动流程。
分析基于Android 9.0源码,有兴趣的朋友可以在AndroidStudio创建一个API28的HelloWorld工程跟着看,如果发现文章有什么问题,可以联系我。
话不多说,先上图,流程图1:
工具类,包装了ActivityManagerService的调用。一些插件化方案就是通过hook该类实现的,例如didi的VirtualApk
Android核心服务,负责调度各应用进程,管理四大组件。实现了IActivityManager接口,应用进程能通过Binder机制调用系统服务。
Activity启动的工具类,处理启动activity的各种flag。
管理所有应用的Activity的栈,其中mFocusedStack就是当前应用的activity栈。
启动Activity的消息。收到消息后执行execute方法启动activity。
应用的主线程。
接下来开始分析流程:
流程图1,第1-3步,Activity的startActivity会调用startActivityForResult。当应用已经启动时,会先调用startActivityFromChild。但是无论应用是否启动,最后都会调用Instrumentation.execStartActivity
。
正如前面所说,ActivityManagerService实现了IActivityManager.aidl
接口,提供了应用进程调用系统服务的方法,而Instrumentation包装了ActivityManagerService的调用。
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
@Nullable Bundle options) {
if (mParent == null) {
...
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode, options);
...
} else {
if (options != null) {
mParent.startActivityFromChild(this, intent, requestCode, options);
} else {
mParent.startActivityFromChild(this, intent, requestCode);
}
}
}
public void startActivityFromChild(@NonNull Activity child, @RequiresPermission Intent intent,
int requestCode, @Nullable Bundle options) {
...
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, child,
intent, requestCode, options);
...
}
流程图1,第4步,Instrumentation调用ActivityManagerService的startActivity
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
IApplicationThread whoThread = (IApplicationThread) contextThread;
...
try {
...
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;
}
流程图1,第5-6步,ActivityManagerService创建ActivityStarter并执行。
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) {
...
return mActivityStartController.obtainStarter(intent, "startActivityAsUser")
.setCaller(caller)
.setCallingPackage(callingPackage)
.setResolvedType(resolvedType)
.setResultTo(resultTo)
.setResultWho(resultWho)
.setRequestCode(requestCode)
.setStartFlags(startFlags)
.setProfilerInfo(profilerInfo)
.setActivityOptions(bOptions)
.setMayWait(userId)
.execute();
}
流程图1,第7步,由于第6步setMayWait将mayWait设置为true,所以执行startActivityMayWait方法。
ActivityStarter setMayWait(int userId) {
mRequest.mayWait = true;
mRequest.userId = userId;
return this;
}
int execute() {
try {
if (mRequest.mayWait) {
return startActivityMayWait(...);
} else {
return startActivity(...);
}
} finally {
onExecutionComplete();
}
}
流程图1,第8-11步,ActivityStarter处理启动activity的intent和flag比较繁琐,最后会调用ActivityStackSupervisor的resumeFocusedStackTopActivityLocked。
boolean resumeFocusedStackTopActivityLocked(
ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
...
if (targetStack != null && isFocusedStack(targetStack)) {
return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
}
final ActivityRecord r = mFocusedStack.topRunningActivityLocked();
if (r == null || !r.isState(RESUMED)) {
mFocusedStack.resumeTopActivityUncheckedLocked(null, null);
} else if (r.isState(RESUMED)) {
...
}
return false;
}
流程图1,第12步,resumeTopActivityInnerLocked是一个非常冗长的方法,该方法会判断栈中是否有需要启动的Activity,判断Activity是否在栈顶等等。如果需要启动的Activity没有被创建,就会执行流程图13步ActivityStackSupervisor的startSpecificActivityLocked方法。
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
final ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */);
if (next.app != null && next.app.thread != null) {
...
}else{
// Whoops, need to restart this activity!
...
mStackSupervisor.startSpecificActivityLocked(next, true, true);
}
}
流程图1,第13-14步,startSpecificActivityLocked方法中先判断App是否启动,如果启动则执行realStartActivityLocked。如果未启动则调用ActivityManagerService.startProcessLocked方法启动App。
为了分析方便,我们先看App启动的情况。在realStartActivityLocked方法中,ActivityManangerService会调用应用进程的接口,最终执行ClientTransaction的callBack,也就是LaunchActivityItem。这个调用过程将在稍后分析。
void startSpecificActivityLocked(ActivityRecord r,
boolean andResume, boolean checkConfig) {
// Is this activity's application already running?
ProcessRecord app = mService.getProcessRecordLocked(r.processName,
r.info.applicationInfo.uid, true);
if (app != null && app.thread != null) {
try {
...
realStartActivityLocked(r, app, andResume, checkConfig);
return;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when starting activity "
+ r.intent.getComponent().flattenToShortString(), e);
}
}
mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
"activity", r.intent.getComponent(), false, false, true);
}
final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
boolean andResume, boolean checkConfig) throws RemoteException {
...
// Create activity launch transaction.
final ClientTransaction clientTransaction = ClientTransaction.obtain(app.thread,
r.appToken);
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, app.repProcState, r.icicle,
r.persistentState, results, newIntents, mService.isNextTransitionForward(),
profilerInfo));
...
// Schedule transaction.
mService.getLifecycleManager().scheduleTransaction(clientTransaction);
...
}
流程图1,第15步,LaunchActivityItem的execute方法执行了ClientTransactionHandler的handleLaunchActivity。而这个ClientTransactionHandler就是ActivityThread。至于为什么是ActivityThread,可以看第二部分。
@Override
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);
client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
流程图1,第16-19,ActivityThread执行handleLaunchActivity方法,调用真正Activity启动方法performLaunchActivity。
performLaunchActivity中调用Instrumentation.newActivity方法创建Activity对象!
创建完成后,performLaunchActivity会继续调用Instrumentation.callActivityOnCreate。这里往下走就会调用Activity.OnCreate。
// ActivityThread.java:
@Override
public Activity handleLaunchActivity(ActivityClientRecord r,
PendingTransactionActions pendingActions, Intent customIntent) {
...
final Activity a = performLaunchActivity(r, customIntent);
...
return a;
}
// ActivityThread.java:
/** Core implementation of activity launch. */
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
...
Activity activity = null;
try {
java.lang.ClassLoader cl = appContext.getClassLoader();
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
...
} catch (Exception e) {
...
}
try {
...
if (activity != null) {
...
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);
...
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
...
}
...
} catch (SuperNotCalledException e) {
throw e;
} catch (Exception e) {
...
}
return activity;
}
// Instrumentation.java:
public Activity newActivity(ClassLoader cl, String className,
Intent intent)
throws InstantiationException, IllegalAccessException,
ClassNotFoundException {
String pkg = intent != null && intent.getComponent() != null
? intent.getComponent().getPackageName() : null;
return getFactory(pkg).instantiateActivity(cl, className, intent);
}
// AppComponentFactory.java:
public @NonNull Activity instantiateActivity(@NonNull ClassLoader cl, @NonNull String className,
@Nullable Intent intent)
throws InstantiationException, IllegalAccessException, ClassNotFoundException {
return (Activity) cl.loadClass(className).newInstance();
}
流程图1,第20-21,Instrumentation.callActivityOnCreate中调用Activity的performCreate。performCreate调用Activity.onCreate!
// Instrumentation.java
public void callActivityOnCreate(Activity activity, Bundle icicle) {
prePerformCreate(activity);
activity.performCreate(icicle);
postPerformCreate(activity);
}
// Activity.java
final void performCreate(Bundle icicle, PersistableBundle persistentState) {
...
if (persistentState != null) {
onCreate(icicle, persistentState);
} else {
onCreate(icicle);
}
...
}
上面流程中最难理解的大概就是第15步了,clientTransaction中添加的LaunchActivityItem是如何被执行的?要理解这一步就需要先了解一下系统与应用之间的通信。
Android进程间通过Binder机制进行通信。AMS(ActivityManagerService)与应用进程之间的通信,Android设计了IApplicationThread与IActivityManager两个接口。
两个通信接口都是单向的:
IApplicationThread是AMS请求应用进程的接口。
IActivityManager是应用进程请求AMS的接口。
public class ActivityManagerService extends IActivityManager.Stub
// ActivityThread的内部类
private class ApplicationThread extends IApplicationThread.Stub
流程图2,第3步,mClient就是IApplicationThread。
private IApplicationThread mClient;
public void schedule() throws RemoteException {
mClient.scheduleTransaction(this);
}
流程图2,第4步,ApplicationThread中scheduleTransaction方法直接调用外部类ActivityThread的scheduleTransaction,但是ActivityThread.java中没有scheduleTransaction方法,而是在父类ClientTransactionHandler。
// ApplicationThread
@Override
public void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
ActivityThread.this.scheduleTransaction(transaction);
}
//ClientTransactionHandler.java
void scheduleTransaction(ClientTransaction transaction) {
transaction.preExecute(this);
sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
}
流程图2,第5步,ClientTransactionHandler中发了一个handler消息EXECUTE_TRANSACTION。这个Handler就是ActivityThread的子类H。在H的handleMessage中可以找到EXECUTE_TRANSACTION的处理。
case EXECUTE_TRANSACTION:
final ClientTransaction transaction = (ClientTransaction) msg.obj;
mTransactionExecutor.execute(transaction);
if (isSystem()) {
transaction.recycle();
}
break;
最终会在TransactionExecutor中取出LaunchActivityItem,执行execute。也是Activity启动流程图中的第15步。
AMS是何时获取到IApplicationThread? App如何获取IActivityManager? 答案就在ActivityThread.main方法中,main中调用了attach方法。
// ActivityThread.java
private void attach(boolean system, long startSeq) {
...
if (!system) {
RuntimeInit.setApplicationObject(mAppThread.asBinder());
final IActivityManager mgr = ActivityManager.getService();
try {
mgr.attachApplication(mAppThread, startSeq);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
} else {
//system
}
...
}
App进程在启动时通过ActivityManager获取单例的IActivityManager,利用IActivityManager的attachApplication接口将IApplicationThread注册到AMS。这样就实现了App与AMS的通信。
刚才提到了ActivityThread的main方法,这是应用进程的入口。在Activity启动流程中,第13步startSpecificActivityLocked,如果App未启动mService.startProcessLocked就会走到ActivityThread.main方法。
接下来看一下App的启动流程,流程图3:
流程图3,第14-15步,startSpecificActivityLocked中判断app未启动进入AMS的startProcessLocked,startProcessLocked经过多次重载调用走到startProcess,startProcess调用Process.start启动进程。
这里注意下,Process.start的第一个参数,在其中一个startProcessLocked方法中赋值为"android.app.ActivityThread",搜索字符串就可以找到!
// ActivityStackSupervisor.java
void startSpecificActivityLocked(ActivityRecord r,
boolean andResume, boolean checkConfig) {
// application is not running
mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
"activity", r.intent.getComponent(), false, false, true);
}
// ActivityManagerService.java
private ProcessStartResult startProcess(String hostingType, String entryPoint,
ProcessRecord app, int uid, int[] gids, int runtimeFlags, int mountExternal,
String seInfo, String requiredAbi, String instructionSet, String invokeWith,
long startTime) {
try {
...
final ProcessStartResult startResult;
if (hostingType.equals("webview_service")) {
// webview process
} else {
startResult = Process.start(entryPoint,
app.processName, uid, uid, gids, runtimeFlags, mountExternal,
app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
app.info.dataDir, invokeWith,
new String[] {PROC_START_SEQ_IDENT + app.startSeq});
}
checkTime(startTime, "startProcess: returned from zygote!");
return startResult;
} finally {
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
}
流程图3,第16步,Process.start中出现了著名的ZygoteProcess! 传说中Android的所有进程起源于Zygote,Process类只是对Zygote的包装而已。
public static final ProcessStartResult start(final String processClass,
final String niceName,
int uid, int gid, int[] gids,
int runtimeFlags, int mountExternal,
int targetSdkVersion,
String seInfo,
String abi,
String instructionSet,
String appDataDir,
String invokeWith,
String[] zygoteArgs) {
return zygoteProcess.start(processClass, niceName, uid, gid, gids,
runtimeFlags, mountExternal, targetSdkVersion, seInfo,
abi, instructionSet, appDataDir, invokeWith, zygoteArgs);
}
流程图3,第17-20步,zygoteProcess.start调用zygoteProcess.startViaZygote。startViaZygote中通过socket与zygote通信,启动app进程,zygoteSendArgsAndGetResult方法返回app进程的pid。
private Process.ProcessStartResult startViaZygote(final String processClass,
final String niceName,
final int uid, final int gid,
final int[] gids,
int runtimeFlags, int mountExternal,
int targetSdkVersion,
String seInfo,
String abi,
String instructionSet,
String appDataDir,
String invokeWith,
boolean startChildZygote,
String[] extraArgs)
throws ZygoteStartFailedEx {
ArrayList argsForZygote = new ArrayList();
// --runtime-args, --setuid=, --setgid=,
// and --setgroups= must go first
argsForZygote.add("--runtime-args");
argsForZygote.add("--setuid=" + uid);
argsForZygote.add("--setgid=" + gid);
argsForZygote.add("--runtime-flags=" + runtimeFlags);
...
synchronized(mLock) {
return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);
}
}
接下来就是需要寻找argsForZygote中的参数在哪里解析,在zygoteSendArgsAndGetResult方法中有这样一段注释:
/**
* See com.android.internal.os.SystemZygoteInit.readArgumentList()
* Presently the wire format to the zygote process is:
* a) a count of arguments (argc, in essence)
* b) a number of newline-separated argument strings equal to count
*
* After the zygote process reads these it will write the pid of
* the child or -1 on failure, followed by boolean to
* indicate whether a wrapper process was used.
*/
然而找不到SystemZygoteInit这个类!
既然argsForZygote中参数是一些hardcode的字符串,那解析的地方应该也是hardcode。所以搜了一下参数。
果然在ZygoteInit.java和ZygoteConnection.java中发现了这些参数。ZygoteInit是zygote进程启动类,main方法中创建了ZygoteServer。由ZygoteServer监听Socket请求,并执行相应的命令。ZygoteServer与客户端的通信协议定义在ZygoteConnection.Arguments中。
流程图3,第21-22步,经过上面一波分析,我们看到ZygoteServer的runSelectLoop方法中,接收到Socket请求后,执行了ZygoteConnection.processOneCommand。
Runnable runSelectLoop(String abiList) {
while (true) {
...
ZygoteConnection connection = peers.get(i);
final Runnable command = connection.processOneCommand(this);
...
}
流程图3,第23-24步,processOneCommand中通过readArgumentList方法读取参数,创建Arguments对象时,在Arguments.parseArgs方法中解析参数。将解析后的参数传入Zygote.forkAndSpecialize创建子进程。
Runnable processOneCommand(ZygoteServer zygoteServer) {
String args[];
Arguments parsedArgs = null;
FileDescriptor[] descriptors;
try {
args = readArgumentList();
descriptors = mSocket.getAncillaryFileDescriptors();
} catch (IOException ex) {
throw new IllegalStateException("IOException on command socket", ex);
}
...
parsedArgs = new Arguments(args);
....
pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
parsedArgs.runtimeFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
parsedArgs.niceName, fdsToClose, fdsToIgnore, parsedArgs.startChildZygote,
parsedArgs.instructionSet, parsedArgs.appDataDir);
....
}
在readArgumentList中看到了一段与zygoteSendArgsAndGetResult方法遥相呼应的注释
/**
* See android.os.Process.zygoteSendArgsAndGetPid()
* Presently the wire format to the zygote process is:
* a) a count of arguments (argc, in essence)
* b) a number of newline-separated argument strings equal to count
*
* After the zygote process reads these it will write the pid of
* the child or -1 on failure.
*/
然而在Process中也找不到zygoteSendArgsAndGetPid。感觉是历史代码的注释,误导啊!
流程图3,第25步,processOneCommand执行完forkAndSpecialize后,在子进程(pid=0)中,执行handleChildProc进行子进程初始化。
Runnable processOneCommand(ZygoteServer zygoteServer) {
...
pid = Zygote.forkAndSpecialize(...);
try {
if (pid == 0) {
// in child
zygoteServer.setForkChild();
zygoteServer.closeServerSocket();
IoUtils.closeQuietly(serverPipeFd);
serverPipeFd = null;
return handleChildProc(parsedArgs, descriptors, childPipeFd,
parsedArgs.startChildZygote);
} else {
// In the parent. A pid < 0 indicates a failure and will be handled in
// handleParentProc.
IoUtils.closeQuietly(childPipeFd);
childPipeFd = null;
handleParentProc(pid, descriptors, serverPipeFd);
return null;
}
} finally {
IoUtils.closeQuietly(childPipeFd);
IoUtils.closeQuietly(serverPipeFd);
}
}
流程图3,第26步,handleChildProc中,invokeWith是socket参数"–invoke-with",在ActivityManagerService的startProcessLocked中赋值,只有在debug的情况下才!null。
isZygote是参数"–start-child-zygote",在ZygoteProcess.start方法中为false。
所以handleChildProc会走到ZygoteInit.zygoteInit。 这里比较奇怪,为什么不是走childZygoteInit,希望有想法的朋友告知一下=。=
private Runnable handleChildProc(Arguments parsedArgs, FileDescriptor[] descriptors,
FileDescriptor pipeFd, boolean isZygote) {
...
if (parsedArgs.invokeWith != null) {
WrapperInit.execApplication(parsedArgs.invokeWith,
parsedArgs.niceName, parsedArgs.targetSdkVersion,
VMRuntime.getCurrentInstructionSet(),
pipeFd, parsedArgs.remainingArgs);
// Should not get here.
throw new IllegalStateException("WrapperInit.execApplication unexpectedly returned");
} else {
if (!isZygote) {
return ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs,
null /* classLoader */);
} else {
return ZygoteInit.childZygoteInit(parsedArgs.targetSdkVersion,
parsedArgs.remainingArgs, null /* classLoader */);
}
}
}
流程图3,第27-28步,zygoteInit中执行RuntimeInit.applicationInit,applicationInit调用findStaticMain,反射ActivityThread.main方法!
public static final Runnable zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) {
if (RuntimeInit.DEBUG) {
Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote");
}
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit");
RuntimeInit.redirectLogStreams();
RuntimeInit.commonInit();
ZygoteInit.nativeZygoteInit();
return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
}
protected static Runnable applicationInit(int targetSdkVersion, String[] argv,
ClassLoader classLoader) {
...
final Arguments args = new Arguments(argv);
...
return findStaticMain(args.startClass, args.startArgs, classLoader);
}
protected static Runnable findStaticMain(String className, String[] argv,
ClassLoader classLoader) {
Class> cl;
try {
cl = Class.forName(className, true, classLoader);
} catch (ClassNotFoundException ex) {
throw new RuntimeException(
"Missing class when invoking static main " + className,
ex);
}
Method m;
try {
m = cl.getMethod("main", new Class[] { String[].class });
} catch (NoSuchMethodException ex) {
throw new RuntimeException(
"Missing static main on " + className, ex);
} catch (SecurityException ex) {
throw new RuntimeException(
"Problem getting static main on " + className, ex);
}
...
return new MethodAndArgsCaller(m, argv);
}
流程图3,第29-33步,回到ActivityThread.main方法中,走到attach中,向AMS注册IApplicationThread,经过多次attachApplicationLocked走到Activity的启动流程,ActivityStackSupervisor的realStartActivityLocked,也就是流程图1的第14步。
// 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(thread, callingPid, callingUid, startSeq);
Binder.restoreCallingIdentity(origId);
}
}
老罗:Android应用程序内部启动Activity过程(startActivity)的源代码分析
Android四大组件之Activity–应用进程与系统进程的通信
ps:
源码阅读过程中,遇得了许多疑惑的地方。一方面是能力有限,需要多参考前辈的文章,另一方面源码也并非完美,代码中也有许多todo存在,也许还能发现一些bug。对于ZygoteProcess.zygoteSendArgsAndGetResult()与ZygoteConnection.readArgumentList中出现的误导注释,给google提了一个issue,就当阅读源码的纪念了。
以上。