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

Commit bf75b2d5 authored by Felipe Leme's avatar Felipe Leme
Browse files

Added OrganizationOwnedDevice to cmd device_policy list-owners

Also refactored listOwners() to get rid of OwnerShellData.

Test: adb shell cmd device_policy list-owners
Flag: EXEMPT changes on debugging components only
Bug: 417943524

Change-Id: If66d57ded31b511f4273109bed983c9526f3673c
parent 201e6965
Loading
Loading
Loading
Loading
+20 −28
Original line number Diff line number Diff line
@@ -1688,39 +1688,31 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
    }
    // Used by DevicePolicyManagerServiceShellCommand
    List<OwnerShellData> listAllOwners() {
    void printAllOwners(PrintWriter pw) {
        Preconditions.checkCallAuthorization(
                hasCallingOrSelfPermission(permission.MANAGE_DEVICE_ADMINS));
        return mInjector.binderWithCleanCallingIdentity(() -> {
            SparseArray<DevicePolicyData> userData;
            // Gets the owners of "full users" first (device owner and profile owners)
            List<OwnerShellData> owners = mOwners.listAllOwners();
        synchronized (getLockObject()) {
                for (int i = 0; i < owners.size(); i++) {
                    OwnerShellData owner = owners.get(i);
                    owner.isAffiliated = isUserAffiliatedWithDeviceLocked(owner.userId);
            if (getDeviceOwnerUserIdUncheckedLocked() != UserHandle.USER_NULL) {
                pw.printf("User %d: admin=%s,DeviceOwner\n", getDeviceOwnerUserIdUncheckedLocked(),
                        getDeviceOwnerAdminLocked().info.getComponent().flattenToShortString());
            }
                userData = mUserData;
            for (var userId : mOwners.getProfileOwnerKeys()) {
                pw.printf("User %d: admin=%s,", userId, getProfileOwnerAdminLocked(userId).info
                        .getComponent().flattenToShortString());
                if (isManagedProfile(userId)) {
                    pw.printf("ManagedProfileOwner(parentUserId=%d)", getProfileParentId(userId));
                } else {
                    pw.print("ProfileOwner");
                }
            // Then the owners of profile users (managed profiles)
            for (int i = 0; i < userData.size(); i++) {
                DevicePolicyData policyData = mUserData.valueAt(i);
                int userId = userData.keyAt(i);
                int parentUserId = mUserManagerInternal.getProfileParentId(userId);
                boolean isProfile = parentUserId != userId;
                if (!isProfile) continue;
                for (int j = 0; j < policyData.mAdminList.size(); j++) {
                    ActiveAdmin admin = policyData.mAdminList.get(j);
                    OwnerShellData owner = OwnerShellData.forManagedProfileOwner(userId,
                            parentUserId, admin.info.getComponent());
                    owners.add(owner);
                if (isUserAffiliatedWithDeviceLocked(userId)) {
                    pw.print(",Affiliated");
                }
                if (mOwners.isProfileOwnerOfOrganizationOwnedDevice(userId)) {
                    pw.print(",OrganizationOwnedDevice");
                }
                pw.println();
            }
        }
            return owners;
        });
    }
    /**
+1 −22
Original line number Diff line number Diff line
@@ -219,28 +219,7 @@ final class DevicePolicyManagerServiceShellCommand extends ShellCommand {
    }

    private int runListOwners(PrintWriter pw) {
        List<OwnerShellData> owners = mService.listAllOwners();
        int size = printAndGetSize(pw, owners, "owner");
        if (size == 0) return 0;

        for (int i = 0; i < size; i++) {
            OwnerShellData owner = owners.get(i);
            pw.printf("User %2d: admin=%s", owner.userId, owner.admin.flattenToShortString());
            if (owner.isDeviceOwner) {
                pw.print(",DeviceOwner");
            }
            if (owner.isProfileOwner) {
                pw.print(",ProfileOwner");
            }
            if (owner.isManagedProfileOwner) {
                pw.printf(",ManagedProfileOwner(parentUserId=%d)", owner.parentUserId);
            }
            if (owner.isAffiliated) {
                pw.print(",Affiliated");
            }
            pw.println();
        }

        mService.printAllOwners(pw);
        return 0;
    }

+0 −98
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 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 static android.os.UserHandle.USER_NULL;

import android.annotation.UserIdInt;
import android.content.ComponentName;

import com.android.internal.util.Preconditions;

import java.util.Objects;

/**
 * Data-transfer object used by {@link DevicePolicyManagerServiceShellCommand}.
 */
final class OwnerShellData {

    public final @UserIdInt int userId;
    public final @UserIdInt int parentUserId;
    public final ComponentName admin;
    public final boolean isDeviceOwner;
    public final boolean isProfileOwner;
    public final boolean isManagedProfileOwner;
    public boolean isAffiliated;

    // NOTE: class is too simple to require a Builder (not to mention isAffiliated is mutable)
    private OwnerShellData(@UserIdInt int userId, @UserIdInt int parentUserId, ComponentName admin,
            boolean isDeviceOwner, boolean isProfileOwner, boolean isManagedProfileOwner) {
        Preconditions.checkArgument(userId != USER_NULL, "userId cannot be USER_NULL");
        this.userId = userId;
        this.parentUserId = parentUserId;
        this.admin = Objects.requireNonNull(admin, "admin must not be null");
        this.isDeviceOwner = isDeviceOwner;
        this.isProfileOwner = isProfileOwner;
        this.isManagedProfileOwner = isManagedProfileOwner;
        if (isManagedProfileOwner) {
            Preconditions.checkArgument(parentUserId != USER_NULL,
                    "parentUserId cannot be USER_NULL for managed profile owner");
            Preconditions.checkArgument(parentUserId != userId,
                    "cannot be parent of itself (%d)", userId);
        }
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder(getClass().getSimpleName())
                .append("[userId=").append(userId)
                .append(",admin=").append(admin.flattenToShortString());
        if (isDeviceOwner) {
            sb.append(",deviceOwner");
        }
        if (isProfileOwner) {
            sb.append(",isProfileOwner");
        }
        if (isManagedProfileOwner) {
            sb.append(",isManagedProfileOwner");
        }
        if (parentUserId != USER_NULL) {
            sb.append(",parentUserId=").append(parentUserId);
        }
        if (isAffiliated) {
            sb.append(",isAffiliated");
        }
        return sb.append(']').toString();
    }

    static OwnerShellData forDeviceOwner(@UserIdInt int userId, ComponentName admin) {
        return new OwnerShellData(userId, /* parentUserId= */ USER_NULL, admin,
                /* isDeviceOwner= */ true, /* isProfileOwner= */ false,
                /* isManagedProfileOwner= */ false);
    }

    static OwnerShellData forUserProfileOwner(@UserIdInt int userId, ComponentName admin) {
        return new OwnerShellData(userId, /* parentUserId= */ USER_NULL, admin,
                /* isDeviceOwner= */ false, /* isProfileOwner= */ true,
                /* isManagedProfileOwner= */ false);
    }

    static OwnerShellData forManagedProfileOwner(@UserIdInt int userId, @UserIdInt int parentUserId,
            ComponentName admin) {
        return new OwnerShellData(userId, parentUserId, admin, /* isDeviceOwner= */ false,
                /* isProfileOwner= */ false, /* isManagedProfileOwner= */ true);
    }
}
+0 −21
Original line number Diff line number Diff line
@@ -49,8 +49,6 @@ import com.android.server.wm.ActivityTaskManagerInternal;

import java.io.File;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Set;

@@ -64,8 +62,6 @@ import java.util.Set;
class Owners {
    private static final String TAG = "DevicePolicyManagerService";

    private static final boolean DEBUG = false; // DO NOT SUBMIT WITH TRUE

    private final UserManager mUserManager;
    private final PackageManagerInternal mPackageManagerInternal;
    private final ActivityTaskManagerInternal mActivityTaskManagerInternal;
@@ -357,23 +353,6 @@ class Owners {
        }
    }

    List<OwnerShellData> listAllOwners() {
        List<OwnerShellData> owners = new ArrayList<>();
        synchronized (mData) {
            if (mData.mDeviceOwner != null) {
                owners.add(OwnerShellData.forDeviceOwner(mData.mDeviceOwnerUserId,
                        mData.mDeviceOwner.admin));
            }
            for (int i = 0; i < mData.mProfileOwners.size(); i++) {
                int userId = mData.mProfileOwners.keyAt(i);
                OwnerInfo info = mData.mProfileOwners.valueAt(i);
                owners.add(OwnerShellData.forUserProfileOwner(userId, info.admin));
            }
        }
        return owners;
    }


    SystemUpdatePolicy getSystemUpdatePolicy() {
        synchronized (mData) {
            return mData.mSystemUpdatePolicy;
+0 −129
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 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 static android.os.UserHandle.USER_NULL;

import static com.google.common.truth.Truth.assertWithMessage;

import static org.testng.Assert.expectThrows;

import android.content.ComponentName;

import org.junit.Test;

/**
 * Run it as {@code atest FrameworksMockingServicesTests:OwnerShellDataTest}
 */
public final class OwnerShellDataTest {

    private static final int USER_ID = 007;
    private static final int PARENT_USER_ID = 'M' + 'I' + 6;
    private static final ComponentName ADMIN = new ComponentName("Bond", "James");

    @Test
    public void testForDeviceOwner_noAdmin() {
        expectThrows(NullPointerException.class,
                () -> OwnerShellData.forDeviceOwner(USER_ID, /* admin= */ null));
    }

    @Test
    public void testForDeviceOwner_invalidUser() {
        expectThrows(IllegalArgumentException.class,
                () -> OwnerShellData.forDeviceOwner(USER_NULL, ADMIN));
    }

    @Test
    public void testForDeviceOwner() {
        OwnerShellData dto = OwnerShellData.forDeviceOwner(USER_ID, ADMIN);

        assertWithMessage("dto(%s).userId", dto).that(dto.userId).isEqualTo(USER_ID);
        assertWithMessage("dto(%s).parentUserId", dto).that(dto.parentUserId)
                .isEqualTo(USER_NULL);
        assertWithMessage("dto(%s).admin", dto).that(dto.admin).isSameInstanceAs(ADMIN);
        assertWithMessage("dto(%s).isDeviceOwner", dto).that(dto.isDeviceOwner).isTrue();
        assertWithMessage("dto(%s).isProfileOwner", dto).that(dto.isProfileOwner).isFalse();
        assertWithMessage("dto(%s).isManagedProfileOwner", dto).that(dto.isManagedProfileOwner)
                .isFalse();
        assertWithMessage("dto(%s).isAffiliated", dto).that(dto.isAffiliated).isFalse();
    }

    @Test
    public void testForUserProfileOwner_noAdmin() {
        expectThrows(NullPointerException.class,
                () -> OwnerShellData.forUserProfileOwner(USER_ID, /* admin= */ null));
    }

    @Test
    public void testForUserProfileOwner_invalidUser() {
        expectThrows(IllegalArgumentException.class,
                () -> OwnerShellData.forUserProfileOwner(USER_NULL, ADMIN));
    }

    @Test
    public void testForUserProfileOwner() {
        OwnerShellData dto = OwnerShellData.forUserProfileOwner(USER_ID, ADMIN);

        assertWithMessage("dto(%s).userId", dto).that(dto.userId).isEqualTo(USER_ID);
        assertWithMessage("dto(%s).parentUserId", dto).that(dto.parentUserId)
                .isEqualTo(USER_NULL);
        assertWithMessage("dto(%s).admin", dto).that(dto.admin).isSameInstanceAs(ADMIN);
        assertWithMessage("dto(%s).isDeviceOwner", dto).that(dto.isDeviceOwner).isFalse();
        assertWithMessage("dto(%s).isProfileOwner", dto).that(dto.isProfileOwner).isTrue();
        assertWithMessage("dto(%s).isManagedProfileOwner", dto).that(dto.isManagedProfileOwner)
                .isFalse();
        assertWithMessage("dto(%s).isAffiliated", dto).that(dto.isAffiliated).isFalse();
    }

    @Test
    public void testForManagedProfileOwner_noAdmin() {
        expectThrows(NullPointerException.class,
                () -> OwnerShellData.forManagedProfileOwner(USER_ID, PARENT_USER_ID, null));
    }

    @Test
    public void testForManagedProfileOwner_invalidUser() {
        expectThrows(IllegalArgumentException.class,
                () -> OwnerShellData.forManagedProfileOwner(USER_NULL, PARENT_USER_ID, ADMIN));
    }

    @Test
    public void testForManagedProfileOwner_invalidParent() {
        expectThrows(IllegalArgumentException.class,
                () -> OwnerShellData.forManagedProfileOwner(USER_ID, USER_NULL, ADMIN));
    }

    @Test
    public void testForManagedProfileOwner_parentOfItself() {
        expectThrows(IllegalArgumentException.class,
                () -> OwnerShellData.forManagedProfileOwner(USER_ID, USER_ID, ADMIN));
    }

    @Test
    public void testForManagedProfileOwner() {
        OwnerShellData dto = OwnerShellData.forManagedProfileOwner(USER_ID, PARENT_USER_ID, ADMIN);

        assertWithMessage("dto(%s).userId", dto).that(dto.userId).isEqualTo(USER_ID);
        assertWithMessage("dto(%s).parentUserId", dto).that(dto.parentUserId)
                .isEqualTo(PARENT_USER_ID);
        assertWithMessage("dto(%s).admin", dto).that(dto.admin).isSameInstanceAs(ADMIN);
        assertWithMessage("dto(%s).isDeviceOwner", dto).that(dto.isDeviceOwner).isFalse();
        assertWithMessage("dto(%s).isProfileOwner", dto).that(dto.isProfileOwner).isFalse();
        assertWithMessage("dto(%s).isManagedProfileOwner", dto).that(dto.isManagedProfileOwner)
                .isTrue();
        assertWithMessage("dto(%s).isAffiliated", dto).that(dto.isAffiliated).isFalse();
    }
}