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 17 package com.android.managedprovisioning; 18 19 import static android.app.admin.DeviceAdminReceiver.ACTION_PROFILE_PROVISIONING_COMPLETE; 20 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_ACCOUNT_TO_MIGRATE; 21 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE; 22 23 import android.accounts.Account; 24 import android.app.Activity; 25 import android.app.admin.DevicePolicyManager; 26 import android.content.BroadcastReceiver; 27 import android.content.ComponentName; 28 import android.content.Context; 29 import android.content.Intent; 30 import android.content.pm.PackageManager; 31 import android.os.AsyncTask; 32 import android.os.Bundle; 33 import android.os.UserHandle; 34 35 import com.android.managedprovisioning.Utils.IllegalProvisioningArgumentException; 36 37 /* 38 * This class is used to make sure that we start the mdm after we shut the Setup wizard down. 39 * The shut down of the Setup wizard is initiated in the DeviceOwnerProvisioningActivity or 40 * ProfileOwnerProvisioningActivity by setting Global.DEVICE_PROVISIONED. This will cause the 41 * Setup wizard to shut down and send a HOME intent. Instead of opening the home screen we want 42 * to open the mdm, so the HOME intent is caught by this activity instead which will send the 43 * ACTION_PROFILE_PROVISIONING_COMPLETE to the mdm, which will then open up. 44 */ 45 46 public class HomeReceiverActivity extends Activity { 47 48 private ProvisioningParams mParams; 49 50 @Override 51 public void onCreate(Bundle savedInstanceState) { 52 super.onCreate(savedInstanceState); 53 try { 54 finalizeProvisioning(); 55 } finally { 56 // Disable the HomeReceiverActivity. Make sure this is always called to prevent an 57 // infinite loop of HomeReceiverActivity capturing HOME intent in case something fails. 58 disableComponent(new ComponentName(this, HomeReceiverActivity.class)); 59 } 60 finish(); 61 } 62 63 private void finalizeProvisioning() { 64 mParams = loadProvisioningParamsFromStore( 65 BootReminder.getProfileOwnerFinalizingIntentStore(this)); 66 if (mParams != null) { 67 // Finalizing provisioning: send complete intent to mdm. 68 finalizeProfileOwnerProvisioning(); 69 return; 70 } 71 mParams = loadProvisioningParamsFromStore( 72 BootReminder.getDeviceOwnerFinalizingIntentStore(this)); 73 if (mParams != null) { 74 finalizeDeviceOwnerProvisioning(); 75 } 76 } 77 78 private void finalizeProfileOwnerProvisioning() { 79 Intent provisioningCompleteIntent = getProvisioningCompleteIntent(); 80 if (provisioningCompleteIntent == null) { 81 return; 82 } 83 84 final UserHandle managedUserHandle = Utils.getManagedProfile(this); 85 if (managedUserHandle == null) { 86 ProvisionLogger.loge("Failed to retrieve the userHandle of the managed profile."); 87 return; 88 } 89 BroadcastReceiver mdmReceivedSuccessReceiver = new MdmReceivedSuccessReceiver( 90 mParams.accountToMigrate, mParams.deviceAdminPackageName); 91 92 sendOrderedBroadcastAsUser(provisioningCompleteIntent, managedUserHandle, null, 93 mdmReceivedSuccessReceiver, null, Activity.RESULT_OK, null, null); 94 } 95 96 private void finalizeDeviceOwnerProvisioning() { 97 Intent provisioningCompleteIntent = getProvisioningCompleteIntent(); 98 if (provisioningCompleteIntent == null) { 99 return; 100 } 101 102 // Disable the Device Initializer component, if it exists, in case it did not do so itself. 103 if(mParams.deviceInitializerComponentName != null) { 104 DevicePolicyManager devicePolicyManager = 105 (DevicePolicyManager) getSystemService(DEVICE_POLICY_SERVICE); 106 devicePolicyManager.removeActiveAdmin(mParams.deviceInitializerComponentName); 107 disableComponent(mParams.deviceInitializerComponentName); 108 } 109 110 sendBroadcast(provisioningCompleteIntent); 111 } 112 113 private Intent getProvisioningCompleteIntent() { 114 Intent intent = new Intent(ACTION_PROFILE_PROVISIONING_COMPLETE); 115 try { 116 intent.setComponent(mParams.inferDeviceAdminComponentName(this)); 117 } catch (Utils.IllegalProvisioningArgumentException e) { 118 ProvisionLogger.loge("Failed to infer the device admin component name", e); 119 return null; 120 } 121 intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES | Intent.FLAG_RECEIVER_FOREGROUND); 122 if (mParams.adminExtrasBundle != null) { 123 intent.putExtra(EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE, mParams.adminExtrasBundle); 124 } 125 return intent; 126 } 127 128 private ProvisioningParams loadProvisioningParamsFromStore(IntentStore store) { 129 Intent intent = store.load(); 130 if (intent == null) { 131 ProvisionLogger.loge("Fail to retrieve ProvisioningParams from intent store."); 132 return null; 133 } 134 store.clear(); 135 ProvisioningParams params = null; 136 try { 137 params = (new MessageParser()).parseNonNfcIntent(intent, true /* trusted */); 138 } catch (IllegalProvisioningArgumentException e) { 139 ProvisionLogger.loge("Failed to parse provisioning intent", e); 140 } 141 return params; 142 } 143 144 private void disableComponent(ComponentName component) { 145 PackageManager pm = getPackageManager(); 146 pm.setComponentEnabledSetting(component, 147 PackageManager.COMPONENT_ENABLED_STATE_DISABLED, 148 PackageManager.DONT_KILL_APP); 149 } 150 } 151