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

Commit 1cf6480b authored by Irem Uguz's avatar Irem Uguz
Browse files

Update the order of admins in PolicyEnforcementInfo

PolicyEnforcementInfo sorts the admins in constructor in a way that
supervision admin will be first one if it exists. To keep the behaviour
consistent with DPMS.getEnforcingAdminInternal, change the ordering in
following way: supervision admins -> DPC admins -> other admins.

Test:  atest FrameworksServicesTests:com.android.server.devicepolicy.PolicyEnforcementInfoTest
Flag: android.app.admin.flags.policy_transparency_refactor_enabled
Bug: 414733570

Change-Id: Idf3f83c46f089b90e5f67a660736d2950b8c3524
parent bd5349dc
Loading
Loading
Loading
Loading
+16 −13
Original line number Diff line number Diff line
@@ -16,13 +16,11 @@

package android.app.admin;

import static java.util.function.Predicate.not;

import android.annotation.Nullable;
import android.app.role.RoleManager;

import java.util.Comparator;
import java.util.List;
import java.util.stream.Stream;

/**
 * Class that contains information about the admins that are enforcing a specific policy.
@@ -30,22 +28,23 @@ import java.util.stream.Stream;
 * @hide
 */
public class PolicyEnforcementInfo {
    // Contains all admins who has enforced the policy. The supervision admin will be first on
    // the list, if there's any.
    // Contains all admins who has enforced the policy. The admins will be ordered as
    // supervision, DPC admin then any other admin if they exist in the list.
    private final List<EnforcingAdmin> mAllAdmins;

    /**
     * @hide
     */
    public PolicyEnforcementInfo(List<EnforcingAdmin> enforcingAdmins) {
        // Add any supervisor admins first.
        Stream<EnforcingAdmin> supervisorAdmins = enforcingAdmins.stream().filter(
                PolicyEnforcementInfo::isSupervisionRole);
        // Add all other admins afterwards. Only supervisor admin will be added first, for others
        // the order doesn't matter.
        Stream<EnforcingAdmin> otherAdmins = enforcingAdmins.stream().filter(
                not(PolicyEnforcementInfo::isSupervisionRole));
        mAllAdmins = Stream.concat(supervisorAdmins, otherAdmins).toList();
        mAllAdmins = enforcingAdmins.stream().sorted(Comparator.comparingInt(admin -> {
            if (isSupervisionRole(admin)) {
                return 0; // Supervision role holders have the highest priority.
            }
            if (isDpcAdmin(admin)) {
                return 1; // DPC are next.
            }
            return 2; // All other admins at the end.
        })).toList();
    }

    /**
@@ -88,4 +87,8 @@ public class PolicyEnforcementInfo {
        return ((RoleAuthority) enforcingAdmin.getAuthority()).getRoles().contains(
                RoleManager.ROLE_SYSTEM_SUPERVISION);
    }

    private static boolean isDpcAdmin(EnforcingAdmin enforcingAdmin) {
        return enforcingAdmin.getAuthority() instanceof DpcAuthority;
    }
}
+105 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 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 com.android.server.devicepolicy

import android.app.admin.DpcAuthority
import android.app.admin.PolicyEnforcementInfo
import android.app.admin.RoleAuthority
import android.app.admin.SystemAuthority
import android.app.role.RoleManager
import android.content.ComponentName
import android.os.UserHandle
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.google.common.truth.Truth.assertThat
import kotlin.test.Test
import org.junit.runner.RunWith

@RunWith(AndroidJUnit4::class)
class PolicyEnforcementInfoTest {

    @Test
    fun getAllAdmins_sortsAdmins_supervisionAdminDpcAdminOtherAdmin() {
        val policyEnforcementInfo =
            PolicyEnforcementInfo(listOf(DPC_ADMIN, SYSTEM_ADMIN, SUPERVISION_ADMIN))
        assertThat(policyEnforcementInfo.allAdmins)
            .containsExactly(SUPERVISION_ADMIN, DPC_ADMIN, SYSTEM_ADMIN)
            .inOrder()
    }

    @Test
    fun getAllAdmins_sortsAdmins_dpcAdminOtherAdmin() {
        val policyEnforcementInfo = PolicyEnforcementInfo(listOf(SYSTEM_ADMIN, DPC_ADMIN))
        assertThat(policyEnforcementInfo.allAdmins)
            .containsExactly(DPC_ADMIN, SYSTEM_ADMIN)
            .inOrder()
    }

    @Test
    fun isOnlyEnforcedBySystem_returnsFalse() {
        val policyEnforcementInfo =
            PolicyEnforcementInfo(listOf(SYSTEM_ADMIN, SUPERVISION_ADMIN, DPC_ADMIN))
        assertThat(policyEnforcementInfo.isOnlyEnforcedBySystem).isFalse()
    }

    @Test
    fun isOnlyEnforcedBySystem_returnsTrue() {
        val policyEnforcementInfo = PolicyEnforcementInfo(listOf(SYSTEM_ADMIN))
        assertThat(policyEnforcementInfo.isOnlyEnforcedBySystem).isTrue()
    }

    @Test
    fun getMostImportantEnforcingAdmin_returnsSupervisionAdmin() {
        val policyEnforcementInfo =
            PolicyEnforcementInfo(listOf(SUPERVISION_ADMIN, DPC_ADMIN, SYSTEM_ADMIN))
        assertThat(policyEnforcementInfo.mostImportantEnforcingAdmin).isEqualTo(SUPERVISION_ADMIN)
    }

    @Test
    fun getMostImportantEnforcingAdmin_returnsDpcAdmin() {
        val policyEnforcementInfo = PolicyEnforcementInfo(listOf(SYSTEM_ADMIN, DPC_ADMIN))
        assertThat(policyEnforcementInfo.mostImportantEnforcingAdmin).isEqualTo(DPC_ADMIN)
    }

    companion object {
        private const val PACKAGE_NAME = "package-name"
        private const val PACKAGE_CLASS = "package-name-class"
        private const val SYSTEM_ENTITY = "android-platform"
        private val SYSTEM_USER_HANDLE = UserHandle.SYSTEM
        private val COMPONENT_NAME = ComponentName(PACKAGE_NAME, PACKAGE_CLASS)
        val SUPERVISION_ADMIN =
            android.app.admin.EnforcingAdmin(
                PACKAGE_NAME,
                RoleAuthority(setOf(RoleManager.ROLE_SYSTEM_SUPERVISION)),
                SYSTEM_USER_HANDLE,
                COMPONENT_NAME,
            )
        val DPC_ADMIN =
            android.app.admin.EnforcingAdmin(
                PACKAGE_NAME,
                DpcAuthority.DPC_AUTHORITY,
                SYSTEM_USER_HANDLE,
                COMPONENT_NAME,
            )
        val SYSTEM_ADMIN =
            android.app.admin.EnforcingAdmin(
                PACKAGE_NAME,
                SystemAuthority(SYSTEM_ENTITY),
                SYSTEM_USER_HANDLE,
                null,
            )
    }
}