第2章 理解包管理機制和PMS

首先偷俭,作者巧妙的以應用安裝作為切入點引入了包管理的話題浪讳。

進而介紹了第一個關鍵類:PackageManager。
PackageManager是一個抽象類涌萤,具體實現(xiàn)類是ApplicationPackageManager淹遵。
PackageManager提供了以下幾個主要功能:

1.獲取一個應用程序的所有信息
2.獲取四大組件的信息
3.查詢permission的相關信息
4.獲取包的信息
5.安裝口猜、卸載apk

尋找PackageInstaller入口,
當我們在程序中調(diào)用以下代碼時(7.0以前):

 Intent intent = new Intent(Intent.ACTION_VIEW);
 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
 intent.setDataAndType(Uri.parse("file://" + path), "application/vnd.android.package-archive");
 startActivity(intent);

或者(7.0及以后)
因為7.0以后透揣,Android要求使用ContentProvider替代原有的直接暴露Uri的方式訪問文件济炎。

Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(xxx, "application/vnd.android.package-archive");
startActivity(intent);

最終我們都是跳轉到一個Activity去進行安裝應用,那這個Activity到底是哪個Activity呢辐真?因為是隱式跳轉须尚,所以我們要找到對應匹配的Activity。

通過閱讀源碼侍咱,我們發(fā)現(xiàn)在7.0及以前能隱式匹配的Activity為PackageInstallerActivity耐床,而在8.0及以后能匹配到的是InstallStart。

那就以InstallStart為入口跟蹤整個流程吧楔脯!

InstallStart是PackageInstaller中的入口Activity属愤,其中PackageInstaller是系統(tǒng)內(nèi)置的應用程序员淫,用于安裝和卸載應用。

進入到InstallStart以后經(jīng)過對安裝路徑的解析,最終將其傳給InstallStaging頁面驳阎,在InstallStaging頁面中會開啟一個StagingAsyncTask任務。這個任務會將傳入的packageUri的內(nèi)容寫入到mStagedFile中间学,寫入成功的話入偷,則將mStagedFile傳入到PackageInstallerActivity中,開啟PackageInstallerActivity頁面弄诲。所以愚战,最終還是回到了PackageInstallerActivity里。
所以齐遵,你看人家google工程師就是牛逼寂玲,在寫代碼的時候就考慮到了代碼的可擴展性。在7.0之后加入ContentProvider讀取文件信息的時候梗摇,也同樣可以復用之前PackageInstallerActivity的流程拓哟。

進入到PackageInstallerActivity中,首先初始化了一堆安裝應用所需要的對象:PackageManager伶授、IPackageManager断序、UserManager等。然后糜烹,經(jīng)過解析PackageInfo等信息违诗,最終調(diào)用checkIfAllowedAndInitiateInstall方法。

private void checkIfAllowedAndInitiateInstall() {
        // Check for install apps user restriction first.
        final int installAppsRestrictionSource = mUserManager.getUserRestrictionSource(
                UserManager.DISALLOW_INSTALL_APPS, Process.myUserHandle());
        if ((installAppsRestrictionSource & UserManager.RESTRICTION_SOURCE_SYSTEM) != 0) {
            showDialogInner(DLG_INSTALL_APPS_RESTRICTED_FOR_USER);
            return;
        } else if (installAppsRestrictionSource != UserManager.RESTRICTION_NOT_SET) {
            startActivity(new Intent(Settings.ACTION_SHOW_ADMIN_SUPPORT_DETAILS));
            finish();
            return;
        }

        if (mAllowUnknownSources || !isInstallRequestFromUnknownSource(getIntent())) {
            initiateInstall();
        } else {
            // Check for unknown sources restrictions.
            final int unknownSourcesRestrictionSource = mUserManager.getUserRestrictionSource(
                    UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, Process.myUserHandle());
            final int unknownSourcesGlobalRestrictionSource = mUserManager.getUserRestrictionSource(
                    UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY, Process.myUserHandle());
            final int systemRestriction = UserManager.RESTRICTION_SOURCE_SYSTEM
                    & (unknownSourcesRestrictionSource | unknownSourcesGlobalRestrictionSource);
            if (systemRestriction != 0) {
                showDialogInner(DLG_UNKNOWN_SOURCES_RESTRICTED_FOR_USER);
            } else if (unknownSourcesRestrictionSource != UserManager.RESTRICTION_NOT_SET) {
                startAdminSupportDetailsActivity(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES);
            } else if (unknownSourcesGlobalRestrictionSource != UserManager.RESTRICTION_NOT_SET) {
                startAdminSupportDetailsActivity(
                        UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY);
            } else {
                handleUnknownSources();
            }
        }
    }

