Loading core/java/android/os/IUserManager.aidl +1 −0 Original line number Original line Diff line number Diff line Loading @@ -52,4 +52,5 @@ interface IUserManager { void removeRestrictions(); void removeRestrictions(); void setDefaultGuestRestrictions(in Bundle restrictions); void setDefaultGuestRestrictions(in Bundle restrictions); Bundle getDefaultGuestRestrictions(); Bundle getDefaultGuestRestrictions(); boolean markGuestForDeletion(int userHandle); } } core/java/android/os/UserManager.java +16 −0 Original line number Original line Diff line number Diff line Loading @@ -675,6 +675,22 @@ public class UserManager { } } } } /** * @hide * Marks the guest user for deletion to allow a new guest to be created before deleting * the current user who is a guest. * @param userHandle * @return */ public boolean markGuestForDeletion(int userHandle) { try { return mService.markGuestForDeletion(userHandle); } catch (RemoteException re) { Log.w(TAG, "Could not mark guest for deletion", re); return false; } } /** /** * Sets the user as enabled, if such an user exists. * Sets the user as enabled, if such an user exists. * Requires {@link android.Manifest.permission#MANAGE_USERS} permission. * Requires {@link android.Manifest.permission#MANAGE_USERS} permission. Loading packages/SystemUI/src/com/android/systemui/GuestResumeSessionReceiver.java +7 −1 Original line number Original line Diff line number Diff line Loading @@ -112,17 +112,23 @@ public class GuestResumeSessionReceiver extends BroadcastReceiver { return; return; } } userManager.removeUser(currentUser.id); boolean marked = userManager.markGuestForDeletion(currentUser.id); if (!marked) { Log.w(TAG, "Couldn't mark the guest for deletion for user " + userId); return; } UserInfo newGuest = userManager.createGuest(context, currentUser.name); UserInfo newGuest = userManager.createGuest(context, currentUser.name); try { try { if (newGuest == null) { if (newGuest == null) { Log.e(TAG, "Could not create new guest, switching back to owner"); Log.e(TAG, "Could not create new guest, switching back to owner"); ActivityManagerNative.getDefault().switchUser(UserHandle.USER_OWNER); ActivityManagerNative.getDefault().switchUser(UserHandle.USER_OWNER); userManager.removeUser(currentUser.id); WindowManagerGlobal.getWindowManagerService().lockNow(null /* options */); WindowManagerGlobal.getWindowManagerService().lockNow(null /* options */); return; return; } } ActivityManagerNative.getDefault().switchUser(newGuest.id); ActivityManagerNative.getDefault().switchUser(newGuest.id); userManager.removeUser(currentUser.id); } catch (RemoteException e) { } catch (RemoteException e) { Log.e(TAG, "Couldn't wipe session because ActivityManager or WindowManager is dead"); Log.e(TAG, "Couldn't wipe session because ActivityManager or WindowManager is dead"); return; return; Loading services/core/java/com/android/server/am/ActivityManagerService.java +11 −3 Original line number Original line Diff line number Diff line Loading @@ -1107,7 +1107,12 @@ public final class ActivityManagerService extends ActivityManagerNative final ActivityThread mSystemThread; final ActivityThread mSystemThread; // Holds the current foreground user's id int mCurrentUserId = 0; int mCurrentUserId = 0; // Holds the target user's id during a user switch int mTargetUserId = UserHandle.USER_NULL; // If there are multiple profiles for the current user, their ids are here // Currently only the primary user can have managed profiles int[] mCurrentProfileIds = new int[] {UserHandle.USER_OWNER}; // Accessed by ActivityStack int[] mCurrentProfileIds = new int[] {UserHandle.USER_OWNER}; // Accessed by ActivityStack /** /** Loading Loading @@ -17935,6 +17940,7 @@ public final class ActivityManagerService extends ActivityManagerNative return false; return false; } } userName = userInfo.name; userName = userInfo.name; mTargetUserId = userId; } } mHandler.removeMessages(START_USER_SWITCH_MSG); mHandler.removeMessages(START_USER_SWITCH_MSG); mHandler.sendMessage(mHandler.obtainMessage(START_USER_SWITCH_MSG, userId, 0, userName)); mHandler.sendMessage(mHandler.obtainMessage(START_USER_SWITCH_MSG, userId, 0, userName)); Loading Loading @@ -18002,6 +18008,7 @@ public final class ActivityManagerService extends ActivityManagerNative if (foreground) { if (foreground) { mCurrentUserId = userId; mCurrentUserId = userId; mTargetUserId = UserHandle.USER_NULL; // reset, mCurrentUserId has caught up updateCurrentProfileIdsLocked(); updateCurrentProfileIdsLocked(); mWindowManager.setCurrentUser(userId, mCurrentProfileIds); mWindowManager.setCurrentUser(userId, mCurrentProfileIds); // Once the internal notion of the active user has switched, we lock the device // Once the internal notion of the active user has switched, we lock the device Loading Loading @@ -18369,7 +18376,7 @@ public final class ActivityManagerService extends ActivityManagerNative private int stopUserLocked(final int userId, final IStopUserCallback callback) { private int stopUserLocked(final int userId, final IStopUserCallback callback) { if (DEBUG_MU) Slog.i(TAG_MU, "stopUserLocked userId=" + userId); if (DEBUG_MU) Slog.i(TAG_MU, "stopUserLocked userId=" + userId); if (mCurrentUserId == userId) { if (mCurrentUserId == userId && mTargetUserId == UserHandle.USER_NULL) { return ActivityManager.USER_OP_IS_CURRENT; return ActivityManager.USER_OP_IS_CURRENT; } } Loading Loading @@ -18509,12 +18516,13 @@ public final class ActivityManagerService extends ActivityManagerNative throw new SecurityException(msg); throw new SecurityException(msg); } } synchronized (this) { synchronized (this) { return getUserManagerLocked().getUserInfo(mCurrentUserId); int userId = mTargetUserId != UserHandle.USER_NULL ? mTargetUserId : mCurrentUserId; return getUserManagerLocked().getUserInfo(userId); } } } } int getCurrentUserIdLocked() { int getCurrentUserIdLocked() { return mCurrentUserId; return mTargetUserId != UserHandle.USER_NULL ? mTargetUserId : mCurrentUserId; } } @Override @Override services/core/java/com/android/server/pm/UserManagerService.java +42 −1 Original line number Original line Diff line number Diff line Loading @@ -519,7 +519,7 @@ public class UserManagerService extends IUserManager.Stub { for (int i = 0; i < totalUserCount; i++) { for (int i = 0; i < totalUserCount; i++) { UserInfo user = mUsers.valueAt(i); UserInfo user = mUsers.valueAt(i); if (!mRemovingUserIds.get(user.id) if (!mRemovingUserIds.get(user.id) && !user.isGuest()) { && !user.isGuest() && !user.partial) { aliveUserCount++; aliveUserCount++; } } } } Loading Loading @@ -1179,6 +1179,47 @@ public class UserManagerService extends IUserManager.Stub { return count; return count; } } /** * Mark this guest user for deletion to allow us to create another guest * and switch to that user before actually removing this guest. * @param userHandle the userid of the current guest * @return whether the user could be marked for deletion */ public boolean markGuestForDeletion(int userHandle) { checkManageUsersPermission("Only the system can remove users"); if (getUserRestrictions(UserHandle.getCallingUserId()).getBoolean( UserManager.DISALLOW_REMOVE_USER, false)) { Log.w(LOG_TAG, "Cannot remove user. DISALLOW_REMOVE_USER is enabled."); return false; } long ident = Binder.clearCallingIdentity(); try { final UserInfo user; synchronized (mPackagesLock) { user = mUsers.get(userHandle); if (userHandle == 0 || user == null || mRemovingUserIds.get(userHandle)) { return false; } if (!user.isGuest()) { return false; } // Set this to a partially created user, so that the user will be purged // on next startup, in case the runtime stops now before stopping and // removing the user completely. user.partial = true; // Mark it as disabled, so that it isn't returned any more when // profiles are queried. user.flags |= UserInfo.FLAG_DISABLED; user.flags &= ~UserInfo.FLAG_GUEST; writeUserLocked(user); } } finally { Binder.restoreCallingIdentity(ident); } return true; } /** /** * Removes a user and all data directories created for that user. This method should be called * Removes a user and all data directories created for that user. This method should be called * after the user's processes have been terminated. * after the user's processes have been terminated. Loading Loading
core/java/android/os/IUserManager.aidl +1 −0 Original line number Original line Diff line number Diff line Loading @@ -52,4 +52,5 @@ interface IUserManager { void removeRestrictions(); void removeRestrictions(); void setDefaultGuestRestrictions(in Bundle restrictions); void setDefaultGuestRestrictions(in Bundle restrictions); Bundle getDefaultGuestRestrictions(); Bundle getDefaultGuestRestrictions(); boolean markGuestForDeletion(int userHandle); } }
core/java/android/os/UserManager.java +16 −0 Original line number Original line Diff line number Diff line Loading @@ -675,6 +675,22 @@ public class UserManager { } } } } /** * @hide * Marks the guest user for deletion to allow a new guest to be created before deleting * the current user who is a guest. * @param userHandle * @return */ public boolean markGuestForDeletion(int userHandle) { try { return mService.markGuestForDeletion(userHandle); } catch (RemoteException re) { Log.w(TAG, "Could not mark guest for deletion", re); return false; } } /** /** * Sets the user as enabled, if such an user exists. * Sets the user as enabled, if such an user exists. * Requires {@link android.Manifest.permission#MANAGE_USERS} permission. * Requires {@link android.Manifest.permission#MANAGE_USERS} permission. Loading
packages/SystemUI/src/com/android/systemui/GuestResumeSessionReceiver.java +7 −1 Original line number Original line Diff line number Diff line Loading @@ -112,17 +112,23 @@ public class GuestResumeSessionReceiver extends BroadcastReceiver { return; return; } } userManager.removeUser(currentUser.id); boolean marked = userManager.markGuestForDeletion(currentUser.id); if (!marked) { Log.w(TAG, "Couldn't mark the guest for deletion for user " + userId); return; } UserInfo newGuest = userManager.createGuest(context, currentUser.name); UserInfo newGuest = userManager.createGuest(context, currentUser.name); try { try { if (newGuest == null) { if (newGuest == null) { Log.e(TAG, "Could not create new guest, switching back to owner"); Log.e(TAG, "Could not create new guest, switching back to owner"); ActivityManagerNative.getDefault().switchUser(UserHandle.USER_OWNER); ActivityManagerNative.getDefault().switchUser(UserHandle.USER_OWNER); userManager.removeUser(currentUser.id); WindowManagerGlobal.getWindowManagerService().lockNow(null /* options */); WindowManagerGlobal.getWindowManagerService().lockNow(null /* options */); return; return; } } ActivityManagerNative.getDefault().switchUser(newGuest.id); ActivityManagerNative.getDefault().switchUser(newGuest.id); userManager.removeUser(currentUser.id); } catch (RemoteException e) { } catch (RemoteException e) { Log.e(TAG, "Couldn't wipe session because ActivityManager or WindowManager is dead"); Log.e(TAG, "Couldn't wipe session because ActivityManager or WindowManager is dead"); return; return; Loading
services/core/java/com/android/server/am/ActivityManagerService.java +11 −3 Original line number Original line Diff line number Diff line Loading @@ -1107,7 +1107,12 @@ public final class ActivityManagerService extends ActivityManagerNative final ActivityThread mSystemThread; final ActivityThread mSystemThread; // Holds the current foreground user's id int mCurrentUserId = 0; int mCurrentUserId = 0; // Holds the target user's id during a user switch int mTargetUserId = UserHandle.USER_NULL; // If there are multiple profiles for the current user, their ids are here // Currently only the primary user can have managed profiles int[] mCurrentProfileIds = new int[] {UserHandle.USER_OWNER}; // Accessed by ActivityStack int[] mCurrentProfileIds = new int[] {UserHandle.USER_OWNER}; // Accessed by ActivityStack /** /** Loading Loading @@ -17935,6 +17940,7 @@ public final class ActivityManagerService extends ActivityManagerNative return false; return false; } } userName = userInfo.name; userName = userInfo.name; mTargetUserId = userId; } } mHandler.removeMessages(START_USER_SWITCH_MSG); mHandler.removeMessages(START_USER_SWITCH_MSG); mHandler.sendMessage(mHandler.obtainMessage(START_USER_SWITCH_MSG, userId, 0, userName)); mHandler.sendMessage(mHandler.obtainMessage(START_USER_SWITCH_MSG, userId, 0, userName)); Loading Loading @@ -18002,6 +18008,7 @@ public final class ActivityManagerService extends ActivityManagerNative if (foreground) { if (foreground) { mCurrentUserId = userId; mCurrentUserId = userId; mTargetUserId = UserHandle.USER_NULL; // reset, mCurrentUserId has caught up updateCurrentProfileIdsLocked(); updateCurrentProfileIdsLocked(); mWindowManager.setCurrentUser(userId, mCurrentProfileIds); mWindowManager.setCurrentUser(userId, mCurrentProfileIds); // Once the internal notion of the active user has switched, we lock the device // Once the internal notion of the active user has switched, we lock the device Loading Loading @@ -18369,7 +18376,7 @@ public final class ActivityManagerService extends ActivityManagerNative private int stopUserLocked(final int userId, final IStopUserCallback callback) { private int stopUserLocked(final int userId, final IStopUserCallback callback) { if (DEBUG_MU) Slog.i(TAG_MU, "stopUserLocked userId=" + userId); if (DEBUG_MU) Slog.i(TAG_MU, "stopUserLocked userId=" + userId); if (mCurrentUserId == userId) { if (mCurrentUserId == userId && mTargetUserId == UserHandle.USER_NULL) { return ActivityManager.USER_OP_IS_CURRENT; return ActivityManager.USER_OP_IS_CURRENT; } } Loading Loading @@ -18509,12 +18516,13 @@ public final class ActivityManagerService extends ActivityManagerNative throw new SecurityException(msg); throw new SecurityException(msg); } } synchronized (this) { synchronized (this) { return getUserManagerLocked().getUserInfo(mCurrentUserId); int userId = mTargetUserId != UserHandle.USER_NULL ? mTargetUserId : mCurrentUserId; return getUserManagerLocked().getUserInfo(userId); } } } } int getCurrentUserIdLocked() { int getCurrentUserIdLocked() { return mCurrentUserId; return mTargetUserId != UserHandle.USER_NULL ? mTargetUserId : mCurrentUserId; } } @Override @Override
services/core/java/com/android/server/pm/UserManagerService.java +42 −1 Original line number Original line Diff line number Diff line Loading @@ -519,7 +519,7 @@ public class UserManagerService extends IUserManager.Stub { for (int i = 0; i < totalUserCount; i++) { for (int i = 0; i < totalUserCount; i++) { UserInfo user = mUsers.valueAt(i); UserInfo user = mUsers.valueAt(i); if (!mRemovingUserIds.get(user.id) if (!mRemovingUserIds.get(user.id) && !user.isGuest()) { && !user.isGuest() && !user.partial) { aliveUserCount++; aliveUserCount++; } } } } Loading Loading @@ -1179,6 +1179,47 @@ public class UserManagerService extends IUserManager.Stub { return count; return count; } } /** * Mark this guest user for deletion to allow us to create another guest * and switch to that user before actually removing this guest. * @param userHandle the userid of the current guest * @return whether the user could be marked for deletion */ public boolean markGuestForDeletion(int userHandle) { checkManageUsersPermission("Only the system can remove users"); if (getUserRestrictions(UserHandle.getCallingUserId()).getBoolean( UserManager.DISALLOW_REMOVE_USER, false)) { Log.w(LOG_TAG, "Cannot remove user. DISALLOW_REMOVE_USER is enabled."); return false; } long ident = Binder.clearCallingIdentity(); try { final UserInfo user; synchronized (mPackagesLock) { user = mUsers.get(userHandle); if (userHandle == 0 || user == null || mRemovingUserIds.get(userHandle)) { return false; } if (!user.isGuest()) { return false; } // Set this to a partially created user, so that the user will be purged // on next startup, in case the runtime stops now before stopping and // removing the user completely. user.partial = true; // Mark it as disabled, so that it isn't returned any more when // profiles are queried. user.flags |= UserInfo.FLAG_DISABLED; user.flags &= ~UserInfo.FLAG_GUEST; writeUserLocked(user); } } finally { Binder.restoreCallingIdentity(ident); } return true; } /** /** * Removes a user and all data directories created for that user. This method should be called * Removes a user and all data directories created for that user. This method should be called * after the user's processes have been terminated. * after the user's processes have been terminated. Loading