Android中的多用户与Windows的多用户类似,可以支持多个用户使用系统。通常,第一个在系统中注册的用户将默认成为系统管理员。
不同用户的设置各不相同,并且不同用户安装的应用及应用数据也不相同。但是系统中和硬件相关的设置则是共用的,例如网络设置等。
Android与Windows不同,用户切换后前面用户运行的后台进程还可以继续运行。这样,进行用户切换时无须中断一些后台进行的耗时操作(如下载)。
一、管理用户的系统服务--UserManagerService
UserManagerService的主要功能是创建和删除用户,以及查询用户信息。
1、初始化
UserManagerService是在PackageManagerService的构造方法中创建的,如下:
sUserManager = new UserManagerService(context, this, mInstallLock, mPackages);
UserManagerService的构造方法,如下:
UserManagerService(Context context, PackageManagerService pm,
Object installLock, Object packagesLock) {
this(context, pm, installLock, packagesLock,
Environment.getDataDirectory(),
new File(Environment.getDataDirectory(), "user"));
}
调用另一个构造方法,并多传递了两个参数:/data目录和/data/user文件。如下:
private UserManagerService(Context context, PackageManagerService pm,
Object installLock, Object packagesLock,
File dataDir, File baseUserPath) {
mContext = context;
mPm = pm;
mInstallLock = installLock;
mPackagesLock = packagesLock;
mHandler = new Handler();
synchronized (mInstallLock) {
synchronized (mPackagesLock) {
mUsersDir = new File(dataDir, USER_INFO_DIR);// /data/system/users
mUsersDir.mkdirs();
// Make zeroth user directory, for services to migrate their files to that location
File userZeroDir = new File(mUsersDir, "0");//第一个用户的目录/data/system/users/0
userZeroDir.mkdirs();
mBaseUserPath = baseUserPath;// /data/user
FileUtils.setPermissions(mUsersDir.toString(),
FileUtils.S_IRWXU|FileUtils.S_IRWXG
|FileUtils.S_IROTH|FileUtils.S_IXOTH,
-1, -1);
mUserListFile = new File(mUsersDir, USER_LIST_FILENAME);// /data/system/users/userlist.xml
initDefaultGuestRestrictions();
readUserListLocked();//分析用户的信息文件
// Prune out any partially created/partially removed users.
ArrayList<UserInfo> partials = new ArrayList<UserInfo>();
for (int i = 0; i < mUsers.size(); i++) {
UserInfo ui = mUsers.valueAt(i);
if ((ui.partial || ui.guestToRemove) && i != 0) {
partials.add(ui);//寻找userlist.xml文件中属性partial为true的用户
}
}
for (int i = 0; i < partials.size(); i++) {
UserInfo ui = partials.get(i);
Slog.w(LOG_TAG, "Removing partially created user #" + i
+ " (name=" + ui.name + ")");
removeUserStateLocked(ui.id);//属性为partial表示创建没完成的用户,从系统中移除
}
sInstance = this;
}
}
}
在构造方法中创建了几个目录:/data/system/users、data/system/users/0、/data/system/users/userlist.xml等。之后设置基本的限制条件,如下:
private void initDefaultGuestRestrictions() {
if (mGuestRestrictions.isEmpty()) {
mGuestRestrictions.putBoolean(UserManager.DISALLOW_OUTGOING_CALLS, true);//"no_outgoing_calls"
mGuestRestrictions.putBoolean(UserManager.DISALLOW_SMS, true);//"no_sms"
}
}
然后调用readUserListLocked()方法解析/data/system/users/userlist.xml文件,这个文件保存了系统中所有用户的id信息。文件内容如下:
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<users nextSerialNumber="11" version="5">
<guestRestrictions>
<restrictions no_outgoing_calls="true" no_sms="true" />
</guestRestrictions>
<user id="0" />
<user id="10" />
</users>
得到id信息后还有读取保存了用户注册信息的xml文件,以用户id的数字表示,如0.xml。内容如下:
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<user id="0" serialNumber="0" flags="19" created="0" lastLoggedIn="1436392413074">
<name>Owner</name>
<restrictions />
</user>
读取用户的xml文件内容后,将根据文件内容来创建和初始化一个UserInfo对象来保存信息,并把该对象加入到mUsers列表中。如果xml文件中某个用户的属性中有partial="true',则表示这个用户没有完全创建成功,需要从系统中移除掉。
这样UserManagerService的初始化工作就完成了,主要的工作是分析userlist.xml文件,并创建了mUsers列表中的UserInfo对象。
2、UserInfo的定义
在UserManagerService中,UserInfo对象代表用户,定义如下:public class UserInfo implements Parcelable {
/** 8 bits for user type 用户类型 */
public static final int FLAG_MASK_USER_TYPE = 0x000000FF;
/**
* Primary user. Only one user can have this flag set. Meaning of this
* flag TBD.主用户的标志,通常是第一个Id为0的用户
*/
public static final int FLAG_PRIMARY = 0x00000001;
/**
* User with administrative privileges. Such a user can create and
* delete users.admin用户标志,有此标志才能创建和删除用户
*/
public static final int FLAG_ADMIN = 0x00000002;
/**
* Indicates a guest user that may be transient.guest用户标志
*/
public static final int FLAG_GUEST = 0x00000004;
/**
* Indicates the user has restrictions in privileges, 标识权限受限的用户,具体受限功能未定。
* Exact meaning TBD. For instance, maybe they can't install apps or administer WiFi access pts.
*/
public static final int FLAG_RESTRICTED = 0x00000008;
/**
* Indicates that this user has gone through its first-time initialization.标识该用户是否已经初始化
*/
public static final int FLAG_INITIALIZED = 0x00000010;
/**
* Indicates that this user is a profile of another user, for example holding a users
* corporate data.标识该UserInfo是用户的信息,还是一份profile
*/
public static final int FLAG_MANAGED_PROFILE = 0x00000020;
/**
* Indicates that this user is disabled.标识该用户是否已经被“禁止”
*/
public static final int FLAG_DISABLED = 0x00000040;
public static final int NO_PROFILE_GROUP_ID = -1;//profile group id 的无效值定义
public int id;//用户id
public int serialNumber;//用户的序列号,不会重复
public String name;//用户的名称
public String iconPath;//用户的头像路径
public int flags;//用户的标志
public long creationTime;//创建用户的时间
public long lastLoggedInTime;//上次登录的时间
public int profileGroupId;//用户的profile group id
/** User is only partially created. */
public boolean partial;//此标志为true,表示用户没有创建完成
public boolean guestToRemove;
注意:用户id用来标识用户,用户删除后它的id会分配给下一个新建的用户,保持id号的连续;而serialNumber则是一个在设备中不会重复的数字,用来唯一标识一个用户,如果应用中希望记录和某个用户相关的信息,最好使用serialNumber来表示用户,而不是用户id。
3、用户限制(Restriction)
Android5.1的UserManager中定义了很多和用户相关的限制,这样管理员在创建用户时就能通过这些限制来给予不同用户不同的权限,介绍如下: public static final String DISALLOW_MODIFY_ACCOUNTS = "no_modify_accounts";//限制修改用户账号
public static final String DISALLOW_CONFIG_WIFI = "no_config_wifi";//限制配置WiFi
public static final String DISALLOW_INSTALL_APPS = "no_install_apps";//限制安装app
public static final String DISALLOW_UNINSTALL_APPS = "no_uninstall_apps";//限制卸载app
public static final String DISALLOW_SHARE_LOCATION = "no_share_location";//限制共享地理位置
public static final String DISALLOW_INSTALL_UNKNOWN_SOURCES = "no_install_unknown_sources";//限制安装本地应用
public static final String DISALLOW_CONFIG_BLUETOOTH = "no_config_bluetooth";//限制配置蓝牙
public static final String DISALLOW_USB_FILE_TRANSFER = "no_usb_file_transfer";//限制通过usb传输文件
public static final String DISALLOW_CONFIG_CREDENTIALS = "no_config_credentials";//限制配置设备的安全设置
public static final String DISALLOW_REMOVE_USER = "no_remove_user";//限制删除用户
public static final String DISALLOW_DEBUGGING_FEATURES = "no_debugging_features";//限制使用调试功能
public static final String DISALLOW_CONFIG_VPN = "no_config_vpn";//限制配置VPN
public static final String DISALLOW_CONFIG_TETHERING = "no_config_tethering";//限制配置Tether
public static final String DISALLOW_FACTORY_RESET = "no_factory_reset";//限制进行出厂设置
public static final String DISALLOW_ADD_USER = "no_add_user";//限制创建用户
public static final String ENSURE_VERIFY_APPS = "ensure_verify_apps";//对该用户安装的app要进行校验
public static final String DISALLOW_CONFIG_CELL_BROADCASTS = "no_config_cell_broadcasts";//限制用户配置小区广播
public static final String DISALLOW_CONFIG_MOBILE_NETWORKS = "no_config_mobile_networks";//限制配置移动网络
public static final String DISALLOW_APPS_CONTROL = "no_control_apps";//限制进行清除应用数据和缓存的操作
public static final String DISALLOW_MOUNT_PHYSICAL_MEDIA = "no_physical_media";//限制挂载
public static final String DISALLOW_UNMUTE_MICROPHONE = "no_unmute_microphone";//限制对microphone进行静音
public static final String DISALLOW_ADJUST_VOLUME = "no_adjust_volume";//限制调节音量
public static final String DISALLOW_OUTGOING_CALLS = "no_outgoing_calls";//限制拨打电话
public static final String DISALLOW_SMS = "no_sms";//限制发送短信
public static final String DISALLOW_CREATE_WINDOWS = "no_create_windows";//限制用户的应用进行弹窗功能
public static final String DISALLOW_CROSS_PROFILE_COPY_PASTE = "no_cross_profile_copy_paste";//限制对profile进行复制、粘贴
public static final String DISALLOW_OUTGOING_BEAM = "no_outgoing_beam";//限制
4、添加用户
UserManagerService服务中添加用户的接口是createUser(),如下:
public UserInfo createUser(String name, int flags) {
checkManageUsersPermission("Only the system can create users");
return createUserInternal(name, flags, UserHandle.USER_NULL);
}
createUser()方法首先检查调用者的权限,只有system身份的进程才能调用这个方法。然后调用createUserInternal()方法继续执行,如下:
private UserInfo createUserInternal(String name, int flags, int parentId) {
if (getUserRestrictions(UserHandle.getCallingUserId()).getBoolean(