欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

LOCAL_PRIVILEGED_MODULE 详解(2)

程序员文章站 2022-05-14 20:42:22
...

2.安装时作用

2.1 准备知识

在介绍LOCAL_PRIVILEGED_MODULE在安装时的作用之前,先介绍几个关键的准备知识:
(1)packages.xml
这个文件位于ROM设备的 data/system,读取需要root权限。记录系统中所有安装的应用信息,包含基本信息、签名和权限等。
举几个关键字段为例:
name 包名
codePath 应用安装的路径,非系统应用一般在/data/app/xxx,或者SD卡上;系统应用一般在/system/app/xxx或/system/priv-app/xxx
nativeLibraryPath 应用中本地库安装路径,一般在codePath/lib
version 版本号
userId/sharedUserId 应用的userId
(2)PMS的扫描(scan)与安装(install)
PMS,即PackageManagerService,是安卓框架层核心系统服务之一,常驻内存,实现与app安装、卸载相关功能。PMS对应的主要源代码为 frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java。下面部分内容引自刘超《深入解析Android5.0系统》中对于PMS的总结。
扫描:PMS启动的时候,会扫描所有的apk文件和jar包,把它们的信息读取出来,保存在内存中。扫描过程中如果遇到没有优化的文件,会执行转换,将app文件从dex格式转成odex。扫描的逻辑在PMS构造方法中调用,下面是构造方法中的一部分相关逻辑:

    public PackageManagerService(Context context, Installer installer,
            boolean factoryTest, boolean onlyCore) {

            ......

            // Collect vendor overlay packages.
            // (Do this before scanning any apps.)
            // For security and version matching reason, only consider
            // overlay packages if they reside in VENDOR_OVERLAY_DIR.
            File vendorOverlayDir = new File(VENDOR_OVERLAY_DIR);
            scanDirLI(vendorOverlayDir, PackageParser.PARSE_IS_SYSTEM
                    | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags | SCAN_TRUSTED_OVERLAY, 0);

            // Find base frameworks (resource packages without code).
            scanDirLI(frameworkDir, PackageParser.PARSE_IS_SYSTEM
                    | PackageParser.PARSE_IS_SYSTEM_DIR
                    | PackageParser.PARSE_IS_PRIVILEGED,
                    scanFlags | SCAN_NO_DEX, 0);

            // Collected privileged system packages.
            final File privilegedAppDir = new File(Environment.getRootDirectory(), "priv-app");
            scanDirLI(privilegedAppDir, PackageParser.PARSE_IS_SYSTEM
                    | PackageParser.PARSE_IS_SYSTEM_DIR
                    | PackageParser.PARSE_IS_PRIVILEGED, scanFlags, 0);

            // Collect ordinary system packages.
            final File systemAppDir = new File(Environment.getRootDirectory(), "app");
            scanDirLI(systemAppDir, PackageParser.PARSE_IS_SYSTEM
                    | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);

            // Collect all vendor packages.
            File vendorAppDir = new File("/vendor/app");
            try {
                vendorAppDir = vendorAppDir.getCanonicalFile();
            } catch (IOException e) {
                // failed to look up canonical path, continue with original one
            }
            scanDirLI(vendorAppDir, PackageParser.PARSE_IS_SYSTEM
                    | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);

            // Collect all OEM packages.
            final File oemAppDir = new File(Environment.getOemDirectory(), "app");
            scanDirLI(oemAppDir, PackageParser.PARSE_IS_SYSTEM
                    | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);


            ......
     }

安装:主要分为两个阶段,第一阶段是复制文件,把需要安装的apk复制到 /data/app;第二阶段是装载应用,把应用转成odex,为应用创建数据目录,把应用的信息装载进PMS的数据结构中。
非系统应用和系统应用的区别在于,系统应用并不存在安装的阶段,系统应用是随ROM出厂烧写到手机设备上,位于 system/app和system/priv-app。
(3)PMS对外提供的信息查询接口
由(2)可知,通过扫描和安装,PMS已经将应用的信息装载到了内存。我们知道,Android的公开API中有各种各样的XXXManager,第三方应用可以使用它们很方便地获取各种信息和能力。这些Manager大都在后台对应着某个系统应用。PMS的前台就是大名鼎鼎的PackageManager。所以你通过调用PackageManager查询某个应用的相关信息,实际上使用的就是PMS(2)中得到的缓存。举一个例子,下面代码通过PackageManager公开接口获取微信的一些信息:

    private void test2() {
        PackageManager packageManager = getApplicationContext().getPackageManager();
        try {
            PackageInfo packageInfo = packageManager.getPackageInfo("com.tencent.mm",
                    PackageManager.GET_ACTIVITIES);

            Log.i("TEST_PMR", "packageName : " + packageInfo.packageName);
            Log.i("TEST_PMR", "versionName : " + packageInfo.versionName);
            Log.i("TEST_PMR", "versionCode : " + packageInfo.versionCode);
            Log.i("TEST_PMR", "sharedUserId : " + packageInfo.sharedUserId);
            Log.i("TEST_PMR", "dataDir : " + packageInfo.applicationInfo.dataDir);
            Log.i("TEST_PMR", "nativeLibraryDir : " + packageInfo.applicationInfo.nativeLibraryDir);
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }
    }

输出:

07-17 20:20:50.599 14661 14661 I TEST_PMR: packageName : com.tencent.mm
07-17 20:20:50.600 14661 14661 I TEST_PMR: versionName : 6.5.10
07-17 20:20:50.600 14661 14661 I TEST_PMR: versionCode : 1080
07-17 20:20:50.600 14661 14661 I TEST_PMR: sharedUserId : null
07-17 20:20:50.600 14661 14661 I TEST_PMR: dataDir : /data/user/0/com.tencent.mm
07-17 20:20:50.600 14661 14661 I TEST_PMR: nativeLibraryDir : /data/app/com.tencent.mm-1/lib/arm

LOCAL_PRIVILEGED_MODULE 详解(1)
LOCAL_PRIVILEGED_MODULE 详解(2)
LOCAL_PRIVILEGED_MODULE 详解(3)
LOCAL_PRIVILEGED_MODULE 详解(4)
LOCAL_PRIVILEGED_MODULE 详解(5)