Merge "Adding hidden APIs for assigning Admin flag to users." into pi-dev

This commit is contained in:
Jovana Knezevic
2018-05-23 05:16:55 +00:00
committed by Android (Google) Code Review
4 changed files with 100 additions and 27 deletions

View File

@@ -45,6 +45,7 @@ interface IUserManager {
in String[] disallowedPackages);
UserInfo createRestrictedProfile(String name, int parentUserHandle);
void setUserEnabled(int userHandle);
void setUserAdmin(int userId);
void evictCredentialEncryptionKey(int userHandle);
boolean removeUser(int userHandle);
boolean removeUserEvenWhenDisallowed(int userHandle);

View File

@@ -2087,12 +2087,33 @@ public class UserManager {
* Also ephemeral users can be disabled to indicate that their removal is in progress and they
* shouldn't be re-entered. Therefore ephemeral users should not be re-enabled once disabled.
*
* @param userHandle the id of the profile to enable
* @param userId the id of the profile to enable
* @hide
*/
public void setUserEnabled(@UserIdInt int userHandle) {
public void setUserEnabled(@UserIdInt int userId) {
try {
mService.setUserEnabled(userHandle);
mService.setUserEnabled(userId);
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
}
}
/**
* Assigns admin privileges to the user, if such a user exists.
*
* <p>Requires {@link android.Manifest.permission#MANAGE_USERS} and
* {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL} permissions.
*
* @param userHandle the id of the user to become admin
* @hide
*/
@RequiresPermission(allOf = {
Manifest.permission.INTERACT_ACROSS_USERS_FULL,
Manifest.permission.MANAGE_USERS
})
public void setUserAdmin(@UserIdInt int userHandle) {
try {
mService.setUserAdmin(userHandle);
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
}

View File

@@ -873,9 +873,8 @@ public class UserManagerService extends IUserManager.Stub {
throw new SecurityException("MANAGE_USERS permission is required to start intent "
+ "after disabling quiet mode.");
}
final boolean hasModifyQuietModePermission = ActivityManager.checkComponentPermission(
Manifest.permission.MODIFY_QUIET_MODE,
callingUid, -1, true) == PackageManager.PERMISSION_GRANTED;
final boolean hasModifyQuietModePermission = hasPermissionGranted(
Manifest.permission.MODIFY_QUIET_MODE, callingUid);
if (hasModifyQuietModePermission) {
return;
}
@@ -1002,6 +1001,30 @@ public class UserManagerService extends IUserManager.Stub {
}
}
@Override
public void setUserAdmin(int userId) {
checkManageUserAndAcrossUsersFullPermission("set user admin");
synchronized (mPackagesLock) {
UserInfo info;
synchronized (mUsersLock) {
info = getUserInfoLU(userId);
}
if (info == null || info.isAdmin()) {
// Exit if no user found with that id, or the user is already an Admin.
return;
}
info.flags ^= UserInfo.FLAG_ADMIN;
writeUserLP(getUserDataLU(info.id));
}
// Remove non-admin restrictions.
// Keep synchronized with createUserEvenWhenDisallowed.
setUserRestriction(UserManager.DISALLOW_SMS, false, userId);
setUserRestriction(UserManager.DISALLOW_OUTGOING_CALLS, false, userId);
}
/**
* Evicts a user's CE key by stopping and restarting the user.
*
@@ -1122,8 +1145,8 @@ public class UserManagerService extends IUserManager.Stub {
hasManageUsersPermission()) {
return;
}
if (ActivityManager.checkComponentPermission(Manifest.permission.INTERACT_ACROSS_USERS,
Binder.getCallingUid(), -1, true) != PackageManager.PERMISSION_GRANTED) {
if (!hasPermissionGranted(Manifest.permission.INTERACT_ACROSS_USERS,
Binder.getCallingUid())) {
throw new SecurityException("You need INTERACT_ACROSS_USERS or MANAGE_USERS permission "
+ "to: check " + name);
}
@@ -1801,17 +1824,26 @@ public class UserManagerService extends IUserManager.Stub {
*/
private static final void checkManageUserAndAcrossUsersFullPermission(String message) {
final int uid = Binder.getCallingUid();
if (uid != Process.SYSTEM_UID && uid != 0
&& ActivityManager.checkComponentPermission(
Manifest.permission.MANAGE_USERS,
uid, -1, true) != PackageManager.PERMISSION_GRANTED
&& ActivityManager.checkComponentPermission(
Manifest.permission.INTERACT_ACROSS_USERS_FULL,
uid, -1, true) != PackageManager.PERMISSION_GRANTED) {
throw new SecurityException(
"You need MANAGE_USERS and INTERACT_ACROSS_USERS_FULL permission to: "
+ message);
if (uid == Process.SYSTEM_UID || uid == 0) {
// System UID or root's UID are granted privilege.
return;
}
if (hasPermissionGranted(Manifest.permission.MANAGE_USERS, uid)
&& hasPermissionGranted(Manifest.permission.INTERACT_ACROSS_USERS_FULL, uid)) {
// Apps with both permissions are granted privilege.
return;
}
throw new SecurityException(
"You need MANAGE_USERS and INTERACT_ACROSS_USERS_FULL permission to: " + message);
}
private static boolean hasPermissionGranted(String permission, int uid) {
return ActivityManager.checkComponentPermission(
permission, uid, /* owningUid = */-1, /* exported = */ true) ==
PackageManager.PERMISSION_GRANTED;
}
/**
@@ -1872,9 +1904,7 @@ public class UserManagerService extends IUserManager.Stub {
final int callingUid = Binder.getCallingUid();
return UserHandle.isSameApp(callingUid, Process.SYSTEM_UID)
|| callingUid == Process.ROOT_UID
|| ActivityManager.checkComponentPermission(
android.Manifest.permission.MANAGE_USERS,
callingUid, -1, true) == PackageManager.PERMISSION_GRANTED;
|| hasPermissionGranted(android.Manifest.permission.MANAGE_USERS, callingUid);
}
/**
@@ -1886,12 +1916,8 @@ public class UserManagerService extends IUserManager.Stub {
final int callingUid = Binder.getCallingUid();
return UserHandle.isSameApp(callingUid, Process.SYSTEM_UID)
|| callingUid == Process.ROOT_UID
|| ActivityManager.checkComponentPermission(
android.Manifest.permission.MANAGE_USERS,
callingUid, -1, true) == PackageManager.PERMISSION_GRANTED
|| ActivityManager.checkComponentPermission(
android.Manifest.permission.CREATE_USERS,
callingUid, -1, true) == PackageManager.PERMISSION_GRANTED;
|| hasPermissionGranted(android.Manifest.permission.MANAGE_USERS, callingUid)
|| hasPermissionGranted(android.Manifest.permission.CREATE_USERS, callingUid);
}
/**

View File

@@ -169,6 +169,31 @@ public class UserManagerTest extends AndroidTestCase {
assertNull(userInfo2);
}
@MediumTest
public void testSetUserAdmin() throws Exception {
UserInfo userInfo = createUser("SecondaryUser", /*flags=*/ 0);
// Assert user is not admin and has SMS and calls restrictions.
assertFalse(userInfo.isAdmin());
assertTrue(mUserManager.hasUserRestriction(UserManager.DISALLOW_SMS,
userInfo.getUserHandle()));
assertTrue(mUserManager.hasUserRestriction(UserManager.DISALLOW_OUTGOING_CALLS,
userInfo.getUserHandle()));
// Assign admin privileges.
mUserManager.setUserAdmin(userInfo.id);
// Refresh.
userInfo = mUserManager.getUserInfo(userInfo.id);
// Verify user became admin and SMS and call restrictions are lifted.
assertTrue(userInfo.isAdmin());
assertFalse(mUserManager.hasUserRestriction(UserManager.DISALLOW_SMS,
userInfo.getUserHandle()));
assertFalse(mUserManager.hasUserRestriction(UserManager.DISALLOW_OUTGOING_CALLS,
userInfo.getUserHandle()));
}
@MediumTest
public void testGetProfileParent() throws Exception {
final int primaryUserId = mUserManager.getPrimaryUser().id;