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.IntDef;
     21 import android.annotation.SdkConstant;
     22 import android.annotation.SdkConstant.SdkConstantType;
     23 import android.annotation.SystemApi;
     24 import android.app.Service;
     25 import android.content.BroadcastReceiver;
     26 import android.content.ComponentName;
     27 import android.content.Context;
     28 import android.content.Intent;
     29 import android.net.Uri;
     30 import android.os.Bundle;
     31 import android.security.KeyChain;
     32 
     33 import java.lang.annotation.Retention;
     34 import java.lang.annotation.RetentionPolicy;
     35 
     36 /**
     37  * Base class for implementing a device administration component.  This
     38  * class provides a convenience for interpreting the raw intent actions
     39  * that are sent by the system.
     40  *
     41  * <p>The callback methods, like the base
     42  * {@link BroadcastReceiver#onReceive(Context, Intent) BroadcastReceiver.onReceive()}
     43  * method, happen on the main thread of the process.  Thus long running
     44  * operations must be done on another thread.  Note that because a receiver
     45  * is done once returning from its receive function, such long-running operations
     46  * should probably be done in a {@link Service}.
     47  *
     48  * <p>When publishing your DeviceAdmin subclass as a receiver, it must
     49  * handle {@link #ACTION_DEVICE_ADMIN_ENABLED} and require the
     50  * {@link android.Manifest.permission#BIND_DEVICE_ADMIN} permission.  A typical
     51  * manifest entry would look like:</p>
     52  *
     53  * {@sample development/samples/ApiDemos/AndroidManifest.xml device_admin_declaration}
     54  *
     55  * <p>The meta-data referenced here provides addition information specific
     56  * to the device administrator, as parsed by the {@link DeviceAdminInfo} class.
     57  * A typical file would be:</p>
     58  *
     59  * {@sample development/samples/ApiDemos/res/xml/device_admin_sample.xml meta_data}
     60  *
     61  * <div class="special reference">
     62  * <h3>Developer Guides</h3>
     63  * <p>For more information about device administration, read the
     64  * <a href="{@docRoot}guide/topics/admin/device-admin.html">Device Administration</a>
     65  * developer guide.</p>
     66  * </div>
     67  */
     68 public class DeviceAdminReceiver extends BroadcastReceiver {
     69     private static String TAG = "DevicePolicy";
     70     private static boolean localLOGV = false;
     71 
     72     /**
     73      * This is the primary action that a device administrator must implement to be
     74      * allowed to manage a device.  This will be set to the receiver
     75      * when the user enables it for administration.  You will generally
     76      * handle this in {@link DeviceAdminReceiver#onEnabled(Context, Intent)}.  To be
     77      * supported, the receiver must also require the
     78      * {@link android.Manifest.permission#BIND_DEVICE_ADMIN} permission so
     79      * that other applications can not abuse it.
     80      */
     81     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     82     public static final String ACTION_DEVICE_ADMIN_ENABLED
     83             = "android.app.action.DEVICE_ADMIN_ENABLED";
     84 
     85     /**
     86      * Action sent to a device administrator when the user has requested to
     87      * disable it, but before this has actually been done.  This gives you
     88      * a chance to supply a message to the user about the impact of
     89      * disabling your admin, by setting the extra field
     90      * {@link #EXTRA_DISABLE_WARNING} in the result Intent.  If not set,
     91      * no warning will be displayed.  If set, the given text will be shown
     92      * to the user before they disable your admin.
     93      */
     94     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     95     public static final String ACTION_DEVICE_ADMIN_DISABLE_REQUESTED
     96             = "android.app.action.DEVICE_ADMIN_DISABLE_REQUESTED";
     97 
     98     /**
     99      * A CharSequence that can be shown to the user informing them of the
    100      * impact of disabling your admin.
    101      *
    102      * @see #ACTION_DEVICE_ADMIN_DISABLE_REQUESTED
    103      */
    104     public static final String EXTRA_DISABLE_WARNING = "android.app.extra.DISABLE_WARNING";
    105 
    106     /**
    107      * Action sent to a device administrator when the user has disabled
    108      * it.  Upon return, the application no longer has access to the
    109      * protected device policy manager APIs.  You will generally
    110      * handle this in {@link DeviceAdminReceiver#onDisabled(Context, Intent)}.  Note
    111      * that this action will be
    112      * sent the receiver regardless of whether it is explicitly listed in
    113      * its intent filter.
    114      */
    115     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    116     public static final String ACTION_DEVICE_ADMIN_DISABLED
    117             = "android.app.action.DEVICE_ADMIN_DISABLED";
    118 
    119     /**
    120      * Action sent to a device administrator when the user has changed the password of their device
    121      * or profile challenge.  You can at this point check the characteristics
    122      * of the new password with {@link DevicePolicyManager#isActivePasswordSufficient()
    123      * DevicePolicyManager.isActivePasswordSufficient()}.
    124      * You will generally
    125      * handle this in {@link DeviceAdminReceiver#onPasswordChanged}.
    126      *
    127      * <p>The calling device admin must have requested
    128      * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to receive
    129      * this broadcast.
    130      */
    131     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    132     public static final String ACTION_PASSWORD_CHANGED
    133             = "android.app.action.ACTION_PASSWORD_CHANGED";
    134 
    135     /**
    136      * Action sent to a device administrator when the user has entered an incorrect device
    137      * or profile challenge password.  You can at this point check the
    138      * number of failed password attempts there have been with
    139      * {@link DevicePolicyManager#getCurrentFailedPasswordAttempts
    140      * DevicePolicyManager.getCurrentFailedPasswordAttempts()}.  You will generally
    141      * handle this in {@link DeviceAdminReceiver#onPasswordFailed}.
    142      *
    143      * <p>The calling device admin must have requested
    144      * {@link DeviceAdminInfo#USES_POLICY_WATCH_LOGIN} to receive
    145      * this broadcast.
    146      */
    147     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    148     public static final String ACTION_PASSWORD_FAILED
    149             = "android.app.action.ACTION_PASSWORD_FAILED";
    150 
    151     /**
    152      * Action sent to a device administrator when the user has successfully entered their device
    153      * or profile challenge password, after failing one or more times.  You will generally
    154      * handle this in {@link DeviceAdminReceiver#onPasswordSucceeded}.
    155      *
    156      * <p>The calling device admin must have requested
    157      * {@link DeviceAdminInfo#USES_POLICY_WATCH_LOGIN} to receive
    158      * this broadcast.
    159      */
    160     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    161     public static final String ACTION_PASSWORD_SUCCEEDED
    162             = "android.app.action.ACTION_PASSWORD_SUCCEEDED";
    163 
    164     /**
    165      * Action periodically sent to a device administrator when the device or profile challenge
    166      * password is expiring.  You will generally
    167      * handle this in {@link DeviceAdminReceiver#onPasswordExpiring}.
    168      *
    169      * <p>The calling device admin must have requested
    170      * {@link DeviceAdminInfo#USES_POLICY_EXPIRE_PASSWORD} to receive
    171      * this broadcast.
    172      */
    173     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    174     public static final String ACTION_PASSWORD_EXPIRING
    175             = "android.app.action.ACTION_PASSWORD_EXPIRING";
    176 
    177     /**
    178      * Action sent to a device administrator to notify that the device is entering
    179      * lock task mode.  The extra {@link #EXTRA_LOCK_TASK_PACKAGE}
    180      * will describe the package using lock task mode.
    181      *
    182      * <p>The calling device admin must be the device owner or profile
    183      * owner to receive this broadcast.
    184      *
    185      * @see DevicePolicyManager#isLockTaskPermitted(String)
    186      */
    187     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    188     public static final String ACTION_LOCK_TASK_ENTERING
    189             = "android.app.action.LOCK_TASK_ENTERING";
    190 
    191     /**
    192      * Action sent to a device administrator to notify that the device is exiting
    193      * lock task mode.
    194      *
    195      * <p>The calling device admin must be the device owner or profile
    196      * owner to receive this broadcast.
    197      *
    198      * @see DevicePolicyManager#isLockTaskPermitted(String)
    199      */
    200     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    201     public static final String ACTION_LOCK_TASK_EXITING
    202             = "android.app.action.LOCK_TASK_EXITING";
    203 
    204     /**
    205      * A string containing the name of the package entering lock task mode.
    206      *
    207      * @see #ACTION_LOCK_TASK_ENTERING
    208      */
    209     public static final String EXTRA_LOCK_TASK_PACKAGE =
    210             "android.app.extra.LOCK_TASK_PACKAGE";
    211 
    212     /**
    213      * Broadcast Action: This broadcast is sent to indicate that provisioning of a managed profile
    214      * or managed device has completed successfully.
    215      *
    216      * <p>The broadcast is limited to the profile that will be managed by the application that
    217      * requested provisioning. In the device owner case the profile is the primary user.
    218      * The broadcast will also be limited to the {@link DeviceAdminReceiver} component
    219      * specified in the original intent or NFC bump that started the provisioning process
    220      * (see {@link DevicePolicyManager#ACTION_PROVISION_MANAGED_PROFILE
    221      * DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE}).
    222      *
    223      * <p>A device admin application which listens to this intent can find out if the device was
    224      * provisioned for the device owner or profile owner case by calling respectively
    225      * {@link android.app.admin.DevicePolicyManager#isDeviceOwnerApp} and
    226      * {@link android.app.admin.DevicePolicyManager#isProfileOwnerApp}. You will generally handle
    227      * this in {@link DeviceAdminReceiver#onProfileProvisioningComplete}.
    228      *
    229      * <p>Input: Nothing.</p>
    230      * <p>Output: Nothing</p>
    231      */
    232     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    233     public static final String ACTION_PROFILE_PROVISIONING_COMPLETE =
    234             "android.app.action.PROFILE_PROVISIONING_COMPLETE";
    235 
    236     /**
    237      * Action sent to a device administrator to notify that the device user
    238      * has declined sharing a bugreport.
    239      *
    240      * <p>The calling device admin must be the device owner to receive this broadcast.
    241      * @see DevicePolicyManager#requestBugreport
    242      * @hide
    243      */
    244     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    245     public static final String ACTION_BUGREPORT_SHARING_DECLINED =
    246             "android.app.action.BUGREPORT_SHARING_DECLINED";
    247 
    248     /**
    249      * Action sent to a device administrator to notify that the collection of a bugreport
    250      * has failed.
    251      *
    252      * <p>The calling device admin must be the device owner to receive this broadcast.
    253      * @see DevicePolicyManager#requestBugreport
    254      * @hide
    255      */
    256     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    257     public static final String ACTION_BUGREPORT_FAILED = "android.app.action.BUGREPORT_FAILED";
    258 
    259     /**
    260      * Action sent to a device administrator to share the bugreport.
    261      *
    262      * <p>The calling device admin must be the device owner to receive this broadcast.
    263      * @see DevicePolicyManager#requestBugreport
    264      * @hide
    265      */
    266     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    267     public static final String ACTION_BUGREPORT_SHARE =
    268             "android.app.action.BUGREPORT_SHARE";
    269 
    270     /**
    271      * Broadcast action: notify that a new batch of security logs is ready to be collected.
    272      * @hide
    273      */
    274     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    275     public static final String ACTION_SECURITY_LOGS_AVAILABLE
    276             = "android.app.action.SECURITY_LOGS_AVAILABLE";
    277 
    278     /**
    279      * A string containing the SHA-256 hash of the bugreport file.
    280      *
    281      * @see #ACTION_BUGREPORT_SHARE
    282      * @hide
    283      */
    284     public static final String EXTRA_BUGREPORT_HASH = "android.app.extra.BUGREPORT_HASH";
    285 
    286     /**
    287      * An {@code int} failure code representing the reason of the bugreport failure. One of
    288      * {@link #BUGREPORT_FAILURE_FAILED_COMPLETING}
    289      * or {@link #BUGREPORT_FAILURE_FILE_NO_LONGER_AVAILABLE}
    290      *
    291      * @see #ACTION_BUGREPORT_FAILED
    292      * @hide
    293      */
    294     public static final String EXTRA_BUGREPORT_FAILURE_REASON =
    295             "android.app.extra.BUGREPORT_FAILURE_REASON";
    296 
    297     /**
    298      * An interface representing reason of bugreport failure.
    299      *
    300      * @see #EXTRA_BUGREPORT_FAILURE_REASON
    301      * @hide
    302      */
    303     @Retention(RetentionPolicy.SOURCE)
    304     @IntDef({
    305         BUGREPORT_FAILURE_FAILED_COMPLETING,
    306         BUGREPORT_FAILURE_FILE_NO_LONGER_AVAILABLE
    307     })
    308     public @interface BugreportFailureCode {}
    309 
    310     /**
    311      * Bugreport completion process failed.
    312      *
    313      * <p>If this error code is received, the requesting of bugreport can be retried.
    314      * @see DevicePolicyManager#requestBugreport
    315      */
    316     public static final int BUGREPORT_FAILURE_FAILED_COMPLETING = 0;
    317 
    318     /**
    319      * Bugreport has been created, but is no longer available for collection.
    320      *
    321      * <p>This error likely occurs because the user of the device hasn't consented to share
    322      * the bugreport for a long period after its creation.
    323      *
    324      * <p>If this error code is received, the requesting of bugreport can be retried.
    325      * @see DevicePolicyManager#requestBugreport
    326      */
    327     public static final int BUGREPORT_FAILURE_FILE_NO_LONGER_AVAILABLE = 1;
    328 
    329     /** @hide */
    330     public static final String ACTION_CHOOSE_PRIVATE_KEY_ALIAS = "android.app.action.CHOOSE_PRIVATE_KEY_ALIAS";
    331 
    332     /** @hide */
    333     public static final String EXTRA_CHOOSE_PRIVATE_KEY_SENDER_UID = "android.app.extra.CHOOSE_PRIVATE_KEY_SENDER_UID";
    334 
    335     /** @hide */
    336     public static final String EXTRA_CHOOSE_PRIVATE_KEY_URI = "android.app.extra.CHOOSE_PRIVATE_KEY_URI";
    337 
    338     /** @hide */
    339     public static final String EXTRA_CHOOSE_PRIVATE_KEY_ALIAS = "android.app.extra.CHOOSE_PRIVATE_KEY_ALIAS";
    340 
    341     /** @hide */
    342     public static final String EXTRA_CHOOSE_PRIVATE_KEY_RESPONSE = "android.app.extra.CHOOSE_PRIVATE_KEY_RESPONSE";
    343 
    344     /**
    345      * Broadcast action: notify device owner that there is a pending system update.
    346      * @hide
    347      */
    348     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    349     public static final String ACTION_NOTIFY_PENDING_SYSTEM_UPDATE = "android.app.action.NOTIFY_PENDING_SYSTEM_UPDATE";
    350 
    351     /**
    352      * A long type extra for {@link #onSystemUpdatePending} recording the system time as given by
    353      * {@link System#currentTimeMillis()} when the current pending system update is first available.
    354      * @hide
    355      */
    356     public static final String EXTRA_SYSTEM_UPDATE_RECEIVED_TIME = "android.app.extra.SYSTEM_UPDATE_RECEIVED_TIME";
    357 
    358     /**
    359      * Name under which a DevicePolicy component publishes information
    360      * about itself.  This meta-data must reference an XML resource containing
    361      * a device-admin tag.
    362      */
    363     //  TO DO: describe syntax.
    364     public static final String DEVICE_ADMIN_META_DATA = "android.app.device_admin";
    365 
    366     private DevicePolicyManager mManager;
    367     private ComponentName mWho;
    368 
    369     /**
    370      * Retrieve the DevicePolicyManager interface for this administrator to work
    371      * with the system.
    372      */
    373     public DevicePolicyManager getManager(Context context) {
    374         if (mManager != null) {
    375             return mManager;
    376         }
    377         mManager = (DevicePolicyManager)context.getSystemService(
    378                 Context.DEVICE_POLICY_SERVICE);
    379         return mManager;
    380     }
    381 
    382     /**
    383      * Retrieve the ComponentName describing who this device administrator is, for
    384      * use in {@link DevicePolicyManager} APIs that require the administrator to
    385      * identify itself.
    386      */
    387     public ComponentName getWho(Context context) {
    388         if (mWho != null) {
    389             return mWho;
    390         }
    391         mWho = new ComponentName(context, getClass());
    392         return mWho;
    393     }
    394 
    395     /**
    396      * Called after the administrator is first enabled, as a result of
    397      * receiving {@link #ACTION_DEVICE_ADMIN_ENABLED}.  At this point you
    398      * can use {@link DevicePolicyManager} to set your desired policies.
    399      *
    400      * <p> If the admin is activated by a device owner, then the intent
    401      * may contain private extras that are relevant to user setup.
    402      * {@see DevicePolicyManager#createAndManageUser(ComponentName, String, ComponentName,
    403      *      PersistableBundle, int)}
    404      *
    405      * @param context The running context as per {@link #onReceive}.
    406      * @param intent The received intent as per {@link #onReceive}.
    407      */
    408     public void onEnabled(Context context, Intent intent) {
    409     }
    410 
    411     /**
    412      * Called when the user has asked to disable the administrator, as a result of
    413      * receiving {@link #ACTION_DEVICE_ADMIN_DISABLE_REQUESTED}, giving you
    414      * a chance to present a warning message to them.  The message is returned
    415      * as the result; if null is returned (the default implementation), no
    416      * message will be displayed.
    417      * @param context The running context as per {@link #onReceive}.
    418      * @param intent The received intent as per {@link #onReceive}.
    419      * @return Return the warning message to display to the user before
    420      * being disabled; if null is returned, no message is displayed.
    421      */
    422     public CharSequence onDisableRequested(Context context, Intent intent) {
    423         return null;
    424     }
    425 
    426     /**
    427      * Called prior to the administrator being disabled, as a result of
    428      * receiving {@link #ACTION_DEVICE_ADMIN_DISABLED}.  Upon return, you
    429      * can no longer use the protected parts of the {@link DevicePolicyManager}
    430      * API.
    431      * @param context The running context as per {@link #onReceive}.
    432      * @param intent The received intent as per {@link #onReceive}.
    433      */
    434     public void onDisabled(Context context, Intent intent) {
    435     }
    436 
    437     /**
    438      * Called after the user has changed their device or profile challenge password, as a result of
    439      * receiving {@link #ACTION_PASSWORD_CHANGED}.  At this point you
    440      * can use {@link DevicePolicyManager#getPasswordQuality(android.content.ComponentName)}
    441      * to retrieve the active password characteristics.
    442      * @param context The running context as per {@link #onReceive}.
    443      * @param intent The received intent as per {@link #onReceive}.
    444      */
    445     public void onPasswordChanged(Context context, Intent intent) {
    446     }
    447 
    448     /**
    449      * Called after the user has failed at entering their device or profile challenge password,
    450      * as a result of receiving {@link #ACTION_PASSWORD_FAILED}.  At this point you can use
    451      * {@link DevicePolicyManager#getCurrentFailedPasswordAttempts()} to retrieve the number of
    452      * failed password attempts.
    453      * @param context The running context as per {@link #onReceive}.
    454      * @param intent The received intent as per {@link #onReceive}.
    455      */
    456     public void onPasswordFailed(Context context, Intent intent) {
    457     }
    458 
    459     /**
    460      * Called after the user has succeeded at entering their device or profile challenge password,
    461      * as a result of receiving {@link #ACTION_PASSWORD_SUCCEEDED}.  This will
    462      * only be received the first time they succeed after having previously
    463      * failed.
    464      * @param context The running context as per {@link #onReceive}.
    465      * @param intent The received intent as per {@link #onReceive}.
    466      */
    467     public void onPasswordSucceeded(Context context, Intent intent) {
    468     }
    469 
    470     /**
    471      * Called periodically when the device or profile challenge password is about to expire
    472      * or has expired.  It will typically be called at these times: on device boot, once per day
    473      * before the password expires, and at the time when the password expires.
    474      *
    475      * <p>If the password is not updated by the user, this method will continue to be called
    476      * once per day until the password is changed or the device admin disables password expiration.
    477      *
    478      * <p>The admin will typically post a notification requesting the user to change their password
    479      * in response to this call. The actual password expiration time can be obtained by calling
    480      * {@link DevicePolicyManager#getPasswordExpiration(ComponentName) }
    481      *
    482      * <p>The admin should be sure to take down any notifications it posted in response to this call
    483      * when it receives {@link DeviceAdminReceiver#onPasswordChanged(Context, Intent) }.
    484      *
    485      * @param context The running context as per {@link #onReceive}.
    486      * @param intent The received intent as per {@link #onReceive}.
    487      */
    488     public void onPasswordExpiring(Context context, Intent intent) {
    489     }
    490 
    491     /**
    492      * Called when provisioning of a managed profile or managed device has completed successfully.
    493      *
    494      * <p> As a prerequisite for the execution of this callback the {@link DeviceAdminReceiver} has
    495      * to declare an intent filter for {@link #ACTION_PROFILE_PROVISIONING_COMPLETE}.
    496      * Its component must also be specified in the {@link DevicePolicyManager#EXTRA_DEVICE_ADMIN}
    497      * of the {@link DevicePolicyManager#ACTION_PROVISION_MANAGED_PROFILE} intent that started the
    498      * managed provisioning.
    499      *
    500      * <p>When provisioning of a managed profile is complete, the managed profile is hidden until
    501      * the profile owner calls {DevicePolicyManager#setProfileEnabled(ComponentName admin)}.
    502      * Typically a profile owner will enable the profile when it has finished any additional setup
    503      * such as adding an account by using the {@link AccountManager} and calling apis to bring the
    504      * profile into the desired state.
    505      *
    506      * <p> Note that provisioning completes without waiting for any server interactions, so the
    507      * profile owner needs to wait for data to be available if required (e.g. android device ids or
    508      * other data that is set as a result of server interactions).
    509      *
    510      * @param context The running context as per {@link #onReceive}.
    511      * @param intent The received intent as per {@link #onReceive}.
    512      */
    513     public void onProfileProvisioningComplete(Context context, Intent intent) {
    514     }
    515 
    516     /**
    517      * Called during provisioning of a managed device to allow the device initializer to perform
    518      * user setup steps.
    519      *
    520      * @param context The running context as per {@link #onReceive}.
    521      * @param intent The received intent as per {@link #onReceive}.
    522      * @deprecated Do not use
    523      */
    524     @Deprecated
    525     @SystemApi
    526     public void onReadyForUserInitialization(Context context, Intent intent) {
    527     }
    528 
    529     /**
    530      * Called when a device is entering lock task mode.
    531      *
    532      * @param context The running context as per {@link #onReceive}.
    533      * @param intent The received intent as per {@link #onReceive}.
    534      * @param pkg If entering, the authorized package using lock task mode, otherwise null.
    535      */
    536     public void onLockTaskModeEntering(Context context, Intent intent, String pkg) {
    537     }
    538 
    539     /**
    540      * Called when a device is exiting lock task mode.
    541      *
    542      * @param context The running context as per {@link #onReceive}.
    543      * @param intent The received intent as per {@link #onReceive}.
    544      */
    545     public void onLockTaskModeExiting(Context context, Intent intent) {
    546     }
    547 
    548     /**
    549      * Allows this receiver to select the alias for a private key and certificate pair for
    550      * authentication. If this method returns null, the default {@link android.app.Activity} will be
    551      * shown that lets the user pick a private key and certificate pair.
    552      *
    553      * @param context The running context as per {@link #onReceive}.
    554      * @param intent The received intent as per {@link #onReceive}.
    555      * @param uid The uid asking for the private key and certificate pair.
    556      * @param uri The URI to authenticate, may be null.
    557      * @param alias The alias preselected by the client, or null.
    558      * @return The private key alias to return and grant access to.
    559      * @see KeyChain#choosePrivateKeyAlias
    560      */
    561     public String onChoosePrivateKeyAlias(Context context, Intent intent, int uid, Uri uri,
    562             String alias) {
    563         return null;
    564     }
    565 
    566     /**
    567      * Allows the receiver to be notified when information about a pending system update is
    568      * available from the system update service. The same pending system update can trigger multiple
    569      * calls to this method, so it is necessary to examine the incoming parameters for details about
    570      * the update.
    571      * <p>
    572      * This callback is only applicable to device owners.
    573      *
    574      * @param context The running context as per {@link #onReceive}.
    575      * @param intent The received intent as per {@link #onReceive}.
    576      * @param receivedTime The time as given by {@link System#currentTimeMillis()} indicating when
    577      *        the current pending update was first available. -1 if no pending update is available.
    578      */
    579     public void onSystemUpdatePending(Context context, Intent intent, long receivedTime) {
    580     }
    581 
    582     /**
    583      * Called when sharing a bugreport has been cancelled by the user of the device.
    584      *
    585      * <p>This callback is only applicable to device owners.
    586      *
    587      * @param context The running context as per {@link #onReceive}.
    588      * @param intent The received intent as per {@link #onReceive}.
    589      * @see DevicePolicyManager#requestBugreport
    590      */
    591     public void onBugreportSharingDeclined(Context context, Intent intent) {
    592     }
    593 
    594     /**
    595      * Called when the bugreport has been shared with the device administrator app.
    596      *
    597      * <p>This callback is only applicable to device owners.
    598      *
    599      * @param context The running context as per {@link #onReceive}.
    600      * @param intent The received intent as per {@link #onReceive}. Contains the URI of
    601      * the bugreport file (with MIME type "application/vnd.android.bugreport"), that can be accessed
    602      * by calling {@link Intent#getData()}
    603      * @param bugreportHash SHA-256 hash of the bugreport file.
    604      * @see DevicePolicyManager#requestBugreport
    605      */
    606     public void onBugreportShared(Context context, Intent intent, String bugreportHash) {
    607     }
    608 
    609     /**
    610      * Called when the bugreport collection flow has failed.
    611      *
    612      * <p>This callback is only applicable to device owners.
    613      *
    614      * @param context The running context as per {@link #onReceive}.
    615      * @param intent The received intent as per {@link #onReceive}.
    616      * @param failureCode int containing failure code. One of
    617      * {@link #BUGREPORT_FAILURE_FAILED_COMPLETING}
    618      * or {@link #BUGREPORT_FAILURE_FILE_NO_LONGER_AVAILABLE}
    619      * @see DevicePolicyManager#requestBugreport
    620      */
    621     public void onBugreportFailed(Context context, Intent intent,
    622             @BugreportFailureCode int failureCode) {
    623     }
    624 
    625     /**
    626      * Called when a new batch of security logs can be retrieved.
    627      *
    628      * <p>This callback is only applicable to device owners.
    629      *
    630      * @param context The running context as per {@link #onReceive}.
    631      * @param intent The received intent as per {@link #onReceive}.
    632      * @see DevicePolicyManager#retrieveSecurityLogs(ComponentName)
    633      */
    634     public void onSecurityLogsAvailable(Context context, Intent intent) {
    635     }
    636 
    637     /**
    638      * Intercept standard device administrator broadcasts.  Implementations
    639      * should not override this method; it is better to implement the
    640      * convenience callbacks for each action.
    641      */
    642     @Override
    643     public void onReceive(Context context, Intent intent) {
    644         String action = intent.getAction();
    645 
    646         if (ACTION_PASSWORD_CHANGED.equals(action)) {
    647             onPasswordChanged(context, intent);
    648         } else if (ACTION_PASSWORD_FAILED.equals(action)) {
    649             onPasswordFailed(context, intent);
    650         } else if (ACTION_PASSWORD_SUCCEEDED.equals(action)) {
    651             onPasswordSucceeded(context, intent);
    652         } else if (ACTION_DEVICE_ADMIN_ENABLED.equals(action)) {
    653             onEnabled(context, intent);
    654         } else if (ACTION_DEVICE_ADMIN_DISABLE_REQUESTED.equals(action)) {
    655             CharSequence res = onDisableRequested(context, intent);
    656             if (res != null) {
    657                 Bundle extras = getResultExtras(true);
    658                 extras.putCharSequence(EXTRA_DISABLE_WARNING, res);
    659             }
    660         } else if (ACTION_DEVICE_ADMIN_DISABLED.equals(action)) {
    661             onDisabled(context, intent);
    662         } else if (ACTION_PASSWORD_EXPIRING.equals(action)) {
    663             onPasswordExpiring(context, intent);
    664         } else if (ACTION_PROFILE_PROVISIONING_COMPLETE.equals(action)) {
    665             onProfileProvisioningComplete(context, intent);
    666         } else if (ACTION_CHOOSE_PRIVATE_KEY_ALIAS.equals(action)) {
    667             int uid = intent.getIntExtra(EXTRA_CHOOSE_PRIVATE_KEY_SENDER_UID, -1);
    668             Uri uri = intent.getParcelableExtra(EXTRA_CHOOSE_PRIVATE_KEY_URI);
    669             String alias = intent.getStringExtra(EXTRA_CHOOSE_PRIVATE_KEY_ALIAS);
    670             String chosenAlias = onChoosePrivateKeyAlias(context, intent, uid, uri, alias);
    671             setResultData(chosenAlias);
    672         } else if (ACTION_LOCK_TASK_ENTERING.equals(action)) {
    673             String pkg = intent.getStringExtra(EXTRA_LOCK_TASK_PACKAGE);
    674             onLockTaskModeEntering(context, intent, pkg);
    675         } else if (ACTION_LOCK_TASK_EXITING.equals(action)) {
    676             onLockTaskModeExiting(context, intent);
    677         } else if (ACTION_NOTIFY_PENDING_SYSTEM_UPDATE.equals(action)) {
    678             long receivedTime = intent.getLongExtra(EXTRA_SYSTEM_UPDATE_RECEIVED_TIME, -1);
    679             onSystemUpdatePending(context, intent, receivedTime);
    680         } else if (ACTION_BUGREPORT_SHARING_DECLINED.equals(action)) {
    681             onBugreportSharingDeclined(context, intent);
    682         } else if (ACTION_BUGREPORT_SHARE.equals(action)) {
    683             String bugreportFileHash = intent.getStringExtra(EXTRA_BUGREPORT_HASH);
    684             onBugreportShared(context, intent, bugreportFileHash);
    685         } else if (ACTION_BUGREPORT_FAILED.equals(action)) {
    686             int failureCode = intent.getIntExtra(EXTRA_BUGREPORT_FAILURE_REASON,
    687                     BUGREPORT_FAILURE_FAILED_COMPLETING);
    688             onBugreportFailed(context, intent, failureCode);
    689         } else if (ACTION_SECURITY_LOGS_AVAILABLE.equals(action)) {
    690             onSecurityLogsAvailable(context, intent);
    691         }
    692     }
    693 }
    694