Android之PackageManagerService构造函数部分分析

1.Settings
在PackageManagerService构造方法中初始化如下:

mSettings = new Settings(context);

Settings构造方法如下:

    Settings(Context context) {
        this(context, Environment.getDataDirectory());
    }    

    Settings(Context context, File dataDir) {
        mSystemDir = new File(dataDir, "system");
        mSystemDir.mkdirs();
        FileUtils.setPermissions(mSystemDir.toString(),
                FileUtils.S_IRWXU|FileUtils.S_IRWXG
                |FileUtils.S_IROTH|FileUtils.S_IXOTH,
                -1, -1); 
        mSettingsFilename = new File(mSystemDir, "packages.xml");
        mBackupSettingsFilename = new File(mSystemDir, "packages-backup.xml");
        mPackageListFilename = new File(mSystemDir, "packages.list");
        FileUtils.setPermissions(mPackageListFilename, 0660, SYSTEM_UID, PACKAGE_INFO_GID);

        // Deprecated: Needed for migration
        mStoppedPackagesFilename = new File(mSystemDir, "packages-stopped.xml");
        mBackupStoppedPackagesFilename = new File(mSystemDir, "packages-stopped-backup.xml");
    }    

构造函数中知识创建了系统目录system, 设置文件packages.xml,设置备份文件packages-backup.xml,应用列表文件packages.list等.
下面是:

        mSettings.addSharedUserLPw(
        "android.uid.system", //字符串
        Process.SYSTEM_UID,   //系统进程使用的用户id,值为1000 
        ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PRIVILEGED); //标识系统package

来看一下addSharedUserLPw函数:

    SharedUserSetting addSharedUserLPw(String name, int uid, int pkgFlags) {
        SharedUserSetting s = mSharedUsers.get(name);
        if (s != null) {
            if (s.userId == uid) {
 return s;
            }
            PackageManagerService.reportSettingsProblem(Log.ERROR,
                    "Adding duplicate shared user, keeping first: " + name);
 return null;
        }
        s = new SharedUserSetting(name, pkgFlags);
        s.userId = uid;
        if (addUserIdLPw(uid, s, name)) {
            mSharedUsers.put(name, s);
 return s;
        }
 return null;
    }

mSharedUsers是一个HashMap,key为字符串,值为SharedUserSetting对象 HashMap<String, SharedUserSetting> mSharedUsers
SharedUserSetting类的成员变量如下,此类的作用就是存储特定共享用户ID的设置数据:

    final String name;
    int userId;
    // 与该uid有关的任何flags
    int uidFlags;
    final HashSet<PackageSetting> packages = new HashSet<PackageSetting>();

    final PackageSignatures signatures = new PackageSignatures();

在androidManifest.xml文件中声明sharedUserId属性如下:

android:sharedUserId="android.uid.system"

其作用如下:
1)两个或多个生命了同一种sharedUserId的APK可共享彼此的数据,并且可运行在同一个进程中.
2)更重要的是,通过声明特定的sharedUserId,该APK所在进程将被赋予指定的UID.例如,上面应用system的uid,运行该进程的就可享有system用户所有对应的权限(实际上就是将该进程的uid设置为system的uid).

2.SystemConfig
在PKMS初始化的过程中初始化SystemConfig,方法如下:

    public static SystemConfig getInstance() {
        synchronized (SystemConfig.class) {
            if (sInstance == null) {
                sInstance = new SystemConfig();
            }   
            return sInstance;
        }   
    }   

SystemConfig的构造方法如下:

    SystemConfig() {
        // 从系统中读取配置文件
        readPermissions(Environment.buildPath( Environment.getRootDirectory(), "etc", "sysconfig"), false);
        // Read configuration from the old permissions dir
        readPermissions(Environment.buildPath( Environment.getRootDirectory(), "etc", "permissions"), false);
        // Only read features from OEM config
        readPermissions(Environment.buildPath( Environment.getOemDirectory(), "etc", "sysconfig"), true);
        readPermissions(Environment.buildPath( Environment.getOemDirectory(), "etc", "permissions"), true);
    }

