android N进程启动流程(二)(上一个activity的暂停、进程启动、绑定进程与创建application)
第二部分将分为:上一个activity的暂停、进程启动、绑定进程与创建application
5. 上一个activity的暂停

图5.1 上一个activity的暂停
接着章节3.6的startActivityUnchecked中会调用最后有调用resumeFocusedStackTopActivityLocked,我们接下去从这里开始讲解。
5.1 resumeFocusedStackTopActivityLocked(ActivityStackSupervisor.java)
resumeFocusedStackTopActivityLocked恢复当前focus的堆栈stack中的顶端活动对象top activity
1) 上面章节3.6中setTaskFromReuseOrCreateNewTask->computeStackFocus->mSupervisor.getStack已经创建了mTargetStack,并将其添加到ActivityDisplay的mStack中去。
2) 章节3.6中moveToFront的insertTaskAtTop中也设置了需要启动的应用如test2.com.myapplication成为堆栈顶端Top的进程
3) 章节4.2中setFocusStackUnchecked也设置了mTargetStack为test2
//上面章节3.6中setTaskFromReuseOrCreateNewTask已经创建了mTargetStack,
//章节3.6中moveToFront的insertTaskAtTop中也设置了需要启动的应用如test2.com.myapplication
//成为堆栈顶端Top的进程
boolean resumeFocusedStackTopActivityLocked(
ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
if (targetStack != null && isFocusedStack(targetStack)) {
//targetStack不为null,而且isFocusedStack也是test2,故此处是会进来的
return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
}
//...
}
5.2 resumeTopActivityUncheckedLocked(ActivityStack.java)
resumeFocusedStackTopActivityLocked恢复当前focus堆栈stack中的顶端活动对象
1) 此处的stack this对象是test2上一章节5.1中说的mTargetStack
2) 此时是第一次看到resumeTopActivityInnerLocked,故是第一次进入,传递的prev是test2.com.myapplication我们先看第一次进入该函数的处理逻辑(第二次的请忽略先)
3) 此处逻辑依次是resumeTopActivityUncheckedLocked->resumeTopActivityInnerLocked->pauseBackStacks
4) 第一次进入由于在pauseBackStacks返回有需要pause的应用,故pausing==true,pauseBackStacks做完不久就直接返回了
boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
//....
result = resumeTopActivityInnerLocked(prev, options);
//....
}
//第一次进来的时候prev是test2.com.myapplication(所以会先pause上一个应用如com.android.launcher);
//第二次进来是prev是com.android.launcher,此时launcher已经pause了,
//会进入下一个应用的resume流程(如test2.com.myapplication)
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
//...
//第一次进来topRunningActivityLocked是test2,第二次进来也是test2,
//此处是在moveActivityStackToFront中已经设置过了
final ActivityRecord next = topRunningActivityLocked();
//...
//此处allPausedActivitiesComplete是true,不会进入这里,
//说明之前已经没有需要pause的应用(第一次进来mPausingActivity还没有设置过==null)
//或者pause完成(第二次进来)
if (!mStackSupervisor.allPausedActivitiesComplete()) {
…
return false;
}
//...
//是否有设置标志位在pausing的时候resume,默认没有设置都是false
final boolean dontWaitForPause = (next.info.flags & FLAG_RESUME_WHILE_PAUSING) != ;
//此处判断是否有需要pasue的进程(是所有stack而不仅仅是当前stack),
//第一次进来会pause launcher(launcher的堆栈中有mResumedActivity,
//但是章节4.2已经将焦点切换到test2)故反馈pausing==true,第二次直接返回pausing==false
boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, true, dontWaitForPause);
//mResumedActivity一直都是null(由于当前mTargetStack是新new出来的给进程test2使用),
//只有在test2 resume之后才会设置,如在minimalResumeActivityLocked之后设置,故不会走下面的逻辑
if (mResumedActivity != null) {
//...
}
//第一次走的pausing是true(代表有需要暂停的应用,如launcher),第二次pausing是false
if (pausing) {
//...
//第一次进来到这里就结束了
return true;
//此处一般都是不走的mResumedActivity == null,第二次pausing是false,
//但是还是有activity继续resume(allResumedActivitiesComplete返回false)
} else if (mResumedActivity == next && next.state == ActivityState.RESUMED &&
mStackSupervisor.allResumedActivitiesComplete()) {
...
return true;
}
//第二次时会进来这里prev != next,此处next代表test2.com.myapplication,
//prev代表com.android.launcher
if (prev != null && prev != next) {
if (!mStackSupervisor.mWaitingVisibleActivities.contains(prev)
&& next != null && !next.nowVisible) {
//等待prev的界面launcher隐藏,此处在mStackSupervisor的
//processStoppingActivitiesLocked时才会remove
mStackSupervisor.mWaitingVisibleActivities.add(prev);
} else {
//...
}
//...
//第二次进来时prev == com.android.launcher
if (prev != null) {
//launcher是没有finishing的,不进入这里
if (prev.finishing) {
//...
//准备resume test2.com.myapplication时prev代表com.android.launcher,会进来这里
} else {
//prev.task不等于next.task,mLaunchTaskBehind是false,
//WMS中传输类型是TRANSIT_TASK_OPEN
mWindowManager.prepareAppTransition(prev.task == next.task
? TRANSIT_ACTIVITY_OPEN
: next.mLaunchTaskBehind
? TRANSIT_TASK_OPEN_BEHIND
: TRANSIT_TASK_OPEN, false);
}
} else {
//...
}
//...
//此处next(test2.com.myapplication)进程都还没有起来,不会进入这里
if (next.app != null && next.app.thread != null) {
//...
//next(test2.com.myapplication)进入的是else
} else {
//第一次启动hasBeenLaunched肯定是false,所以会进入此处
if (!next.hasBeenLaunched) {
next.hasBeenLaunched = true;
} else {
...
}
//这里才是真正启动test2进程的地方
mStackSupervisor.startSpecificActivityLocked(next, true, true);
}
//...
}
5.3 pauseBackStacks(ActivityStackSupervisor.java)
pauseBackStacks遍历ActivityDisplay显示设备中的所有栈,当循环到luancher的时候,由于launcher已经不是focus的stack栈,但是它的mResumedActivity仍然存在,代表这个activity需要进行pause暂停的操作。
boolean pauseBackStacks(boolean userLeaving, boolean resuming, boolean dontWait) {
//...
//遍历stacks当前显示设备的所有堆栈
final ActivityStack stack = stacks.get(stackNdx);
//stack是launcher,isFocusedStack是false,mResumedActivity是launcher不等于null
if (!isFocusedStack(stack) && stack.mResumedActivity != null) {
//launcher的stack进行pause的操作,注意resuming是true,dontWait是false,
//userLeaving是true,在章节3.6 startActivityUnchecked->setInitialState中设置
someActivityPaused |= stack.startPausingLocked(userLeaving, false, resuming,
dontWait);
//...
}
5.4 startPausingLocked(ActivityStack.java)
1) startPausingLocked这个函数是启动应用暂停pause(如此处的是上一个应用launcher),设置当前状态为pausing
2) 进入ActivityThread处理暂停任务之前会在eventlog中输出am_pause_activity的信息,表示将要开始该应用的暂停了
3) 不过最重要的函数还是ActivityThread的schedulePauseActivity,该函数会处理pause任务
//userLeaving==true, uiSleeping==false, resuming==true, dontWait==false
final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping, boolean resuming,
boolean dontWait) {
//第一次进来mPausingActivity是null,应用没有暂停就没有所谓的mPausingActivity
if (mPausingActivity != null) {
//...
}
//mResumedActivity是当前resume的activity,此处是launcher
ActivityRecord prev = mResumedActivity;
//注意此处pause之后将设置mResumedActivity==null,代表没有该Stack没有resume的activity了
mResumedActivity = null;
//launcher设置为正在pause的进程
mPausingActivity = prev;
//设置上一个暂停的应用
mLastPausedActivity = prev;
//标定该进程在PAUSING状态
prev.state = ActivityState.PAUSING;
//此处next是test2,章节4.2的insertTaskAtTop已经设置过
final ActivityRecord next = mStackSupervisor.topRunningActivityLocked();
//pause应用会触发cpu状态更新,可以使用adb shell dumpsys cpuinfo查询
mService.updateCpuStats();
//prev是launcher,里面的app和thread都是已经创建的,所有此处会进入
if (prev.app != null && prev.app.thread != null) {
try {
//event log中的am_pause_activity,代表应用的pause开始
EventLog.writeEvent(EventLogTags.AM_PAUSE_ACTIVITY,
prev.userId, System.identityHashCode(prev),
prev.shortComponentName);
//cpu前后台切换,用于耗电统计
mService.updateUsageStats(prev, false);
//ActivityThread里面的方法是handle(异步),此处才是activity的真正的pause执行的地方
prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing,
userLeaving, prev.configChangeFlags, dontWait);
//...
//mPausingActivity就是launcher,所以会进来此处。
if (mPausingActivity != null) {
//uiSleeping==false
if (!uiSleeping) {
//应用的pause的时候,会暂停接收输入事件,此时系统触摸了不反馈给上层
prev.pauseKeyDispatchingLocked();
}
//dontWait==false,章节5.2中设置dontWaitForPause
if (dontWait) {
//只有当dontWait是true的时候才会走这里,就是不等待pause完成
completePauseLocked(false);
return false;
} else {
//launcher的最后onpause会走到这里来
Message msg = mHandler.obtainMessage(PAUSE_TIMEOUT_MSG);
msg.obj = prev;
prev.pauseTime = SystemClock.uptimeMillis();
//设置pause的超时时间为500ms
mHandler.sendMessageDelayed(msg, PAUSE_TIMEOUT);
//返回ture,代表有响应的activity正在pausing,
//故在章节5.2 resumeTopActivityInnerLocked运行完该函数后不久就返回了
return true;
}
} else {
//...
}
ps:上面也看到了pause的时候会限制输入事件,如果应用一直重启又挂掉又重启,此时如果不停调用pause/finish的话会限制输入事件的分发pauseKeyDispatchingLocked,当然这种情况只是极端情况,一般不会出现
5.5 schedulePauseActivity(ActivityThread.java)
1) schedulePauseActivity这个是通过handler(一直想吐槽这个hander也类名也太简洁了的点吧,一个”H”就搞定)在UI主线程里面做的事情
2) 主要流程是schedulePauseActivity->PAUSE_ACTIVITY->handlePauseActivity->performPauseActivity->performPauseActivityIfNeeded
3) 我们主要关注performPauseActivityIfNeeded当前activity暂停(这部分本章节讲解)、activityPaused通知AMS上一个activity暂停完成(这部分下一章里讲解)。
//ActivityThread给外部提供的接口,pause暂停是通过应用的主线程进行处理
public final void schedulePauseActivity(IBinder token, boolean finished,
boolean userLeaving, int configChanges, boolean dontReport) {
int seq = getLifecycleSeq();
//...
//finished等于false,走的是PAUSE_ACTIVITY,userLeaving==true,dontReport==dontWait==false
sendMessage(
finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY,
token,
(userLeaving ? USER_LEAVING : ) | (dontReport ? DONT_REPORT : ),
configChanges,
seq);
}
//handler传递,调用的是handlePauseActivity
case PAUSE_ACTIVITY: {
//...
//进入pause的处理
handlePauseActivity((IBinder) args.arg1, false,
(args.argi1 & USER_LEAVING) != , args.argi2,
(args.argi1 & DONT_REPORT) != , args.argi3);
//...
} break;
//finished是false,userLeaving==true,dontReport==false
private void handlePauseActivity(IBinder token, boolean finished,
boolean userLeaving, int configChanges, boolean dontReport, int seq) {
ActivityClientRecord r = mActivities.get(token);
...
if (r != null) {
//userLeaving一般都是true
if (userLeaving) {
//会进入此处,会调用activity.performUserLeaving,当离开用户可视的时候会调用
performUserLeavingActivity(r);
}
//...
//此处是pause上一个应用launcher,isPreHoneycomb是android3.0之前用的,此处是false
performPauseActivity(token, finished, r.isPreHoneycomb(), "handlePauseActivity");
//dontReport一般没有设置都是false,故一般都是进入此处的
if (!dontReport) {
try {
//通知AMS上一个应用完成pause了,这里接下去就会resume下一个应用(先启动进程),
//下一章会讲到
ActivityManagerNative.getDefault().activityPaused(token);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
mSomeActivitiesChanged = true;
}
}
final Bundle performPauseActivity(ActivityClientRecord r, boolean finished,
boolean saveState, String reason) {
//saveState是false,不跑这里
if (!r.activity.mFinished && saveState) {
callCallActivityOnSaveInstanceState(r);
}
//这里才是pause activity的地方
performPauseActivityIfNeeded(r, reason);
// 将当前pause的应用的OnActivityPausedListener暂停监听去除
ArrayList<OnActivityPausedListener> listeners;
synchronized (mOnPauseListeners) {
listeners = mOnPauseListeners.remove(r.activity);
}
//...
for (int i = ; i < size; i++) {
//此处是调用注册了该activity thread的监听onPaused的回调,
//如NfcAdapter.java中的ActivityThread.currentActivityThread()
//.registerOnActivityPausedListener(activity,mForegroundDispatchListener);
listeners.get(i).onPaused(r.activity);
}
//...
}
5.6 performPauseActivityIfNeeded(ActivityThread.java)
1) 通过代理类Instrumentation调用callActivityOnPause,其调用的是activity的performPause(分别会调用mFragments.dispatchPause、activity的onPause,application的ActivityLifecycleCallback生命周期回调方法onActivityPaused)
2) OnPause调用完成后会在event log中写入am_on_paused_called,代表activity的OnPause已经完成(如果你使用onpause有问题,可以从am_pause_activity到am_on_paused_called之间所花费的时间做初步判断)
3) 注意OnPause完成之后paused会赋值为true,代表当前是暂停状态
private void performPauseActivityIfNeeded(ActivityClientRecord r, String reason) {
if (r.paused) {
//如果之前paused==true了就直接返回,activitythread创建设置成false,
//oncreate将设置成ture,onresume将设置成false
//上一个activity的上一个状态是onresume,正在pause,故此处是paused==false
return;
}
try {
//这里解释一下mCalled,这个值是用来判断是否有调用activity生命周期的函数
r.activity.mCalled = false;
//这就就是具体调用activity的performPause的地方
//(包括mFragments.dispatchPause、activity的onPause,
//application的ActivityLifecycleCallback生命周期回调方法onActivityPaused),
//运行完之后mCalled会设置成true
mInstrumentation.callActivityOnPause(r.activity);
//写event log,am_on_paused_called,说明pause已经调用
EventLog.writeEvent(LOG_AM_ON_PAUSE_CALLED, UserHandle.myUserId(),
r.activity.getComponentName().getClassName(), reason);
//...
//运行了之后设置标致位paused==true
r.paused = true;
}
到目前为止基本上把上一个activity的OnPause流程讲解完了。
6. 进程启动(一)am_proc_start
讲了一大堆,是不是发现我们需要启动的进程test2怎么还没到呢,流程有点长,目前android的默认架构就是这样,大家耐心的继续看下去,我们这一章节就开始讲到进程启动(这部分应该很多文章都有提到,了解的同学可以不必细看)。
其实这些流程只是学习作用,对我们了解android架构有一定帮助,解决问题(仅针对那些代码不规范自己改出来的问题)时有帮助,不过这些都不是关注的重点,我们关注的是如何优化整个流程,如果没有明确这个目的,对我们来说是没有很大提升的。路漫漫其修远,我们先把流程梳理清楚,一步步来…
图6.1 进程启动(一)
6.1 activityPaused(ActivityManagerService.java)
在章节5.5中的
ActivityManagerNative.getDefault().activityPaused(token)
,这个函数的意思是告诉AMS,上一个应用已经完成OnPause了,接下去的工作可以继续下去。
public final void activityPaused(IBinder token) {
//...
//调用的是ActivityStack的activityPausedLocked,第二个参数timeout==false
stack.activityPausedLocked(token, false);
//...
}
其中token是上一个应用的Ibinder对象,我们认为是launcher就行了
6.2 activityPausedLocked(ActivityStack.java)
1) 通知launcher自身Stack栈中的activityPausedLocked,当前已经完成pause暂停操作了,可以将之前章节5.4中说的PAUSE_TIMEOUT_MSG超时去掉。
2) mPausingActivity也是在章节5.4开始暂停的时候设置的,如果发现真正暂停的应用和完成暂停的应用是一个,代表暂停完成,调用completePauseLocked,并传递resumeNext==true,代表需要resume下一个应用
//AMS调用的timeout==false
final void activityPausedLocked(IBinder token, boolean timeout) {
//代表该task仍在堆栈中,此时launcher是launcher的paused
final ActivityRecord r = isInStackLocked(token);
if (r != null) {
//pause已经完成,不需要PAUSE_TIMEOUT_MSG了
mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
//之前在startPausingLocked的时候设置了当前pause的应用,
//这个时候AMS返回代表pause成功,会进入这里
if (mPausingActivity == r) {
//pause成功,传递的参数是resumeNext==true,代表需要resume下一个应用
completePauseLocked(true);
return;
} else {
...
}
6.3 completePauseLocked(true)
1) mWaitingVisibleActivities这里代表的是需要隐藏的可视界面,到目前为止我们没有设置过,这个是在第二次进入章节5.2 resumeTopActivityInnerLocked的时候才会设置。(准备resume恢复下一个应用test2,上一个应用launcher就会放入等待隐藏的列表mWaitingVisibleActivities中)
2) 非睡眠或者关机状态的时候会进入下一个activity的resume操作resumeFocusedStackTopActivityLocked
3) 最后ensureActivitiesVisibleLocked(ActivityStackSupervisor.java/ActivityStack.java)会更新界面相关操作,属于WMS范畴,本文不过多涉及
{
//启动进程后会更新界面,此处仅仅把流程列出来,由于这篇文章本身太长了,不想在额外增加内容
ensureActivitiesVisibleLocked
->ensureActivityConfigurationLocked
->makeVisibleAndRestartIfNeeded->startSpecificActivityLocked()
->screenshotActivitiesLocked
->makeInvisible->addToStopping->scheduleIdleLocked
}
private void completePauseLocked(boolean resumeNext) {
//prev,mPausingActivity是launcher
ActivityRecord prev = mPausingActivity;
//prev是不等于null的会进来这里
if (prev != null) {
//state在startPausingLocked时设置了ActivityState.PAUSING,
//所以一般情况wasStopping都是false
final boolean wasStopping = prev.state == ActivityState.STOPPING;
//重新设置标志位是ActivityState.PAUSED,这个是已经暂停的状态
prev.state = ActivityState.PAUSED;
//一般情况launcher启动应用,prev.finishing==false,故不会进入这里面
if (prev.finishing) {
//...
//prev.app是launcher
} else if (prev.app != null) {
//pause com.android.launcher时,此处会进来,prev就是com.android.launcher,
//wasStopping==false,visible==true
//第一次进来时mWaitingVisibleActivities还没有prev(resumeTopActivityInnerLocked
//第二次运行是才会设置),故不会进来这个
if (mStackSupervisor.mWaitingVisibleActivities.remove(prev)) {
//...
}
//这个是在pause之后重新启动,一般都是false
if (prev.deferRelaunchUntilPaused) {
//...
//wasStopping==false,也不走这里
} else if (wasStopping) {
//...
//由于visible==true,也不是在睡眠状态,这里也不会进来
} else if ((!prev.visible && !hasVisibleBehindActivity())
|| mService.isSleepingOrShuttingDownLocked()) {
//...
}
} else {
//这里实在app在onpause过程中died掉才会进入,正常不会运行
prev = null;
}
if (prev != null) {
//如果界面是冻屏的话,由于界面不再可见,将移除冻屏状态
prev.stopFreezingScreenLocked(true /*force*/);
}
//mPausingActivity设置为null,此时pause已经全部完成
mPausingActivity = null;
}
//上面都是AMS进来的activityPausedLocked,resumeNext == true
if (resumeNext) {
//之前的moveActivityStackToFront中有设置过focus stack为test2
final ActivityStack topStack = mStackSupervisor.getFocusedStack();
//非睡眠或者关机会进入这里
if (!mService.isSleepingOrShuttingDownLocked()) {
//一般进入这里,会resume 下一个应用(next),
//同步的,执行了Process.start之后才会继续往下跑
mStackSupervisor.resumeFocusedStackTopActivityLocked(topStack, prev, null);
} else {
...
}
if (prev != null) {
//重新恢复接收输入事件
prev.resumeKeyDispatchingLocked();
//如果是在使用电池
if (prev.app != null && prev.cpuTimeAtResume >
&& mService.mBatteryStatsService.isOnBattery()) {
//cpuTimeAtResume是在activity resume的时候设置的,
//代表从resume到pause的时间,将作为前台运行时间
long diff = mService.mProcessCpuTracker.getCpuTimeForPid(prev.app.pid)
- prev.cpuTimeAtResume;
//...
//addForegroundTimeLocked这个是电量估算的时候用的,判断该activity前台运行的时常
if (ps != null) {
ps.addForegroundTimeLocked(diff);
//...
}
//当前已经是onpause暂停了,清空进入resume的时间
prev.cpuTimeAtResume = ;
}
//有界面可视的时候mAppVisibilitiesChangedSinceLastPause==true(setVisible时设置),
//所以这里会进来
if (mStackSupervisor.mAppVisibilitiesChangedSinceLastPause) {
//...
//launcher已经pause,设置mAppVisibilitiesChangedSinceLastPause==false
mStackSupervisor.mAppVisibilitiesChangedSinceLastPause = false;
}
//最后是更新显示界面,这里是第一次调用ensureActivitiesVisibleLocked,
//遍历所有stack的ensureActivitiesVisibleLocked
mStackSupervisor.ensureActivitiesVisibleLocked(null, , !PRESERVE_WINDOWS);
}
6.4 resumeFocusedStackTopActivityLocked/startSpecificActivityLocked(ActivityStackSupervisor.java)
resumeFocusedStackTopActivityLocked在章节5.1-5.2已经看过,此处传递的targetStack是test2,pre是launcher,resumeFocusedStackTopActivityLocked(ActivityStackSupervisor.java) -> resumeTopActivityUncheckedLocked(ActivityStack.java) -> resumeTopActivityInnerLocked -> startSpecificActivityLocked(ActivityStackSupervisor.java),启动的是next==test2
这里就不翻回去讲了,接下去讲
startSpecificActivityLocked(ActivityStackSupervisor.java)
这个启动应用的函数(注意此处是第一次进入,章节6.3提到的那一次是第二次进入,是在之后)
//r==test2,andResume==true,checkConfig==true
void startSpecificActivityLocked(ActivityRecord r,
boolean andResume, boolean checkConfig) {
//...
//当进程都未启动时不走这里,thread肯定是null,热启动相关逻辑本次不讨论
if (app != null && app.thread != null) {
...
}
//AMS中去启动进程
mService.startProcessLocked(r.processName, r.info.applicationInfo, true, ,
"activity", r.intent.getComponent(), false, false, true);
}
6.5 startProcessLocked(ActivityManagerService.java)
重要看到startProcessLocked启动进程相关名字,这个是AMS的启动进程的api。
先关注第一次进入的逻辑:
1) 新建一个进程对象的实例new ProcessRecord,该对象可以代表一个进程
2) 判断应用是32位还是64位的,用于虚拟机参数配置
3) Process.start进程启动
4) event log写入am_proc_start,代表进程已经启动,这句话出来的时候应用进程已经创建
//9个参数(r.processName==test2, r.info.applicationInfo, true, 0,
//"activity", r.intent.getComponent(), false, false, true)
final ProcessRecord startProcessLocked(String processName,
ApplicationInfo info, boolean knownToBeDead, int intentFlags,
String hostingType, ComponentName hostingName, boolean allowWhileBooting,
boolean isolated, boolean keepIfLarge) {
//注意此处entryPoint==null
return startProcessLocked(processName, info, knownToBeDead, intentFlags, hostingType,
hostingName, allowWhileBooting, isolated, /* isolatedUid */, keepIfLarge,
null /* ABI override */, null /* entryPoint */, null /* entryPointArgs */,
null /* crashHandler */);
}
//14个参数,新建ProcessRecord
final ProcessRecord startProcessLocked(String processName, ...) {
long startTime = SystemClock.elapsedRealtime();
ProcessRecord app;
//isolated(孤立应用)是false,knownToBeDead是true
if (!isolated) {
//第一次进来app肯定是null
app = getProcessRecordLocked(processName, info.uid, keepIfLarge);
//...
//设置了后台运行,桌面启动应用一般都不会走这里
if ((intentFlags & Intent.FLAG_FROM_BACKGROUND) != ) {
...
} else {
//重新计算崩溃次数(crash大于等于2次服务将不会再启动)
mAppErrors.resetProcessCrashTimeLocked(info);
//...
}
}
//这个是用来设置启动进程时cpu的策略,可以加快app启动速度
//默认没有用到,需要设置USE_SCHED_BOOST才会生效
nativeMigrateToBoost();
//3s钟后会关闭启动进程的cpu策略,同样此处默认没有用到
mHandler.sendMessageDelayed(msg, APP_BOOST_MESSAGE_DELAY);
//第一次进入时没有启动过app/thread是null,pid是没有的.
//第二次进来时此处app是有了,pid也生成了,但是thread还没有
//第一次没启动不走这里,第二次会进来
if (app != null && app.pid > ) {
//knownToBeDead是true,第二次进来app.thread还是null,故会进来,
//第二次是从章节6.3中ensureActivitiesVisibleLocked调用过来的
if ((!knownToBeDead && !app.killed) || app.thread == null) {
//第二次进程已经创建了,直接返回
//...
return app;
}
//...
}
//...
//第一次走这里,app是null
if (app == null) {
//这个是google的,用于调试卡顿的,不过除了特别有问题一般情况不会出现问题,
//50ms去掉系统或许更快,如果是给用户的稳定版本可以考虑把这段调试代码删除
checkTime(startTime, "startProcess: creating new process record");
//此处是new ProcessRecord
app = newProcessRecordLocked(info, processName, isolated, isolatedUid);
//...
//新建ProcessRecord完成,该监控操作(newProcessRecordLocked)完成
checkTime(startTime, "startProcess: done creating new process record");
}
//监控进程启动的时常是否超时
checkTime(startTime, "startProcess: stepping in to startProcess");
//这里才是真正的启动进程的地方
startProcessLocked(
app, hostingType, hostingNameStr, abiOverride, entryPoint, entryPointArgs);
checkTime(startTime, "startProcess: done starting proc!");
//如果有pid产生代表进程创建完成
return (app.pid != ) ? app : null;
}
//真正启动进程的地方
private final void startProcessLocked(ProcessRecord app, String hostingType,
String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
//...
if (app.pid > && app.pid != MY_PID) {//第一次启动app.pid == -1,不走这里
...
}
//...
updateCpuStats();//启动进程也会更新CPU状态
try {
try {
//用于检测是否可以启动,如:是否安装,是否正在冻屏等
AppGlobals.getPackageManager().checkPackageStartable(app.info.packageName, userId);
}
//isolated初始值是false
if (!app.isolated) {
//...
//返回应用用户组的gid,如果是uid不一样,同一个应用该值也会不一样
permGids = pm.getPackageGids(app.info.packageName,
MATCH_DEBUG_TRIAGED_MISSING, app.userId);
MountServiceInternal mountServiceInternal = LocalServices.getService(
MountServiceInternal.class);
//获取应用读写外部存储的权限
//如果是孤立应用(uid是99000-99999)将返回MOUNT_EXTERNAL_NONE;
//能读返回MOUNT_EXTERNAL_READ,能写返回MOUNT_EXTERNAL_WRITE
mountExternal = mountServiceInternal.getExternalStorageMountMode(uid,
app.info.packageName);
//...
}
//...
//android:multiArch="true"代表所有架构都支持,一般都不设置,
//一般应用库文件需要判断是否32位还算64位,判断方法使用
//com_android_internal_content_NativeLibraryHelper.cpp的findSupportedAbi
//requiredAbi就是为了兼容32位&64位系统设计的
String requiredAbi = (abiOverride != null) ? abiOverride : app.info.primaryCpuAbi;
if (requiredAbi == null) {
//此处如果应用没有设置实在32位还是64位运行的化,
//默认使用属性值ro.product.cpu.abilist的第一个值arm64-v8a(64bit),
//armeabi-v7a(32bit),armeabi(32bit)
requiredAbi = Build.SUPPORTED_ABIS[];
}
String instructionSet = null;
if (app.info.primaryCpuAbi != null) {
//通过应用的库文件获取虚拟机要使用那种参数
instructionSet = VMRuntime.getInstructionSet(app.info.primaryCpuAbi);
}
//上面传递的entryPoint==null,isActivityProcess==true
boolean isActivityProcess = (entryPoint == null);
//将ActivityThread作为应用默认的入口函数entryPoint
if (entryPoint == null) entryPoint = "android.app.ActivityThread";
//此处才是调用Process.start启动进程的地方
Process.ProcessStartResult startResult = Process.start(entryPoint,
app.processName, uid, uid, gids, debugFlags, mountExternal,
app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,
app.info.dataDir, entryPointArgs);//此处才是调用Process.start启动进程的地方
//此处就是event log中am_proc_start
EventLog.writeEvent(EventLogTags.AM_PROC_START,
UserHandle.getUserId(uid), startResult.pid, uid,
app.processName, hostingType,
hostingNameStr != null ? hostingNameStr : "");
//设置进程的pid
app.setPid(startResult.pid);
//一般usingWrapper==false
app.usingWrapper = startResult.usingWrapper;
//代表正在运行
app.removed = false;
app.killed = false;
//代表没有给AMS杀死
app.killedByAm = false;
synchronized (mPidsSelfLocked) {
//process start之后就会有pid了,此处是test2.com.myapplication的pid会生成
//会将该pid放入AMS的pid列表中
this.mPidsSelfLocked.put(startResult.pid, app);
if (isActivityProcess) {//isActivityProcess==true
//10s没有启动将不再启动,该app,Process.start虚拟机进程创建是同步的,
//但是attachApplicationLocked是异步的,在attachApplication的时候
//会remove这个超时PROC_START_TIMEOUT_MSG
mHandler.sendMessageDelayed(msg, startResult.usingWrapper
? PROC_START_TIMEOUT_WITH_WRAPPER : PROC_START_TIMEOUT);
...
}
7. 进程启动(二)Process.start
Process.start这个是新建进程通用的系统方法,代码位置:
frameworks/base/core/java/android/os/Process.java。
接下去从这个开始,这里面大家熟悉的内容可能更多。
图7.1 进程启动(二)
7.1 Process.start(Process.java)
我们注意传递的参数processClass是android.app.ActivityThread,niceName是processName,debugFlags一般都是等于0,mountExternal代表是否可读写外部存储,targetSdkVersion是这个应用的targetSdkVersion,seInfo是签名相关(默认是”default”),abi是这个应用要运行的cpu架构(32还是64位),instructionSet是指的是arm或者arm64,appDataDir一般指的是/data这个目录,zygoteArgs==null。
后面这些参数都会有用到,对于理解流程有很大的帮助。
//processClass是android.app.ActivityThread,niceName是processName,
//debugFlags一般都是等于0,mountExternal代表是否可读写外部存储,
//targetSdkVersion是这个应用的targetSdkVersion,seInfo是签名相关(默认是”default”),
//abi是这个应用要运行的cpu架构(32还是64位),instructionSet是指的是arm或者arm64,
//appDataDir一般指的是/data这个目录,zygoteArgs==null
public static final ProcessStartResult start(final String processClass,
final String niceName,
int uid, int gid, int[] gids,
int debugFlags, int mountExternal,
int targetSdkVersion,
String seInfo,
String abi,
String instructionSet,
String appDataDir,
String[] zygoteArgs) {
try {
//通过虚拟机来创建新的进程
return startViaZygote(processClass, niceName, uid, gid, gids,
debugFlags, mountExternal, targetSdkVersion, seInfo,
abi, instructionSet, appDataDir, zygoteArgs);
//...
}
7.2 startViaZygote-> zygoteSendArgsAndGetResult
1) startViaZygote通将参数全部转化成Zygote的数组String
2) openZygoteSocketIfNeeded/zygoteSocket.connect创建Socket链接,并获取输入输出流对象
3) zygoteSendArgsAndGetResult通过Socket与底层交互,传递相应的事件内容,并获取返回的结果
private static ProcessStartResult startViaZygote(final String processClass,
//...
ArrayList<String> argsForZygote = new ArrayList<String>();
//...添加虚拟机参数
//最后添加的是ActivityThread应用的入口类
argsForZygote.add(processClass);
//extraArgs==null,所以后面没有参数了
if (extraArgs != null) {
for (String arg : extraArgs) {
argsForZygote.add(arg);
}
}
//注意openZygoteSocketIfNeeded是connect Socket,
//zygoteSendArgsAndGetResult是向Socket传递参数
return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);
}
private static ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx {
if (primaryZygoteState == null || primaryZygoteState.isClosed()) {
try {
//ZYGOTE_SOCKET的名字是"zygote",连接socket
primaryZygoteState = ZygoteState.connect(ZYGOTE_SOCKET);
//...
}
public static ZygoteState connect(String socketAddress) throws IOException {
//...
try {
//这里是connect的地方,会通知相应的链接对象
zygoteSocket.connect(new LocalSocketAddress(socketAddress,
LocalSocketAddress.Namespace.RESERVED));
//输入流,是用来读东西的,例如设备有数据输出,然后我们读取
zygoteInputStream = new DataInputStream(zygoteSocket.getInputStream());
//输出流是用来写东西的,例如写东西然后输出到什么位置
zygoteWriter = new BufferedWriter(new OutputStreamWriter(
zygoteSocket.getOutputStream()), );
//...
}
private static ProcessStartResult zygoteSendArgsAndGetResult(
ZygoteState zygoteState, ArrayList<String> args)
throws ZygoteStartFailedEx {
try {
//...
//第一个先写的是参数大小
writer.write(Integer.toString(args.size()));
writer.newLine();
for (int i = ; i < sz; i++) {
String arg = args.get(i);
//传递设置参数
writer.write(arg);
writer.newLine();
}
//清空输出流,并写入,运行完成之后代表写入成功,此时Socket会接受到相应消息
writer.flush();
//...
//读取返回的pid数据
result.pid = inputStream.readInt();
//读取返回的usingWrapper数据
result.usingWrapper = inputStream.readBoolean();
...
}
7.3 ZygoteInit.main(ZygoteInit.java)
1) 开机运行app_process进程(init.zygote*.rc->app_process)->app_main.main->ZygoteInit.main,Zygote受精卵进程是由init进程创建,如下通过ps可知:init进程是Zygote64受精卵进程的父进程,而system_server是通过zygote64受精卵进程创建的。(pid是该进程的id,ppid是其父进程的id)
USER PID PPID VSIZE RSS WCHAN PC NAME
root SyS_epoll_ S /init
root poll_sched S zygote64 //此处代表是64bit的
system SyS_epoll_ S system_server
2) 获取当前操作系统的32&64位架构abiList,这个在socket connect的时候用于
2) 注册zygote的LocalServerSocket对象(Socket的服务端,可以给别人connect)
3) 启动系统服务startSystemServer
4) 等待Socket消息的通知来执行相应的任务runSelectLoop
5) MethodAndArgsCaller的run方法
//开机运行app_process进程(init.zygote*.rc->app_process)->app_main.main->ZygoteInit.main
public static void main(String argv[]) {
//...
try {
//Socket的名字是zygote
String socketName = "zygote";
String abiList = null;
for (int i = ; i < argv.length; i++) {
//第一次进来会设置startSystemServer==true
if ("start-system-server".equals(argv[i])) {
startSystemServer = true;
} else if (argv[i].startsWith(ABI_LIST_ARG)) {
//读的是系统属性ro.product.cpu.abilist64或者ro.product.cpu.abilist32里面的值
abiList = argv[i].substring(ABI_LIST_ARG.length());
//...
//android的Socket名字:ANDROID_SOCKET_ + zygote
registerZygoteSocket(socketName);
//event log中会出现boot_progress_preload_start
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
SystemClock.uptimeMillis());
//重新加载Cache,Classes,Resources,OpenGL,SharedLibraries,
//TextResources,WebView,AndroidKeyStoreProvider
preload();
//event log中会出现boot_progress_preload_end
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
SystemClock.uptimeMillis());
//...
//做GC,清除一些软引用对象
gcAndFinalize();
//...
//在初始化时unmount根目录"/storage"
Zygote.nativeUnmountStorageOnInit();
//允许zygote创建进程
ZygoteHooks.stopZygoteNoThreadCreation();
//如果需要启动系统服务则进入这里
if (startSystemServer) {
//启动系统服务system_server,先后调用fork顺序是init
//->zygote64(64位系统)->system_server,如果是系统进程的话,
//这里是永远不会返回的startSystemServer->handleSystemServerProcess
//->RuntimeInit.zygoteInit->SystemServer.main/run->Looper.loop()
//->(pollInner/epoll_wait)Looper.cpp,
//这个除了Loop里面调用mQueue.quit是不会退出的
startSystemServer(abiList, socketName);
}
//会跑下来的是zygote进程,zygote进程会一直在此运行
runSelectLoop(abiList);
closeServerSocket();
} catch (MethodAndArgsCaller caller) {
//对于此处zygote frok的子进程会进入此处,抛出MethodAndArgsCaller异常,
//会执行run方法,其实是反射调用ActivityThread.main,这个后面会讲到
caller.run();
//...
}
ps: Zygote进程是用来fork各个子进程的,如system_server就是其创建的,其中zygote64是所有64位进程的父进程,zygote是所有32位进程的父进程。
7.4 runSelectLoop
runSelectLoop循环等待Socket的数据反馈,这里写的是Select的Loop,目前androidN使用的方法是Os.poll不再有1024个Socket的限制(androidL和之前的版本使用的是select方法),后续android版本升级的话可能使用epoll(目前上层的Looper、MessageQueue就是使用epoll)
1) 循环遍历等待Socket缓冲区有可读的数据
2) Socket.connect时会创建新的ZygoteConnection
3) ZygoteConnection执行runOnce
4) 创建子进程后,子进程退出循环,父进程继续等待下一个Socket数据
private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {
//...
// sServerSocket是AMS Process.java中的ZYGOTE_SOCKET链接的对象, 用来创建进程
//sServerSocket是LocalServerSocket,代表整个socket
//fds是所有zygote Socket相关的文件描述符
fds.add(sServerSocket.getFileDescriptor());
//peers是ZygoteConnection对象,是zygote链接之后的对象
peers.add(null);
while (true) {
//...
//events代表等待的事件类型,POLLIN类型代表我们只关心缓冲区是否有数据可读
pollFds[i].events = (short) POLLIN;
//...
try {
//poll函数与select类似都是,可以监视多个描述符,-1代表永不超时,
//轮询一遍之后等待,当设备驱动发生自身资源可读写后,会唤醒其等待队列上睡眠的进程
Os.poll(pollFds, -);
}
//...
for (int i = pollFds.length - ; i >= ; --i) {
//revents域是文件描述符的操作结果事件掩码,POLLIN代表有数据可读
if ((pollFds[i].revents & POLLIN) == ) {
continue;
}
//i==0是就是外部有创建socket的时候,如Socket.connect,
//这个时候Os.poll中LocalServerSocket会有数据返回,
//此时LocalServerSocket会accept并创建新的ZygoteConnection
if (i == ) {
//创建新的受精卵的Socket链接ZygoteConnection
ZygoteConnection newPeer = acceptCommandPeer(abiList);
//添加到ZygoteConnection数组peers
peers.add(newPeer);
//添加到zygote Socket相关的文件描述符数组中去
fds.add(newPeer.getFileDesciptor());
//非第一次运行时,如果之前创建的Socket链接对象ZygoteConnection有数据可以读,
//如OutputStream(zygoteWriter就是输出流)有写入,那么此处会有数据,
//进入runOnce函数。
} else {
//创建子进程会抛出MethodAndArgsCaller的异常,
//给ZygoteInit.main捕获,然后运行ActivityThread的main函数,
//子进程抛出异常后退出该循环,但是Zygote父进程还算会继续循环的
boolean done = peers.get(i).runOnce();
//创建子进程后,父进程也就是zygote进程才会进入这里
//...
}
}
}
}
runSelectLoop函数就是在监听Socket端是否有数据可以读,如果有数据来了,那么就是创建进程,这个Zygote进程主要作用就是创建进程(子进程的一些基本信息都不用再初始化,因为Zygote已经初始过了,相当于优化了启动进程的流程)。
7.5 runOnce(ZygoteConnection.java)
1) 读取相应的参数列表
2) 创建子进程forkAndSpecialize(Zygote.forkAndSpecialize -> com_android_internal_os_Zygote_nativeForkAndSpecialize/ForkAndSpecializeCommon/fork(com_android_internal_os_Zygote.cpp)),通过jni调用com_android_internal_os_Zygote_nativeForkAndSpecialize,最后调用的是fork函数,该函数用于创建进程,具体在这里不展开,具体可以参考之前的一篇文章
Android上层如何调用一个底层函数
的章节
2.1.3 com_android_internal_os_Zygote.cpp本地函数
里面有关于fork的讲解。最终子进程返回的是pid==0,父进程返回的是子进程的pid。
3) 处理父进程的内容handleParentProc,如返回给AMS章节6.5中startProcessLocked的Process.start,其值是Process.ProcessStartResult startResult,包含子进程pid
4) 处理子进程的内容handleChildProc,这个放在下一节讲解
boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {
...
try {
//读取相应的参数列表
args = readArgumentList();
descriptors = mSocket.getAncillaryFileDescriptors();
}
//...
//invokeWith==null,目前没有设置
if (parsedArgs.invokeWith != null) {
//...
}
//...
int [] fdsToClose = { -, - };
FileDescriptor fd = mSocket.getFileDescriptor();
if (fd != null) {
//客户端的文件描述符
fdsToClose[] = fd.getInt$();
}
fd = ZygoteInit.getServerSocketFileDescriptor();
if (fd != null) {
//服务端的文件描述符
fdsToClose[] = fd.getInt$();
}
//调用native fork进程的地方
//此处是fock进程(Zygote.forkAndSpecialize
//->com_android_internal_os_Zygote_nativeForkAndSpecialize
//->ForkAndSpecializeCommon/fork(com_android_internal_os_Zygote.cpp))
pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
parsedArgs.niceName, fdsToClose, parsedArgs.instructionSet,
parsedArgs.appDataDir);
//...
try {
//如果是子进程pid会等于0,父进程此处pid会返回子进程的pid
if (pid == ) {
//...
//处理子进程逻辑
handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);
//子进程是永远不会到这个位置来的,因为之前已经抛出MethodAndArgsCaller异常
return true;
} else {
//...
//处理父进程逻辑
return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs);
}
...
}
private String[] readArgumentList()
throws IOException {
//...
try {
//读取第一个参数
String s = mSocketReader.readLine();
//第一个参数上面章节7.2 Process.java中zygoteSendArgsAndGetResult写的就是参数个数
argc = Integer.parseInt(s);
}
//传递的参数最多是1024个,超过的话系统可能受到DOS攻击
if (argc > MAX_ZYGOTE_ARGC) {
throw new IOException("max arg count exceeded");
}
for (int i = ; i < argc; i++) {
//读出每一个参数返回result数组中去
result[i] = mSocketReader.readLine();
...
}
private boolean handleParentProc(int pid,
FileDescriptor[] descriptors, FileDescriptor pipeFd, Arguments parsedArgs) {
if (pid > ) {
//如果返回的pid大于0,说明子进程创建成功,此时设置子进程的pid
setChildPgid(pid);
}
//...
try {
//传递pid回去,最后写入章节7.2中zygoteSendArgsAndGetResult的result.pid
mSocketOutStream.writeInt(pid);
//传递是否wrapped进程,此处一般都是false
mSocketOutStream.writeBoolean(usingWrapper);
}
//...
return false;
}
8. 绑定进程am_proc_bound
上一章节我们知道了Process.start用于创建进程,父进程会直接返回子进程的pid,那么接下去我们需要从子进程处理的内容开始分析,看看子进程是怎样关联到上层的application中去的,这里讲解第一步am_proc_bound
图8.1 绑定进程
8.1 handleChildProc(ZygoteConnection.java)
1) 关闭相应的子进程Socket链接
2) 设置进程的名字,这个时候通过ps就可以看到进程名字变成应用声明的进程(如果没有定义
android:process
那么默认该进程名字就是应用的包名)
3) RuntimeInit.zygoteInit子进程的初始化
private void handleChildProc(Arguments parsedArgs,
FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr)
throws ZygoteInit.MethodAndArgsCaller {
//关闭自己的Socket
closeSocket();
//关闭ZygoteInit中服务端的Socket
ZygoteInit.closeServerSocket();
//...
if (parsedArgs.niceName != null) {
//自己设置自己的名字,此处设置进程名字为之前传进来的processName
Process.setArgV0(parsedArgs.niceName);
}
//这里是不运行的
if (parsedArgs.invokeWith != null) {
//...
//此处会进来
} else {
//运行初始化RuntimeInit中的进程(受精卵)初始化zygoteInit
RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion,
parsedArgs.remainingArgs, null /* classLoader */);
}
}
ps:Process.setArgV0会通过prctl(PR_SET_NAME…),裁剪后(process_name.c),只保留processName后面15个字符(kernel实际还会裁剪到最后一个字符,其实是14个字符),设置进程名字(内核标识进程的名字是task_struc->comm).
进程的名字在某些地方显示不是无限长的,如在systrace显示的进程名字就不超过15个字符。
8.2 zygoteInit(RuntimeInit.java)
1) log重定向redirectLogStreams
2) 通用设置初始化commonInit
3) 初始化zygote:nativeZygoteInit
4) 应用初始化applicationInit
public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
throws ZygoteInit.MethodAndArgsCaller {
//重新定向log的输入地方,此处设置log输出到Android log中
redirectLogStreams();
//一些通用设置的初始化
commonInit();
//初始化zygote,这里AppRuntime继承的是AndroidRuntime,运行的是启动线程池startThreadPool
nativeZygoteInit();
//应用初始化,此处是接下来运行的地方
applicationInit(targetSdkVersion, argv, classLoader);
}
private static final void commonInit() {
//...
//设置默认的异常捕获
Thread.setDefaultUncaughtExceptionHandler(new UncaughtHandler());
TimezoneGetter.setInstance(new TimezoneGetter() {
@Override
public String getId() {
//设置时区id
return SystemProperties.get("persist.sys.timezone");
}
});
//设置时区
TimeZone.setDefault(null);
LogManager.getLogManager().reset();
//Android log相关初始化
new AndroidConfig();
String userAgent = getDefaultUserAgent();
//网络用户代理初始化
System.setProperty("http.agent", userAgent);
//网络Socket相关
NetworkManagementSocketTagger.install();
//...
initialized = true;
}
8.3 applicationInit
1) 设置虚拟机GC回收比例,正在使用的对象/堆栈大小 = 0.75
2) 设置虚拟机sdk的版本号
3) 获取相应的参数,如args.startClass就是在章节7.2 startViaZygote设置的processClass(ActivityThread)
4) 通过反射查找ActivityThread的main函数,并将其作为MethodAndArgsCaller异常的参数
private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
throws ZygoteInit.MethodAndArgsCaller {
//设置退出时不调用onExit()函数
nativeSetExitWithoutCleanup(true);
//设置GC回收后的比例,正在使用的对象/堆栈大小 = 0.75,对应于dalvik.vm.heaptargetutilization
VMRuntime.getRuntime().setTargetHeapUtilization(f);
//设置sdk的版本号,这个是进程启动Process.start时就传递过来的
VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
//获取相应的参数,如args.startClass就是第一个非"--"开头的参数
final Arguments args;
try {
args = new Arguments(argv);
}
//...
//反射调用main函数,注意startClass是Process.start时传递进来的android.app.ActivityThread
invokeStaticMain(args.startClass, args.startArgs, classLoader);
}
private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)
throws ZygoteInit.MethodAndArgsCaller {
//...
//查找android.app.ActivityThread类
cl = Class.forName(className, true, classLoader);
//...
//查找其中的main函数
m = cl.getMethod("main", new Class[] { String[].class });
//...
//获取函数的调用属性
int modifiers = m.getModifiers();
//必须是静态而且是public的方法,否则抛出RuntimeException异常
if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
throw new RuntimeException(
"Main method is not public and static on " + className);
}
//抛出MethodAndArgsCaller异常
throw new ZygoteInit.MethodAndArgsCaller(m, argv);
}
在章节7.3 ZygoteInit.main方法里面有捕获MethodAndArgsCaller异常,并调用MethodAndArgsCaller的run方法。
8.4 MethodAndArgsCaller.run()
反射调用ActivityThread的main静态函数
public static class MethodAndArgsCaller extends Exception
implements Runnable {
//...
public MethodAndArgsCaller(Method method, String[] args) {
//mMethod是ActivityThread的main方法
mMethod = method;
//mArgs一般都是null
mArgs = args;
}
public void run() {
try {
//调用方法method,传递的是args参数,传递第一个参数是类对象为null,代表静态函数
mMethod.invoke(null, new Object[] { mArgs });
//...
到这里进程已经启动完成,将进入应用相关流程
8.5 MethodAndArgsCaller.run()
1) 消息队列初始化Looper.prepareMainLooper
2) 新建ActivityThread并附着thread.attach
3) 进入消息队列的循环Looper.loop
public static void main(String[] args) {
//默认是没有用到SamplingProfilerIntegration的,
//该类用于监听性能数据,包含进程名字、应用信息、线程启动与关闭,
//还有默认persist.sys.profiler_ms毫秒dump一次该进程堆栈信息
SamplingProfilerIntegration.start();
//在严格模式或者调试的时候打开,默认不打卡
CloseGuard.setEnabled(false);
//初始化环境(这里主要是存储设备的环境,用user id初始化)
Environment.initForCurrentUser();
//主要是libcore中使用event log的方法,Reporter的report类似于EventLog.writeEvent
EventLogger.setReporter(new EventLoggingReporter());
//配置文件目录在/data/misc/user/1000
final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
//设置认证相关的目录cacerts-added,cacerts-removed
TrustedCertificateStore.setDefaultUserDirectory(configDir);
//设置进程名字为<pre-initialized>,这个很快在handleBindApplication时就会给修改
Process.setArgV0("<pre-initialized>");
//消息队列初始化,主进程是不允许退出的,无法调用MessageQueue.quit退出
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
//新建一个ActivityThread并attach附着,这个跟接下去的attachApplication相关
thread.attach(false);
if (sMainThreadHandler == null) {
//获取thread的handler,将其作为应用的主线程
sMainThreadHandler = thread.getHandler();
}
if (false) {
//用户调试log,用于消息队列Message的事件分发log输出,
//调试消息队列的时候可以打开
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
//Looper.loop()里面是个for (;;)死循环,只要Message不为null,会一直运行
//Looper.loop() -> MessageQueue.next()
//-> nativePollOnce(android_os_MessageQueue.cpp)
//->(pollOnce/pollInner/epoll_wait) Looper.cpp,
//这个Message==null情况只有调用MessageQueue.quit才会发生,
//目前没有看到主动调用MessageQueue.quit,故这个消息队列循环是不会退出的
Looper.loop();
//如果进入到这里代表程序出错了,这里程序正常运行是不会进来的
throw new RuntimeException("Main thread loop unexpectedly exited");
}
在调用静态方法ActivityThread.main之后会新建一个ActivityThread对象,相当于该进程的主线程(UI线程),创建之后首先跑的就是ActivityThread的attach函数
8.6 attach
这里我们主要关注attachApplication,也就是AMS的应用附着即可
private void attach(boolean system) {
//...
//是否system,应用启动肯定不是system,会进入此处
if (!system) {
//...
//设置ddms中的进程名字为"<pre-initialized>",临时的
android.ddm.DdmHandleAppName.setAppName("<pre-initialized>", UserHandle.myUserId());
//设置ApplicationObject为ActivityThread
RuntimeInit.setApplicationObject(mAppThread.asBinder());
final IActivityManager mgr = ActivityManagerNative.getDefault();
try {
//此处就是attachApplication
mgr.attachApplication(mAppThread);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
//Java允许在类中定义一个名为finalize()的方法。
//它的工作原理是:一旦垃圾回收器准备好释放对象占用的存储空间,将首先调用其finalize()方法。
//并且在下一次垃圾回收动作发生时,才会真正回收对象占用的内存
//BinderInternal里面实现的是Object finalize,
//当资源释放的时候会调用finalize,然后会调用
BinderInternal.addGcWatcher(new Runnable() {
//ActivityThread对象没有再使用时会进行回收
@Override public void run() {
if (!mSomeActivitiesChanged) {
return;
}
Runtime runtime = Runtime.getRuntime();
//这个是HeapGrowthLimit,正常应用虚拟机内存最大值dalvik.vm.heapgrowthlimit,
//AndroidRuntime.cpp/runtime.cc/heap.cc
long dalvikMax = runtime.maxMemory();
long dalvikUsed = runtime.totalMemory() - runtime.freeMemory();
//当前使用内存,如果最大内存的3/4将进行activity的释放操作
if (dalvikUsed > ((*dalvikMax)/)) {
//...
mSomeActivitiesChanged = false;
try {
//此处释放指的是activity的ondestroy,
//目前可以destroy的activity是处于onstop状态的activity
mgr.releaseSomeActivities(mAppThread);
//...
//让DropBox在libcore可用
DropBox.setReporter(new DropBoxReporter());
}
8.7 attachApplication/attachApplicationLocked
1) 首先是ActivityManagerNative.java的attachApplication会传递ActivityThread和调用者的pid给到AMS的attachApplicationLocked
2) eventlog中设置服务绑定进程am_proc_bound,说明进程启动完成,而且该进程的主线程ActivityThread已经创建,并且通知到AMS中
3) ActivityThread的绑定应用bindApplication, 这个会在下面章节讲解
4) 由于我们这个例子是桌面启动应用,那么最后mStackSupervisor.attachApplicationLocked堆栈中的绑定应用会真正启动activity活动对象,这个会在下面章节讲解
//ActivityManagerNative.java
public final void attachApplication(IApplicationThread thread) {
...
attachApplicationLocked(thread, callingPid);
...
//ActivityManagerService.java
private final boolean attachApplicationLocked(IApplicationThread thread,
int pid) {
//...
ProcessRecord app;
//调用者非系统进程,且调用者的pid大于0
if (pid != MY_PID && pid >= ) {
synchronized (mPidsSelfLocked) {
//在进程启动Process.start后就将pid添加进入mPidsSelfLocked了(父进程调用)
//现在是子进程调用,这个时候已经添加
app = mPidsSelfLocked.get(pid);
//...
//app.thread还没有设置过,下面makeActive将进行设置,会将app.thread设置成
//IApplicationThread(在ActivityThread中),app.thread不为null了
if (app.thread != null) {
//...
}
//...
try {
AppDeathRecipient adr = new AppDeathRecipient(
app, pid, thread);
//设置binder died掉之后的的回调地方是binderDied
thread.asBinder().linkToDeath(adr, );
//设置目前谁在监控死亡状态
app.deathRecipient = adr;
//...
//eventlog中设置服务绑定am_proc_bound
EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.userId, app.pid, app.processName);
//设置ProcessRecord的IApplicationThread(在ActivityThread中)
app.makeActive(thread, mProcessStats);
//默认设置一个adj
app.curAdj = app.setAdj = app.verifiedAdj = ProcessList.INVALID_ADJ;
//...
//用户更新电量估算mBatteryStatsService的FOREGROUND时间
updateProcessForegroundLocked(app, false, false);
//...
//判断是否解锁
app.unlocked = StorageManager.isUserKeyUnlocked(app.userId);
//去除进程启动超时的msg PROC_START_TIMEOUT_MSG,
//此处有ActivityThread回传,代表进程启动完成
mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
//一般情况normalMode都是true
boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
//generateApplicationProvidersLocked是开始创建应用的ContentProvider对象
List<ProviderInfo> providers = normalMode ? generateApplicationProvidersLocked(app) : null;
//...
//一般不会进入这里,这里是自动化测试的时候会进来
if (app.instrumentationClass != null) {
//...
}
//...
//应用兼容性相关,该参数会传入AcitiviyThread中
app.compat = compatibilityInfoForPackageLocked(appInfo);
//一般profilerInfo==null
ProfilerInfo profilerInfo = profileFile == null ? null
: new ProfilerInfo(profileFile, profileFd, samplingInterval, profileAutoStop);
//回到AcitiviyThread中的bindApplication,processName==test2,
//instrument相关都等于null,mBinderTransactionTrackingEnabled/
//enableTrackAllocation/isRestrictedBackupMode默认等于false,
//normalMode默认是true,persistent代表是否常驻内存,compat是兼容性相关,
//isolated==false,getCommonServicesLocked是将PMS、WMS、ALARM相关服务传入,
//mCoreSettingsObserver用于监听一些参数变化(长按超时,12/24小时显示时间变化,
//调试界面属性),bindApplication是异步的
thread.bindApplication(processName, appInfo, providers, app.instrumentationClass,
profilerInfo, app.instrumentationArguments, app.instrumentationWatcher,
app.instrumentationUiAutomationConnection, testMode,
mBinderTransactionTrackingEnabled, enableTrackAllocation,
isRestrictedBackupMode || !normalMode, app.persistent,
new Configuration(mConfiguration), app.compat,
getCommonServicesLocked(app.isolated),
mCoreSettingsObserver.getCoreSettingsLocked());
//将进程添加进入mLruProcesses中
//mLruProcesses保存的是正在运行应用的列表,第一个是最近使用的
updateLruProcessLocked(app, false, null);
//触发GC的时间重新计算
app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
//...
//一般normalMode都是true
if (normalMode) {
try {
//如果是activity导致的进程启动,activity从这里开始启动
//此处用于am_restart_activity,此处设置了didSomething = true
if (mStackSupervisor.attachApplicationLocked(app)) {
didSomething = true;
}
//...
//一般badApp==false
if (!badApp) {
try {
//如果之前该进程有需要启动的服务,此处开始启动服务
//启动进程了之后才会去启动服务
didSomething |= mServices.attachApplicationLocked(app, processName);
//...
if (!badApp && isPendingBroadcastProcessLocked(pid)) {
try {
//如果该进程之前有挂起的广播,现在可以开始发送了
didSomething |= sendPendingBroadcastsLocked(app);
// ...
到目前为止绑定进程的逻辑已经讲解完了,接下去我们仅需要关注thread.bindApplication和mStackSupervisor.attachApplicationLocked这2个函数
9 创建application
这一章节将会讲到application的实例化、application进程上下文context的创建、application的OnCreate
图9.1 创建application
9.1 bindApplication(ActivityThread.java)
我们关注的重点:
1) getPackageInfoNoCheck新建new LoadedApk,该类用于加载apk
2) makeApplication新建一个Application对象new newApplication(这里面会createAppContext创建application的进程上下文context)
3) callApplicationOnCreate调用Application的OnCreate
private void handleBindApplication(AppBindData data) {
//设置art实时编译更加敏感,更新art配置相关信息的计数count会乘10=((10000/500)/2),
//会让art更容易更新配置(如做实时编译还是解释执行等)
VMRuntime.registerSensitiveThread();
//...
//设置process的启动时间,这个主要是给上层调用的
Process.setStartTimes(SystemClock.elapsedRealtime(), SystemClock.uptimeMillis());
//AMS传递进来的参数全部放在data上
mBoundApplication = data;
//进程启动时如果你没有设置固定方向或者手动改变方向,这个config就是AMS中的mConfiguration
mConfiguration = new Configuration(data.config);
mCompatConfiguration = new Configuration(data.config);
mProfiler = new Profiler();
//一般情况initProfilerInfo都是null,除了使用instrumentation(如自动化测试相关会使用到)
if (data.initProfilerInfo != null) {
...
}
//此处会通过prctl(PR_SET_NAME...),裁剪后(process_name.c)
//只保留processName后面15个字符(kernel实际还会裁剪到最后一个字符,其实是14个字符),
//设置进程名字(内核标识进程的名字是task_struc->comm).
Process.setArgV0(data.processName);
//此处设置的是ddms调试使用的名字
android.ddm.DdmHandleAppName.setAppName(data.processName,
UserHandle.myUserId());
//常驻内存的进程
if (data.persistent) {
//如果在不能使用GPU加速(如低内存设备
//或者显示定义config_avoidGfxAccel为ture的情况都会进来)
if (!ActivityManager.isHighEndGfx()) {
//当前进程停止使用硬件渲染,这里的作用主要是为了减少运存RAM的消耗,
//对于低内存手机,这个是有帮助的
ThreadedRenderer.disable(false);
}
}
//...
//回复系统默认时区
TimeZone.setDefault(null);
//设置默认的语言
LocaleList.setDefault(data.config.getLocales());
//...
//新建new LoadedApk,该类用于加载apk
data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
//...
//可以通过config对分辨率进行设置,默认是没有设置的
updateDefaultDensity();
//设置是否24小时
final boolean is24Hr = "24".equals(mCoreSettings.getString(Settings.System.TIME_12_24));
DateFormat.set24HourTimePref(is24Hr);
//...
//网络代理相关设置
final IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
if (b != null) {
final IConnectivityManager service = IConnectivityManager.Stub.asInterface(b);
try {
final ProxyInfo proxyInfo = service.getProxyForNetwork(null);
Proxy.setHttpProxySystemProperty(proxyInfo);
//...
//新建一个appContext
final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
//...
//应用一般是isIsolated == false,这里讲的不是系统进程,是普通app的进程的启动,故会进入此处
if (!Process.isIsolated() && !"android".equals(appContext.getPackageName())) {
//获取应用缓存目录,如("/data/user_de/0/com.android.settings/cache")
final File cacheDir = appContext.getCacheDir();
//...
//获取应用代码缓存目录,"/data/user_de/0/com.android.settings/code_cache"
//此处主要是存放的opengl和renderscript部分的缓存代码
//类似于com.android.opengl.shaders_cache、com.android.renderscript.cache这样的数据
final File codeCacheDir = deviceContext.getCodeCacheDir();
}
//...
//ii非自动化测试一般都是null
if (ii != null) {
...
} else {
//一般情况下走的是这里
mInstrumentation = new Instrumentation();
}
//设置虚拟机堆栈最大能增长到的内存是多少,根据largeHeap属性判断是否大应用
if ((data.appInfo.flags&ApplicationInfo.FLAG_LARGE_HEAP) != ) {
//如果是大应用的话,应用虚拟机内存可以增长到堆栈大小dalvik.vm.heapsize
dalvik.system.VMRuntime.getRuntime().clearGrowthLimit();
} else {
//默认只能增长到dalvik.vm.heapgrowthlimit受限制的堆栈大小
dalvik.system.VMRuntime.getRuntime().clampGrowthLimit();
}
// allowThreadDiskWrites在应用oncreate的时候允许写的操作,
//返回的值是就得策略,此处仅用于临时修改
final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskWrites();
try {
//restrictedBackupMode是flase,data.info是上面new的LoadedApk,
//这里面的createAppContext和上面的createAppContext传递的参数是一样的
//此处会新建一个Application对象new newApplication,此处是Application的实例化
//此处传递的第二个参数instrumentation==null,故application不会在此处OnCreate
Application app = data.info.makeApplication(data.restrictedBackupMode, null);
//保存当前的Application对象
mInitialApplication = app;
//一般没有限制备份模式,restrictedBackupMode == false
if (!data.restrictedBackupMode) {
//如果apk有provider就会进入这里(如静态注册的providers)
if (!ArrayUtils.isEmpty(data.providers)) {
//初始化app中的所有provider
installContentProviders(app, data.providers);
//...
}
}
try {
//如果没有复写Instrumentation,一般此处没有做任何事情
mInstrumentation.onCreate(data.instrumentationArgs);
}
//...
try {
//此处调用的就是Application的OnCreate方法,
//activity的OnCreate后面会讲到,这里先调用的是Application的OnCreate
mInstrumentation.callApplicationOnCreate(app);
//...
}
9.2 getPackageInfoNoCheck/getPackageInfo
getPackageInfoNoCheck/getPackageInfo返回的是LoadedApk,用于加载apk
public final LoadedApk getPackageInfoNoCheck(ApplicationInfo ai,
CompatibilityInfo compatInfo) {
return getPackageInfo(ai, compatInfo, null, false, true, false);
}
//(ai, compatInfo, null, false, true, false);
private LoadedApk getPackageInfo(ApplicationInfo aInfo, CompatibilityInfo compatInfo,
ClassLoader baseLoader, boolean securityViolation, boolean includeCode,
boolean registerPackage) {
//...
//此处apk是包含代码的,故是从mPackages取,第一次进来此处是null
ref = mPackages.get(aInfo.packageName);
LoadedApk packageInfo = ref != null ? ref.get() : null;
//新建LoadedApk加载apk的类
packageInfo =
new LoadedApk(this, aInfo, compatInfo, baseLoader,
securityViolation, includeCode &&
(aInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != , registerPackage);
//...
//将新建的LoadedApk放到mPackages中
mPackages.put(aInfo.packageName,
new WeakReference<LoadedApk>(packageInfo));
//...
return packageInfo;
}
9.3 makeApplication(LoadedApk.java)
1) 创建Application的进程上下文
2) 调用代理Instrumentation新建Application
3) Application实例化、Application设置进程上下文context
//LoadedApk.java
//forceDefaultAppClass==false,instrumentation==null
public Application makeApplication(boolean forceDefaultAppClass,
Instrumentation instrumentation) {
//...
Application app = null;
//如果应用没有重载Application类的话,直接使用默认的"android.app.Application"
String appClass = mApplicationInfo.className;
if (forceDefaultAppClass || (appClass == null)) {
appClass = "android.app.Application";
}
try {
java.lang.ClassLoader cl = getClassLoader();
//...
//创建Application的进程上下文
ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
//调用代理Instrumentation新建Application
app = mActivityThread.mInstrumentation.newApplication(
cl, appClass, appContext);
appContext.setOuterContext(app);
}
//...
return app;
}
//Instrumentation.java
public Application newApplication(ClassLoader cl, String className, Context context)
throws InstantiationException, IllegalAccessException,
ClassNotFoundException {
return newApplication(cl.loadClass(className), context);
}
static public Application newApplication(Class<?> clazz, Context context)
... {
//Application类的实例化,如类非静态变量等会在此处生成
Application app = (Application)clazz.newInstance();
//调用Application的attach附着,用于设置进程上下文context
app.attach(context);
return app;
}
//Application.java
final void attach(Context context) {
//设置base应用基本的进程上下文
attachBaseContext(context);
//设置类的加载器
mLoadedApk = ContextImpl.getImpl(context).mPackageInfo;
}
现在有了Application这个对象,下面接着会进行Application的OnCreate
9.4 callApplicationOnCreate(Instrumentation.java)
callApplicationOnCreate这个函数通过代理调用Application的OnCreate
//Instrumentation.java
public void callApplicationOnCreate(Application app) {
app.onCreate();
}
//Application.java
public void onCreate() {
}
进程启动会先调用Application的OnCreate,这个也是算在应用启动生命周期内的。
目前Application创建了,Application的OnCreate也调用了,接下去就是Activity相关的逻辑。