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 package com.android.managedprovisioning; 17 18 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_ACCOUNT_TO_MIGRATE; 19 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE; 20 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME; 21 22 import android.app.Notification; 23 import android.app.NotificationManager; 24 import android.app.PendingIntent; 25 import android.content.BroadcastReceiver; 26 import android.content.ComponentName; 27 import android.content.Context; 28 import android.content.Intent; 29 import android.os.Bundle; 30 31 /** 32 * Class that handles the resuming process that takes place after a reboot for encryption 33 * during the provisioning process. 34 */ 35 public class BootReminder extends BroadcastReceiver { 36 private static final int NOTIFY_ID = 1; 37 38 /* 39 * Profile owner parameters that are stored in the IntentStore for resuming provisioning. 40 */ 41 private static final String PROFILE_OWNER_PREFERENCES_NAME = 42 "profile-owner-provisioning-resume"; 43 44 private static final String[] PROFILE_OWNER_STRING_EXTRAS = { 45 // Key for the device admin package name 46 EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME 47 }; 48 49 private static final String[] PROFILE_OWNER_PERSISTABLE_BUNDLE_EXTRAS = { 50 // Key for the admin extras bundle 51 EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE 52 }; 53 54 private static final String[] PROFILE_OWNER_ACCOUNT_EXTRAS = { 55 // Key for the account extras 56 EXTRA_PROVISIONING_ACCOUNT_TO_MIGRATE 57 }; 58 59 private static final ComponentName PROFILE_OWNER_INTENT_TARGET = 60 ProfileOwnerPreProvisioningActivity.ALIAS_NO_CHECK_CALLER; 61 62 /* 63 * Device owner parameters that are stored in the IntentStore for resuming provisioning. 64 */ 65 private static final String DEVICE_OWNER_PREFERENCES_NAME = 66 "device-owner-provisioning-resume"; 67 68 private static final ComponentName DEVICE_OWNER_INTENT_TARGET = 69 new ComponentName("com.android.managedprovisioning", 70 "com.android.managedprovisioning.DeviceOwnerProvisioningActivity"); 71 72 @Override onReceive(Context context, Intent intent)73 public void onReceive(Context context, Intent intent) { 74 if (android.content.Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) { 75 76 // Resume profile owner provisioning if applicable. 77 IntentStore profileOwnerIntentStore = getProfileOwnerIntentStore(context); 78 final Intent resumeProfileOwnerPrvIntent = profileOwnerIntentStore.load(); 79 if (resumeProfileOwnerPrvIntent != null) { 80 if (EncryptDeviceActivity.isDeviceEncrypted()) { 81 // Show reminder notification and then forget about it for next boot 82 profileOwnerIntentStore.clear(); 83 setNotification(context, resumeProfileOwnerPrvIntent); 84 } 85 } 86 87 // Resume device owner provisioning if applicable. 88 IntentStore deviceOwnerIntentStore = getDeviceOwnerIntentStore(context); 89 Intent resumeDeviceOwnerPrvIntent = deviceOwnerIntentStore.load(); 90 if (resumeDeviceOwnerPrvIntent != null) { 91 deviceOwnerIntentStore.clear(); 92 resumeDeviceOwnerPrvIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 93 context.startActivity(resumeDeviceOwnerPrvIntent); 94 } 95 } 96 } 97 98 /** 99 * Schedule a provisioning reminder notification for the next reboot. 100 * 101 * {@code extras} should be a Bundle containing the 102 * {@link EncryptDeviceActivity.EXTRA_RESUME_TARGET}. 103 * This field has only two supported values {@link EncryptDeviceActivity.TARGET_PROFILE_OWNER} 104 * and {@link EncryptDeviceActivity.TARGET_DEVICE_OWNER} 105 * 106 * <p> In case of TARGET_PROFILE_OWNER {@code extras} should further contain a value for at 107 * least the key: {@link EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME}, a {@link String} which 108 * specifies the package to set as profile owner. 109 * 110 * <p> 111 * See {@link MessageParser} for the TARGET_DEVICE_OWNER case. 112 * </ul> 113 * 114 * <p> These fields will be persisted and restored to the provisioner after rebooting. Any other 115 * key/value pairs will be ignored. 116 */ setProvisioningReminder(Context context, Bundle extras)117 public static void setProvisioningReminder(Context context, Bundle extras) { 118 IntentStore intentStore; 119 String resumeTarget = extras.getString(EncryptDeviceActivity.EXTRA_RESUME_TARGET, null); 120 if (resumeTarget == null) { 121 return; 122 } 123 if (resumeTarget.equals(EncryptDeviceActivity.TARGET_PROFILE_OWNER)) { 124 intentStore = getProfileOwnerIntentStore(context); 125 } else if (resumeTarget.equals(EncryptDeviceActivity.TARGET_DEVICE_OWNER)) { 126 intentStore = getDeviceOwnerIntentStore(context); 127 } else { 128 ProvisionLogger.loge("Unknown resume target for bootreminder."); 129 return; 130 } 131 intentStore.save(extras); 132 } 133 134 /** 135 * Cancel all active provisioning reminders. 136 */ cancelProvisioningReminder(Context context)137 public static void cancelProvisioningReminder(Context context) { 138 getProfileOwnerIntentStore(context).clear(); 139 getDeviceOwnerIntentStore(context).clear(); 140 setNotification(context, null); 141 } 142 getProfileOwnerIntentStore(Context context)143 private static IntentStore getProfileOwnerIntentStore(Context context) { 144 return new IntentStore(context,PROFILE_OWNER_INTENT_TARGET, PROFILE_OWNER_PREFERENCES_NAME) 145 .setStringKeys(PROFILE_OWNER_STRING_EXTRAS) 146 .setPersistableBundleKeys(PROFILE_OWNER_PERSISTABLE_BUNDLE_EXTRAS) 147 .setAccountKeys(PROFILE_OWNER_ACCOUNT_EXTRAS); 148 } 149 getDeviceOwnerIntentStore(Context context)150 private static IntentStore getDeviceOwnerIntentStore(Context context) { 151 return new IntentStore(context, DEVICE_OWNER_INTENT_TARGET, DEVICE_OWNER_PREFERENCES_NAME) 152 .setStringKeys(MessageParser.DEVICE_OWNER_STRING_EXTRAS) 153 .setLongKeys(MessageParser.DEVICE_OWNER_LONG_EXTRAS) 154 .setIntKeys(MessageParser.DEVICE_OWNER_INT_EXTRAS) 155 .setBooleanKeys(MessageParser.DEVICE_OWNER_BOOLEAN_EXTRAS) 156 .setPersistableBundleKeys(MessageParser.DEVICE_OWNER_PERSISTABLE_BUNDLE_EXTRAS); 157 } 158 159 /** Create and show the provisioning reminder notification. */ setNotification(Context context, Intent intent)160 private static void setNotification(Context context, Intent intent) { 161 final NotificationManager notificationManager = (NotificationManager) 162 context.getSystemService(Context.NOTIFICATION_SERVICE); 163 if (intent == null) { 164 notificationManager.cancel(NOTIFY_ID); 165 return; 166 } 167 final PendingIntent resumePendingIntent = PendingIntent.getActivity( 168 context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); 169 final Notification.Builder notify = new Notification.Builder(context) 170 .setContentIntent(resumePendingIntent) 171 .setContentTitle(context.getString(R.string.continue_provisioning_notify_title)) 172 .setContentText(context.getString(R.string.continue_provisioning_notify_text)) 173 .setSmallIcon(com.android.internal.R.drawable.ic_corp_statusbar_icon) 174 .setVisibility(Notification.VISIBILITY_PUBLIC) 175 .setColor(context.getResources().getColor( 176 com.android.internal.R.color.system_notification_accent_color)) 177 .setAutoCancel(true); 178 notificationManager.notify(NOTIFY_ID, notify.build()); 179 } 180 } 181