Android开发经验谈Android技术知识Android开发

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

2020-05-11  本文已影响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

上一篇下一篇

猜你喜欢

热点阅读