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      */
getManager(Context context)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      */
getWho(Context context)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      */
onEnabled(Context context, Intent intent)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      */
onDisableRequested(Context context, Intent intent)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      */
onDisabled(Context context, Intent intent)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      */
onPasswordChanged(Context context, Intent intent)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      */
onPasswordFailed(Context context, Intent intent)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      */
onPasswordSucceeded(Context context, Intent intent)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      */
onPasswordExpiring(Context context, Intent intent)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      */
onProfileProvisioningComplete(Context context, Intent intent)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
onReadyForUserInitialization(Context context, Intent intent)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      */
onLockTaskModeEntering(Context context, Intent intent, String pkg)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      */
onLockTaskModeExiting(Context context, Intent intent)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      */
onChoosePrivateKeyAlias(Context context, Intent intent, int uid, Uri uri, String alias)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      */
onSystemUpdatePending(Context context, Intent intent, long receivedTime)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      */
onBugreportSharingDeclined(Context context, Intent intent)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      */
onBugreportShared(Context context, Intent intent, String bugreportHash)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      */
onBugreportFailed(Context context, Intent intent, @BugreportFailureCode int failureCode)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      */
onSecurityLogsAvailable(Context context, Intent intent)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
onReceive(Context context, Intent intent)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