大概看一下這個方法疮蹦,主要是判斷是不是允許安裝未知來源應用或者判斷是不是未知來源應用诸迟,如果不是的話進入正常安裝流程即走initiateInstall方法,如果是未知來源應用則會提示跳轉到設置頁面去開啟允許安裝未知來源應用的開關。

下面就進入到初始化安裝的確認頁面了阵苇,即走startInstallConfirm方法壁公。
這個方法會初始化安裝確認頁面,然后會列出安裝apk需要訪問的系統(tǒng)權限绅项。

至此紊册,PackageInstaller初始化的工作就完成了。
簡單總結一下PackageInstaller初始化的過程:

1.根據(jù)Uri的scheme協(xié)議的不同快耿,跳轉到不同的頁面囊陡。如果是Content協(xié)議,也就是走ContentProvider類型的則跳轉InstallStart頁面润努,其他的則跳轉的PackageInstallerActivity頁面关斜。不過最終都會進入到PackageInstallerActivity頁面進行安裝的初始化流程。

2.PackageInstallerActivity會對package協(xié)議和file協(xié)議進行分別處理铺浇,如果是file協(xié)議痢畜,會解析apk文件進而得到包信息PackageInfo。

3.PackageInstallerActivity會對未知來源的APK進行處理鳍侣,如果允許未知來源的應用或者APK不屬于未知來源則會初始化安裝確認頁面丁稀。否則,彈出提示對話框或者跳轉到設置頁面倚聚。

ok线衫,準備工作已經(jīng)做完了,那正式進入到安裝流程了惑折。
當我們點擊安裝確認頁面的確認按鈕時授账,我們就正式進入了安裝流程了。

private void startInstall() {
        // Start subactivity to actually install the application
        Intent newIntent = new Intent();
        newIntent.putExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO,
                mPkgInfo.applicationInfo);
        newIntent.setData(mPackageURI);
        newIntent.setClass(this, InstallInstalling.class);
        String installerPackageName = getIntent().getStringExtra(
                Intent.EXTRA_INSTALLER_PACKAGE_NAME);
        if (mOriginatingURI != null) {
            newIntent.putExtra(Intent.EXTRA_ORIGINATING_URI, mOriginatingURI);
        }
        if (mReferrerURI != null) {
            newIntent.putExtra(Intent.EXTRA_REFERRER, mReferrerURI);
        }
        if (mOriginatingUid != PackageInstaller.SessionParams.UID_UNKNOWN) {
            newIntent.putExtra(Intent.EXTRA_ORIGINATING_UID, mOriginatingUid);
        }
        if (installerPackageName != null) {
            newIntent.putExtra(Intent.EXTRA_INSTALLER_PACKAGE_NAME,
                    installerPackageName);
        }
        if (getIntent().getBooleanExtra(Intent.EXTRA_RETURN_RESULT, false)) {
            newIntent.putExtra(Intent.EXTRA_RETURN_RESULT, true);
        }
        newIntent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
        if(localLOGV) Log.i(TAG, "downloaded app uri="+mPackageURI);
        startActivity(newIntent);
        finish();
    }

可以看出會跳轉到InstallInstalling這個Activity中惨驶,并關閉當前PackageInstallerActivity白热。
在InstallInstalling中,會注冊一個廣播來監(jiān)聽安裝apk最后的結果粗卜。即InstallEventReceiver屋确。然后會開啟一個InstallingAsyncTask任務,執(zhí)行這個任務即是安裝apk的過程续扔。

 @Override
    protected void onResume() {
        super.onResume();

        // This is the first onResume in a single life of the activity
        if (mInstallingTask == null) {
            PackageInstaller installer = getPackageManager().getPackageInstaller();
            PackageInstaller.SessionInfo sessionInfo = installer.getSessionInfo(mSessionId);

            if (sessionInfo != null && !sessionInfo.isActive()) {
                mInstallingTask = new InstallingAsyncTask();
                mInstallingTask.execute();
            } else {
                // we will receive a broadcast when the install is finished
                mCancelButton.setEnabled(false);
                setFinishOnTouchOutside(false);
            }
        }
    }

