Merge "Added UserManager#getUserSwitchability."
diff --git a/api/system-current.txt b/api/system-current.txt
index 7fc08fa..f2a81c7 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -5602,7 +5602,6 @@
}
public class UserManager {
- method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS}, conditional=true) public boolean canSwitchUsers();
method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public void clearSeedAccountData();
method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public android.os.UserHandle getProfileParent(@NonNull android.os.UserHandle);
method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public String getSeedAccountName();
@@ -5612,6 +5611,7 @@
method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public android.graphics.Bitmap getUserIcon();
method @Deprecated @android.os.UserManager.UserRestrictionSource @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public int getUserRestrictionSource(String, android.os.UserHandle);
method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public java.util.List<android.os.UserManager.EnforcingUser> getUserRestrictionSources(String, android.os.UserHandle);
+ method @RequiresPermission(allOf={android.Manifest.permission.READ_PHONE_STATE, android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS}, conditional=true) public int getUserSwitchability();
method public boolean hasRestrictedProfiles();
method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean isAdminUser();
method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean isGuestUser();
@@ -5629,6 +5629,10 @@
field public static final int RESTRICTION_SOURCE_DEVICE_OWNER = 2; // 0x2
field public static final int RESTRICTION_SOURCE_PROFILE_OWNER = 4; // 0x4
field public static final int RESTRICTION_SOURCE_SYSTEM = 1; // 0x1
+ field public static final int SWITCHABILITY_STATUS_OK = 0; // 0x0
+ field public static final int SWITCHABILITY_STATUS_SYSTEM_USER_LOCKED = 4; // 0x4
+ field public static final int SWITCHABILITY_STATUS_USER_IN_CALL = 1; // 0x1
+ field public static final int SWITCHABILITY_STATUS_USER_SWITCH_DISALLOWED = 2; // 0x2
}
public static final class UserManager.EnforcingUser implements android.os.Parcelable {
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 921db9f..185df5e 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -25,6 +25,7 @@
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
import android.annotation.UserIdInt;
import android.annotation.WorkerThread;
import android.app.Activity;
@@ -1117,6 +1118,47 @@
public static final int USER_CREATION_FAILED_NO_MORE_USERS = Activity.RESULT_FIRST_USER + 1;
/**
+ * Indicates that users are switchable.
+ * @hide
+ */
+ @SystemApi
+ public static final int SWITCHABILITY_STATUS_OK = 0;
+
+ /**
+ * Indicated that the user is in a phone call.
+ * @hide
+ */
+ @SystemApi
+ public static final int SWITCHABILITY_STATUS_USER_IN_CALL = 1 << 0;
+
+ /**
+ * Indicates that user switching is disallowed ({@link #DISALLOW_USER_SWITCH} is set).
+ * @hide
+ */
+ @SystemApi
+ public static final int SWITCHABILITY_STATUS_USER_SWITCH_DISALLOWED = 1 << 1;
+
+ /**
+ * Indicates that the system user is locked and user switching is not allowed.
+ * @hide
+ */
+ @SystemApi
+ public static final int SWITCHABILITY_STATUS_SYSTEM_USER_LOCKED = 1 << 2;
+
+ /**
+ * Result returned in {@link #getUserSwitchability()} indicating user swichability.
+ * @hide
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(flag = true, prefix = { "SWITCHABILITY_STATUS_" }, value = {
+ SWITCHABILITY_STATUS_OK,
+ SWITCHABILITY_STATUS_USER_IN_CALL,
+ SWITCHABILITY_STATUS_USER_SWITCH_DISALLOWED,
+ SWITCHABILITY_STATUS_SYSTEM_USER_LOCKED
+ })
+ public @interface UserSwitchabilityResult {}
+
+ /**
* Indicates user operation is successful.
*/
public static final int USER_OPERATION_SUCCESS = 0;
@@ -1238,14 +1280,13 @@
}
/**
- * Returns whether switching users is currently allowed.
- * <p>For instance switching users is not allowed if the current user is in a phone call,
- * system user hasn't been unlocked yet, or {@link #DISALLOW_USER_SWITCH} is set.
+ * @deprecated use {@link #getUserSwitchability()} instead.
+ *
+ * @removed
* @hide
*/
- @SystemApi
- @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS,
- android.Manifest.permission.INTERACT_ACROSS_USERS}, conditional = true)
+ @Deprecated
+ @UnsupportedAppUsage
public boolean canSwitchUsers() {
boolean allowUserSwitchingWhenSystemUserLocked = Settings.Global.getInt(
mContext.getContentResolver(),
@@ -1259,6 +1300,42 @@
}
/**
+ * Returns whether switching users is currently allowed.
+ * <p>
+ * Switching users is not allowed in the following cases:
+ * <li>the user is in a phone call</li>
+ * <li>{@link #DISALLOW_USER_SWITCH} is set</li>
+ * <li>system user hasn't been unlocked yet</li>
+ *
+ * @return A {@link UserSwitchabilityResult} flag indicating if the user is switchable.
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(allOf = {Manifest.permission.READ_PHONE_STATE,
+ android.Manifest.permission.MANAGE_USERS,
+ android.Manifest.permission.INTERACT_ACROSS_USERS}, conditional = true)
+ public @UserSwitchabilityResult int getUserSwitchability() {
+ final boolean allowUserSwitchingWhenSystemUserLocked = Settings.Global.getInt(
+ mContext.getContentResolver(),
+ Settings.Global.ALLOW_USER_SWITCHING_WHEN_SYSTEM_USER_LOCKED, 0) != 0;
+ final boolean systemUserUnlocked = isUserUnlocked(UserHandle.SYSTEM);
+ final TelephonyManager tm =
+ (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
+
+ int flags = SWITCHABILITY_STATUS_OK;
+ if (tm.getCallState() != TelephonyManager.CALL_STATE_IDLE) {
+ flags |= SWITCHABILITY_STATUS_USER_IN_CALL;
+ }
+ if (hasUserRestriction(DISALLOW_USER_SWITCH)) {
+ flags |= SWITCHABILITY_STATUS_USER_SWITCH_DISALLOWED;
+ }
+ if (!allowUserSwitchingWhenSystemUserLocked && !systemUserUnlocked) {
+ flags |= SWITCHABILITY_STATUS_SYSTEM_USER_LOCKED;
+ }
+ return flags;
+ }
+
+ /**
* Returns the user handle for the user that this process is running under.
*
* @return the user handle of this process.
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index 85322d6..57ce98c 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -1674,8 +1674,9 @@
int runSwitchUser(PrintWriter pw) throws RemoteException {
UserManager userManager = mInternal.mContext.getSystemService(UserManager.class);
- if (!userManager.canSwitchUsers()) {
- getErrPrintWriter().println("Error: disallowed switching user");
+ final int userSwitchable = userManager.getUserSwitchability();
+ if (userSwitchable != UserManager.SWITCHABILITY_STATUS_OK) {
+ getErrPrintWriter().println("Error: " + userSwitchable);
return -1;
}
String user = getNextArgRequired();
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
index 391627e..e9edba5 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
@@ -532,6 +532,12 @@
}
}
+ public void testGetUserSwitchability() {
+ int userSwitchable = mUserManager.getUserSwitchability();
+ assertEquals("Expected users to be switchable", UserManager.SWITCHABILITY_STATUS_OK,
+ userSwitchable);
+ }
+
@LargeTest
public void testSwitchUser() {
ActivityManager am = getContext().getSystemService(ActivityManager.class);