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

Commit c729bfed authored by Kholoud Mohamed's avatar Kholoud Mohamed
Browse files

send broadcast to admins on financed role changing

Bug: 272483242
Test: btest DeviceManagementCoexistenceTests
Change-Id: I5f4b4f75e85ea71a4b3de2834c0656b92900f38b
parent 46f31feb
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -8049,6 +8049,7 @@ package android.app.admin {
    field public static final String ACTION_APPLICATION_DELEGATION_SCOPES_CHANGED = "android.app.action.APPLICATION_DELEGATION_SCOPES_CHANGED";
    field public static final String ACTION_CHECK_POLICY_COMPLIANCE = "android.app.action.CHECK_POLICY_COMPLIANCE";
    field public static final String ACTION_DEVICE_ADMIN_SERVICE = "android.app.action.DEVICE_ADMIN_SERVICE";
    field public static final String ACTION_DEVICE_FINANCING_STATE_CHANGED = "android.app.admin.action.DEVICE_FINANCING_STATE_CHANGED";
    field public static final String ACTION_DEVICE_OWNER_CHANGED = "android.app.action.DEVICE_OWNER_CHANGED";
    field public static final String ACTION_DEVICE_POLICY_RESOURCE_UPDATED = "android.app.action.DEVICE_POLICY_RESOURCE_UPDATED";
    field public static final String ACTION_GET_PROVISIONING_MODE = "android.app.action.GET_PROVISIONING_MODE";
+22 −0
Original line number Diff line number Diff line
@@ -57,6 +57,7 @@ import static com.android.internal.util.function.pooled.PooledLambda.obtainMessa
import android.Manifest.permission;
import android.accounts.Account;
import android.annotation.BroadcastBehavior;
import android.annotation.CallbackExecutor;
import android.annotation.ColorInt;
import android.annotation.IntDef;
@@ -3998,6 +3999,27 @@ public class DevicePolicyManager {
    public static final String EXTRA_RESOURCE_IDS =
            "android.app.extra.RESOURCE_IDS";
    /**
     * Broadcast Action: Broadcast sent to indicate that the device financing state has changed.
     *
     * <p>This occurs when, for example, a financing kiosk app has been added or removed.
     *
     * <p>To query the current device financing state see {@link #isDeviceFinanced}.
     *
     * <p>This will be delivered to the following apps if they include a receiver for this action
     * in their manifest:
     * <ul>
     *     <li>Device owner admins.
     *     <li>Organization-owned profile owner admins
     *     <li>The supervision app
     *     <li>The device management role holder
     * </ul>
     */
    @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
    @BroadcastBehavior(explicitOnly = true, includeBackground = true)
    public static final String ACTION_DEVICE_FINANCING_STATE_CHANGED =
            "android.app.admin.action.DEVICE_FINANCING_STATE_CHANGED";
    /** Allow the user to choose whether to enable MTE on the device. */
    public static final int MTE_NOT_CONTROLLED_BY_POLICY = 0;
+99 −42
Original line number Diff line number Diff line
@@ -95,6 +95,7 @@ import static android.app.admin.DeviceAdminReceiver.ACTION_COMPLIANCE_ACKNOWLEDG
import static android.app.admin.DeviceAdminReceiver.EXTRA_TRANSFER_OWNERSHIP_ADMIN_EXTRAS_BUNDLE;
import static android.app.admin.DevicePolicyIdentifiers.AUTO_TIMEZONE_POLICY;
import static android.app.admin.DevicePolicyManager.ACTION_CHECK_POLICY_COMPLIANCE;
import static android.app.admin.DevicePolicyManager.ACTION_DEVICE_FINANCING_STATE_CHANGED;
import static android.app.admin.DevicePolicyManager.ACTION_DEVICE_POLICY_RESOURCE_UPDATED;
import static android.app.admin.DevicePolicyManager.ACTION_MANAGED_PROFILE_PROVISIONED;
import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE;
@@ -15440,7 +15441,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
            Slogf.i(LOG_TAG, "Sending %s broadcast to manifest receivers.", intent.getAction());
            broadcastIntentToCrossProfileManifestReceivers(
                    intent, parentHandle, requiresPermission);
            broadcastIntentToDevicePolicyManagerRoleHolder(intent, parentHandle);
            broadcastExplicitIntentToRoleHolder(
                    intent, RoleManager.ROLE_DEVICE_POLICY_MANAGEMENT, parentHandle);
        }
        @Override
@@ -15481,36 +15483,6 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
            }
        }
        private void broadcastIntentToDevicePolicyManagerRoleHolder(
                Intent intent, UserHandle userHandle) {
            final int userId = userHandle.getIdentifier();
            final String packageName = getDevicePolicyManagementRoleHolderPackageName(mContext);
            if (packageName == null) {
                return;
            }
            try {
                final Intent packageIntent = new Intent(intent)
                        .setPackage(packageName);
                final List<ResolveInfo> receivers = mIPackageManager.queryIntentReceivers(
                        packageIntent,
                        /* resolvedType= */ null,
                        STOCK_PM_FLAGS,
                        userId).getList();
                if (receivers.isEmpty()) {
                    return;
                }
                for (ResolveInfo receiver : receivers) {
                    final Intent componentIntent = new Intent(packageIntent)
                            .setComponent(receiver.getComponentInfo().getComponentName())
                            .addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
                    mContext.sendBroadcastAsUser(componentIntent, userHandle);
                }
            } catch (RemoteException ex) {
                Slogf.w(LOG_TAG, "Cannot get list of broadcast receivers for %s because: %s.",
                        intent.getAction(), ex);
            }
        }
        /**
         * Checks whether the package {@code packageName} has the {@code MODIFY_QUIET_MODE}
         * permission granted for the user {@code userId}.
@@ -20718,7 +20690,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
    private void maybeInstallDevicePolicyManagementRoleHolderInUser(int targetUserId) {
        String devicePolicyManagerRoleHolderPackageName =
                getDevicePolicyManagementRoleHolderPackageName(mContext);
                getRoleHolderPackageName(mContext, RoleManager.ROLE_DEVICE_POLICY_MANAGEMENT);
        if (devicePolicyManagerRoleHolderPackageName == null) {
            Slogf.d(LOG_TAG, "No device policy management role holder specified.");
            return;
@@ -20744,14 +20716,24 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
        }
    }
    /**
     * If multiple packages hold the role, returns the first package in the list.
     */
    @Nullable
    private String getRoleHolderPackageName(Context context, String role) {
        return getRoleHolderPackageNameOnUser(context, role, Process.myUserHandle());
    }
    private String getDevicePolicyManagementRoleHolderPackageName(Context context) {
    /**
     * If multiple packages hold the role, returns the first package in the list.
     */
    @Nullable
    private String getRoleHolderPackageNameOnUser(Context context, String role, UserHandle user) {
        RoleManager roleManager = context.getSystemService(RoleManager.class);
        // Calling identity needs to be cleared as this method is used in the permissions checks.
        return mInjector.binderWithCleanCallingIdentity(() -> {
            List<String> roleHolders =
                    roleManager.getRoleHolders(RoleManager.ROLE_DEVICE_POLICY_MANAGEMENT);
            List<String> roleHolders = roleManager.getRoleHoldersAsUser(role, user);
            if (roleHolders.isEmpty()) {
                return null;
            }
@@ -20762,7 +20744,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
    private boolean isCallerDevicePolicyManagementRoleHolder(CallerIdentity caller) {
        int callerUid = caller.getUid();
        String devicePolicyManagementRoleHolderPackageName =
                getDevicePolicyManagementRoleHolderPackageName(mContext);
                getRoleHolderPackageName(mContext, RoleManager.ROLE_DEVICE_POLICY_MANAGEMENT);
        int roleHolderUid = mInjector.getPackageManagerInternal().getPackageUid(
                devicePolicyManagementRoleHolderPackageName, 0, caller.getUserId());
@@ -21830,15 +21812,23 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
        }
        public void register() {
            mRm.addOnRoleHoldersChangedListenerAsUser(mExecutor, this, UserHandle.SYSTEM);
            mRm.addOnRoleHoldersChangedListenerAsUser(mExecutor, this, UserHandle.ALL);
        }
        @Override
        public void onRoleHoldersChanged(@NonNull String roleName, @NonNull UserHandle user) {
            if (!RoleManager.ROLE_DEVICE_POLICY_MANAGEMENT.equals(roleName)) {
            if (RoleManager.ROLE_DEVICE_POLICY_MANAGEMENT.equals(roleName)) {
                handleDevicePolicyManagementRoleChange(user);
                return;
            }
            if (RoleManager.ROLE_FINANCED_DEVICE_KIOSK.equals(roleName)) {
                handleFinancedDeviceKioskRoleChange();
                return;
            }
            String newRoleHolder = getRoleHolder();
        }
        private void handleDevicePolicyManagementRoleChange(UserHandle user) {
            String newRoleHolder = getDeviceManagementRoleHolder(user);
            if (isDefaultRoleHolder(newRoleHolder)) {
                Slogf.i(LOG_TAG,
                        "onRoleHoldersChanged: Default role holder is set, returning early");
@@ -21873,9 +21863,42 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
            }
        }
        private String getRoleHolder() {
            return DevicePolicyManagerService.this.getDevicePolicyManagementRoleHolderPackageName(
                    mContext);
        private void handleFinancedDeviceKioskRoleChange() {
            if (!isDevicePolicyEngineEnabled()) {
                return;
            }
            Slog.i(LOG_TAG, "Handling action " + ACTION_DEVICE_FINANCING_STATE_CHANGED);
            Intent intent = new Intent(ACTION_DEVICE_FINANCING_STATE_CHANGED);
            mInjector.binderWithCleanCallingIdentity(() -> {
                for (UserInfo userInfo : mUserManager.getUsers()) {
                    UserHandle user = userInfo.getUserHandle();
                    broadcastExplicitIntentToRoleHolder(
                            intent, RoleManager.ROLE_SYSTEM_SUPERVISION, user);
                    broadcastExplicitIntentToRoleHolder(
                            intent, RoleManager.ROLE_DEVICE_POLICY_MANAGEMENT, user);
                    ActiveAdmin admin = getDeviceOrProfileOwnerAdminLocked(user.getIdentifier());
                    if (admin == null) {
                        continue;
                    }
                    if (!isProfileOwnerOfOrganizationOwnedDevice(
                            admin.info.getComponent(), user.getIdentifier())
                            && !isDeviceOwner(admin)) {
                        continue;
                    }
                    // Don't send the broadcast twice if the DPC is the same package as the
                    // DMRH
                    if (admin.info.getPackageName().equals(getDeviceManagementRoleHolder(user))) {
                        continue;
                    }
                    broadcastExplicitIntentToPackage(
                            intent, admin.info.getPackageName(), admin.getUserHandle());
                }
            });
        }
        private String getDeviceManagementRoleHolder(UserHandle user) {
            return DevicePolicyManagerService.this.getRoleHolderPackageNameOnUser(
                    mContext, RoleManager.ROLE_DEVICE_POLICY_MANAGEMENT, user);
        }
        private boolean isDefaultRoleHolder(String packageName) {
@@ -21935,6 +21958,40 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
        }
    }
    private void broadcastExplicitIntentToRoleHolder(
            Intent intent, String role, UserHandle userHandle) {
        String packageName = getRoleHolderPackageNameOnUser(mContext, role, userHandle);
        if (packageName == null) {
            return;
        }
        broadcastExplicitIntentToPackage(intent, packageName, userHandle);
    }
    private void broadcastExplicitIntentToPackage(
            Intent intent, String packageName, UserHandle userHandle) {
        int userId = userHandle.getIdentifier();
        if (packageName == null) {
            return;
        }
        Intent packageIntent = new Intent(intent)
                .setPackage(packageName);
        List<ResolveInfo> receivers = mContext.getPackageManager().queryBroadcastReceiversAsUser(
                packageIntent,
                PackageManager.ResolveInfoFlags.of(PackageManager.GET_RECEIVERS),
                userId);
        if (receivers.isEmpty()) {
            Slog.i(LOG_TAG, "Found no receivers to handle intent " + intent
                    + " in package " + packageName);
            return;
        }
        for (ResolveInfo receiver : receivers) {
            Intent componentIntent = new Intent(packageIntent)
                    .setComponent(receiver.getComponentInfo().getComponentName())
                    .addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
            mContext.sendBroadcastAsUser(componentIntent, userHandle);
        }
    }
    @Override
    public List<UserHandle> getPolicyManagedProfiles(@NonNull UserHandle user) {
        Preconditions.checkCallAuthorization(hasCallingOrSelfPermission(