diff options
3 files changed, 234 insertions, 14 deletions
diff --git a/core/java/android/app/admin/PreferentialNetworkServiceConfig.java b/core/java/android/app/admin/PreferentialNetworkServiceConfig.java index 54170a2a187f..24b4f4b99ad0 100644 --- a/core/java/android/app/admin/PreferentialNetworkServiceConfig.java +++ b/core/java/android/app/admin/PreferentialNetworkServiceConfig.java @@ -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; diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java b/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java index aca138935491..3912991a41ed 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java @@ -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(); + } } } diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 18bffebb427c..cb205de87e39 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -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, |