Android 系统服务 - PMS 的启动过程

作者: 你也不知道 | 来源:发表于2020-05-11 12:30 被阅读0次

    相关文章链接:

    1. Android Framework - 学习启动篇

    2. Android 系统服务 - PMS 的启动过程

    相关源码文件:

    
    frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
    
    frameworks/base/services/core/java/com/android/server/pm/PackageInstallerService.java
    
    frameworks/base/services/core/java/com/android/server/pm/Settings.java
    
    frameworks/base/services/core/java/com/android/server/SystemConfig
    
    frameworks/base/core/java/android/content/pm/PackageManager.java
    
    frameworks/base/core/android/java/content/pm/IPackageManager.aidl
    
    frameworks/base/core/java/android/content/pm/PackageParser.java
    
    frameworks/base/cmds/pm/src/com/android/commands/pm/Pm.java
    
    frameworks/base/services/core/java/com/android/server/pm/Installer.java
    
    frameworks/base/core/java/com/android/internal/os/InstallerConnection.java
    
    

    PackageManagerService 也是 Android 应用开发者需要重点熟悉的一个服务,也是由 SystemService 进程创建的,管理着所有跟 package 相关的工作,常见的比如安装、卸载应用。我们先找到其启动创建的源代码:

    
    private void startBootstrapServices() {
    
        // 启动 installer 服务
    
        Installer installer = mSystemServiceManager.startService(Installer.class);
    
        ...
    
        // 处于加密状态则仅仅解析核心应用
    
        String cryptState = SystemProperties.get("vold.decrypt");
    
        if (ENCRYPTING_STATE.equals(cryptState)) {
    
            mOnlyCore = true; // ENCRYPTING_STATE = "trigger_restart_min_framework"
    
        } else if (ENCRYPTED_STATE.equals(cryptState)) {
    
            mOnlyCore = true; // ENCRYPTED_STATE = "1"
    
        }
    
        // 创建 PKMS 对象
    
        mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
    
                    mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
    
        mPackageManager = mSystemContext.getPackageManager();
    
    }
    
    

    SystemService 进程启动过程中跟 PKMS 相关的有 installer 服务和 PackageManager 对象,我们主要分析他的创建过程也就是 PackageManagerService.main() 方法

    
        public static PackageManagerService main(Context context, Installer installer,
    
                boolean factoryTest, boolean onlyCore) {
    
            // 创建 PackageManagerService 对象
    
            PackageManagerService m = new PackageManagerService(context, installer,
    
                    factoryTest, onlyCore);
    
            // 将 PKMS 添加到 ServiceManager 进程去管理
    
            ServiceManager.addService("package", m);
    
            return m;
    
        }
    
    
    
        public PackageManagerService(Context context, Installer installer,
    
                boolean factoryTest, boolean onlyCore) {
    
            // 保存一些基本变量
    
            mContext = context;
    
            mFactoryTest = factoryTest;
    
            mOnlyCore = onlyCore;
    
            // 创建 Settings 对象
    
            mSettings = new Settings(mPackages);
    
            // 添加 system, phone, log, nfc, bluetooth, shell 这六种shareUserId到mSettings;
    
            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);
    
            mSettings.addSharedUserLPw("android.uid.log", LOG_UID,
    
                    ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
    
            mSettings.addSharedUserLPw("android.uid.nfc", NFC_UID,
    
                    ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
    
            mSettings.addSharedUserLPw("android.uid.bluetooth", BLUETOOTH_UID,
    
                    ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
    
            mSettings.addSharedUserLPw("android.uid.shell", SHELL_UID,
    
                    ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
    
            mInstaller = installer;
    
            // 用来优化 dex
    
            mPackageDexOptimizer = new PackageDexOptimizer(this);
    
            synchronized (mInstallLock) {
    
            synchronized (mPackages) {
    
                // 创建名为 “PackageManager” 的 handler 线程
    
                mHandlerThread = new ServiceThread(TAG,
    
                        Process.THREAD_PRIORITY_BACKGROUND, true /*allowIo*/);
    
                mHandlerThread.start();
    
                mHandler = new PackageHandler(mHandlerThread.getLooper());
    
                Watchdog.getInstance().addThread(mHandler, WATCHDOG_TIMEOUT);
    
                // 创建各种目录
    
                File dataDir = Environment.getDataDirectory();
    
                mAppDataDir = new File(dataDir, "data");
    
                mAppInstallDir = new File(dataDir, "app");
    
                mAppLib32InstallDir = new File(dataDir, "app-lib");
    
                mAsecInternalPath = new File(dataDir, "app-asec").getPath();
    
                mUserAppDataDir = new File(dataDir, "user");
    
                mDrmAppPrivateInstallDir = new File(dataDir, "app-private");
    
                // 创建用户管理服务
    
                sUserManager = new UserManagerService(context, this,
    
                        mInstallLock, mPackages);
    
                // 这个目录为 /system/framework
    
                File frameworkDir = new File(Environment.getRootDirectory(), "framework");
    
                // 获取到 frameworkDir 下面的所有文件
    
                String[] frameworkFiles = frameworkDir.list();
    
                if (frameworkFiles != null) {
    
                    for (String dexCodeInstructionSet : dexCodeInstructionSets) {
    
                        for (int i=0; i<frameworkFiles.length; i++) {
    
                            File libPath = new File(frameworkDir, frameworkFiles[i]);
    
                            String path = libPath.getPath();
    
                            // alreadyDexOpted 列表是否包含该文件
    
                            if (alreadyDexOpted.contains(path)) {
    
                                continue;
    
                            }
    
                            // 过滤掉不是 apk 和 jar 的文件
    
                            if (!path.endsWith(".apk") && !path.endsWith(".jar")) {
    
                                continue;
    
                            }
    
                            try {
    
                                int dexoptNeeded = DexFile.getDexOptNeeded(path, null, dexCodeInstructionSet, false);
    
                                if (dexoptNeeded != DexFile.NO_DEXOPT_NEEDED) {
    
                                    // 执行 dexopt 优化操作
    
                                    mInstaller.dexopt(path, Process.SYSTEM_UID, true, dexCodeInstructionSet, dexoptNeeded);
    
                                }
    
                            } catch (FileNotFoundException e) {
    
                                Slog.w(TAG, "Jar not found: " + path);
    
                            } catch (IOException e) {
    
                                Slog.w(TAG, "Exception reading jar: " + path, e);
    
                            }
    
                        }
    
                    }
    
                }
    
                // 搜集解析系统各种 app 包信息
    
                ...
    
                // 移除文件
    
                mInstaller.moveFiles();
    
                // 清理所有安装不完整的包
    
                ArrayList<PackageSetting> deletePkgsList = mSettings.getListOfIncompleteInstallPackagesLPr();
    
                for(int i = 0; i < deletePkgsList.size(); i++) {
    
                    cleanupInstallFailedPackage(deletePkgsList.get(i));
    
                }
    
                // 删除临时文件
    
                deleteTempPackageFiles();
    
                // 处理解析非系统的 app
    
                if (!mOnlyCore) {
    
                    // 扫描解析 /data/app 目录
    
                    scanDirLI(mAppInstallDir, 0, scanFlags | SCAN_REQUIRE_KNOWN, 0);
    
                    // 扫描解析 /data/app-private 目录
    
                    scanDirLI(mDrmAppPrivateInstallDir, PackageParser.PARSE_FORWARD_LOCK,
    
                            scanFlags | SCAN_REQUIRE_KNOWN, 0);
    
                    ...
    
                }
    
                // 将所有解析的包信息写到 packages.xml 文件
    
                mSettings.writeLPr();
    
            } // synchronized (mPackages)
    
            } // synchronized (mInstallLock)
    
            // 调用 gc
    
            Runtime.getRuntime().gc();
    
        }
    
    

    PKMS 的创建和启动过程比 AMS 复杂太多,我删减了很多不是核心的代码,总得来说 PKMS 在创建的过程中会去解析所有 apk 的安装信息,其中包括系统应用和非系统的安装应用,对于应用开发者来说,我们只需要关注非系统应用就足够了。我们平时安装的手机应用主要放在 mAppInstallDir(data/app) 目录下。总的来说 PKMS 在启动的时候会去解析我们手机所有的应用的 apk 包信息,并会将其所解析的内容全部保存在 mPackages 变量中,最后我们来看下 PKMS 到底是扫描解析保存了 apk 的哪些信息。

    
        private void scanDirLI(File dir, int parseFlags, int scanFlags, long currentTime) {
    
            ...
    
            for (File file : files) {
    
                // 是不是 apk 文件
    
                final boolean isPackage = (isApkFile(file) || file.isDirectory())
    
                        && !PackageInstallerService.isStageName(file.getName());
    
                if (!isPackage) {
    
                    // Ignore entries which are not packages
    
                    continue;
    
                }
    
                try {
    
                    // 扫描解析 apk 文件
    
                    scanPackageLI(file, parseFlags | PackageParser.PARSE_MUST_BE_APK,
    
                            scanFlags, currentTime, null);
    
                } catch (PackageManagerException e) {
    
                    // 如果有异常,把这个文件或者文件夹删除
    
                    if ((parseFlags & PackageParser.PARSE_IS_SYSTEM) == 0 &&
    
                            e.error == PackageManager.INSTALL_FAILED_INVALID_APK) {
    
                        logCriticalInfo(Log.WARN, "Deleting invalid package at " + file);
    
                        if (file.isDirectory()) {
    
                            mInstaller.rmPackageDir(file.getAbsolutePath());
    
                        } else {
    
                            file.delete();
    
                        }
    
                    }
    
                }
    
            }
    
        }
    
        private PackageParser.Package scanPackageLI(File scanFile, int parseFlags, int scanFlags,
    
                long currentTime, UserHandle user) throws PackageManagerException {
    
            // 创建一个解析对象
    
            PackageParser pp = new PackageParser();
    
            pp.setSeparateProcesses(mSeparateProcesses);
    
            pp.setOnlyCoreApps(mOnlyCore);
    
            pp.setDisplayMetrics(mMetrics);
    
            final PackageParser.Package pkg;
    
            try {
    
                // 解析 apk 参数,返回 PackageParser.Package
    
                pkg = pp.parsePackage(scanFile, parseFlags);
    
            } catch (PackageParserException e) {
    
                throw PackageManagerException.from(e);
    
            }
    
            // 搜集证书信息
    
            collectCertificatesLI(pp, ps, pkg, scanFile, parseFlags);
    
            ...
    
            return scannedPkg;
    
        }
    
        public Package parsePackage(File packageFile, int flags) throws PackageParserException {
    
            if (packageFile.isDirectory()) {
    
                ...
    
            } else {
    
                return parseMonolithicPackage(packageFile, flags);
    
            }
    
        }
    
        public Package parseMonolithicPackage(File apkFile, int flags) throws PackageParserException {
    
            final AssetManager assets = new AssetManager();
    
            try {
    
                final Package pkg = parseBaseApk(apkFile, assets, flags);
    
                pkg.codePath = apkFile.getAbsolutePath();
    
                return pkg;
    
            } finally {
    
                IoUtils.closeQuietly(assets);
    
            }
    
        }
    
        private Package parseBaseApk(File apkFile, AssetManager assets, int flags)
    
                throws PackageParserException {
    
            final String apkPath = apkFile.getAbsolutePath();
    
            final int cookie = loadApkIntoAssetManager(assets, apkPath, flags);
    
            Resources res = null;
    
            XmlResourceParser parser = null;
    
            try {
    
                res = new Resources(assets, mMetrics, null);
    
                assets.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    
                        Build.VERSION.RESOURCES_SDK_INT);
    
                // 打开解析 AndroidManifest.xml 文件
    
                parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
    
                final String[] outError = new String[1];
    
                final Package pkg = parseBaseApk(res, parser, flags, outError);
    
                if (pkg == null) {
    
                    throw new PackageParserException(mParseError,
    
                            apkPath + " (at " + parser.getPositionDescription() + "): " + outError[0]);
    
                }
    
                return pkg;
    
            } catch (PackageParserException e) {
    
                throw e;
    
            } catch (Exception e) {
    
                throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
    
                        "Failed to read manifest from " + apkPath, e);
    
            } finally {
    
                IoUtils.closeQuietly(parser);
    
            }
    
        }
    
        private Package parseBaseApk(Resources res, XmlResourceParser parser, int flags,
    
                String[] outError) throws XmlPullParserException, IOException {
    
            AttributeSet attrs = parser;
    
            // 解析包名
    
            try {
    
                Pair<String, String> packageSplit = parsePackageSplitNames(parser, attrs, flags);
    
                pkgName = packageSplit.first;
    
                splitName = packageSplit.second;
    
            } catch (PackageParserException e) {
    
                mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
    
                return null;
    
            }
    
            // 构建一个 Package 对象
    
            final Package pkg = new Package(pkgName);
    
            boolean foundApp = false;
    
            // 获取 VersionCode 和 VersionName
    
            TypedArray sa = res.obtainAttributes(attrs,
    
                    com.android.internal.R.styleable.AndroidManifest);
    
            pkg.mVersionCode = pkg.applicationInfo.versionCode = sa.getInteger(
    
                    com.android.internal.R.styleable.AndroidManifest_versionCode, 0);
    
            pkg.mVersionName = sa.getNonConfigurationString(
    
                    com.android.internal.R.styleable.AndroidManifest_versionName, 0);
    
            if (pkg.mVersionName != null) {
    
                pkg.mVersionName = pkg.mVersionName.intern();
    
            }
    
            // 解析所有可能出现的属性,application ,uses-permission,permission,等等
    
            int outerDepth = parser.getDepth();
    
            while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
    
                    && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
    
                if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
    
                    continue;
    
                }
    
                String tagName = parser.getName();
    
                if (tagName.equals("application")) {
    
                    if (foundApp) {
    
                        if (RIGID_PARSER) {
    
                            outError[0] = "<manifest> has more than one <application>";
    
                            mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
    
                            return null;
    
                        } else {
    
                            Slog.w(TAG, "<manifest> has more than one <application>");
    
                            XmlUtils.skipCurrentTag(parser);
    
                            continue;
    
                        }
    
                    }
    
                    foundApp = true;
    
                    if (!parseBaseApplication(pkg, res, parser, attrs, flags, outError)) {
    
                        return null;
    
                    }
    
                } else if (tagName.equals("permission")) {
    
                    if (parsePermission(pkg, res, parser, attrs, outError) == null) {
    
                        return null;
    
                    }
    
                } else if (tagName.equals("uses-permission")) {
    
                    if (!parseUsesPermission(pkg, res, parser, attrs)) {
    
                        return null;
    
                    }
    
                } else if (RIGID_PARSER) {
    
                    outError[0] = "Bad element under <manifest>: "
    
                        + parser.getName();
    
                    mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
    
                    return null;
    
                } else {
    
                    Slog.w(TAG, "Unknown element under <manifest>: " + parser.getName()
    
                            + " at " + mArchiveSourcePath + " "
    
                            + parser.getPositionDescription());
    
                    XmlUtils.skipCurrentTag(parser);
    
                    continue;
    
                }
    
            }
    
            ...
    
            return pkg;
    
        }
    
        private boolean parseBaseApplication(Package owner, Resources res,
    
                XmlPullParser parser, AttributeSet attrs, int flags, String[] outError)
    
            throws XmlPullParserException, IOException {
    
            final ApplicationInfo ai = owner.applicationInfo;
    
            final String pkgName = owner.applicationInfo.packageName;
    
            TypedArray sa = res.obtainAttributes(attrs,
    
                    com.android.internal.R.styleable.AndroidManifestApplication);
    
            // 解析 application
    
            String name = sa.getNonConfigurationString(
    
                    com.android.internal.R.styleable.AndroidManifestApplication_name, 0);
    
            if (name != null) {
    
                ai.className = buildClassName(pkgName, name, outError);
    
                if (ai.className == null) {
    
                    sa.recycle();
    
                    mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
    
                    return false;
    
                }
    
            }
    
            // 解析 allowBackup
    
            boolean allowBackup = sa.getBoolean(
    
                    com.android.internal.R.styleable.AndroidManifestApplication_allowBackup, true);
    
            if (allowBackup) {
    
                ...
    
            }
    
            // 解析 label 也就是 app 的名字
    
            TypedValue v = sa.peekValue(
    
                    com.android.internal.R.styleable.AndroidManifestApplication_label);
    
            if (v != null && (ai.labelRes=v.resourceId) == 0) {
    
                ai.nonLocalizedLabel = v.coerceToString();
    
            }
    
            // 解析 icon ,logo,theme 等等
    
            ai.icon = sa.getResourceId(
    
                    com.android.internal.R.styleable.AndroidManifestApplication_icon, 0);
    
            ai.logo = sa.getResourceId(
    
                    com.android.internal.R.styleable.AndroidManifestApplication_logo, 0);
    
            ai.banner = sa.getResourceId(
    
                    com.android.internal.R.styleable.AndroidManifestApplication_banner, 0);
    
            ai.theme = sa.getResourceId(
    
                    com.android.internal.R.styleable.AndroidManifestApplication_theme, 0);
    
            // 开始解析四大组件
    
            final int innerDepth = parser.getDepth();
    
            int type;
    
            while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
    
                    && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
    
                if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
    
                    continue;
    
                }
    
                String tagName = parser.getName();
    
                if (tagName.equals("activity")) {
    
                    Activity a = parseActivity(owner, res, parser, attrs, flags, outError, false,
    
                            owner.baseHardwareAccelerated);
    
                    if (a == null) {
    
                        mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
    
                        return false;
    
                    }
    
                    owner.activities.add(a);
    
                } else if (tagName.equals("receiver")) {
    
                    Activity a = parseActivity(owner, res, parser, attrs, flags, outError, true, false);
    
                    if (a == null) {
    
                        mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
    
                        return false;
    
                    }
    
                    owner.receivers.add(a);
    
                } else if (tagName.equals("service")) {
    
                    Service s = parseService(owner, res, parser, attrs, flags, outError);
    
                    if (s == null) {
    
                        mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
    
                        return false;
    
                    }
    
                    owner.services.add(s);
    
                } else if (tagName.equals("provider")) {
    
                    Provider p = parseProvider(owner, res, parser, attrs, flags, outError);
    
                    if (p == null) {
    
                        mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
    
                        return false;
    
                    }
    
                    owner.providers.add(p);
    
                } else if (tagName.equals("activity-alias")) {
    
                    Activity a = parseActivityAlias(owner, res, parser, attrs, flags, outError);
    
                    if (a == null) {
    
                        mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
    
                        return false;
    
                    }
    
                    owner.activities.add(a);
    
                } else if (parser.getName().equals("meta-data")) {
    
                    // note: application meta-data is stored off to the side, so it can
    
                    // remain null in the primary copy (we like to avoid extra copies because
    
                    // it can be large)
    
                    if ((owner.mAppMetaData = parseMetaData(res, parser, attrs, owner.mAppMetaData,
    
                            outError)) == null) {
    
                        mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
    
                        return false;
    
                    }
    
                } else if (tagName.equals("library")) {
    
                    sa = res.obtainAttributes(attrs,
    
                            com.android.internal.R.styleable.AndroidManifestLibrary);
    
                    // Note: don't allow this value to be a reference to a resource
    
                    // that may change.
    
                    String lname = sa.getNonResourceString(
    
                            com.android.internal.R.styleable.AndroidManifestLibrary_name);
    
                    sa.recycle();
    
                    if (lname != null) {
    
                        lname = lname.intern();
    
                        if (!ArrayUtils.contains(owner.libraryNames, lname)) {
    
                            owner.libraryNames = ArrayUtils.add(owner.libraryNames, lname);
    
                        }
    
                    }
    
                    XmlUtils.skipCurrentTag(parser);
    
                } else if (tagName.equals("uses-library")) {
    
                    sa = res.obtainAttributes(attrs,
    
                            com.android.internal.R.styleable.AndroidManifestUsesLibrary);
    
                    // Note: don't allow this value to be a reference to a resource
    
                    // that may change.
    
                    String lname = sa.getNonResourceString(
    
                            com.android.internal.R.styleable.AndroidManifestUsesLibrary_name);
    
                    boolean req = sa.getBoolean(
    
                            com.android.internal.R.styleable.AndroidManifestUsesLibrary_required,
    
                            true);
    
                    sa.recycle();
    
                    if (lname != null) {
    
                        lname = lname.intern();
    
                        if (req) {
    
                            owner.usesLibraries = ArrayUtils.add(owner.usesLibraries, lname);
    
                        } else {
    
                            owner.usesOptionalLibraries = ArrayUtils.add(
    
                                    owner.usesOptionalLibraries, lname);
    
                        }
    
                    }
    
                    XmlUtils.skipCurrentTag(parser);
    
                } else if (tagName.equals("uses-package")) {
    
                    // Dependencies for app installers; we don't currently try to
    
                    // enforce this.
    
                    XmlUtils.skipCurrentTag(parser);
    
                } else {
    
                    if (!RIGID_PARSER) {
    
                        Slog.w(TAG, "Unknown element under <application>: " + tagName
    
                                + " at " + mArchiveSourcePath + " "
    
                                + parser.getPositionDescription());
    
                        XmlUtils.skipCurrentTag(parser);
    
                        continue;
    
                    } else {
    
                        outError[0] = "Bad element under <application>: " + tagName;
    
                        mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
    
                        return false;
    
                    }
    
                }
    
            }
    
            return true;
    
        }
    
    

    视频地址:https://pan.baidu.com/s/1dM3K9bPRuepFUJIASIDeQg

    视频密码:af97

    相关文章

      网友评论

        本文标题:Android 系统服务 - PMS 的启动过程

        本文链接:https://www.haomeiwen.com/subject/vaqunhtx.html