summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Benjamin Franz <bfranz@google.com> 2017-08-09 14:16:03 +0100
committer Benjamin Franz <bfranz@google.com> 2017-08-31 16:11:47 +0100
commit77c94a9c03cf92a2325b442c863a19e5fd58f255 (patch)
treeea80c815fefb56b8bb314b8f7913268044a18cdf
parentb1671e0e1affc085e0e196e79ee1185d03a5ae91 (diff)
Create a flag to allow starting managed user in background
Currently DPM.createAndManageUser does not start the user in the background, leading to a potential race between user having access to the secondary user and admin having time to push policies. To mitigate this we're adding a flag that allows secondary users to be started in background as part of the API. The admin can then apply policies before switching to that user. Bug: 64382185 Test: cts-tradefed run singleCommand cts -m DevicePolicyManager --test com.android.cts.devicepolicy.DeviceOwnerTest#testCreateAndManageUser_StartUserInBackground --abi arm64-v8a Change-Id: Id6f6ab7584a249680c8554c21977cbb69a220332
-rw-r--r--api/current.txt1
-rw-r--r--api/system-current.txt1
-rw-r--r--api/test-current.txt1
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java22
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java28
5 files changed, 42 insertions, 11 deletions
diff --git a/api/current.txt b/api/current.txt
index 97facecbd681..f1f6fb7532f3 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -6538,6 +6538,7 @@ 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 START_USER_IN_BACKGROUND = 8; // 0x8
field public static final int WIPE_EXTERNAL_STORAGE = 1; // 0x1
field public static final int WIPE_RESET_PROTECTION_DATA = 2; // 0x2
}
diff --git a/api/system-current.txt b/api/system-current.txt
index 2212fd0843cd..6c497293e344 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -6780,6 +6780,7 @@ 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 START_USER_IN_BACKGROUND = 8; // 0x8
field public static final int STATE_USER_PROFILE_COMPLETE = 4; // 0x4
field public static final int STATE_USER_SETUP_COMPLETE = 2; // 0x2
field public static final int STATE_USER_SETUP_FINALIZED = 3; // 0x3
diff --git a/api/test-current.txt b/api/test-current.txt
index 36515a555c99..464ec492fdbc 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -6569,6 +6569,7 @@ 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 START_USER_IN_BACKGROUND = 8; // 0x8
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 d8da8c5bee82..b0c985010830 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -5980,6 +5980,26 @@ public class DevicePolicyManager {
public static final int MAKE_USER_DEMO = 0x0004;
/**
+ * Flag used by {@link #createAndManageUser} to specificy that the newly created user should be
+ * started in the background as part of the user creation.
+ */
+ // TODO: Investigate solutions for the case where reboot happens before setup is completed.
+ public static final int START_USER_IN_BACKGROUND = 0x0008;
+
+ /**
+ * @hide
+ */
+ @IntDef(
+ flag = true,
+ prefix = {"SKIP_", "MAKE_USER_", "START_"},
+ value = {SKIP_SETUP_WIZARD, MAKE_USER_EPHEMERAL, MAKE_USER_DEMO,
+ START_USER_IN_BACKGROUND}
+ )
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface CreateAndManageUserFlags {}
+
+
+ /**
* Called by a device owner to create a user with the specified name and a given component of
* the calling package as profile owner. The UserHandle returned by this method should not be
* persisted as user handles are recycled as users are removed and created. If you need to
@@ -6010,7 +6030,7 @@ public class DevicePolicyManager {
public @Nullable UserHandle createAndManageUser(@NonNull ComponentName admin,
@NonNull String name,
@NonNull ComponentName profileOwner, @Nullable PersistableBundle adminExtras,
- int flags) {
+ @CreateAndManageUserFlags int flags) {
throwIfParentInstance("createAndManageUser");
try {
return mService.createAndManageUser(admin, name, profileOwner, adminExtras, flags);
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index ab919a27802e..77ce7e5dd596 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -43,6 +43,7 @@ import static android.app.admin.DevicePolicyManager.DELEGATION_PACKAGE_ACCESS;
import static android.app.admin.DevicePolicyManager.DELEGATION_PERMISSION_GRANT;
import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_COMPLEX;
import static android.app.admin.DevicePolicyManager.PROFILE_KEYGUARD_FEATURES_AFFECT_OWNER;
+import static android.app.admin.DevicePolicyManager.START_USER_IN_BACKGROUND;
import static android.app.admin.DevicePolicyManager.WIPE_EUICC;
import static android.app.admin.DevicePolicyManager.WIPE_EXTERNAL_STORAGE;
import static android.app.admin.DevicePolicyManager.WIPE_RESET_PROTECTION_DATA;
@@ -8157,7 +8158,6 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
if (user == null) {
return null;
}
- // Set admin.
final long id = mInjector.binderClearCallingIdentity();
try {
final String adminPkg = admin.getPackageName();
@@ -8170,30 +8170,38 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
0 /*installFlags*/, PackageManager.INSTALL_REASON_POLICY);
}
} catch (RemoteException e) {
- Slog.e(LOG_TAG, "Failed to make remote calls for createAndManageUser, "
- + "removing created user", e);
- mUserManager.removeUser(user.getIdentifier());
- return null;
+ // Does not happen, same process
}
+ // Set admin.
setActiveAdmin(profileOwner, true, userHandle);
- // User is not started yet, the broadcast by setActiveAdmin will not be received.
- // So we store adminExtras for broadcasting when the user starts for first time.
- synchronized(this) {
+ final String ownerName = getProfileOwnerName(Process.myUserHandle().getIdentifier());
+ setProfileOwner(profileOwner, ownerName, userHandle);
+
+ synchronized (this) {
DevicePolicyData policyData = getUserData(userHandle);
policyData.mInitBundle = adminExtras;
policyData.mAdminBroadcastPending = true;
saveSettingsLocked(userHandle);
}
- final String ownerName = getProfileOwnerName(Process.myUserHandle().getIdentifier());
- setProfileOwner(profileOwner, ownerName, userHandle);
if ((flags & DevicePolicyManager.SKIP_SETUP_WIZARD) != 0) {
Settings.Secure.putIntForUser(mContext.getContentResolver(),
Settings.Secure.USER_SETUP_COMPLETE, 1, userHandle);
}
+ if ((flags & START_USER_IN_BACKGROUND) != 0) {
+ try {
+ mInjector.getIActivityManager().startUserInBackground(user.getIdentifier());
+ } catch (RemoteException re) {
+ // Does not happen, same process
+ }
+ }
+
return user;
+ } catch (Throwable re) {
+ mUserManager.removeUser(user.getIdentifier());
+ return null;
} finally {
mInjector.binderRestoreCallingIdentity(id);
}