我們看一下InstallingAsyncTask最終的執(zhí)行結果攻臀,

 @Override
        protected void onPostExecute(PackageInstaller.Session session) {
            if (session != null) {
                Intent broadcastIntent = new Intent(BROADCAST_ACTION);
                broadcastIntent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
                broadcastIntent.setPackage(getPackageName());
                broadcastIntent.putExtra(EventResultPersister.EXTRA_ID, mInstallId);

                PendingIntent pendingIntent = PendingIntent.getBroadcast(
                        InstallInstalling.this,
                        mInstallId,
                        broadcastIntent,
                        PendingIntent.FLAG_UPDATE_CURRENT);

                session.commit(pendingIntent.getIntentSender());
                mCancelButton.setEnabled(false);
                setFinishOnTouchOutside(false);
            } else {
                getPackageManager().getPackageInstaller().abandonSession(mSessionId);

                if (!isCancelled()) {
                    launchFailure(PackageManager.INSTALL_FAILED_INVALID_APK, null);
                }
            }
        }

最終調(diào)用的session.commit方法,將這個intent發(fā)出去了纱昧。
而這個session其實是PackageInstallerSession刨啸,最終調(diào)用的是PMS的installState方法。

那么現(xiàn)在我們就來到了我們的主角PMS了识脆。

上面我們分析到设联,最終是調(diào)用到PMS的installStage了加匈。

 void installStage(ActiveInstallSession activeInstallSession) {
        if (DEBUG_INSTANT) {
            if ((activeInstallSession.getSessionParams().installFlags
                    & PackageManager.INSTALL_INSTANT_APP) != 0) {
                Slog.d(TAG, "Ephemeral install of " + activeInstallSession.getPackageName());
            }
        }
        final Message msg = mHandler.obtainMessage(INIT_COPY);
        final InstallParams params = new InstallParams(activeInstallSession);
        params.setTraceMethod("installStage").setTraceCookie(System.identityHashCode(params));
        msg.obj = params;

        Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "installStage",
                System.identityHashCode(msg.obj));
        Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "queueInstall",
                System.identityHashCode(msg.obj));

        mHandler.sendMessage(msg);
    }

可以發(fā)現(xiàn),其實是向mHandler發(fā)送了一個INIT_COPY的message仑荐。而這個mHandler其實是PackageHandler。它繼承自Handler纵东,我們大概看一下對INIT_COPY消息的處理粘招。
[圖片上傳失敗...(image-9176ee-1608472714341)]

那我們知道,其實安裝apk的過程就是將對應的apk的文件解壓并copy到指定目錄的過程偎球。在copy的過程當中實際上是將對應的文件存儲到了臨時的一個目錄當中洒扎。


