Home | History | Annotate | Download | only in task
      1 /*
      2  * Copyright (C) 2016 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.managedprovisioning.task;
     18 
     19 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.PROVISIONING_COPY_ACCOUNT_TASK_MS;
     20 import static com.android.managedprovisioning.analytics.ProvisioningAnalyticsTracker.COPY_ACCOUNT_EXCEPTION;
     21 import static com.android.managedprovisioning.analytics.ProvisioningAnalyticsTracker.COPY_ACCOUNT_FAILED;
     22 import static com.android.managedprovisioning.analytics.ProvisioningAnalyticsTracker.COPY_ACCOUNT_SUCCEEDED;
     23 import static com.android.managedprovisioning.analytics.ProvisioningAnalyticsTracker.COPY_ACCOUNT_TIMED_OUT;
     24 
     25 import android.accounts.Account;
     26 import android.accounts.AccountManager;
     27 import android.accounts.AuthenticatorException;
     28 import android.accounts.OperationCanceledException;
     29 import android.content.Context;
     30 import android.os.UserHandle;
     31 
     32 import com.android.internal.annotations.VisibleForTesting;
     33 import com.android.managedprovisioning.analytics.ProvisioningAnalyticsTracker;
     34 import com.android.managedprovisioning.common.ProvisionLogger;
     35 import com.android.managedprovisioning.R;
     36 import com.android.managedprovisioning.model.ProvisioningParams;
     37 
     38 import java.io.IOException;
     39 import java.util.concurrent.TimeUnit;
     40 
     41 /**
     42  * This task copies the account in {@link ProvisioningParams#accountToMigrate} from an existing
     43  * user to the user that is being provisioned.
     44  *
     45  * <p>If the account migration fails or times out, we still return success as we consider account
     46  * migration not to be a critical operation.</p>
     47  */
     48 public class CopyAccountToUserTask extends AbstractProvisioningTask {
     49     private static final int ACCOUNT_COPY_TIMEOUT_SECONDS = 60 * 3;  // 3 minutes
     50 
     51     private final int mSourceUserId;
     52     private final ProvisioningAnalyticsTracker mProvisioningAnalyticsTracker;
     53 
     54     public CopyAccountToUserTask(
     55             int sourceUserId,
     56             Context context,
     57             ProvisioningParams provisioningParams,
     58             Callback callback) {
     59         super(context, provisioningParams, callback);
     60 
     61         mSourceUserId = sourceUserId;
     62         mProvisioningAnalyticsTracker = ProvisioningAnalyticsTracker.getInstance();
     63     }
     64 
     65     @Override
     66     public void run(int userId) {
     67         startTaskTimer();
     68 
     69         final boolean copySucceeded = maybeCopyAccount(userId);
     70         // Do not log time if account migration did not succeed, as that isn't useful.
     71         if (copySucceeded) {
     72             stopTaskTimer();
     73         }
     74         // account migration is not considered a critical operation, so succeed anyway
     75         success();
     76     }
     77 
     78     @Override
     79     public int getStatusMsgId() {
     80         return R.string.progress_finishing_touches;
     81     }
     82 
     83     @Override
     84     protected int getMetricsCategory() {
     85         return PROVISIONING_COPY_ACCOUNT_TASK_MS;
     86     }
     87 
     88     @VisibleForTesting
     89     boolean maybeCopyAccount(int targetUserId) {
     90         Account accountToMigrate = mProvisioningParams.accountToMigrate;
     91         UserHandle sourceUser = UserHandle.of(mSourceUserId);
     92         UserHandle targetUser = UserHandle.of(targetUserId);
     93 
     94         if (accountToMigrate == null) {
     95             ProvisionLogger.logd("No account to migrate.");
     96             return false;
     97         }
     98         if (sourceUser.equals(targetUser)) {
     99             ProvisionLogger.loge("sourceUser and targetUser are the same, won't migrate account.");
    100             return false;
    101         }
    102         ProvisionLogger.logd("Attempting to copy account from " + sourceUser + " to " + targetUser);
    103         try {
    104             AccountManager accountManager = (AccountManager)
    105                     mContext.getSystemService(Context.ACCOUNT_SERVICE);
    106             boolean copySucceeded = accountManager.copyAccountToUser(
    107                     accountToMigrate,
    108                     sourceUser,
    109                     targetUser,
    110                     /* callback= */ null, /* handler= */ null)
    111                     .getResult(ACCOUNT_COPY_TIMEOUT_SECONDS, TimeUnit.SECONDS);
    112             if (copySucceeded) {
    113                 ProvisionLogger.logi("Copied account to " + targetUser);
    114                 mProvisioningAnalyticsTracker.logCopyAccountStatus(mContext,
    115                         COPY_ACCOUNT_SUCCEEDED);
    116                 return true;
    117             } else {
    118                 mProvisioningAnalyticsTracker.logCopyAccountStatus(mContext, COPY_ACCOUNT_FAILED);
    119                 ProvisionLogger.loge("Could not copy account to " + targetUser);
    120             }
    121         } catch (OperationCanceledException e) {
    122             mProvisioningAnalyticsTracker.logCopyAccountStatus(mContext, COPY_ACCOUNT_TIMED_OUT);
    123             ProvisionLogger.loge("Exception copying account to " + targetUser, e);
    124         } catch (AuthenticatorException | IOException e) {
    125             mProvisioningAnalyticsTracker.logCopyAccountStatus(mContext, COPY_ACCOUNT_EXCEPTION);
    126             ProvisionLogger.loge("Exception copying account to " + targetUser, e);
    127         }
    128         return false;
    129     }
    130 }
    131