diff --git a/api/current.txt b/api/current.txt index 79c4abd67f822..b0e8ef0402e04 100644 --- a/api/current.txt +++ b/api/current.txt @@ -5344,6 +5344,7 @@ package android.app.admin { method public void setRestrictionsProvider(android.content.ComponentName, android.content.ComponentName); method public void setSecureSetting(android.content.ComponentName, java.lang.String, java.lang.String); method public int setStorageEncryption(android.content.ComponentName, boolean); + method public boolean switchUser(android.content.ComponentName, android.os.UserHandle); method public void uninstallCaCert(android.content.ComponentName, byte[]); method public void wipeData(int); field public static final java.lang.String ACTION_ADD_DEVICE_ADMIN = "android.app.action.ADD_DEVICE_ADMIN"; diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 2feec1b4c8904..6ea6b4b26063b 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -2374,6 +2374,24 @@ public class DevicePolicyManager { } } + /** + * Called by a device owner to switch the specified user to the foreground. + * + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @param userHandle the user to switch to; null will switch to primary. + * @return {@code true} if the switch was successful, {@code false} otherwise. + * + * @see Intent#ACTION_USER_FOREGROUND + */ + public boolean switchUser(ComponentName admin, UserHandle userHandle) { + try { + return mService.switchUser(admin, userHandle); + } catch (RemoteException re) { + Log.w(TAG, "Could not switch user ", re); + return false; + } + } + /** * Called by a profile or device owner to get the application restrictions for a given target * application running in the managed profile. diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl index 40bd7d1bd058d..c27d1ccf51c52 100644 --- a/core/java/android/app/admin/IDevicePolicyManager.aidl +++ b/core/java/android/app/admin/IDevicePolicyManager.aidl @@ -139,6 +139,7 @@ interface IDevicePolicyManager { UserHandle createUser(in ComponentName who, in String name); UserHandle createAndInitializeUser(in ComponentName who, in String name, in String profileOwnerName, in ComponentName profileOwnerComponent, in Bundle adminExtras); boolean removeUser(in ComponentName who, in UserHandle userHandle); + boolean switchUser(in ComponentName who, in UserHandle userHandle); void setAccountManagementDisabled(in ComponentName who, in String accountType, in boolean disabled); String[] getAccountTypesWithManagementDisabled(); diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 61f09f6e3617b..5445dc06b2d84 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -3591,6 +3591,30 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } + @Override + public boolean switchUser(ComponentName who, UserHandle userHandle) { + synchronized (this) { + if (who == null) { + throw new NullPointerException("ComponentName is null"); + } + getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER); + + long id = Binder.clearCallingIdentity(); + try { + int userId = UserHandle.USER_OWNER; + if (userHandle != null) { + userId = userHandle.getIdentifier(); + } + return ActivityManagerNative.getDefault().switchUser(userId); + } catch (RemoteException e) { + Log.e(LOG_TAG, "Couldn't switch user", e); + return false; + } finally { + restoreCallingIdentity(id); + } + } + } + @Override public Bundle getApplicationRestrictions(ComponentName who, String packageName) { final UserHandle userHandle = new UserHandle(UserHandle.getCallingUserId());