PackageHandler處理安裝消息調(diào)用時序圖(摘自劉望舒https://blog.csdn.net/itachi85/article/details/81321138?utm_source=blogxgwz1)

復制工作完成之后,才最后進入到apk的安裝衰絮。
先上一張大神的時序圖袍冷,完了我們再來跟代碼:

安裝apk的時序圖

我們上面跟到,handleStartCopy。下面緊接著就調(diào)用handleReturnCode方法猫牡。

  @Override
        void handleReturnCode() {
            for (InstallParams params : mChildParams) {
                params.handleReturnCode();
                if (params.mRet != INSTALL_SUCCEEDED) {
                    mRet = params.mRet;
                }
            }
        }

最終調(diào)用 processPendingInstall(mArgs, mRet);

 // Queue up an async operation since the package installation may take a little while.
    private void processInstallRequestsAsync(boolean success,
            List<InstallRequest> installRequests) {
        mHandler.post(() -> {
            if (success) {
                for (InstallRequest request : installRequests) {
                    request.args.doPreInstall(request.installResult.returnCode);
                }
                synchronized (mInstallLock) {
                    installPackagesTracedLI(installRequests);
                }
                for (InstallRequest request : installRequests) {
                    request.args.doPostInstall(
                            request.installResult.returnCode, request.installResult.uid);
                }
            }
            for (InstallRequest request : installRequests) {
                restoreAndPostInstall(request.args.user.getIdentifier(), request.installResult,
                        new PostInstallData(request.args, request.installResult, null));
            }
        });
    }

最終調(diào)用的是installPackagesTracedLI方法胡诗。

private void installPackagesLI(List<InstallRequest> requests) {
        final Map<String, ScanResult> preparedScans = new ArrayMap<>(requests.size());
        final Map<String, InstallArgs> installArgs = new ArrayMap<>(requests.size());
        final Map<String, PackageInstalledInfo> installResults = new ArrayMap<>(requests.size());
        final Map<String, PrepareResult> prepareResults = new ArrayMap<>(requests.size());
        final Map<String, VersionInfo> versionInfos = new ArrayMap<>(requests.size());
        final Map<String, PackageSetting> lastStaticSharedLibSettings =
                new ArrayMap<>(requests.size());
        final Map<String, Boolean> createdAppId = new ArrayMap<>(requests.size());
        boolean success = false;
        try {
            Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "installPackagesLI");
            for (InstallRequest request : requests) {
                // TODO(b/109941548): remove this once we've pulled everything from it and into
                //                    scan, reconcile or commit.
                final PrepareResult prepareResult;
                try {
                    Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "preparePackage");
                    prepareResult =
                            preparePackageLI(request.args, request.installResult);
                } catch (PrepareFailure prepareFailure) {
                    request.installResult.setError(prepareFailure.error,
                            prepareFailure.getMessage());
                    request.installResult.origPackage = prepareFailure.conflictingPackage;
                    request.installResult.origPermission = prepareFailure.conflictingPermission;
                    return;
                } finally {
                    Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
                }
                request.installResult.setReturnCode(PackageManager.INSTALL_SUCCEEDED);
                request.installResult.installerPackageName =
                        request.args.installSource.installerPackageName;

                final String packageName = prepareResult.packageToScan.getPackageName();
                prepareResults.put(packageName, prepareResult);
                installResults.put(packageName, request.installResult);
                installArgs.put(packageName, request.args);
                try {
                    final ScanResult result = scanPackageTracedLI(
                            prepareResult.packageToScan, prepareResult.parseFlags,
                            prepareResult.scanFlags, System.currentTimeMillis(),
                            request.args.user, request.args.abiOverride);
                    if (null != preparedScans.put(result.pkgSetting.pkg.getPackageName(), result)) {
                        request.installResult.setError(
                                PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE,
                                "Duplicate package " + result.pkgSetting.pkg.getPackageName()
                                        + " in multi-package install request.");
                        return;
                    }
                    createdAppId.put(packageName, optimisticallyRegisterAppId(result));
                    versionInfos.put(result.pkgSetting.pkg.getPackageName(),
                            getSettingsVersionForPackage(result.pkgSetting.pkg));
                    if (result.staticSharedLibraryInfo != null) {
                        final PackageSetting sharedLibLatestVersionSetting =
                                getSharedLibLatestVersionSetting(result);
                        if (sharedLibLatestVersionSetting != null) {
                            lastStaticSharedLibSettings.put(result.pkgSetting.pkg.getPackageName(),
                                    sharedLibLatestVersionSetting);
                        }
                    }
                } catch (PackageManagerException e) {
                    request.installResult.setError("Scanning Failed.", e);
                    return;
                }
            }
            ReconcileRequest reconcileRequest = new ReconcileRequest(preparedScans, installArgs,
                    installResults,
                    prepareResults,
                    mSharedLibraries,
                    Collections.unmodifiableMap(mPackages), versionInfos,
                    lastStaticSharedLibSettings);
            CommitRequest commitRequest = null;
            synchronized (mLock) {
                Map<String, ReconciledPackage> reconciledPackages;
                try {
                    Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "reconcilePackages");
                    reconciledPackages = reconcilePackagesLocked(
                            reconcileRequest, mSettings.mKeySetManagerService);
                } catch (ReconcileFailure e) {
                    for (InstallRequest request : requests) {
                        request.installResult.setError("Reconciliation failed...", e);
                    }
                    return;
                } finally {
                    Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
                }
                try {
                    Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "commitPackages");
                    commitRequest = new CommitRequest(reconciledPackages,
                            mUserManager.getUserIds());
                    commitPackagesLocked(commitRequest);
                    success = true;
                } finally {
                    Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
                }
            }
            executePostCommitSteps(commitRequest);
        } finally {
            if (success) {
                for (InstallRequest request : requests) {
                    final InstallArgs args = request.args;
                    if (args.mDataLoaderType != DataLoaderType.INCREMENTAL) {
                        continue;
                    }
                    if (args.signingDetails.signatureSchemeVersion != SIGNING_BLOCK_V4) {
                        continue;
                    }
                    // For incremental installs, we bypass the verifier prior to install. Now
                    // that we know the package is valid, send a notice to the verifier with
                    // the root hash of the base.apk.
                    final String baseCodePath = request.installResult.pkg.getBaseCodePath();
                    final String[] splitCodePaths = request.installResult.pkg.getSplitCodePaths();
                    final Uri originUri = Uri.fromFile(args.origin.resolvedFile);
                    final int verificationId = mPendingVerificationToken++;
                    final String rootHashString = PackageManagerServiceUtils
                            .buildVerificationRootHashString(baseCodePath, splitCodePaths);
                    broadcastPackageVerified(verificationId, originUri,
                            PackageManager.VERIFICATION_ALLOW, rootHashString,
                            args.mDataLoaderType, args.getUser());
                }
            } else {
                for (ScanResult result : preparedScans.values()) {
                    if (createdAppId.getOrDefault(result.request.parsedPackage.getPackageName(),
                            false)) {
                        cleanUpAppIdCreation(result);
                    }
                }
                // TODO(patb): create a more descriptive reason than unknown in future release
                // mark all non-failure installs as UNKNOWN so we do not treat them as success
                for (InstallRequest request : requests) {
                    if (request.installResult.freezer != null) {
                        request.installResult.freezer.close();
                    }
                    if (request.installResult.returnCode == PackageManager.INSTALL_SUCCEEDED) {
                        request.installResult.returnCode = PackageManager.INSTALL_UNKNOWN;
                    }
                }
            }
            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
        }
    }

