PackageManagerService Android 8.1 源码解读 06

接力上一篇:PackageManagerService Android 8.1 源码解读 05


六、五部曲 - PMS之权限扫描

a、分析此 “PMS之权限扫描” 的目标是: PackageManagerService中执行构造函数()后,需求对【/system/etc/permissions】中的各种xml进行扫描,进行相应的权限存储,让以后可以使用,这就是本次“PMS之权限扫描”分析的目的。

b、权限扫描:PackageManagerService执行构造函数()时,通过单例对象SystemConfigreadPermissionsFromXml()来扫描读取/system/etc/permissions中的xml文件,包括platform.xml和系统支持的各种硬件模块的feature主要工作:
 

public PackageManagerService(Context context, Installer installer,
        boolean factoryTest, boolean onlyCore) {
    ......省略代码
    Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "get system config");
    SystemConfig systemConfig = SystemConfig.getInstance();
    mGlobalGids = systemConfig.getGlobalGids();
    mSystemPermissions = systemConfig.getSystemPermissions();
    mAvailableFeatures = systemConfig.getAvailableFeatures();
    Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
    ......省略代码
}
// 构造函数读取配置权限
SystemConfig() {
    // Read configuration from system
    readPermissions(Environment.buildPath(
            Environment.getRootDirectory(), "etc", "sysconfig"), ALLOW_ALL);
    // Read configuration from the old permissions dir
    readPermissions(Environment.buildPath(
            Environment.getRootDirectory(), "etc", "permissions"), ALLOW_ALL);
    // Allow Vendor to customize system configs around libs, features, permissions and apps
    int vendorPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_PERMISSIONS |
            ALLOW_APP_CONFIGS;
    readPermissions(Environment.buildPath(
            Environment.getVendorDirectory(), "etc", "sysconfig"), vendorPermissionFlag);
    readPermissions(Environment.buildPath(
            Environment.getVendorDirectory(), "etc", "permissions"), vendorPermissionFlag);
    // Allow ODM to customize system configs around libs, features and apps
    int odmPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_APP_CONFIGS;
    readPermissions(Environment.buildPath(
            Environment.getOdmDirectory(), "etc", "sysconfig"), odmPermissionFlag);
    readPermissions(Environment.buildPath(
            Environment.getOdmDirectory(), "etc", "permissions"), odmPermissionFlag);
    // Only allow OEM to customize features
    readPermissions(Environment.buildPath(
            Environment.getOemDirectory(), "etc", "sysconfig"), ALLOW_FEATURES);
    readPermissions(Environment.buildPath(
            Environment.getOemDirectory(), "etc", "permissions"), ALLOW_FEATURES);
}

c、SystemConfigreadPermissions函数:此函数目的:(扫描/system/etc/permissions中文件,调readPermissionsFromXml()进行解析,存入SsytemConfig相应的成员数组变量中)

void readPermissions(File libraryDir, int permissionFlag) {
    // Read permissions from given directory.
    // 如果文件不存在,或者文件不是目录,直接返回
    if (!libraryDir.exists() || !libraryDir.isDirectory()) {
        if (permissionFlag == ALLOW_ALL) {
            Slog.w(TAG, "No directory " + libraryDir + ", skipping");
        }
        return;
    }
    // 文件不可读,直接返回
    if (!libraryDir.canRead()) {
        Slog.w(TAG, "Directory " + libraryDir + " cannot be read");
        return;
    }

    // Iterate over the files in the directory and scan .xml files
    File platformFile = null;
    // 列表目录下定位文件
    for (File f : libraryDir.listFiles()) {
        // 最后才读取 platform.xml 文件
        if (f.getPath().endsWith("etc/permissions/platform.xml")) {
            platformFile = f;
            continue;
        }
        // 过滤不是.xml结尾的文件
        if (!f.getPath().endsWith(".xml")) {
            Slog.i(TAG, "Non-xml file " + f + " in " + libraryDir + " directory, ignoring");
            continue;
        }
        // 文件不可读
        if (!f.canRead()) {
            Slog.w(TAG, "Permissions library file " + f + " cannot be read");
            continue;
        }
        // 开始读取文件
        readPermissionsFromXml(f, permissionFlag);
    }

    // Read platform permissions last so it will take precedence
    if (platformFile != null) {
        // 到这里最后才读取 platform.xml 文件,可以覆盖之前的权限
        readPermissionsFromXml(platformFile, permissionFlag);
    }
}

