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

Commit 17382ed5 authored by Kholoud Mohamed's avatar Kholoud Mohamed
Browse files

migrate setUninstallBlocked API

Bug: 258442629
Bug: 232918480
Test: atest BlockUninstallTest
Change-Id: I1e68f3cfe07ff394858d049ef96bad1aa1077259
parent 1ca3f550
Loading
Loading
Loading
Loading
+11 −2
Original line number Diff line number Diff line
@@ -3985,6 +3985,7 @@ public class DevicePolicyManager {
     */
    public static final String AUTO_TIMEZONE_POLICY = "autoTimezone";
    // TODO: Expose this as SystemAPI once we add the query API
    /**
     * @hide
     */
@@ -4011,14 +4012,22 @@ public class DevicePolicyManager {
    /**
     * @hide
     */
    public static final String USER_CONTROL_DISABLED_PACKAGES = "userControlDisabledPackages";
    public static final String USER_CONTROL_DISABLED_PACKAGES_POLICY =
            "userControlDisabledPackages";
    // TODO: Expose this as SystemAPI once we add the query API
    /**
     * @hide
     */
    public static final String PERSISTENT_PREFERRED_ACTIVITY_POLICY =
            "persistentPreferredActivity";
    // TODO: Expose this as SystemAPI once we add the query API
    /**
     * @hide
     */
    public static final String PERSISTENT_PREFERRED_ACTIVITY = "persistentPreferredActivity";
    public static final String PACKAGE_UNINSTALL_BLOCKED_POLICY = "packageUninstallBlocked";
    /**
     * This object is a single place to tack on invalidation and disable calls.  All
+50 −14
Original line number Diff line number Diff line
@@ -12219,11 +12219,25 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
                || isFinancedDeviceOwner(caller)))
                || (caller.hasPackage() && isCallerDelegate(caller, DELEGATION_BLOCK_UNINSTALL)));
        if (isCoexistenceEnabled(caller)) {
            // TODO(b/260573124): Add correct enforcing admin when permission changes are
            //  merged, and don't forget to handle delegates! Enterprise admins assume
            //  component name isn't null.
            EnforcingAdmin admin = EnforcingAdmin.createEnterpriseEnforcingAdmin(
                    who != null ? who : new ComponentName(callerPackage, "delegate"),
                    caller.getUserId());
            mDevicePolicyEngine.setLocalPolicy(
                    PolicyDefinition.PACKAGE_UNINSTALL_BLOCKED(packageName),
                    admin,
                    uninstallBlocked,
                    caller.getUserId());
        } else {
            final int userId = caller.getUserId();
            synchronized (getLockObject()) {
                long id = mInjector.binderClearCallingIdentity();
                try {
                mIPackageManager.setBlockUninstallForUser(packageName, uninstallBlocked, userId);
                    mIPackageManager.setBlockUninstallForUser(
                            packageName, uninstallBlocked, userId);
                } catch (RemoteException re) {
                    // Shouldn't happen.
                    Slogf.e(LOG_TAG, "Failed to setBlockUninstallForUser", re);
@@ -12237,6 +12251,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
                pmi.removeDistractingPackageRestrictions(packageName, userId);
                pmi.flushPackageRestrictions(userId);
            }
        }
        DevicePolicyEventLogger
                .createEvent(DevicePolicyEnums.SET_UNINSTALL_BLOCKED)
                .setAdmin(caller.getPackageName())
@@ -12245,6 +12261,26 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
                .write();
    }
    static void setUninstallBlockedUnchecked(
            String packageName, boolean uninstallBlocked, int userId) {
        Binder.withCleanCallingIdentity(() -> {
            try {
                AppGlobals.getPackageManager().setBlockUninstallForUser(
                        packageName, uninstallBlocked, userId);
            } catch (RemoteException re) {
                // Shouldn't happen.
                Slogf.e(LOG_TAG, "Failed to setBlockUninstallForUser", re);
            }
        });
        if (uninstallBlocked) {
            final PackageManagerInternal pmi = LocalServices.getService(
                    PackageManagerInternal.class);
            pmi.removeNonSystemPackageSuspensions(packageName, userId);
            pmi.removeDistractingPackageRestrictions(packageName, userId);
            pmi.flushPackageRestrictions(userId);
        }
    }
    @Override
    public boolean isUninstallBlocked(ComponentName who, String packageName) {
        // This function should return true if and only if the package is blocked by
+101 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 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.app.admin.PolicyUpdatesReceiver.EXTRA_PACKAGE_NAME;
import static android.app.admin.PolicyUpdatesReceiver.EXTRA_POLICY_BUNDLE_KEY;

import android.annotation.Nullable;
import android.os.Bundle;

import com.android.modules.utils.TypedXmlPullParser;
import com.android.modules.utils.TypedXmlSerializer;

import org.xmlpull.v1.XmlPullParserException;

import java.io.IOException;
import java.util.Objects;

/**
 * Class used to identify a policy that relates to a certain package in the policy engine's data
 * structure.
 */
final class PackageSpecificPolicyKey extends PolicyKey {
    private static final String ATTR_POLICY_KEY = "policy-key";
    private static final String ATTR_PACKAGE_NAME = "package-name";
    private static final String ATTR_PERMISSION_NAME = "permission-name";

    private final String mPackageName;

    PackageSpecificPolicyKey(String key, String packageName) {
        super(key);
        mPackageName = Objects.requireNonNull((packageName));
    }

    PackageSpecificPolicyKey(String key) {
        super(key);
        mPackageName = null;
    }

    @Nullable
    String getPackageName() {
        return mPackageName;
    }

    @Override
    void saveToXml(TypedXmlSerializer serializer) throws IOException {
        serializer.attribute(/* namespace= */ null, ATTR_POLICY_KEY, mKey);
        serializer.attribute(/* namespace= */ null, ATTR_PACKAGE_NAME, mPackageName);
    }

    @Override
    PackageSpecificPolicyKey readFromXml(TypedXmlPullParser parser)
            throws XmlPullParserException, IOException {
        String policyKey = parser.getAttributeValue(/* namespace= */ null, ATTR_POLICY_KEY);
        String packageName = parser.getAttributeValue(/* namespace= */ null, ATTR_PACKAGE_NAME);
        String permissionName = parser.getAttributeValue(
                /* namespace= */ null, ATTR_PERMISSION_NAME);
        return new PackageSpecificPolicyKey(policyKey, packageName);
    }

    @Override
    void writeToBundle(Bundle bundle) {
        super.writeToBundle(bundle);
        Bundle extraPolicyParams = new Bundle();
        extraPolicyParams.putString(EXTRA_PACKAGE_NAME, mPackageName);
        bundle.putBundle(EXTRA_POLICY_BUNDLE_KEY, extraPolicyParams);
    }

    @Override
    public boolean equals(@Nullable Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        PackageSpecificPolicyKey other = (PackageSpecificPolicyKey) o;
        return Objects.equals(mKey, other.mKey)
                && Objects.equals(mPackageName, other.mPackageName);
    }

    @Override
    public int hashCode() {
        return Objects.hash(mKey, mPackageName);
    }

    @Override
    public String toString() {
        return "mPolicyKey= " + mKey + "; mPackageName= " + mPackageName;
    }
}
+37 −5
Original line number Diff line number Diff line
@@ -47,6 +47,9 @@ final class PolicyDefinition<V> {
    private static final MostRestrictive<Boolean> FALSE_MORE_RESTRICTIVE = new MostRestrictive<>(
            List.of(false, true));

    private static final MostRestrictive<Boolean> TRUE_MORE_RESTRICTIVE = new MostRestrictive<>(
            List.of(true, false));

    static PolicyDefinition<Boolean> AUTO_TIMEZONE = new PolicyDefinition<>(
            new DefaultPolicyKey(DevicePolicyManager.AUTO_TIMEZONE_POLICY),
            // auto timezone is enabled by default, hence disabling it is more restrictive.
@@ -102,7 +105,7 @@ final class PolicyDefinition<V> {
            new LockTaskPolicy.LockTaskPolicySerializer());

    static PolicyDefinition<Set<String>> USER_CONTROLLED_DISABLED_PACKAGES = new PolicyDefinition<>(
            new DefaultPolicyKey(DevicePolicyManager.USER_CONTROL_DISABLED_PACKAGES),
            new DefaultPolicyKey(DevicePolicyManager.USER_CONTROL_DISABLED_PACKAGES_POLICY),
            new SetUnion<>(),
            (Set<String> value, Context context, Integer userId, PolicyKey policyKey) ->
                    PolicyEnforcerCallbacks.setUserControlDisabledPackages(value, userId),
@@ -114,7 +117,7 @@ final class PolicyDefinition<V> {
    static PolicyDefinition<ComponentName> GENERIC_PERSISTENT_PREFERRED_ACTIVITY =
            new PolicyDefinition<>(
                    new PersistentPreferredActivityPolicyKey(
                            DevicePolicyManager.PERSISTENT_PREFERRED_ACTIVITY),
                            DevicePolicyManager.PERSISTENT_PREFERRED_ACTIVITY_POLICY),
            new TopPriority<>(List.of(
                    // TODO(b/258166155): add correct device lock role name
                    EnforcingAdmin.getRoleAuthorityOf("DeviceLock"),
@@ -134,15 +137,44 @@ final class PolicyDefinition<V> {
        }
        return GENERIC_PERSISTENT_PREFERRED_ACTIVITY.createPolicyDefinition(
                new PersistentPreferredActivityPolicyKey(
                        DevicePolicyManager.PERSISTENT_PREFERRED_ACTIVITY, intentFilter));
                        DevicePolicyManager.PERSISTENT_PREFERRED_ACTIVITY_POLICY, intentFilter));
    }

    // This is saved in the static map sPolicyDefinitions so that we're able to reconstruct the
    // actual uninstall blocked policy with the correct arguments (i.e. packageName)
    // when reading the policies from xml.
    static PolicyDefinition<Boolean> GENERIC_PACKAGE_UNINSTALL_BLOCKED =
            new PolicyDefinition<>(
                    new PackageSpecificPolicyKey(
                            DevicePolicyManager.PACKAGE_UNINSTALL_BLOCKED_POLICY),
                    TRUE_MORE_RESTRICTIVE,
                    POLICY_FLAG_LOCAL_ONLY_POLICY,
                    PolicyEnforcerCallbacks::setUninstallBlocked,
                    new BooleanPolicySerializer());

    /**
     * Passing in {@code null} for {@code packageName} will return
     * {@link #GENERIC_PACKAGE_UNINSTALL_BLOCKED}.
     */
    static PolicyDefinition<Boolean> PACKAGE_UNINSTALL_BLOCKED(
            String packageName) {
        if (packageName == null) {
            return GENERIC_PACKAGE_UNINSTALL_BLOCKED;
        }
        return GENERIC_PACKAGE_UNINSTALL_BLOCKED.createPolicyDefinition(
                new PackageSpecificPolicyKey(
                        DevicePolicyManager.PACKAGE_UNINSTALL_BLOCKED_POLICY, packageName));
    }

    private static final Map<String, PolicyDefinition<?>> sPolicyDefinitions = Map.of(
            DevicePolicyManager.AUTO_TIMEZONE_POLICY, AUTO_TIMEZONE,
            DevicePolicyManager.PERMISSION_GRANT_POLICY_KEY, GENERIC_PERMISSION_GRANT,
            DevicePolicyManager.LOCK_TASK_POLICY, LOCK_TASK,
            DevicePolicyManager.USER_CONTROL_DISABLED_PACKAGES, USER_CONTROLLED_DISABLED_PACKAGES,
            DevicePolicyManager.PERSISTENT_PREFERRED_ACTIVITY, GENERIC_PERSISTENT_PREFERRED_ACTIVITY
            DevicePolicyManager.USER_CONTROL_DISABLED_PACKAGES_POLICY,
            USER_CONTROLLED_DISABLED_PACKAGES,
            DevicePolicyManager.PERSISTENT_PREFERRED_ACTIVITY_POLICY,
            GENERIC_PERSISTENT_PREFERRED_ACTIVITY,
            DevicePolicyManager.PACKAGE_UNINSTALL_BLOCKED_POLICY, GENERIC_PACKAGE_UNINSTALL_BLOCKED
    );


+18 −0
Original line number Diff line number Diff line
@@ -179,4 +179,22 @@ final class PolicyEnforcerCallbacks {
        });
        return true;
    }

    static boolean setUninstallBlocked(
            @Nullable Boolean uninstallBlocked, @NonNull Context context, int userId,
            @NonNull PolicyKey policyKey) {
        return Boolean.TRUE.equals(Binder.withCleanCallingIdentity(() -> {
            if (!(policyKey instanceof PackageSpecificPolicyKey)) {
                throw new IllegalArgumentException("policyKey is not of type "
                        + "PackageSpecificPolicyKey");
            }
            PackageSpecificPolicyKey parsedKey = (PackageSpecificPolicyKey) policyKey;
            String packageName = Objects.requireNonNull(parsedKey.getPackageName());
            DevicePolicyManagerService.setUninstallBlockedUnchecked(
                    packageName,
                    uninstallBlocked != null && uninstallBlocked,
                    userId);
            return true;
        }));
    }
}