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