• 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_START_PROFILE_TASK_MS;
20 import static com.android.internal.util.Preconditions.checkNotNull;
21 
22 import android.app.ActivityManager;
23 import android.app.IActivityManager;
24 import android.content.BroadcastReceiver;
25 import android.content.Context;
26 import android.content.Intent;
27 import android.content.IntentFilter;
28 import android.os.RemoteException;
29 import android.os.UserHandle;
30 
31 import com.android.internal.annotations.VisibleForTesting;
32 import com.android.managedprovisioning.common.ProvisionLogger;
33 import com.android.managedprovisioning.R;
34 import com.android.managedprovisioning.model.ProvisioningParams;
35 
36 import java.util.concurrent.Semaphore;
37 import java.util.concurrent.TimeUnit;
38 
39 /**
40  * This task starts the managed profile and waits for it to be unlocked.
41  */
42 public class StartManagedProfileTask extends AbstractProvisioningTask {
43     // Maximum time we will wait for ACTION_USER_UNLOCK until we give up
44     private static final int USER_UNLOCKED_TIMEOUT_SECONDS = 120; // 2 minutes
45     @VisibleForTesting
46     static final IntentFilter UNLOCK_FILTER = new IntentFilter(Intent.ACTION_USER_UNLOCKED);
47 
48     private final IActivityManager mIActivityManager;
49 
StartManagedProfileTask(Context context, ProvisioningParams params, Callback callback)50     public StartManagedProfileTask(Context context, ProvisioningParams params, Callback callback) {
51         this(ActivityManager.getService(), context, params, callback);
52     }
53 
54     @VisibleForTesting
StartManagedProfileTask( IActivityManager iActivityManager, Context context, ProvisioningParams params, Callback callback)55     StartManagedProfileTask(
56             IActivityManager iActivityManager,
57             Context context,
58             ProvisioningParams params,
59             Callback callback) {
60         super(context, params, callback);
61 
62         mIActivityManager = checkNotNull(iActivityManager);
63     }
64 
65     @Override
run(int userId)66     public void run(int userId) {
67         startTaskTimer();
68         UserUnlockedReceiver unlockedReceiver = new UserUnlockedReceiver(userId);
69         mContext.registerReceiverAsUser(unlockedReceiver, new UserHandle(userId), UNLOCK_FILTER,
70                 null, null);
71         try {
72             if (!mIActivityManager.startUserInBackground(userId)) {
73                 ProvisionLogger.loge("Unable to start user in background: " + userId);
74                 error(0);
75                 return;
76             }
77 
78             if (!unlockedReceiver.waitForUserUnlocked()) {
79                 ProvisionLogger.loge("Timeout whilst waiting for unlock of user: " + userId);
80                 error(0);
81                 return;
82             }
83         } catch (RemoteException e) {
84             ProvisionLogger.loge("Exception when starting user in background: " + userId, e);
85             error(0);
86             return;
87         } finally {
88             mContext.unregisterReceiver(unlockedReceiver);
89         }
90         stopTaskTimer();
91         success();
92     }
93 
94     @Override
getStatusMsgId()95     public int getStatusMsgId() {
96         return R.string.progress_finishing_touches;
97     }
98 
99     @Override
getMetricsCategory()100     protected int getMetricsCategory() {
101         return PROVISIONING_START_PROFILE_TASK_MS;
102     }
103 
104     /**
105      * BroadcastReceiver that listens to {@link Intent#ACTION_USER_UNLOCKED} in order to provide
106      * a blocking wait until the managed profile has been started and unlocked.
107      */
108     @VisibleForTesting
109     static class UserUnlockedReceiver extends BroadcastReceiver {
110         private final Semaphore semaphore = new Semaphore(0);
111         private final int mUserId;
112 
UserUnlockedReceiver(int userId)113         UserUnlockedReceiver(int userId) {
114             mUserId = userId;
115         }
116 
117         @Override
onReceive(Context context, Intent intent )118         public void onReceive(Context context, Intent intent ) {
119             if (!Intent.ACTION_USER_UNLOCKED.equals(intent.getAction())) {
120                 ProvisionLogger.logw("Unexpected intent: " + intent);
121                 return;
122             }
123             if (intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL) == mUserId) {
124                 ProvisionLogger.logd("Received ACTION_USER_UNLOCKED for user " + mUserId);
125                 semaphore.release();
126             }
127         }
128 
waitForUserUnlocked()129         public boolean waitForUserUnlocked() {
130             ProvisionLogger.logd("Waiting for ACTION_USER_UNLOCKED");
131             try {
132                 return semaphore.tryAcquire(USER_UNLOCKED_TIMEOUT_SECONDS, TimeUnit.SECONDS);
133             } catch (InterruptedException ie) {
134                 return false;
135             }
136         }
137     }
138 }
139