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

Commit ee3a15d4 authored by Sooraj Sasindran's avatar Sooraj Sasindran
Browse files

Store preferential network service config in xml

Bug: 227338666
Test: verified using manual test that config is persistent
Change-Id: I0cc2e7395ef9530a8ebdd27fcf7a791a7f126367
parent 6584dbb6
Loading
Loading
Loading
Loading
+161 −2
Original line number Diff line number Diff line
@@ -16,15 +16,31 @@

package android.app.admin;

import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
import static org.xmlpull.v1.XmlPullParser.END_TAG;
import static org.xmlpull.v1.XmlPullParser.TEXT;

import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.SuppressLint;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.IndentingPrintWriter;
import android.util.Log;
import android.util.TypedXmlPullParser;
import android.util.TypedXmlSerializer;

import org.xmlpull.v1.XmlPullParserException;

import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * Network configuration to be set for the user profile
@@ -37,6 +53,20 @@ public final class PreferentialNetworkServiceConfig implements Parcelable {
    final int[] mIncludedUids;
    final int[] mExcludedUids;

    private static final String LOG_TAG = "PreferentialNetworkServiceConfig";
    private static final String TAG_PREFERENTIAL_NETWORK_SERVICE_CONFIG =
            "preferential_network_service_config";
    private static final String TAG_CONFIG_ENABLED =
            "preferential_network_service_config_enabled";
    private static final String TAG_UID = "uid";
    private static final String TAG_NETWORK_ID =
            "preferential_network_service_network_id";
    private static final String TAG_ALLOW_FALLBACK_TO_DEFAULT_CONNECTION =
            "allow_fallback_to_default_connection";
    private static final String TAG_INCLUDED_UIDS = "included_uids";
    private static final String TAG_EXCLUDED_UIDS = "excluded_uids";
    private static final String ATTR_VALUE = "value";

    /** @hide */
    public static final PreferentialNetworkServiceConfig DEFAULT =
            (new PreferentialNetworkServiceConfig.Builder()).build();
@@ -159,8 +189,8 @@ public final class PreferentialNetworkServiceConfig implements Parcelable {
        return "PreferentialNetworkServiceConfig{"
                + "mIsEnabled=" + isEnabled()
                + "mAllowFallbackToDefaultConnection=" + isFallbackToDefaultConnectionAllowed()
                + "mIncludedUids=" + mIncludedUids.toString()
                + "mExcludedUids=" + mExcludedUids.toString()
                + "mIncludedUids=" + Arrays.toString(mIncludedUids)
                + "mExcludedUids=" + Arrays.toString(mExcludedUids)
                + "mNetworkId=" + mNetworkId
                + '}';
    }
@@ -309,6 +339,135 @@ public final class PreferentialNetworkServiceConfig implements Parcelable {
        dest.writeIntArray(mExcludedUids);
    }

    private void writeAttributeValueToXml(TypedXmlSerializer out, String tag, int value)
            throws IOException {
        out.startTag(null, tag);
        out.attributeInt(null, ATTR_VALUE, value);
        out.endTag(null, tag);
    }

    private void writeAttributeValueToXml(TypedXmlSerializer out, String tag, boolean value)
            throws IOException {
        out.startTag(null, tag);
        out.attributeBoolean(null, ATTR_VALUE, value);
        out.endTag(null, tag);
    }

    private void writeAttributeValuesToXml(TypedXmlSerializer out, String outerTag, String innerTag,
            @NonNull Collection<String> values) throws IOException {
        out.startTag(null, outerTag);
        for (String value : values) {
            out.startTag(null, innerTag);
            out.attribute(null, ATTR_VALUE, value);
            out.endTag(null, innerTag);
        }
        out.endTag(null, outerTag);
    }

    private static  void readAttributeValues(
            TypedXmlPullParser parser, String tag, Collection<String> result)
            throws XmlPullParserException, IOException {
        result.clear();
        int outerDepthDAM = parser.getDepth();
        int typeDAM;
        while ((typeDAM = parser.next()) != END_DOCUMENT
                && (typeDAM != END_TAG || parser.getDepth() > outerDepthDAM)) {
            if (typeDAM == END_TAG || typeDAM == TEXT) {
                continue;
            }
            String tagDAM = parser.getName();
            if (tag.equals(tagDAM)) {
                result.add(parser.getAttributeValue(null, ATTR_VALUE));
            } else {
                Log.e(LOG_TAG, "Expected tag " + tag + " but found " + tagDAM);
            }
        }
    }

    private List<String> intArrayToStringList(int[] array) {
        return Arrays.stream(array).mapToObj(String::valueOf).collect(Collectors.toList());
    }

    private static int[] readStringListToIntArray(TypedXmlPullParser parser, String tag)
            throws XmlPullParserException, IOException {
        List<String> stringList = new ArrayList<>();
        readAttributeValues(parser, tag, stringList);
        int[] intArray = stringList.stream()
                .map(s -> Integer.parseInt(s))
                .mapToInt(Integer::intValue)
                .toArray();
        return intArray;
    }

    /**
     * @hide
     */
    public static PreferentialNetworkServiceConfig getPreferentialNetworkServiceConfig(
            TypedXmlPullParser parser, String tag) throws XmlPullParserException, IOException  {
        int outerDepthDAM = parser.getDepth();
        int typeDAM;
        PreferentialNetworkServiceConfig.Builder resultBuilder =
                new PreferentialNetworkServiceConfig.Builder();
        while ((typeDAM = parser.next()) != END_DOCUMENT
                && (typeDAM != END_TAG || parser.getDepth() > outerDepthDAM)) {
            if (typeDAM == END_TAG || typeDAM == TEXT) {
                continue;
            }
            String tagDAM = parser.getName();
            if (TAG_CONFIG_ENABLED.equals(tagDAM)) {
                resultBuilder.setEnabled(parser.getAttributeBoolean(null, ATTR_VALUE,
                        DevicePolicyManager.PREFERENTIAL_NETWORK_SERVICE_ENABLED_DEFAULT));
            } else if (TAG_NETWORK_ID.equals(tagDAM)) {
                int val = parser.getAttributeInt(null, ATTR_VALUE, 0);
                if (val != 0) {
                    resultBuilder.setNetworkId(val);
                }
            } else if (TAG_ALLOW_FALLBACK_TO_DEFAULT_CONNECTION.equals(tagDAM)) {
                resultBuilder.setFallbackToDefaultConnectionAllowed(parser.getAttributeBoolean(
                        null, ATTR_VALUE, true));
            } else if (TAG_INCLUDED_UIDS.equals(tagDAM)) {
                resultBuilder.setIncludedUids(readStringListToIntArray(parser, TAG_UID));
            } else if (TAG_EXCLUDED_UIDS.equals(tagDAM)) {
                resultBuilder.setExcludedUids(readStringListToIntArray(parser, TAG_UID));
            } else {
                Log.w(LOG_TAG, "Unknown tag under " + tag + ": " + tagDAM);
            }
        }
        return resultBuilder.build();
    }

    /**
     * @hide
     */
    public void writeToXml(@NonNull TypedXmlSerializer out) throws IOException {
        out.startTag(null, TAG_PREFERENTIAL_NETWORK_SERVICE_CONFIG);
        writeAttributeValueToXml(out, TAG_CONFIG_ENABLED, isEnabled());
        writeAttributeValueToXml(out, TAG_NETWORK_ID, getNetworkId());
        writeAttributeValueToXml(out, TAG_ALLOW_FALLBACK_TO_DEFAULT_CONNECTION,
                isFallbackToDefaultConnectionAllowed());
        writeAttributeValuesToXml(out, TAG_INCLUDED_UIDS, TAG_UID,
                intArrayToStringList(getIncludedUids()));
        writeAttributeValuesToXml(out, TAG_EXCLUDED_UIDS, TAG_UID,
                intArrayToStringList(getExcludedUids()));
        out.endTag(null, TAG_PREFERENTIAL_NETWORK_SERVICE_CONFIG);
    }

    /**
     * @hide
     */
    public void dump(IndentingPrintWriter pw) {
        pw.print("networkId=");
        pw.println(mNetworkId);
        pw.print("isEnabled=");
        pw.println(mIsEnabled);
        pw.print("allowFallbackToDefaultConnection=");
        pw.println(mAllowFallbackToDefaultConnection);
        pw.print("includedUids=");
        pw.println(mIncludedUids);
        pw.print("excludedUids=");
        pw.println(mExcludedUids);
    }

    @Override
    public int describeContents() {
        return 0;
+65 −8
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_NONE;
import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
import static android.app.admin.WifiSsidPolicy.WIFI_SSID_POLICY_TYPE_ALLOWLIST;
import static android.app.admin.WifiSsidPolicy.WIFI_SSID_POLICY_TYPE_DENYLIST;
import static android.net.NetworkCapabilities.NET_ENTERPRISE_ID_1;

import static com.android.server.devicepolicy.DevicePolicyManagerService.LOG_TAG;

@@ -159,6 +160,10 @@ class ActiveAdmin {
    private static final String ATTR_VALUE = "value";
    private static final String ATTR_LAST_NETWORK_LOGGING_NOTIFICATION = "last-notification";
    private static final String ATTR_NUM_NETWORK_LOGGING_NOTIFICATIONS = "num-notifications";
    private static final String TAG_PREFERENTIAL_NETWORK_SERVICE_CONFIGS =
            "preferential_network_service_configs";
    private static final String TAG_PREFERENTIAL_NETWORK_SERVICE_CONFIG =
            "preferential_network_service_config";

    DeviceAdminInfo info;

@@ -587,8 +592,6 @@ class ActiveAdmin {
        }
        writeAttributeValueToXml(out, TAG_ADMIN_CAN_GRANT_SENSORS_PERMISSIONS,
                mAdminCanGrantSensorsPermissions);
        writeAttributeValueToXml(out, TAG_PREFERENTIAL_NETWORK_SERVICE_ENABLED,
                mPreferentialNetworkServiceEnabled);
        if (mUsbDataSignalingEnabled != USB_DATA_SIGNALING_ENABLED_DEFAULT) {
            writeAttributeValueToXml(out, TAG_USB_DATA_SIGNALING, mUsbDataSignalingEnabled);
        }
@@ -603,6 +606,13 @@ class ActiveAdmin {
                writeAttributeValuesToXml(out, TAG_SSID_DENYLIST, TAG_SSID, ssids);
            }
        }
        if (!mPreferentialNetworkServiceConfigs.isEmpty()) {
            out.startTag(null, TAG_PREFERENTIAL_NETWORK_SERVICE_CONFIGS);
            for (PreferentialNetworkServiceConfig config : mPreferentialNetworkServiceConfigs) {
                config.writeToXml(out);
            }
            out.endTag(null, TAG_PREFERENTIAL_NETWORK_SERVICE_CONFIGS);
        }
    }

    private List<String> ssidsToStrings(Set<WifiSsid> ssids) {
@@ -833,6 +843,14 @@ class ActiveAdmin {
            } else if (TAG_PREFERENTIAL_NETWORK_SERVICE_ENABLED.equals(tag)) {
                mPreferentialNetworkServiceEnabled = parser.getAttributeBoolean(null, ATTR_VALUE,
                        DevicePolicyManager.PREFERENTIAL_NETWORK_SERVICE_ENABLED_DEFAULT);
                if (mPreferentialNetworkServiceEnabled) {
                    PreferentialNetworkServiceConfig.Builder configBuilder =
                            new PreferentialNetworkServiceConfig.Builder();
                    configBuilder.setEnabled(mPreferentialNetworkServiceEnabled);
                    configBuilder.setNetworkId(NET_ENTERPRISE_ID_1);
                    mPreferentialNetworkServiceConfigs = List.of(configBuilder.build());
                    mPreferentialNetworkServiceEnabled = false;
                }
            } else if (TAG_COMMON_CRITERIA_MODE.equals(tag)) {
                mCommonCriteriaMode = parser.getAttributeBoolean(null, ATTR_VALUE, false);
            } else if (TAG_PASSWORD_COMPLEXITY.equals(tag)) {
@@ -871,6 +889,12 @@ class ActiveAdmin {
                List<WifiSsid> ssids = readWifiSsids(parser, TAG_SSID);
                mWifiSsidPolicy = new WifiSsidPolicy(
                        WIFI_SSID_POLICY_TYPE_DENYLIST, new ArraySet<>(ssids));
            } else if (TAG_PREFERENTIAL_NETWORK_SERVICE_CONFIGS.equals(tag)) {
                List<PreferentialNetworkServiceConfig> configs =
                        getPreferentialNetworkServiceConfigs(parser, tag);
                if (!configs.isEmpty()) {
                    mPreferentialNetworkServiceConfigs = configs;
                }
            } else {
                Slogf.w(LOG_TAG, "Unknown admin tag: %s", tag);
                XmlUtils.skipCurrentTag(parser);
@@ -956,19 +980,43 @@ class ActiveAdmin {
        return result;
    }

    private TrustAgentInfo getTrustAgentInfo(TypedXmlPullParser parser, String tag)
    private TrustAgentInfo getTrustAgentInfo(TypedXmlPullParser parser, String outerTag)
            throws XmlPullParserException, IOException  {
        int outerDepthDAM = parser.getDepth();
        int typeDAM;
        int outerDepth = parser.getDepth();
        int type;
        TrustAgentInfo result = new TrustAgentInfo(null);
        while ((type = parser.next()) != END_DOCUMENT
                && (type != END_TAG || parser.getDepth() > outerDepth)) {
            if (type == END_TAG || type == TEXT) {
                continue;
            }
            String tag = parser.getName();
            if (TAG_TRUST_AGENT_COMPONENT_OPTIONS.equals(tag)) {
                result.options = PersistableBundle.restoreFromXml(parser);
            } else {
                Slogf.w(LOG_TAG, "Unknown tag under %s: %s", outerTag, tag);
            }
        }
        return result;
    }

    @NonNull
    private List<PreferentialNetworkServiceConfig> getPreferentialNetworkServiceConfigs(
            TypedXmlPullParser parser, String tag) throws XmlPullParserException, IOException {
        int outerDepth = parser.getDepth();
        int typeDAM;
        final List<PreferentialNetworkServiceConfig> result = new ArrayList<>();
        while ((typeDAM = parser.next()) != END_DOCUMENT
                && (typeDAM != END_TAG || parser.getDepth() > outerDepthDAM)) {
            && (typeDAM != END_TAG || parser.getDepth() > outerDepth)) {
            if (typeDAM == END_TAG || typeDAM == TEXT) {
                continue;
            }
            String tagDAM = parser.getName();
            if (TAG_TRUST_AGENT_COMPONENT_OPTIONS.equals(tagDAM)) {
                result.options = PersistableBundle.restoreFromXml(parser);
            if (TAG_PREFERENTIAL_NETWORK_SERVICE_CONFIG.equals(tagDAM)) {
                final PreferentialNetworkServiceConfig preferentialNetworkServiceConfig =
                        PreferentialNetworkServiceConfig.getPreferentialNetworkServiceConfig(
                                parser, tag);
                result.add(preferentialNetworkServiceConfig);
            } else {
                Slogf.w(LOG_TAG, "Unknown tag under %s: %s", tag, tagDAM);
            }
@@ -1258,5 +1306,14 @@ class ActiveAdmin {
            mFactoryResetProtectionPolicy.dump(pw);
            pw.decreaseIndent();
        }

        if (mPreferentialNetworkServiceConfigs != null) {
            pw.println("mPreferentialNetworkServiceConfigs:");
            pw.increaseIndent();
            for (PreferentialNetworkServiceConfig config : mPreferentialNetworkServiceConfigs) {
                config.dump(pw);
            }
            pw.decreaseIndent();
        }
    }
}
+8 −4
Original line number Diff line number Diff line
@@ -18251,16 +18251,20 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
                    preferenceBuilder.setPreference(
                            PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK);
                }
                preferenceBuilder.setIncludedUids(
                        preferentialNetworkServiceConfig.getIncludedUids());
                preferenceBuilder.setExcludedUids(
                        preferentialNetworkServiceConfig.getExcludedUids());
                preferenceBuilder.setPreferenceEnterpriseId(
                        preferentialNetworkServiceConfig.getNetworkId());
            } else {
                preferenceBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_DEFAULT);
            }
            preferenceBuilder.setIncludedUids(preferentialNetworkServiceConfig.getIncludedUids());
            preferenceBuilder.setExcludedUids(preferentialNetworkServiceConfig.getExcludedUids());
            preferenceBuilder.setPreferenceEnterpriseId(
                    preferentialNetworkServiceConfig.getNetworkId());
            preferences.add(preferenceBuilder.build());
        }
        Slogf.d(LOG_TAG, "updateNetworkPreferenceForUser to " + preferences);
        mInjector.binderWithCleanCallingIdentity(() ->
                mInjector.getConnectivityManager().setProfileNetworkPreferences(
                        UserHandle.of(userId), preferences,