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