/* * Copyright (C) 2010 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.app.admin; import static android.app.admin.DevicePolicyManager.OperationSafetyReason; import android.accounts.AccountManager; import android.annotation.BroadcastBehavior; import android.annotation.IntDef; import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; import android.app.Service; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.net.Uri; import android.os.Bundle; import android.os.PersistableBundle; import android.os.Process; import android.os.UserHandle; import android.security.KeyChain; import android.util.Log; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** * Base class for implementing a device administration component. This * class provides a convenience for interpreting the raw intent actions * that are sent by the system. * *

The callback methods, like the base * {@link BroadcastReceiver#onReceive(Context, Intent) BroadcastReceiver.onReceive()} * method, happen on the main thread of the process. Thus long running * operations must be done on another thread. Note that because a receiver * is done once returning from its receive function, such long-running operations * should probably be done in a {@link Service}. * *

When publishing your DeviceAdmin subclass as a receiver, it must * handle {@link #ACTION_DEVICE_ADMIN_ENABLED} and require the * {@link android.Manifest.permission#BIND_DEVICE_ADMIN} permission. A typical * manifest entry would look like:

* * {@sample development/samples/ApiDemos/AndroidManifest.xml device_admin_declaration} * *

The meta-data referenced here provides addition information specific * to the device administrator, as parsed by the {@link DeviceAdminInfo} class. * A typical file would be:

* * {@sample development/samples/ApiDemos/res/xml/device_admin_sample.xml meta_data} * *
*

Developer Guides

*

For more information about device administration, read the * Device Administration * developer guide.

*
*/ public class DeviceAdminReceiver extends BroadcastReceiver { private static final String TAG = "DevicePolicy"; private static final boolean LOCAL_LOGV = false; /** * This is the primary action that a device administrator must implement to be * allowed to manage a device. This will be set to the receiver * when the user enables it for administration. You will generally * handle this in {@link DeviceAdminReceiver#onEnabled(Context, Intent)}. To be * supported, the receiver must also require the * {@link android.Manifest.permission#BIND_DEVICE_ADMIN} permission so * that other applications can not abuse it. */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) @BroadcastBehavior(explicitOnly = true) public static final String ACTION_DEVICE_ADMIN_ENABLED = "android.app.action.DEVICE_ADMIN_ENABLED"; /** * Action sent to a device administrator when the user has requested to * disable it, but before this has actually been done. This gives you * a chance to supply a message to the user about the impact of * disabling your admin, by setting the extra field * {@link #EXTRA_DISABLE_WARNING} in the result Intent. If not set, * no warning will be displayed. If set, the given text will be shown * to the user before they disable your admin. */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) @BroadcastBehavior(explicitOnly = true) public static final String ACTION_DEVICE_ADMIN_DISABLE_REQUESTED = "android.app.action.DEVICE_ADMIN_DISABLE_REQUESTED"; /** * A CharSequence that can be shown to the user informing them of the * impact of disabling your admin. * * @see #ACTION_DEVICE_ADMIN_DISABLE_REQUESTED */ public static final String EXTRA_DISABLE_WARNING = "android.app.extra.DISABLE_WARNING"; /** * Action sent to a device administrator when the user has disabled * it. Upon return, the application no longer has access to the * protected device policy manager APIs. You will generally * handle this in {@link DeviceAdminReceiver#onDisabled(Context, Intent)}. Note * that this action will be * sent the receiver regardless of whether it is explicitly listed in * its intent filter. */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) @BroadcastBehavior(explicitOnly = true) public static final String ACTION_DEVICE_ADMIN_DISABLED = "android.app.action.DEVICE_ADMIN_DISABLED"; /** * Action sent to a device administrator when the user has changed the password of their device * or profile challenge. You can at this point check the characteristics * of the new password with {@link DevicePolicyManager#isActivePasswordSufficient() * DevicePolicyManager.isActivePasswordSufficient()}. * You will generally * handle this in {@link DeviceAdminReceiver#onPasswordChanged(Context, Intent, UserHandle)}. * *

The calling device admin must have requested * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to receive * this broadcast. */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) @BroadcastBehavior(explicitOnly = true) public static final String ACTION_PASSWORD_CHANGED = "android.app.action.ACTION_PASSWORD_CHANGED"; /** * Action sent to a device administrator when the user has entered an incorrect device * or profile challenge password. You can at this point check the * number of failed password attempts there have been with * {@link DevicePolicyManager#getCurrentFailedPasswordAttempts * DevicePolicyManager.getCurrentFailedPasswordAttempts()}. You will generally * handle this in {@link DeviceAdminReceiver#onPasswordFailed(Context, Intent, UserHandle)}. * *

The calling device admin must have requested * {@link DeviceAdminInfo#USES_POLICY_WATCH_LOGIN} to receive * this broadcast. */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) @BroadcastBehavior(explicitOnly = true) public static final String ACTION_PASSWORD_FAILED = "android.app.action.ACTION_PASSWORD_FAILED"; /** * Action sent to a device administrator when the user has successfully entered their device * or profile challenge password, after failing one or more times. You will generally * handle this in {@link DeviceAdminReceiver#onPasswordSucceeded(Context, Intent, UserHandle)}. * *

The calling device admin must have requested * {@link DeviceAdminInfo#USES_POLICY_WATCH_LOGIN} to receive * this broadcast. */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) @BroadcastBehavior(explicitOnly = true) public static final String ACTION_PASSWORD_SUCCEEDED = "android.app.action.ACTION_PASSWORD_SUCCEEDED"; /** * Action periodically sent to a device administrator when the device or profile challenge * password is expiring. You will generally * handle this in {@link DeviceAdminReceiver#onPasswordExpiring(Context, Intent, UserHandle)}. * *

The calling device admin must have requested * {@link DeviceAdminInfo#USES_POLICY_EXPIRE_PASSWORD} to receive * this broadcast. */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) @BroadcastBehavior(explicitOnly = true) public static final String ACTION_PASSWORD_EXPIRING = "android.app.action.ACTION_PASSWORD_EXPIRING"; /** * Action sent to a device administrator to notify that the device is entering * lock task mode. The extra {@link #EXTRA_LOCK_TASK_PACKAGE} * will describe the package using lock task mode. * *

The calling device admin must be the device owner or profile * owner to receive this broadcast. * * @see DevicePolicyManager#isLockTaskPermitted(String) */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) @BroadcastBehavior(explicitOnly = true) public static final String ACTION_LOCK_TASK_ENTERING = "android.app.action.LOCK_TASK_ENTERING"; /** * Action sent to a device administrator to notify that the device is exiting * lock task mode. * *

The calling device admin must be the device owner or profile * owner to receive this broadcast. * * @see DevicePolicyManager#isLockTaskPermitted(String) */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) @BroadcastBehavior(explicitOnly = true) public static final String ACTION_LOCK_TASK_EXITING = "android.app.action.LOCK_TASK_EXITING"; /** * A string containing the name of the package entering lock task mode. * * @see #ACTION_LOCK_TASK_ENTERING */ public static final String EXTRA_LOCK_TASK_PACKAGE = "android.app.extra.LOCK_TASK_PACKAGE"; /** * Broadcast Action: This broadcast is sent to indicate that provisioning of a managed profile * or managed device has completed successfully. * *

The broadcast is limited to the profile that will be managed by the application that * requested provisioning. In the device owner case the profile is the primary user. * The broadcast will also be limited to the {@link DeviceAdminReceiver} component * specified in the original intent or NFC bump that started the provisioning process * (see {@link DevicePolicyManager#ACTION_PROVISION_MANAGED_PROFILE * DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE}). * *

A device admin application which listens to this intent can find out if the device was * provisioned for the device owner or profile owner case by calling respectively * {@link android.app.admin.DevicePolicyManager#isDeviceOwnerApp} and * {@link android.app.admin.DevicePolicyManager#isProfileOwnerApp}. You will generally handle * this in {@link DeviceAdminReceiver#onProfileProvisioningComplete}. * *

The intent for this action may include the following extras: *