大概總結一下installPackageLI:

1.創(chuàng)建PackageParser,解析APK
2.檢查APK是否存在淌友,如果存在就獲取此前沒被改名前的包名并在注釋1處賦值給PackageParser.Package類型的pkg煌恢。
3.如果Settings中存在要安裝的APK的信息,說明此前安裝過該APK震庭,則需要校驗APK的簽名信息瑰抵,確保替換安裝是安全的
4.重命名臨時文件。
5.系統(tǒng)App的更新安裝會有兩個限制器联,一個是系統(tǒng)App不能安裝在sd卡上二汛,另一個是系統(tǒng)app不能被Instant App替換。

至此拨拓,PMS處理APK安裝就完成了肴颊。
總結一下步驟:

1.PackageInstaller安裝APK時會將APK的信息交由PMS處理,PMS通過向PackageHandler發(fā)送消息來驅動apk的復制和安裝工作千元。
2.PMS發(fā)送INIT_COPY和MCS_BOUND類型的消息苫昌,控制PackageHandler來綁定DefaultContainerService,完成復制APK等工作
3.復制完APK后幸海,開始進行安裝APK的流程祟身,包括安裝前的檢查、安裝APK和安裝后的收尾工作物独。

后續(xù)袜硫,作者還介紹了PMS的創(chuàng)建過程。簡單的說就是在開機過程中挡篓,由SystemServer完成的啟動關鍵服務過程中創(chuàng)建的婉陷。具體過程看如下代碼:

 public static void main(String[] args) {
        new SystemServer().run();
    }
//run方法中
 // Start services.
        try {
            t.traceBegin("StartServices");
            startBootstrapServices(t);
            startCoreServices(t);
            startOtherServices(t);
        } catch (Throwable ex) {
            Slog.e("System", "******************************************");
            Slog.e("System", "************ Failure starting system services", ex);
            throw ex;
        } finally {
            t.traceEnd(); // StartServices
        }
