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
17package android.app.admin;
18
19import android.accounts.AccountManager;
20import android.annotation.IntDef;
21import android.annotation.SdkConstant;
22import android.annotation.SdkConstant.SdkConstantType;
23import android.annotation.SystemApi;
24import android.app.Service;
25import android.content.BroadcastReceiver;
26import android.content.ComponentName;
27import android.content.Context;
28import android.content.Intent;
29import android.net.Uri;
30import android.os.Bundle;
31import android.security.KeyChain;
32
33import java.lang.annotation.Retention;
34import 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 */
68public 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