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.BroadcastBehavior;
21 import android.annotation.IntDef;
22 import android.annotation.NonNull;
23 import android.annotation.Nullable;
24 import android.annotation.SdkConstant;
25 import android.annotation.SdkConstant.SdkConstantType;
26 import android.annotation.SystemApi;
27 import android.app.Service;
28 import android.content.BroadcastReceiver;
29 import android.content.ComponentName;
30 import android.content.Context;
31 import android.content.Intent;
32 import android.net.Uri;
33 import android.os.Bundle;
34 import android.os.PersistableBundle;
35 import android.os.Process;
36 import android.os.UserHandle;
37 import android.security.KeyChain;
38 
39 import java.lang.annotation.Retention;
40 import java.lang.annotation.RetentionPolicy;
41 
42 /**
43  * Base class for implementing a device administration component.  This
44  * class provides a convenience for interpreting the raw intent actions
45  * that are sent by the system.
46  *
47  * <p>The callback methods, like the base
48  * {@link BroadcastReceiver#onReceive(Context, Intent) BroadcastReceiver.onReceive()}
49  * method, happen on the main thread of the process.  Thus long running
50  * operations must be done on another thread.  Note that because a receiver
51  * is done once returning from its receive function, such long-running operations
52  * should probably be done in a {@link Service}.
53  *
54  * <p>When publishing your DeviceAdmin subclass as a receiver, it must
55  * handle {@link #ACTION_DEVICE_ADMIN_ENABLED} and require the
56  * {@link android.Manifest.permission#BIND_DEVICE_ADMIN} permission.  A typical
57  * manifest entry would look like:</p>
58  *
59  * {@sample development/samples/ApiDemos/AndroidManifest.xml device_admin_declaration}
60  *
61  * <p>The meta-data referenced here provides addition information specific
62  * to the device administrator, as parsed by the {@link DeviceAdminInfo} class.
63  * A typical file would be:</p>
64  *
65  * {@sample development/samples/ApiDemos/res/xml/device_admin_sample.xml meta_data}
66  *
67  * <div class="special reference">
68  * <h3>Developer Guides</h3>
69  * <p>For more information about device administration, read the
70  * <a href="{@docRoot}guide/topics/admin/device-admin.html">Device Administration</a>
71  * developer guide.</p>
72  * </div>
73  */
74 public class DeviceAdminReceiver extends BroadcastReceiver {
75     private static String TAG = "DevicePolicy";
76     private static boolean localLOGV = false;
77 
78     /**
79      * This is the primary action that a device administrator must implement to be
80      * allowed to manage a device.  This will be set to the receiver
81      * when the user enables it for administration.  You will generally
82      * handle this in {@link DeviceAdminReceiver#onEnabled(Context, Intent)}.  To be
83      * supported, the receiver must also require the
84      * {@link android.Manifest.permission#BIND_DEVICE_ADMIN} permission so
85      * that other applications can not abuse it.
86      */
87     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
88     @BroadcastBehavior(explicitOnly = true)
89     public static final String ACTION_DEVICE_ADMIN_ENABLED
90             = "android.app.action.DEVICE_ADMIN_ENABLED";
91 
92     /**
93      * Action sent to a device administrator when the user has requested to
94      * disable it, but before this has actually been done.  This gives you
95      * a chance to supply a message to the user about the impact of
96      * disabling your admin, by setting the extra field
97      * {@link #EXTRA_DISABLE_WARNING} in the result Intent.  If not set,
98      * no warning will be displayed.  If set, the given text will be shown
99      * to the user before they disable your admin.
100      */
101     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
102     @BroadcastBehavior(explicitOnly = true)
103     public static final String ACTION_DEVICE_ADMIN_DISABLE_REQUESTED
104             = "android.app.action.DEVICE_ADMIN_DISABLE_REQUESTED";
105 
106     /**
107      * A CharSequence that can be shown to the user informing them of the
108      * impact of disabling your admin.
109      *
110      * @see #ACTION_DEVICE_ADMIN_DISABLE_REQUESTED
111      */
112     public static final String EXTRA_DISABLE_WARNING = "android.app.extra.DISABLE_WARNING";
113 
114     /**
115      * Action sent to a device administrator when the user has disabled
116      * it.  Upon return, the application no longer has access to the
117      * protected device policy manager APIs.  You will generally
118      * handle this in {@link DeviceAdminReceiver#onDisabled(Context, Intent)}.  Note
119      * that this action will be
120      * sent the receiver regardless of whether it is explicitly listed in
121      * its intent filter.
122      */
123     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
124     @BroadcastBehavior(explicitOnly = true)
125     public static final String ACTION_DEVICE_ADMIN_DISABLED
126             = "android.app.action.DEVICE_ADMIN_DISABLED";
127 
128     /**
129      * Action sent to a device administrator when the user has changed the password of their device
130      * or profile challenge.  You can at this point check the characteristics
131      * of the new password with {@link DevicePolicyManager#isActivePasswordSufficient()
132      * DevicePolicyManager.isActivePasswordSufficient()}.
133      * You will generally
134      * handle this in {@link DeviceAdminReceiver#onPasswordChanged(Context, Intent, UserHandle)}.
135      *
136      * <p>The calling device admin must have requested
137      * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to receive
138      * this broadcast.
139      */
140     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
141     @BroadcastBehavior(explicitOnly = true)
142     public static final String ACTION_PASSWORD_CHANGED
143             = "android.app.action.ACTION_PASSWORD_CHANGED";
144 
145     /**
146      * Action sent to a device administrator when the user has entered an incorrect device
147      * or profile challenge password.  You can at this point check the
148      * number of failed password attempts there have been with
149      * {@link DevicePolicyManager#getCurrentFailedPasswordAttempts
150      * DevicePolicyManager.getCurrentFailedPasswordAttempts()}.  You will generally
151      * handle this in {@link DeviceAdminReceiver#onPasswordFailed(Context, Intent, UserHandle)}.
152      *
153      * <p>The calling device admin must have requested
154      * {@link DeviceAdminInfo#USES_POLICY_WATCH_LOGIN} to receive
155      * this broadcast.
156      */
157     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
158     @BroadcastBehavior(explicitOnly = true)
159     public static final String ACTION_PASSWORD_FAILED
160             = "android.app.action.ACTION_PASSWORD_FAILED";
161 
162     /**
163      * Action sent to a device administrator when the user has successfully entered their device
164      * or profile challenge password, after failing one or more times.  You will generally
165      * handle this in {@link DeviceAdminReceiver#onPasswordSucceeded(Context, Intent, UserHandle)}.
166      *
167      * <p>The calling device admin must have requested
168      * {@link DeviceAdminInfo#USES_POLICY_WATCH_LOGIN} to receive
169      * this broadcast.
170      */
171     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
172     @BroadcastBehavior(explicitOnly = true)
173     public static final String ACTION_PASSWORD_SUCCEEDED
174             = "android.app.action.ACTION_PASSWORD_SUCCEEDED";
175 
176     /**
177      * Action periodically sent to a device administrator when the device or profile challenge
178      * password is expiring.  You will generally
179      * handle this in {@link DeviceAdminReceiver#onPasswordExpiring(Context, Intent, UserHandle)}.
180      *
181      * <p>The calling device admin must have requested
182      * {@link DeviceAdminInfo#USES_POLICY_EXPIRE_PASSWORD} to receive
183      * this broadcast.
184      */
185     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
186     @BroadcastBehavior(explicitOnly = true)
187     public static final String ACTION_PASSWORD_EXPIRING
188             = "android.app.action.ACTION_PASSWORD_EXPIRING";
189 
190     /**
191      * Action sent to a device administrator to notify that the device is entering
192      * lock task mode.  The extra {@link #EXTRA_LOCK_TASK_PACKAGE}
193      * will describe the package using 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     @BroadcastBehavior(explicitOnly = true)
202     public static final String ACTION_LOCK_TASK_ENTERING
203             = "android.app.action.LOCK_TASK_ENTERING";
204 
205     /**
206      * Action sent to a device administrator to notify that the device is exiting
207      * lock task mode.
208      *
209      * <p>The calling device admin must be the device owner or profile
210      * owner to receive this broadcast.
211      *
212      * @see DevicePolicyManager#isLockTaskPermitted(String)
213      */
214     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
215     @BroadcastBehavior(explicitOnly = true)
216     public static final String ACTION_LOCK_TASK_EXITING
217             = "android.app.action.LOCK_TASK_EXITING";
218 
219     /**
220      * A string containing the name of the package entering lock task mode.
221      *
222      * @see #ACTION_LOCK_TASK_ENTERING
223      */
224     public static final String EXTRA_LOCK_TASK_PACKAGE =
225             "android.app.extra.LOCK_TASK_PACKAGE";
226 
227     /**
228      * Broadcast Action: This broadcast is sent to indicate that provisioning of a managed profile
229      * or managed device has completed successfully.
230      *
231      * <p>The broadcast is limited to the profile that will be managed by the application that
232      * requested provisioning. In the device owner case the profile is the primary user.
233      * The broadcast will also be limited to the {@link DeviceAdminReceiver} component
234      * specified in the original intent or NFC bump that started the provisioning process
235      * (see {@link DevicePolicyManager#ACTION_PROVISION_MANAGED_PROFILE
236      * DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE}).
237      *
238      * <p>A device admin application which listens to this intent can find out if the device was
239      * provisioned for the device owner or profile owner case by calling respectively
240      * {@link android.app.admin.DevicePolicyManager#isDeviceOwnerApp} and
241      * {@link android.app.admin.DevicePolicyManager#isProfileOwnerApp}. You will generally handle
242      * this in {@link DeviceAdminReceiver#onProfileProvisioningComplete}.
243      *
244      * @see DevicePolicyManager#ACTION_PROVISIONING_SUCCESSFUL
245      */
246     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
247     @BroadcastBehavior(explicitOnly = true)
248     public static final String ACTION_PROFILE_PROVISIONING_COMPLETE =
249             "android.app.action.PROFILE_PROVISIONING_COMPLETE";
250 
251     /**
252      * Action sent to a device administrator to notify that the device user
253      * has declined sharing a bugreport.
254      *
255      * <p>The calling device admin must be the device owner to receive this broadcast.
256      * @see DevicePolicyManager#requestBugreport
257      * @hide
258      */
259     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
260     @BroadcastBehavior(explicitOnly = true)
261     public static final String ACTION_BUGREPORT_SHARING_DECLINED =
262             "android.app.action.BUGREPORT_SHARING_DECLINED";
263 
264     /**
265      * Action sent to a device administrator to notify that the collection of a bugreport
266      * has failed.
267      *
268      * <p>The calling device admin must be the device owner to receive this broadcast.
269      * @see DevicePolicyManager#requestBugreport
270      * @hide
271      */
272     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
273     @BroadcastBehavior(explicitOnly = true)
274     public static final String ACTION_BUGREPORT_FAILED = "android.app.action.BUGREPORT_FAILED";
275 
276     /**
277      * Action sent to a device administrator to share the bugreport.
278      *
279      * <p>The calling device admin must be the device owner to receive this broadcast.
280      * @see DevicePolicyManager#requestBugreport
281      * @hide
282      */
283     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
284     @BroadcastBehavior(explicitOnly = true)
285     public static final String ACTION_BUGREPORT_SHARE =
286             "android.app.action.BUGREPORT_SHARE";
287 
288     /**
289      * Broadcast action: notify that a new batch of security logs is ready to be collected.
290      * @hide
291      */
292     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
293     @BroadcastBehavior(explicitOnly = true)
294     public static final String ACTION_SECURITY_LOGS_AVAILABLE
295             = "android.app.action.SECURITY_LOGS_AVAILABLE";
296 
297     /**
298      * Broadcast action: notify that a new batch of network logs is ready to be collected.
299      * @see DeviceAdminReceiver#onNetworkLogsAvailable
300      * @hide
301      */
302     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
303     @BroadcastBehavior(explicitOnly = true)
304     public static final String ACTION_NETWORK_LOGS_AVAILABLE
305             = "android.app.action.NETWORK_LOGS_AVAILABLE";
306 
307     /**
308      * A {@code long} containing a token of the current batch of network logs, that has to be used
309      * to retrieve the batch of logs by the device owner.
310      *
311      * @see #ACTION_NETWORK_LOGS_AVAILABLE
312      * @see DevicePolicyManager#retrieveNetworkLogs
313      * @hide
314      */
315     public static final String EXTRA_NETWORK_LOGS_TOKEN =
316             "android.app.extra.EXTRA_NETWORK_LOGS_TOKEN";
317 
318     /**
319      * An {@code int} count representing a total count of network logs inside the current batch of
320      * network logs.
321      *
322      * @see #ACTION_NETWORK_LOGS_AVAILABLE
323      * @hide
324      */
325     public static final String EXTRA_NETWORK_LOGS_COUNT =
326             "android.app.extra.EXTRA_NETWORK_LOGS_COUNT";
327 
328     /**
329      * Broadcast action: notify the device owner that a user or profile has been added.
330      * Carries an extra {@link Intent#EXTRA_USER} that has the {@link UserHandle} of
331      * the new user.
332      * @hide
333      */
334     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
335     @BroadcastBehavior(explicitOnly = true)
336     public static final String ACTION_USER_ADDED = "android.app.action.USER_ADDED";
337 
338     /**
339      * Broadcast action: notify the device owner that a user or profile has been removed.
340      * Carries an extra {@link Intent#EXTRA_USER} that has the {@link UserHandle} of
341      * the user.
342      * @hide
343      */
344     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
345     @BroadcastBehavior(explicitOnly = true)
346     public static final String ACTION_USER_REMOVED = "android.app.action.USER_REMOVED";
347 
348     /**
349      * Broadcast action: notify the device owner that a user or profile has been started.
350      * Carries an extra {@link Intent#EXTRA_USER} that has the {@link UserHandle} of
351      * the user.
352      * @hide
353      */
354     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
355     @BroadcastBehavior(explicitOnly = true)
356     public static final String ACTION_USER_STARTED = "android.app.action.USER_STARTED";
357 
358     /**
359      * Broadcast action: notify the device owner that a user or profile has been stopped.
360      * Carries an extra {@link Intent#EXTRA_USER} that has the {@link UserHandle} of
361      * the user.
362      * @hide
363      */
364     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
365     @BroadcastBehavior(explicitOnly = true)
366     public static final String ACTION_USER_STOPPED = "android.app.action.USER_STOPPED";
367 
368     /**
369      * Broadcast action: notify the device owner that a user or profile has been switched to.
370      * Carries an extra {@link Intent#EXTRA_USER} that has the {@link UserHandle} of
371      * the user.
372      * @hide
373      */
374     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
375     @BroadcastBehavior(explicitOnly = true)
376     public static final String ACTION_USER_SWITCHED = "android.app.action.USER_SWITCHED";
377 
378     /**
379      * A string containing the SHA-256 hash of the bugreport file.
380      *
381      * @see #ACTION_BUGREPORT_SHARE
382      * @hide
383      */
384     public static final String EXTRA_BUGREPORT_HASH = "android.app.extra.BUGREPORT_HASH";
385 
386     /**
387      * An {@code int} failure code representing the reason of the bugreport failure. One of
388      * {@link #BUGREPORT_FAILURE_FAILED_COMPLETING}
389      * or {@link #BUGREPORT_FAILURE_FILE_NO_LONGER_AVAILABLE}
390      *
391      * @see #ACTION_BUGREPORT_FAILED
392      * @hide
393      */
394     public static final String EXTRA_BUGREPORT_FAILURE_REASON =
395             "android.app.extra.BUGREPORT_FAILURE_REASON";
396 
397     /**
398      * An interface representing reason of bugreport failure.
399      *
400      * @see #EXTRA_BUGREPORT_FAILURE_REASON
401      * @hide
402      */
403     @Retention(RetentionPolicy.SOURCE)
404     @IntDef(prefix = { "BUGREPORT_FAILURE_" }, value = {
405             BUGREPORT_FAILURE_FAILED_COMPLETING,
406             BUGREPORT_FAILURE_FILE_NO_LONGER_AVAILABLE
407     })
408     public @interface BugreportFailureCode {}
409 
410     /**
411      * Bugreport completion process failed.
412      *
413      * <p>If this error code is received, the requesting of bugreport can be retried.
414      * @see DevicePolicyManager#requestBugreport
415      */
416     public static final int BUGREPORT_FAILURE_FAILED_COMPLETING = 0;
417 
418     /**
419      * Bugreport has been created, but is no longer available for collection.
420      *
421      * <p>This error likely occurs because the user of the device hasn't consented to share
422      * the bugreport for a long period after its creation.
423      *
424      * <p>If this error code is received, the requesting of bugreport can be retried.
425      * @see DevicePolicyManager#requestBugreport
426      */
427     public static final int BUGREPORT_FAILURE_FILE_NO_LONGER_AVAILABLE = 1;
428 
429     /** @hide */
430     public static final String ACTION_CHOOSE_PRIVATE_KEY_ALIAS =
431             "android.app.action.CHOOSE_PRIVATE_KEY_ALIAS";
432 
433     /** @hide */
434     public static final String EXTRA_CHOOSE_PRIVATE_KEY_SENDER_UID =
435             "android.app.extra.CHOOSE_PRIVATE_KEY_SENDER_UID";
436 
437     /** @hide */
438     public static final String EXTRA_CHOOSE_PRIVATE_KEY_URI =
439             "android.app.extra.CHOOSE_PRIVATE_KEY_URI";
440 
441     /** @hide */
442     public static final String EXTRA_CHOOSE_PRIVATE_KEY_ALIAS =
443             "android.app.extra.CHOOSE_PRIVATE_KEY_ALIAS";
444 
445     /** @hide */
446     public static final String EXTRA_CHOOSE_PRIVATE_KEY_RESPONSE =
447             "android.app.extra.CHOOSE_PRIVATE_KEY_RESPONSE";
448 
449     /**
450      * Broadcast action: notify device owner that there is a pending system update.
451      * @hide
452      */
453     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
454     @BroadcastBehavior(explicitOnly = true)
455     public static final String ACTION_NOTIFY_PENDING_SYSTEM_UPDATE =
456             "android.app.action.NOTIFY_PENDING_SYSTEM_UPDATE";
457 
458     /**
459      * A long type extra for {@link #onSystemUpdatePending} recording the system time as given by
460      * {@link System#currentTimeMillis()} when the current pending system update is first available.
461      * @hide
462      */
463     public static final String EXTRA_SYSTEM_UPDATE_RECEIVED_TIME =
464             "android.app.extra.SYSTEM_UPDATE_RECEIVED_TIME";
465 
466     /**
467      * Name under which a DevicePolicy component publishes information
468      * about itself.  This meta-data must reference an XML resource containing
469      * a device-admin tag.
470      */
471     //  TO DO: describe syntax.
472     public static final String DEVICE_ADMIN_META_DATA = "android.app.device_admin";
473 
474     /**
475      * Broadcast action: notify the newly transferred administrator that the transfer
476      * from the original administrator was successful.
477      *
478      * @hide
479      */
480     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
481     public static final String ACTION_TRANSFER_OWNERSHIP_COMPLETE =
482             "android.app.action.TRANSFER_OWNERSHIP_COMPLETE";
483 
484     /**
485      * Broadcast action: notify the device owner that the ownership of one of its affiliated
486      * profiles is transferred.
487      *
488      * @hide
489      */
490     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
491     public static final String ACTION_AFFILIATED_PROFILE_TRANSFER_OWNERSHIP_COMPLETE =
492             "android.app.action.AFFILIATED_PROFILE_TRANSFER_OWNERSHIP_COMPLETE";
493 
494     /**
495      * A {@link android.os.Parcelable} extra of type {@link android.os.PersistableBundle} that
496      * allows a mobile device management application to pass data to the management application
497      * instance after owner transfer.
498      *
499      * <p>If the transfer is successful, the new owner receives the data in
500      * {@link DeviceAdminReceiver#onTransferOwnershipComplete(Context, PersistableBundle)}.
501      * The bundle is not changed during the ownership transfer.
502      *
503      * @see DevicePolicyManager#transferOwnership(ComponentName, ComponentName, PersistableBundle)
504      */
505     public static final String EXTRA_TRANSFER_OWNERSHIP_ADMIN_EXTRAS_BUNDLE =
506             "android.app.extra.TRANSFER_OWNERSHIP_ADMIN_EXTRAS_BUNDLE";
507 
508     private DevicePolicyManager mManager;
509     private ComponentName mWho;
510 
511     /**
512      * Retrieve the DevicePolicyManager interface for this administrator to work
513      * with the system.
514      */
getManager(Context context)515     public DevicePolicyManager getManager(Context context) {
516         if (mManager != null) {
517             return mManager;
518         }
519         mManager = (DevicePolicyManager)context.getSystemService(
520                 Context.DEVICE_POLICY_SERVICE);
521         return mManager;
522     }
523 
524     /**
525      * Retrieve the ComponentName describing who this device administrator is, for
526      * use in {@link DevicePolicyManager} APIs that require the administrator to
527      * identify itself.
528      */
getWho(Context context)529     public ComponentName getWho(Context context) {
530         if (mWho != null) {
531             return mWho;
532         }
533         mWho = new ComponentName(context, getClass());
534         return mWho;
535     }
536 
537     /**
538      * Called after the administrator is first enabled, as a result of
539      * receiving {@link #ACTION_DEVICE_ADMIN_ENABLED}.  At this point you
540      * can use {@link DevicePolicyManager} to set your desired policies.
541      *
542      * <p> If the admin is activated by a device owner, then the intent
543      * may contain private extras that are relevant to user setup.
544      * {@see DevicePolicyManager#createAndManageUser(ComponentName, String, ComponentName,
545      *      PersistableBundle, int)}
546      *
547      * @param context The running context as per {@link #onReceive}.
548      * @param intent The received intent as per {@link #onReceive}.
549      */
onEnabled(Context context, Intent intent)550     public void onEnabled(Context context, Intent intent) {
551     }
552 
553     /**
554      * Called when the user has asked to disable the administrator, as a result of
555      * receiving {@link #ACTION_DEVICE_ADMIN_DISABLE_REQUESTED}, giving you
556      * a chance to present a warning message to them.  The message is returned
557      * as the result; if null is returned (the default implementation), no
558      * message will be displayed.
559      * @param context The running context as per {@link #onReceive}.
560      * @param intent The received intent as per {@link #onReceive}.
561      * @return Return the warning message to display to the user before
562      * being disabled; if null is returned, no message is displayed.
563      */
onDisableRequested(Context context, Intent intent)564     public CharSequence onDisableRequested(Context context, Intent intent) {
565         return null;
566     }
567 
568     /**
569      * Called prior to the administrator being disabled, as a result of
570      * receiving {@link #ACTION_DEVICE_ADMIN_DISABLED}.  Upon return, you
571      * can no longer use the protected parts of the {@link DevicePolicyManager}
572      * API.
573      * @param context The running context as per {@link #onReceive}.
574      * @param intent The received intent as per {@link #onReceive}.
575      */
onDisabled(Context context, Intent intent)576     public void onDisabled(Context context, Intent intent) {
577     }
578 
579     /**
580      * Called after the user has changed their device or profile challenge password, as a result of
581      * receiving {@link #ACTION_PASSWORD_CHANGED}.  At this point you
582      * can use {@link DevicePolicyManager#getPasswordQuality(android.content.ComponentName)}
583      * to retrieve the active password characteristics.
584      * @param context The running context as per {@link #onReceive}.
585      * @param intent The received intent as per {@link #onReceive}.
586      *
587      * @deprecated From {@link android.os.Build.VERSION_CODES#O}, use
588      *             {@link #onPasswordChanged(Context, Intent, UserHandle)} instead.
589      */
590     @Deprecated
onPasswordChanged(Context context, Intent intent)591     public void onPasswordChanged(Context context, Intent intent) {
592     }
593 
594     /**
595      * Called after the user has changed their device or profile challenge password, as a result of
596      * receiving {@link #ACTION_PASSWORD_CHANGED}.  At this point you
597      * can use {@link DevicePolicyManager#getPasswordQuality(android.content.ComponentName)}
598      * to retrieve the active password characteristics.
599      * @param context The running context as per {@link #onReceive}.
600      * @param intent The received intent as per {@link #onReceive}.
601      * @param user The user or profile for whom the password changed. To see whether this
602      *        user is the current profile or a parent user, check for equality with
603      *        {@link Process#myUserHandle}.
604      */
onPasswordChanged(Context context, Intent intent, UserHandle user)605     public void onPasswordChanged(Context context, Intent intent, UserHandle user) {
606         onPasswordChanged(context, intent);
607     }
608 
609     /**
610      * Called after the user has failed at entering their device or profile challenge password,
611      * as a result of receiving {@link #ACTION_PASSWORD_FAILED}.  At this point you can use
612      * {@link DevicePolicyManager#getCurrentFailedPasswordAttempts()} to retrieve the number of
613      * failed password attempts.
614      * @param context The running context as per {@link #onReceive}.
615      * @param intent The received intent as per {@link #onReceive}.
616      *
617      * @deprecated From {@link android.os.Build.VERSION_CODES#O}, use
618      *             {@link #onPasswordFailed(Context, Intent, UserHandle)} instead.
619      */
620     @Deprecated
onPasswordFailed(Context context, Intent intent)621     public void onPasswordFailed(Context context, Intent intent) {
622     }
623 
624     /**
625      * Called after the user has failed at entering their device or profile challenge password,
626      * as a result of receiving {@link #ACTION_PASSWORD_FAILED}.  At this point you can use
627      * {@link DevicePolicyManager#getCurrentFailedPasswordAttempts()} to retrieve the number of
628      * failed password attempts.
629      * @param context The running context as per {@link #onReceive}.
630      * @param intent The received intent as per {@link #onReceive}.
631      * @param user The user or profile for whom the password check failed. To see whether this
632      *        user is the current profile or a parent user, check for equality with
633      *        {@link Process#myUserHandle}.
634      */
onPasswordFailed(Context context, Intent intent, UserHandle user)635     public void onPasswordFailed(Context context, Intent intent, UserHandle user) {
636         onPasswordFailed(context, intent);
637     }
638 
639     /**
640      * Called after the user has succeeded at entering their device or profile challenge password,
641      * as a result of receiving {@link #ACTION_PASSWORD_SUCCEEDED}.  This will
642      * only be received the first time they succeed after having previously
643      * failed.
644      * @param context The running context as per {@link #onReceive}.
645      * @param intent The received intent as per {@link #onReceive}.
646      *
647      * @deprecated From {@link android.os.Build.VERSION_CODES#O}, use
648      *             {@link #onPasswordSucceeded(Context, Intent, UserHandle)} instead.
649      */
650     @Deprecated
onPasswordSucceeded(Context context, Intent intent)651     public void onPasswordSucceeded(Context context, Intent intent) {
652     }
653 
654     /**
655      * Called after the user has succeeded at entering their device or profile challenge password,
656      * as a result of receiving {@link #ACTION_PASSWORD_SUCCEEDED}.  This will
657      * only be received the first time they succeed after having previously
658      * failed.
659      * @param context The running context as per {@link #onReceive}.
660      * @param intent The received intent as per {@link #onReceive}.
661      * @param user The user of profile for whom the password check succeeded.  To see whether this
662      *        user is the current profile or a parent user, check for equality with
663      *        {@link Process#myUserHandle}.
664      */
onPasswordSucceeded(Context context, Intent intent, UserHandle user)665     public void onPasswordSucceeded(Context context, Intent intent, UserHandle user) {
666         onPasswordSucceeded(context, intent);
667     }
668 
669     /**
670      * Called periodically when the device or profile challenge password is about to expire
671      * or has expired.  It will typically be called at these times: on device boot, once per day
672      * before the password expires, and at the time when the password expires.
673      *
674      * <p>If the password is not updated by the user, this method will continue to be called
675      * once per day until the password is changed or the device admin disables password expiration.
676      *
677      * <p>The admin will typically post a notification requesting the user to change their password
678      * in response to this call. The actual password expiration time can be obtained by calling
679      * {@link DevicePolicyManager#getPasswordExpiration(ComponentName) }
680      *
681      * <p>The admin should be sure to take down any notifications it posted in response to this call
682      * when it receives {@link DeviceAdminReceiver#onPasswordChanged(Context, Intent) }.
683      *
684      * @param context The running context as per {@link #onReceive}.
685      * @param intent The received intent as per {@link #onReceive}.
686      *
687      * @deprecated From {@link android.os.Build.VERSION_CODES#O}, use
688      *             {@link #onPasswordExpiring(Context, Intent, UserHandle)} instead.
689      */
690     @Deprecated
onPasswordExpiring(Context context, Intent intent)691     public void onPasswordExpiring(Context context, Intent intent) {
692     }
693 
694     /**
695      * Called periodically when the device or profile challenge password is about to expire
696      * or has expired.  It will typically be called at these times: on device boot, once per day
697      * before the password expires, and at the time when the password expires.
698      *
699      * <p>If the password is not updated by the user, this method will continue to be called
700      * once per day until the password is changed or the device admin disables password expiration.
701      *
702      * <p>The admin will typically post a notification requesting the user to change their password
703      * in response to this call. The actual password expiration time can be obtained by calling
704      * {@link DevicePolicyManager#getPasswordExpiration(ComponentName) }
705      *
706      * <p>The admin should be sure to take down any notifications it posted in response to this call
707      * when it receives {@link DeviceAdminReceiver#onPasswordChanged(Context, Intent, UserHandle) }.
708      *
709      * @param context The running context as per {@link #onReceive}.
710      * @param intent The received intent as per {@link #onReceive}.
711      * @param user The user or profile for whom the password is expiring. To see whether this
712      *        user is the current profile or a parent user, check for equality with
713      *        {@link Process#myUserHandle}.
714      */
onPasswordExpiring(Context context, Intent intent, UserHandle user)715     public void onPasswordExpiring(Context context, Intent intent, UserHandle user) {
716         onPasswordExpiring(context, intent);
717     }
718 
719     /**
720      * Called when provisioning of a managed profile or managed device has completed successfully.
721      *
722      * <p> As a prerequisite for the execution of this callback the {@link DeviceAdminReceiver} has
723      * to declare an intent filter for {@link #ACTION_PROFILE_PROVISIONING_COMPLETE}.
724      * Its component must also be specified in the {@link DevicePolicyManager#EXTRA_DEVICE_ADMIN}
725      * of the {@link DevicePolicyManager#ACTION_PROVISION_MANAGED_PROFILE} intent that started the
726      * managed provisioning.
727      *
728      * <p>When provisioning of a managed profile is complete, the managed profile is hidden until
729      * the profile owner calls {@link DevicePolicyManager#setProfileEnabled(ComponentName admin)}.
730      * Typically a profile owner will enable the profile when it has finished any additional setup
731      * such as adding an account by using the {@link AccountManager} and calling APIs to bring the
732      * profile into the desired state.
733      *
734      * <p> Note that provisioning completes without waiting for any server interactions, so the
735      * profile owner needs to wait for data to be available if required (e.g. Android device IDs or
736      * other data that is set as a result of server interactions).
737      *
738      * <p>From version {@link android.os.Build.VERSION_CODES#O}, when managed provisioning has
739      * completed, along with this callback the activity intent
740      * {@link DevicePolicyManager#ACTION_PROVISIONING_SUCCESSFUL} will also be sent to the same
741      * application.
742      *
743      * @param context The running context as per {@link #onReceive}.
744      * @param intent The received intent as per {@link #onReceive}.
745      */
onProfileProvisioningComplete(Context context, Intent intent)746     public void onProfileProvisioningComplete(Context context, Intent intent) {
747     }
748 
749     /**
750      * Called during provisioning of a managed device to allow the device initializer to perform
751      * user setup steps.
752      *
753      * @param context The running context as per {@link #onReceive}.
754      * @param intent The received intent as per {@link #onReceive}.
755      * @deprecated Do not use
756      */
757     @Deprecated
758     @SystemApi
onReadyForUserInitialization(Context context, Intent intent)759     public void onReadyForUserInitialization(Context context, Intent intent) {
760     }
761 
762     /**
763      * Called when a device is entering lock task mode.
764      *
765      * @param context The running context as per {@link #onReceive}.
766      * @param intent The received intent as per {@link #onReceive}.
767      * @param pkg If entering, the authorized package using lock task mode, otherwise null.
768      */
onLockTaskModeEntering(Context context, Intent intent, String pkg)769     public void onLockTaskModeEntering(Context context, Intent intent, String pkg) {
770     }
771 
772     /**
773      * Called when a device is exiting lock task mode.
774      *
775      * @param context The running context as per {@link #onReceive}.
776      * @param intent The received intent as per {@link #onReceive}.
777      */
onLockTaskModeExiting(Context context, Intent intent)778     public void onLockTaskModeExiting(Context context, Intent intent) {
779     }
780 
781     /**
782      * Allows this receiver to select the alias for a private key and certificate pair for
783      * authentication. If this method returns null, the default {@link android.app.Activity} will be
784      * shown that lets the user pick a private key and certificate pair.
785      *
786      * @param context The running context as per {@link #onReceive}.
787      * @param intent The received intent as per {@link #onReceive}.
788      * @param uid The uid asking for the private key and certificate pair.
789      * @param uri The URI to authenticate, may be null.
790      * @param alias The alias preselected by the client, or null.
791      * @return The private key alias to return and grant access to.
792      * @see KeyChain#choosePrivateKeyAlias
793      */
onChoosePrivateKeyAlias(Context context, Intent intent, int uid, Uri uri, String alias)794     public String onChoosePrivateKeyAlias(Context context, Intent intent, int uid, Uri uri,
795             String alias) {
796         return null;
797     }
798 
799     /**
800      * Called when the information about a pending system update is available.
801      *
802      * <p>Allows the receiver to be notified when information about a pending system update is
803      * available from the system update service. The same pending system update can trigger multiple
804      * calls to this method, so it is necessary to examine the incoming parameters for details about
805      * the update.
806      *
807      * <p>This callback is only applicable to device owners and profile owners.
808      *
809      * <p>To get further information about a pending system update (for example, whether or not the
810      * update is a security patch), the device owner or profile owner can call
811      * {@link DevicePolicyManager#getPendingSystemUpdate}.
812      *
813      * @param context The running context as per {@link #onReceive}.
814      * @param intent The received intent as per {@link #onReceive}.
815      * @param receivedTime The time as given by {@link System#currentTimeMillis()} indicating when
816      *        the current pending update was first available. -1 if no pending update is available.
817      * @see DevicePolicyManager#getPendingSystemUpdate
818      */
onSystemUpdatePending(Context context, Intent intent, long receivedTime)819     public void onSystemUpdatePending(Context context, Intent intent, long receivedTime) {
820     }
821 
822     /**
823      * Called when sharing a bugreport has been cancelled by the user of the device.
824      *
825      * <p>This callback is only applicable to device owners.
826      *
827      * @param context The running context as per {@link #onReceive}.
828      * @param intent The received intent as per {@link #onReceive}.
829      * @see DevicePolicyManager#requestBugreport
830      */
onBugreportSharingDeclined(Context context, Intent intent)831     public void onBugreportSharingDeclined(Context context, Intent intent) {
832     }
833 
834     /**
835      * Called when the bugreport has been shared with the device administrator app.
836      *
837      * <p>This callback is only applicable to device owners.
838      *
839      * @param context The running context as per {@link #onReceive}.
840      * @param intent The received intent as per {@link #onReceive}. Contains the URI of
841      * the bugreport file (with MIME type "application/vnd.android.bugreport"), that can be accessed
842      * by calling {@link Intent#getData()}
843      * @param bugreportHash SHA-256 hash of the bugreport file.
844      * @see DevicePolicyManager#requestBugreport
845      */
onBugreportShared(Context context, Intent intent, String bugreportHash)846     public void onBugreportShared(Context context, Intent intent, String bugreportHash) {
847     }
848 
849     /**
850      * Called when the bugreport collection flow has failed.
851      *
852      * <p>This callback is only applicable to device owners.
853      *
854      * @param context The running context as per {@link #onReceive}.
855      * @param intent The received intent as per {@link #onReceive}.
856      * @param failureCode int containing failure code. One of
857      * {@link #BUGREPORT_FAILURE_FAILED_COMPLETING}
858      * or {@link #BUGREPORT_FAILURE_FILE_NO_LONGER_AVAILABLE}
859      * @see DevicePolicyManager#requestBugreport
860      */
onBugreportFailed(Context context, Intent intent, @BugreportFailureCode int failureCode)861     public void onBugreportFailed(Context context, Intent intent,
862             @BugreportFailureCode int failureCode) {
863     }
864 
865     /**
866      * Called when a new batch of security logs can be retrieved.
867      *
868      * <p>If a secondary user or profile is created, this callback won't be received until all users
869      * become affiliated again (even if security logging is enabled).
870      * See {@link DevicePolicyManager#setAffiliationIds}
871      *
872      * <p>This callback will be re-triggered if the logs are not retrieved.
873      *
874      * <p>This callback is only applicable to device owners.
875      *
876      * @param context The running context as per {@link #onReceive}.
877      * @param intent The received intent as per {@link #onReceive}.
878      * @see DevicePolicyManager#retrieveSecurityLogs(ComponentName)
879      */
onSecurityLogsAvailable(Context context, Intent intent)880     public void onSecurityLogsAvailable(Context context, Intent intent) {
881     }
882 
883     /**
884      * Called each time a new batch of network logs can be retrieved. This callback method will only
885      * ever be called when network logging is enabled. The logs can only be retrieved while network
886      * logging is enabled.
887      *
888      * <p>If a secondary user or profile is created, this callback won't be received until all users
889      * become affiliated again (even if network logging is enabled). It will also no longer be
890      * possible to retrieve the network logs batch with the most recent {@code batchToken} provided
891      * by this callback. See {@link DevicePolicyManager#setAffiliationIds}.
892      *
893      * <p>This callback is only applicable to device owners.
894      *
895      * @param context The running context as per {@link #onReceive}.
896      * @param intent The received intent as per {@link #onReceive}.
897      * @param batchToken The token representing the current batch of network logs.
898      * @param networkLogsCount The total count of events in the current batch of network logs.
899      * @see DevicePolicyManager#retrieveNetworkLogs
900      */
onNetworkLogsAvailable(Context context, Intent intent, long batchToken, int networkLogsCount)901     public void onNetworkLogsAvailable(Context context, Intent intent, long batchToken,
902             int networkLogsCount) {
903     }
904 
905     /**
906      * Called when a user or profile is created.
907      *
908      * <p>This callback is only applicable to device owners.
909      *
910      * @param context The running context as per {@link #onReceive}.
911      * @param intent The received intent as per {@link #onReceive}.
912      * @param newUser The {@link UserHandle} of the user that has just been added.
913      */
onUserAdded(Context context, Intent intent, @NonNull UserHandle newUser)914     public void onUserAdded(Context context, Intent intent, @NonNull UserHandle newUser) {
915     }
916 
917     /**
918      * Called when a user or profile is removed.
919      *
920      * <p>This callback is only applicable to device owners.
921      *
922      * @param context The running context as per {@link #onReceive}.
923      * @param intent The received intent as per {@link #onReceive}.
924      * @param removedUser The {@link UserHandle} of the user that has just been removed.
925      */
onUserRemoved(Context context, Intent intent, @NonNull UserHandle removedUser)926     public void onUserRemoved(Context context, Intent intent, @NonNull UserHandle removedUser) {
927     }
928 
929     /**
930      * Called when a user or profile is started.
931      *
932      * <p>This callback is only applicable to device owners.
933      *
934      * @param context The running context as per {@link #onReceive}.
935      * @param intent The received intent as per {@link #onReceive}.
936      * @param startedUser The {@link UserHandle} of the user that has just been started.
937      */
onUserStarted(Context context, Intent intent, @NonNull UserHandle startedUser)938     public void onUserStarted(Context context, Intent intent, @NonNull UserHandle startedUser) {
939     }
940 
941     /**
942      * Called when a user or profile is stopped.
943      *
944      * <p>This callback is only applicable to device owners.
945      *
946      * @param context The running context as per {@link #onReceive}.
947      * @param intent The received intent as per {@link #onReceive}.
948      * @param stoppedUser The {@link UserHandle} of the user that has just been stopped.
949      */
onUserStopped(Context context, Intent intent, @NonNull UserHandle stoppedUser)950     public void onUserStopped(Context context, Intent intent, @NonNull UserHandle stoppedUser) {
951     }
952 
953     /**
954      * Called when a user or profile is switched to.
955      *
956      * <p>This callback is only applicable to device owners.
957      *
958      * @param context The running context as per {@link #onReceive}.
959      * @param intent The received intent as per {@link #onReceive}.
960      * @param switchedUser The {@link UserHandle} of the user that has just been switched to.
961      */
onUserSwitched(Context context, Intent intent, @NonNull UserHandle switchedUser)962     public void onUserSwitched(Context context, Intent intent, @NonNull UserHandle switchedUser) {
963     }
964 
965     /**
966      * Called on the newly assigned owner (either device owner or profile owner) when the ownership
967      * transfer has completed successfully.
968      *
969      * <p> The {@code bundle} parameter allows the original owner to pass data
970      * to the new one.
971      *
972      * @param context the running context as per {@link #onReceive}
973      * @param bundle the data to be passed to the new owner
974      */
onTransferOwnershipComplete(@onNull Context context, @Nullable PersistableBundle bundle)975     public void onTransferOwnershipComplete(@NonNull Context context,
976             @Nullable PersistableBundle bundle) {
977     }
978 
979     /**
980      * Called on the device owner when the ownership of one of its affiliated profiles is
981      * transferred.
982      *
983      * <p>This can be used when transferring both device and profile ownership when using
984      * work profile on a fully managed device. The process would look like this:
985      * <ol>
986      * <li>Transfer profile ownership</li>
987      * <li>The device owner gets notified with this callback</li>
988      * <li>Transfer device ownership</li>
989      * <li>Both profile and device ownerships have been transferred</li>
990      * </ol>
991      *
992      * @param context the running context as per {@link #onReceive}
993      * @param user the {@link UserHandle} of the affiliated user
994      * @see DevicePolicyManager#transferOwnership(ComponentName, ComponentName, PersistableBundle)
995      */
onTransferAffiliatedProfileOwnershipComplete(Context context, UserHandle user)996     public void onTransferAffiliatedProfileOwnershipComplete(Context context, UserHandle user) {
997     }
998 
999     /**
1000      * Intercept standard device administrator broadcasts.  Implementations
1001      * should not override this method; it is better to implement the
1002      * convenience callbacks for each action.
1003      */
1004     @Override
onReceive(Context context, Intent intent)1005     public void onReceive(Context context, Intent intent) {
1006         String action = intent.getAction();
1007 
1008         if (ACTION_PASSWORD_CHANGED.equals(action)) {
1009             onPasswordChanged(context, intent, intent.getParcelableExtra(Intent.EXTRA_USER));
1010         } else if (ACTION_PASSWORD_FAILED.equals(action)) {
1011             onPasswordFailed(context, intent, intent.getParcelableExtra(Intent.EXTRA_USER));
1012         } else if (ACTION_PASSWORD_SUCCEEDED.equals(action)) {
1013             onPasswordSucceeded(context, intent, intent.getParcelableExtra(Intent.EXTRA_USER));
1014         } else if (ACTION_DEVICE_ADMIN_ENABLED.equals(action)) {
1015             onEnabled(context, intent);
1016         } else if (ACTION_DEVICE_ADMIN_DISABLE_REQUESTED.equals(action)) {
1017             CharSequence res = onDisableRequested(context, intent);
1018             if (res != null) {
1019                 Bundle extras = getResultExtras(true);
1020                 extras.putCharSequence(EXTRA_DISABLE_WARNING, res);
1021             }
1022         } else if (ACTION_DEVICE_ADMIN_DISABLED.equals(action)) {
1023             onDisabled(context, intent);
1024         } else if (ACTION_PASSWORD_EXPIRING.equals(action)) {
1025             onPasswordExpiring(context, intent, intent.getParcelableExtra(Intent.EXTRA_USER));
1026         } else if (ACTION_PROFILE_PROVISIONING_COMPLETE.equals(action)) {
1027             onProfileProvisioningComplete(context, intent);
1028         } else if (ACTION_CHOOSE_PRIVATE_KEY_ALIAS.equals(action)) {
1029             int uid = intent.getIntExtra(EXTRA_CHOOSE_PRIVATE_KEY_SENDER_UID, -1);
1030             Uri uri = intent.getParcelableExtra(EXTRA_CHOOSE_PRIVATE_KEY_URI);
1031             String alias = intent.getStringExtra(EXTRA_CHOOSE_PRIVATE_KEY_ALIAS);
1032             String chosenAlias = onChoosePrivateKeyAlias(context, intent, uid, uri, alias);
1033             setResultData(chosenAlias);
1034         } else if (ACTION_LOCK_TASK_ENTERING.equals(action)) {
1035             String pkg = intent.getStringExtra(EXTRA_LOCK_TASK_PACKAGE);
1036             onLockTaskModeEntering(context, intent, pkg);
1037         } else if (ACTION_LOCK_TASK_EXITING.equals(action)) {
1038             onLockTaskModeExiting(context, intent);
1039         } else if (ACTION_NOTIFY_PENDING_SYSTEM_UPDATE.equals(action)) {
1040             long receivedTime = intent.getLongExtra(EXTRA_SYSTEM_UPDATE_RECEIVED_TIME, -1);
1041             onSystemUpdatePending(context, intent, receivedTime);
1042         } else if (ACTION_BUGREPORT_SHARING_DECLINED.equals(action)) {
1043             onBugreportSharingDeclined(context, intent);
1044         } else if (ACTION_BUGREPORT_SHARE.equals(action)) {
1045             String bugreportFileHash = intent.getStringExtra(EXTRA_BUGREPORT_HASH);
1046             onBugreportShared(context, intent, bugreportFileHash);
1047         } else if (ACTION_BUGREPORT_FAILED.equals(action)) {
1048             int failureCode = intent.getIntExtra(EXTRA_BUGREPORT_FAILURE_REASON,
1049                     BUGREPORT_FAILURE_FAILED_COMPLETING);
1050             onBugreportFailed(context, intent, failureCode);
1051         } else if (ACTION_SECURITY_LOGS_AVAILABLE.equals(action)) {
1052             onSecurityLogsAvailable(context, intent);
1053         } else if (ACTION_NETWORK_LOGS_AVAILABLE.equals(action)) {
1054             long batchToken = intent.getLongExtra(EXTRA_NETWORK_LOGS_TOKEN, -1);
1055             int networkLogsCount = intent.getIntExtra(EXTRA_NETWORK_LOGS_COUNT, 0);
1056             onNetworkLogsAvailable(context, intent, batchToken, networkLogsCount);
1057         } else if (ACTION_USER_ADDED.equals(action)) {
1058             onUserAdded(context, intent, intent.getParcelableExtra(Intent.EXTRA_USER));
1059         } else if (ACTION_USER_REMOVED.equals(action)) {
1060             onUserRemoved(context, intent, intent.getParcelableExtra(Intent.EXTRA_USER));
1061         } else if (ACTION_USER_STARTED.equals(action)) {
1062             onUserStarted(context, intent, intent.getParcelableExtra(Intent.EXTRA_USER));
1063         } else if (ACTION_USER_STOPPED.equals(action)) {
1064             onUserStopped(context, intent, intent.getParcelableExtra(Intent.EXTRA_USER));
1065         } else if (ACTION_USER_SWITCHED.equals(action)) {
1066             onUserSwitched(context, intent, intent.getParcelableExtra(Intent.EXTRA_USER));
1067         } else if (ACTION_TRANSFER_OWNERSHIP_COMPLETE.equals(action)) {
1068             PersistableBundle bundle =
1069                     intent.getParcelableExtra(EXTRA_TRANSFER_OWNERSHIP_ADMIN_EXTRAS_BUNDLE);
1070             onTransferOwnershipComplete(context, bundle);
1071         } else if (ACTION_AFFILIATED_PROFILE_TRANSFER_OWNERSHIP_COMPLETE.equals(action)) {
1072             onTransferAffiliatedProfileOwnershipComplete(context,
1073                     intent.getParcelableExtra(Intent.EXTRA_USER));
1074         }
1075     }
1076 }
1077