Android启动之BOOT_COMPLETED广播
16lz
2021-12-04
AMS启动Home(启动Launcher)
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.javapublic 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.javapublic 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.javafinal 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.javaprivate 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.javavoid 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.javafinal 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.javafinal 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.javavoid 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.javaenableScreenAfterBoot() -> performEnableScreen() -> surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION, data, null, 0); ->frameworks/native/ services/surfaceflinger/SurfaceFlinger.cppbootFinished() -> property_set("service.bootanim.exit", "1"); //将该属性设为1,开机动画退出。
更多相关文章
- Android连续点击两次返回键退出App
- Android(安卓)JB 4.2 中InputManager 启动过程解析 -- 1
- android 开机自启动程序2
- Android(安卓)自定义APP开机启动,并打开其它App
- Android完全退出程序、线程
- 在编译Android时,开机不锁屏
- Android(安卓)-- 重写android返回键
- android双击返回键退出程序
- Android——修改开机画面