Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d2a73ed2 authored by Robin Lee's avatar Robin Lee
Browse files

Send EXTRA_USER with DevicePolicy lock broadcasts

DeviceAdmins inside profiles may receive broadcasts referring either
to the parent profile or to themselves.

We need a way to differentiate that.

Same commit fixes a bug in DevicePolicyManagerTest where USER_SYSTEM
is returned twice in getProfiles() when called for a managed profile of
USER_SYSTEM. This does not happen in the real API.

Bug: 30185351
Bug: 31001762
Test: runtest -x services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
Change-Id: Iea2735357f4019b2b81b6784e7ea6aead63f2636
parent 8ae761f7
Loading
Loading
Loading
Loading
+8 −4
Original line number Diff line number Diff line
@@ -6024,10 +6024,14 @@ package android.app.admin {
    method public void onLockTaskModeEntering(android.content.Context, android.content.Intent, java.lang.String);
    method public void onLockTaskModeExiting(android.content.Context, android.content.Intent);
    method public void onNetworkLogsAvailable(android.content.Context, android.content.Intent, long, int);
    method public void onPasswordChanged(android.content.Context, android.content.Intent);
    method public void onPasswordExpiring(android.content.Context, android.content.Intent);
    method public void onPasswordFailed(android.content.Context, android.content.Intent);
    method public void onPasswordSucceeded(android.content.Context, android.content.Intent);
    method public deprecated void onPasswordChanged(android.content.Context, android.content.Intent);
    method public void onPasswordChanged(android.content.Context, android.content.Intent, android.os.UserHandle);
    method public deprecated void onPasswordExpiring(android.content.Context, android.content.Intent);
    method public void onPasswordExpiring(android.content.Context, android.content.Intent, android.os.UserHandle);
    method public deprecated void onPasswordFailed(android.content.Context, android.content.Intent);
    method public void onPasswordFailed(android.content.Context, android.content.Intent, android.os.UserHandle);
    method public deprecated void onPasswordSucceeded(android.content.Context, android.content.Intent);
    method public void onPasswordSucceeded(android.content.Context, android.content.Intent, android.os.UserHandle);
    method public void onProfileProvisioningComplete(android.content.Context, android.content.Intent);
    method public deprecated void onReadyForUserInitialization(android.content.Context, android.content.Intent);
    method public void onReceive(android.content.Context, android.content.Intent);
+8 −4
Original line number Diff line number Diff line
@@ -6202,10 +6202,14 @@ package android.app.admin {
    method public void onLockTaskModeEntering(android.content.Context, android.content.Intent, java.lang.String);
    method public void onLockTaskModeExiting(android.content.Context, android.content.Intent);
    method public void onNetworkLogsAvailable(android.content.Context, android.content.Intent, long, int);
    method public void onPasswordChanged(android.content.Context, android.content.Intent);
    method public void onPasswordExpiring(android.content.Context, android.content.Intent);
    method public void onPasswordFailed(android.content.Context, android.content.Intent);
    method public void onPasswordSucceeded(android.content.Context, android.content.Intent);
    method public deprecated void onPasswordChanged(android.content.Context, android.content.Intent);
    method public void onPasswordChanged(android.content.Context, android.content.Intent, android.os.UserHandle);
    method public deprecated void onPasswordExpiring(android.content.Context, android.content.Intent);
    method public void onPasswordExpiring(android.content.Context, android.content.Intent, android.os.UserHandle);
    method public deprecated void onPasswordFailed(android.content.Context, android.content.Intent);
    method public void onPasswordFailed(android.content.Context, android.content.Intent, android.os.UserHandle);
    method public deprecated void onPasswordSucceeded(android.content.Context, android.content.Intent);
    method public void onPasswordSucceeded(android.content.Context, android.content.Intent, android.os.UserHandle);
    method public void onProfileProvisioningComplete(android.content.Context, android.content.Intent);
    method public deprecated void onReadyForUserInitialization(android.content.Context, android.content.Intent);
    method public void onReceive(android.content.Context, android.content.Intent);
+8 −4
Original line number Diff line number Diff line
@@ -6041,10 +6041,14 @@ package android.app.admin {
    method public void onLockTaskModeEntering(android.content.Context, android.content.Intent, java.lang.String);
    method public void onLockTaskModeExiting(android.content.Context, android.content.Intent);
    method public void onNetworkLogsAvailable(android.content.Context, android.content.Intent, long, int);
    method public void onPasswordChanged(android.content.Context, android.content.Intent);
    method public void onPasswordExpiring(android.content.Context, android.content.Intent);
    method public void onPasswordFailed(android.content.Context, android.content.Intent);
    method public void onPasswordSucceeded(android.content.Context, android.content.Intent);
    method public deprecated void onPasswordChanged(android.content.Context, android.content.Intent);
    method public void onPasswordChanged(android.content.Context, android.content.Intent, android.os.UserHandle);
    method public deprecated void onPasswordExpiring(android.content.Context, android.content.Intent);
    method public void onPasswordExpiring(android.content.Context, android.content.Intent, android.os.UserHandle);
    method public deprecated void onPasswordFailed(android.content.Context, android.content.Intent);
    method public void onPasswordFailed(android.content.Context, android.content.Intent, android.os.UserHandle);
    method public deprecated void onPasswordSucceeded(android.content.Context, android.content.Intent);
    method public void onPasswordSucceeded(android.content.Context, android.content.Intent, android.os.UserHandle);
    method public void onProfileProvisioningComplete(android.content.Context, android.content.Intent);
    method public deprecated void onReadyForUserInitialization(android.content.Context, android.content.Intent);
    method public void onReceive(android.content.Context, android.content.Intent);
+95 −8
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Process;
import android.os.UserHandle;
import android.security.KeyChain;

@@ -123,7 +124,7 @@ public class DeviceAdminReceiver extends BroadcastReceiver {
     * of the new password with {@link DevicePolicyManager#isActivePasswordSufficient()
     * DevicePolicyManager.isActivePasswordSufficient()}.
     * You will generally
     * handle this in {@link DeviceAdminReceiver#onPasswordChanged}.
     * handle this in {@link DeviceAdminReceiver#onPasswordChanged(Context, Intent, UserHandle)}.
     *
     * <p>The calling device admin must have requested
     * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to receive
@@ -139,7 +140,7 @@ public class DeviceAdminReceiver extends BroadcastReceiver {
     * number of failed password attempts there have been with
     * {@link DevicePolicyManager#getCurrentFailedPasswordAttempts
     * DevicePolicyManager.getCurrentFailedPasswordAttempts()}.  You will generally
     * handle this in {@link DeviceAdminReceiver#onPasswordFailed}.
     * handle this in {@link DeviceAdminReceiver#onPasswordFailed(Context, Intent, UserHandle)}.
     *
     * <p>The calling device admin must have requested
     * {@link DeviceAdminInfo#USES_POLICY_WATCH_LOGIN} to receive
@@ -152,7 +153,7 @@ public class DeviceAdminReceiver extends BroadcastReceiver {
    /**
     * 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}.
     * handle this in {@link DeviceAdminReceiver#onPasswordSucceeded(Context, Intent, UserHandle)}.
     *
     * <p>The calling device admin must have requested
     * {@link DeviceAdminInfo#USES_POLICY_WATCH_LOGIN} to receive
@@ -165,7 +166,7 @@ public class DeviceAdminReceiver extends BroadcastReceiver {
    /**
     * 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}.
     * handle this in {@link DeviceAdminReceiver#onPasswordExpiring(Context, Intent, UserHandle)}.
     *
     * <p>The calling device admin must have requested
     * {@link DeviceAdminInfo#USES_POLICY_EXPIRE_PASSWORD} to receive
@@ -497,10 +498,29 @@ public class DeviceAdminReceiver extends BroadcastReceiver {
     * to retrieve the active password characteristics.
     * @param context The running context as per {@link #onReceive}.
     * @param intent The received intent as per {@link #onReceive}.
     *
     * @deprecated From {@link android.os.Build.VERSION_CODES#O}, use
     *             {@link #onPasswordChanged(Context, Intent, UserHandle)} instead.
     */
    @Deprecated
    public void onPasswordChanged(Context context, Intent intent) {
    }

    /**
     * Called after the user has changed their device or profile challenge password, as a result of
     * receiving {@link #ACTION_PASSWORD_CHANGED}.  At this point you
     * can use {@link DevicePolicyManager#getPasswordQuality(android.content.ComponentName)}
     * to retrieve the active password characteristics.
     * @param context The running context as per {@link #onReceive}.
     * @param intent The received intent as per {@link #onReceive}.
     * @param user The user or profile for whom the password changed. To see whether this
     *        user is the current profile or a parent user, check for equality with
     *        {@link Process#myUserHandle}.
     */
    public void onPasswordChanged(Context context, Intent intent, UserHandle user) {
        onPasswordChanged(context, intent);
    }

    /**
     * Called after the user has failed at entering their device or profile challenge password,
     * as a result of receiving {@link #ACTION_PASSWORD_FAILED}.  At this point you can use
@@ -508,10 +528,29 @@ public class DeviceAdminReceiver extends BroadcastReceiver {
     * failed password attempts.
     * @param context The running context as per {@link #onReceive}.
     * @param intent The received intent as per {@link #onReceive}.
     *
     * @deprecated From {@link android.os.Build.VERSION_CODES#O}, use
     *             {@link #onPasswordFailed(Context, Intent, UserHandle)} instead.
     */
    @Deprecated
    public void onPasswordFailed(Context context, Intent intent) {
    }

    /**
     * Called after the user has failed at entering their device or profile challenge password,
     * as a result of receiving {@link #ACTION_PASSWORD_FAILED}.  At this point you can use
     * {@link DevicePolicyManager#getCurrentFailedPasswordAttempts()} to retrieve the number of
     * failed password attempts.
     * @param context The running context as per {@link #onReceive}.
     * @param intent The received intent as per {@link #onReceive}.
     * @param user The user or profile for whom the password check failed. To see whether this
     *        user is the current profile or a parent user, check for equality with
     *        {@link Process#myUserHandle}.
     */
    public void onPasswordFailed(Context context, Intent intent, UserHandle user) {
        onPasswordFailed(context, intent);
    }

    /**
     * Called after the user has succeeded at entering their device or profile challenge password,
     * as a result of receiving {@link #ACTION_PASSWORD_SUCCEEDED}.  This will
@@ -519,10 +558,29 @@ public class DeviceAdminReceiver extends BroadcastReceiver {
     * failed.
     * @param context The running context as per {@link #onReceive}.
     * @param intent The received intent as per {@link #onReceive}.
     *
     * @deprecated From {@link android.os.Build.VERSION_CODES#O}, use
     *             {@link #onPasswordSucceeded(Context, Intent, UserHandle)} instead.
     */
    @Deprecated
    public void onPasswordSucceeded(Context context, Intent intent) {
    }

    /**
     * Called after the user has succeeded at entering their device or profile challenge password,
     * as a result of receiving {@link #ACTION_PASSWORD_SUCCEEDED}.  This will
     * only be received the first time they succeed after having previously
     * failed.
     * @param context The running context as per {@link #onReceive}.
     * @param intent The received intent as per {@link #onReceive}.
     * @param user The user of profile for whom the password check succeeded.  To see whether this
     *        user is the current profile or a parent user, check for equality with
     *        {@link Process#myUserHandle}.
     */
    public void onPasswordSucceeded(Context context, Intent intent, UserHandle user) {
        onPasswordSucceeded(context, intent);
    }

    /**
     * Called periodically when the device or profile challenge password is about to expire
     * or has expired.  It will typically be called at these times: on device boot, once per day
@@ -540,10 +598,39 @@ public class DeviceAdminReceiver extends BroadcastReceiver {
     *
     * @param context The running context as per {@link #onReceive}.
     * @param intent The received intent as per {@link #onReceive}.
     *
     * @deprecated From {@link android.os.Build.VERSION_CODES#O}, use
     *             {@link #onPasswordExpiring(Context, Intent, UserHandle)} instead.
     */
    @Deprecated
    public void onPasswordExpiring(Context context, Intent intent) {
    }

    /**
     * Called periodically when the device or profile challenge password is about to expire
     * or has expired.  It will typically be called at these times: on device boot, once per day
     * before the password expires, and at the time when the password expires.
     *
     * <p>If the password is not updated by the user, this method will continue to be called
     * once per day until the password is changed or the device admin disables password expiration.
     *
     * <p>The admin will typically post a notification requesting the user to change their password
     * in response to this call. The actual password expiration time can be obtained by calling
     * {@link DevicePolicyManager#getPasswordExpiration(ComponentName) }
     *
     * <p>The admin should be sure to take down any notifications it posted in response to this call
     * when it receives {@link DeviceAdminReceiver#onPasswordChanged(Context, Intent, UserHandle) }.
     *
     * @param context The running context as per {@link #onReceive}.
     * @param intent The received intent as per {@link #onReceive}.
     * @param user The user or profile for whom the password is expiring. To see whether this
     *        user is the current profile or a parent user, check for equality with
     *        {@link Process#myUserHandle}.
     */
    public void onPasswordExpiring(Context context, Intent intent, UserHandle user) {
        onPasswordExpiring(context, intent);
    }

    /**
     * Called when provisioning of a managed profile or managed device has completed successfully.
     *
@@ -741,11 +828,11 @@ public class DeviceAdminReceiver extends BroadcastReceiver {
        String action = intent.getAction();

        if (ACTION_PASSWORD_CHANGED.equals(action)) {
            onPasswordChanged(context, intent);
            onPasswordChanged(context, intent, intent.getParcelableExtra(Intent.EXTRA_USER));
        } else if (ACTION_PASSWORD_FAILED.equals(action)) {
            onPasswordFailed(context, intent);
            onPasswordFailed(context, intent, intent.getParcelableExtra(Intent.EXTRA_USER));
        } else if (ACTION_PASSWORD_SUCCEEDED.equals(action)) {
            onPasswordSucceeded(context, intent);
            onPasswordSucceeded(context, intent, intent.getParcelableExtra(Intent.EXTRA_USER));
        } else if (ACTION_DEVICE_ADMIN_ENABLED.equals(action)) {
            onEnabled(context, intent);
        } else if (ACTION_DEVICE_ADMIN_DISABLE_REQUESTED.equals(action)) {
@@ -757,7 +844,7 @@ public class DeviceAdminReceiver extends BroadcastReceiver {
        } else if (ACTION_DEVICE_ADMIN_DISABLED.equals(action)) {
            onDisabled(context, intent);
        } else if (ACTION_PASSWORD_EXPIRING.equals(action)) {
            onPasswordExpiring(context, intent);
            onPasswordExpiring(context, intent, intent.getParcelableExtra(Intent.EXTRA_USER));
        } else if (ACTION_PROFILE_PROVISIONING_COMPLETE.equals(action)) {
            onProfileProvisioningComplete(context, intent);
        } else if (ACTION_CHOOSE_PRIVATE_KEY_ALIAS.equals(action)) {
+15 −12
Original line number Diff line number Diff line
@@ -2213,15 +2213,13 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
    /**
     * Send an update to all admins of a user that enforce a specified policy.
     */
    void sendAdminCommandLocked(String action, int reqPolicy, int userHandle) {
    void sendAdminCommandLocked(String action, int reqPolicy, int userHandle, Bundle adminExtras) {
        final DevicePolicyData policy = getUserData(userHandle);
        final int count = policy.mAdminList.size();
        if (count > 0) {
        for (int i = 0; i < count; i++) {
            final ActiveAdmin admin = policy.mAdminList.get(i);
            if (admin.info.usesPolicy(reqPolicy)) {
                    sendAdminCommandLocked(admin, action);
                }
                sendAdminCommandLocked(admin, action, adminExtras, null);
            }
        }
    }
@@ -2231,10 +2229,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
     * enforce a specified policy.
     */
    private void sendAdminCommandToSelfAndProfilesLocked(String action, int reqPolicy,
            int userHandle) {
            int userHandle, Bundle adminExtras) {
        int[] profileIds = mUserManager.getProfileIdsWithDisabled(userHandle);
        for (int profileId : profileIds) {
            sendAdminCommandLocked(action, reqPolicy, profileId);
            sendAdminCommandLocked(action, reqPolicy, profileId, adminExtras);
        }
    }

@@ -2243,10 +2241,12 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
     */
    private void sendAdminCommandForLockscreenPoliciesLocked(
            String action, int reqPolicy, int userHandle) {
        final Bundle extras = new Bundle();
        extras.putParcelable(Intent.EXTRA_USER, UserHandle.of(userHandle));
        if (isSeparateProfileChallengeEnabled(userHandle)) {
            sendAdminCommandLocked(action, reqPolicy, userHandle);
            sendAdminCommandLocked(action, reqPolicy, userHandle, extras);
        } else {
            sendAdminCommandToSelfAndProfilesLocked(action, reqPolicy, userHandle);
            sendAdminCommandToSelfAndProfilesLocked(action, reqPolicy, userHandle, extras);
        }
    }

@@ -2796,6 +2796,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
    }

    private void handlePasswordExpirationNotification(int userHandle) {
        final Bundle adminExtras = new Bundle();
        adminExtras.putParcelable(Intent.EXTRA_USER, UserHandle.of(userHandle));

        synchronized (this) {
            final long now = System.currentTimeMillis();

@@ -2809,7 +2812,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
                        && now >= admin.passwordExpirationDate - EXPIRATION_GRACE_PERIOD_MS
                        && admin.passwordExpirationDate > 0L) {
                    sendAdminCommandLocked(admin,
                            DeviceAdminReceiver.ACTION_PASSWORD_EXPIRING);
                            DeviceAdminReceiver.ACTION_PASSWORD_EXPIRING, adminExtras, null);
                }
            }
            setExpirationAlarmCheckLocked(mContext, userHandle, /* parent */ false);
Loading