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