AMS启动Home(启动Launcher)
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
public void systemReady(final Runnable goingCallback) {
... ...
Slog.i(TAG, "System now ready");
... ...
startHomeActivityLocked(mCurrentUserId, "systemReady"); //启动 Home
}
boolean startHomeActivityLocked(int userId, String reason) {
if (mStartHomeSetDefaultLauncherCount > 0) {
mStartHomeSetDefaultLauncherCount--;
boolean firstLaunch =
SystemProperties.getBoolean("persist.sys.sw.firstLaunch", true);
if(firstLaunch){
setDefaultLauncher(); //设置默认launcher
if (mStartHomeSetDefaultLauncherCount == 0) {
SystemProperties.set("persist.sys.sw.firstLaunch", "false");
}
}
}
... ...
Intent intent = getHomeIntent(); //获取Home的Intent
ActivityInfo aInfo = resolveActivityInfo(intent, STOCK_PM_FLAGS, userId);
//如果系统没有任何Home应用,aInfo == null,不会启动Home
//但是,如果系统是第一次启动或恢复出厂设置,会首先启动开机向导,此时aInfo != null
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);
Slog.w("zhangc","startHomeActivity intent "+intent+"; aInfo "+aInfo+"; reason "+reason);
mStackSupervisor.startHomeActivity(intent, aInfo, reason); //此处启动Home应用
}
}
}
Home应用启动后,回调AMS的activityIdle方法
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
public final void activityIdle(IBinder token, Configuration config, boolean stopProfiling) {
... ...
ActivityRecord r = mStackSupervisor.activityIdleInternalLocked(token, false, config);
}
frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java
final ActivityRecord activityIdleInternalLocked(final IBinder token, boolean fromTimeout, Configuration config) {
... ...
if (isFrontStack(r.task.stack) || fromTimeout) {
booting = checkFinishBootingLocked();
}
}
checkFinishBootingLocked会报告启动时间结束,以及检查是否是还在开机阶段,结束开机流程。当桌面已经拿到焦点显示好了,开机动画可以退出。在这里会修改AMS的mBooting全局变量为true,enableScreen也是true,发送Message给AMS进行处理。代码片段如下:
frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java
private boolean checkFinishBootingLocked() {
final boolean booting = mService.mBooting;
boolean enableScreen = false;
mService.mBooting = false;
if (!mService.mBooted) {
mService.mBooted = true;
enableScreen = true;
}
if (booting || enableScreen) {
mService.postFinishBooting(booting, enableScreen);
}
return booting;
}
postFinishBooting函数发送FINISH_BOOTING_MSG消息:
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
void postFinishBooting(boolean finishBooting, boolean enableScreen) {
mHandler.sendMessage(mHandler.obtainMessage(FINISH_BOOTING_MSG,
finishBooting? 1 : 0, enableScreen ? 1 : 0));
}
处理FINISH_BOOTING_MSG消息:
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
final class MainHandler extends Handler {
public MainHandler(Looper looper) {
super(looper, null, true);
}
@Override
public void handleMessage(Message msg) {
... ...
case FINISH_BOOTING_MSG: {
if (msg.arg1 != 0) {
finishBooting();
}
if (msg.arg2 != 0) {
enableScreenAfterBoot();
}
break;
}
}
}
下面分别分析finishBooting和enableScreenAfterBoot
finishBooting里面先判断开机动画有没有结束,如果没有结束,直接返回。如果已经结束,则经过一些处理,最后发送开机广播BOOT_COMPLETED。
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
final void finishBooting() {
synchronized (this) {
if (!mBootAnimationComplete) { //如果开机动画没有退出,直接返回
mCallFinishBooting = true;
return;
}
mCallFinishBooting = false;
}
// Tell anyone interested that we are done booting!
SystemProperties.set("sys.boot_completed", "1"); //设置属性,表明开机完成
... ...
Intent intent = new Intent(Intent.ACTION_BOOT_COMPLETED, null);
intent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
intent.addFlags(Intent.FLAG_RECEIVER_NO_ABORT);
broadcastIntentLocked... ... //发送开机广播
}
那么,开机动画什么时候退出呢?继续往下看。
等待WMS准备好,SystemProperties.set("service.bootanim.exit", "1");,然后bootanimation退出。
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
void enableScreenAfterBoot() {
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
SystemClock.uptimeMillis());
mWindowManager.enableScreenAfterBoot(); //退出bootanimation
synchronized (this) {
updateEventDispatchingLocked();
}
}
经过一系列调用,最后设置service.bootanim.exit这个属性。
property_set("service.bootanim.exit", "1");
frameworks/ base/services/core/java/com/android/server/wm/WindowManagerService.java
enableScreenAfterBoot() ->
performEnableScreen() ->
surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION, data, null, 0); ->
frameworks/native/ services/surfaceflinger/SurfaceFlinger.cpp
bootFinished() ->
property_set("service.bootanim.exit", "1"); //将该属性设为1,开机动画退出。