8.2.6 解析packages文件
调用mSettings.readLPw()方法解析系统中以下4个packages文件:
/data/system/packages. xml
/data/system/packages-backup. xml
/data/system/packages-stopped. xml
/data/system/packages-stopped-backup. xml.
这4个文件都是在mSettings初始化的过程中指定的。解析成功后返回结果true存入PackageManagerService.mRestoredSettings变量中,其代码如下:
mRestoredSettings=mSettings.readLPw(getUsers());
packages. xml在系统第一次启动的时候是不存在的,它是在后续步骤中由scanDirLi方法解析完APK后,调用mSettings.writeLP()方法创建的。该文件实质是对mSetings对象的持久化,记录了系统的permissions,以及每个已安装APK的name、codePath、flags、ts、version、uesrid等信息,这些信息主要通过scanDirLi方法解析APK的AndroidManifest.xml文件获取。当有APK安装或卸载时也会更新这个文件,所以这个文件中的信息是动态的。
packages-backup. xml是packages.xml的备份文件,每次需要更新packages.xml时,先将packages.xml更名为packages-backup.xml,然后创建新的packages.xml文件。packages.xml创建成功后会删除packages-backup.xml。
packages-stopped. xml中记录了被强制停止的应用程序,通常可以在Settings中强制停止一个应用程序。应用程序被强行停止后,其信息便记录到packages-stopped.xml中,同样packages-stopped-backup.xml是其备份文件。
packages-stopped. xml和packages-stopped-backup.xml在Jelly Bean中已经废弃,取而代之的是package-restrictions.xml和package-restrictions-backup.xml。
readLPw以getUsers()的返回值为参数,对于system或者root用户,返回UserManager.mUsers中存储的用户信息。readLPw的详细处理流程如图8-7所示。
图 8-7 readLPw处理过程
图8-7中显示readLPw方法主要包括4个步骤。下面将详细分析这4个步骤。
步骤1 readLPw方法首先判断packages-backup.xml是否存在。如果packages-backup.xml文件存在,说明系统出现过异常情况导致packages.xml中的数据是不完整的。当发现异常情况时,首先打开packages-backup.xml备份文件,以备之后的步骤处理;然后调用report-SettingsProblem方法记录异常情况到uiderrors.txt文件中;接着判断packages.xml文件是否存在,如果存在则删除;最后清空mSettings.mPendingPackages和mSettings.mPast-Signatures。如果没有发现异常情况,则直接清空mSettings.mPendingPackages和mSettings.mPastSignatures。以上步骤执行完毕后,出现两种情况:packages-backup.xml和packages.xml只存在其中一个;packages-backup.xml和packages.xml都不存在。
步骤2 判断步骤1的处理结果,如果packages.xml和packages-backup.xml都不存在,说明该信息丢失或者这是系统第一次启动,此时需要执行readDefaultPreferredAppsLPw方法解析etc/preferred-apps目录下的XML文件,并读取<preferred-activities>标签的值存入Settings的成员变量mPreferredActivities中。步骤2执行完毕后,不经过步骤3和步骤4直接返回false。
如果packages.xml和packages-backup.xml只存在一个,首先判断需要解析packages.xml还是packages-backup.xml;然后便根据不同的标签分别调用不同的处理方法解析各个标签,这些信息最终保存到mSettings的成员变量中。
步骤3 处理mPendingPackages中的packages信息。在步骤2中,调用readPackageLPw时,如果发现sharedUserId属性,则把该包信息暂时存入到mPendingPackages中,以便解析完所有sharedUserId后再将这部分信息填入packages中。mPendingPackages中的包信息处理完毕后,需要更新那些升级过的系统级package(mDisabledSysPackages)的sharedUserId信息。
步骤4 解析packages-stopped.xml和packages-stopped-backup.xml。如果这两个文件至少存在一个,则解析强行停止的包信息,并在Settings.mPackages找到该包对应的Package Setting信息,将其设置为stop状态,最后调用writePackageRestrictionsLPr(0)方法将信息写入package-restrictions.xml中。如果packages-stopped.xml和packages-stopped-backup.xml都不存在,则调用readPackageRestrictionsLPr,从package-restrictions.xml文件中读取stopped和notLaunched的包信息,并设置Settings.mPackages中相应的状态值。
注意Jelly Bean中已经废弃packages-stopped.xml和packages-stopped-backup.xml,其功能并入package-restrictions.xml中。