Android可以支持多个用户使用系统,通常第一个在系统中注册的用户将默认成为系统管理员。
不同用户的设置各不相同,并且不同用户安装的应用及应用数据也不相同。但是系统中和硬件相关的设置则是共用的,如网络设置等。
UserManagerService的构造方法如下:
调用了另一个构造方法,并多传递了一个参数:/data目录
先看下/data/system/users/userlist.xml文件的内容,再分析读取过程,文件内容如下:
这样UserManagerService的初始化工作就完成了,主要的工作就是解析userlist.xml文件,并创建了mUsers列表中的UserData对象。
不同用户的设置各不相同,并且不同用户安装的应用及应用数据也不相同。但是系统中和硬件相关的设置则是共用的,如网络设置等。
用户切换后前面用户运行的后台进程还可以继续运行,这样进行用户切换时无须中断一些后台进行的耗时操作(如下载)。
管理用户的系统服务--UserManagerService
UserManagerService的主要功能是创建和删除用户,以及查询用户信息。
1.在PackageManagerService中进行初始化
final ArrayMap<String, PackageParser.Package> mPackages =
new ArrayMap<String, PackageParser.Package>();
public PackageManagerService(Context context, Installer installer,
boolean factoryTest, boolean onlyCore) {
...
synchronized (mInstallLock) {
// writer
synchronized (mPackages) {
...
sUserManager = new UserManagerService(context, this, mPackages);
...
} // synchronized (mPackages)
} // synchronized (mInstallLock)
...
}
@Override
public void systemReady() {
...
sUserManager.systemReady();
...
}
UserManagerService的构造方法如下:
UserManagerService(Context context, PackageManagerService pm, Object packagesLock) {
this(context, pm, packagesLock, Environment.getDataDirectory());
}
调用了另一个构造方法,并多传递了一个参数:/data目录
private static final String USER_INFO_DIR = "system" + File.separator + "users";
private UserManagerService(Context context, PackageManagerService pm,
Object packagesLock, File dataDir) {
mContext = context;
mPm = pm;
mPackagesLock = packagesLock;
mHandler = new MainHandler();
synchronized (mPackagesLock) {
// /data/system/users
mUsersDir = new File(dataDir, USER_INFO_DIR);
mUsersDir.mkdirs();
// Make zeroth user directory, for services to migrate their files to that location
File userZeroDir = new File(mUsersDir, String.valueOf(UserHandle.USER_SYSTEM));
// 创建第一个用户目录:/data/system/users/0
userZeroDir.mkdirs();
// 设置访问文件的权限
FileUtils.setPermissions(mUsersDir.toString(),
FileUtils.S_IRWXU | FileUtils.S_IRWXG | FileUtils.S_IROTH | FileUtils.S_IXOTH,
-1, -1);
// /data/system/users/userlist.xml
mUserListFile = new File(mUsersDir, USER_LIST_FILENAME);
// 初始化来宾账户的默认限制条件
initDefaultGuestRestrictions();
// 从/data/system/users/userlist.xml文件读取用户信息
readUserListLP();
sInstance = this;
}
mLocalService = new LocalService();
LocalServices.addService(UserManagerInternal.class, mLocalService);
mLockPatternUtils = new LockPatternUtils(mContext);
mUserStates.put(UserHandle.USER_SYSTEM, UserState.STATE_BOOTING);
}
private final Bundle mGuestRestrictions = new Bundle();
// 初始化来宾账户的默认限制条件
private void initDefaultGuestRestrictions() {
synchronized (mGuestRestrictions) {
if (mGuestRestrictions.isEmpty()) {
// "no_config_wifi",不允许配置WiFi
mGuestRestrictions.putBoolean(UserManager.DISALLOW_CONFIG_WIFI, true);
// "no_install_unknown_sources",不允许安装未知来源的应用
mGuestRestrictions.putBoolean(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, true);
// "no_outgoing_calls",不允许呼叫电话
mGuestRestrictions.putBoolean(UserManager.DISALLOW_OUTGOING_CALLS, true);
// "no_sms",不允许收发短信
mGuestRestrictions.putBoolean(UserManager.DISALLOW_SMS, true);
}
}
}
先看下/data/system/users/userlist.xml文件的内容,再分析读取过程,文件内容如下:
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<users nextSerialNumber="10" version="5">
<guestRestrictions>
<restrictions no_config_wifi="true" no_outgoing_calls="true" no_sms="true" />
</guestRestrictions>
<user id="0" />
</users>
// 从/data/system/users/userlist.xml文件读取用户信息
private final SparseArray<UserData> mUsers = new SparseArray<>();
private void readUserListLP() {
// 如果文件不存在,则创建管理员用户并返回
if (!mUserListFile.exists()) {
fallbackToSingleUserLP();
return;
}
FileInputStream fis = null;
AtomicFile userListFile = new AtomicFile(mUserListFile);
try {
fis = userListFile.openRead();
XmlPullParser parser = Xml.newPullParser();
parser.setInput(fis, StandardCharsets.UTF_8.name());
int type;
while ((type = parser.next()) != XmlPullParser.START_TAG
&& type != XmlPullParser.END_DOCUMENT) {
// Skip
}
if (type != XmlPullParser.START_TAG) {
Slog.e(LOG_TAG, "Unable to read user list");
// 如果文件异常,则创建管理员用户并返回
fallbackToSingleUserLP();
return;
}
mNextSerialNumber = -1;
// 解析文件
if (parser.getName().equals(TAG_USERS)) {
String lastSerialNumber = parser.getAttributeValue(null, ATTR_NEXT_SERIAL_NO);
if (lastSerialNumber != null) {
mNextSerialNumber = Integer.parseInt(lastSerialNumber);
}
String versionNumber = parser.getAttributeValue(null, ATTR_USER_VERSION);
if (versionNumber != null) {
mUserVersion = Integer.parseInt(versionNumber);
}
}
final Bundle newDevicePolicyGlobalUserRestrictions = new Bundle();
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
if (type == XmlPullParser.START_TAG) {
final String name = parser.getName();
if (name.equals(TAG_USER)) {
String id = parser.getAttributeValue(null, ATTR_ID);
// 初始化UserData对象保存从 /data/system/users/${id}.xml 文件中读取到的用户信息
UserData userData = readUserLP(Integer.parseInt(id));
if (userData != null) {
synchronized (mUsersLock) {
// 把解析到的用户信息保存到mUsers中
mUsers.put(userData.info.id, userData);
if (mNextSerialNumber < 0
|| mNextSerialNumber <= userData.info.id) {
mNextSerialNumber = userData.info.id + 1;
}
}
}
} else if (name.equals(TAG_GUEST_RESTRICTIONS)) {
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
&& type != XmlPullParser.END_TAG) {
if (type == XmlPullParser.START_TAG) {
if (parser.getName().equals(TAG_RESTRICTIONS)) {
synchronized (mGuestRestrictions) {
UserRestrictionsUtils
.readRestrictions(parser, mGuestRestrictions);
}
} else if (parser.getName().equals(TAG_DEVICE_POLICY_RESTRICTIONS)
) {
UserRestrictionsUtils.readRestrictions(parser,
newDevicePolicyGlobalUserRestrictions);
}
break;
}
}
} else if (name.equals(TAG_GLOBAL_RESTRICTION_OWNER_ID)) {
String ownerUserId = parser.getAttributeValue(null, ATTR_ID);
if (ownerUserId != null) {
mGlobalRestrictionOwnerUserId = Integer.parseInt(ownerUserId);
}
}
}
}
synchronized (mRestrictionsLock) {
mDevicePolicyGlobalUserRestrictions = newDevicePolicyGlobalUserRestrictions;
}
// 解析完文件后,更新用户ID
updateUserIds();
// 如果有必要,则升级Version
upgradeIfNecessaryLP();
} catch (IOException | XmlPullParserException e) {
fallbackToSingleUserLP();
} finally {
IoUtils.closeQuietly(fis);
}
}
// 创建管理员用户
private void fallbackToSingleUserLP() {
int flags = UserInfo.FLAG_INITIALIZED;
// In split system user mode, the admin and primary flags are assigned to the first human
// user.
if (!UserManager.isSplitSystemUser()) {
flags |= UserInfo.FLAG_ADMIN | UserInfo.FLAG_PRIMARY;
}
// Create the system user
UserInfo system = new UserInfo(UserHandle.USER_SYSTEM, null, null, flags);
UserData userData = new UserData();
userData.info = system;
synchronized (mUsersLock) {
mUsers.put(system.id, userData);
}
mNextSerialNumber = MIN_USER_ID;
mUserVersion = USER_VERSION;
Bundle restrictions = new Bundle();
synchronized (mRestrictionsLock) {
mBaseUserRestrictions.append(UserHandle.USER_SYSTEM, restrictions);
}
// 更新用户ID
updateUserIds();
// 初始化来宾账户的默认限制条件
initDefaultGuestRestrictions();
/*
* 把用户信息写到 /data/system/users/${id}.xml文件中,简单的写文件,不再看源码
* Writes the user file in this format:
*
* <user flags="20039023" id="0">
* <name>Primary</name>
* </user>
*/
writeUserLP(userData);
/*
* 把用户信息写到 /data/system/users/userlist.xml文件中
* Writes the user list file in this format:
*
* <users nextSerialNumber="3">
* <user id="0"></user>
* <user id="2"></user>
* </users>
*/
writeUserListLP();
}
这样UserManagerService的初始化工作就完成了,主要的工作就是解析userlist.xml文件,并创建了mUsers列表中的UserData对象。