8.2.4 创建data目录并初始化UserManager
初始化data信息包含初始化mAppDataDir、mUserAppDataDir、mDrmAppPrivateInstallDir三个变量的值。初始化user信息,即构造UserManager对象,代码如下:
final File mAppDataDir;
final File mUserAppDataDir;
final String mAsecInternalPath;
……
final Installer mInstaller;
final File mDrmAppPrivateInstallDir;
……
static UserManager sUserManager;
……
public PackageManagerService(Context context, boolean factoryTest, boolean onlyCore){
……
mInstaller=new Installer();
……
synchronized(mInstallLock){
synchronized(mPackages){
File dataDir=Environment.getDataDirectory();//即"/data"目录
mAppDataDir=new File(dataDir,"data");
mAsecInternalPath=new File(dataDir,"app-asec").getPath();
mUserAppDataDir=new File(dataDir,"user");
mDrmAppPrivateInstallDir=new File(dataDir,"app-private");
sUserManager=new UserManager(mInstaller, mUserAppDataDir);
……
}
由以上代码可知,首先初始化4个成员变量用来保存数据目录信息,然后创建UserManager。4个成员变量的数据目录赋值如下:
PackageManagerService. mAppDataDir:/data/data
PackageManagerService. mAsecInternalPath:/data/app-asec
PackageManagerService. mUserAppDataDir:/data/user
PackageManagerService. mDrmAppPrivateInstallDir:/data/app-private
创建UserManager,需要传入mInstaller和/data/user两个参数。UserManager定义位于frameworks/base/services/java/com/android/server/pm/UserManager.java中,代码如下:
public class UserManager{
private static final String USER_INFO_DIR="system"+File.separator+"users";
private static final String USER_LIST_FILENAME="userlist.xml";
private SparseArray<UserInfo>mUsers=new SparseArray<UserInfo>();
private final File mUsersDir;
private final File mUserListFile;
private int[]mUserIds;
private Installer mInstaller;
private File mBaseUserPath;
public UserManager(Installer installer, File baseUserPath){
//baseUserPath即/data/user
this(Environment.getDataDirectory(),baseUserPath);
mInstaller=installer;
}
UserManager(File dataDir, File baseUserPath){
//mUsersDir代表data/system/users目录
mUsersDir=new File(dataDir, USER_INFO_DIR);
mUsersDir.mkdirs();
//创建data/system/users/0
File userZeroDir=new File(mUsersDir,"0");
userZeroDir.mkdirs();
//将/data/user存入mBaseUserPath中
mBaseUserPath=baseUserPath;
FileUtils.setPermissions(mUsersDir.toString(),
FileUtils.S_IRWXU|FileUtils.S_IRWXG
|FileUtils.S_IROTH|FileUtils.S_IXOTH,
-1,-1);
//mUserListFile代表data/system/users/userlist.xml
mUserListFile=new File(mUsersDir, USER_LIST_FILENAME);
readUserList();
}
在UserManager的构造函数中,首先创建/data/system/users目录和data/system/users/0文件;然后调用readUserList()方法解析userlist.xml文件。
readUserList()方法会解析/data/system/users/userlist.xml和data/system/users/<UID>.xml文件。解析过程如下:
1)如果userlist.xml文件不存在,则调用fallbackToSingleUser()方法处理异常后返回,否则进行下一步。
2)解析userlist.xml,如果出现解析错误,则调用fallbackToSingleUser()方法处理异常后返回,否则进行下一步。
3)解析userlist.xml的<user>标签并读取其id属性值,进入下一步。
4)以id属性值为参数调用readUser方法解析data/system/users/<id>.xml文件,并创建UserInfo。
5)将UserInfo存入UserManager.mUsers中,其中id为键,UserInfo为值。
6)调用updateUserIdsLocked更新UserManager.mUserIds中的id信息。
readUserList()方法的解析过程涉及UserInfo类,该类位于frameworks/base/core/java/android/content/pm/UserInfo.java中,其代码如下:
public class UserInfo implements Parcelable{
//私有用户,有待完善
public static final int FLAG_PRIMARY=0x00000001;
//管理员用户,可以添加或删除其他用户
public static final int FLAG_ADMIN=0x00000002;
//临时的guest user
public static final int FLAG_GUEST=0x00000004;
public int id;//用户ID
public String name;//用户名
public int flags;//用户类型的标记
public UserInfo(int id, String name, int flags){
this.id=id;
this.name=name;
this.flags=flags;
}
public boolean isPrimary(){//私有用户由FLAG_PRIMARY标记
return(flags&FLAG_PRIMARY)==FLAG_PRIMARY;
}
public boolean isAdmin(){//管理员用户由FLAG_ADMIN标记
return(flags&FLAG_ADMIN)==FLAG_ADMIN;
}
public boolean isGuest(){//guest用户由FLAG_GUEST标记
return(flags&FLAG_GUEST)==FLAG_GUEST;
}
可见Android中定义了三种用户:1)私有用户,2)管理员用户,3)guest用户。用户由用户名、用户ID和用户类型标记三部分组成。
解析userlist.xml文件出现异常时,调用fallbackToSingleUser()方法处理异常,代码如下:
private void fallbackToSingleUser(){
UserInfo primary=new UserInfo(0,"Primary",
UserInfo.FLAG_ADMIN|UserInfo.FLAG_PRIMARY);
mUsers.put(0,primary);
updateUserIds();
writeUserList();
writeUser(primary);
}
在fallbackToSingleUser()方法中,首先创建名为Primary的UserInfo对象,并将其存入UserManager.mUsers中,其在mUsers中的键为0,表示UID值为0;调用updateUserIds()将mUsers中新增加的UserInfo的id值更新到UserManager.mUserIds中;调用writeUserList()将该UserManager.mUsers中存储的UserInfo信息写入userlist.xml中。在当前情况下写入的内容如下:
<users>
<user id="0"/>
</users>
调用writeUser(primary)将primary写入<uid>.xml文件中,这里的<uid>为0,即0.xml文件。文件内容如下:
<user id="0"flags="3">
<name>Primary</name>
</user>