//而PMS就是在startBootstrapServices中
private void startBootstrapServices(@NonNull TimingsTraceAndSlog t) {
        t.traceBegin("startBootstrapServices");

        // Start the watchdog as early as possible so we can crash the system server
        // if we deadlock during early boot
        t.traceBegin("StartWatchdog");
        final Watchdog watchdog = Watchdog.getInstance();
        watchdog.start();
        t.traceEnd();

        Slog.i(TAG, "Reading configuration...");
        final String TAG_SYSTEM_CONFIG = "ReadingSystemConfig";
        t.traceBegin(TAG_SYSTEM_CONFIG);
        SystemServerInitThreadPool.submit(SystemConfig::getInstance, TAG_SYSTEM_CONFIG);
        t.traceEnd();

        // Platform compat service is used by ActivityManagerService, PackageManagerService, and
        // possibly others in the future. b/135010838.
        t.traceBegin("PlatformCompat");
        PlatformCompat platformCompat = new PlatformCompat(mSystemContext);
        ServiceManager.addService(Context.PLATFORM_COMPAT_SERVICE, platformCompat);
        ServiceManager.addService(Context.PLATFORM_COMPAT_NATIVE_SERVICE,
                new PlatformCompatNative(platformCompat));
        AppCompatCallbacks.install(new long[0]);
        t.traceEnd();

        // FileIntegrityService responds to requests from apps and the system. It needs to run after
        // the source (i.e. keystore) is ready, and before the apps (or the first customer in the
        // system) run.
        t.traceBegin("StartFileIntegrityService");
        mSystemServiceManager.startService(FileIntegrityService.class);
        t.traceEnd();

        // Wait for installd to finish starting up so that it has a chance to
        // create critical directories such as /data/user with the appropriate
        // permissions.  We need this to complete before we initialize other services.
        t.traceBegin("StartInstaller");
        Installer installer = mSystemServiceManager.startService(Installer.class);
        t.traceEnd();

        // In some cases after launching an app we need to access device identifiers,
        // therefore register the device identifier policy before the activity manager.
        t.traceBegin("DeviceIdentifiersPolicyService");
        mSystemServiceManager.startService(DeviceIdentifiersPolicyService.class);
        t.traceEnd();

        // Uri Grants Manager.
        t.traceBegin("UriGrantsManagerService");
        mSystemServiceManager.startService(UriGrantsManagerService.Lifecycle.class);
        t.traceEnd();

        // Activity manager runs the show.
        t.traceBegin("StartActivityManager");
        // TODO: Might need to move after migration to WM.
        ActivityTaskManagerService atm = mSystemServiceManager.startService(
                ActivityTaskManagerService.Lifecycle.class).getService();
        mActivityManagerService = ActivityManagerService.Lifecycle.startService(
                mSystemServiceManager, atm);
        mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
        mActivityManagerService.setInstaller(installer);
        mWindowManagerGlobalLock = atm.getGlobalLock();
        t.traceEnd();

        // Data loader manager service needs to be started before package manager
        t.traceBegin("StartDataLoaderManagerService");
        mDataLoaderManagerService = mSystemServiceManager.startService(
                DataLoaderManagerService.class);
        t.traceEnd();

        // Incremental service needs to be started before package manager
        t.traceBegin("StartIncrementalService");
        mIncrementalServiceHandle = startIncrementalService();
        t.traceEnd();

        // Power manager needs to be started early because other services need it.
        // Native daemons may be watching for it to be registered so it must be ready
        // to handle incoming binder calls immediately (including being able to verify
        // the permissions for those calls).
        t.traceBegin("StartPowerManager");
        mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);
        t.traceEnd();

        t.traceBegin("StartThermalManager");
        mSystemServiceManager.startService(ThermalManagerService.class);
        t.traceEnd();

        // Now that the power manager has been started, let the activity manager
        // initialize power management features.
        t.traceBegin("InitPowerManagement");
        mActivityManagerService.initPowerManagement();
        t.traceEnd();

        // Bring up recovery system in case a rescue party needs a reboot
        t.traceBegin("StartRecoverySystemService");
        mSystemServiceManager.startService(RecoverySystemService.Lifecycle.class);
        t.traceEnd();

        // Now that we have the bare essentials of the OS up and running, take
        // note that we just booted, which might send out a rescue party if
        // we're stuck in a runtime restart loop.
        RescueParty.registerHealthObserver(mSystemContext);
        PackageWatchdog.getInstance(mSystemContext).noteBoot();

        // Manages LEDs and display backlight so we need it to bring up the display.
        t.traceBegin("StartLightsService");
        mSystemServiceManager.startService(LightsService.class);
        t.traceEnd();

        t.traceBegin("StartSidekickService");
        // Package manager isn't started yet; need to use SysProp not hardware feature
        if (SystemProperties.getBoolean("config.enable_sidekick_graphics", false)) {
            mSystemServiceManager.startService(WEAR_SIDEKICK_SERVICE_CLASS);
        }
        t.traceEnd();

        // Display manager is needed to provide display metrics before package manager
        // starts up.
        t.traceBegin("StartDisplayManager");
        mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class);
        t.traceEnd();

        // We need the default display before we can initialize the package manager.
        t.traceBegin("WaitForDisplay");
        mSystemServiceManager.startBootPhase(t, SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);
        t.traceEnd();

        // Only run "core" apps if we're encrypting the device.
        String cryptState = VoldProperties.decrypt().orElse("");
        if (ENCRYPTING_STATE.equals(cryptState)) {
            Slog.w(TAG, "Detected encryption in progress - only parsing core apps");
            mOnlyCore = true;
        } else if (ENCRYPTED_STATE.equals(cryptState)) {
            Slog.w(TAG, "Device encrypted - only parsing core apps");
            mOnlyCore = true;
        }

        // Start the package manager.
        if (!mRuntimeRestart) {
            FrameworkStatsLog.write(FrameworkStatsLog.BOOT_TIME_EVENT_ELAPSED_TIME_REPORTED,
                    FrameworkStatsLog
                            .BOOT_TIME_EVENT_ELAPSED_TIME__EVENT__PACKAGE_MANAGER_INIT_START,
                    SystemClock.elapsedRealtime());
        }

        t.traceBegin("StartPackageManagerService");
        try {
            Watchdog.getInstance().pauseWatchingCurrentThread("packagemanagermain");
            mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
                    mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
        } finally {
            Watchdog.getInstance().resumeWatchingCurrentThread("packagemanagermain");
        }

        // Now that the package manager has started, register the dex load reporter to capture any
        // dex files loaded by system server.
        // These dex files will be optimized by the BackgroundDexOptService.
        SystemServerDexLoadReporter.configureSystemServerDexReporter(mPackageManagerService);

        mFirstBoot = mPackageManagerService.isFirstBoot();
        mPackageManager = mSystemContext.getPackageManager();
        t.traceEnd();
        if (!mRuntimeRestart && !isFirstBootOrUpgrade()) {
            FrameworkStatsLog.write(FrameworkStatsLog.BOOT_TIME_EVENT_ELAPSED_TIME_REPORTED,
                    FrameworkStatsLog
                            .BOOT_TIME_EVENT_ELAPSED_TIME__EVENT__PACKAGE_MANAGER_INIT_READY,
                    SystemClock.elapsedRealtime());
        }
        // Manages A/B OTA dexopting. This is a bootstrap service as we need it to rename
        // A/B artifacts after boot, before anything else might touch/need them.
        // Note: this isn't needed during decryption (we don't have /data anyways).
        if (!mOnlyCore) {
            boolean disableOtaDexopt = SystemProperties.getBoolean("config.disable_otadexopt",
                    false);
            if (!disableOtaDexopt) {
                t.traceBegin("StartOtaDexOptService");
                try {
                    Watchdog.getInstance().pauseWatchingCurrentThread("moveab");
                    OtaDexoptService.main(mSystemContext, mPackageManagerService);
                } catch (Throwable e) {
                    reportWtf("starting OtaDexOptService", e);
                } finally {
                    Watchdog.getInstance().resumeWatchingCurrentThread("moveab");
                    t.traceEnd();
                }
            }
        }

        t.traceBegin("StartUserManagerService");
        mSystemServiceManager.startService(UserManagerService.LifeCycle.class);
        t.traceEnd();

        // Initialize attribute cache used to cache resources from packages.
        t.traceBegin("InitAttributerCache");
        AttributeCache.init(mSystemContext);
        t.traceEnd();

        // Set up the Application instance for the system process and get started.
        t.traceBegin("SetSystemProcess");
        mActivityManagerService.setSystemProcess();
        t.traceEnd();

        // Complete the watchdog setup with an ActivityManager instance and listen for reboots
        // Do this only after the ActivityManagerService is properly started as a system process
        t.traceBegin("InitWatchdog");
        watchdog.init(mSystemContext, mActivityManagerService);
        t.traceEnd();

        // DisplayManagerService needs to setup android.display scheduling related policies
        // since setSystemProcess() would have overridden policies due to setProcessGroup
        mDisplayManagerService.setupSchedulerPolicies();

        // Manages Overlay packages
        t.traceBegin("StartOverlayManagerService");
        mSystemServiceManager.startService(new OverlayManagerService(mSystemContext));
        t.traceEnd();

        t.traceBegin("StartSensorPrivacyService");
        mSystemServiceManager.startService(new SensorPrivacyService(mSystemContext));
        t.traceEnd();

        if (SystemProperties.getInt("persist.sys.displayinset.top", 0) > 0) {
            // DisplayManager needs the overlay immediately.
            mActivityManagerService.updateSystemUiContext();
            LocalServices.getService(DisplayManagerInternal.class).onOverlayChanged();
        }

        // The sensor service needs access to package manager service, app ops
        // service, and permissions service, therefore we start it after them.
        // Start sensor service in a separate thread. Completion should be checked
        // before using it.
        mSensorServiceStart = SystemServerInitThreadPool.submit(() -> {
            TimingsTraceAndSlog traceLog = TimingsTraceAndSlog.newAsyncLog();
            traceLog.traceBegin(START_SENSOR_SERVICE);
            startSensorService();
            traceLog.traceEnd();
        }, START_SENSOR_SERVICE);

        t.traceEnd(); // startBootstrapServices
    }

