From 9e7ee61753f32ad2fa1d6572fc7d90648cefb0eb Mon Sep 17 00:00:00 2001 From: Benjamin Franz Date: Thu, 8 Oct 2015 14:37:47 +0100 Subject: Add extra checks and timeouts to account migration. DO NOT MERGE Adding an extra check to verify that the account type is ready on the target user. Also, adding a timeout to the copyAccountToUser call to avoid managed provisioning getting stuck in an endless loop in case somehting goes wrong here. Bug: 23798494 Change-Id: Ieea43bbd9c3db29c125eff342aadb86b242cba91 --- .../ProfileOwnerProvisioningService.java | 49 ++++++++++++++++++++-- 1 file changed, 45 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/com/android/managedprovisioning/ProfileOwnerProvisioningService.java b/src/com/android/managedprovisioning/ProfileOwnerProvisioningService.java index e13e53e4..93478b1c 100644 --- a/src/com/android/managedprovisioning/ProfileOwnerProvisioningService.java +++ b/src/com/android/managedprovisioning/ProfileOwnerProvisioningService.java @@ -25,6 +25,7 @@ import static android.Manifest.permission.BIND_DEVICE_ADMIN; import android.accounts.Account; import android.accounts.AccountManager; import android.accounts.AccountManagerFuture; +import android.accounts.AuthenticatorDescription; import android.accounts.AuthenticatorException; import android.accounts.OperationCanceledException; import android.app.Activity; @@ -62,6 +63,7 @@ import com.android.managedprovisioning.task.DisableBluetoothSharingTask; import com.android.managedprovisioning.task.DisableInstallShortcutListenersTask; import java.io.IOException; +import java.util.concurrent.TimeUnit; /** * Service that runs the profile owner provisioning. @@ -94,6 +96,10 @@ public class ProfileOwnerProvisioningService extends Service { /** Provisioning cancelled and cleanup complete. */ private static final int STATUS_CANCELLED = 5; + private static final int ACCOUNT_COPY_TIMEOUT_SECONDS = 60 * 2; // 2 minutes + private static final int ACCOUNT_TYPE_RETRIES = 30; + private static final int ACCOUNT_TYPE_POLLING_TIMEOUT_MILLIS = 1000; // 1 second + private IPackageManager mIpm; private UserInfo mManagedProfileUserInfo; private AccountManager mAccountManager; @@ -434,26 +440,61 @@ public class ProfileOwnerProvisioningService extends Service { } private void copyAccount() { - if (mParams.accountToMigrate == null) { + if (mParams.accountToMigrate == null || mParams.accountToMigrate.type == null) { ProvisionLogger.logd("No account to migrate to the managed profile."); return; } ProvisionLogger.logd("Attempting to copy account to user " + mManagedProfileUserInfo.id); + if (!waitForAuthenticatorReadyForAccountType(mParams.accountToMigrate.type, + mManagedProfileUserInfo.id)) { + ProvisionLogger.loge("Could not copy account to user " + mManagedProfileUserInfo.id + + ". Authenticator missing for account type " + mParams.accountToMigrate.type); + return; + } try { - if (mAccountManager.copyAccountToUser(mParams.accountToMigrate, + boolean copySucceeded = mAccountManager.copyAccountToUser( + mParams.accountToMigrate, mManagedProfileUserInfo.getUserHandle(), - /* callback= */ null, /* handler= */ null).getResult()) { + /* callback= */ null, /* handler= */ null) + .getResult(ACCOUNT_COPY_TIMEOUT_SECONDS, TimeUnit.SECONDS); + if (copySucceeded) { ProvisionLogger.logi("Copied account to user " + mManagedProfileUserInfo.id); } else { ProvisionLogger.loge("Could not copy account to user " + mManagedProfileUserInfo.id); } } catch (OperationCanceledException | AuthenticatorException | IOException e) { - ProvisionLogger.logw("Exception copying account to user " + mManagedProfileUserInfo.id, + ProvisionLogger.loge("Exception copying account to user " + mManagedProfileUserInfo.id, e); } } + private boolean waitForAuthenticatorReadyForAccountType(String accountType, int userId) { + for (int i = 0; i < ACCOUNT_TYPE_RETRIES; i++) { + if (!isAuthenticatorPresent(accountType, userId)) { + try { + Thread.sleep(ACCOUNT_TYPE_POLLING_TIMEOUT_MILLIS); + } catch (InterruptedException e) { + return false; + } + } else { + return true; + } + } + return false; + } + + private boolean isAuthenticatorPresent(String accountType, int userId) { + AuthenticatorDescription[] authenticators = AccountManager.get(this) + .getAuthenticatorTypesAsUser(userId); + for (AuthenticatorDescription authenticator : authenticators) { + if (authenticator.type.equals(accountType)) { + return true; + } + } + return false; + } + private void createProfile(String profileName) throws ProvisioningException { ProvisionLogger.logd("Creating managed profile with name " + profileName); -- cgit v1.2.3