0. 写在前面的话
上一篇讲了各种Service是在何时启动的,最后提到了关于
HomeActivity
的启动。HomeActivity
作为Android系统启动后第一个加载的Activity,今天就来分析下其启动流程。
其实还有个时序图的,但是太大了,截图也不全,等下次直接上传,方便自己查看。
暂时的规划先是Activity的启动流程,通过这个又会涉及到进程间通信——Binder机制,接着Activity启动后,布局是如何绘制到屏幕上,View的事件是如何分发的?通过这条线来慢慢整理这两年多我对Android的理解,加深自己的印象。
1. ActivityManagerService.systemReady(new Runnable())
做了什么?
我们先来看下这个方法的代码:
public void systemReady(final Runnable goingCallback) {
synchronized(this) {
//mSystemReady默认为false,所以第一次调用这个方法时不会执行goingCallback.run()
if (mSystemReady) {
if (goingCallback != null) {
goingCallback.run();
}
return;
}
......
}
//要杀掉的进程(启动时不允许启动的进程)
ArrayList<ProcessRecord> procsToKill = null;
synchronized(mPidsSelfLocked) {
for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
ProcessRecord proc = mPidsSelfLocked.valueAt(i);
if (!isAllowedWhileBooting(proc.info)){
if (procsToKill == null) {
procsToKill = new ArrayList<ProcessRecord>();
}
procsToKill.add(proc);
}
}
}
//杀掉这些进程
synchronized(this) {
if (procsToKill != null) {
for (int i=procsToKill.size()-1; i>=0; i--) {
ProcessRecord proc = procsToKill.get(i);
Slog.i(TAG, "Removing system update proc: " + proc);
removeProcessLocked(proc, true, false, "system update done");
}
}
// Now that we have cleaned up any update processes, we
// are ready to start launching real processes and know that
// we won't trample on them any more.
mProcessesReady = true;
}
......
//这里会调用Runnable的run()方法
if (goingCallback != null) goingCallback.run();
......
synchronized (this) {
//启动常驻的应用
startPersistentApps(PackageManager.MATCH_DIRECT_BOOT_AWARE);
mBooting = true;
if (UserManager.isSplitSystemUser()) {
ComponentName cName = new ComponentName(mContext, SystemUserHomeActivity.class);
try {
//解禁SystemUserHomeActivity
AppGlobals.getPackageManager().setComponentEnabledSetting(cName,
PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0,
UserHandle.USER_SYSTEM);
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
}
}
//开始启动HomeActivity
startHomeActivityLocked(currentUserId, "systemReady");
......
}
}
这个方法内容挺多的,首次进入是设置的Runnable不会执行,后面通过查找启动时系统不允许启动的进程,并将其kill掉。接下来启动了系统常驻应用
startPersistentApps(PackageManager.MATCH_DIRECT_BOOT_AWARE)
,通过使用AppGlobals.getPackageManager().setComponentEnabledSetting
方法解禁SystemUserHomeActivity
,其flag为PackageManager.COMPONENT_ENABLED_STATE_ENABLED
,最后通过startHomeActivityLocked(currentUserId, "systemReady")
来启动HomeActivity
。
2. startHomeActivityLocked
开始启动HomeActivity
这里的代码不多,也很好理解:
boolean startHomeActivityLocked(int userId, String reason) {
//测试模式下不用管
if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL
&& mTopAction == null) {
// We are running in factory test mode, but unable to find
// the factory test app, so just sit around displaying the
// error message and don't try to start anything.
return false;
}
//得到要启动Activity的Intent
Intent intent = getHomeIntent();
//将Intent解析成ActivityInfo
ActivityInfo aInfo = resolveActivityInfo(intent, STOCK_PM_FLAGS, userId);
if (aInfo != null) {
intent.setComponent(new ComponentName(aInfo.applicationInfo.packageName, aInfo.name));
// Don't do this if the home app is currently being
// instrumented.
aInfo = new ActivityInfo(aInfo);
aInfo.applicationInfo = getAppInfoForUser(aInfo.applicationInfo, userId);
ProcessRecord app = getProcessRecordLocked(aInfo.processName,
aInfo.applicationInfo.uid, true);
if (app == null || app.instrumentationClass == null) {
intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
//启动Activity
mActivityStarter.startHomeActivityLocked(intent, aInfo, reason);
}
} else {
Slog.wtf(TAG, "No home screen found for " + intent, new Throwable());
}
return true;
}
Intent getHomeIntent() {
Intent intent = new Intent(mTopAction, mTopData != null ? Uri.parse(mTopData) : null);
intent.setComponent(mTopComponent);
intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
//不是测试情况下则设置Category为Intent.CATEGORY_HOME
if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
intent.addCategory(Intent.CATEGORY_HOME);
}
return intent;
}
首先是判断当前系统是否处于测试环境,接着去获取(创建)
HomeIntent
,并将其解析成ActivityInfo
,接下来调用ActivityStarter
中的startHomeActivityLocked(intent, aInfo, reason)
方法去启动HomeActivity
。
3. startHomeActivityLocked
和startActivityLocked
我们进入
ActivityStarter
中可以看到startHomeActivityLocked
调用了startActivityLocked
方法,其中传入的参数只有Intent
和ActivityInfo
不为空,其他的都为null
或者0
或者false
,由于大部分参数都为null
,startActivityLocked
中真正执行的代码并不是很多。
void startHomeActivityLocked(Intent intent, ActivityInfo aInfo, String reason) {
mSupervisor.moveHomeStackTaskToTop(HOME_ACTIVITY_TYPE, reason);
//调用了参数居多的方法
startActivityLocked(null /*caller*/, intent, null /*ephemeralIntent*/,
null /*resolvedType*/, aInfo, null /*rInfo*/, null /*voiceSession*/,
null /*voiceInteractor*/, null /*resultTo*/, null /*resultWho*/,
0 /*requestCode*/, 0 /*callingPid*/, 0 /*callingUid*/, null /*callingPackage*/,
0 /*realCallingPid*/, 0 /*realCallingUid*/, 0 /*startFlags*/, null /*options*/,
false /*ignoreTargetSecurity*/, false /*componentSpecified*/, null /*outActivity*/,
null /*container*/, null /*inTask*/);
if (mSupervisor.inResumeTopActivity) {
// If we are in resume section already, home activity will be initialized, but not
// resumed (to avoid recursive resume) and will stay that way until something pokes it
// again. We need to schedule another resume.
mSupervisor.scheduleResumeTopActivities();
}
}
//这个参数是真TM的多啊
final int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container,
TaskRecord inTask) {
//启动结果代码
int err = ActivityManager.START_SUCCESS;
ProcessRecord callerApp = null;
//caller == null
if (caller != null) {
......
}
final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
if (err == ActivityManager.START_SUCCESS) {
..Log..
}
ActivityRecord sourceRecord = null;
ActivityRecord resultRecord = null;
//resultTo == null
if (resultTo != null) {
......
}
final int launchFlags = intent.getFlags();
//Activity启动是设置的flags
if ((launchFlags & Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 && sourceRecord != null) {
......
}
......
//检查启动Activity的权限
boolean abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, resultWho,