Home | History | Annotate | Download | only in admin
      1 /*
      2  * Copyright (C) 2010 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 android.app.admin;
     18 
     19 import android.accounts.AccountManager;
     20 import android.annotation.SdkConstant;
     21 import android.annotation.SdkConstant.SdkConstantType;
     22 import android.app.Service;
     23 import android.content.BroadcastReceiver;
     24 import android.content.ComponentName;
     25 import android.content.Context;
     26 import android.content.Intent;
     27 import android.os.Bundle;
     28 
     29 /**
     30  * Base class for implementing a device administration component.  This
     31  * class provides a convenience for interpreting the raw intent actions
     32  * that are sent by the system.
     33  *
     34  * <p>The callback methods, like the base
     35  * {@link BroadcastReceiver#onReceive(Context, Intent) BroadcastReceiver.onReceive()}
     36  * method, happen on the main thread of the process.  Thus long running
     37  * operations must be done on another thread.  Note that because a receiver
     38  * is done once returning from its receive function, such long-running operations
     39  * should probably be done in a {@link Service}.
     40  *
     41  * <p>When publishing your DeviceAdmin subclass as a receiver, it must
     42  * handle {@link #ACTION_DEVICE_ADMIN_ENABLED} and require the
     43  * {@link android.Manifest.permission#BIND_DEVICE_ADMIN} permission.  A typical
     44  * manifest entry would look like:</p>
     45  *
     46  * {@sample development/samples/ApiDemos/AndroidManifest.xml device_admin_declaration}
     47  *
     48  * <p>The meta-data referenced here provides addition information specific
     49  * to the device administrator, as parsed by the {@link DeviceAdminInfo} class.
     50  * A typical file would be:</p>
     51  *
     52  * {@sample development/samples/ApiDemos/res/xml/device_admin_sample.xml meta_data}
     53  *
     54  * <div class="special reference">
     55  * <h3>Developer Guides</h3>
     56  * <p>For more information about device administration, read the
     57  * <a href="{@docRoot}guide/topics/admin/device-admin.html">Device Administration</a>
     58  * developer guide.</p>
     59  * </div>
     60  */
     61 public class DeviceAdminReceiver extends BroadcastReceiver {
     62     private static String TAG = "DevicePolicy";
     63     private static boolean localLOGV = false;
     64 
     65     /**
     66      * This is the primary action that a device administrator must implement to be
     67      * allowed to manage a device.  This will be set to the receiver
     68      * when the user enables it for administration.  You will generally
     69      * handle this in {@link DeviceAdminReceiver#onEnabled(Context, Intent)}.  To be
     70      * supported, the receiver must also require the
     71      * {@link android.Manifest.permission#BIND_DEVICE_ADMIN} permission so
     72      * that other applications can not abuse it.
     73      */
     74     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     75     public static final String ACTION_DEVICE_ADMIN_ENABLED
     76             = "android.app.action.DEVICE_ADMIN_ENABLED";
     77 
     78     /**
     79      * Action sent to a device administrator when the user has requested to
     80      * disable it, but before this has actually been done.  This gives you
     81      * a chance to supply a message to the user about the impact of
     82      * disabling your admin, by setting the extra field
     83      * {@link #EXTRA_DISABLE_WARNING} in the result Intent.  If not set,
     84      * no warning will be displayed.  If set, the given text will be shown
     85      * to the user before they disable your admin.
     86      */
     87     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     88     public static final String ACTION_DEVICE_ADMIN_DISABLE_REQUESTED
     89             = "android.app.action.DEVICE_ADMIN_DISABLE_REQUESTED";
     90 
     91     /**
     92      * A CharSequence that can be shown to the user informing them of the
     93      * impact of disabling your admin.
     94      *
     95      * @see #ACTION_DEVICE_ADMIN_DISABLE_REQUESTED
     96      */
     97     public static final String EXTRA_DISABLE_WARNING = "android.app.extra.DISABLE_WARNING";
     98 
     99     /**
    100      * Action sent to a device administrator when the user has disabled
    101      * it.  Upon return, the application no longer has access to the
    102      * protected device policy manager APIs.  You will generally
    103      * handle this in {@link DeviceAdminReceiver#onDisabled(Context, Intent)}.  Note
    104      * that this action will be
    105      * sent the receiver regardless of whether it is explicitly listed in
    106      * its intent filter.
    107      */
    108     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    109     public static final String ACTION_DEVICE_ADMIN_DISABLED
    110             = "android.app.action.DEVICE_ADMIN_DISABLED";
    111 
    112     /**
    113      * Action sent to a device administrator when the user has changed the
    114      * password of their device.  You can at this point check the characteristics
    115      * of the new password with {@link DevicePolicyManager#isActivePasswordSufficient()
    116      * DevicePolicyManager.isActivePasswordSufficient()}.
    117      * You will generally
    118      * handle this in {@link DeviceAdminReceiver#onPasswordChanged}.
    119      *
    120      * <p>The calling device admin must have requested
    121      * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to receive
    122      * this broadcast.
    123      */
    124     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    125     public static final String ACTION_PASSWORD_CHANGED
    126             = "android.app.action.ACTION_PASSWORD_CHANGED";
    127 
    128     /**
    129      * Action sent to a device administrator when the user has failed at
    130      * attempted to enter the password.  You can at this point check the
    131      * number of failed password attempts there have been with
    132      * {@link DevicePolicyManager#getCurrentFailedPasswordAttempts
    133      * DevicePolicyManager.getCurrentFailedPasswordAttempts()}.  You will generally
    134      * handle this in {@link DeviceAdminReceiver#onPasswordFailed}.
    135      *
    136      * <p>The calling device admin must have requested
    137      * {@link DeviceAdminInfo#USES_POLICY_WATCH_LOGIN} to receive
    138      * this broadcast.
    139      */
    140     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    141     public static final String ACTION_PASSWORD_FAILED
    142             = "android.app.action.ACTION_PASSWORD_FAILED";
    143 
    144     /**
    145      * Action sent to a device administrator when the user has successfully
    146      * entered their password, after failing one or more times.
    147      *
    148      * <p>The calling device admin must have requested
    149      * {@link DeviceAdminInfo#USES_POLICY_WATCH_LOGIN} to receive
    150      * this broadcast.
    151      */
    152     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    153     public static final String ACTION_PASSWORD_SUCCEEDED
    154             = "android.app.action.ACTION_PASSWORD_SUCCEEDED";
    155 
    156     /**
    157      * Action periodically sent to a device administrator when the device password
    158      * is expiring.
    159      *
    160      * <p>The calling device admin must have requested
    161      * {@link DeviceAdminInfo#USES_POLICY_EXPIRE_PASSWORD} to receive
    162      * this broadcast.
    163      */
    164     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    165     public static final String ACTION_PASSWORD_EXPIRING
    166             = "android.app.action.ACTION_PASSWORD_EXPIRING";
    167 
    168     /**
    169      * Action sent to a device administrator to notify that the device is entering
    170      * lock task mode from an authorized package.  The extra {@link #EXTRA_LOCK_TASK_PACKAGE}
    171      * will describe the authorized package using lock task mode.
    172      *
    173      * <p>The calling device admin must be the device owner or profile
    174      * owner to receive this broadcast.
    175      *
    176      * @see DevicePolicyManager#isLockTaskPermitted(String)
    177      */
    178     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    179     public static final String ACTION_LOCK_TASK_ENTERING
    180             = "android.app.action.LOCK_TASK_ENTERING";
    181 
    182     /**
    183      * Action sent to a device administrator to notify that the device is exiting
    184      * lock task mode from an authorized package.
    185      *
    186      * <p>The calling device admin must be the device owner or profile
    187      * owner to receive this broadcast.
    188      *
    189      * @see DevicePolicyManager#isLockTaskPermitted(String)
    190      */
    191     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    192     public static final String ACTION_LOCK_TASK_EXITING
    193             = "android.app.action.LOCK_TASK_EXITING";
    194 
    195     /**
    196      * A string containing the name of the package entering lock task mode.
    197      *
    198      * @see #ACTION_LOCK_TASK_ENTERING
    199      */
    200     public static final String EXTRA_LOCK_TASK_PACKAGE =
    201             "android.app.extra.LOCK_TASK_PACKAGE";
    202 
    203     /**
    204      * Broadcast Action: This broadcast is sent to indicate that provisioning of a managed profile
    205      * or managed device has completed successfully.
    206      *
    207      * <p>The broadcast is limited to the profile that will be managed by the application that
    208      * requested provisioning. In the device owner case the profile is the primary user.
    209      * The broadcast will also be limited to the {@link DeviceAdminReceiver} component
    210      * specified in the original intent or NFC bump that started the provisioning process
    211      * (@see DevicePolicyManager#ACTION_PROVISION_MANAGED_PROFILE).
    212      *
    213      * <p>A device admin application which listens to this intent can find out if the device was
    214      * provisioned for the device owner or profile owner case by calling respectively
    215      * {@link android.app.admin.DevicePolicyManager#isDeviceOwnerApp} and
    216      * {@link android.app.admin.DevicePolicyManager#isProfileOwnerApp}.
    217      *
    218      * <p>Input: Nothing.</p>
    219      * <p>Output: Nothing</p>
    220      */
    221     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    222     public static final String ACTION_PROFILE_PROVISIONING_COMPLETE =
    223             "android.app.action.PROFILE_PROVISIONING_COMPLETE";
    224 
    225     /**
    226      * Name under which a DevicePolicy component publishes information
    227      * about itself.  This meta-data must reference an XML resource containing
    228      * a device-admin tag.  XXX TO DO: describe syntax.
    229      */
    230     public static final String DEVICE_ADMIN_META_DATA = "android.app.device_admin";
    231 
    232     private DevicePolicyManager mManager;
    233     private ComponentName mWho;
    234 
    235     /**
    236      * Retrieve the DevicePolicyManager interface for this administrator to work
    237      * with the system.
    238      */
    239     public DevicePolicyManager getManager(Context context) {
    240         if (mManager != null) {
    241             return mManager;
    242         }
    243         mManager = (DevicePolicyManager)context.getSystemService(
    244                 Context.DEVICE_POLICY_SERVICE);
    245         return mManager;
    246     }
    247 
    248     /**
    249      * Retrieve the ComponentName describing who this device administrator is, for
    250      * use in {@link DevicePolicyManager} APIs that require the administrator to
    251      * identify itself.
    252      */
    253     public ComponentName getWho(Context context) {
    254         if (mWho != null) {
    255             return mWho;
    256         }
    257         mWho = new ComponentName(context, getClass());
    258         return mWho;
    259     }
    260 
    261     /**
    262      * Called after the administrator is first enabled, as a result of
    263      * receiving {@link #ACTION_DEVICE_ADMIN_ENABLED}.  At this point you
    264      * can use {@link DevicePolicyManager} to set your desired policies.
    265      *
    266      * <p> If the admin is activated by a device owner, then the intent
    267      * may contain private extras that are relevant to user setup.
    268      * {@see DevicePolicyManager#createAndInitializeUser(ComponentName, String, String,
    269      *      ComponentName, Intent)}
    270      *
    271      * @param context The running context as per {@link #onReceive}.
    272      * @param intent The received intent as per {@link #onReceive}.
    273      */
    274     public void onEnabled(Context context, Intent intent) {
    275     }
    276 
    277     /**
    278      * Called when the user has asked to disable the administrator, as a result of
    279      * receiving {@link #ACTION_DEVICE_ADMIN_DISABLE_REQUESTED}, giving you
    280      * a chance to present a warning message to them.  The message is returned
    281      * as the result; if null is returned (the default implementation), no
    282      * message will be displayed.
    283      * @param context The running context as per {@link #onReceive}.
    284      * @param intent The received intent as per {@link #onReceive}.
    285      * @return Return the warning message to display to the user before
    286      * being disabled; if null is returned, no message is displayed.
    287      */
    288     public CharSequence onDisableRequested(Context context, Intent intent) {
    289         return null;
    290     }
    291 
    292     /**
    293      * Called prior to the administrator being disabled, as a result of
    294      * receiving {@link #ACTION_DEVICE_ADMIN_DISABLED}.  Upon return, you
    295      * can no longer use the protected parts of the {@link DevicePolicyManager}
    296      * API.
    297      * @param context The running context as per {@link #onReceive}.
    298      * @param intent The received intent as per {@link #onReceive}.
    299      */
    300     public void onDisabled(Context context, Intent intent) {
    301     }
    302 
    303     /**
    304      * Called after the user has changed their password, as a result of
    305      * receiving {@link #ACTION_PASSWORD_CHANGED}.  At this point you
    306      * can use {@link DevicePolicyManager#getCurrentFailedPasswordAttempts()
    307      * DevicePolicyManager.getCurrentFailedPasswordAttempts()}
    308      * to retrieve the active password characteristics.
    309      * @param context The running context as per {@link #onReceive}.
    310      * @param intent The received intent as per {@link #onReceive}.
    311      */
    312     public void onPasswordChanged(Context context, Intent intent) {
    313     }
    314 
    315     /**
    316      * Called after the user has failed at entering their current password, as a result of
    317      * receiving {@link #ACTION_PASSWORD_FAILED}.  At this point you
    318      * can use {@link DevicePolicyManager} to retrieve the number of failed
    319      * password attempts.
    320      * @param context The running context as per {@link #onReceive}.
    321      * @param intent The received intent as per {@link #onReceive}.
    322      */
    323     public void onPasswordFailed(Context context, Intent intent) {
    324     }
    325 
    326     /**
    327      * Called after the user has succeeded at entering their current password,
    328      * as a result of receiving {@link #ACTION_PASSWORD_SUCCEEDED}.  This will
    329      * only be received the first time they succeed after having previously
    330      * failed.
    331      * @param context The running context as per {@link #onReceive}.
    332      * @param intent The received intent as per {@link #onReceive}.
    333      */
    334     public void onPasswordSucceeded(Context context, Intent intent) {
    335     }
    336 
    337     /**
    338      * Called periodically when the password is about to expire or has expired.  It will typically
    339      * be called at these times: on device boot, once per day before the password expires,
    340      * and at the time when the password expires.
    341      *
    342      * <p>If the password is not updated by the user, this method will continue to be called
    343      * once per day until the password is changed or the device admin disables password expiration.
    344      *
    345      * <p>The admin will typically post a notification requesting the user to change their password
    346      * in response to this call. The actual password expiration time can be obtained by calling
    347      * {@link DevicePolicyManager#getPasswordExpiration(ComponentName) }
    348      *
    349      * <p>The admin should be sure to take down any notifications it posted in response to this call
    350      * when it receives {@link DeviceAdminReceiver#onPasswordChanged(Context, Intent) }.
    351      *
    352      * @param context The running context as per {@link #onReceive}.
    353      * @param intent The received intent as per {@link #onReceive}.
    354      */
    355     public void onPasswordExpiring(Context context, Intent intent) {
    356     }
    357 
    358     /**
    359      * Called when provisioning of a managed profile or managed device has completed successfully.
    360      *
    361      * <p> As a prerequisit for the execution of this callback the (@link DeviceAdminReceiver} has
    362      * to declare an intent filter for {@link #ACTION_PROFILE_PROVISIONING_COMPLETE}.
    363      * Its component must also be specified in the {@link DevicePolicyManager#EXTRA_DEVICE_ADMIN}
    364      * of the {@link DevicePolicyManager#ACTION_PROVISION_MANAGED_PROFILE} intent that started the
    365      * managed provisioning.
    366      *
    367      * <p>When provisioning is complete, the managed profile is hidden until the profile owner
    368      * calls {DevicePolicyManager#setProfileEnabled(ComponentName admin)}. Typically a profile
    369      * owner will enable the profile when it has finished any additional setup such as adding an
    370      * account by using the {@link AccountManager} and calling apis to bring the profile into the
    371      * desired state.
    372      *
    373      * <p> Note that provisioning completes without waiting for any server interactions, so the
    374      * profile owner needs to wait for data to be available if required (e.g android device ids or
    375      * other data that is set as a result of server interactions).
    376      *
    377      * @param context The running context as per {@link #onReceive}.
    378      * @param intent The received intent as per {@link #onReceive}.
    379      */
    380     public void onProfileProvisioningComplete(Context context, Intent intent) {
    381     }
    382 
    383     /**
    384      * Called when a device is entering lock task mode by a package authorized
    385      * by {@link DevicePolicyManager#isLockTaskPermitted(String)}
    386      *
    387      * @param context The running context as per {@link #onReceive}.
    388      * @param intent The received intent as per {@link #onReceive}.
    389      * @param pkg If entering, the authorized package using lock task mode, otherwise null.
    390      */
    391     public void onLockTaskModeEntering(Context context, Intent intent, String pkg) {
    392     }
    393 
    394     /**
    395      * Called when a device is exiting lock task mode by a package authorized
    396      * by {@link DevicePolicyManager#isLockTaskPermitted(String)}
    397      *
    398      * @param context The running context as per {@link #onReceive}.
    399      * @param intent The received intent as per {@link #onReceive}.
    400      */
    401     public void onLockTaskModeExiting(Context context, Intent intent) {
    402     }
    403 
    404     /**
    405      * Intercept standard device administrator broadcasts.  Implementations
    406      * should not override this method; it is better to implement the
    407      * convenience callbacks for each action.
    408      */
    409     @Override
    410     public void onReceive(Context context, Intent intent) {
    411         String action = intent.getAction();
    412 
    413         if (ACTION_PASSWORD_CHANGED.equals(action)) {
    414             onPasswordChanged(context, intent);
    415         } else if (ACTION_PASSWORD_FAILED.equals(action)) {
    416             onPasswordFailed(context, intent);
    417         } else if (ACTION_PASSWORD_SUCCEEDED.equals(action)) {
    418             onPasswordSucceeded(context, intent);
    419         } else if (ACTION_DEVICE_ADMIN_ENABLED.equals(action)) {
    420             onEnabled(context, intent);
    421         } else if (ACTION_DEVICE_ADMIN_DISABLE_REQUESTED.equals(action)) {
    422             CharSequence res = onDisableRequested(context, intent);
    423             if (res != null) {
    424                 Bundle extras = getResultExtras(true);
    425                 extras.putCharSequence(EXTRA_DISABLE_WARNING, res);
    426             }
    427         } else if (ACTION_DEVICE_ADMIN_DISABLED.equals(action)) {
    428             onDisabled(context, intent);
    429         } else if (ACTION_PASSWORD_EXPIRING.equals(action)) {
    430             onPasswordExpiring(context, intent);
    431         } else if (ACTION_PROFILE_PROVISIONING_COMPLETE.equals(action)) {
    432             onProfileProvisioningComplete(context, intent);
    433         } else if (ACTION_LOCK_TASK_ENTERING.equals(action)) {
    434             String pkg = intent.getStringExtra(EXTRA_LOCK_TASK_PACKAGE);
    435             onLockTaskModeEntering(context, intent, pkg);
    436         } else if (ACTION_LOCK_TASK_EXITING.equals(action)) {
    437             onLockTaskModeExiting(context, intent);
    438         }
    439     }
    440 }
    441