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>