Robin Lee | 3ab2b57 | 2014-05-06 18:39:07 +0100 | [diff] [blame] | 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 | |
Alexandra Gherghina | 7cca927 | 2014-11-26 20:57:13 +0000 | [diff] [blame] | 18 | import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_ACCOUNT_TO_MIGRATE; |
Sander Alewijnse | f88f709 | 2014-08-20 16:26:09 +0100 | [diff] [blame] | 19 | import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE; |
Nicolas Prevot | 0b44725 | 2015-03-09 14:59:02 +0000 | [diff] [blame] | 20 | import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME; |
Nicolas Prevot | 668d65f | 2015-03-10 17:58:15 +0000 | [diff] [blame] | 21 | import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME; |
Robin Lee | 3ab2b57 | 2014-05-06 18:39:07 +0100 | [diff] [blame] | 22 | |
| 23 | import android.app.Notification; |
| 24 | import android.app.NotificationManager; |
| 25 | import android.app.PendingIntent; |
Robin Lee | 3ab2b57 | 2014-05-06 18:39:07 +0100 | [diff] [blame] | 26 | import android.content.BroadcastReceiver; |
| 27 | import android.content.ComponentName; |
| 28 | import android.content.Context; |
| 29 | import android.content.Intent; |
Robin Lee | 3ab2b57 | 2014-05-06 18:39:07 +0100 | [diff] [blame] | 30 | import android.os.Bundle; |
| 31 | |
| 32 | /** |
Rubin Xu | 292e9a3 | 2015-03-20 17:02:38 +0000 | [diff] [blame] | 33 | * Class that handles the resuming process that takes place after a reboot during the provisioning |
| 34 | * process. The reboot could be an unexpected reboot or a reboot during the encryption process. |
Robin Lee | 3ab2b57 | 2014-05-06 18:39:07 +0100 | [diff] [blame] | 35 | */ |
| 36 | public class BootReminder extends BroadcastReceiver { |
| 37 | private static final int NOTIFY_ID = 1; |
| 38 | |
Sander Alewijnse | 28bffd6 | 2014-06-05 10:54:26 +0100 | [diff] [blame] | 39 | /* |
| 40 | * Profile owner parameters that are stored in the IntentStore for resuming provisioning. |
| 41 | */ |
| 42 | private static final String PROFILE_OWNER_PREFERENCES_NAME = |
| 43 | "profile-owner-provisioning-resume"; |
| 44 | |
Nicolas Prevot | 668d65f | 2015-03-10 17:58:15 +0000 | [diff] [blame] | 45 | private static final String[] PROFILE_OWNER_STRING_EXTRAS = { |
| 46 | // Key for the device admin package name |
| 47 | EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME |
| 48 | }; |
| 49 | |
Nicolas Prevot | 0b44725 | 2015-03-09 14:59:02 +0000 | [diff] [blame] | 50 | private static final String[] PROFILE_OWNER_COMPONENT_NAME_EXTRAS = { |
| 51 | // Key for the device admin component name |
| 52 | EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME |
Sander Alewijnse | 28bffd6 | 2014-06-05 10:54:26 +0100 | [diff] [blame] | 53 | }; |
| 54 | |
Sander Alewijnse | f88f709 | 2014-08-20 16:26:09 +0100 | [diff] [blame] | 55 | private static final String[] PROFILE_OWNER_PERSISTABLE_BUNDLE_EXTRAS = { |
| 56 | // Key for the admin extras bundle |
| 57 | EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE |
| 58 | }; |
| 59 | |
Alexandra Gherghina | 7cca927 | 2014-11-26 20:57:13 +0000 | [diff] [blame] | 60 | private static final String[] PROFILE_OWNER_ACCOUNT_EXTRAS = { |
| 61 | // Key for the account extras |
| 62 | EXTRA_PROVISIONING_ACCOUNT_TO_MIGRATE |
| 63 | }; |
| 64 | |
Sander Alewijnse | 28bffd6 | 2014-06-05 10:54:26 +0100 | [diff] [blame] | 65 | private static final ComponentName PROFILE_OWNER_INTENT_TARGET = |
Sander Alewijnse | 606780d | 2014-10-29 10:51:39 +0000 | [diff] [blame] | 66 | ProfileOwnerPreProvisioningActivity.ALIAS_NO_CHECK_CALLER; |
Sander Alewijnse | 28bffd6 | 2014-06-05 10:54:26 +0100 | [diff] [blame] | 67 | |
| 68 | /* |
Rubin Xu | 292e9a3 | 2015-03-20 17:02:38 +0000 | [diff] [blame] | 69 | * Device owner parameters that are stored in the IntentStore for resuming provisioning after |
| 70 | * encryption. |
Sander Alewijnse | 28bffd6 | 2014-06-05 10:54:26 +0100 | [diff] [blame] | 71 | */ |
Rubin Xu | 292e9a3 | 2015-03-20 17:02:38 +0000 | [diff] [blame] | 72 | private static final String DEVICE_OWNER_ENCRYPTION_PREFERENCES_NAME = |
| 73 | "device-owner-encryption-resume"; |
| 74 | |
| 75 | // Device owner parameter stored for resuming provisioning after unexpected device reboot during |
| 76 | // finalizing stage. |
| 77 | private static final String DEVICE_OWNER_FINALIZING_PREFERENCES_NAME = |
| 78 | "device-owner-finalizing-resume"; |
Sander Alewijnse | 28bffd6 | 2014-06-05 10:54:26 +0100 | [diff] [blame] | 79 | |
Sander Alewijnse | 28bffd6 | 2014-06-05 10:54:26 +0100 | [diff] [blame] | 80 | private static final ComponentName DEVICE_OWNER_INTENT_TARGET = |
| 81 | new ComponentName("com.android.managedprovisioning", |
| 82 | "com.android.managedprovisioning.DeviceOwnerProvisioningActivity"); |
Robin Lee | 3ab2b57 | 2014-05-06 18:39:07 +0100 | [diff] [blame] | 83 | |
Rubin Xu | 292e9a3 | 2015-03-20 17:02:38 +0000 | [diff] [blame] | 84 | private static final ComponentName HOME_RECEIVER_INTENT_TARGET = |
| 85 | new ComponentName("com.android.managedprovisioning", |
| 86 | "com.android.managedprovisioning.HomeReceiverActivity"); |
| 87 | |
Robin Lee | 3ab2b57 | 2014-05-06 18:39:07 +0100 | [diff] [blame] | 88 | @Override |
| 89 | public void onReceive(Context context, Intent intent) { |
| 90 | if (android.content.Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) { |
Robin Lee | 3ab2b57 | 2014-05-06 18:39:07 +0100 | [diff] [blame] | 91 | |
Sander Alewijnse | 28bffd6 | 2014-06-05 10:54:26 +0100 | [diff] [blame] | 92 | // Resume profile owner provisioning if applicable. |
| 93 | IntentStore profileOwnerIntentStore = getProfileOwnerIntentStore(context); |
| 94 | final Intent resumeProfileOwnerPrvIntent = profileOwnerIntentStore.load(); |
Robin Lee | 4af4ed0 | 2014-08-04 12:29:31 +0100 | [diff] [blame] | 95 | if (resumeProfileOwnerPrvIntent != null) { |
Robin Lee | 7691d19 | 2014-08-29 21:29:38 +0100 | [diff] [blame] | 96 | if (EncryptDeviceActivity.isDeviceEncrypted()) { |
| 97 | // Show reminder notification and then forget about it for next boot |
| 98 | profileOwnerIntentStore.clear(); |
| 99 | setNotification(context, resumeProfileOwnerPrvIntent); |
| 100 | } |
Sander Alewijnse | 28bffd6 | 2014-06-05 10:54:26 +0100 | [diff] [blame] | 101 | } |
| 102 | |
Rubin Xu | 292e9a3 | 2015-03-20 17:02:38 +0000 | [diff] [blame] | 103 | // Resume device owner provisioning after encryption if applicable. |
| 104 | IntentStore deviceOwnerIntentStore = getDeviceOwnerEncryptionResumptionIntentStore(context); |
Sander Alewijnse | 28bffd6 | 2014-06-05 10:54:26 +0100 | [diff] [blame] | 105 | Intent resumeDeviceOwnerPrvIntent = deviceOwnerIntentStore.load(); |
| 106 | if (resumeDeviceOwnerPrvIntent != null) { |
| 107 | deviceOwnerIntentStore.clear(); |
| 108 | resumeDeviceOwnerPrvIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); |
| 109 | context.startActivity(resumeDeviceOwnerPrvIntent); |
Robin Lee | 3ab2b57 | 2014-05-06 18:39:07 +0100 | [diff] [blame] | 110 | } |
| 111 | } |
| 112 | } |
| 113 | |
| 114 | /** |
| 115 | * Schedule a provisioning reminder notification for the next reboot. |
| 116 | * |
Sander Alewijnse | 28bffd6 | 2014-06-05 10:54:26 +0100 | [diff] [blame] | 117 | * {@code extras} should be a Bundle containing the |
| 118 | * {@link EncryptDeviceActivity.EXTRA_RESUME_TARGET}. |
Jessica Hummel | 2e9cec6 | 2014-06-20 11:50:01 +0100 | [diff] [blame] | 119 | * This field has only two supported values {@link EncryptDeviceActivity.TARGET_PROFILE_OWNER} |
| 120 | * and {@link EncryptDeviceActivity.TARGET_DEVICE_OWNER} |
Sander Alewijnse | 28bffd6 | 2014-06-05 10:54:26 +0100 | [diff] [blame] | 121 | * |
Jessica Hummel | 2e9cec6 | 2014-06-20 11:50:01 +0100 | [diff] [blame] | 122 | * <p> In case of TARGET_PROFILE_OWNER {@code extras} should further contain a value for at |
Nicolas Prevot | 0b44725 | 2015-03-09 14:59:02 +0000 | [diff] [blame] | 123 | * least the key: {@link EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME}, a {@link String} |
| 124 | * which, when unflattened to a componentName, specifies the component to set as profile owner. |
Robin Lee | 3ab2b57 | 2014-05-06 18:39:07 +0100 | [diff] [blame] | 125 | * |
Sander Alewijnse | 56f7157 | 2014-06-23 16:21:33 +0100 | [diff] [blame] | 126 | * <p> |
Sander Alewijnse | d8dcb1f | 2014-07-24 15:24:50 +0100 | [diff] [blame] | 127 | * See {@link MessageParser} for the TARGET_DEVICE_OWNER case. |
Sander Alewijnse | 56f7157 | 2014-06-23 16:21:33 +0100 | [diff] [blame] | 128 | * </ul> |
Sander Alewijnse | 28bffd6 | 2014-06-05 10:54:26 +0100 | [diff] [blame] | 129 | * |
Jessica Hummel | 2e9cec6 | 2014-06-20 11:50:01 +0100 | [diff] [blame] | 130 | * <p> These fields will be persisted and restored to the provisioner after rebooting. Any other |
| 131 | * key/value pairs will be ignored. |
Robin Lee | 3ab2b57 | 2014-05-06 18:39:07 +0100 | [diff] [blame] | 132 | */ |
| 133 | public static void setProvisioningReminder(Context context, Bundle extras) { |
Sander Alewijnse | 28bffd6 | 2014-06-05 10:54:26 +0100 | [diff] [blame] | 134 | IntentStore intentStore; |
| 135 | String resumeTarget = extras.getString(EncryptDeviceActivity.EXTRA_RESUME_TARGET, null); |
| 136 | if (resumeTarget == null) { |
Sander Alewijnse | 28bffd6 | 2014-06-05 10:54:26 +0100 | [diff] [blame] | 137 | return; |
| 138 | } |
| 139 | if (resumeTarget.equals(EncryptDeviceActivity.TARGET_PROFILE_OWNER)) { |
| 140 | intentStore = getProfileOwnerIntentStore(context); |
| 141 | } else if (resumeTarget.equals(EncryptDeviceActivity.TARGET_DEVICE_OWNER)) { |
Rubin Xu | 292e9a3 | 2015-03-20 17:02:38 +0000 | [diff] [blame] | 142 | intentStore = getDeviceOwnerEncryptionResumptionIntentStore(context); |
Sander Alewijnse | 28bffd6 | 2014-06-05 10:54:26 +0100 | [diff] [blame] | 143 | } else { |
| 144 | ProvisionLogger.loge("Unknown resume target for bootreminder."); |
| 145 | return; |
| 146 | } |
| 147 | intentStore.save(extras); |
Robin Lee | 3ab2b57 | 2014-05-06 18:39:07 +0100 | [diff] [blame] | 148 | } |
| 149 | |
Robin Lee | 563ea17 | 2014-06-20 18:55:31 +0100 | [diff] [blame] | 150 | /** |
| 151 | * Cancel all active provisioning reminders. |
| 152 | */ |
| 153 | public static void cancelProvisioningReminder(Context context) { |
| 154 | getProfileOwnerIntentStore(context).clear(); |
Rubin Xu | 292e9a3 | 2015-03-20 17:02:38 +0000 | [diff] [blame] | 155 | getDeviceOwnerEncryptionResumptionIntentStore(context).clear(); |
Robin Lee | 563ea17 | 2014-06-20 18:55:31 +0100 | [diff] [blame] | 156 | setNotification(context, null); |
| 157 | } |
| 158 | |
Sander Alewijnse | 28bffd6 | 2014-06-05 10:54:26 +0100 | [diff] [blame] | 159 | private static IntentStore getProfileOwnerIntentStore(Context context) { |
Sander Alewijnse | f88f709 | 2014-08-20 16:26:09 +0100 | [diff] [blame] | 160 | return new IntentStore(context,PROFILE_OWNER_INTENT_TARGET, PROFILE_OWNER_PREFERENCES_NAME) |
Nicolas Prevot | 0b44725 | 2015-03-09 14:59:02 +0000 | [diff] [blame] | 161 | .setComponentNameKeys(PROFILE_OWNER_COMPONENT_NAME_EXTRAS) |
Nicolas Prevot | 668d65f | 2015-03-10 17:58:15 +0000 | [diff] [blame] | 162 | .setStringKeys(PROFILE_OWNER_STRING_EXTRAS) |
Alexandra Gherghina | 7cca927 | 2014-11-26 20:57:13 +0000 | [diff] [blame] | 163 | .setPersistableBundleKeys(PROFILE_OWNER_PERSISTABLE_BUNDLE_EXTRAS) |
| 164 | .setAccountKeys(PROFILE_OWNER_ACCOUNT_EXTRAS); |
Sander Alewijnse | 28bffd6 | 2014-06-05 10:54:26 +0100 | [diff] [blame] | 165 | } |
Robin Lee | 3ab2b57 | 2014-05-06 18:39:07 +0100 | [diff] [blame] | 166 | |
Rubin Xu | 292e9a3 | 2015-03-20 17:02:38 +0000 | [diff] [blame] | 167 | private static IntentStore getDeviceOwnerIntentStore(Context context, |
| 168 | ComponentName intentTarget, String storeName) { |
| 169 | return new IntentStore(context, intentTarget, storeName) |
Nicolas Prevot | 0b44725 | 2015-03-09 14:59:02 +0000 | [diff] [blame] | 170 | .setComponentNameKeys(MessageParser.DEVICE_OWNER_COMPONENT_NAME_EXTRAS) |
Sander Alewijnse | f88f709 | 2014-08-20 16:26:09 +0100 | [diff] [blame] | 171 | .setStringKeys(MessageParser.DEVICE_OWNER_STRING_EXTRAS) |
| 172 | .setLongKeys(MessageParser.DEVICE_OWNER_LONG_EXTRAS) |
| 173 | .setIntKeys(MessageParser.DEVICE_OWNER_INT_EXTRAS) |
| 174 | .setBooleanKeys(MessageParser.DEVICE_OWNER_BOOLEAN_EXTRAS) |
| 175 | .setPersistableBundleKeys(MessageParser.DEVICE_OWNER_PERSISTABLE_BUNDLE_EXTRAS); |
Robin Lee | 3ab2b57 | 2014-05-06 18:39:07 +0100 | [diff] [blame] | 176 | } |
| 177 | |
Rubin Xu | 292e9a3 | 2015-03-20 17:02:38 +0000 | [diff] [blame] | 178 | private static IntentStore getDeviceOwnerEncryptionResumptionIntentStore(Context context) { |
| 179 | return getDeviceOwnerIntentStore(context, DEVICE_OWNER_INTENT_TARGET, |
| 180 | DEVICE_OWNER_ENCRYPTION_PREFERENCES_NAME); |
| 181 | } |
| 182 | |
| 183 | protected static IntentStore getDeviceOwnerFinalizingIntentStore(Context context) { |
| 184 | return getDeviceOwnerIntentStore(context, HOME_RECEIVER_INTENT_TARGET, |
| 185 | DEVICE_OWNER_FINALIZING_PREFERENCES_NAME); |
| 186 | } |
| 187 | |
Robin Lee | 3ab2b57 | 2014-05-06 18:39:07 +0100 | [diff] [blame] | 188 | /** Create and show the provisioning reminder notification. */ |
| 189 | private static void setNotification(Context context, Intent intent) { |
| 190 | final NotificationManager notificationManager = (NotificationManager) |
| 191 | context.getSystemService(Context.NOTIFICATION_SERVICE); |
Robin Lee | 563ea17 | 2014-06-20 18:55:31 +0100 | [diff] [blame] | 192 | if (intent == null) { |
| 193 | notificationManager.cancel(NOTIFY_ID); |
| 194 | return; |
| 195 | } |
Robin Lee | 3ab2b57 | 2014-05-06 18:39:07 +0100 | [diff] [blame] | 196 | final PendingIntent resumePendingIntent = PendingIntent.getActivity( |
| 197 | context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); |
| 198 | final Notification.Builder notify = new Notification.Builder(context) |
| 199 | .setContentIntent(resumePendingIntent) |
| 200 | .setContentTitle(context.getString(R.string.continue_provisioning_notify_title)) |
| 201 | .setContentText(context.getString(R.string.continue_provisioning_notify_text)) |
Alexandra Gherghina | dd5bb0b | 2014-09-18 16:19:15 +0100 | [diff] [blame] | 202 | .setSmallIcon(com.android.internal.R.drawable.ic_corp_statusbar_icon) |
Robin Lee | 4af4ed0 | 2014-08-04 12:29:31 +0100 | [diff] [blame] | 203 | .setVisibility(Notification.VISIBILITY_PUBLIC) |
Selim Cinek | ee3ce60 | 2014-08-27 16:59:20 +0200 | [diff] [blame] | 204 | .setColor(context.getResources().getColor( |
| 205 | com.android.internal.R.color.system_notification_accent_color)) |
Robin Lee | 3ab2b57 | 2014-05-06 18:39:07 +0100 | [diff] [blame] | 206 | .setAutoCancel(true); |
Robin Lee | 3ab2b57 | 2014-05-06 18:39:07 +0100 | [diff] [blame] | 207 | notificationManager.notify(NOTIFY_ID, notify.build()); |
| 208 | } |
| 209 | } |