diff options
5 files changed, 131 insertions, 48 deletions
diff --git a/api/current.txt b/api/current.txt index 2794a7661744..922c56a5181a 100644 --- a/api/current.txt +++ b/api/current.txt @@ -6498,7 +6498,7 @@ package android.app.admin { method public boolean isUsingUnifiedPassword(android.content.ComponentName); method public void lockNow(); method public void lockNow(int); - method public boolean logoutUser(android.content.ComponentName); + method public int logoutUser(android.content.ComponentName); method public void reboot(android.content.ComponentName); method public void removeActiveAdmin(android.content.ComponentName); method public boolean removeCrossProfileWidgetProvider(android.content.ComponentName, java.lang.String); @@ -6583,8 +6583,8 @@ package android.app.admin { method public void setTrustAgentConfiguration(android.content.ComponentName, android.content.ComponentName, android.os.PersistableBundle); method public void setUninstallBlocked(android.content.ComponentName, java.lang.String, boolean); method public void setUserIcon(android.content.ComponentName, android.graphics.Bitmap); - method public boolean startUserInBackground(android.content.ComponentName, android.os.UserHandle); - method public boolean stopUser(android.content.ComponentName, android.os.UserHandle); + method public int startUserInBackground(android.content.ComponentName, android.os.UserHandle); + method public int stopUser(android.content.ComponentName, android.os.UserHandle); method public boolean switchUser(android.content.ComponentName, android.os.UserHandle); method public void transferOwnership(android.content.ComponentName, android.content.ComponentName, android.os.PersistableBundle); method public void uninstallAllUserCaCerts(android.content.ComponentName); @@ -6698,6 +6698,11 @@ package android.app.admin { field public static final int RESET_PASSWORD_DO_NOT_ASK_CREDENTIALS_ON_BOOT = 2; // 0x2 field public static final int RESET_PASSWORD_REQUIRE_ENTRY = 1; // 0x1 field public static final int SKIP_SETUP_WIZARD = 1; // 0x1 + field public static final int USER_OPERATION_ERROR_CURRENT_USER = 4; // 0x4 + field public static final int USER_OPERATION_ERROR_MANAGED_PROFILE = 2; // 0x2 + field public static final int USER_OPERATION_ERROR_MAX_RUNNING_USERS = 3; // 0x3 + field public static final int USER_OPERATION_ERROR_UNKNOWN = 1; // 0x1 + field public static final int USER_OPERATION_SUCCESS = 0; // 0x0 field public static final int WIPE_EXTERNAL_STORAGE = 1; // 0x1 field public static final int WIPE_RESET_PROTECTION_DATA = 2; // 0x2 } diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 131abb5e4664..e190fd4cf6cd 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -6609,15 +6609,81 @@ public class DevicePolicyManager { } /** + * Indicates user operation is successful. + * + * @see #startUserInBackground(ComponentName, UserHandle) + * @see #stopUser(ComponentName, UserHandle) + * @see #logoutUser(ComponentName) + */ + public static final int USER_OPERATION_SUCCESS = 0; + + /** + * Indicates user operation failed for unknown reason. + * + * @see #startUserInBackground(ComponentName, UserHandle) + * @see #stopUser(ComponentName, UserHandle) + * @see #logoutUser(ComponentName) + */ + public static final int USER_OPERATION_ERROR_UNKNOWN = 1; + + /** + * Indicates user operation failed because target user is a managed profile. + * + * @see #startUserInBackground(ComponentName, UserHandle) + * @see #stopUser(ComponentName, UserHandle) + * @see #logoutUser(ComponentName) + */ + public static final int USER_OPERATION_ERROR_MANAGED_PROFILE = 2; + + /** + * Indicates user operation failed because maximum running user limit has reached. + * + * @see #startUserInBackground(ComponentName, UserHandle) + */ + public static final int USER_OPERATION_ERROR_MAX_RUNNING_USERS = 3; + + /** + * Indicates user operation failed because the target user is in foreground. + * + * @see #stopUser(ComponentName, UserHandle) + * @see #logoutUser(ComponentName) + */ + public static final int USER_OPERATION_ERROR_CURRENT_USER = 4; + + /** + * Result returned from + * <ul> + * <li>{@link #startUserInBackground(ComponentName, UserHandle)}</li> + * <li>{@link #stopUser(ComponentName, UserHandle)}</li> + * <li>{@link #logoutUser(ComponentName)}</li> + * </ul> + * + * @hide + */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = { "USER_OPERATION_" }, value = { + USER_OPERATION_SUCCESS, + USER_OPERATION_ERROR_UNKNOWN, + USER_OPERATION_ERROR_MANAGED_PROFILE, + USER_OPERATION_ERROR_MAX_RUNNING_USERS, + USER_OPERATION_ERROR_CURRENT_USER + }) + public @interface UserOperationResult {} + + /** * Called by a device owner to start the specified secondary user in background. * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. - * @param userHandle the user to be stopped. - * @return {@code true} if the user can be started, {@code false} otherwise. + * @param userHandle the user to be started in background. + * @return one of the following result codes: + * {@link #USER_OPERATION_ERROR_UNKNOWN}, + * {@link #USER_OPERATION_SUCCESS}, + * {@link #USER_OPERATION_ERROR_MANAGED_PROFILE}, + * {@link #USER_OPERATION_ERROR_MAX_RUNNING_USERS}, * @throws SecurityException if {@code admin} is not a device owner. * @see #getSecondaryUsers(ComponentName) */ - public boolean startUserInBackground( + public @UserOperationResult int startUserInBackground( @NonNull ComponentName admin, @NonNull UserHandle userHandle) { throwIfParentInstance("startUserInBackground"); try { @@ -6632,11 +6698,16 @@ public class DevicePolicyManager { * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @param userHandle the user to be stopped. - * @return {@code true} if the user can be stopped, {@code false} otherwise. + * @return one of the following result codes: + * {@link #USER_OPERATION_ERROR_UNKNOWN}, + * {@link #USER_OPERATION_SUCCESS}, + * {@link #USER_OPERATION_ERROR_MANAGED_PROFILE}, + * {@link #USER_OPERATION_ERROR_CURRENT_USER} * @throws SecurityException if {@code admin} is not a device owner. * @see #getSecondaryUsers(ComponentName) */ - public boolean stopUser(@NonNull ComponentName admin, @NonNull UserHandle userHandle) { + public @UserOperationResult int stopUser( + @NonNull ComponentName admin, @NonNull UserHandle userHandle) { throwIfParentInstance("stopUser"); try { return mService.stopUser(admin, userHandle); @@ -6650,11 +6721,15 @@ public class DevicePolicyManager { * calling user and switch back to primary. * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. - * @return {@code true} if the exit was successful, {@code false} otherwise. + * @return one of the following result codes: + * {@link #USER_OPERATION_ERROR_UNKNOWN}, + * {@link #USER_OPERATION_SUCCESS}, + * {@link #USER_OPERATION_ERROR_MANAGED_PROFILE}, + * {@link #USER_OPERATION_ERROR_CURRENT_USER} * @throws SecurityException if {@code admin} is not a profile owner affiliated with the device. * @see #getSecondaryUsers(ComponentName) */ - public boolean logoutUser(@NonNull ComponentName admin) { + public @UserOperationResult int logoutUser(@NonNull ComponentName admin) { throwIfParentInstance("logoutUser"); try { return mService.logoutUser(admin); diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl index cba9311ff68b..5197de4cef9f 100644 --- a/core/java/android/app/admin/IDevicePolicyManager.aidl +++ b/core/java/android/app/admin/IDevicePolicyManager.aidl @@ -227,9 +227,9 @@ interface IDevicePolicyManager { UserHandle createAndManageUser(in ComponentName who, in String name, in ComponentName profileOwner, in PersistableBundle adminExtras, in int flags); boolean removeUser(in ComponentName who, in UserHandle userHandle); boolean switchUser(in ComponentName who, in UserHandle userHandle); - boolean startUserInBackground(in ComponentName who, in UserHandle userHandle); - boolean stopUser(in ComponentName who, in UserHandle userHandle); - boolean logoutUser(in ComponentName who); + int startUserInBackground(in ComponentName who, in UserHandle userHandle); + int stopUser(in ComponentName who, in UserHandle userHandle); + int logoutUser(in ComponentName who); List<UserHandle> getSecondaryUsers(in ComponentName who); void enableSystemApp(in ComponentName admin, in String callerPackage, in String packageName); diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java b/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java index d1cc5de821c7..9fcf3eedd983 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java @@ -19,12 +19,10 @@ import android.annotation.UserIdInt; import android.app.admin.IDevicePolicyManager; import android.content.ComponentName; import android.os.PersistableBundle; -import android.os.UserHandle; import android.security.keymaster.KeymasterCertificateChain; import android.security.keystore.ParcelableKeyGenParameterSpec; import android.telephony.data.ApnSetting; -import com.android.internal.R; import com.android.server.SystemService; import java.util.ArrayList; @@ -107,11 +105,6 @@ abstract class BaseIDevicePolicyManager extends IDevicePolicyManager.Stub { } @Override - public boolean startUserInBackground(ComponentName who, UserHandle userHandle) { - return false; - } - - @Override public void setStartUserSessionMessage( ComponentName admin, CharSequence startUserSessionMessage) {} diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index dae760576b4f..7c7811a8de4e 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -19,7 +19,6 @@ package com.android.server.devicepolicy; import static android.Manifest.permission.BIND_DEVICE_ADMIN; import static android.Manifest.permission.MANAGE_CA_CERTIFICATES; import static android.app.ActivityManager.LOCK_TASK_MODE_NONE; -import static android.app.ActivityManager.USER_OP_SUCCESS; import static android.app.admin.DeviceAdminReceiver.EXTRA_TRANSFER_OWNERSHIP_ADMIN_EXTRAS_BUNDLE; import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_USER; import static android.app.admin.DevicePolicyManager.CODE_ACCOUNTS_NOT_EMPTY; @@ -68,9 +67,6 @@ import static com.android.internal.logging.nano.MetricsProto.MetricsEvent import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker .STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW; -import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.PROVISIONING_ENTRY_POINT_ADB; -import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW; - import static com.android.server.devicepolicy.TransferOwnershipMetadataManager.ADMIN_TYPE_DEVICE_OWNER; import static com.android.server.devicepolicy.TransferOwnershipMetadataManager.ADMIN_TYPE_PROFILE_OWNER; @@ -249,7 +245,6 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Objects; -import java.util.Map.Entry; import java.util.Set; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; @@ -9030,7 +9025,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } @Override - public boolean startUserInBackground(ComponentName who, UserHandle userHandle) { + public int startUserInBackground(ComponentName who, UserHandle userHandle) { Preconditions.checkNotNull(who, "ComponentName is null"); Preconditions.checkNotNull(userHandle, "UserHandle is null"); @@ -9041,27 +9036,31 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { final int userId = userHandle.getIdentifier(); if (isManagedProfile(userId)) { Log.w(LOG_TAG, "Managed profile cannot be started in background"); - return false; + return DevicePolicyManager.USER_OPERATION_ERROR_MANAGED_PROFILE; } final long id = mInjector.binderClearCallingIdentity(); try { if (!mInjector.getActivityManagerInternal().canStartMoreUsers()) { Log.w(LOG_TAG, "Cannot start more users in background"); - return false; + return DevicePolicyManager.USER_OPERATION_ERROR_MAX_RUNNING_USERS; } - return mInjector.getIActivityManager().startUserInBackground(userId); + if (mInjector.getIActivityManager().startUserInBackground(userId)) { + return DevicePolicyManager.USER_OPERATION_SUCCESS; + } else { + return DevicePolicyManager.USER_OPERATION_ERROR_UNKNOWN; + } } catch (RemoteException e) { // Same process, should not happen. - return false; + return DevicePolicyManager.USER_OPERATION_ERROR_UNKNOWN; } finally { mInjector.binderRestoreCallingIdentity(id); } } @Override - public boolean stopUser(ComponentName who, UserHandle userHandle) { + public int stopUser(ComponentName who, UserHandle userHandle) { Preconditions.checkNotNull(who, "ComponentName is null"); Preconditions.checkNotNull(userHandle, "UserHandle is null"); @@ -9072,23 +9071,14 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { final int userId = userHandle.getIdentifier(); if (isManagedProfile(userId)) { Log.w(LOG_TAG, "Managed profile cannot be stopped"); - return false; + return DevicePolicyManager.USER_OPERATION_ERROR_MANAGED_PROFILE; } - final long id = mInjector.binderClearCallingIdentity(); - try { - return mInjector.getIActivityManager().stopUser(userId, true /*force*/, null) - == USER_OP_SUCCESS; - } catch (RemoteException e) { - // Same process, should not happen. - return false; - } finally { - mInjector.binderRestoreCallingIdentity(id); - } + return stopUserUnchecked(userId); } @Override - public boolean logoutUser(ComponentName who) { + public int logoutUser(ComponentName who) { Preconditions.checkNotNull(who, "ComponentName is null"); final int callingUserId = mInjector.userHandleGetCallingUserId(); @@ -9102,20 +9092,40 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { if (isManagedProfile(callingUserId)) { Log.w(LOG_TAG, "Managed profile cannot be logout"); - return false; + return DevicePolicyManager.USER_OPERATION_ERROR_MANAGED_PROFILE; } final long id = mInjector.binderClearCallingIdentity(); try { if (!mInjector.getIActivityManager().switchUser(UserHandle.USER_SYSTEM)) { Log.w(LOG_TAG, "Failed to switch to primary user"); - return false; + // This should never happen as target user is UserHandle.USER_SYSTEM + return DevicePolicyManager.USER_OPERATION_ERROR_UNKNOWN; } - return mInjector.getIActivityManager().stopUser(callingUserId, true /*force*/, null) - == USER_OP_SUCCESS; } catch (RemoteException e) { // Same process, should not happen. - return false; + return DevicePolicyManager.USER_OPERATION_ERROR_UNKNOWN; + } finally { + mInjector.binderRestoreCallingIdentity(id); + } + + return stopUserUnchecked(callingUserId); + } + + private int stopUserUnchecked(int userId) { + final long id = mInjector.binderClearCallingIdentity(); + try { + switch (mInjector.getIActivityManager().stopUser(userId, true /*force*/, null)) { + case ActivityManager.USER_OP_SUCCESS: + return DevicePolicyManager.USER_OPERATION_SUCCESS; + case ActivityManager.USER_OP_IS_CURRENT: + return DevicePolicyManager.USER_OPERATION_ERROR_CURRENT_USER; + default: + return DevicePolicyManager.USER_OPERATION_ERROR_UNKNOWN; + } + } catch (RemoteException e) { + // Same process, should not happen. + return DevicePolicyManager.USER_OPERATION_ERROR_UNKNOWN; } finally { mInjector.binderRestoreCallingIdentity(id); } |