Home | History | Annotate | Download | only in managedprovisioning
      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
     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      */
    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      */
    137     public static void cancelProvisioningReminder(Context context) {
    138         getProfileOwnerIntentStore(context).clear();
    139         getDeviceOwnerIntentStore(context).clear();
    140         setNotification(context, null);
    141     }
    142 
    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 
    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. */
    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