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

Commit 9088ec46 authored by Kholoud Mohamed's avatar Kholoud Mohamed Committed by Android (Google) Code Review
Browse files

Merge "cleanup up appRestrictions policy in the policy engine" into udc-dev

parents ca08538c 4da93f5a
Loading
Loading
Loading
Loading
+13 −97
Original line number Diff line number Diff line
@@ -17,50 +17,28 @@
package com.android.server.devicepolicy;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.admin.BundlePolicyValue;
import android.app.admin.PackagePolicyKey;
import android.app.admin.PolicyKey;
import android.os.Bundle;
import android.os.Environment;
import android.os.Parcelable;
import android.util.AtomicFile;
import android.util.Slog;
import android.util.Xml;
import android.util.Log;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.XmlUtils;
import com.android.modules.utils.TypedXmlPullParser;
import com.android.modules.utils.TypedXmlSerializer;

import libcore.io.IoUtils;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Objects;

// TODO(b/266704763): clean this up and stop creating separate files for each value, the code here
//  is copied from UserManagerService, however it doesn't currently handle setting different
//  restrictions for the same package in different users, it also will not remove the files for
//  outdated restrictions, this will all get fixed when we save it as part of the policies file
//  rather than in its own files.
final class BundlePolicySerializer extends PolicySerializer<Bundle> {

    private static final String TAG = "BundlePolicySerializer";

    private static final String ATTR_FILE_NAME = "file-name";

    private static final String RESTRICTIONS_FILE_PREFIX = "AppRestrictions_";
    private static final String XML_SUFFIX = ".xml";

