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      * @see DevicePolicyManager#isLockTaskPermitted(String)
    174      *
    175      * <p>The calling device admin must be the device owner or profile
    176      * owner to receive this broadcast.
    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      * @see DevicePolicyManager#isLockTaskPermitted(String)
    187      *
    188      * <p>The calling device admin must be the device owner or profile
    189      * owner to receive this broadcast.
    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 boolean describing whether the device is currently entering or exiting
    197      * lock task mode.
    198      *
    199      * @see #ACTION_LOCK_TASK_CHANGED
    200      */
    201     public static final String EXTRA_LOCK_TASK_PACKAGE =
    202             "android.app.extra.LOCK_TASK_PACKAGE";
    203 
    204     /**
    205      * Broadcast Action: This broadcast is sent to indicate that provisioning of a managed profile
    206      * or managed device has completed successfully.
    207      *
    208      * <p>The broadcast is limited to the profile that will be managed by the application that
    209      * requested provisioning. In the device owner case the profile is the primary user.
    210      * The broadcast will also be limited to the {@link DeviceAdminReceiver} component
    211      * specified in the original intent or NFC bump that started the provisioning process
    212      * (@see DevicePolicyManager#ACTION_PROVISION_MANAGED_PROFILE).
    213      *
    214      * <p>A device admin application which listens to this intent can find out if the device was
    215      * provisioned for the device owner or profile owner case by calling respectively
    216      * {@link android.app.admin.DevicePolicyManager#isDeviceOwnerApp} and
    217      * {@link android.app.admin.DevicePolicyManager#isProfileOwnerApp}.
    218      *
    219      * <p>Input: Nothing.</p>
    220      * <p>Output: Nothing</p>
    221      */
    222     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    223     public static final String ACTION_PROFILE_PROVISIONING_COMPLETE =
    224             "android.app.action.PROFILE_PROVISIONING_COMPLETE";
    225 
    226     /**
    227      * Name under which a DevicePolicy component publishes information
    228      * about itself.  This meta-data must reference an XML resource containing
    229      * a device-admin tag.  XXX TO DO: describe syntax.
    230      */
    231     public static final String DEVICE_ADMIN_META_DATA = "android.app.device_admin";
    232 
    233     private DevicePolicyManager mManager;
    234     private ComponentName mWho;
    235 
    236     /**
    237      * Retrieve the DevicePolicyManager interface for this administrator to work
    238      * with the system.
    239      */
    240     public DevicePolicyManager getManager(Context context) {
    241         if (mManager != null) {
    242             return mManager;
    243         }
    244         mManager = (DevicePolicyManager)context.getSystemService(
    245                 Context.DEVICE_POLICY_SERVICE);
    246         return mManager;
    247     }
    248 
    249     /**
    250      * Retrieve the ComponentName describing who this device administrator is, for
    251      * use in {@link DevicePolicyManager} APIs that require the administrator to
    252      * identify itself.
    253      */
    254     public ComponentName getWho(Context context) {
    255         if (mWho != null) {
    256             return mWho;
    257         }
    258         mWho = new ComponentName(context, getClass());
    259         return mWho;
    260     }
    261 
    262     /**
    263      * Called after the administrator is first enabled, as a result of
    264      * receiving {@link #ACTION_DEVICE_ADMIN_ENABLED}.  At this point you
    265      * can use {@link DevicePolicyManager} to set your desired policies.
    266      *
    267      * <p> If the admin is activated by a device owner, then the intent
    268      * may contain private extras that are relevant to user setup.
    269      * {@see DevicePolicyManager#createAndInitializeUser(ComponentName, String, String,
    270      *      ComponentName, Intent)}
    271      *
    272      * @param context The running context as per {@link #onReceive}.
    273      * @param intent The received intent as per {@link #onReceive}.
    274      */
    275     public void onEnabled(Context context, Intent intent) {
    276     }
    277 
    278     /**
    279      * Called when the user has asked to disable the administrator, as a result of
    280      * receiving {@link #ACTION_DEVICE_ADMIN_DISABLE_REQUESTED}, giving you
    281      * a chance to present a warning message to them.  The message is returned
    282      * as the result; if null is returned (the default implementation), no
    283      * message will be displayed.
    284      * @param context The running context as per {@link #onReceive}.
    285      * @param intent The received intent as per {@link #onReceive}.
    286      * @return Return the warning message to display to the user before
    287      * being disabled; if null is returned, no message is displayed.
    288      */
    289     public CharSequence onDisableRequested(Context context, Intent intent) {
    290         return null;
    291     }
    292 
    293     /**
    294      * Called prior to the administrator being disabled, as a result of
    295      * receiving {@link #ACTION_DEVICE_ADMIN_DISABLED}.  Upon return, you
    296      * can no longer use the protected parts of the {@link DevicePolicyManager}
    297      * API.
    298      * @param context The running context as per {@link #onReceive}.
    299      * @param intent The received intent as per {@link #onReceive}.
    300      */
    301     public void onDisabled(Context context, Intent intent) {
    302     }
    303 
    304     /**
    305      * Called after the user has changed their password, as a result of
    306      * receiving {@link #ACTION_PASSWORD_CHANGED}.  At this point you
    307      * can use {@link DevicePolicyManager#getCurrentFailedPasswordAttempts()
    308      * DevicePolicyManager.getCurrentFailedPasswordAttempts()}
    309      * to retrieve the active password characteristics.
    310      * @param context The running context as per {@link #onReceive}.
    311      * @param intent The received intent as per {@link #onReceive}.
    312      */
    313     public void onPasswordChanged(Context context, Intent intent) {
    314     }
    315 
    316     /**
    317      * Called after the user has failed at entering their current password, as a result of
    318      * receiving {@link #ACTION_PASSWORD_FAILED}.  At this point you
    319      * can use {@link DevicePolicyManager} to retrieve the number of failed
    320      * password attempts.
    321      * @param context The running context as per {@link #onReceive}.
    322      * @param intent The received intent as per {@link #onReceive}.
    323      */
    324     public void onPasswordFailed(Context context, Intent intent) {
    325     }
    326 
    327     /**
    328      * Called after the user has succeeded at entering their current password,
    329      * as a result of receiving {@link #ACTION_PASSWORD_SUCCEEDED}.  This will
    330      * only be received the first time they succeed after having previously
    331      * failed.
    332      * @param context The running context as per {@link #onReceive}.
    333      * @param intent The received intent as per {@link #onReceive}.
    334      */
    335     public void onPasswordSucceeded(Context context, Intent intent) {
    336     }
    337 
    338     /**
    339      * Called periodically when the password is about to expire or has expired.  It will typically
    340      * be called at these times: on device boot, once per day before the password expires,
    341      * and at the time when the password expires.
    342      *
    343      * <p>If the password is not updated by the user, this method will continue to be called
    344      * once per day until the password is changed or the device admin disables password expiration.
    345      *
    346      * <p>The admin will typically post a notification requesting the user to change their password
    347      * in response to this call. The actual password expiration time can be obtained by calling
    348      * {@link DevicePolicyManager#getPasswordExpiration(ComponentName) }
    349      *
    350      * <p>The admin should be sure to take down any notifications it posted in response to this call
    351      * when it receives {@link DeviceAdminReceiver#onPasswordChanged(Context, Intent) }.
    352      *
    353      * @param context The running context as per {@link #onReceive}.
    354      * @param intent The received intent as per {@link #onReceive}.
    355      */
    356     public void onPasswordExpiring(Context context, Intent intent) {
    357     }
    358 
    359     /**
    360      * Called when provisioning of a managed profile or managed device has completed successfully.
    361      *
    362      * <p> As a prerequisit for the execution of this callback the (@link DeviceAdminReceiver} has
    363      * to declare an intent filter for {@link #ACTION_PROFILE_PROVISIONING_COMPLETE}.
    364      * Its component must also be specified in the {@link DevicePolicyManager#EXTRA_DEVICE_ADMIN}
    365      * of the {@link DevicePolicyManager#ACTION_PROVISION_MANAGED_PROFILE} intent that started the
    366      * managed provisioning.
    367      *
    368      * <p>When provisioning is complete, the managed profile is hidden until the profile owner
    369      * calls {DevicePolicyManager#setProfileEnabled(ComponentName admin)}. Typically a profile
    370      * owner will enable the profile when it has finished any additional setup such as adding an
    371      * account by using the {@link AccountManager} and calling apis to bring the profile into the
    372      * desired state.
    373      *
    374      * <p> Note that provisioning completes without waiting for any server interactions, so the
    375      * profile owner needs to wait for data to be available if required (e.g android device ids or
    376      * other data that is set as a result of server interactions).
    377      *
    378      * @param context The running context as per {@link #onReceive}.
    379      * @param intent The received intent as per {@link #onReceive}.
    380      */
    381     public void onProfileProvisioningComplete(Context context, Intent intent) {
    382     }
    383 
    384     /**
    385      * Called when a device is entering lock task mode by a package authorized
    386      * by {@link DevicePolicyManager#isLockTaskPermitted(String)}
    387      *
    388      * @param context The running context as per {@link #onReceive}.
    389      * @param intent The received intent as per {@link #onReceive}.
    390      * @param pkg If entering, the authorized package using lock task mode, otherwise null.
    391      */
    392     public void onLockTaskModeEntering(Context context, Intent intent, String pkg) {
    393     }
    394 
    395     /**
    396      * Called when a device is exiting lock task mode by a package authorized
    397      * by {@link DevicePolicyManager#isLockTaskPermitted(String)}
    398      *
    399      * @param context The running context as per {@link #onReceive}.
    400      * @param intent The received intent as per {@link #onReceive}.
    401      */
    402     public void onLockTaskModeExiting(Context context, Intent intent) {
    403     }
    404 
    405     /**
    406      * Intercept standard device administrator broadcasts.  Implementations
    407      * should not override this method; it is better to implement the
    408      * convenience callbacks for each action.
    409      */
    410     @Override
    411     public void onReceive(Context context, Intent intent) {
    412         String action = intent.getAction();
    413 
    414         if (ACTION_PASSWORD_CHANGED.equals(action)) {
    415             onPasswordChanged(context, intent);
    416         } else if (ACTION_PASSWORD_FAILED.equals(action)) {
    417             onPasswordFailed(context, intent);
    418         } else if (ACTION_PASSWORD_SUCCEEDED.equals(action)) {
    419             onPasswordSucceeded(context, intent);
    420         } else if (ACTION_DEVICE_ADMIN_ENABLED.equals(action)) {
    421             onEnabled(context, intent);
    422         } else if (ACTION_DEVICE_ADMIN_DISABLE_REQUESTED.equals(action)) {
    423             CharSequence res = onDisableRequested(context, intent);
    424             if (res != null) {
    425                 Bundle extras = getResultExtras(true);
    426                 extras.putCharSequence(EXTRA_DISABLE_WARNING, res);
    427             }
    428         } else if (ACTION_DEVICE_ADMIN_DISABLED.equals(action)) {
    429             onDisabled(context, intent);
    430         } else if (ACTION_PASSWORD_EXPIRING.equals(action)) {
    431             onPasswordExpiring(context, intent);
    432         } else if (ACTION_PROFILE_PROVISIONING_COMPLETE.equals(action)) {
    433             onProfileProvisioningComplete(context, intent);
    434         } else if (ACTION_LOCK_TASK_ENTERING.equals(action)) {
    435             String pkg = intent.getStringExtra(EXTRA_LOCK_TASK_PACKAGE);
    436             onLockTaskModeEntering(context, intent, pkg);
    437         } else if (ACTION_LOCK_TASK_EXITING.equals(action)) {
    438             onLockTaskModeExiting(context, intent);
    439         }
    440     }
    441 }
    442