启动阶段分析
我们把Activity启动分为4个阶段,
阶段1:用户点击应用图标,由Launcher传入参数,ATMS构建ActivityRecord和Task
阶段2:Pause掉Launcher的Activty
阶段3:Zygote进程创建目标进程,触发ActivityThread的运行
阶段4:ActivityThread主线程绑定AMS,目标Activity的初始化和显示到前台
上面四个阶段还可以细分到不同的进程:Launcher,system_server,zygote,目标进程
总流程图
Luancher启动app入口
Launcher点击app图标后触发点击事件,设置启动目标Activity参数,最后调用Activity的startActivityForResult函数进入Instrumentation
Intrumentation
Intrumentation 对象用来监控应用程序和系统之间的交互操作。由于启动 Activity 是应用程序与系统之间的交互操作,因此调用 Intrumentation 的成员函数 execStartActivity 来代替执行启动 Activity 的操作,以便可以监控这个交互过程
Instrumentation获取系统服务ATMS的startActivity进入system_server进程调用
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
IApplicationThread whoThread = (IApplicationThread) contextThread;
...
try {
intent.migrateExtraStreamToClipData(who);
intent.prepareToLeaveProcess(who);
// ATMS启动Activity
int result = ActivityTaskManager.getService().startActivity(whoThread,
who.getOpPackageName(), who.getAttributionTag(), 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;
}时序图
Launcher的作用
总结一下,Launcher 阶段就干了一件事:准备下一阶段 Activity 启动的参数
SystemServer处理
SystemServer 端主要要完成以下一些工作:
解析与处理请求参数,要启动那个 Activity,怎么启动(flags 等参数),是谁启动等等一些信息
修改窗口容器树,创建新的 ActivityRecord 与 Task 并挂载到窗口容器树中
pause 源 Activity
启动新进程,触发 Application Activity 的初始化和启动生命周期回调
ATMS创建ActivityStarter
ATMS收到请求后,通过ActivityController创建ActivityStarter对象,创建ActivityStarter类时调用了很多set函数,这些参数都会保存到Request类里边,Request 中保存了启动 Activity 需要的所有数据,这些数据主要来自 startActivity 的传入参数
base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
private int startActivityAsUser(IApplicationThread caller, String callingPackage,
@Nullable String callingFeatureId, Intent intent, String resolvedType,
IBinder resultTo, String resultWho, int requestCode, int startFlags,
ProfilerInfo profilerInfo, Bundle bOptions, int userId, boolean validateIncomingUser) {
...
return getActivityStartController().obtainStarter(intent, "startActivityAsUser")
.setCaller(caller)
.setCallingPackage(callingPackage)
.setCallingFeatureId(callingFeatureId)
.setResolvedType(resolvedType)
.setResultTo(resultTo)
.setResultWho(resultWho)
.setRequestCode(requestCode)
.setStartFlags(startFlags)
.setProfilerInfo(profilerInfo)
.setActivityOptions(bOptions)
.setUserId(userId)
.execute();
}
内部的request对象调用
base/services/core/java/com/android/server/wm/ActivityStarter.java
ActivityStarter setRequestCode(int requestCode) {
mRequest.requestCode = requestCode;
return this;
}ActivityStarter-Factory-Request类图
ActivityStarter主要是由Factory创建,相关的类图如下:
ActivityRecord创建
ActivityRecord是Activity在服务端AMS中的描述,保存了所有的activity信息,包括启动模式flag,包名,进程
Activity信息的提取
在execute()函数中关注两点resolveActivity和接下来的executeRequest
int execute() {
...
if (mRequest.activityInfo == null) {
mRequest.resolveActivity(mSupervisor);
}
int res;
synchronized (mService.mGlobalLock) {
...
res = executeRequest(mRequest);
}resolveActivity通过PMS获取目标Activity信息,这些信息是在应用安装时由PMS解析而来,从AndroidManifest.xml提取Activity信息
void resolveActivity(ActivityTaskSupervisor supervisor) {
...
resolveInfo = supervisor.resolveIntent(intent, resolvedType, userId,
0 /* matchFlags */,
computeResolveFilterUid(callingUid, realCallingUid, filterCallingUid));
...
// Collect information about the target of the Intent.
activityInfo = supervisor.resolveActivity(intent, resolveInfo, startFlags,
profilerInfo);
}
其中supervisor的resolveActivity总的来说就是
从 ResolveInfo 中获取到 ActivityInfo,这些信息包括 launchMode,configChanges,screenOrientation
利用 ActivityInfo 中的信息构建一个 ComponentName 对象,然后设置给 Intent。
返回 ActivityInfo
executeRequest
函数很长,主要功能包含
准备一大堆参数,这些参数大多来自最开始的 startActivity 方法参数
各类权限检测
启动过程拦截器 mInterceptor 处理
构建待启动的目标 Activity 对应的 ActivityRecord 对象
接着调用 startActivityUnchecked 方法
private int executeRequest(Request request) {
...
if (err == ActivityManager.START_SUCCESS) {
Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
+ "} from uid " + callingUid);
}
...
final ActivityRecord r = new ActivityRecord.Builder(mService)
.setCaller(callerApp)
.setLaunchedFromPid(callingPid)
.setLaunchedFromUid(callingUid)
.setLaunchedFromPackage(callingPackage)
.setLaunchedFromFeature(callingFeatureId)
.setIntent(intent)
.setResolvedType(resolvedType)
.setActivityInfo(aInfo)
.setConfiguration(mService.getGlobalConfiguration())
.setResultTo(resultRecord)
.setResultWho(resultWho)
.setRequestCode(requestCode)
.setComponentSpecified(request.componentSpecified)
.setRootVoiceInteraction(voiceSession != null)
.setActivityOptions(checkedOptions)
.setSourceRecord(sourceRecord)
.build();
mLastStartActivityRecord = r;
...
mLastStartActivityResult = startActivityUnchecked(r, sourceRecord, voiceSession,
request.voiceInteractor, startFlags, true /* doResume */, checkedOptions,
inTask, inTaskFragment, restrictedBgActivity, intentGrants);
if (request.outActivity != null) {
request.outActivity[0] = mLastStartActivityRecord;
}
return mLastStartActivityResult;
}函数首先有一条日志,这就是我们查看Activity启动日志我们经常会看到的log
ActivityRecord构造方法
ActivityRecord的初始化是由ActivityRecord.Builder完成的,在其构造函数中我们需要关注token
base/services/core/java/com/android/server/wm/ActivityRecord.java
private ActivityRecord(ActivityTaskManagerService _service, WindowProcessController _caller,
int _launchedFromPid, int _launchedFromUid, String _launchedFromPackage,
@Nullable String _launchedFromFeature, Intent _intent, String _resolvedType,
ActivityInfo aInfo, Configuration _configuration, ActivityRecord _resultTo,
String _resultWho, int _reqCode, boolean _componentSpecified,
boolean _rootVoiceInteraction, ActivityTaskSupervisor supervisor,
ActivityOptions options, ActivityRecord sourceRecord, PersistableBundle persistentState,
TaskDescription _taskDescription, long _createTime) {
super(_service.mWindowManager, new Token(), TYPE_APPLICATION, true,
null /* displayContent */, false /* ownerCanManageAppTokens */);
mAtmService = _service;
((Token) token).mActivityRef = new WeakReference<>(this);
...
}
Token
token是一个Binder对象,在super调用的时候创建,其持有ActivityRecord本身的引用
身份标识:每个 Activity 启动时, 都会为其创建一个 ActivityRecord 实体,并生成一个唯一的 IBinder 对象作为其 Token。Activity启动后会持有这个Token的binder代理对象
其中的super函数如下
base/services/core/java/com/android/server/wm/WindowToken.java
protected WindowToken(WindowManagerService service, IBinder _token, int type,
boolean persistOnEmpty, DisplayContent dc, boolean ownerCanManageAppTokens,
boolean roundedCornerOverlay, boolean fromClientToken, @Nullable Bundle options) {
super(service);
token = _token;
windowType = type;
mOptions = options;
mPersistOnEmpty = persistOnEmpty;
mOwnerCanManageAppTokens = ownerCanManageAppTokens;
mRoundedCornerOverlay = roundedCornerOverlay;
mFromClientToken = fromClientToken;
// dc 始终为null,跳过
if (dc != null) {
dc.addWindowToken(token, this);
}
}从上边看到,这里的token是不会调用addWindowToken添加到窗口层级中去的
从ATMS收到启动消息到创建ActivityRecord的时序图
Task的创建
Task创建时序图
尝试创建Task
在ActivityStarter中创建好ActivityRecord之后,在startActivityUnchecked函数中调用startActivityInner
在startActivityInner中调用getOrCreateRootTask试图创建rootTask
为什么要尝试?因为可能复用
int startActivityInner(final ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
int startFlags, boolean doResume, ActivityOptions options, Task inTask,
TaskFragment inTaskFragment, boolean restrictedBgActivity,
NeededUriGrants intentGrants) {
...
if (mTargetRootTask == null) {
mTargetRootTask = getOrCreateRootTask(mStartActivity, mLaunchFlags, targetTask,
mOptions);
}
if (newTask) {
final Task taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
? mSourceRecord.getTask() : null;
// 将ActivityRecord和Task绑定
setNewTask(taskToAffiliate);
} else if (mAddingToTask) {
addOrReparentStartingActivity(targetTask, "adding to task");
}
...
}最终进入TaskDisplayArea的getOrCreateRootTask函数创建Task
base/services/core/java/com/android/server/wm/TaskDisplayArea.java
Task getOrCreateRootTask(int windowingMode, int activityType, boolean onTop,
@Nullable Task candidateTask, @Nullable Task sourceTask,
@Nullable ActivityOptions options, int launchFlags) {
...
if(...)
return candidateTask.getRootTask();
}
...
return new Task.Builder(mAtmService)
.setWindowingMode(windowingMode)
.setActivityType(activityType)
.setOnTop(onTop)
.setParent(this)
.setSourceTask(sourceTask)
.setActivityOptions(options)
.setLaunchFlags(launchFlags)
.build();
}Task复用条件判断
如果需要创建一个Task则走最后的new 实例化,在此之前会判断是否需要复用Task, 根据启动模式,比如在应用内以复用栈的模式启动另一个Activity就会走上边的candidateTask.getRootTask()
ActivityRecord挂载时序图
先看看整个挂载的时序图,在ActivityStarter中此流程是紧接着Task创建完成之后开始的
将ActivityRecord添加到Task
private void setNewTask(Task taskToAffiliate) {
final boolean toTop = !mLaunchTaskBehind && !mAvoidMoveToFront;
final Task task = mTargetRootTask.reuseOrCreateTask(
mNewTaskInfo != null ? mNewTaskInfo : mStartActivity.info,
mNewTaskIntent != null ? mNewTaskIntent : mIntent, mVoiceSession,
mVoiceInteractor, toTop, mStartActivity, mSourceRecord, mOptions);
task.mTransitionController.collectExistenceChange(task);
addOrReparentStartingActivity(task, "setTaskFromReuseOrCreateNewTask");
ProtoLog.v(WM_DEBUG_TASKS, "Starting new activity %s in new task %s",
mStartActivity, mStartActivity.getTask());
if (taskToAffiliate != null) {
mStartActivity.setTaskToAffiliateWith(taskToAffiliate);
}
}这里有条log Starting new activity 分析系统日志经常会看到
重点看下addOrReparentStartingActivity
private void addOrReparentStartingActivity(@NonNull Task task, String reason) {
TaskFragment newParent = task;
...
if (mStartActivity.getTaskFragment() == null
|| mStartActivity.getTaskFragment() == newParent) {
newParent.addChild(mStartActivity, POSITION_TOP);
} else {
mStartActivity.reparent(newParent, newParent.getChildCount() /* top */, reason);
}
}mStartActivity是上面创建的ActivityRecord, 调用 newParent.addChild添加ActivityRecord到Task里边
Move task
将Task移动到容器DefaultTaskDisplayArea顶部,Task就是为目标Activity创建的Task, Task的父容器是DefaultTaskDisplayArea,如果需要深入了解,此处需要理解WMS/AMS的窗口层级结构
//base/services/core/java/com/android/server/wm/ActivityStarter.java
//startActivityInner
if (!mAvoidMoveToFront && mDoResume) {
//targetTask 为null
mTargetRootTask.getRootTask().moveToFront("reuseOrNewTask", targetTask);
}
//base/services/core/java/com/android/server/wm/Task.java
//实现函数
void moveToFrontInner(String reason, Task task) {
if (!isAttached()) {
return;
}
final TaskDisplayArea taskDisplayArea = getDisplayArea();
if (!isActivityTypeHome() && returnsToHomeRootTask()) {
// Make sure the root home task is behind this root task since that is where we
// should return to when this root task is no longer visible.
taskDisplayArea.moveHomeRootTaskToFront(reason + " returnToHome");
}
final Task lastFocusedTask = isRootTask() ? taskDisplayArea.getFocusedRootTask() : null;
//true
if (task == null) {
task = this;
}
task.getParent().positionChildAt(POSITION_TOP, task, true /* includingParents */);
taskDisplayArea.updateLastFocusedRootTask(lastFocusedTask, reason);
}上面的getParent 就是 DefaultTaskDisplayArea ,将当前的 Task 移动到 DefaultTaskDisplayArea 的最前面
命令行查看窗口挂载层级
adb shell dumpsys window displays
Task display areas in top down Z order:
TaskDisplayArea DefaultTaskDisplayArea
overrideConfig={0.0 ?mcc0mnc ?localeList ?layoutDir ?swdp ?wdp ?hdp ?density ?lsize ?long ?ldr ?wideColorGamut ?orien ?uimode ?night ?touch ?keyb/?/? ?nav/? winConfig={ mBounds=Rect(0, 0 - 0, 0) mAppBounds=null mMaxBounds=Rect(0, 0 - 0, 0) mDisplayRotation=undefined mWindowingMode=fullscreen mActivityType=undefined mAlwaysOnTop=undefined mRotation=undefined} ?fontWeightAdjustment}
mPreferredTopFocusableRootTask=Task{c83b3a2 #32 type=standard A=10211:com.example.androiddemo}
mLastFocusedRootTask=Task{c83b3a2 #32 type=standard A=10211:com.example.androiddemo}
Application tokens in top down Z order:
//Begin 新增的Demo Activity
* Task{c83b3a2 #32 type=standard A=10211:com.example.androiddemo U=0 visible=true visibleRequested=true mode=fullscreen translucent=false sz=1}
bounds=[0,0][1080,2400]
* ActivityRecord{241515373 u0 com.example.androiddemo/.MainActivity t32}
//End
* Task{47cfc2e #1 type=home U=0 visible=false visibleRequested=false mode=fullscreen translucent=true sz=1}
bounds=[0,0][1080,2400]
* Task{bef315c #5 type=home I=com.google.android.apps.nexuslauncher/.NexusLauncherActivity U=0 rootTaskId=1 visible=false visibleRequested=false mode=fullscreen translucent=true sz=2}
bounds=[0,0][1080,2400]
* ActivityRecord{72491568 u0 com.google.android.apps.nexuslauncher/.NexusLauncherActivity t5}
* TaskFragment{afb81ba mode=multi-window organizerUid=10176 organizerProc=com.google.android.apps.nexuslauncher}
bounds=[0,0][1080,2400]
* Task{2a2e03b #2 type=undefined U=0 visible=false visibleRequested=false mode=fullscreen translucent=true sz=2}
bounds=[0,0][1080,2400]
* Task{ee38cb1 #4 type=undefined U=0 rootTaskId=2 visible=false visibleRequested=false mode=multi-window translucent=true sz=0}
bounds=[0,2400][1080,3600]
* Task{3ce20e9 #3 type=undefined U=0 rootTaskId=2 visible=false visibleRequested=false mode=multi-window translucent=true sz=0}
bounds=[0,0][1080,2400]
显示Activity
当Task创建完成,并且处理好窗口层级之后,就要开始准备显示Activity了
resume时序图
resume入口
startActivityInner调用mRootWindowContainer.resumeFocusedTasksTopActivities进入resume流程,这里的resume不是Activity的Resume生命周期,而是启动Activity,这里的执行时机是发生在system_server进程,而onResume生命周期这个流程是在应用进程里边。
base/services/core/java/com/android/server/wm/ActivityStarter.java
int startActivityInner(final ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
int startFlags, boolean doResume, ActivityOptions options, Task inTask,
TaskFragment inTaskFragment, boolean restrictedBgActivity,
NeededUriGrants intentGrants) {
// 调整Task层级
if (!mAvoidMoveToFront && mDoResume) {
//targetTask 为null
mTargetRootTask.getRootTask().moveToFront("reuseOrNewTask", targetTask);
}
...
if (mDoResume) {
//启动Activity
mRootWindowContainer.resumeFocusedTasksTopActivities(
mTargetRootTask, mStartActivity, mOptions, mTransientLaunch);
}
}RootWindowContainer调用链
从resumeFocusedTasksTopActivities开始的关键调用函数如下
RootWindowContainer::resumeFocusedTasksTopActivities
Task::resumeTopActivityUncheckedLocked
Task::resumeTopActivityInnerLocked
TaskFragment::resumeTopActivity
TaskDisplayArea::pauseBackTasks -- pause LauncherActivity
WindowContainer::forAllLeafTask
TaskFragment::forAllLeafTaskFragments
TaskFragment::startPausing
TaskFragment::startPausing
TaskFragment::schedulePauseActivity --构建 PauseActivityItem,触发onPause生命周期
ActivityTaskManagerService::startProcessAsync -- 创建进程
从上面的时序图走进TaskFragment中,首先发起对上一个Activity的pause流程
base/services/core/java/com/android/server/wm/TaskFragment.java
final boolean resumeTopActivity(ActivityRecord prev, ActivityOptions options,
boolean deferPause) {
...
//暂停Launcher的Activity
boolean pausing = !deferPause && taskDisplayArea.pauseBackTasks(next);
if (pausing) {
...
//启动新进程
mAtmService.startProcessAsync(next, false /* knownToBeDead */, isTop,
isTop ? HostingRecord.HOSTING_TYPE_NEXT_TOP_ACTIVITY
: HostingRecord.HOSTING_TYPE_NEXT_ACTIVITY);
}
return true
}
}这里有两个重点:
暂停上一个Activity
启动新进程
到这里,我们的启动流程就因为上面两个点而无法启动,等上面两个流程走完后再次尝试启动。
小结
代码走到这里,已经创建了 TargetActivity 所在的 Task 和对应的 ActivityRecord ,并也挂载到 DefaultTaskDisplayArea 下了,而且还将Task移到了顶部,所以得到上面主要的一个关系。 但是这个时候用户还是只能看到 Launcher 的 Activity 。这是因为 TargetActivity 都还没启动,甚至连它的进程都没创建。
要让 TargetActivity 启动起来,所以触发了 RootWindowContainer#resumeFocusedTasksTopActivities 方法,但是在执行到 TaskFragment#resumeTopActivity 方法的时候发现想显示 TargetActivity 的条件2个都没满足,所以就需要触发 Launcher 的pause 和 TargetActivity 所在进程的创建
主要的工作如下:
在 Launcher 进程构建了启动参数放在了 ActivityOption 中,然后通过 Bundle 传递给 system_server 端
ATMS 先解析参数,放在了 Request 这个类中保存
ATMS 构建出一个 ActivityRecord ,这个类在 system_server 端就代表着 Activity ,同时也是一个窗口容器
再构建出一个 Task 挂载到窗口树上
将 ActivityRecord 挂载到 Task 中,这样 ActivityRecord 也就挂载到窗口层级树中了
触发 Launcher 执行 pause 逻辑
触发 TargetActivity 所在的进程创建
不管是pause Launcher的Activity还是创建进程,都要转移到其他进程,所以接下来进入到阶段二和阶段三,两个并行的任务执行
pause Activity
跨进程调用到app进程执行onPause
进入第二阶段,首先看看pause activity的触发流程
在RootWindowContainer::resumeFocusedTasksTopActivities函数的调用链中
TaskDisplayArea::pauseBackTasks -- pause LauncherActivity
WindowContainer::forAllLeafTask
TaskFragment::forAllLeafTaskFragments
TaskFragment::startPausing
TaskFragment::startPausing
TaskFragment::schedulePauseActivity --构建 PauseActivityItem,触发onPause生命周期我们留意最后一行schedulePauseActivity,函数实现如下
void schedulePauseActivity(ActivityRecord prev, boolean userLeaving,
boolean pauseImmediately, String reason) {
ProtoLog.v(WM_DEBUG_STATES, "Enqueueing pending pause: %s", prev);
...
mAtmService.getLifecycleManager().scheduleTransaction(prev.app.getThread(),
prev.token, PauseActivityItem.obtain(prev.finishing, userLeaving,
prev.configChangeFlags, pauseImmediately));
...
}scheduleTransaction函数的主要作用是发起一个Transaction,注意传入的参数是PauseActivityItem对象, 所以接下来会走到PauseActivityItem的execute函数,当走到execute时就已经完成跨进程调用了,接下来都是在Launcher进程执行了
public class PauseActivityItem extends ActivityLifecycleItem {
...
@Override
public void execute(ClientTransactionHandler client, ActivityClientRecord r,
PendingTransactionActions pendingActions) {
Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
// ActivityThread实现
client.handlePauseActivity(r, mFinished, mUserLeaving, mConfigChanges, pendingActions,
"PAUSE_ACTIVITY_ITEM");
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
@Override
public void postExecute(ClientTransactionHandler client, IBinder token,
PendingTransactionActions pendingActions) {
if (mDontReport) {
return;
}
ActivityClient.getInstance().activityPaused(token);
}
}client对象的实现类是ActivityThread,其重写了handlePauseActivity函数
Transaction详细流程参考 Android Activity Transaction
onPause结束
当onPause流程走完之后,回到PauseActivityItem :: postExecute函数,会通知ATMS pause结束,然后尝试显示新Activity
public void activityPaused(IBinder token) {
try {
getActivityClientController().activityPaused(token);
} catch (RemoteException e) {
e.rethrowFromSystemServer();
}
}ActivityClientController调用链[2]如下
ActivityClientController::activityPaused
ActivityRecord::activityPaused
TaskFragment::completePause
RootWindowContainer::resumeFocusedTasksTopActivities -- 显示顶层Activity
RootWindowContainer::resumeFocusedTasksTopActivities
Task::resumeTopActivityUncheckedLocked
Task::resumeTopActivityInnerLocked
TaskFragment::resumeTopActivity
ActivityTaskSupervisor::startSpecificActivity -- 试图启动 Activity
completePause
上一个activity pause之后,再次尝试显示Activity,TaskFragment::completePause 有两个重要的调用函数:前面出现过的resumeFocusedTasksTopActivities和ensureActivitiesVisible
void completePause(boolean resumeNext, ActivityRecord resuming) {
...
if (resumeNext) {
// 尝试启动ACtivity
mRootWindowContainer.resumeFocusedTasksTopActivities(topRootTask, prev,
null /* targetOptions */);
}
// 确保activity可见
mRootWindowContainer.ensureActivitiesVisible(resuming, 0, !PRESERVE_WINDOWS);
}
在complete函数中调用了 resumeFocusedTasksTopActivities, 上边 显示Activity-resume入口小节中提到,在startActivityInner函数把Task层级调整到最顶层之后,准备显示activity就调用了这个函数,同一个调用链,直到resumeTopActivity,再看看resumeTopActivity的实现逻辑
final boolean resumeTopActivity(ActivityRecord prev, ActivityOptions options,
boolean deferPause) {
// 此时activity已经puase completed了,所以这里不会被拦截
// If we are currently pausing an activity, then don't do anything until that is done.
final boolean allPausedComplete = mRootWindowContainer.allPausedActivitiesComplete();
if (!allPausedComplete) {
ProtoLog.v(WM_DEBUG_STATES,
"resumeTopActivity: Skip resume: some activity pausing.");
return false;
}
// 这里同上,尝试pause上一个activity,但是我们已经pause completed了,所以为false
boolean pausing = !deferPause && taskDisplayArea.pauseBackTasks(next);
if (pausing) {
// 启动进程,resume的时候走过一次,这里不会走了
...
}
// 进程还没启动
if (next.attachedToProcess()) {
} else {
// 启动Activity
ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivity: Restarting %s", next);
mTaskSupervisor.startSpecificActivity(next, true, true);
}
return true;
}
尝试启动activity
函数很简单,两个功能,要么启动activity,要么启动进程
base/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
void startSpecificActivity(ActivityRecord r, boolean andResume, boolean checkConfig) {
// Is this activity's application already running?
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;
}
}
// 进程未启动则启动进程
final boolean isTop = andResume && r.isTopRunningActivity();
mService.startProcessAsync(r, knownToBeDead, isTop,
isTop ? HostingRecord.HOSTING_TYPE_TOP_ACTIVITY
: HostingRecord.HOSTING_TYPE_ACTIVITY);
}进程启动判断条件
这里首先判断了进程是否启动,如果进程启动非常快,此时就会直接调用realStartActivityLocked启动Activity
resumeTopActivity里边也有一个判断进程是否启动,但是这里有个不同点
startSpecificActivity:通过mService.getProcessController获取到进程WindowProcessController对象,这个接口可以认为是实时获取
resumeTopActivity:attachedToProcess里边也是用的WindowProcessController对象,代码如下
boolean hasProcess() {
return app != null;
}
boolean attachedToProcess() {
return hasProcess() && app.hasThread();
}这里的app在setProcess函数里边初始化,而setProcess函数又是在realStartActivityLocked里边调用,所以resumeTopActivity如果activity没有启动,那么那里判断进程是否启动是肯定为false,而在ActivityTaskSupervisor::startSpecificActivity是很可能为true的
ensureActivitiesVisible流程
在completePause函数中的第二个关键函数调用 RootWindowContainer::ensureActivitiesVisible
调用链[2]
RootWindowContainer::ensureActivitiesVisible -- 确保设备上 Activity 的可见性
RootWindowContainer::ensureActivitiesVisible
DisplayContent::ensureActivitiesVisible
WindowContainer::forAllRootTasks --忽略固定逻辑
Task::ensureActivitiesVisible
Task::forAllLeafTasks --忽略固定逻辑
TaskFragment::updateActivityVisibilities
EnsureActivitiesVisibleHelper::process
EnsureActivitiesVisibleHelper::setActivityVisibilityState
EnsureActivitiesVisibleHelper::makeVisibleAndRestartIfNeeded
ActivityTaskSupervisor::startSpecificActivity -- 试图启动 ActivityensureActivitiesVisible 流程。这个流程执行的概率很高,界面有个风吹草动可能影响 Activity 显示的都会执行这个方法,这个方法的目的就是确保当前设备上的 Activity 正确显示。 比如当前这个场景,一个 Activity 完成了 completePause ,那肯定要有新的 Activity 显示,那整个手机系统的 Activity 规则肯定发生了改变,所以需要执行 ensureActivitiesVisible 流程来确保正确的显示。[2]
遍历所有屏幕
base/services/core/java/com/android/server/wm/RootWindowContainer.java
void ensureActivitiesVisible(ActivityRecord starting, int configChanges,
boolean preserveWindows, boolean notifyClients) {
try {
mTaskSupervisor.beginActivityVisibilityUpdate();
// First the front root tasks. In case any are not fullscreen and are in front of home.
// 遍历屏幕
for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
final DisplayContent display = getChildAt(displayNdx);
display.ensureActivitiesVisible(starting, configChanges, preserveWindows,
notifyClients);
}
} finally {
mTaskSupervisor.endActivityVisibilityUpdate();
}
}遍历所有的RootTask
base/services/core/java/com/android/server/wm/DisplayContent.java
void ensureActivitiesVisible(ActivityRecord starting, int configChanges,
boolean preserveWindows, boolean notifyClients) {
...
forAllRootTasks(rootTask -> {
rootTask.ensureActivitiesVisible(starting, configChanges, preserveWindows,
notifyClients);
});
...
}遍历所有子叶
void ensureActivitiesVisible(@Nullable ActivityRecord starting, int configChanges,
boolean preserveWindows, boolean notifyClients) {
...
forAllLeafTasks(task -> {
task.updateActivityVisibilities(starting, configChanges, preserveWindows,
notifyClients);
}, true /* traverseTopToBottom */);
...
}调用了一个EnsureActivitiesVisibleHelper::process函数来处理可见性
final void updateActivityVisibilities(@Nullable ActivityRecord starting, int configChanges,
boolean preserveWindows, boolean notifyClients) {
mTaskSupervisor.beginActivityVisibilityUpdate();
try {
mEnsureActivitiesVisibleHelper.process(
starting, configChanges, preserveWindows, notifyClients);
} finally {
mTaskSupervisor.endActivityVisibilityUpdate();
}
}EnsureActivitiesVisibleHelper::process
process函数中遍历了所有children,如果child是TaskFragment则会进入递归调用,这里用了asTaskFragment和asActivityRecord是否返回null来对容器WindowContainer做了具体的类型判断
void process(@Nullable ActivityRecord starting, int configChanges, boolean preserveWindows,
boolean notifyClients) {
reset(starting, configChanges, preserveWindows, notifyClients);
...
ArrayList<TaskFragment> adjacentTaskFragments = null;
for (int i = mTaskFragment.mChildren.size() - 1; i >= 0; --i) {
final WindowContainer child = mTaskFragment.mChildren.get(i);
// 类型判断 TaskFragment
final TaskFragment childTaskFragment = child.asTaskFragment();
if (childTaskFragment != null
&& childTaskFragment.getTopNonFinishingActivity() != null) {
// 这是一个递归调用,马上又会进入process函数
childTaskFragment.updateActivityVisibilities(starting, configChanges,
preserveWindows, notifyClients);
...
} else if (child.asActivityRecord() != null) {
// 类型为ActivityRecord
setActivityVisibilityState(child.asActivityRecord(), starting, resumeTopActivity);
}
}
}处理ActivityRecord可见性
对于ActivityRecord,也就是对应的Activity的可见性,其可见性的具体设置就是由setActivityVisibilityState函数负责
private void setActivityVisibilityState(ActivityRecord r, ActivityRecord starting,
final boolean resumeTopActivity) {
final boolean reallyVisible = r.shouldBeVisibleUnchecked();
if (reallyVisible) {
// 进程未启动,启动activity
if (!r.attachedToProcess()) {
makeVisibleAndRestartIfNeeded(mStarting, mConfigChanges, isTop,
resumeTopActivity && isTop, r);
} else if (r.mVisibleRequested) {
} else {
r.makeVisibleIfNeeded(mStarting, mNotifyClients);
}
} else {
// 不可见
r.makeInvisible();
}
}尝试启动Activity
可以看到,可见性控制函数都是实现在ActivityRecord类里边,如果进程未启动,则尝试启动Activity
makeVisibleAndRestartIfNeeded如下:
private void makeVisibleAndRestartIfNeeded(ActivityRecord starting, int configChanges,
boolean isTop, boolean andResume, ActivityRecord r) {
...
if (!r.mVisibleRequested || r.mLaunchTaskBehind) {
// 设置为可见
r.setVisibility(true);
}
if (r != starting) {
mTaskFragment.mTaskSupervisor.startSpecificActivity(r, andResume,
true /* checkConfig */);
}
}启动activity有一个条件 r!=starting, 这个starting是在调用栈最顶部的completePause函数传递进来的是一个null值,所以在当前逻辑下肯定为true.
pause activity整个流程就结束了,后续仍然是判断进程是否启动,然后判断是继续启动activity还是启动进程
触发进程创建
第一阶段末尾,触发了两个平行的进程,首先pause activity, 然后接着启动进程,pause activity已经分析完了,并且我们已经分析到了pause activity完全结束
现在进入第三阶段
这里只分析如何触发进程创建的以及跨进程通信方式,进程的真正创建是在Linux中通过fork出来的
ATMS发送进程启动消息
我看看到多次尝试启动进程的函数如下
base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
void startProcessAsync(ActivityRecord activity, boolean knownToBeDead, boolean isTop,
String hostingType) {
// Post message to start process to avoid possible deadlock of calling into AMS with the
// ATMS lock held.
final Message m = PooledLambda.obtainMessage(ActivityManagerInternal::startProcess,
mAmInternal, activity.processName, activity.info.applicationInfo, knownToBeDead,
isTop, hostingType, activity.intent.getComponent());
mH.sendMessage(m);
}这里发了一个消息给Handler去执行,真正的执行函数是ActivityManagerInternal::startProcess,后面的参数都是这个函数需要的参数,真正的实现函数是ActivityManagerService$LocalService::startProcess
base/services/core/java/com/android/server/am/ActivityManagerService.java
@Override
public void startProcess(String processName, ApplicationInfo info, boolean knownToBeDead,
boolean isTop, String hostingType, ComponentName hostingName) {
...
synchronized (ActivityManagerService.this) {
startProcessLocked(processName, info, knownToBeDead, 0 /* intentFlags */,
new HostingRecord(hostingType, hostingName, isTop),
ZYGOTE_POLICY_FLAG_LATENCY_SENSITIVE, false /* allowWhileBooting */,
false /* isolated */);
}
...
}
final ProcessRecord startProcessLocked(String processName,
ApplicationInfo info, boolean knownToBeDead, int intentFlags,
HostingRecord hostingRecord, int zygotePolicyFlags, boolean allowWhileBooting,
boolean isolated) {
return mProcessList.startProcessLocked(processName, info, knownToBeDead, intentFlags,
hostingRecord, zygotePolicyFlags, allowWhileBooting, isolated, 0 /* isolatedUid */,
false /* isSdkSandbox */, 0 /* sdkSandboxClientAppUid */,
null /* sdkSandboxClientAppPackage */,
null /* ABI override */, null /* entryPoint */,
null /* entryPointArgs */, null /* crashHandler */);
}
ProcessList::startProcessLocked
在ProcessList对象中经过5次startProcessLocked函数的重载调用,略过多次重载调用
boolean startProcessLocked(HostingRecord hostingRecord, String entryPoint, ProcessRecord app,
int uid, int[] gids, int runtimeFlags, int zygotePolicyFlags, int mountExternal,
String seInfo, String requiredAbi, String instructionSet, String invokeWith,
long startUptime, long startElapsedTime) {
app.setPendingStart(true);
app.setRemoved(false);
if (mService.mConstants.FLAG_PROCESS_START_ASYNC) {
if (DEBUG_PROCESSES) Slog.i(TAG_PROCESSES,
"Posting procStart msg for " + app.toShortString());
mService.mProcStartHandler.post(() -> handleProcessStart(
app, entryPoint, gids, runtimeFlags, zygotePolicyFlags, mountExternal,
requiredAbi, instructionSet, invokeWith, startSeq));
return true;
}
...
}从源码来看FLAG_PROCESS_START_ASYNC始终为true,接下来通过AMS的handler post了一个runnable对象,真正的实现在函数 handleProcessStart里边
handleProcessStart
private void handleProcessStart(final ProcessRecord app, final String entryPoint,
final int[] gids, final int runtimeFlags, int zygotePolicyFlags,
final int mountExternal, final String requiredAbi, final String instructionSet,
final String invokeWith, final long startSeq) {
final Runnable startRunnable = () -> {
final Process.ProcessStartResult startResult = startProcess(app.getHostingRecord(),
entryPoint, app, app.getStartUid(), gids, runtimeFlags, zygotePolicyFlags,
mountExternal, app.getSeInfo(), requiredAbi, instructionSet, invokeWith,
app.getStartTime());
synchronized (mService) {
handleProcessStartedLocked(app, startResult, startSeq);
}
...
}在startProcess函数中对要启动的进程做了一个分类,最后都调用了Process::start来启动进程
private Process.ProcessStartResult startProcess(HostingRecord hostingRecord, String entryPoint,
ProcessRecord app, int uid, int[] gids, int runtimeFlags, int zygotePolicyFlags,
int mountExternal, String seInfo, String requiredAbi, String instructionSet,
String invokeWith, long startTime) {
...
if (hostingRecord.usesWebviewZygote()) {
startResult = startWebView(entryPoint,
app.processName, uid, uid, gids, runtimeFlags, mountExternal,
app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
app.info.dataDir, null, app.info.packageName,
app.getDisabledCompatChanges(),
new String[]{PROC_START_SEQ_IDENT + app.getStartSeq()});
} else if (hostingRecord.usesAppZygote()) {
final AppZygote appZygote = createAppZygoteForProcessIfNeeded(app);
// We can't isolate app data and storage data as parent zygote already did that.
startResult = appZygote.getProcess().start(entryPoint,
app.processName, uid, uid, gids, runtimeFlags, mountExternal,
app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
app.info.dataDir, null, app.info.packageName,
/*zygotePolicyFlags=*/ ZYGOTE_POLICY_FLAG_EMPTY, isTopApp,
app.getDisabledCompatChanges(), pkgDataInfoMap, allowlistedAppDataInfoMap,
false, false,
new String[]{PROC_START_SEQ_IDENT + app.getStartSeq()});
} else {
regularZygote = true;
startResult = Process.start(entryPoint,
app.processName, uid, uid, gids, runtimeFlags, mountExternal,
app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
app.info.dataDir, invokeWith, app.info.packageName, zygotePolicyFlags,
isTopApp, app.getDisabledCompatChanges(), pkgDataInfoMap,
allowlistedAppDataInfoMap, bindMountAppsData, bindMountAppStorageDirs,
new String[]{PROC_START_SEQ_IDENT + app.getStartSeq()});
}
...
}Process::start
这里只有一个函数调用startViaZygote
public final Process.ProcessStartResult start(@NonNull final String processClass, ...) {
return startViaZygote(processClass, niceName, uid, gid, gids,
runtimeFlags, mountExternal, targetSdkVersion, seInfo,
abi, instructionSet, appDataDir, invokeWith, /*startChildZygote=*/ false,
packageName, zygotePolicyFlags, isTopApp, disabledCompatChanges,
pkgDataInfoMap, allowlistedDataInfoList, bindMountAppsData,
bindMountAppStorageDirs, zygoteArgs);
}Process::startViaZygote
继续看startViaZygote
private Process.ProcessStartResult startViaZygote(@NonNull final String processClass,
@Nullable final String niceName,
final int uid, final int gid,
@Nullable final int[] gids,
int runtimeFlags, int mountExternal,
int targetSdkVersion,
@Nullable String seInfo,
@NonNull String abi,
@Nullable String instructionSet,
@Nullable String appDataDir,
@Nullable String invokeWith,
boolean startChildZygote,
@Nullable String packageName,
int zygotePolicyFlags,
boolean isTopApp,
@Nullable long[] disabledCompatChanges,
@Nullable Map<String, Pair<String, Long>>
pkgDataInfoMap,
@Nullable Map<String, Pair<String, Long>>
allowlistedDataInfoList,
boolean bindMountAppsData,
boolean bindMountAppStorageDirs,
@Nullable String[] extraArgs)
throws ZygoteStartFailedEx {
ArrayList<String> 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);
...
// 将所有的参数都添加到argsForZygote 里边
...
argsForZygote.add(processClass);
if (extraArgs != null) {
Collections.addAll(argsForZygote, extraArgs);
}
synchronized(mLock) {
// The USAP pool can not be used if the application will not use the systems graphics
// driver. If that driver is requested use the Zygote application start path.
return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi),
zygotePolicyFlags,
argsForZygote);
}
}将所有的进程参数都封装到ArrayList,然后通过zygoteSendArgsAndGetResult发送给Zygote进程
Process::startViaZygote
Process::zygoteSendArgsAndGetResult
Process::attemptZygoteSendArgsAndGetResultSocket通信
我们直接关注 attemptZygoteSendArgsAndGetResult函数,这里就是AMS和Zygote进程通信的IPC代码
private Process.ProcessStartResult attemptZygoteSendArgsAndGetResult(
ZygoteState zygoteState, String msgStr) throws ZygoteStartFailedEx {
try {
final BufferedWriter zygoteWriter = zygoteState.mZygoteOutputWriter;
final DataInputStream zygoteInputStream = zygoteState.mZygoteInputStream;
zygoteWriter.write(msgStr);
zygoteWriter.flush();
// Always read the entire result from the input stream to avoid leaving
// bytes in the stream for future process starts to accidentally stumble
// upon.
Process.ProcessStartResult result = new Process.ProcessStartResult();
result.pid = zygoteInputStream.readInt();
result.usingWrapper = zygoteInputStream.readBoolean();
if (result.pid < 0) {
throw new ZygoteStartFailedEx("fork() failed");
}
return result;
} catch (IOException ex) {
zygoteState.close();
Log.e(LOG_TAG, "IO Exception while communicating with Zygote - "
+ ex.toString());
throw new ZygoteStartFailedEx(ex);
}
}将应用进程的启动参数argsForZygote写入ZygoteState中,这样Zygote进程就会收到一个创建新的应用程序进程的请求
ZygoteState是怎么来的呢,回到上边的startViaZygote函数,最后调用了openZygoteSocketIfNeeded函数
return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi),
zygotePolicyFlags,
argsForZygote);Socket连接的建立
openZygoteSocketIfNeeded函数创建了socket连接
private ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx {
attemptConnectionToPrimaryZygote();
if (primaryZygoteState.matches(abi)) {
return primaryZygoteState;
}
...
}
private void attemptConnectionToPrimaryZygote() throws IOException {
if (primaryZygoteState == null || primaryZygoteState.isClosed()) {
primaryZygoteState =
ZygoteState.connect(mZygoteSocketAddress, mUsapPoolSocketAddress);
maybeSetApiDenylistExemptions(primaryZygoteState, false);
maybeSetHiddenApiAccessLogSampleRate(primaryZygoteState);
}
}这里的Socket通信最核心的就是我们上边用到的ZygoteState对象
base/core/java/android/os/ZygoteProcess.java
static ZygoteState connect(@NonNull LocalSocketAddress zygoteSocketAddress,
@Nullable LocalSocketAddress usapSocketAddress)
throws IOException {
DataInputStream zygoteInputStream;
BufferedWriter zygoteOutputWriter;
final LocalSocket zygoteSessionSocket = new LocalSocket();
if (zygoteSocketAddress == null) {
throw new IllegalArgumentException("zygoteSocketAddress can't be null");
}
try {
zygoteSessionSocket.connect(zygoteSocketAddress);
zygoteInputStream = new DataInputStream(zygoteSessionSocket.getInputStream());
zygoteOutputWriter =
new BufferedWriter(
new OutputStreamWriter(zygoteSessionSocket.getOutputStream()),
Zygote.SOCKET_BUFFER_SIZE);
} catch (IOException ex) {
try {
zygoteSessionSocket.close();
} catch (IOException ignore) { }
throw ex;
}
return new ZygoteState(zygoteSocketAddress, usapSocketAddress,
zygoteSessionSocket, zygoteInputStream, zygoteOutputWriter,
getAbiList(zygoteOutputWriter, zygoteInputStream));
}通过LocalSocket和目的addr发起连接,然后创建了inputStream和outputStream作为输入输出接口
所以我们看到在attemptZygoteSendArgsAndGetResult函数中使用zygoteWriter.write(msgStr);发起了跨进程通信
总结下Process::startViaZygote函数开始的主要流程如下:
将应用进程的启动参数保存到 argsForZygote 集合中
用 openZygoteSocketIfNeeded() 方法用来创建用于通信的 socket
调用 zygoteSendArgsAndGetResult 方法将应用程序进程的启动参数通过 socket 发送到 Zygote 进程
为什么用Socket?
Zyote是单线程模式
进程的创建是通过fork来的,fork的原理就是copy-on-write机制,这种方式可以提高进程启动速度,因为新的进程所需要资源已经在 zygote 进程中加载和初始化一次,进程被创建时会复制 zygote 的共享的资源,避免重复初始化。
fork操作会复制当前进程(包括线程)到子进程,如果Zygote在fork之前使用了Binder进行通信,那么Binder线程也会被复制到子进程中,子进程中Binder线程可能不再需要,可能引发问题(如死锁或资源竞争)。因此,使用Socket可以避免这些潜在问题(如死锁或资源竞争)
Zygote进程的核心任务是通过fork()克隆自身生成新进程,而Binder机制与fork()存在以下不可调和的矛盾[4]:
状态混乱:
Binder依赖线程池和接口状态,子进程会继承父进程的Binder线程池和未处理的请求队列。
子进程的Binder驱动状态可能因线程ID冲突或资源竞争导致死锁或崩溃。
资源释放难题:
Binder对象成对存在(Client端和Server端),子进程无法安全释放父进程的Binder对象。
如果子进程释放了Server端Binder对象,AMS(Activity Manager Service)将失去与Zygote的通信能力。
初始化时序问题:
Binder驱动需要依赖
ServiceManager进程完成注册,而ServiceManager的初始化晚于Zygote。Zygote无法保证在
ServiceManager完全就绪后注册Binder接口,导致通信失败。
总的来说,在Linux中fork 创建的子进程会继承父进程的虚拟地址空间,但只复制调用 fork 的线程,其他线程会在子进程中“消失”。这种行为可能导致锁、文件描述符等资源的状态不一致,从而引发死锁或其他问题。
Zygote创建进程
Zygote进程启动之后,开启了Socket监听,如果收到来自客户端的创建进程请求,则解析参数,启动进程,查找并执行Main函数
main入口
base/core/java/com/android/internal/os/ZygoteInit.java
public static void main(String[] argv) {
ZygoteServer zygoteServer = null;
Runnable caller;
try {
...
zygoteServer = new ZygoteServer(isPrimaryZygote);
// 启动system_server进程
if (startSystemServer) {
Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);
// {@code r == null} in the parent (zygote) process, and {@code r != null} in the
// child (system_server) process.
if (r != null) {
r.run();
return;
}
}
// The select loop returns early in the child process after a fork and
// loops forever in the zygote.
//启动其他应用进程
caller = zygoteServer.runSelectLoop(abiList);
} catch (Throwable ex) {
Log.e(TAG, "System zygote died with fatal exception", ex);
throw ex;
} finally {
if (zygoteServer != null) {
zygoteServer.closeServerSocket();
}
}
// We're in the child process and have exited the select loop. Proceed to execute the
// command.
if (caller != null) {
// 执行子进程的Main函数
caller.run();
}
预加载系统资源,包含系统常用类、资源、字体等等
开启 socket 服务,启动system_server进程,然后调用 runSelectLoop 方法进入无限循环中等待 socket 消息
Zygote 收到启动新进程的 socket 消息后,fork 新进程并执行新进程的 main 函数
开启Socket监听
ZygoteServer初始化的时候开启LocalSocket监听
ZygoteServer(boolean isPrimaryZygote) {
mUsapPoolEventFD = Zygote.getUsapPoolEventFD();
if (isPrimaryZygote) {
mZygoteSocket = Zygote.createManagedSocketFromInitSocket(Zygote.PRIMARY_SOCKET_NAME);
...
}
...
}
createManagedSocketFromInitSocket从环境变量中获取到 zygote socket,最终返回一个LocalServerSocket对象
static LocalServerSocket createManagedSocketFromInitSocket(String socketName) {
int fileDesc;
final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;
String env = System.getenv(fullSocketName);
fileDesc = Integer.parseInt(env);
FileDescriptor fd = new FileDescriptor();
fd.setInt$(fileDesc);
//把 socket fd 包装成一个 LocalServerSocket
return new LocalServerSocket(fd);
}runSelectLoop等待 socket消息
runSelectLoop开启了while(true)的无限循环,用来监听来自system_server的socket连接
Runnable runSelectLoop(String abiList) {
ArrayList<FileDescriptor> socketFDs = new ArrayList<>();
ArrayList<ZygoteConnection> peers = new ArrayList<>();
socketFDs.add(mZygoteSocket.getFileDescriptor());
peers.add(null);
while (true) {
int[] usapPipeFDs = null;
StructPollfd[] pollFDs;
if (mUsapPoolEnabled) {
...
} else {
pollFDs = new StructPollfd[socketFDs.size()];
}
// 将socket fd存入pollFDs数组,当前的逻辑下就只有一个,mZygoteSocket的fd
int pollIndex = 0;
for (FileDescriptor socketFD : socketFDs) {
pollFDs[pollIndex] = new StructPollfd();
pollFDs[pollIndex].fd = socketFD;
// 监听可读事件
pollFDs[pollIndex].events = (short) POLLIN;
++pollIndex;
}
...
try {
// poll机制,进入休眠并监听
pollReturnValue = Os.poll(pollFDs, pollTimeoutMs);
} catch (ErrnoException ex) {
throw new RuntimeException("poll failed", ex);
}
...
}
上面将mZygoteSocket的fd保存到了StructPollfd数组中,system_server创建跨进程时会socket连接到这个fd, Zygote通过poll进入休眠,当有socket连接消息时,就会唤醒进程
Socket唤醒进程
Runnable runSelectLoop(String abiList) {
...
while (true) {
...
try {
// socket唤醒
pollReturnValue = Os.poll(pollFDs, pollTimeoutMs);
} catch (ErrnoException ex) {
throw new RuntimeException("poll failed", ex);
}
if (pollReturnValue == 0) {
...
} else {
while (--pollIndex >= 0) {
// 只接受POLLIN事件
if ((pollFDs[pollIndex].revents & POLLIN) == 0) {
continue;
}
if (pollIndex == 0) {
// Zygote server socket
// 构建一个与客户端通信的 ZygoteConnection 类型的辅助对象
ZygoteConnection newPeer = acceptCommandPeer(abiList);
peers.add(newPeer);
//加入列表,监听来自客户端的消息
socketFDs.add(newPeer.getFileDescriptor());
} else if (pollIndex < usapPoolEventFDIndex) {
// Session socket accepted from the Zygote server socket
try {
ZygoteConnection connection = peers.get(pollIndex);
boolean multipleForksOK = !isUsapPoolEnabled()
&& ZygoteHooks.isIndefiniteThreadSuspensionSafe();
final Runnable command =
connection.processCommand(this, multipleForksOK);
// 子进程
if (mIsForkChild) {
// We're in the child. We should always have a command to run at
// this stage if processCommand hasn't called "exec".
return command;
} else {
// 父进程/Zygote进程
// We're in the server - we should never have any commands to run.
if (command != null) {
throw new IllegalStateException("command != null");
}
// We don't know whether the remote side of the socket was closed or
// not until we attempt to read from it from processCommand. This
// shows up as a regular POLLIN event in our regular processing
// loop.
if (connection.isClosedByPeer()) {
connection.closeSocket();
peers.remove(pollIndex);
socketFDs.remove(pollIndex);
}
}
} catch (Exception e) {
}
...
Os.poll(pollFDs, pollTimeoutMs)是一种IO多路复用技术,socket收到消息唤醒进程
接下来有一个循环 while (--pollIndex >= 0) , 上面遍历了socketFDs并且将元素添加到pollFDs数组,socketFDs只添加了只有一个mZygoteSocket的fd,所以这里的pollIndex 为1,因此if (pollIndex == 0)条件成立。
此时表示system_server和Zygote进程建立了socket连接,创建一个ZygoteConnection对象保存到peer,将fd添加到socketFDs,进入下一次while(true)循环触发休眠。
接下来如果socketFDs中的连接有消息发过来,那么将会唤醒,此时pollIndex ==2,从peer中获取一个connection对象,调用connection.processCommand(this, multipleForksOK)创建子进程
connection.processCommand子进程一旦创建成功,接下来的代码就分别运行在不同的进程中了,这和Linux fork一个进程之后的逻辑是一样的,在子进程中mIsForkChild变量被置为true,将返回 command,结束while循环,在外面执行子进程的main函数对于Zygote进程,将继续执行后面的代码,关闭connection的socket连接,将其从peer列表中移除,删除对应的fd,然后继续陷入死循环,进入休眠,直到下一个socket连接进来唤醒进程
创建子进程
核心函数processCommand
Runnable processCommand(ZygoteServer zygoteServer, boolean multipleOK) {
ZygoteArguments parsedArgs;
try (ZygoteCommandBuffer argBuffer = new ZygoteCommandBuffer(mSocket)) {
while (true) {
try {
// 解析来自Socket的参数
parsedArgs = ZygoteArguments.getInstance(argBuffer);
// Keep argBuffer around, since we need it to fork.
} catch (IOException ex) {
throw new IllegalStateException("IOException on command socket", ex);
}
int pid;
if (parsedArgs.mInvokeWith != null || parsedArgs.mStartChildZygote
|| !multipleOK || peer.getUid() != Process.SYSTEM_UID) {
// Continue using old code for now. TODO: Handle these cases in the other path.
// 创建子进程
// forkAndSpecialize 是对 fork 系统调用的包装
pid = Zygote.forkAndSpecialize(parsedArgs.mUid, parsedArgs.mGid,
parsedArgs.mGids, parsedArgs.mRuntimeFlags, rlimits,
parsedArgs.mMountExternal, parsedArgs.mSeInfo, parsedArgs.mNiceName,
fdsToClose, fdsToIgnore, parsedArgs.mStartChildZygote,
parsedArgs.mInstructionSet, parsedArgs.mAppDataDir,
parsedArgs.mIsTopApp, parsedArgs.mPkgDataInfoList,
parsedArgs.mAllowlistedDataInfoList, parsedArgs.mBindMountAppDataDirs,
parsedArgs.mBindMountAppStorageDirs);
try {
//成功创建出子进程
if (pid == 0) {
// in child
zygoteServer.setForkChild();
zygoteServer.closeServerSocket();
IoUtils.closeQuietly(serverPipeFd);
serverPipeFd = null;
return handleChildProc(parsedArgs, childPipeFd,
parsedArgs.mStartChildZygote);
} else {
// In the parent. A pid < 0 indicates a failure and will be handled in
// handleParentProc.
IoUtils.closeQuietly(childPipeFd);
childPipeFd = null;
handleParentProc(pid, serverPipeFd);
return null;
}
} finally {
IoUtils.closeQuietly(childPipeFd);
IoUtils.closeQuietly(serverPipeFd);
}
}
生成ZygoteArguments对象,这个对象创建的时候就开始解析参数,都是以
--开头的参数,这些参数正是Process::start函数中传递进来的
private ZygoteArguments(ZygoteCommandBuffer args, int argCount)
throws IllegalArgumentException, EOFException {
parseArgs(args, argCount);
}
private void parseArgs(ZygoteCommandBuffer args, int argCount)
throws IllegalArgumentException, EOFException {
for ( /* curArg */ ; curArg < argCount; ++curArg) {
String arg = args.nextArg();
if (arg.equals("--")) {
curArg++;
break;
} else if (arg.startsWith("--setuid=")) {
if (mUidSpecified) {
throw new IllegalArgumentException(
"Duplicate arg specified");
}
mUidSpecified = true;
mUid = Integer.parseInt(getAssignmentValue(arg));
}
...
调用forkAndSpecialize创建子进程
从参数的mRemainingArgs字段中查找Main函数并且封装为Runnable返回
fork vs java标准API
在Android 中创建子线程是通过jni调用Linux的fork函数,所以进程创建之后共享父进程的所有资源,代码接着fork之后开始执行
在纯Java中,创建子进程要通过 ProcessBuilder 或 Runtime.exec(),没有fork函数,java会“从头启动”新程序:启动一个全新的、独立的进程,并且效率低于fork,每个新进程都是一个完全独立的内存空间,不共享初始化状态
查找Main函数
private Runnable handleChildProc(ZygoteArguments parsedArgs,
FileDescriptor pipeFd, boolean isZygote) {
//关闭监听用的 socket 和从 Zygote 中继承的文件描述符
closeSocket();
Zygote.setAppProcessName(parsedArgs, TAG);
// End of the postFork event.
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
if (parsedArgs.mInvokeWith != null) {
...
} else {
if (!isZygote) {
return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,
parsedArgs.mDisabledCompatChanges,
parsedArgs.mRemainingArgs, null /* classLoader */);
} else {
return ZygoteInit.childZygoteInit(
parsedArgs.mRemainingArgs /* classLoader */);
}
}
}
关闭socket
设置进程名称
接着调用ZygoteInit::zygoteInit函数
base/core/java/com/android/internal/os/RuntimeInit.java
public static Runnable zygoteInit(int targetSdkVersion, long[] disabledCompatChanges,
String[] argv, ClassLoader classLoader) {
RuntimeInit.commonInit();
ZygoteInit.nativeZygoteInit();
return RuntimeInit.applicationInit(targetSdkVersion, disabledCompatChanges, argv,
classLoader);
}
protected static Runnable applicationInit(int targetSdkVersion, long[] disabledCompatChanges,
String[] argv, ClassLoader classLoader) {
VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
VMRuntime.getRuntime().setDisabledCompatChanges(disabledCompatChanges);
final Arguments args = new Arguments(argv);
// The end of of the RuntimeInit event (see #zygoteInit).
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
// Remaining arguments are passed to the start class's static main
return findStaticMain(args.startClass, args.startArgs, classLoader);
}查找启动类
new Arguments(argv) 通过parseArgs查找启动类,查找的是argv中第一个非--开头的参数,我们探究一下这个class是什么
start class的来源
再来看看启动进程的函数ProcessList::startProcessLocked
boolean startProcessLocked(ProcessRecord app, HostingRecord hostingRecord,
int zygotePolicyFlags, boolean disableHiddenApiChecks, boolean disableTestApiChecks,
String abiOverride) {
if (app.isPendingStart()) {
return true;
}
try {
...
final String entryPoint = "android.app.ActivityThread";
return startProcessLocked(hostingRecord, entryPoint, app, uid, gids,
runtimeFlags, zygotePolicyFlags, mountExternal, seInfo, requiredAbi,
instructionSet, invokeWith, startUptime, startElapsedTime);
} catch (RuntimeException e) {
}
}这里定义了一个entryPoint变量,这个变量就是我们的startClass, entryPoint会作为参数传递到ZygoteProcess::startViaZygote,变量名称变为processClass
private Process.ProcessStartResult startViaZygote(@NonNull final String processClass,
@Nullable final String niceName,
final int uid, final int gid, ...) {
ArrayList<String> 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);
// 添加及其他参数,均以--开头
....
// 添加启动类
argsForZygote.add(processClass);
// 添加启动类main函数的参数
if (extraArgs != null) {
Collections.addAll(argsForZygote, extraArgs);
}
synchronized(mLock) {
// 发起socket连接
return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi),
zygotePolicyFlags,
argsForZygote);
}
}argsForZygote会将所有--开头的参数添加完之后再添加 processClass, 从上层函数传递的值可以看到启动类就是ActivityThread,所以Zygote进程在查找启动类就是从第一个非--参数读出来的,后续的参数作为main函数的参数
封装Runnable
protected static Runnable findStaticMain(String className, String[] argv,
ClassLoader classLoader) {
...
Class<?> cl;
cl = Class.forName(className, true, classLoader);
Method m;
m = cl.getMethod("main", new Class[] { String[].class });
int modifiers = m.getModifiers();
if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
throw new RuntimeException(
"Main method is not public and static on " + className);
}
return new MethodAndArgsCaller(m, argv);
}
findStaticMain中通过反射查找到public static main()函数,然后封装到MethodAndArgsCaller,这是一个Runnable的实现类
小结
在MainActivity的onCreate函数中打印调用栈如下:
Demo-zygote-stack: java.lang.Throwable: DEBUG
D Demo-zygote-stack: at com.mercedes.wellbeing.ui.MainActivity.onCreate(MainActivity.kt:126)
D Demo-zygote-stack: at android.app.Activity.performCreate(Activity.java:8350)
D Demo-zygote-stack: at android.app.Activity.performCreate(Activity.java:8329)
D Demo-zygote-stack: at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1417)
D Demo-zygote-stack: at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3625)
D Demo-zygote-stack: at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3781)
D Demo-zygote-stack: at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:101)
D Demo-zygote-stack: at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:138)
D Demo-zygote-stack: at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
D Demo-zygote-stack: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2306)
D Demo-zygote-stack: at android.os.Handler.dispatchMessage(Handler.java:106)
D Demo-zygote-stack: at android.os.Looper.loopOnce(Looper.java:201)
D Demo-zygote-stack: at android.os.Looper.loop(Looper.java:288)
D Demo-zygote-stack: at android.app.ActivityThread.main(ActivityThread.java:7924)
D Demo-zygote-stack: at java.lang.reflect.Method.invoke(Native Method)
D Demo-zygote-stack: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
D Demo-zygote-stack: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:946)可以看到,与上面的进程启动分析一致,ZygoteInit::main为Android进程的顶级入口,通过Caller的反射调用进入启动类ActivityThread::main, 所有app的调用栈顶级函数都是固定的这几个函数调用。
自此,子进程创建完毕,找到启动类,并且封装好了Runnable,子进程中断了继承自Zygote进程的while无限循环,回到main函数调用
base/core/java/com/android/internal/os/ZygoteInit.java
public static void main(String[] argv) {
...
caller = zygoteServer.runSelectLoop(abiList);
if (caller != null) {
caller.run();
}
}接下来就执行到了ActivityThread::main函数里边了,Android 应用进程启动了
ActivityThread应用进程启动
现在进入到了第四阶段
我们把ActivityThread::main函数当作真正的应用进程启动入口,或者理解为主线程入口函数,接下来我们继续分析进程启动之后发生了什么
main入口
base/core/java/android/app/ActivityThread.java
public static void main(String[] args) {
//Trace点
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
Environment.initForCurrentUser();
// 创建主线程的looper
Looper.prepareMainLooper();
// Find the value for {@link #PROC_START_SEQ_IDENT} if provided on the command line.
// It will be in the format "seq=114"
long startSeq = 0;
ActivityThread thread = new ActivityThread();
// 绑定AMS
thread.attach(false, startSeq);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
// End of event ActivityThreadMain.
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
// 开启Handler的消息循环
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
创建主线程的Looper, 这个Looper存到ThreadLocal中,主线程在任何时候都能通过
Looper::getMainLooper获取到主线程的Looper, 常常在主线程中创建Handler的时候用到创建ActivityThread对象,并且通过
attach将ApplicationThread binder绑定到AMS, 该binder作为AMS和应用进程通信的核心接口主线程进入无限循环模式,之后的事都交给内部类H:Handler来处理
向AMS注册ActivityThread
ActivityThread和AMS之间的通信主要是ApplicationThread这个binder对象,首先从ServiceManager获取AMS的binder:IActivityManager , IActivityManager 实现类是AMS
private void attach(boolean system, long startSeq) {
sCurrentActivityThread = this;
mConfigurationController = new ConfigurationController(this);
mSystemThread = system;
if (!system) {
RuntimeInit.setApplicationObject(mAppThread.asBinder());
final IActivityManager mgr = ActivityManager.getService();
try {
mgr.attachApplication(mAppThread, startSeq);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
...
ActivityManagerService类定义如下
base/services/core/java/com/android/server/am/ActivityManagerService.java
public class ActivityManagerService extends IActivityManager.Stub
implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback, ActivityManagerGlobalLock {
...
}AMS attachApplication绑定进程信息
函数AMS::attachApplication简单调用attachApplicationLocked
private boolean attachApplicationLocked(@NonNull IApplicationThread thread,
int pid, int callingUid, long startSeq) {
// app进程
ProcessRecord app;
long startTime = SystemClock.uptimeMillis();
long bindApplicationTimeMillis;
if (pid != MY_PID && pid >= 0) {
synchronized (mPidsSelfLocked) {
app = mPidsSelfLocked.get(pid);
}
...
} else {
app = null;
}
//没有进程直接结束
if (app == null) {
...
return false;
}
// system_server已经准备就绪,或者app允许在BOOT_COMPLETED之前启动
boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
try {
...
if (app.getIsolatedEntryPoint() != null) {
...
} else if (instr2 != null) {
thread.bindApplication(processName, ...);
} else {
thread.bindApplication(processName, appInfo,
app.sdkSandboxClientAppVolumeUuid, app.sdkSandboxClientAppPackage,
providerList, null, profilerInfo, null, null, null, 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,
app.getStartElapsedTime(), app.getStartUptime());
}
...
}
// See if the top visible activity is waiting to run in this process...
// 大多情况下为true
if (normalMode) {
try {
// ATMS
didSomething = mAtmInternal.attachApplication(app.getWindowProcessController());
} catch (Exception e) {
Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
badApp = true;
}
}
ProcessRecord的来源
首先获取ProcessRecord, 这个ProcessRecord在ProcessList::startProcessLocked的时候创建,当Zygote创建好进程之后,回到
ProcessList::handleProcessStartedLocked函数,通过ActivityManagerService::addPidLocked保存下来
base/services/core/java/com/android/server/am/ProcessList.java
boolean handleProcessStartedLocked(ProcessRecord app, int pid, boolean usingWrapper,
long expectedStartSeq, boolean procAttached) {
...
//
mService.reportUidInfoMessageLocked(TAG, buf.toString(), app.getStartUid());
mService.addPidLocked(app);
...
return true
}调用
ActivityThread::bindApplication, 将AppicationInfo等信息回传给ActivityThread进程调用ATMS的attachApplication,这一步就会再次去启动Activity
AMS向ActivityThread注册应用信息
在ActivityManagerService::attachApplicationLocked中,马上会调用 thread.bindApplication(processName, appInfo,...),向ActivityThread注册一些App相关的信息,比如appInfo,processName这些都是在ProcessList启动进程的时候创建的
thread.bindApplication是一次binder跨进程,在ActivityThread中有一个H类,会发送一个消息:BIND_APPLICATION,在主线程中处理
// class H extends Handler
public void handleMessage(Message msg) {
if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
switch (msg.what) {
case BIND_APPLICATION:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
AppBindData data = (AppBindData)msg.obj;
handleBindApplication(data);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
...
}ATMS 启动Activity
ATMS在AMS中的对象是 mAtmInternal,作为一个系统service获取方式如下
mAtmInternal = LocalServices.getService(ActivityTaskManagerInternal.class);系统Service都通过LocalServices注册,AMS服务本身也是在初始化的时候注册进去的
ATMS的attachApplication();调用栈如下,直接进入process函数,当调用进入RootWindowContainer之后,处理的就是跟窗口相关的功能了
//ATMS调用链
ActivityTaskManagerService::attachApplication
RootWindowContainer::attachApplication
AttachApplicationHelper::process
// WindowContainer$AttachApplicationHelper
boolean process(WindowProcessController app) throws RemoteException {
mApp = app;
for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
//遍历所有容器
getChildAt(displayNdx).forAllRootTasks(this);
if (mRemoteException != null) {
throw mRemoteException;
}
}
if (!mHasActivityStarted) {
ensureActivitiesVisible(null /* starting */, 0 /* configChanges */,
false /* preserveWindows */);
}
return mHasActivityStarted;
}AttachApplicationHelper 实现了Consumer函数接口,所以forAllRootTasks(this)this表示传入的是一个函数接口Consumer
forAllRootTasks的子类实现在Task,调用的是accept函数
base/services/core/java/com/android/server/wm/Task.java
void forAllRootTasks(Consumer<Task> callback, boolean traverseTopToBottom) {
if (isRootTask()) {
callback.accept(this);
}
}重点关注AttachApplicationHelper::accept和AttachApplicationHelper::test函数
// called by Task
public void accept(Task rootTask) {
// 跳过不可见的Task
if (rootTask.getVisibility(null /* starting */)
== TASK_FRAGMENT_VISIBILITY_INVISIBLE) {
return;
}
mTop = rootTask.topRunningActivity();
// 遍历Task下的ActivityRecord,并执行test函数
rootTask.forAllActivities(this);
}
// called by ActivityRecord
@Override
public boolean test(ActivityRecord r) {
try {
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;
}accept函数遍历了Task下的所有Activity并对其执行forAllActivities函数,forAllActivities实现类是ActivityRecord,这个函数饶了一圈会执行到test函数
test函数的终极功能就是调用realStartActivityLocked启动Activity, 如果启动成功赋值 mHasActivityStarted = true
回到process函数,当遍历完所有Task之后,如果没有activity启动:if (!mHasActivityStarted),触发函数ensureActivitiesVisible,这个函数之前已经分析过,处理所有Activity的可见性
创建Activity
上面分析了启动Activity之前的流程,概括下
准备Activity启动参数,生成ActivityRecord对象,并且挂载到Task的顶层,然后调用一个很重要的函数
resumeFocusedTasksTopActivities来执行下面两步让上一个Activity暂停掉,也就是进入Pause状态,应用端暂停之后触发pauseComplete回调,此时如果进程还没有启动,则尝试创建进程
和第二步并行执行,启动目标应用进程,在ProcessList里边准备进程启动参数,然后在Zygote进程中fork一个子进程,执行
ActivityThread::main函数,通过ActivityManagerService::attachApplication函数和AMS/ATMS绑定,ATMS启动Activity接着到了Activity创建流程
ATMS发起启动Transaction
在分析ATMS时,曾多次试图启动Activity,调用的是ActivityTaskSupervisor::startSpecificActivity,首先判断进程是否启动,如果进程已经启动,则调用ActivityTaskSupervisor::realStartActivityLocked来启动Activity, 当进程启动之后在RootWindowContainer::test函数中调用realStartActivityLocked函数来启动Activity.
来看看核心的 realStartActivityLocked
base/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
boolean realStartActivityLocked(ActivityRecord r, WindowProcessController proc,
boolean andResume, boolean checkConfig) throws RemoteException {
// 如果还有正在paused的activity没有完成,不会启动Activity
if (!mRootWindowContainer.allPausedActivitiesComplete()) {
return false;
}
final Task task = r.getTask();
final Task rootTask = task.getRootTask();
try {
// ActivityRecord已连接到相应的进程
r.setProcess(proc);
final IActivityClientController activityClientController =
proc.hasEverLaunchedActivity() ? null : mService.mActivityClientController;
r.launchCount++;
r.lastLaunchTime = SystemClock.uptimeMillis();
...
try {
// 进程启动了,但是主线程ActivityThread::main还没有执行
if (!proc.hasThread()) {
throw new RemoteException();
}
...
// Create activity launch transaction.
final ClientTransaction clientTransaction = ClientTransaction.obtain(
proc.getThread(), r.token);
final boolean isTransitionForward = r.isTransitionForward();
final IBinder fragmentToken = r.getTaskFragment().getFragmentToken();
clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),
System.identityHashCode(r), r.info,
mergedConfiguration.getGlobalConfiguration(),
mergedConfiguration.getOverrideConfiguration(), r.compat,
r.getFilteredReferrer(r.launchedFromPackage), task.voiceInteractor,
proc.getReportedProcState(), r.getSavedState(), r.getPersistentSavedState(),
results, newIntents, r.takeOptions(), isTransitionForward,
proc.createProfilerInfoIfNeeded(), r.assistToken, activityClientController,
r.shareableActivityToken, r.getLaunchedFromBubble(), fragmentToken));
// Set desired final state.
final ActivityLifecycleItem lifecycleItem;
if (andResume) {
lifecycleItem = ResumeActivityItem.obtain(isTransitionForward);
} else {
lifecycleItem = PauseActivityItem.obtain();
}
clientTransaction.setLifecycleStateRequest(lifecycleItem);
// Schedule transaction.
mService.getLifecycleManager().scheduleTransaction(clientTransaction);
}
...
return true;
}等待Pause complete
一开始就有个条件判断 allPausedActivitiesComplete
如果进程启动很快,pause的进度比我们慢了,那么此时还不能执行启动,当completePause之后再次尝试启动Activity
当前的分析逻辑是进程启动了,然后启动Activity,但是有个条件
设置ActivityRecord进程信息
创建ClientTransaction
创建一个LaunchActivityItem并且添加到transaction里边,还添加了一个ResumeActivityItem表示启动之后马上Resume
调用scheduleTransaction函数发起transaction
Transaction最终由TransactionExecutor::execute执行,先执行callback,然后执行lifeCycleState
Transaction执行到ActivityThread
transaction的执行最终执行到LaunchActivityItem::execute函数
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, mActivityOptions, mIsForward, mProfilerInfo,
client, mAssistToken, mShareableActivityToken, mLaunchedFromBubble,
mTaskFragmentToken);
client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}参数client的实现类是ActivityThread,token是ActivityRecord的token,然后将Activity启动参数封装到ActivityClientRecord对象
ActivityThread执行Activity启动流程
ActivityThread::handleLaunchActivity
@Override
public Activity handleLaunchActivity(ActivityClientRecord r,
PendingTransactionActions pendingActions, Intent customIntent) {
final Activity a = performLaunchActivity(r, customIntent);
return a;
}里边直接调用了performLaunchActivity
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
ActivityInfo aInfo = r.activityInfo;
//创建Context
ContextImpl appContext = createBaseContextForActivity(r);
Activity activity = null;
try {
java.lang.ClassLoader cl = appContext.getClassLoader();
//创建Activity
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
StrictMode.incrementExpectedActivityCount(activity.getClass());
r.intent.setExtrasClassLoader(cl);
r.intent.prepareToEnterProcess(isProtectedComponent(r.activityInfo),
appContext.getAttributionSource());
if (r.state != null) {
r.state.setClassLoader(cl);
}
}
try {
// 创建Application
Application app = r.packageInfo.makeApplicationInner(false, mInstrumentation);
...
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.activityConfigCallback,
r.assistToken, r.shareableActivityToken);
r.activity = activity;
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
}
r.setState(ON_CREATE);
return activity;
}生成Context,context实现类是ContextImpl,如果是非默认屏幕则会根据displayId创建新的ContextImpl
生成Activity对象,调用了Instrumentation::newActivity,实际上是通过ClassLoader加载的Activity
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);
}
public @NonNull Activity instantiateActivity(@NonNull ClassLoader cl, @NonNull String className,
@Nullable Intent intent)
throws InstantiationException, IllegalAccessException, ClassNotFoundException {
// 反射创建
return (Activity) cl.loadClass(className).newInstance();
}执行Activity::attach,绑定Application,Context,Token,创建PhoneWindow对象,初始化LayoutInflator
开始执行Activity::onCreate生命周期
public void callActivityOnCreate(Activity activity, Bundle icicle) {
prePerformCreate(activity);
activity.performCreate(icicle);
postPerformCreate(activity);
}在performCreate函数中会调用onCreate函数, 这个时候就会开始加载布局了
Activity从点击到实例创建的整个流程就分析完了
参考资料
[1].【Android 14源码分析】Activity启动流程-1
[2].【Android 14源码分析】Activity启动流程-2
[3]. 【Android 14源码分析】Activity启动流程-3
[4]. Zygote为什么用Socket而不用Binder?深度解析Android进程通信机制与实战开发 - Android洋芋 - 博客园
[5]. 010.Android 系统启动之应用进程启动分析 | Ahao's Technical Blog
[6]. android开发基于Android10分析Zygote启动过程以及Fork应用进程的过程分析 - yongfengnice - 博客园