    private static final String TAG_RESTRICTIONS = "restrictions";
    private static final String TAG_ENTRY = "entry";
    private static final String TAG_VALUE = "value";
    private static final String ATTR_KEY = "key";
@@ -83,62 +61,26 @@ final class BundlePolicySerializer extends PolicySerializer<Bundle> {
            throw new IllegalArgumentException("policyKey is not of type "
                    + "PackagePolicyKey");
        }
        String packageName = ((PackagePolicyKey) policyKey).getPackageName();
        String fileName = packageToRestrictionsFileName(packageName, value);
        writeApplicationRestrictionsLAr(fileName, value);
        serializer.attribute(/* namespace= */ null, ATTR_FILE_NAME, fileName);
        writeBundle(value, serializer);
    }

    @Nullable
    @Override
    BundlePolicyValue readFromXml(TypedXmlPullParser parser) {
        String fileName = parser.getAttributeValue(/* namespace= */ null, ATTR_FILE_NAME);

        return new BundlePolicyValue(readApplicationRestrictions(fileName));
    }

    private static String packageToRestrictionsFileName(String packageName, Bundle restrictions) {
        return RESTRICTIONS_FILE_PREFIX + packageName + Objects.hash(restrictions) + XML_SUFFIX;
    }

    @GuardedBy("mAppRestrictionsLock")
    private static Bundle readApplicationRestrictions(String fileName) {
        AtomicFile restrictionsFile =
                new AtomicFile(new File(Environment.getDataSystemDirectory(), fileName));
        return readApplicationRestrictions(restrictionsFile);
    }

    @VisibleForTesting
    @GuardedBy("mAppRestrictionsLock")
    static Bundle readApplicationRestrictions(AtomicFile restrictionsFile) {
        final Bundle restrictions = new Bundle();
        final ArrayList<String> values = new ArrayList<>();
        if (!restrictionsFile.getBaseFile().exists()) {
            return restrictions;
        }

        FileInputStream fis = null;
        Bundle bundle = new Bundle();
        ArrayList<String> values = new ArrayList<>();
        try {
            fis = restrictionsFile.openRead();
            final TypedXmlPullParser parser = Xml.resolvePullParser(fis);
            XmlUtils.nextElement(parser);
            if (parser.getEventType() != XmlPullParser.START_TAG) {
                Slog.e(TAG, "Unable to read restrictions file "
                        + restrictionsFile.getBaseFile());
                return restrictions;
            }
            while (parser.next() != XmlPullParser.END_DOCUMENT) {
                readEntry(restrictions, values, parser);
            final int outerDepth = parser.getDepth();
            while (XmlUtils.nextElementWithin(parser, outerDepth)) {
                readBundle(bundle, values, parser);
            }
        } catch (IOException | XmlPullParserException e) {
            Slog.w(TAG, "Error parsing " + restrictionsFile.getBaseFile(), e);
        } finally {
            IoUtils.closeQuietly(fis);
        } catch (XmlPullParserException | IOException e) {
            Log.e(TAG, "Error parsing Bundle policy.", e);
            return null;
        }
        return restrictions;
        return new BundlePolicyValue(bundle);
    }

    private static void readEntry(Bundle restrictions, ArrayList<String> values,
    private static void readBundle(Bundle restrictions, ArrayList<String> values,
            TypedXmlPullParser parser) throws XmlPullParserException, IOException {
        int type = parser.getEventType();
        if (type == XmlPullParser.START_TAG && parser.getName().equals(TAG_ENTRY)) {
@@ -186,37 +128,11 @@ final class BundlePolicySerializer extends PolicySerializer<Bundle> {
        Bundle childBundle = new Bundle();
        int outerDepth = parser.getDepth();
        while (XmlUtils.nextElementWithin(parser, outerDepth)) {
            readEntry(childBundle, values, parser);
            readBundle(childBundle, values, parser);
        }
        return childBundle;
    }

    private static void writeApplicationRestrictionsLAr(String fileName, Bundle restrictions) {
        AtomicFile restrictionsFile = new AtomicFile(
                new File(Environment.getDataSystemDirectory(), fileName));
        writeApplicationRestrictionsLAr(restrictions, restrictionsFile);
    }

    static void writeApplicationRestrictionsLAr(Bundle restrictions, AtomicFile restrictionsFile) {
        FileOutputStream fos = null;
        try {
            fos = restrictionsFile.startWrite();
            final TypedXmlSerializer serializer = Xml.resolveSerializer(fos);
            serializer.startDocument(null, true);
            serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);

            serializer.startTag(null, TAG_RESTRICTIONS);
            writeBundle(restrictions, serializer);
            serializer.endTag(null, TAG_RESTRICTIONS);

            serializer.endDocument();
            restrictionsFile.finishWrite(fos);
        } catch (Exception e) {
            restrictionsFile.failWrite(fos);
            Slog.e(TAG, "Error writing application restrictions list", e);
        }
    }

    private static void writeBundle(Bundle restrictions, TypedXmlSerializer serializer)
            throws IOException {
        for (String key : restrictions.keySet()) {
+21 −11
Original line number Diff line number Diff line
@@ -11053,7 +11053,6 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
        }
        if (!isPermissionCheckFlagEnabled() && !isPolicyEngineForFinanceFlagEnabled()) {
            // TODO: Figure out if something like this needs to be restored for policy engine
            final ComponentName profileOwner = getProfileOwnerAsUser(userId);
            if (profileOwner == null) {
                return false;
@@ -11640,7 +11639,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
                        caller.getUserId());
            }
            setBackwardsCompatibleAppRestrictions(
                    packageName, restrictions, caller.getUserHandle());
                    caller, packageName, restrictions, caller.getUserHandle());
        } else {
            Preconditions.checkCallAuthorization((caller.hasAdminComponent()
                    && (isProfileOwner(caller) || isDefaultDeviceOwner(caller)))
@@ -11661,17 +11660,28 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
    }
    /**
     * Set app restrictions in user manager to keep backwards compatibility for the old
     * getApplicationRestrictions API.
     * Set app restrictions in user manager for DPC callers only to keep backwards compatibility
     * for the old getApplicationRestrictions API.
     */
    private void setBackwardsCompatibleAppRestrictions(
            String packageName, Bundle restrictions, UserHandle userHandle) {
            CallerIdentity caller, String packageName, Bundle restrictions, UserHandle userHandle) {
        if ((caller.hasAdminComponent() && (isProfileOwner(caller) || isDefaultDeviceOwner(caller)))
                || (caller.hasPackage() && isCallerDelegate(caller, DELEGATION_APP_RESTRICTIONS))) {
            Bundle restrictionsToApply = restrictions == null || restrictions.isEmpty()
                    ? getAppRestrictionsSetByAnyAdmin(packageName, userHandle)
                    : restrictions;
            mInjector.binderWithCleanCallingIdentity(() -> {
            mUserManager.setApplicationRestrictions(packageName, restrictionsToApply, userHandle);
                mUserManager.setApplicationRestrictions(packageName, restrictionsToApply,
                        userHandle);
            });
        } else {
            // Notify package of changes via an intent - only sent to explicitly registered
            // receivers. Sending here because For DPCs, this is being sent in UMS.
            final Intent changeIntent = new Intent(Intent.ACTION_APPLICATION_RESTRICTIONS_CHANGED);
            changeIntent.setPackage(packageName);
            changeIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
            mContext.sendBroadcastAsUser(changeIntent, userHandle);
        }
    }
    private Bundle getAppRestrictionsSetByAnyAdmin(String packageName, UserHandle userHandle) {