d、readPermissionsFromXml()方法,解析xml的标签节点,存入mGlobalGids、mPermissions、mSystemPermissions等成员变量中,供其他进行调用

private void readPermissionsFromXml(File permFile, int permissionFlag) {
    FileReader permReader = null;
    try {
        permReader = new FileReader(permFile);
    } catch (FileNotFoundException e) {
        Slog.w(TAG, "Couldn't find or open permissions file " + permFile);
        return;
    }
		// 获取lowRam变量,主要是看设备是否为低内存设备
    final boolean lowRam = ActivityManager.isLowRamDeviceStatic();

    try {
        // 用pull解析xml文件
        XmlPullParser parser = Xml.newPullParser();
        parser.setInput(permReader);
        ......省略代码
        while (true) {
            XmlUtils.nextElement(parser);
            if (parser.getEventType() == XmlPullParser.END_DOCUMENT) {
                break;
            }

            String name = parser.getName();
            // 解析 group 标签,前面介绍的 XML 文件中没有单独使用该标签的地方
            if ("group".equals(name) && allowAll) {
                String gidStr = parser.getAttributeValue(null, "gid");
                if (gidStr != null) {
                    int gid = android.os.Process.getGidForName(gidStr);
                    // 转换 XML 中的 gid字符串为整型,并保存到 mGlobalGids 中
                    mGlobalGids = appendInt(mGlobalGids, gid);
                } else {
                    Slog.w(TAG, "<group> without gid in " + permFile + " at "
                            + parser.getPositionDescription());
                }

                XmlUtils.skipCurrentTag(parser);
                continue;
            } else if ("permission".equals(name) && allowPermissions) {
                //解析 permission 标签
                String perm = parser.getAttributeValue(null, "name");
                if (perm == null) {
                    Slog.w(TAG, "<permission> without name in " + permFile + " at "
                            + parser.getPositionDescription());
                    XmlUtils.skipCurrentTag(parser);
                    continue;
                }
                perm = perm.intern();
                // 调用 readPermission 处理,存入mPermissions
                readPermission(parser, perm);

            } else if ......
   ......省略很多代码
}

e、查看 XML文件:adb devices && adb shell

k37mv1_bsp:/ # ls -la /system/etc/permissions/                                                                                                                        
total 76
drwxr-xr-x  2 root root  4096 2009-01-01 00:00 .
drwxr-xr-x 21 root root  4096 2009-01-01 00:00 ..
-rw-r--r--  1 root root   748 2009-01-01 00:00 android.software.webview.xml
-rw-r--r--  1 root root   828 2009-01-01 00:00 com.android.location.provider.xml
-rw-r--r--  1 root root   828 2009-01-01 00:00 com.android.media.remotedisplay.xml
-rw-r--r--  1 root root   820 2009-01-01 00:00 com.android.mediadrm.signer.xml
-rw-r--r--  1 root root   193 2009-01-01 00:00 mediatek-packages-teleservice.xml
-rw-r--r--  1 root root  9244 2009-01-01 00:00 platform.xml
-rw-r--r--  1 root root   156 2009-01-01 00:00 pms_sysapp_removable_system_list.txt
-rw-r--r--  1 root root  8144 2009-01-01 00:00 privapp-permissions-mediatek.xml
-rw-r--r--  1 root root 20917 2009-01-01 00:00 privapp-permissions-platform.xml
k37mv1_bsp:/ # 

然后在导出去:adb pull /system/etc/permissions

/system/etc/permissions中会存在很多的xml文件,例如我们看下 android.software.webview.xml的
文件,内容如下: 里面只有一个feature "android.software.webview",大部分的xml都是类似的定义方式

f、让我们来简单的看下/system/etc/permissions/platform.xml的内容

<?xml version="1.0" encoding="utf-8"?>
<permissions>

    <!-- ================================================================== -->
    <!-- ================================================================== -->
    <!-- ================================================================== -->

    <!-- The following tags are associating low-level group IDs with
         permission names.  By specifying such a mapping, you are saying
         that any application process granted the given permission will
         also be running with the given group ID attached to its process,
         so it can perform any filesystem (read, write, execute) operations
         allowed for that group. -->

    <permission name="android.permission.BLUETOOTH_ADMIN" >
        <group gid="net_bt_admin" />
    </permission>

    <permission name="android.permission.BLUETOOTH" >
        <group gid="net_bt" />
    </permission>

    <permission name="android.permission.BLUETOOTH_STACK" >
        <group gid="bluetooth" />
        <group gid="wakelock" />
        <group gid="uhid" />
    </permission>

    <permission name="android.permission.NET_TUNNELING" >
        <group gid="vpn" />
    </permission>

    <permission name="android.permission.INTERNET" >
        <group gid="inet" />
    </permission>

    <permission name="android.permission.READ_LOGS" >
        <group gid="log" />
    </permission>

    <permission name="android.permission.WRITE_MEDIA_STORAGE" >
        <group gid="media_rw" />
        <group gid="sdcard_rw" />
    </permission>

    <permission name="android.permission.ACCESS_MTP" >
        <group gid="mtp" />
    </permission>

    <permission name="android.permission.NET_ADMIN" >
        <group gid="net_admin" />
    </permission>

    <!-- The group that /cache belongs to, linked to the permission
         set on the applications that can access /cache -->
    <permission name="android.permission.ACCESS_CACHE_FILESYSTEM" >
        <group gid="cache" />
    </permission>

    <!-- RW permissions to any system resources owned by group 'diag'.
         This is for carrier and manufacture diagnostics tools that must be
         installable from the framework. Be careful. -->
    <permission name="android.permission.DIAGNOSTIC" >
        <group gid="input" />
        <group gid="diag" />
    </permission>

    <!-- Group that can read detailed network usage statistics -->
    <permission name="android.permission.READ_NETWORK_USAGE_HISTORY">
        <group gid="net_bw_stats" />
    </permission>

    <!-- Group that can modify how network statistics are accounted -->
    <permission name="android.permission.UPDATE_DEVICE_STATS">
        <group gid="net_bw_acct" />
    </permission>

    <permission name="android.permission.LOOP_RADIO" >
        <group gid="loop_radio" />
    </permission>

    <!-- Hotword training apps sometimes need a GID to talk with low-level
         hardware; give them audio for now until full HAL support is added. -->
    <permission name="android.permission.MANAGE_VOICE_KEYPHRASES">
        <group gid="audio" />
    </permission>

    <permission name="android.permission.ACCESS_BROADCAST_RADIO" >
        <!-- /dev/fm is gid media, not audio -->
        <group gid="media" />
    </permission>

    <!-- These are permissions that were mapped to gids but we need
         to keep them here until an upgrade from L to the current
         version is to be supported. These permissions are built-in
         and in L were not stored in packages.xml as a result if they
         are not defined here while parsing packages.xml we would
         ignore these permissions being granted to apps and not
         propagate the granted state. From N we are storing the
         built-in permissions in packages.xml as the saved storage
         is negligible (one tag with the permission) compared to
         the fragility as one can remove a built-in permission which
         no longer needs to be mapped to gids and break grant propagation. -->
    <permission name="android.permission.READ_EXTERNAL_STORAGE" />
    <permission name="android.permission.WRITE_EXTERNAL_STORAGE" />

    <!-- ================================================================== -->
    <!-- ================================================================== -->
    <!-- ================================================================== -->

    <!-- The following tags are assigning high-level permissions to specific
         user IDs.  These are used to allow specific core system users to
         perform the given operations with the higher-level framework.  For
         example, we give a wide variety of permissions to the shell user
         since that is the user the adb shell runs under and developers and
         others should have a fairly open environment in which to
         interact with the system. -->

    <assign-permission name="android.permission.MODIFY_AUDIO_SETTINGS" uid="media" />
    <assign-permission name="android.permission.ACCESS_SURFACE_FLINGER" uid="media" />
    <assign-permission name="android.permission.WAKE_LOCK" uid="media" />
    <assign-permission name="android.permission.UPDATE_DEVICE_STATS" uid="media" />
    <assign-permission name="android.permission.UPDATE_APP_OPS_STATS" uid="media" />
    <assign-permission name="android.permission.GET_PROCESS_STATE_AND_OOM_SCORE" uid="media" />
    <assign-permission name="android.permission.CAPTURE_AUDIO_OUTPUT" uid="media" />
    <!-- AudioServer is separated from mediaServer on Android N0, so AudioServer will
         check mediaServer permission when mediaServer call audioServer through binder,
         so add CAPTURE_AUDIO_OUTPUT permission for mediaServer. -->

    <assign-permission name="android.permission.MODIFY_AUDIO_SETTINGS" uid="audioserver" />
    <assign-permission name="android.permission.ACCESS_SURFACE_FLINGER" uid="audioserver" />
    <assign-permission name="android.permission.WAKE_LOCK" uid="audioserver" />
    <assign-permission name="android.permission.UPDATE_DEVICE_STATS" uid="audioserver" />
    <assign-permission name="android.permission.UPDATE_APP_OPS_STATS" uid="audioserver" />

    <assign-permission name="android.permission.MODIFY_AUDIO_SETTINGS" uid="cameraserver" />
    <assign-permission name="android.permission.ACCESS_SURFACE_FLINGER" uid="cameraserver" />
    <assign-permission name="android.permission.WAKE_LOCK" uid="cameraserver" />
    <assign-permission name="android.permission.UPDATE_DEVICE_STATS" uid="cameraserver" />
    <assign-permission name="android.permission.UPDATE_APP_OPS_STATS" uid="cameraserver" />
    <assign-permission name="android.permission.GET_PROCESS_STATE_AND_OOM_SCORE" uid="cameraserver" />

    <assign-permission name="android.permission.ACCESS_SURFACE_FLINGER" uid="graphics" />

    <!-- This is a list of all the libraries available for application
         code to link against. -->

    <library name="android.test.mock"
            file="/system/framework/android.test.mock.jar" />
    <library name="android.test.runner"
            file="/system/framework/android.test.runner.jar" />
    <library name="javax.obex"
            file="/system/framework/javax.obex.jar" />
    <library name="org.apache.http.legacy"
            file="/system/framework/org.apache.http.legacy.jar" />

    <!-- These are the standard packages that are white-listed to always have internet
         access while in power save mode, even if they aren't in the foreground. -->
    <allow-in-power-save package="com.android.providers.downloads" />

    <!-- These are the standard packages that are white-listed to always have internet
         access while in data mode, even if they aren't in the foreground. -->
    <allow-in-data-usage-save package="com.android.providers.downloads" />

    <!-- This is a core platform component that needs to freely run in the background -->
    <allow-in-power-save package="com.android.cellbroadcastreceiver" />
    <allow-in-power-save package="com.android.shell" />

    <!-- These are the packages that are white-listed to be able to run as system user -->
    <system-user-whitelisted-app package="com.android.settings" />

    <!-- These are the packages that shouldn't run as system user -->
    <system-user-blacklisted-app package="com.android.wallpaper.livepicker" />
</permissions>

以上platform.xml中出现的标签种类则较为多样,它们的含义分别是:

platform.xml中出现的标签种类则较为多样,它们的含义分别是:

<group>:根据name获取gid

<permission >标签:把属性name所描述的权限赋予给<group>标签中属性gid所表示的用户组,一个权限
可以有一个或多个group对象,当一个APK授权于这个这个权限时,它同时属于这几个组

<assign-permission>标签:把属性name所描述的权限赋予给uid属性所表示的用户

<split-permission>标签:一个权限可以扩展出一个新的权限

<library>标签:除framework中动态库以外的,所有系统会自动加载的动态库

<feature>标签:硬件支持的一些feature

<oem-permission>标签:oem厂商自己定义的一些权限

<privapp-permission>标签:来自system、vendor、product、system_ext的privapp权限分别存
储,这是防止供应商分区中的xml授权于系统分区中的私有应用权限


最后将上面xml解析出来的数据做如下存储:
<group>标签gid属性的值会存放在mGlobalGids数组中;
总结:权限扫描,扫描/system/etc/permissions中的xml,存入相应的结构体中,供之后权限管理使
用
=============================================
============
<permission>标签,解析得到的值会存放在mPermissions集合中;

<assign-permission>标签解析得到的值会存放在mSystemPermissions中;

<split-permission>存储在mSplitPermissions

<library>标签解析得到的值会存放在mSharedLibraries中;

<feature>存储在mAvaliableFeatures

<oem-permission>存储在mOemPermissions

<privapp-permission>会根据不同的存储路径,分别存储在mVendorPrivAppPermissions、
mProductPrivAppPermissions、mSystemExtPrivAppPermissions、mPrivAppPermissions

g、总结:权限扫描,扫描/system/etc/permissions中的xml,存入相应的结构体中,供之后权限管理使用

PackageManagerService Android 8.1 源码解读 07

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值