From 9d98fed98a171183f88a0006f3375d1b51c4f4aa Mon Sep 17 00:00:00 2001 From: Benjamin Franz Date: Wed, 27 Jan 2016 12:50:42 +0000 Subject: Wait for ACTION_USER_UNLOCKED before finishing managed provisioning When setting up a managed profile, we need to wait for the managed profile user to be started and unlocked before finalizing managed provisioning. Not waiting for this will automatically fail account migration. Bug: 26762234 Change-Id: I88451d606ea855acb52291b67637c746b9203fdd --- .../ProfileOwnerProvisioningService.java | 60 ++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/src/com/android/managedprovisioning/ProfileOwnerProvisioningService.java b/src/com/android/managedprovisioning/ProfileOwnerProvisioningService.java index da91ae48..d410a9d2 100644 --- a/src/com/android/managedprovisioning/ProfileOwnerProvisioningService.java +++ b/src/com/android/managedprovisioning/ProfileOwnerProvisioningService.java @@ -28,6 +28,7 @@ import android.app.admin.DevicePolicyManager; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; +import android.content.IntentFilter; import android.content.pm.IPackageManager; import android.content.pm.PackageManager; import android.content.pm.UserInfo; @@ -46,6 +47,9 @@ import com.android.managedprovisioning.task.DeleteNonRequiredAppsTask; import com.android.managedprovisioning.task.DisableBluetoothSharingTask; import com.android.managedprovisioning.task.DisableInstallShortcutListenersTask; +import java.util.concurrent.Semaphore; +import java.util.concurrent.TimeUnit; + /** * Service that runs the profile owner provisioning. * @@ -62,6 +66,10 @@ public class ProfileOwnerProvisioningService extends Service { "com.android.managedprovisioning.cancelled"; public static final String EXTRA_LOG_MESSAGE_KEY = "ProvisioningErrorLogMessage"; + // Maximum time we will wait for ACTION_USER_UNLOCK until we give up and continue without + // account migration. + private static final int USER_UNLOCKED_TIMEOUT_SECONDS = 120; // 2 minutes + // Status flags for the provisioning process. /** Provisioning not started. */ private static final int STATUS_UNKNOWN = 0; @@ -81,6 +89,7 @@ public class ProfileOwnerProvisioningService extends Service { private UserInfo mManagedProfileOrUserInfo; private AccountManager mAccountManager; private UserManager mUserManager; + private UserUnlockedReceiver mUnlockedReceiver; private AsyncTask runnerTask; @@ -300,6 +309,13 @@ public class ProfileOwnerProvisioningService extends Service { if (!startManagedProfile(mManagedProfileOrUserInfo.id)) { throw raiseError("Could not start user in background"); } + // Wait for ACTION_USER_UNLOCKED to be sent before trying to migrate the account. + // Even if no account is present, we should not send the provisioning complete broadcast + // before the managed profile user is properly started. + if ((mUnlockedReceiver != null) && !mUnlockedReceiver.waitForUserUnlocked()) { + return; + } + // Note: account migration must happen after setting the profile owner. // Otherwise, there will be a time interval where some apps may think that the account // does not have a profile owner. @@ -365,6 +381,9 @@ public class ProfileOwnerProvisioningService extends Service { private boolean startManagedProfile(int userId) { ProvisionLogger.logd("Starting user in background"); IActivityManager iActivityManager = ActivityManagerNative.getDefault(); + // Register a receiver for the Intent.ACTION_USER_UNLOCKED to know when the managed profile + // has been started and unlocked. + mUnlockedReceiver = new UserUnlockedReceiver(this, userId); try { return iActivityManager.startUserInBackground(userId); } catch (RemoteException neverThrown) { @@ -572,4 +591,45 @@ public class ProfileOwnerProvisioningService extends Service { public boolean isProvisioningManagedUser() { return mParams.provisioningAction.equals(DevicePolicyManager.ACTION_PROVISION_MANAGED_USER); } + + /** + * BroadcastReceiver that listens to {@link Intent#ACTION_USER_UNLOCKED} in order to provide + * a blocking wait until the managed profile has been started and unlocked. + */ + private static class UserUnlockedReceiver extends BroadcastReceiver { + private static final IntentFilter FILTER = new IntentFilter(Intent.ACTION_USER_UNLOCKED); + + private final Semaphore semaphore = new Semaphore(0); + private final Context mContext; + private final int mUserId; + + UserUnlockedReceiver(Context context, int userId) { + mContext = context; + mUserId = userId; + mContext.registerReceiverAsUser(this, new UserHandle(userId), FILTER, null, null); + } + + @Override + public void onReceive(Context context, Intent intent ) { + if (!Intent.ACTION_USER_UNLOCKED.equals(intent.getAction())) { + ProvisionLogger.logw("Unexpected intent: " + intent); + return; + } + if (intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL) == mUserId) { + ProvisionLogger.logd("Received ACTION_USER_UNLOCKED for user " + mUserId); + semaphore.release(); + mContext.unregisterReceiver(this); + } + } + + public boolean waitForUserUnlocked() { + ProvisionLogger.logd("Waiting for ACTION_USER_UNLOCKED"); + try { + return semaphore.tryAcquire(USER_UNLOCKED_TIMEOUT_SECONDS, TimeUnit.SECONDS); + } catch (InterruptedException ie) { + mContext.unregisterReceiver(this); + return false; + } + } + } } -- cgit v1.2.3 From 2ab06fb394f04afe8fc9261b4e2e0dca1b0dc01a Mon Sep 17 00:00:00 2001 From: Steven Ng Date: Mon, 21 Mar 2016 12:52:27 +0000 Subject: Deprecate the use of package name in Profile owner creation flow + Replace the use of deviceAdminPackageName with deviceAdminComponentName.getPackageName() because, in the profile owner provisioning, the device admin app must be installed. Even only if the package name is provided, the device component name can be inferred by the package name via PackageManager. Bug: 27743708 Change-Id: I4b84c3c899a7a204b2e10ff57e4e75e7191f0340 --- .../managedprovisioning/FinalizationActivity.java | 2 +- .../ProfileOwnerProvisioningService.java | 16 +++++++++------- .../managedprovisioning/model/ProvisioningParams.java | 2 ++ 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/com/android/managedprovisioning/FinalizationActivity.java b/src/com/android/managedprovisioning/FinalizationActivity.java index f77437f4..9e12c64f 100644 --- a/src/com/android/managedprovisioning/FinalizationActivity.java +++ b/src/com/android/managedprovisioning/FinalizationActivity.java @@ -116,7 +116,7 @@ public class FinalizationActivity extends Activity { return; } BroadcastReceiver mdmReceivedSuccessReceiver = new MdmReceivedSuccessReceiver( - mParams.accountToMigrate, mParams.deviceAdminPackageName); + mParams.accountToMigrate, mParams.deviceAdminComponentName.getPackageName()); sendOrderedBroadcastAsUser(provisioningCompleteIntent, managedUserHandle, null, mdmReceivedSuccessReceiver, null, Activity.RESULT_OK, null, null); diff --git a/src/com/android/managedprovisioning/ProfileOwnerProvisioningService.java b/src/com/android/managedprovisioning/ProfileOwnerProvisioningService.java index fb02bb9d..5e7ab71b 100644 --- a/src/com/android/managedprovisioning/ProfileOwnerProvisioningService.java +++ b/src/com/android/managedprovisioning/ProfileOwnerProvisioningService.java @@ -260,7 +260,7 @@ public class ProfileOwnerProvisioningService extends Service { mManagedProfileOrUserInfo.id); // TODO Add separate set of apps for MANAGED_USER, currently same as of DEVICE_OWNER. deleteNonRequiredAppsTask = new DeleteNonRequiredAppsTask(this, - mParams.deviceAdminPackageName, + mParams.deviceAdminComponentName.getPackageName(), (isProvisioningManagedUser() ? DeleteNonRequiredAppsTask.MANAGED_USER : DeleteNonRequiredAppsTask.PROFILE_OWNER), true /* creating new profile */, @@ -435,7 +435,7 @@ public class ProfileOwnerProvisioningService extends Service { // Use an ordered broadcast, so that we only finish when the mdm has received it. // Avoids a lag in the transition between provisioning and the mdm. BroadcastReceiver mdmReceivedSuccessReceiver = new MdmReceivedSuccessReceiver( - mParams.accountToMigrate, mParams.deviceAdminPackageName); + mParams.accountToMigrate, mParams.deviceAdminComponentName.getPackageName()); Intent completeIntent = new Intent(ACTION_PROFILE_PROVISIONING_COMPLETE); completeIntent.setComponent(mParams.deviceAdminComponentName); @@ -468,11 +468,11 @@ public class ProfileOwnerProvisioningService extends Service { private void installMdmOnManagedProfile() throws ProvisioningException { ProvisionLogger.logd("Installing mobile device management app " - + mParams.deviceAdminPackageName + " on managed profile"); + + mParams.deviceAdminComponentName + " on managed profile"); try { int status = mIpm.installExistingPackageAsUser( - mParams.deviceAdminPackageName, mManagedProfileOrUserInfo.id); + mParams.deviceAdminComponentName.getPackageName(), mManagedProfileOrUserInfo.id); switch (status) { case PackageManager.INSTALL_SUCCEEDED: return; @@ -495,12 +495,14 @@ public class ProfileOwnerProvisioningService extends Service { } private void setMdmAsManagedProfileOwner() throws ProvisioningException { - ProvisionLogger.logd("Setting package " + mParams.deviceAdminPackageName + ProvisionLogger.logd("Setting package " + mParams.deviceAdminComponentName + " as managed profile owner."); DevicePolicyManager dpm = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE); - if (!dpm.setProfileOwner(mParams.deviceAdminComponentName, mParams.deviceAdminPackageName, + if (!dpm.setProfileOwner( + mParams.deviceAdminComponentName, + mParams.deviceAdminComponentName.getPackageName(), mManagedProfileOrUserInfo.id)) { ProvisionLogger.logw("Could not set profile owner."); throw raiseError("Could not set profile owner."); @@ -508,7 +510,7 @@ public class ProfileOwnerProvisioningService extends Service { } private void setMdmAsActiveAdmin() { - ProvisionLogger.logd("Setting package " + mParams.deviceAdminPackageName + ProvisionLogger.logd("Setting package " + mParams.deviceAdminComponentName + " as active admin."); DevicePolicyManager dpm = diff --git a/src/com/android/managedprovisioning/model/ProvisioningParams.java b/src/com/android/managedprovisioning/model/ProvisioningParams.java index dde8b8d8..abcd92bb 100644 --- a/src/com/android/managedprovisioning/model/ProvisioningParams.java +++ b/src/com/android/managedprovisioning/model/ProvisioningParams.java @@ -82,6 +82,7 @@ public final class ProvisioningParams implements Parcelable { *

At least one one of deviceAdminPackageName and deviceAdminComponentName should be * non-null. */ + @Deprecated public final String deviceAdminPackageName; /** @@ -364,6 +365,7 @@ public final class ProvisioningParams implements Parcelable { return this; } + @Deprecated public Builder setDeviceAdminPackageName(String deviceAdminPackageName) { mDeviceAdminPackageName = deviceAdminPackageName; return this; -- cgit v1.2.3