Android AMS 系列之 systemReady

一 前言

Android 系统服务进程 system_server,进入消息循环前的最后一步,就是调用 AMS 的 systemReady() 方法。今天我们分析一下这里的流程。

二 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 SystemServer
                if (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<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);
                    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 类中

三 systemReady 第二部分之回调方法

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 party
            final 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 party
            if (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 manager
                if (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() 方法。包括:位置、国家检测、网络时间、输入管理、网络评分等等。
至此回调方法分析结束。

四 systemReady第三部分

继续回到 AMS 的 systemReady() 方法。

// Only start up encryption-aware persistent apps; once user is
            // unlocked we'll come back around and start unaware apps
            startPersistentApps(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() {
                                @Override
                                public 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。

4.1 Home 启动

@Override
        public 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<ActivityInfo, Intent> 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 的主 Activity
        mLastHomeActivityStartRecord = 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。

你可能感兴趣的:(Android,framework,android,java,webview)