diff options
| -rw-r--r-- | api/current.txt | 1 | ||||
| -rw-r--r-- | api/system-current.txt | 1 | ||||
| -rw-r--r-- | api/test-current.txt | 1 | ||||
| -rw-r--r-- | core/java/android/app/admin/DevicePolicyManager.java | 22 | ||||
| -rw-r--r-- | services/core/java/com/android/server/job/JobServiceContext.java | 29 | ||||
| -rw-r--r-- | services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java | 28 |
6 files changed, 59 insertions, 23 deletions
diff --git a/api/current.txt b/api/current.txt index 23a03940c3ab..61b0989a86ac 100644 --- a/api/current.txt +++ b/api/current.txt @@ -6533,6 +6533,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 a843e6d30ee8..bacbd551c332 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -6777,6 +6777,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 f5b31d10c67b..d270f7c7c403 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -6564,6 +6564,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 6fd4541dcb0f..9e95157b1fc3 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -5983,6 +5983,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 @@ -6013,7 +6033,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/core/java/com/android/server/job/JobServiceContext.java b/services/core/java/com/android/server/job/JobServiceContext.java index 031bdd0ee39c..d3fd3a992a31 100644 --- a/services/core/java/com/android/server/job/JobServiceContext.java +++ b/services/core/java/com/android/server/job/JobServiceContext.java @@ -261,6 +261,13 @@ public final class JobServiceContext implements ServiceConnection { return mRunningJob; } + /** + * Used only for debugging. Will return <code>"<null>"</code> if there is no job running. + */ + private String getRunningJobNameLocked() { + return mRunningJob != null ? mRunningJob.toShortString() : "<null>"; + } + /** Called externally when a job that was scheduled for execution should be cancelled. */ void cancelExecutingJobLocked(int reason, String debugReason) { doCancelLocked(reason, debugReason); @@ -522,7 +529,7 @@ public final class JobServiceContext implements ServiceConnection { /** Start the job on the service. */ private void handleServiceBoundLocked() { if (DEBUG) { - Slog.d(TAG, "handleServiceBound for " + mRunningJob.toShortString()); + Slog.d(TAG, "handleServiceBound for " + getRunningJobNameLocked()); } if (mVerb != VERB_BINDING) { Slog.e(TAG, "Sending onStartJob for a job that isn't pending. " @@ -639,36 +646,34 @@ public final class JobServiceContext implements ServiceConnection { private void handleOpTimeoutLocked() { switch (mVerb) { case VERB_BINDING: - Slog.w(TAG, "Time-out while trying to bind " + mRunningJob.toShortString() + - ", dropping."); + Slog.w(TAG, "Time-out while trying to bind " + getRunningJobNameLocked() + + ", dropping."); closeAndCleanupJobLocked(false /* needsReschedule */, "timed out while binding"); break; case VERB_STARTING: // Client unresponsive - wedged or failed to respond in time. We don't really // know what happened so let's log it and notify the JobScheduler // FINISHED/NO-RETRY. - Slog.w(TAG, "No response from client for onStartJob " + - mRunningJob != null ? mRunningJob.toShortString() : "<null>"); + Slog.w(TAG, "No response from client for onStartJob " + + getRunningJobNameLocked()); closeAndCleanupJobLocked(false /* needsReschedule */, "timed out while starting"); break; case VERB_STOPPING: // At least we got somewhere, so fail but ask the JobScheduler to reschedule. - Slog.w(TAG, "No response from client for onStopJob " + - mRunningJob != null ? mRunningJob.toShortString() : "<null>"); + Slog.w(TAG, "No response from client for onStopJob " + + getRunningJobNameLocked()); closeAndCleanupJobLocked(true /* needsReschedule */, "timed out while stopping"); break; case VERB_EXECUTING: // Not an error - client ran out of time. Slog.i(TAG, "Client timed out while executing (no jobFinished received), " + - "sending onStop: " + - mRunningJob != null ? mRunningJob.toShortString() : "<null>"); + "sending onStop: " + getRunningJobNameLocked()); mParams.setStopReason(JobParameters.REASON_TIMEOUT); sendStopMessageLocked("timeout while executing"); break; default: - Slog.e(TAG, "Handling timeout for an invalid job state: " + - mRunningJob != null ? mRunningJob.toShortString() : "<null>" - + ", dropping."); + Slog.e(TAG, "Handling timeout for an invalid job state: " + + getRunningJobNameLocked() + ", dropping."); closeAndCleanupJobLocked(false /* needsReschedule */, "invalid timeout"); } } diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index f9af654d82bf..e8724aae2894 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; @@ -8158,7 +8159,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(); @@ -8171,30 +8171,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); } |