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

Commit 46a1dcef authored by Salud Lemus's avatar Salud Lemus
Browse files

Extend set user protected packages for multi-user

The current implementation does not work when the multi-user feature is
enabled because it clears the "globally" protected packages set by the
device owner whenever a new user is created.

Bug: 178500150
Test: atest FrameworksServicesTests:com.android.server.devicepolicy.OwnersTest
Test: atest FrameworksServicesTests:com.android.server.devicepolicy.DevicePolicyManagerTest
Test: Ran the CTS tests that were added

Change-Id: Id04cb9b5b2357b0a0b5090442a39d97405287dbe
parent c96669ea
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -382,10 +382,10 @@ public abstract class PackageManagerInternal implements PackageSettingsSnapshotP
            int deviceOwnerUserId, String deviceOwner, SparseArray<String> profileOwners);

    /**
     * Called by DevicePolicyManagerService to set the package names protected by the device
     * owner.
     * Called by Owners to set the package names protected by the device owner.
     */
    public abstract void setDeviceOwnerProtectedPackages(List<String> packageNames);
    public abstract void setDeviceOwnerProtectedPackages(
            String deviceOwnerPackageName, List<String> packageNames);

    /**
     * Returns {@code true} if a given package can't be wiped. Otherwise, returns {@code false}.
+4 −2
Original line number Diff line number Diff line
@@ -26662,8 +26662,10 @@ public class PackageManagerService extends IPackageManager.Stub
        }
        @Override
        public void setDeviceOwnerProtectedPackages(List<String> packageNames) {
            mProtectedPackages.setDeviceOwnerProtectedPackages(packageNames);
        public void setDeviceOwnerProtectedPackages(
                String deviceOwnerPackageName, List<String> packageNames) {
            mProtectedPackages.setDeviceOwnerProtectedPackages(
                    deviceOwnerPackageName, packageNames);
        }
        @Override
+23 −6
Original line number Diff line number Diff line
@@ -20,14 +20,15 @@ import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.content.Context;
import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.SparseArray;

import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.ArrayUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
 * Manages package names that need special protection.
@@ -55,7 +56,7 @@ public class ProtectedPackages {

    @Nullable
    @GuardedBy("this")
    private List<String> mDeviceOwnerProtectedPackages;
    private final ArrayMap<String, Set<String>> mDeviceOwnerProtectedPackages = new ArrayMap<>();

    private final Context mContext;

@@ -78,8 +79,14 @@ public class ProtectedPackages {
                : profileOwnerPackages.clone();
    }

    public synchronized void setDeviceOwnerProtectedPackages(List<String> packageNames) {
        mDeviceOwnerProtectedPackages = new ArrayList<String>(packageNames);
    /** Sets the protected packages for the device owner. */
    public synchronized void setDeviceOwnerProtectedPackages(
            String deviceOwnerPackageName, List<String> packageNames) {
        if (packageNames.isEmpty()) {
            mDeviceOwnerProtectedPackages.remove(deviceOwnerPackageName);
        } else {
            mDeviceOwnerProtectedPackages.put(deviceOwnerPackageName, new ArraySet<>(packageNames));
        }
    }

    private synchronized boolean hasDeviceOwnerOrProfileOwner(int userId, String packageName) {
@@ -118,7 +125,17 @@ public class ProtectedPackages {
     */
    private synchronized boolean isProtectedPackage(String packageName) {
        return packageName != null && (packageName.equals(mDeviceProvisioningPackage)
                || ArrayUtils.contains(mDeviceOwnerProtectedPackages, packageName));
                || isDeviceOwnerProtectedPackage(packageName));
    }

    /** Returns {@code true} if the given package is a protected package set by any device owner. */
    private synchronized boolean isDeviceOwnerProtectedPackage(String packageName) {
        for (Set<String> protectedPackages : mDeviceOwnerProtectedPackages.values()) {
            if (protectedPackages.contains(packageName)) {
                return true;
            }
        }
        return false;
    }

    /**
+30 −20
Original line number Diff line number Diff line
@@ -1759,11 +1759,38 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
                if (userHandle == UserHandle.USER_SYSTEM) {
                    mStateCache.setDeviceProvisioned(policy.mUserSetupComplete);
                }
                migrateDeviceOwnerProtectedPackagesToOwners(userHandle, policy);
            }
            return policy;
        }
    }
    /**
     * Only used by {@link #getUserData(int)} to migrate <b>existing</b> device owner protected
     * packages that were stored in {@link DevicePolicyData#mUserControlDisabledPackages} to
     * {@link Owners} because the device owner protected packages are now stored on a per device
     * owner basis instead of on a per user basis.
     *
     * Any calls to {@link #setUserControlDisabledPackages(ComponentName, List)} would now store
     * the device owner protected packages in {@link Owners} instead of {@link DevicePolicyData}.
     * @param userHandle The device owner user
     * @param policy The policy data of the device owner user
     */
    private void migrateDeviceOwnerProtectedPackagesToOwners(
            int userHandle, DevicePolicyData policy) {
        ComponentName deviceOwnerComponent = getOwnerComponent(userHandle);
        if (isDeviceOwner(deviceOwnerComponent, userHandle)
                && !policy.mUserControlDisabledPackages.isEmpty()) {
            mOwners.setDeviceOwnerProtectedPackages(
                    deviceOwnerComponent.getPackageName(),
                    policy.mUserControlDisabledPackages);
            policy.mUserControlDisabledPackages = new ArrayList<>();
            saveSettingsLocked(userHandle);
        }
    }
    /**
     * Creates and loads the policy data from xml for data that is shared between
     * various profiles of a user. In contrast to {@link #getUserData(int)}
@@ -2856,7 +2883,6 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
        updateMaximumTimeToLockLocked(userHandle);
        updateLockTaskPackagesLocked(policy.mLockTaskPackages, userHandle);
        updateLockTaskFeaturesLocked(policy.mLockTaskFeatures, userHandle);
        updateUserControlDisabledPackagesLocked(policy.mUserControlDisabledPackages);
        if (policy.mStatusBarDisabled) {
            setStatusBarDisabledInternal(policy.mStatusBarDisabled, userHandle);
        }
@@ -2900,10 +2926,6 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
        }
    }
    private void updateUserControlDisabledPackagesLocked(List<String> packages) {
        mInjector.getPackageManagerInternal().setDeviceOwnerProtectedPackages(packages);
    }
    private void updateLockTaskFeaturesLocked(int flags, int userId) {
        long ident = mInjector.binderClearCallingIdentity();
        try {
@@ -8697,7 +8719,6 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
        updateLockTaskPackagesLocked(policy.mLockTaskPackages, userId);
        policy.mLockTaskFeatures = DevicePolicyManager.LOCK_TASK_FEATURE_NONE;
        policy.mUserControlDisabledPackages.clear();
        updateUserControlDisabledPackagesLocked(policy.mUserControlDisabledPackages);
        saveSettingsLocked(userId);
        try {
@@ -16142,14 +16163,14 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
    @Override
    public void setUserControlDisabledPackages(ComponentName who, List<String> packages) {
        Objects.requireNonNull(who, "ComponentName is null");
        Preconditions.checkNotNull(packages, "packages is null");
        Objects.requireNonNull(packages, "packages is null");
        final CallerIdentity caller = getCallerIdentity(who);
        Preconditions.checkCallAuthorization(isDeviceOwner(caller));
        checkCanExecuteOrThrowUnsafe(
                DevicePolicyManager.OPERATION_SET_USER_CONTROL_DISABLED_PACKAGES);
        synchronized (getLockObject()) {
            setUserControlDisabledPackagesLocked(caller.getUserId(), packages);
            mOwners.setDeviceOwnerProtectedPackages(who.getPackageName(), packages);
            DevicePolicyEventLogger
                    .createEvent(DevicePolicyEnums.SET_USER_CONTROL_DISABLED_PACKAGES)
                    .setAdmin(who)
@@ -16158,15 +16179,6 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
        }
    }
    private void setUserControlDisabledPackagesLocked(int userHandle, List<String> packages) {
        final DevicePolicyData policy = getUserData(userHandle);
        policy.mUserControlDisabledPackages = packages;
        // Store the settings persistently.
        saveSettingsLocked(userHandle);
        updateUserControlDisabledPackagesLocked(packages);
    }
    @Override
    public List<String> getUserControlDisabledPackages(ComponentName who) {
        Objects.requireNonNull(who, "ComponentName is null");
@@ -16175,9 +16187,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
        Preconditions.checkCallAuthorization(isDeviceOwner(caller));
        synchronized (getLockObject()) {
            final List<String> packages =
                    getUserData(caller.getUserId()).mUserControlDisabledPackages;
            return packages == null ? Collections.EMPTY_LIST : packages;
            return mOwners.getDeviceOwnerProtectedPackages(who.getPackageName());
        }
    }
+87 −6
Original line number Diff line number Diff line
@@ -62,6 +62,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@@ -97,10 +98,13 @@ class Owners {
    // Holds "context" for device-owner, this must not be show up before device-owner.
    private static final String TAG_DEVICE_OWNER_CONTEXT = "device-owner-context";
    private static final String TAG_DEVICE_OWNER_TYPE = "device-owner-type";
    private static final String TAG_DEVICE_OWNER_PROTECTED_PACKAGES =
            "device-owner-protected-packages";

    private static final String ATTR_NAME = "name";
    private static final String ATTR_PACKAGE = "package";
    private static final String ATTR_COMPONENT_NAME = "component";
    private static final String ATTR_SIZE = "size";
    private static final String ATTR_REMOTE_BUGREPORT_URI = "remoteBugreportUri";
    private static final String ATTR_REMOTE_BUGREPORT_HASH = "remoteBugreportHash";
    private static final String ATTR_USERID = "userId";
@@ -129,6 +133,8 @@ class Owners {
    // Device owner type for a managed device.
    private final ArrayMap<String, Integer> mDeviceOwnerTypes = new ArrayMap<>();

    private final ArrayMap<String, List<String>> mDeviceOwnerProtectedPackages = new ArrayMap<>();

    private int mDeviceOwnerUserId = UserHandle.USER_NULL;

    // Internal state for the profile owner packages.
@@ -216,6 +222,12 @@ class Owners {
            pushToActivityTaskManagerLocked();
            pushToActivityManagerLocked();
            pushToAppOpsLocked();

            for (ArrayMap.Entry<String, List<String>> entry :
                    mDeviceOwnerProtectedPackages.entrySet()) {
                mPackageManagerInternal.setDeviceOwnerProtectedPackages(
                        entry.getKey(), entry.getValue());
            }
        }
    }

@@ -343,6 +355,12 @@ class Owners {
    void clearDeviceOwner() {
        synchronized (mLock) {
            mDeviceOwnerTypes.remove(mDeviceOwner.packageName);
            List<String> protectedPackages =
                    mDeviceOwnerProtectedPackages.remove(mDeviceOwner.packageName);
            if (protectedPackages != null) {
                mPackageManagerInternal.setDeviceOwnerProtectedPackages(
                        mDeviceOwner.packageName, new ArrayList<>());
            }
            mDeviceOwner = null;
            mDeviceOwnerUserId = UserHandle.USER_NULL;

@@ -394,6 +412,12 @@ class Owners {
    void transferDeviceOwnership(ComponentName target) {
        synchronized (mLock) {
            Integer previousDeviceOwnerType = mDeviceOwnerTypes.remove(mDeviceOwner.packageName);
            List<String> previousProtectedPackages =
                    mDeviceOwnerProtectedPackages.remove(mDeviceOwner.packageName);
            if (previousProtectedPackages != null) {
                mPackageManagerInternal.setDeviceOwnerProtectedPackages(
                        mDeviceOwner.packageName, new ArrayList<>());
            }
            // We don't set a name because it's not used anyway.
            // See DevicePolicyManagerService#getDeviceOwnerName
            mDeviceOwner = new OwnerInfo(null, target,
@@ -403,6 +427,10 @@ class Owners {
            if (previousDeviceOwnerType != null) {
                mDeviceOwnerTypes.put(mDeviceOwner.packageName, previousDeviceOwnerType);
            }
            if (previousProtectedPackages != null) {
                mDeviceOwnerProtectedPackages.put(
                        mDeviceOwner.packageName, previousProtectedPackages);
            }
            pushToPackageManagerLocked();
            pushToActivityTaskManagerLocked();
            pushToActivityManagerLocked();
@@ -594,8 +622,10 @@ class Owners {
        }
    }

    /** Sets the indicator that the profile owner manages an organization-owned device,
     * then write to file. */
    /**
     * Sets the indicator that the profile owner manages an organization-owned device,
     * then write to file.
     */
    void markProfileOwnerOfOrganizationOwnedDevice(int userId) {
        synchronized (mLock) {
            OwnerInfo profileOwner = mProfileOwners.get(userId);
@@ -640,6 +670,33 @@ class Owners {
        }
    }

    void setDeviceOwnerProtectedPackages(String packageName, List<String> protectedPackages) {
        synchronized (mLock) {
            if (!hasDeviceOwner()) {
                Slog.e(TAG,
                        "Attempting to set device owner protected packages when there is no "
                                + "device owner");
                return;
            } else if (!mDeviceOwner.packageName.equals(packageName)) {
                Slog.e(TAG, "Attempting to set device owner protected packages when the provided "
                        + "package name " + packageName
                        + " does not match the device owner package name");
                return;
            }

            mDeviceOwnerProtectedPackages.put(packageName, protectedPackages);
            mPackageManagerInternal.setDeviceOwnerProtectedPackages(packageName, protectedPackages);
            writeDeviceOwner();
        }
    }

    List<String> getDeviceOwnerProtectedPackages(String packageName) {
        synchronized (mLock) {
            return mDeviceOwnerProtectedPackages.containsKey(packageName)
                    ? mDeviceOwnerProtectedPackages.get(packageName) : Collections.emptyList();
        }
    }

    private boolean readLegacyOwnerFileLocked(File file) {
        if (!file.exists()) {
            // Already migrated or the device has no owners.
@@ -936,6 +993,21 @@ class Owners {
                }
            }

            if (!mDeviceOwnerProtectedPackages.isEmpty()) {
                for (ArrayMap.Entry<String, List<String>> entry :
                        mDeviceOwnerProtectedPackages.entrySet()) {
                    List<String> protectedPackages = entry.getValue();

                    out.startTag(null, TAG_DEVICE_OWNER_PROTECTED_PACKAGES);
                    out.attribute(null, ATTR_PACKAGE, entry.getKey());
                    out.attributeInt(null, ATTR_SIZE, protectedPackages.size());
                    for (int i = 0, size = protectedPackages.size(); i < size; i++) {
                        out.attribute(null, ATTR_NAME + i, protectedPackages.get(i));
                    }
                    out.endTag(null, TAG_DEVICE_OWNER_PROTECTED_PACKAGES);
                }
            }

            if (mSystemUpdatePolicy != null) {
                out.startTag(null, TAG_SYSTEM_UPDATE_POLICY);
                mSystemUpdatePolicy.saveToXml(out);
@@ -1002,6 +1074,15 @@ class Owners {
                            DEVICE_OWNER_TYPE_DEFAULT);
                    mDeviceOwnerTypes.put(packageName, deviceOwnerType);
                    break;
                case TAG_DEVICE_OWNER_PROTECTED_PACKAGES:
                    packageName = parser.getAttributeValue(null, ATTR_PACKAGE);
                    int protectedPackagesSize = parser.getAttributeInt(null, ATTR_SIZE, 0);
                    List<String> protectedPackages = new ArrayList<>();
                    for (int i = 0; i < protectedPackagesSize; i++) {
                        protectedPackages.add(parser.getAttributeValue(null, ATTR_NAME + i));
                    }
                    mDeviceOwnerProtectedPackages.put(packageName, protectedPackages);
                    break;
                default:
                    Slog.e(TAG, "Unexpected tag: " + tag);
                    return false;
Loading