• Android 进阶——系统启动之SystemServer创建并启动PackageManagerService服务(十一)


    引言

    SystemServer首先启动,创建一个ServerThread线程来启动所有Android核心服务,在创建和启动InstallerActivityManagerServicePowerManagerService、RecoverySystemService、LightsService、DisplayManagerService系统服务启动之后,PackageManagerService就会接着被创建和启动。

    基于Android 28,为了阅读,本文约定方法表示Java的,而函数表示Native层概念,仅供参考

    一、PackageManagerService概述

    PackageManagerService(PKMS)作为管理APK包的系统服务,负责APK包的安装、卸载、优化和查询,

    Android 系统在启动过程中会通过PKMS(PackageManagerService)服务自动去扫描系统中指定的目录寻找APK文件、JAR包和SO库,并逐一解析封装为对应的对象再保存到内存中,系统运行时就迅速找到对应的信息并自动安装。

    PKMS在扫描时遇到需要优化的文件还会额外执行转换工作,将APK的dex格式优化为oat格式(Linux 的ELF格式的一种私有形式)。

    在PKMS 在准备安装APK时主要做了两大工作:

    • 解析APK的清单文件(AndroidManifest.xml)获取其对应的包信息供后面封装为对应的JavaBean 对象(即APK的内存描述对象)
    • App 分配Linux的用户Id 和Linux 用户组Id ,要不然可能在系统里运行时因为安全机制无法得到对应的权限。所以Android 中么一个App 都有一个对应的Linux 用户ID,在PMS 安装该App 时检测发现它没有和其他应用共享同一个用户ID时,就会自动给其分配一个用户ID,除了用户ID之外,当PMS安装时还发现该App 申请了一个特殊的资源访问权限,还会给其分配对应的Linux 用户组ID

    当所有App都安装完毕之后,Android Framework 还会启动Home Launcher 应用程序在Launcher 启动。

    二、PackageManagerService 体系结构概述

    \frameworks\base\core\java\android\content\pm\IPackageManager.aidl

    \out\target\common\obj\JAVA_LIBRARIES\framework_intermediates\src\core\java\android\content\pm\IPackageManager.java

    作为Android 系统的核心服务,PackageManagerService自然也是采用Binder 服务的架构,当某个进程需要访问某个系统服务时首先得通过ServiceManager 获取其对应的Binder对象,从而调用对应的方法,至于中间的通信细节全部由Binder 通信去完成,PackageManagerService 只是负责包管理的相关工作,解析完成之后再传到Installer服务里。

    在这里插入图片描述

    在应用进程里通过调用Context#getPackageManager() 得到ApplicationPackageManager 对象后,通过Binder 机制与PackageManagerService 服务通信,再由PackageManagerService 调用Installer服务,最终Installer服务通过socket 与installd 守护进程通信。

    在这里插入图片描述

    三、SystemServer进程启动PKMS服务

    在前面文章中介绍System进程(SystemServer.java)启动过程中,在AMS、PowerManagerService、DisplayManagerService核心服务启动后,会通过调用PackageManagerService#main方法将PMS 启动

    • 启动Installer服务
    • 启动AMS、PowerManagerService、DisplayManagerService系统服务
    • 调用PackageManagerService#main方法将PKMS 启动
    • 启动MountService
    • dex 优化
    • 调用PackageManagerService#systemReady 回调方法

    当然启动PMS 只是System进程启动后干的很小一部分工作,还有其他很多系统服务也会被启动,而且很多启动流程都大同小异。

    1、com.android.server.SystemServer#startBootstrapServices 触发PKMS 服务启动

    private void startBootstrapServices() {
        //启动Installer服务
        Installer installer = mSystemServiceManager.startService(Installer.class);
        ...
            // Activity manager runs the show.
            mActivityManagerService = mSystemServiceManager.startService(
            ActivityManagerService.Lifecycle.class).getService();
        mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
        mActivityManagerService.setInstaller(installer);		
        //创建 PKMS 对象
        mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
                    mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
        //PKMS是否首次启动
        mFirstBoot = mPackageManagerService.isFirstBoot();
        mPackageManager = mSystemContext.getPackageManager();
        //...
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    2、com.android.server.pm.PackageManagerService#main触发PMKS对象创建并注册到ServiceManager

        public static PackageManagerService main(Context context, Installer installer,
                boolean factoryTest, boolean onlyCore) {
            // Self-check for initial settings.
            PackageManagerServiceCompilerMapping.checkProperties();
    
            PackageManagerService m = new PackageManagerService(context, installer,
                    factoryTest, onlyCore);
            m.enableSystemUserPackages();
            ServiceManager.addService("package", m);
            final PackageManagerNative pmn = m.new PackageManagerNative();
            ServiceManager.addService("package_native", pmn);
            return m;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    3、PackageManagerService构造对象时完成Apk和Jar包的格式转化和扫描解析已安装的系统应用并提取信息

    PackageManagerService 在自己构造方法里主要完成两件事:

    • 把系统中指定目录的Apk文件和Jar包从dex格式转为oat格式
    • 扫描系统已安装的应用,并提取对应的信息
        public PackageManagerService(Context context, Installer installer,
                boolean factoryTest, boolean onlyCore) {
            //true 表示PMKS此次只处理系统应用, SystemProperties.get("vold.decrypt")得到值为trigger_restart_min_framework或者1时SystemServer传过来的参数为true
            mOnlyCore = onlyCore;
            //创建屏幕显示对象
            mMetrics = new DisplayMetrics();
            //mInstallLock 用来保护所有安装apk的访问权限,此操作通常涉及繁重的磁盘数据读写等操作,并且是单线程操作,故有时候会处理很慢
           	        synchronized (mInstallLock) {
                        //mpackages 用来解析内存中所有apk的package信息及相关状态
            synchronized (mPackages) {
                ...
                //多用户管理机制,这是google想模拟windows多用户管理系统,为未来的设计
                sUserManager = new UserManagerService(context, this,
                        new UserDataPreparer(mInstaller, mInstallLock, mContext, mOnlyCore), mPackages);
                mPermissionManager = PermissionManagerService.create(context,
                        new DefaultPermissionGrantedCallback() {
                            @Override
                            public void onDefaultRuntimePermissionsGranted(int userId) {
                                synchronized(mPackages) {
                                    mSettings.onDefaultRuntimePermissionsGrantedLPr(userId);
                                }
                            }
                        }, mPackages /*externalLock*/);
                mDefaultPermissionPolicy = mPermissionManager.getDefaultPermissionGrantPolicy();
                ///创建Settings对象
                mSettings = new Settings(mPermissionManager.getPermissionSettings(), mPackages);
            }
            }
             //创建 SharedUserSetting 对象并把system, phone, log, nfc, bluetooth, shell,se,networkstack 这8种shareUserId到mSettings,把这些系统应用的uid 保存起来,添加共享用户组的信息
            mSettings.addSharedUserLPw("android.uid.system", Process.SYSTEM_UID,
                    ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
            mSettings.addSharedUserLPw("android.uid.phone", RADIO_UID,
                    ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
    			...
             //dex优化工具类
            mPackageDexOptimizer = new PackageDexOptimizer(installer, mInstallLock, context,
                    "*dexopt*");
            //Dex 管理类
            mDexManager = new DexManager(mContext, this, mPackageDexOptimizer, installer, mInstallLock,
                    dexManagerListener);
            // ART虚拟机管理服务
            mArtManagerService = new ArtManagerService(mContext, this, installer, mInstallLock);
            mMoveCallbacks = new MoveCallbacks(FgThread.get().getLooper());
            getDefaultDisplayMetrics(context, mMetrics);//用系统属性设置DisplayMetrics
            //获取SystemConfig()的对象,在其构造方法中会调用readPermissions()完成权限的读取
            SystemConfig systemConfig = SystemConfig.getInstance();
            ...
    
            synchronized (mInstallLock) {
            // writer
            synchronized (mPackages) {
                //创建消息处理线程处理APK的安装和卸载请求
                mHandlerThread = new ServiceThread(TAG,
                        Process.THREAD_PRIORITY_BACKGROUND, true /*allowIo*/);
                mHandlerThread.start();
                //用于处理安装、卸载应用请求的Handler
                mHandler = new PackageHandler(mHandlerThread.getLooper());
                mProcessLoggingHandler = new ProcessLoggingHandler();//创建进程运行信息记录Handler
                Watchdog.getInstance().addThread(mHandler, WATCHDOG_TIMEOUT);//绑定到SystemServer 的Watchdog服务
               	...
                //com.android.server.pm.Settings mSettings 读取并解析/data/system下的XML文件
                mFirstBoot = !mSettingsreadLPw(sUserManager.getUsers(false));
    
                // 清理代码路径不存在的孤立软件包
                final int packageSettingCount = mSettings.mPackages.size();
                for (int i = packageSettingCount - 1; i >= 0; i--) {
                    PackageSetting ps = mSettings.mPackages.valueAt(i);
                    if (!isExternal(ps) && (ps.codePath == null || !ps.codePath.exists())
                            && mSettings.getDisabledSystemPkgLPr(ps.name) != null) {
                        mSettings.mPackages.removeAt(i);
                        mSettings.enableSystemPackageLPw(ps.name);
                    }
                }
    
                if (mFirstBoot) {
                    //拷贝预编译的DEX文件
                    requestCopyPreoptedFiles();
                }
                ...
                    ///获取环境变量 在init.rc里配置的
                final String bootClassPath = System.getenv("BOOTCLASSPATH");
                final String systemServerClassPath = System.getenv("SYSTEMSERVERCLASSPATH");
                File frameworkDir = new File(Environment.getRootDirectory(), "framework");           				...
                mCacheDir = preparePackageParserCache(mIsUpgrade);
    
                // Set flag to monitor and not change apk file paths when
                // scanning install directories.
                int scanFlags = SCAN_BOOTING | SCAN_INITIAL;
    
                if (mIsUpgrade || mFirstBoot) {
                    scanFlags = scanFlags | SCAN_FIRST_BOOT_OR_UPGRADE;
                }
    
                // Collect vendor/product overlay packages. (Do this before scanning any apps.)
                // For security and version matching reason, only consider
                // overlay packages if they reside in the right directory.
                scanDirTracedLI(new File(VENDOR_OVERLAY_DIR),
                        mDefParseFlags
                        | PackageParser.PARSE_IS_SYSTEM_DIR,
                        scanFlags
                        | SCAN_AS_SYSTEM
                        | SCAN_AS_VENDOR,
                        0);
                scanDirTracedLI(new File(PRODUCT_OVERLAY_DIR),
                        mDefParseFlags
                        | PackageParser.PARSE_IS_SYSTEM_DIR,
                        scanFlags
                        | SCAN_AS_SYSTEM
                        | SCAN_AS_PRODUCT,
                        0);
    
                mParallelPackageParserCallback.findStaticOverlayPackages();
    
                // Find base frameworks (resource packages without code).
                scanDirTracedLI(frameworkDir,
                        mDefParseFlags
                        | PackageParser.PARSE_IS_SYSTEM_DIR,
                        scanFlags
                        | SCAN_NO_DEX
                        | SCAN_AS_SYSTEM
                        | SCAN_AS_PRIVILEGED,
                        0);
    
                // Collect privileged system packages.
                final File privilegedAppDir = new File(Environment.getRootDirectory(), "priv-app");
                scanDirTracedLI(privilegedAppDir,
                        mDefParseFlags
                        | PackageParser.PARSE_IS_SYSTEM_DIR,
                        scanFlags
                        | SCAN_AS_SYSTEM
                        | SCAN_AS_PRIVILEGED,
                        0);
    
                // Collect ordinary system packages.
                final File systemAppDir = new File(Environment.getRootDirectory(), "app");
                scanDirTracedLI(systemAppDir,
                        mDefParseFlags
                        | PackageParser.PARSE_IS_SYSTEM_DIR,
                        scanFlags
                        | SCAN_AS_SYSTEM,
                        0);
    
                // Collect privileged vendor packages.
                File privilegedVendorAppDir = new File(Environment.getVendorDirectory(), "priv-app");
                try {
                    privilegedVendorAppDir = privilegedVendorAppDir.getCanonicalFile();
                } catch (IOException e) {
                    // failed to look up canonical path, continue with original one
                }
                scanDirTracedLI(privilegedVendorAppDir,
                        mDefParseFlags
                        | PackageParser.PARSE_IS_SYSTEM_DIR,
                        scanFlags
                        | SCAN_AS_SYSTEM
                        | SCAN_AS_VENDOR
                        | SCAN_AS_PRIVILEGED,
                        0);
    
                // Collect ordinary vendor packages.
                File vendorAppDir = new File(Environment.getVendorDirectory(), "app");
                try {
                    vendorAppDir = vendorAppDir.getCanonicalFile();
                } catch (IOException e) {
                    // failed to look up canonical path, continue with original one
                }
                scanDirTracedLI(vendorAppDir,
                        mDefParseFlags
                        | PackageParser.PARSE_IS_SYSTEM_DIR,
                        scanFlags
                        | SCAN_AS_SYSTEM
                        | SCAN_AS_VENDOR,
                        0);
    
                // Collect privileged odm packages. /odm is another vendor partition
                // other than /vendor.
                File privilegedOdmAppDir = new File(Environment.getOdmDirectory(),
                            "priv-app");
                try {
                    privilegedOdmAppDir = privilegedOdmAppDir.getCanonicalFile();
                } catch (IOException e) {
                    // failed to look up canonical path, continue with original one
                }
                scanDirTracedLI(privilegedOdmAppDir,
                        mDefParseFlags
                        | PackageParser.PARSE_IS_SYSTEM_DIR,
                        scanFlags
                        | SCAN_AS_SYSTEM
                        | SCAN_AS_VENDOR
                        | SCAN_AS_PRIVILEGED,
                        0);
    
                // Collect ordinary odm packages. /odm is another vendor partition
                // other than /vendor.
                File odmAppDir = new File(Environment.getOdmDirectory(), "app");
                try {
                    odmAppDir = odmAppDir.getCanonicalFile();
                } catch (IOException e) {
                    // failed to look up canonical path, continue with original one
                }
                scanDirTracedLI(odmAppDir,
                        mDefParseFlags
                        | PackageParser.PARSE_IS_SYSTEM_DIR,
                        scanFlags
                        | SCAN_AS_SYSTEM
                        | SCAN_AS_VENDOR,
                        0);
    
                // Collect all OEM packages.
                final File oemAppDir = new File(Environment.getOemDirectory(), "app");
                scanDirTracedLI(oemAppDir,
                        mDefParseFlags
                        | PackageParser.PARSE_IS_SYSTEM_DIR,
                        scanFlags
                        | SCAN_AS_SYSTEM
                        | SCAN_AS_OEM,
                        0);
    
                // Collected privileged product packages.
                File privilegedProductAppDir = new File(Environment.getProductDirectory(), "priv-app");
                try {
                    privilegedProductAppDir = privilegedProductAppDir.getCanonicalFile();
                } catch (IOException e) {
                    // failed to look up canonical path, continue with original one
                }
                scanDirTracedLI(privilegedProductAppDir,
                        mDefParseFlags
                        | PackageParser.PARSE_IS_SYSTEM_DIR,
                        scanFlags
                        | SCAN_AS_SYSTEM
                        | SCAN_AS_PRODUCT
                        | SCAN_AS_PRIVILEGED,
                        0);
    
                // Collect ordinary product packages.
                File productAppDir = new File(Environment.getProductDirectory(), "app");
                try {
                    productAppDir = productAppDir.getCanonicalFile();
                } catch (IOException e) {
                    // failed to look up canonical path, continue with original one
                }
                scanDirTracedLI(productAppDir,
                        mDefParseFlags
                        | PackageParser.PARSE_IS_SYSTEM_DIR,
                        scanFlags
                        | SCAN_AS_SYSTEM
                        | SCAN_AS_PRODUCT,
                        0);
    
                // 裁剪不在存在的系统应用的包package
                final List<String> possiblyDeletedUpdatedSystemApps = new ArrayList<>();
                final List<String> stubSystemApps = new ArrayList<>();
                if (!mOnlyCore) {
                    final Iterator<PackageSetting> psit = mSettings.mPackages.values().iterator();
                    while (psit.hasNext()) {
                        PackageSetting ps = psit.next();
                        /**
                         *如果得到的ps代表的package信息不是系统应用的则不能禁用
                         */
                        if ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0) {
                            continue;
                        }
                        final PackageParser.Package scannedPkg = mPackages.get(ps.name);
                        if (scannedPkg != null) {
                            if (mSettings.isDisabledSystemPackageLPr(ps.name)) {
                                removePackageLI(scannedPkg, true);
                                mExpectingBetter.put(ps.name, ps.codePath);
                            }
                            continue;
                        }
                        ...
                    }
                }
    
                //删除临时文件
                deleteTempPackageFiles();
                final int cachedSystemApps = PackageParser.sCachedPackageReadCount.get();
                //裁剪多余没有关联应用的uid
                mSettings.pruneSharedUsersLPw();
                if (!mOnlyCore) {
                    scanDirTracedLI(sAppInstallDir, 0, scanFlags | SCAN_REQUIRE_KNOWN, 0);
    
                    scanDirTracedLI(sDrmAppPrivateInstallDir, mDefParseFlags
                            | PackageParser.PARSE_FORWARD_LOCK,
                            scanFlags | SCAN_REQUIRE_KNOWN, 0);
    
                    // 删除已更新的系统应用程序的禁用包设置,通过 OTA 删除。 如果更新不再存在,完全删除应用程序。 否则,撤销其系统权限。
                    for (String deletedAppName : possiblyDeletedUpdatedSystemApps) {
                        PackageParser.Package deletedPkg = mPackages.get(deletedAppName);
                        mSettings.removeDisabledSystemPackageLPw(deletedAppName);
                        ...
                    }
                    //确保所有应该在userdata分区上显示的系统应用程序能正常显示,如果从未出现过,需要回滚以恢复
                    for (int i = 0; i < mExpectingBetter.size(); i++) {
                        final String packageName = mExpectingBetter.keyAt(i);
                        if (!mPackages.containsKey(packageName)) {
                            final File scanFile = mExpectingBetter.valueAt(i);
      								...
                            mSettings.enableSystemPackageLPw(packageName);
                            try {
                                //扫描指定目录下的apk
                                scanPackageTracedLI(scanFile, reparseFlags, rescanFlags, 0, null);
                            } 
                        }
                    }
    
                    // 解压缩并安装任何存根系统应用程序,以确保所有存根都被替换或禁用。 
                    decompressSystemApplications(stubSystemApps, scanFlags);
                // Resolve the storage manager.
                mStorageManagerPackage = getStorageManagerPackageName();
                // 更新以确保所有客户端持有正确的共享库路径
                updateAllSharedLibrariesLPw(null);
                mPackageUsage.read(mPackages);
                mCompilerStats.read();
    
                EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END,
                        SystemClock.uptimeMillis());
                Slog.i(TAG, "Time to scan packages: "
                        + ((SystemClock.uptimeMillis()-startTime)/1000f)
                        + " seconds");
    
                // 如果自上次启动以来,SDK版本已改变,则需重新授予应用程序权限以捕获出现的任何新权限
                final boolean sdkUpdated = (ver.sdkVersion != mSdkVersion);
                mPermissionManager.updateAllPermissions(
                        StorageManager.UUID_PRIVATE_INTERNAL, sdkUpdated, mPackages.values(),
                        mPermissionCallback);
                ver.sdkVersion = mSdkVersion;
    
                //第一次正常启动或者 M之前版本更新后正常启动的,需要初始化默认的首选应用程序 
                if (!onlyCore && (mPromoteSystemApps || mFirstBoot)) {
                    for (UserInfo user : sUserManager.getUsers(true)) {
                        mSettings.applyDefaultPreferredAppsLPw(this, user.id);
                        applyFactoryDefaultBrowserLPw(user.id);
                        primeDomainVerificationsLPw(user.id);
                    }
                }
    				...
               //如果是在OTA之后首次启动,并且正常启动,那需要清除代码缓存目录,但不清除应用程序配置文件
                if (mIsUpgrade && !onlyCore) {
                    for (int i = 0; i < mSettings.mPackages.size(); i++) {
                        final PackageSetting ps = mSettings.mPackages.valueAt(i);
                        if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, ps.volumeUuid)) {
                            clearAppDataLIF(ps.pkg, UserHandle.USER_ALL,
                                    StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE| Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
                        }
                    }
                    ver.fingerprint = Build.FINGERPRINT;
                }
               
                Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "write settings");
                mSettings.writeLPr();
               
                if (!mOnlyCore) {
                    mRequiredVerifierPackage = getRequiredButNotReallyRequiredVerifierLPr();
                    mRequiredInstallerPackage = getRequiredInstallerLPr();
                    mRequiredUninstallerPackage = getRequiredUninstallerLPr();
                    mIntentFilterVerifierComponent = getIntentFilterVerifierComponentNameLPr();
                    if (mIntentFilterVerifierComponent != null) {
                        mIntentFilterVerifier = new IntentVerifierProxy(mContext,
                                mIntentFilterVerifierComponent);
                    } else {
                        mIntentFilterVerifier = null;
                    }
                    mServicesSystemSharedLibraryPackageName = getRequiredSharedLibraryLPr(
                            PackageManager.SYSTEM_SHARED_LIBRARY_SERVICES,
                            SharedLibraryInfo.VERSION_UNDEFINED);
                    mSharedSystemSharedLibraryPackageName = getRequiredSharedLibraryLPr(
                            PackageManager.SYSTEM_SHARED_LIBRARY_SHARED,
                            SharedLibraryInfo.VERSION_UNDEFINED);
                } else {
                    mRequiredVerifierPackage = null;
                    mRequiredInstallerPackage = null;
                    mRequiredUninstallerPackage = null;
                    mIntentFilterVerifierComponent = null;
                    mIntentFilterVerifier = null;
                    mServicesSystemSharedLibraryPackageName = null;
                    mSharedSystemSharedLibraryPackageName = null;
                }
    				
                mInstallerService = new PackageInstallerService(context, this);
                final Pair<ComponentName, String> instantAppResolverComponent =
                        getInstantAppResolverLPr();
                if (instantAppResolverComponent != null) {
                    if (DEBUG_INSTANT) {
                        Slog.d(TAG, "Set ephemeral resolver: " + instantAppResolverComponent);
                    }
                    mInstantAppResolverConnection = new InstantAppResolverConnection(
                            mContext, instantAppResolverComponent.first,
                            instantAppResolverComponent.second);
                    mInstantAppResolverSettingsComponent =
                            getInstantAppResolverSettingsLPr(instantAppResolverComponent.first);
                } else {
                    mInstantAppResolverConnection = null;
                    mInstantAppResolverSettingsComponent = null;
                }
                updateInstantAppInstallerLocked(null);
    
                // Read and update the usage of dex files.
                // Do this at the end of PM init so that all the packages have their
                // data directory reconciled.
                // At this point we know the code paths of the packages, so we can validate
                // the disk file and build the internal cache.
                // The usage file is expected to be small so loading and verifying it
                // should take a fairly small time compare to the other activities (e.g. package
                // scanning).
                final Map<Integer, List<PackageInfo>> userPackages = new HashMap<>();
                final int[] currentUserIds = UserManagerService.getInstance().getUserIds();
                for (int userId : currentUserIds) {
                    userPackages.put(userId, getInstalledPackages(/*flags*/ 0, userId).getList());
                }
                mDexManager.load(userPackages);
                if (mIsUpgrade) {
                    MetricsLogger.histogram(null, "ota_package_manager_init_time",
                            (int) (SystemClock.uptimeMillis() - startTime));
                }
            } // synchronized (mPackages)
            } // synchronized (mInstallLock)
    
            // Now after opening every single application zip, make sure they
            // are all flushed.  Not really needed, but keeps things nice and
            // tidy.
            Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "GC");
            Runtime.getRuntime().gc();
            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
    
            // The initial scanning above does many calls into installd while
            // holding the mPackages lock, but we're mostly interested in yelling
            // once we have a booted system.
            mInstaller.setWarnIfHeld(mPackages);
    
            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258
    • 259
    • 260
    • 261
    • 262
    • 263
    • 264
    • 265
    • 266
    • 267
    • 268
    • 269
    • 270
    • 271
    • 272
    • 273
    • 274
    • 275
    • 276
    • 277
    • 278
    • 279
    • 280
    • 281
    • 282
    • 283
    • 284
    • 285
    • 286
    • 287
    • 288
    • 289
    • 290
    • 291
    • 292
    • 293
    • 294
    • 295
    • 296
    • 297
    • 298
    • 299
    • 300
    • 301
    • 302
    • 303
    • 304
    • 305
    • 306
    • 307
    • 308
    • 309
    • 310
    • 311
    • 312
    • 313
    • 314
    • 315
    • 316
    • 317
    • 318
    • 319
    • 320
    • 321
    • 322
    • 323
    • 324
    • 325
    • 326
    • 327
    • 328
    • 329
    • 330
    • 331
    • 332
    • 333
    • 334
    • 335
    • 336
    • 337
    • 338
    • 339
    • 340
    • 341
    • 342
    • 343
    • 344
    • 345
    • 346
    • 347
    • 348
    • 349
    • 350
    • 351
    • 352
    • 353
    • 354
    • 355
    • 356
    • 357
    • 358
    • 359
    • 360
    • 361
    • 362
    • 363
    • 364
    • 365
    • 366
    • 367
    • 368
    • 369
    • 370
    • 371
    • 372
    • 373
    • 374
    • 375
    • 376
    • 377
    • 378
    • 379
    • 380
    • 381
    • 382
    • 383
    • 384
    • 385
    • 386
    • 387
    • 388
    • 389
    • 390
    • 391
    • 392
    • 393
    • 394
    • 395
    • 396
    • 397
    • 398
    • 399
    • 400
    • 401
    • 402
    • 403
    • 404
    • 405
    • 406
    • 407
    • 408
    • 409
    • 410
    • 411
    • 412
    • 413
    • 414
    • 415
    • 416
    • 417
    • 418
    • 419
    • 420
    • 421
    • 422
    • 423
    • 424
    • 425
    • 426
    • 427
    • 428
    • 429
    • 430
    • 431

    2、调用PKMS的回调函数systemReady

    private void startOtherServices() {
       	...
        //启动 MountService,后续 PackageManager 会需要使用
        mSystemServiceManager.startService(MOUNT_SERVICE_CLASS);
        //dex 优化工作,dex 是 Android 针对 Java 字节码的一种优化技术,可提高运行效率
        mPackageManagerService.performBootDexOpt();
        //调用PKMS的回调函数,其他系统服务启动后也会有类似的操作
        mPackageManagerService.systemReady();
        //...
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    其他系统服务启动后也会有类似的操作。

    三、PKMS 遍历安装系统目录下的App

    篇幅问题见下文。

  • 相关阅读:
    我和“愚蠢代码”的那些日子
    人工智能学习:NMIST数据分类识别-CNN网络(3)
    基于boost/beast/实现HTTP client,完成从HTTP Server下载文件
    基于Java实现的设备模拟器
    安装RabbitMQ
    Linux环境下安装部署MySQL8.0以上(内置保姆级教程)- 离线模式
    网络编程 lesson6 服务器模型和网络超时检测
    通过filebeat实现对docker服务的通用日志收集
    美创科技列为IDC中国数据安全市场代表厂商
    python实现FINS协议的TCP服务端(篇二)
  • 原文地址:https://blog.csdn.net/CrazyMo_/article/details/126671711