FinalizationActivity.java revision ba113214d1820f32e5132cd83a06fa1eaedd2866
1/* 2 * Copyright 2014, 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 17package com.android.managedprovisioning; 18 19import android.app.Activity; 20import android.app.admin.DevicePolicyManager; 21import android.content.BroadcastReceiver; 22import android.content.Context; 23import android.content.Intent; 24import android.os.Bundle; 25import android.os.UserHandle; 26 27import com.android.managedprovisioning.Utils.IllegalProvisioningArgumentException; 28 29import static android.app.admin.DeviceAdminReceiver.ACTION_PROFILE_PROVISIONING_COMPLETE; 30import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE; 31import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE; 32 33/* 34 * This class is used to make sure that we start the MDM after we shut the setup wizard down. 35 * The shut down of the setup wizard is initiated in the DeviceOwnerProvisioningActivity or 36 * ProfileOwnerProvisioningActivity by calling 37 * {@link DevicePolicyManager.setUserProvisioningState()}. This will cause the 38 * Setup wizard to shut down and send a ACTION_PROVISIONING_FINALIZATION intent. This intent is 39 * caught by this receiver instead which will send the 40 * ACTION_PROFILE_PROVISIONING_COMPLETE broadcast to the MDM, which can then present it's own 41 * activities. 42 */ 43public class FinalizationActivity extends Activity { 44 45 private ProvisioningParams mParams; 46 47 private static final String INTENT_STORE_NAME = "finalization-receiver"; 48 49 @Override 50 public void onCreate(Bundle savedInstanceState) { 51 super.onCreate(savedInstanceState); 52 53 try { 54 DevicePolicyManager dpm = getSystemService(DevicePolicyManager.class); 55 int currentState = dpm.getUserProvisioningState(); 56 57 switch (currentState) { 58 case DevicePolicyManager.STATE_USER_SETUP_INCOMPLETE: 59 case DevicePolicyManager.STATE_USER_SETUP_COMPLETE: 60 case DevicePolicyManager.STATE_USER_PROFILE_COMPLETE: 61 finalizeProvisioning(dpm); 62 break; 63 case DevicePolicyManager.STATE_USER_UNMANAGED: 64 case DevicePolicyManager.STATE_USER_SETUP_FINALIZED: 65 // Nothing to do in these cases. 66 ProvisionLogger.logw("Received ACTION_PROVISIONING_FINALIZATION intent, but " 67 + "nothing to do in state: " + currentState); 68 break; 69 } 70 } finally { 71 // TODO: Remove this once HomeReceiverActivity is removed. 72 HomeReceiverActivity.disableComponent(this); 73 } 74 75 finish(); 76 } 77 78 public static void storeProvisioningParams(Context context, ProvisioningParams params) { 79 Intent intent = new MessageParser().getIntentFromProvisioningParams(params); 80 getIntentStore(context).save(intent); 81 } 82 83 private void finalizeProvisioning(DevicePolicyManager dpm) { 84 mParams = loadProvisioningParamsAndClearIntentStore(); 85 Intent provisioningCompleteIntent = getProvisioningCompleteIntent(dpm); 86 if (provisioningCompleteIntent == null) { 87 return; 88 } 89 90 // It maybe the case that mParams is null at this point - we expect this to be the case if 91 // ManagedProvisioning wasn't invoked to perform setup. We'll simply trigger the normal 92 // broadcast so that the installed DPC knows that user-setup completed. Concrete use-case 93 // is a user being setup through DevicePolicyManager.createAndInitializeUser() by the 94 // device-owner, which sets profile-owner and then launches the user. Setup-wizard on the 95 // user runs, and at the end of it's activity flow will trigger the finalization intent, 96 // which then allows us to notify the DPC that profile setup is complete. 97 if (mParams != null && 98 mParams.provisioningAction.equals(ACTION_PROVISION_MANAGED_PROFILE)) { 99 // For the managed profile owner case, we need to send the provisioning complete 100 // intent to the mdm. Once it has been received, we'll send 101 // ACTION_MANAGED_PROFILE_PROVISIONED in the parent. 102 finalizeManagedProfileOwnerProvisioning(provisioningCompleteIntent); 103 } else { 104 // For managed user and device owner, we just need to send the provisioning complete 105 // intent to the mdm. 106 sendBroadcast(provisioningCompleteIntent); 107 } 108 109 Utils.markUserProvisioningStateFinalized(this, mParams); 110 } 111 112 private void finalizeManagedProfileOwnerProvisioning(Intent provisioningCompleteIntent) { 113 UserHandle managedUserHandle = Utils.getManagedProfile(this); 114 if (managedUserHandle == null) { 115 ProvisionLogger.loge("Failed to retrieve the userHandle of the managed profile."); 116 return; 117 } 118 BroadcastReceiver mdmReceivedSuccessReceiver = new MdmReceivedSuccessReceiver( 119 mParams.accountToMigrate, mParams.deviceAdminPackageName); 120 121 sendOrderedBroadcastAsUser(provisioningCompleteIntent, managedUserHandle, null, 122 mdmReceivedSuccessReceiver, null, Activity.RESULT_OK, null, null); 123 } 124 125 private Intent getProvisioningCompleteIntent(DevicePolicyManager dpm) { 126 Intent intent = new Intent(ACTION_PROFILE_PROVISIONING_COMPLETE); 127 try { 128 // mParams maybe null for cases where DevicePolicyManager has directly set DO or PO and 129 // ManagedProvisioning wasn't involved. In that case, we may still want to use the same 130 // mechanism after setup-wizard to invoke the MDM, hence why we fallback to inspecting 131 // device and profile-owner. 132 if (mParams != null) { 133 intent.setComponent(mParams.inferDeviceAdminComponentName(this)); 134 } else if (dpm.getDeviceOwner() != null) { 135 intent.setComponent(Utils.findDeviceAdmin(dpm.getDeviceOwner(), 136 null /* mdmComponentName */, this)); 137 } else if (dpm.getProfileOwner() != null) { 138 intent.setComponent(Utils.findDeviceAdmin(dpm.getProfileOwner().getPackageName(), 139 null /* mdmComponentName */, this)); 140 } else { 141 return null; 142 } 143 } catch (Utils.IllegalProvisioningArgumentException e) { 144 ProvisionLogger.loge("Failed to infer the device admin component name", e); 145 return null; 146 } 147 intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES | Intent.FLAG_RECEIVER_FOREGROUND); 148 if (mParams != null && mParams.adminExtrasBundle != null) { 149 intent.putExtra(EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE, mParams.adminExtrasBundle); 150 } 151 return intent; 152 } 153 154 private ProvisioningParams loadProvisioningParamsAndClearIntentStore() { 155 IntentStore intentStore = getIntentStore(this); 156 Intent intent = intentStore.load(); 157 if (intent == null) { 158 ProvisionLogger.loge("Fail to retrieve ProvisioningParams from intent store."); 159 return null; 160 } 161 intentStore.clear(); 162 163 try { 164 return (new MessageParser()).parseNonNfcIntent(intent, this, true /* trusted */); 165 } catch (IllegalProvisioningArgumentException e) { 166 ProvisionLogger.loge("Failed to parse provisioning intent", e); 167 } 168 return null; 169 } 170 171 private static IntentStore getIntentStore(Context context) { 172 return new IntentStore(context, INTENT_STORE_NAME); 173 } 174} 175