summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/content/pm/UserInfo.java7
-rw-r--r--core/java/android/os/UserManager.java8
-rw-r--r--core/java/android/os/UserManagerInternal.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java34
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java4
-rw-r--r--services/core/java/com/android/server/am/UserController.java6
-rw-r--r--services/core/java/com/android/server/pm/UserManagerService.java16
7 files changed, 68 insertions, 18 deletions
diff --git a/core/java/android/content/pm/UserInfo.java b/core/java/android/content/pm/UserInfo.java
index 9cf467534daf..3139151b78a0 100644
--- a/core/java/android/content/pm/UserInfo.java
+++ b/core/java/android/content/pm/UserInfo.java
@@ -73,6 +73,9 @@ public class UserInfo implements Parcelable {
/**
* Indicates that this user is disabled.
+ *
+ * <p>Note: If an ephemeral user is disabled, it shouldn't be later re-enabled. Ephemeral users
+ * are disabled as their removal is in progress to indicate that they shouldn't be re-entered.
*/
public static final int FLAG_DISABLED = 0x00000040;
@@ -171,6 +174,10 @@ public class UserInfo implements Parcelable {
* @return true if this user can be switched to.
**/
public boolean supportsSwitchTo() {
+ if (isEphemeral() && !isEnabled()) {
+ // Don't support switching to an ephemeral user with removal in progress.
+ return false;
+ }
// TODO remove fw.show_hidden_users when we have finished developing managed profiles.
return !isManagedProfile() || SystemProperties.getBoolean("fw.show_hidden_users", false);
}
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 1a093d8e5d8e..da7f85fc0e1d 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -1371,8 +1371,12 @@ public class UserManager {
/**
* Sets the user as enabled, if such an user exists.
- * Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
- * Note that the default is true, it's only that managed profiles might not be enabled.
+ *
+ * <p>Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
+ *
+ * <p>Note that the default is true, it's only that managed profiles might not be enabled.
+ * 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
* @hide
diff --git a/core/java/android/os/UserManagerInternal.java b/core/java/android/os/UserManagerInternal.java
index d2ece8bba3ad..f399719fa1fc 100644
--- a/core/java/android/os/UserManagerInternal.java
+++ b/core/java/android/os/UserManagerInternal.java
@@ -109,6 +109,17 @@ public abstract class UserManagerInternal {
public abstract void removeAllUsers();
/**
+ * Called by the activity manager when the ephemeral user goes to background and its removal
+ * starts as a result.
+ *
+ * <p>It marks the ephemeral user as disabled in order to prevent it from being re-entered
+ * before its removal finishes.
+ *
+ * @param userId the ID of the ephemeral user.
+ */
+ public abstract void onEphemeralUserStop(int userId);
+
+ /**
* Same as UserManager.createUser(), but bypasses the check for DISALLOW_ADD_USER.
*
* <p>Called by the {@link com.android.server.devicepolicy.DevicePolicyManagerService} when
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
index 4c67010f54aa..53fd446b2444 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -199,24 +199,26 @@ public class UserSwitcherController {
currentUserInfo = info;
}
boolean switchToEnabled = allowUserSwitching || isCurrent;
- if (info.isGuest()) {
- guestRecord = new UserRecord(info, null /* picture */,
- true /* isGuest */, isCurrent, false /* isAddUser */,
- false /* isRestricted */, switchToEnabled);
- } else if (info.isEnabled() && info.supportsSwitchToByUser()) {
- Bitmap picture = bitmaps.get(info.id);
- if (picture == null) {
- picture = mUserManager.getUserIcon(info.id);
-
- if (picture != null) {
- picture = BitmapHelper.createCircularClip(
- picture, avatarSize, avatarSize);
+ if (info.isEnabled()) {
+ if (info.isGuest()) {
+ guestRecord = new UserRecord(info, null /* picture */,
+ true /* isGuest */, isCurrent, false /* isAddUser */,
+ false /* isRestricted */, switchToEnabled);
+ } else if (info.supportsSwitchToByUser()) {
+ Bitmap picture = bitmaps.get(info.id);
+ if (picture == null) {
+ picture = mUserManager.getUserIcon(info.id);
+
+ if (picture != null) {
+ picture = BitmapHelper.createCircularClip(
+ picture, avatarSize, avatarSize);
+ }
}
+ int index = isCurrent ? 0 : records.size();
+ records.add(index, new UserRecord(info, picture, false /* isGuest */,
+ isCurrent, false /* isAddUser */, false /* isRestricted */,
+ switchToEnabled));
}
- int index = isCurrent ? 0 : records.size();
- records.add(index, new UserRecord(info, picture, false /* isGuest */,
- isCurrent, false /* isAddUser */, false /* isRestricted */,
- switchToEnabled));
}
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 29608ddf5e1a..ec0e07532104 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -20511,6 +20511,10 @@ public final class ActivityManagerService extends ActivityManagerNative
Slog.w(TAG, "No user info for user #" + targetUserId);
return false;
}
+ if (!targetUserInfo.supportsSwitchTo()) {
+ Slog.w(TAG, "Cannot switch to User #" + targetUserId + ": not supported");
+ return false;
+ }
if (targetUserInfo.isManagedProfile()) {
Slog.w(TAG, "Cannot switch to User #" + targetUserId + ": not a full user");
return false;
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index df24d0bf027b..addffd33d746 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -68,6 +68,7 @@ import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.os.UserManager;
+import android.os.UserManagerInternal;
import android.os.storage.IMountService;
import android.os.storage.StorageManager;
import android.provider.Settings;
@@ -82,6 +83,7 @@ import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.ArrayUtils;
import com.android.internal.widget.LockPatternUtils;
+import com.android.server.LocalServices;
import com.android.server.pm.UserManagerService;
import java.io.PrintWriter;
@@ -561,6 +563,10 @@ final class UserController {
continue;
}
UserInfo userInfo = getUserInfo(oldUserId);
+ if (userInfo.isEphemeral()) {
+ LocalServices.getService(UserManagerInternal.class)
+ .onEphemeralUserStop(oldUserId);
+ }
if (userInfo.isGuest() || userInfo.isEphemeral()) {
// This is a user to be stopped.
stopUsersLocked(oldUserId, true, null);
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index d5ed04a94f37..549026090a49 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -2982,6 +2982,22 @@ public class UserManagerService extends IUserManager.Stub {
}
@Override
+ public void onEphemeralUserStop(int userId) {
+ synchronized (mUsersLock) {
+ UserInfo userInfo = getUserInfoLU(userId);
+ if (userInfo != null && userInfo.isEphemeral()) {
+ // Do not allow switching back to the ephemeral user again as the user is going
+ // to be deleted.
+ userInfo.flags |= UserInfo.FLAG_DISABLED;
+ if (userInfo.isGuest()) {
+ // Indicate that the guest will be deleted after it stops.
+ userInfo.guestToRemove = true;
+ }
+ }
+ }
+ }
+
+ @Override
public UserInfo createUserEvenWhenDisallowed(String name, int flags) {
UserInfo user = createUserInternalUnchecked(name, flags, UserHandle.USER_NULL);
// Keep this in sync with UserManager.createUser