从注释可以看出初始化的过程就是读取配置文件的过程,那么看一下readPermissions函数,readPermissions函数最终调用readPermissionsFromXML函数,读取各xml文件中的配置信息,如下:

    private void readPermissionsFromXml(File permFile, boolean onlyFeatures) {
        FileReader permReader = null;
        try {
            permReader = new FileReader(permFile);
        } catch (FileNotFoundException e) {
            Slog.w(TAG, "Couldn't find or open permissions file " + permFile);
            return;
        }

        try {
            XmlPullParser parser = Xml.newPullParser();
            parser.setInput(permReader);

            int type;
            while ((type=parser.next()) != parser.START_TAG
                       && type != parser.END_DOCUMENT) {
                ;
            }

            if (type != parser.START_TAG) {
                throw new XmlPullParserException("No start tag found");
            }

            if (!parser.getName().equals("permissions") && !parser.getName().equals("config")) {
                throw new XmlPullParserException("Unexpected start tag: found " + parser.getName() +
                        ", expected 'permissions' or 'config'");
            }

            while (true) {
                XmlUtils.nextElement(parser);
                if (parser.getEventType() == XmlPullParser.END_DOCUMENT) {
                    break;
                }

                String name = parser.getName();
                if ("group".equals(name) && !onlyFeatures) {
                    String gidStr = parser.getAttributeValue(null, "gid");
                    if (gidStr != null) {
                        int gid = android.os.Process.getGidForName(gidStr);
                        mGlobalGids = appendInt(mGlobalGids, gid);
                    } else {
                        Slog.w(TAG, "<group> without gid at "
                                + parser.getPositionDescription());
                    }
                    XmlUtils.skipCurrentTag(parser);
                    continue;
                } else if ("permission".equals(name) && !onlyFeatures) {
                    String perm = parser.getAttributeValue(null, "name");
                    if (perm == null) {
                        Slog.w(TAG, "<permission> without name at "
                                + parser.getPositionDescription());
                        XmlUtils.skipCurrentTag(parser);
                        continue;
                    }
                    perm = perm.intern();
                    readPermission(parser, perm);

                } else if ("assign-permission".equals(name) && !onlyFeatures) {
                    String perm = parser.getAttributeValue(null, "name");
                    if (perm == null) {
                        Slog.w(TAG, "<assign-permission> without name at "
                                + parser.getPositionDescription());
                        XmlUtils.skipCurrentTag(parser);
                        continue;
                    }
                    String uidStr = parser.getAttributeValue(null, "uid");
                    if (uidStr == null) {
                        Slog.w(TAG, "<assign-permission> without uid at "
                                + parser.getPositionDescription());
                        XmlUtils.skipCurrentTag(parser);
                        continue;
                    }
                    int uid = Process.getUidForName(uidStr);
                    if (uid < 0) {
                        Slog.w(TAG, "<assign-permission> with unknown uid \""
                                + uidStr + "\" at "
                                + parser.getPositionDescription());
                        XmlUtils.skipCurrentTag(parser);
                        continue;
                    }
.......

从代码中看出,从xml文件解析出来的字段有:group,permission,assign-permission,library,feature,allow-in-power-save,fixed-ime-app等字段,这些字段分别保存到一下数组或者列表中:

     //从etc/permission/*.xml文件中读取给定的Group-id
    int[] mGlobalGids;
    //从系统文件中读取内置的uid-permission对
    final SparseArray<HashSet<String>> mSystemPermissions = new SparseArray<>();

    // 从系统配置文件中读取内置的库,keys是库的名称,string是库的路径
    final ArrayMap<String, String> mSharedLibraries  = new ArrayMap<>();

    // 从系统配置文件中读取的设备支持的特征
    final HashMap<String, FeatureInfo> mAvailableFeatures = new HashMap<>();

   // 从系统文件中读取内置的uid-permission对
    final ArrayMap<String, PermissionEntry> mPermissions = new ArrayMap<>();

    // 从配置文件中读取在省电模式下可以运行的packages的白名单
    final ArraySet<String> mAllowInPowerSave = new ArraySet<>();

    // 不允许进行输入法切换的应用名称列表
    final ArraySet<String> mFixedImeApps = new ArraySet<>();

然后通过get方法提供给其它类使用.

3.此后就是扫描系统pkg和非系统package,进行安装工作.最后收集信息,将信息保存到文件中

    原文作者:RuningM
    原文地址: https://blog.csdn.net/dianshanglian/article/details/44938143
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