• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
CopyAccountToUserTask( int sourceUserId, Context context, ProvisioningParams provisioningParams, Callback callback)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
run(int userId)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
getStatusMsgId()79     public int getStatusMsgId() {
80         return R.string.progress_finishing_touches;
81     }
82 
83     @Override
getMetricsCategory()84     protected int getMetricsCategory() {
85         return PROVISIONING_COPY_ACCOUNT_TASK_MS;
86     }
87 
88     @VisibleForTesting
maybeCopyAccount(int targetUserId)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