android系統Launcher啟動時機
阿新 • • 發佈:2018-12-15
今天有空研究了一下系統啟動流程中的Launcher啟動時機,有必要給大家分享一下閱讀程式碼的成果;
首先我們知道系統啟動先會生成init程序,init程序會去啟動各種守護程序類似usbd,adbd等,同時將啟動Zygote程序,而之後Zygote程序會去起SystemServer程序,這個SystemServer是啟動大部分服務的程序,同時將這些服務註冊到ServiceManager中,其實應該能想到服務啟動完之後就會去啟動SystemUI和Launcher,於是進入SystemServer.java看一下:
System.loadLibrary("android_servers"); nativeInit(); // Check whether we failed to shut down last time we tried. // This call may not return. performPendingShutdown(); // Initialize the system context. createSystemContext(); // Create the system service manager. mSystemServiceManager = new SystemServiceManager(mSystemContext); LocalServices.addService(SystemServiceManager.class, mSystemServiceManager); // Start services. try { startBootstrapServices(); startCoreServices(); startOtherServices(); } catch (Throwable ex) { Slog.e("System", "******************************************"); Slog.e("System", "************ Failure starting system services", ex); throw ex; } // For debug builds, log event loop stalls to dropbox for analysis. if (StrictMode.conditionallyEnableDebugLogging()) { Slog.i(TAG, "Enabled StrictMode for system server main thread."); }
以上程式碼可以看到,會先去啟動啟動引導服務,然後去啟動核心服務,其實這兩類服務都是去啟動平臺服務,接下去去啟動其他服務,其他服務就是硬體服務,繼續看程式碼startOtherServices
final CommonTimeManagementService commonTimeMgmtServiceF = commonTimeMgmtService; final TextServicesManagerService textServiceManagerServiceF = tsms; final StatusBarManagerService statusBarF = statusBar; final AssetAtlasService atlasF = atlas; final InputManagerService inputManagerF = inputManager; final TelephonyRegistry telephonyRegistryF = telephonyRegistry; final MediaRouterService mediaRouterF = mediaRouter; final AudioService audioServiceF = audioService; final MmsServiceBroker mmsServiceF = mmsService; // We now tell the activity manager it is okay to run third party // code. It will call back into us once it has gotten to the state // where third party code can really run (but before it has actually // started launching the initial applications), for us to complete our // initialization. mActivityManagerService.systemReady(new Runnable() { @Override public void run() { Slog.i(TAG, "Making services ready"); mSystemServiceManager.startBootPhase( SystemService.PHASE_ACTIVITY_MANAGER_READY); try { mActivityManagerService.startObservingNativeCrashes(); } catch (Throwable e) { reportWtf("observing native crashes", e); } Slog.i(TAG, "WebViewFactory preparation"); WebViewFactory.prepareWebViewInSystemServer(); try { startSystemUi(context); } catch (Throwable e) { reportWtf("starting System UI", e); } try { if (mountServiceF != null) mountServiceF.systemReady(); } catch (Throwable e) { reportWtf("making Mount Service ready", e); }
上面程式碼中可以看到startSystemUi這個函式,很明顯是去啟動SystemUI了,啟動Launcher程式碼應該也是差不多這個地方了,繼續看方法mActivityManagerService.systemReady
int i; for (i=0; i<N; i++) { ApplicationInfo info = (ApplicationInfo)apps.get(i); if (info != null && !info.packageName.equals("android")) { addAppLocked(info, false, null /* ABI override */); } } } } catch (RemoteException ex) { // pm is in same process, this will never happen. } } // Start up initial activity. mBooting = true; startHomeActivityLocked(mCurrentUserId, "systemReady"); try { if (AppGlobals.getPackageManager().hasSystemUidErrors()) { Slog.e(TAG, "UIDs on the system are inconsistent, you need to wipe your" + " data partition or your device will be unstable."); mHandler.obtainMessage(SHOW_UID_ERROR_MSG).sendToTarget(); } } catch (RemoteException e) { } if (!Build.isFingerprintConsistent()) { Slog.e(TAG, "Build fingerprint is not consistent, warning user"); mHandler.obtainMessage(SHOW_FINGERPRINT_ERROR_MSG).sendToTarget(); } long ident = Binder.clearCallingIdentity(); try { Intent intent = new Intent(Intent.ACTION_USER_STARTED);
我們看到startHomeActivityLocked這個方法,
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;
}
Intent intent = getHomeIntent();
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);
}
}
return true;
}
繼續看getHomeIntent方法
UsageEvents.Event.MOVE_TO_BACKGROUND);
}
synchronized (stats) {
stats.noteActivityPausedLocked(component.app.uid);
}
}
}
Intent getHomeIntent() {
Intent intent = new Intent(mTopAction, mTopData != null ? Uri.parse(mTopData) : null);
intent.setComponent(mTopComponent);
if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
intent.addCategory(Intent.CATEGORY_HOME);
}
return intent;
}
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;
這裡我想大家就能看明白,其實getHomeIntent方法是去配置啟動Launcher所需要的Intent,mStackSupervisor.startHomeActivity就是去啟動Launcher應用的,StackSupervisor本質就是遠端也就是服務端啟動Activity的一個類,之前有分析過Activity啟動流程,如果對Activity啟動流程不是很熟的同學可以去了解一下。