DeviceAdminReceiver.java revision 27ee33482a2fdecbbbedbd33a137ceae3e93fa2a
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 device 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.
288     *
289     * @see #ACTION_BUGREPORT_FAILED
290     * @see #BUGREPORT_FAILURE_FAILED_COMPLETING, #BUGREPORT_FAILURE_FILE_NO_LONGER_AVAILABLE
291     * @hide
292     */
293    public static final String EXTRA_BUGREPORT_FAILURE_REASON =
294            "android.app.extra.BUGREPORT_FAILURE_REASON";
295
296    /**
297     * An interface representing reason of bugreport failure.
298     *
299     * @see #EXTRA_BUGREPORT_FAILURE_REASON
300     * @hide
301     */
302    @Retention(RetentionPolicy.SOURCE)
303    @IntDef({
304        BUGREPORT_FAILURE_FAILED_COMPLETING,
305        BUGREPORT_FAILURE_FILE_NO_LONGER_AVAILABLE
306    })
307    public @interface BugreportFailureCode {}
308    /** Bugreport completion process failed. */
309    public static final int BUGREPORT_FAILURE_FAILED_COMPLETING = 0;
310    /** Bugreport is no longer available for collection. */
311    public static final int BUGREPORT_FAILURE_FILE_NO_LONGER_AVAILABLE = 1;
312
313    /** @hide */
314    public static final String ACTION_CHOOSE_PRIVATE_KEY_ALIAS = "android.app.action.CHOOSE_PRIVATE_KEY_ALIAS";
315
316    /** @hide */
317    public static final String EXTRA_CHOOSE_PRIVATE_KEY_SENDER_UID = "android.app.extra.CHOOSE_PRIVATE_KEY_SENDER_UID";
318
319    /** @hide */
320    public static final String EXTRA_CHOOSE_PRIVATE_KEY_URI = "android.app.extra.CHOOSE_PRIVATE_KEY_URI";
321
322    /** @hide */
323    public static final String EXTRA_CHOOSE_PRIVATE_KEY_ALIAS = "android.app.extra.CHOOSE_PRIVATE_KEY_ALIAS";
324
325    /** @hide */
326    public static final String EXTRA_CHOOSE_PRIVATE_KEY_RESPONSE = "android.app.extra.CHOOSE_PRIVATE_KEY_RESPONSE";
327
328    /**
329     * Broadcast action: notify device owner that there is a pending system update.
330     * @hide
331     */
332    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
333    public static final String ACTION_NOTIFY_PENDING_SYSTEM_UPDATE = "android.app.action.NOTIFY_PENDING_SYSTEM_UPDATE";
334
335    /**
336     * A long type extra for {@link #onSystemUpdatePending} recording the system time as given by
337     * {@link System#currentTimeMillis()} when the current pending system update is first available.
338     * @hide
339     */
340    public static final String EXTRA_SYSTEM_UPDATE_RECEIVED_TIME = "android.app.extra.SYSTEM_UPDATE_RECEIVED_TIME";
341
342    /**
343     * Name under which a DevicePolicy component publishes information
344     * about itself.  This meta-data must reference an XML resource containing
345     * a device-admin tag.
346     */
347    //  TO DO: describe syntax.
348    public static final String DEVICE_ADMIN_META_DATA = "android.app.device_admin";
349
350    private DevicePolicyManager mManager;
351    private ComponentName mWho;
352
353    /**
354     * Retrieve the DevicePolicyManager interface for this administrator to work
355     * with the system.
356     */
357    public DevicePolicyManager getManager(Context context) {
358        if (mManager != null) {
359            return mManager;
360        }
361        mManager = (DevicePolicyManager)context.getSystemService(
362                Context.DEVICE_POLICY_SERVICE);
363        return mManager;
364    }
365
366    /**
367     * Retrieve the ComponentName describing who this device administrator is, for
368     * use in {@link DevicePolicyManager} APIs that require the administrator to
369     * identify itself.
370     */
371    public ComponentName getWho(Context context) {
372        if (mWho != null) {
373            return mWho;
374        }
375        mWho = new ComponentName(context, getClass());
376        return mWho;
377    }
378
379    /**
380     * Called after the administrator is first enabled, as a result of
381     * receiving {@link #ACTION_DEVICE_ADMIN_ENABLED}.  At this point you
382     * can use {@link DevicePolicyManager} to set your desired policies.
383     *
384     * <p> If the admin is activated by a device owner, then the intent
385     * may contain private extras that are relevant to user setup.
386     * {@see DevicePolicyManager#createAndManageUser(ComponentName, String, ComponentName,
387     *      PersistableBundle, int)}
388     *
389     * @param context The running context as per {@link #onReceive}.
390     * @param intent The received intent as per {@link #onReceive}.
391     */
392    public void onEnabled(Context context, Intent intent) {
393    }
394
395    /**
396     * Called when the user has asked to disable the administrator, as a result of
397     * receiving {@link #ACTION_DEVICE_ADMIN_DISABLE_REQUESTED}, giving you
398     * a chance to present a warning message to them.  The message is returned
399     * as the result; if null is returned (the default implementation), no
400     * message will be displayed.
401     * @param context The running context as per {@link #onReceive}.
402     * @param intent The received intent as per {@link #onReceive}.
403     * @return Return the warning message to display to the user before
404     * being disabled; if null is returned, no message is displayed.
405     */
406    public CharSequence onDisableRequested(Context context, Intent intent) {
407        return null;
408    }
409
410    /**
411     * Called prior to the administrator being disabled, as a result of
412     * receiving {@link #ACTION_DEVICE_ADMIN_DISABLED}.  Upon return, you
413     * can no longer use the protected parts of the {@link DevicePolicyManager}
414     * API.
415     * @param context The running context as per {@link #onReceive}.
416     * @param intent The received intent as per {@link #onReceive}.
417     */
418    public void onDisabled(Context context, Intent intent) {
419    }
420
421    /**
422     * Called after the user has changed their device or profile challenge password, as a result of
423     * receiving {@link #ACTION_PASSWORD_CHANGED}.  At this point you
424     * can use {@link DevicePolicyManager#getPasswordQuality(android.content.ComponentName)}
425     * to retrieve the active password characteristics.
426     * @param context The running context as per {@link #onReceive}.
427     * @param intent The received intent as per {@link #onReceive}.
428     */
429    public void onPasswordChanged(Context context, Intent intent) {
430    }
431
432    /**
433     * Called after the user has failed at entering their device or profile challenge password,
434     * as a result of receiving {@link #ACTION_PASSWORD_FAILED}.  At this point you can use
435     * {@link DevicePolicyManager#getCurrentFailedPasswordAttempts()} to retrieve the number of
436     * failed password attempts.
437     * @param context The running context as per {@link #onReceive}.
438     * @param intent The received intent as per {@link #onReceive}.
439     */
440    public void onPasswordFailed(Context context, Intent intent) {
441    }
442
443    /**
444     * Called after the user has succeeded at entering their device or profile challenge password,
445     * as a result of receiving {@link #ACTION_PASSWORD_SUCCEEDED}.  This will
446     * only be received the first time they succeed after having previously
447     * failed.
448     * @param context The running context as per {@link #onReceive}.
449     * @param intent The received intent as per {@link #onReceive}.
450     */
451    public void onPasswordSucceeded(Context context, Intent intent) {
452    }
453
454    /**
455     * Called periodically when the device or profile challenge password is about to expire
456     * or has expired.  It will typically be called at these times: on device boot, once per day
457     * before the password expires, and at the time when the password expires.
458     *
459     * <p>If the password is not updated by the user, this method will continue to be called
460     * once per day until the password is changed or the device admin disables password expiration.
461     *
462     * <p>The admin will typically post a notification requesting the user to change their password
463     * in response to this call. The actual password expiration time can be obtained by calling
464     * {@link DevicePolicyManager#getPasswordExpiration(ComponentName) }
465     *
466     * <p>The admin should be sure to take down any notifications it posted in response to this call
467     * when it receives {@link DeviceAdminReceiver#onPasswordChanged(Context, Intent) }.
468     *
469     * @param context The running context as per {@link #onReceive}.
470     * @param intent The received intent as per {@link #onReceive}.
471     */
472    public void onPasswordExpiring(Context context, Intent intent) {
473    }
474
475    /**
476     * Called when provisioning of a managed profile or managed device has completed successfully.
477     *
478     * <p> As a prerequisite for the execution of this callback the {@link DeviceAdminReceiver} has
479     * to declare an intent filter for {@link #ACTION_PROFILE_PROVISIONING_COMPLETE}.
480     * Its component must also be specified in the {@link DevicePolicyManager#EXTRA_DEVICE_ADMIN}
481     * of the {@link DevicePolicyManager#ACTION_PROVISION_MANAGED_PROFILE} intent that started the
482     * managed provisioning.
483     *
484     * <p>When provisioning of a managed profile is complete, the managed profile is hidden until
485     * the profile owner calls {DevicePolicyManager#setProfileEnabled(ComponentName admin)}.
486     * Typically a profile owner will enable the profile when it has finished any additional setup
487     * such as adding an account by using the {@link AccountManager} and calling apis to bring the
488     * profile into the desired state.
489     *
490     * <p> Note that provisioning completes without waiting for any server interactions, so the
491     * profile owner needs to wait for data to be available if required (e.g. android device ids or
492     * other data that is set as a result of server interactions).
493     *
494     * @param context The running context as per {@link #onReceive}.
495     * @param intent The received intent as per {@link #onReceive}.
496     */
497    public void onProfileProvisioningComplete(Context context, Intent intent) {
498    }
499
500    /**
501     * Called during provisioning of a managed device to allow the device initializer to perform
502     * user setup steps.
503     *
504     * @param context The running context as per {@link #onReceive}.
505     * @param intent The received intent as per {@link #onReceive}.
506     * @deprecated Do not use
507     */
508    @Deprecated
509    @SystemApi
510    public void onReadyForUserInitialization(Context context, Intent intent) {
511    }
512
513    /**
514     * Called when a device is entering lock task mode.
515     *
516     * @param context The running context as per {@link #onReceive}.
517     * @param intent The received intent as per {@link #onReceive}.
518     * @param pkg If entering, the authorized package using lock task mode, otherwise null.
519     */
520    public void onLockTaskModeEntering(Context context, Intent intent, String pkg) {
521    }
522
523    /**
524     * Called when a device is exiting lock task mode.
525     *
526     * @param context The running context as per {@link #onReceive}.
527     * @param intent The received intent as per {@link #onReceive}.
528     */
529    public void onLockTaskModeExiting(Context context, Intent intent) {
530    }
531
532    /**
533     * Allows this receiver to select the alias for a private key and certificate pair for
534     * authentication. If this method returns null, the default {@link android.app.Activity} will be
535     * shown that lets the user pick a private key and certificate pair.
536     *
537     * @param context The running context as per {@link #onReceive}.
538     * @param intent The received intent as per {@link #onReceive}.
539     * @param uid The uid asking for the private key and certificate pair.
540     * @param uri The URI to authenticate, may be null.
541     * @param alias The alias preselected by the client, or null.
542     * @return The private key alias to return and grant access to.
543     * @see KeyChain#choosePrivateKeyAlias
544     */
545    public String onChoosePrivateKeyAlias(Context context, Intent intent, int uid, Uri uri,
546            String alias) {
547        return null;
548    }
549
550    /**
551     * Allows the receiver to be notified when information about a pending system update is
552     * available from the system update service. The same pending system update can trigger multiple
553     * calls to this method, so it is necessary to examine the incoming parameters for details about
554     * the update.
555     * <p>
556     * This callback is only applicable to device owners.
557     *
558     * @param context The running context as per {@link #onReceive}.
559     * @param intent The received intent as per {@link #onReceive}.
560     * @param receivedTime The time as given by {@link System#currentTimeMillis()} indicating when
561     *        the current pending update was first available. -1 if no pending update is available.
562     */
563    public void onSystemUpdatePending(Context context, Intent intent, long receivedTime) {
564    }
565
566    /**
567     * Called when sharing a bugreport has been cancelled by the user of the device.
568     *
569     * <p>This callback is only applicable to device owners.
570     *
571     * @param context The running context as per {@link #onReceive}.
572     * @param intent The received intent as per {@link #onReceive}.
573     * @see DevicePolicyManager#requestBugreport
574     */
575    public void onBugreportSharingDeclined(Context context, Intent intent) {
576    }
577
578    /**
579     * Called when the bugreport has been shared with the device administrator app.
580     *
581     * <p>This callback is only applicable to device owners.
582     *
583     * @param context The running context as per {@link #onReceive}.
584     * @param intent The received intent as per {@link #onReceive}. Contains the URI of
585     * the bugreport file (with MIME type "application/vnd.android.bugreport"), that can be accessed
586     * by calling {@link Intent#getData()}
587     * @param bugreportHash SHA-256 hash of the bugreport file.
588     * @see DevicePolicyManager#requestBugreport
589     */
590    public void onBugreportShared(Context context, Intent intent, String bugreportHash) {
591    }
592
593    /**
594     * Called when the bugreport collection flow has failed.
595     *
596     * <p>This callback is only applicable to device owners.
597     *
598     * @param context The running context as per {@link #onReceive}.
599     * @param intent The received intent as per {@link #onReceive}.
600     * @param failureCode int containing failure code. One of
601     * #BUGREPORT_FAILURE_FAILED_COMPLETING or #BUGREPORT_FAILURE_FILE_NO_LONGER_AVAILABLE
602     * @see DevicePolicyManager#requestBugreport
603     */
604    public void onBugreportFailed(Context context, Intent intent,
605            @BugreportFailureCode int failureCode) {
606    }
607
608    /**
609     * Called when a new batch of device logs can be retrieved.
610     *
611     * <p>This callback is only applicable to device owners.
612     *
613     * @param context The running context as per {@link #onReceive}.
614     * @param intent The received intent as per {@link #onReceive}.
615     * @see DevicePolicyManager#retrieveDeviceLogs(ComponentName)
616     */
617    public void onSecurityLogsAvailable(Context context, Intent intent) {
618    }
619
620    /**
621     * Intercept standard device administrator broadcasts.  Implementations
622     * should not override this method; it is better to implement the
623     * convenience callbacks for each action.
624     */
625    @Override
626    public void onReceive(Context context, Intent intent) {
627        String action = intent.getAction();
628
629        if (ACTION_PASSWORD_CHANGED.equals(action)) {
630            onPasswordChanged(context, intent);
631        } else if (ACTION_PASSWORD_FAILED.equals(action)) {
632            onPasswordFailed(context, intent);
633        } else if (ACTION_PASSWORD_SUCCEEDED.equals(action)) {
634            onPasswordSucceeded(context, intent);
635        } else if (ACTION_DEVICE_ADMIN_ENABLED.equals(action)) {
636            onEnabled(context, intent);
637        } else if (ACTION_DEVICE_ADMIN_DISABLE_REQUESTED.equals(action)) {
638            CharSequence res = onDisableRequested(context, intent);
639            if (res != null) {
640                Bundle extras = getResultExtras(true);
641                extras.putCharSequence(EXTRA_DISABLE_WARNING, res);
642            }
643        } else if (ACTION_DEVICE_ADMIN_DISABLED.equals(action)) {
644            onDisabled(context, intent);
645        } else if (ACTION_PASSWORD_EXPIRING.equals(action)) {
646            onPasswordExpiring(context, intent);
647        } else if (ACTION_PROFILE_PROVISIONING_COMPLETE.equals(action)) {
648            onProfileProvisioningComplete(context, intent);
649        } else if (ACTION_CHOOSE_PRIVATE_KEY_ALIAS.equals(action)) {
650            int uid = intent.getIntExtra(EXTRA_CHOOSE_PRIVATE_KEY_SENDER_UID, -1);
651            Uri uri = intent.getParcelableExtra(EXTRA_CHOOSE_PRIVATE_KEY_URI);
652            String alias = intent.getStringExtra(EXTRA_CHOOSE_PRIVATE_KEY_ALIAS);
653            String chosenAlias = onChoosePrivateKeyAlias(context, intent, uid, uri, alias);
654            setResultData(chosenAlias);
655        } else if (ACTION_LOCK_TASK_ENTERING.equals(action)) {
656            String pkg = intent.getStringExtra(EXTRA_LOCK_TASK_PACKAGE);
657            onLockTaskModeEntering(context, intent, pkg);
658        } else if (ACTION_LOCK_TASK_EXITING.equals(action)) {
659            onLockTaskModeExiting(context, intent);
660        } else if (ACTION_NOTIFY_PENDING_SYSTEM_UPDATE.equals(action)) {
661            long receivedTime = intent.getLongExtra(EXTRA_SYSTEM_UPDATE_RECEIVED_TIME, -1);
662            onSystemUpdatePending(context, intent, receivedTime);
663        } else if (ACTION_BUGREPORT_SHARING_DECLINED.equals(action)) {
664            onBugreportSharingDeclined(context, intent);
665        } else if (ACTION_BUGREPORT_SHARE.equals(action)) {
666            String bugreportFileHash = intent.getStringExtra(EXTRA_BUGREPORT_HASH);
667            onBugreportShared(context, intent, bugreportFileHash);
668        } else if (ACTION_BUGREPORT_FAILED.equals(action)) {
669            int failureCode = intent.getIntExtra(EXTRA_BUGREPORT_FAILURE_REASON,
670                    BUGREPORT_FAILURE_FAILED_COMPLETING);
671            onBugreportFailed(context, intent, failureCode);
672        } else if (ACTION_SECURITY_LOGS_AVAILABLE.equals(action)) {
673            onSecurityLogsAvailable(context, intent);
674        }
675    }
676}
677