Android 系统服务进程 system_server,进入消息循环前的最后一步,就是调用 AMS 的 systemReady() 方法。今天我们分析一下这里的流程。
ActivityManagerService.java
public void systemReady(final Runnable goingCallback, TimingsTraceLog traceLog) {synchronized(this) {if (mSystemReady) {// If we're done calling all the receivers, run the next "boot phase" passed in// by the SystemServerif (goingCallback != null) {goingCallback.run();}return;}mLocalDeviceIdleController= LocalServices.getService(DeviceIdleController.LocalService.class);mActivityTaskManager.onSystemReady();// Make sure we have the current profile info, since it is needed for security checks.mUserController.onSystemReady();mAppOpsService.systemReady();mSystemReady = true;}......
}
这里 mSystemReady 是 false,所以回调方法不会在这里被执行。接下来会调用一些关联类的 systemReady() 方法,然后把标志位 mSystemReady 置为 true。
ArrayList 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();}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);mProcessList.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;}
清理进程,把不允许在开机阶段运行的进程都结束掉。判断标准是:应用程序的 AM 配置文件是否有配置 android:persistent 属性。
mAtmInternal.updateTopComponentForFactoryTest();
工厂测试相关的逻辑,正常情况下这个条件不成立,所以不管它。
if (goingCallback != null) goingCallback.run();
执行 systemReady() 传入的回调方法,在 SystemServer.java 类中
SystemServer.java
这个回调方法很长,足有 200 行,我们单独作为一节来分析。
traceBeginAndSlog("StartActivityManagerReadyPhase");mSystemServiceManager.startBootPhase(SystemService.PHASE_ACTIVITY_MANAGER_READY);
traceEnd();
AMS 启动完成,系统进入阶段 PHASE_ACTIVITY_MANAGER_READY,对其它服务调用 onBootPhase() 方法传出这个PHASE。
traceBeginAndSlog("StartObservingNativeCrashes");try {mActivityManagerService.startObservingNativeCrashes();} catch (Throwable e) {reportWtf("observing native crashes", e);}
traceEnd();
启动 native crash监测。
// No dependency on Webview preparation in system server. But this should// be completed before allowing 3rd partyfinal String WEBVIEW_PREPARATION = "WebViewFactoryPreparation";Future> webviewPrep = null;if (!mOnlyCore && mWebViewUpdateService != null) {webviewPrep = SystemServerInitThreadPool.get().submit(() -> {Slog.i(TAG, WEBVIEW_PREPARATION);TimingsTraceLog traceLog = new TimingsTraceLog(SYSTEM_SERVER_TIMING_ASYNC_TAG, Trace.TRACE_TAG_SYSTEM_SERVER);traceLog.traceBegin(WEBVIEW_PREPARATION);ConcurrentUtils.waitForFutureNoInterrupt(mZygotePreload, "Zygote preload");mZygotePreload = null;mWebViewUpdateService.prepareWebViewInSystemServer();traceLog.traceEnd();}, WEBVIEW_PREPARATION);}
这里判断要不要启动 webview。
traceBeginAndSlog("StartSystemUI");try {startSystemUi(context, windowManagerF);} catch (Throwable e) {reportWtf("starting System UI", e);}traceEnd();
启动 SystemUI。
if (safeMode) {traceBeginAndSlog("EnableAirplaneModeInSafeMode");try {connectivityF.setAirplaneMode(true);} catch (Throwable e) {reportWtf("enabling Airplane Mode during Safe Mode bootup", e);}traceEnd();}traceBeginAndSlog("MakeNetworkManagementServiceReady");try {if (networkManagementF != null) {networkManagementF.systemReady();}} catch (Throwable e) {reportWtf("making Network Managment Service ready", e);}CountDownLatch networkPolicyInitReadySignal = null;if (networkPolicyF != null) {networkPolicyInitReadySignal = networkPolicyF.networkScoreAndNetworkManagementServiceReady();}traceEnd();traceBeginAndSlog("MakeIpSecServiceReady");try {if (ipSecServiceF != null) {ipSecServiceF.systemReady();}} catch (Throwable e) {reportWtf("making IpSec Service ready", e);}traceEnd();traceBeginAndSlog("MakeNetworkStatsServiceReady");try {if (networkStatsF != null) {networkStatsF.systemReady();}} catch (Throwable e) {reportWtf("making Network Stats Service ready", e);}traceEnd();traceBeginAndSlog("MakeConnectivityServiceReady");try {if (connectivityF != null) {connectivityF.systemReady();}} catch (Throwable e) {reportWtf("making Connectivity Service ready", e);}traceEnd();traceBeginAndSlog("MakeNetworkPolicyServiceReady");try {if (networkPolicyF != null) {networkPolicyF.systemReady(networkPolicyInitReadySignal);}} catch (Throwable e) {reportWtf("making Network Policy Service ready", e);}traceEnd();
调用一堆网络相关服务的 systemReady() 方法。
// It is now okay to let the various system services start their// third party code...traceBeginAndSlog("PhaseThirdPartyAppsCanStart");// confirm webview completion before starting 3rd partyif (webviewPrep != null) {ConcurrentUtils.waitForFutureNoInterrupt(webviewPrep, WEBVIEW_PREPARATION);}mSystemServiceManager.startBootPhase(SystemService.PHASE_THIRD_PARTY_APPS_CAN_START);traceEnd();
系统进入阶段 PHASE_THIRD_PARTY_APPS_CAN_START。对其它服务调用 onBootPhase() 方法传出这个 PHASE。
traceBeginAndSlog("MakeLocationServiceReady");try {if (locationF != null) {locationF.systemRunning();}} catch (Throwable e) {reportWtf("Notifying Location Service running", e);}traceEnd();traceBeginAndSlog("MakeCountryDetectionServiceReady");try {if (countryDetectorF != null) {countryDetectorF.systemRunning();}} catch (Throwable e) {reportWtf("Notifying CountryDetectorService running", e);}traceEnd();traceBeginAndSlog("MakeNetworkTimeUpdateReady");try {if (networkTimeUpdaterF != null) {networkTimeUpdaterF.systemRunning();}} catch (Throwable e) {reportWtf("Notifying NetworkTimeService running", e);}traceEnd();traceBeginAndSlog("MakeInputManagerServiceReady");try {// TODO(BT) Pass parameter to input managerif (inputManagerF != null) {inputManagerF.systemRunning();}} catch (Throwable e) {reportWtf("Notifying InputManagerService running", e);}traceEnd();traceBeginAndSlog("MakeTelephonyRegistryReady");try {if (telephonyRegistryF != null) {telephonyRegistryF.systemRunning();}} catch (Throwable e) {reportWtf("Notifying TelephonyRegistry running", e);}traceEnd();traceBeginAndSlog("MakeMediaRouterServiceReady");try {if (mediaRouterF != null) {mediaRouterF.systemRunning();}} catch (Throwable e) {reportWtf("Notifying MediaRouterService running", e);}traceEnd();traceBeginAndSlog("MakeMmsServiceReady");try {if (mmsServiceF != null) {mmsServiceF.systemRunning();}} catch (Throwable e) {reportWtf("Notifying MmsService running", e);}traceEnd();
对其他相关服务调用 systemRunning() 方法。包括:位置、国家检测、网络时间、输入管理、网络评分等等。
至此回调方法分析结束。
继续回到 AMS 的 systemReady() 方法。
// Only start up encryption-aware persistent apps; once user is// unlocked we'll come back around and start unaware appsstartPersistentApps(PackageManager.MATCH_DIRECT_BOOT_AWARE);
启动锁屏状态下的应用,通过应用配置文件的 android:directBoot 属性过滤。
if (bootingSystemUser) {mAtmInternal.startHomeOnAllDisplays(currentUserId, "systemReady");
}
启动 Home 程序。这个在下一节分析。
mAtmInternal.showSystemReadyErrorDialogsIfNeeded();public void showSystemReadyErrorDialogsIfNeeded() {synchronized (mGlobalLock) {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.");mUiHandler.post(() -> {if (mShowDialogs) {AlertDialog d = new BaseErrorDialog(mUiContext);d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);d.setCancelable(false);d.setTitle(mUiContext.getText(R.string.android_system_label));d.setMessage(mUiContext.getText(R.string.system_error_wipe_data));d.setButton(DialogInterface.BUTTON_POSITIVE,mUiContext.getText(R.string.ok),mUiHandler.obtainMessage(DISMISS_DIALOG_UI_MSG, d));d.show();}});}} catch (RemoteException e) {}if (!Build.isBuildConsistent()) {Slog.e(TAG, "Build fingerprint is not consistent, warning user");mUiHandler.post(() -> {if (mShowDialogs) {AlertDialog d = new BaseErrorDialog(mUiContext);d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);d.setCancelable(false);d.setTitle(mUiContext.getText(R.string.android_system_label));d.setMessage(mUiContext.getText(R.string.system_error_manufacturer));d.setButton(DialogInterface.BUTTON_POSITIVE,mUiContext.getText(R.string.ok),mUiHandler.obtainMessage(DISMISS_DIALOG_UI_MSG, d));d.show();}});}}}
检查 uid 和 fingerprint,如果有异常会弹出 Android System 的弹框。
if (bootingSystemUser) {final int callingUid = Binder.getCallingUid();final int callingPid = Binder.getCallingPid();long ident = Binder.clearCallingIdentity();try {Intent intent = new Intent(Intent.ACTION_USER_STARTED);intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY| Intent.FLAG_RECEIVER_FOREGROUND);intent.putExtra(Intent.EXTRA_USER_HANDLE, currentUserId);broadcastIntentLocked(null, null, intent,null, null, 0, null, null, null, OP_NONE,null, false, false, MY_PID, SYSTEM_UID, callingUid, callingPid,currentUserId);intent = new Intent(Intent.ACTION_USER_STARTING);intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);intent.putExtra(Intent.EXTRA_USER_HANDLE, currentUserId);broadcastIntentLocked(null, null, intent,null, new IIntentReceiver.Stub() {@Overridepublic void performReceive(Intent intent, int resultCode, String data,Bundle extras, boolean ordered, boolean sticky, int sendingUser)throws RemoteException {}}, 0, null, null,new String[] {INTERACT_ACROSS_USERS}, OP_NONE,null, true, false, MY_PID, SYSTEM_UID, callingUid, callingPid,UserHandle.USER_ALL);} catch (Throwable t) {Slog.wtf(TAG, "Failed sending first user broadcasts", t);} finally {Binder.restoreCallingIdentity(ident);}} else {Slog.i(TAG, "Not sending multi-user broadcasts for non-system user "+ currentUserId);}
发送两个广播:ACTION_USER_STARTED、ACTION_USER_STARTING。
@Overridepublic boolean startHomeOnAllDisplays(int userId, String reason) {synchronized (mGlobalLock) {return mRootActivityContainer.startHomeOnAllDisplays(userId, reason);}}
RootActivityContainer.java
boolean startHomeOnAllDisplays(int userId, String reason) {boolean homeStarted = false;for (int i = mActivityDisplays.size() - 1; i >= 0; i--) {final int displayId = mActivityDisplays.get(i).mDisplayId;homeStarted |= startHomeOnDisplay(userId, reason, displayId);}return homeStarted;}
boolean startHomeOnDisplay(int userId, String reason, int displayId) {return startHomeOnDisplay(userId, reason, displayId, false /* allowInstrumenting */,false /* fromHomeKey */);}
boolean startHomeOnDisplay(int userId, String reason, int displayId, boolean allowInstrumenting,boolean fromHomeKey) {// Fallback to top focused display if the displayId is invalid.if (displayId == INVALID_DISPLAY) {displayId = getTopDisplayFocusedStack().mDisplayId;}Intent homeIntent = null;ActivityInfo aInfo = null;if (displayId == DEFAULT_DISPLAY) {homeIntent = mService.getHomeIntent();aInfo = resolveHomeActivity(userId, homeIntent);} else if (shouldPlaceSecondaryHomeOnDisplay(displayId)) {Pair info = resolveSecondaryHomeActivity(userId, displayId);aInfo = info.first;homeIntent = info.second;}if (aInfo == null || homeIntent == null) {return false;}if (!canStartHomeOnDisplay(aInfo, displayId, allowInstrumenting)) {return false;}// Updates the home component of the intent.homeIntent.setComponent(new ComponentName(aInfo.applicationInfo.packageName, aInfo.name));homeIntent.setFlags(homeIntent.getFlags() | FLAG_ACTIVITY_NEW_TASK);// Updates the extra information of the intent.if (fromHomeKey) {homeIntent.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, true);}// Update the reason for ANR debugging to verify if the user activity is the one that// actually launched.final String myReason = reason + ":" + userId + ":" + UserHandle.getUserId(aInfo.applicationInfo.uid) + ":" + displayId;mService.getActivityStartController().startHomeActivity(homeIntent, aInfo, myReason,displayId);return true;}
ActivityStartController.java
void startHomeActivity(Intent intent, ActivityInfo aInfo, String reason, int displayId) {final ActivityOptions options = ActivityOptions.makeBasic();options.setLaunchWindowingMode(WINDOWING_MODE_FULLSCREEN);if (!ActivityRecord.isResolverActivity(aInfo.name)) {// The resolver activity shouldn't be put in home stack because when the foreground is// standard type activity, the resolver activity should be put on the top of current// foreground instead of bring home stack to front.options.setLaunchActivityType(ACTIVITY_TYPE_HOME);}options.setLaunchDisplayId(displayId);mLastHomeActivityStartResult = obtainStarter(intent, "startHomeActivity: " + reason).setOutActivity(tmpOutRecord).setCallingUid(0).setActivityInfo(aInfo).setActivityOptions(options.toBundle()).execute(); // 根据 Intent,启动 Home 的主 ActivitymLastHomeActivityStartRecord = tmpOutRecord[0];final ActivityDisplay display =mService.mRootActivityContainer.getActivityDisplay(displayId);final ActivityStack homeStack = display != null ? display.getHomeStack() : null;if (homeStack != null && homeStack.mInResumeTopActivity) {// 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();}}
根据 Intent,启动 Home 的主 Activity。
下一篇:面试总结 http相关的题目