可以看到帚称,PMS和AMS的初始化都在其中,那還有另一個常見的WMS在哪里初始化的呢秽澳?
WMS以及IMS都是在startOtherServices方法中初始化的闯睹。
好了,下次再看WMS和AMS吧5I瘛Bコ浴!

?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末妄讯,一起剝皮案震驚了整個濱河市孩锡,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌亥贸,老刑警劉巖躬窜,帶你破解...
    沈念sama閱讀 218,941評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異炕置,居然都是意外死亡荣挨,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評論 3 395
  • 文/潘曉璐 我一進店門讹俊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來垦沉,“玉大人,你說我怎么就攤上這事仍劈〔薇叮” “怎么了?”我有些...
    開封第一講書人閱讀 165,345評論 0 356
  • 文/不壞的土叔 我叫張陵贩疙,是天一觀的道長讹弯。 經(jīng)常有香客問我,道長这溅,這世上最難降的妖魔是什么组民? 我笑而不...
    開封第一講書人閱讀 58,851評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮悲靴,結果婚禮上臭胜,老公的妹妹穿的比我還像新娘。我一直安慰自己癞尚,他們只是感情好耸三,可當我...
    茶點故事閱讀 67,868評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著浇揩,像睡著了一般仪壮。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上胳徽,一...
    開封第一講書人閱讀 51,688評論 1 305
  • 那天积锅,我揣著相機與錄音爽彤,去河邊找鬼。 笑死缚陷,一個胖子當著我的面吹牛适篙,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播箫爷,決...
    沈念sama閱讀 40,414評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼匙瘪,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了蝶缀?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,319評論 0 276
  • 序言:老撾萬榮一對情侶失蹤薄货,失蹤者是張志新(化名)和其女友劉穎翁都,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體谅猾,經(jīng)...
    沈念sama閱讀 45,775評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡柄慰,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了税娜。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片坐搔。...
    茶點故事閱讀 40,096評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖敬矩,靈堂內(nèi)的尸體忽然破棺而出概行,到底是詐尸還是另有隱情,我是刑警寧澤弧岳,帶...
    沈念sama閱讀 35,789評論 5 346
  • 正文 年R本政府宣布凳忙,位于F島的核電站,受9級特大地震影響禽炬,放射性物質(zhì)發(fā)生泄漏涧卵。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,437評論 3 331
  • 文/蒙蒙 一腹尖、第九天 我趴在偏房一處隱蔽的房頂上張望柳恐。 院中可真熱鬧,春花似錦热幔、人聲如沸乐设。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽伤提。三九已至,卻和暖如春认烁,著一層夾襖步出監(jiān)牢的瞬間肿男,已是汗流浹背介汹。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留舶沛,地道東北人嘹承。 一個月前我還...
    沈念sama閱讀 48,308評論 3 372
  • 正文 我出身青樓,卻偏偏與公主長得像如庭,于是被迫代替她去往敵國和親叹卷。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,037評論 2 355

推薦閱讀更多精彩內(nèi)容