From 1063207d4c3ee2916daf53d1696240fd401acd24 Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Tue, 10 Jan 2023 18:56:09 +0900 Subject: [PATCH] Implement an API to block non-enterprise networks Test: New CTS in aosp/2384597 Change-Id: I0931cf120ea487c6c5fb2eead6608a94bd6183cc --- core/api/current.txt | 2 + .../PreferentialNetworkServiceConfig.java | 103 ++++++++++++++++-- .../DevicePolicyManagerService.java | 4 + 3 files changed, 99 insertions(+), 10 deletions(-) diff --git a/core/api/current.txt b/core/api/current.txt index a0c132f980dc..6ca5c4f32d0c 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -7890,6 +7890,7 @@ package android.app.admin { method public int getNetworkId(); method public boolean isEnabled(); method public boolean isFallbackToDefaultConnectionAllowed(); + method public boolean shouldBlockNonMatchingNetworks(); method public void writeToParcel(@NonNull android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator CREATOR; field public static final int PREFERENTIAL_NETWORK_ID_1 = 1; // 0x1 @@ -7907,6 +7908,7 @@ package android.app.admin { method @NonNull public android.app.admin.PreferentialNetworkServiceConfig.Builder setFallbackToDefaultConnectionAllowed(boolean); method @NonNull public android.app.admin.PreferentialNetworkServiceConfig.Builder setIncludedUids(@NonNull int[]); method @NonNull public android.app.admin.PreferentialNetworkServiceConfig.Builder setNetworkId(int); + method @NonNull public android.app.admin.PreferentialNetworkServiceConfig.Builder setShouldBlockNonMatchingNetworks(boolean); } public class SecurityLog { diff --git a/core/java/android/app/admin/PreferentialNetworkServiceConfig.java b/core/java/android/app/admin/PreferentialNetworkServiceConfig.java index 63c9839a87e3..1e0d0628c310 100644 --- a/core/java/android/app/admin/PreferentialNetworkServiceConfig.java +++ b/core/java/android/app/admin/PreferentialNetworkServiceConfig.java @@ -50,6 +50,7 @@ public final class PreferentialNetworkServiceConfig implements Parcelable { final boolean mIsEnabled; final int mNetworkId; final boolean mAllowFallbackToDefaultConnection; + final boolean mShouldBlockNonMatchingNetworks; final int[] mIncludedUids; final int[] mExcludedUids; @@ -63,6 +64,8 @@ public final class PreferentialNetworkServiceConfig implements Parcelable { "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_BLOCK_NON_MATCHING_NETWORKS = + "block_non_matching_networks"; 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"; @@ -110,10 +113,12 @@ public final class PreferentialNetworkServiceConfig implements Parcelable { } private PreferentialNetworkServiceConfig(boolean isEnabled, - boolean allowFallbackToDefaultConnection, int[] includedUids, + boolean allowFallbackToDefaultConnection, boolean shouldBlockNonMatchingNetworks, + int[] includedUids, int[] excludedUids, @PreferentialNetworkPreferenceId int networkId) { mIsEnabled = isEnabled; mAllowFallbackToDefaultConnection = allowFallbackToDefaultConnection; + mShouldBlockNonMatchingNetworks = shouldBlockNonMatchingNetworks; mIncludedUids = includedUids; mExcludedUids = excludedUids; mNetworkId = networkId; @@ -122,6 +127,7 @@ public final class PreferentialNetworkServiceConfig implements Parcelable { private PreferentialNetworkServiceConfig(Parcel in) { mIsEnabled = in.readBoolean(); mAllowFallbackToDefaultConnection = in.readBoolean(); + mShouldBlockNonMatchingNetworks = in.readBoolean(); mNetworkId = in.readInt(); mIncludedUids = in.createIntArray(); mExcludedUids = in.createIntArray(); @@ -136,15 +142,39 @@ public final class PreferentialNetworkServiceConfig implements Parcelable { } /** - * is fallback to default network allowed. This boolean configures whether default connection - * (default internet or wifi) should be used or not if a preferential network service - * connection is not available. + * Whether fallback to the device-wide default network is allowed. + * + * This boolean configures whether the default connection (e.g. general cell network or wifi) + * should be used if no preferential network service connection is available. If true, the + * default connection will be used when no preferential service is available. If false, the + * UIDs subject to this configuration will have no default network. + * Note that while this boolean determines whether the UIDs subject to this configuration have + * a default network in the absence of a preferential service, apps can still explicitly decide + * to use another network than their default network by requesting them from the system. This + * boolean does not determine whether the UIDs are blocked from using such other networks. + * See {@link #shouldBlockNonMatchingNetworks()} for that configuration. + * * @return true if fallback is allowed, else false. */ public boolean isFallbackToDefaultConnectionAllowed() { return mAllowFallbackToDefaultConnection; } + /** + * Whether to block UIDs from using other networks than the preferential service. + * + * Apps can inspect the list of available networks on the device and choose to use multiple + * of them concurrently for performance, privacy or other reasons. + * This boolean configures whether the concerned UIDs should be blocked from using + * networks that do not match the configured preferential network service even if these + * networks are otherwise open to all apps. + * + * @return true if UIDs should be blocked from using the other networks, else false. + */ + public boolean shouldBlockNonMatchingNetworks() { + return mShouldBlockNonMatchingNetworks; + } + /** * Get the array of uids that are applicable for the profile preference. * @@ -189,6 +219,7 @@ public final class PreferentialNetworkServiceConfig implements Parcelable { return "PreferentialNetworkServiceConfig{" + "mIsEnabled=" + isEnabled() + "mAllowFallbackToDefaultConnection=" + isFallbackToDefaultConnectionAllowed() + + "mBlockNonMatchingNetworks=" + shouldBlockNonMatchingNetworks() + "mIncludedUids=" + Arrays.toString(mIncludedUids) + "mExcludedUids=" + Arrays.toString(mExcludedUids) + "mNetworkId=" + mNetworkId @@ -202,6 +233,7 @@ public final class PreferentialNetworkServiceConfig implements Parcelable { final PreferentialNetworkServiceConfig that = (PreferentialNetworkServiceConfig) o; return mIsEnabled == that.mIsEnabled && mAllowFallbackToDefaultConnection == that.mAllowFallbackToDefaultConnection + && mShouldBlockNonMatchingNetworks == that.mShouldBlockNonMatchingNetworks && mNetworkId == that.mNetworkId && Arrays.equals(mIncludedUids, that.mIncludedUids) && Arrays.equals(mExcludedUids, that.mExcludedUids); @@ -210,7 +242,8 @@ public final class PreferentialNetworkServiceConfig implements Parcelable { @Override public int hashCode() { return Objects.hash(mIsEnabled, mAllowFallbackToDefaultConnection, - Arrays.hashCode(mIncludedUids), Arrays.hashCode(mExcludedUids), mNetworkId); + mShouldBlockNonMatchingNetworks, Arrays.hashCode(mIncludedUids), + Arrays.hashCode(mExcludedUids), mNetworkId); } /** @@ -221,6 +254,7 @@ public final class PreferentialNetworkServiceConfig implements Parcelable { boolean mIsEnabled = false; int mNetworkId = 0; boolean mAllowFallbackToDefaultConnection = true; + boolean mShouldBlockNonMatchingNetworks = false; int[] mIncludedUids = new int[0]; int[] mExcludedUids = new int[0]; @@ -242,10 +276,21 @@ public final class PreferentialNetworkServiceConfig implements Parcelable { } /** - * Set whether the default connection should be used as fallback. - * This boolean configures whether the default connection (default internet or wifi) - * should be used if a preferential network service connection is not available. - * Default value is true + * Set whether fallback to the device-wide default network is allowed. + * + * This boolean configures whether the default connection (e.g. general cell network or + * wifi) should be used if no preferential network service connection is available. If true, + * the default connection will be used when no preferential service is available. If false, + * the UIDs subject to this configuration will have no default network. + * Note that while this boolean determines whether the UIDs subject to this configuration + * have a default network in the absence of a preferential service, apps can still + * explicitly decide to use another network than their default network by requesting them + * from the system. This boolean does not determine whether the UIDs are blocked from using + * such other networks. + * Use {@link #setShouldBlockNonMatchingNetworks(boolean)} to specify this. + * + * The default value is true. + * * @param allowFallbackToDefaultConnection true if fallback is allowed else false * @return The builder to facilitate chaining. */ @@ -257,6 +302,31 @@ public final class PreferentialNetworkServiceConfig implements Parcelable { return this; } + /** + * Set whether to block UIDs from using other networks than the preferential service. + * + * Apps can inspect the list of available networks on the device and choose to use multiple + * of them concurrently for performance, privacy or other reasons. + * This boolean configures whether the concerned UIDs should be blocked from using + * networks that do not match the configured preferential network service even if these + * networks are otherwise open to all apps. + * + * The default value is false. This value can only be set to {@code true} if + * {@link #setFallbackToDefaultConnectionAllowed(boolean)} is set to {@code false}, because + * allowing fallback but blocking it does not make sense. Failure to comply with this + * constraint will throw when building the object. + * + * @param blockNonMatchingNetworks true if UIDs should be blocked from using non-matching + * networks. + * @return The builder to facilitate chaining. + */ + @NonNull + public PreferentialNetworkServiceConfig.Builder setShouldBlockNonMatchingNetworks( + boolean blockNonMatchingNetworks) { + mShouldBlockNonMatchingNetworks = blockNonMatchingNetworks; + return this; + } + /** * Set the array of uids whose network access will go through this preferential * network service. @@ -305,8 +375,13 @@ public final class PreferentialNetworkServiceConfig implements Parcelable { throw new IllegalStateException("Both includedUids and excludedUids " + "cannot be nonempty"); } + if (mShouldBlockNonMatchingNetworks && mAllowFallbackToDefaultConnection) { + throw new IllegalStateException("A config cannot both allow fallback and " + + "block non-matching networks"); + } return new PreferentialNetworkServiceConfig(mIsEnabled, - mAllowFallbackToDefaultConnection, mIncludedUids, mExcludedUids, mNetworkId); + mAllowFallbackToDefaultConnection, mShouldBlockNonMatchingNetworks, + mIncludedUids, mExcludedUids, mNetworkId); } /** @@ -331,6 +406,7 @@ public final class PreferentialNetworkServiceConfig implements Parcelable { public void writeToParcel(@NonNull android.os.Parcel dest, int flags) { dest.writeBoolean(mIsEnabled); dest.writeBoolean(mAllowFallbackToDefaultConnection); + dest.writeBoolean(mShouldBlockNonMatchingNetworks); dest.writeInt(mNetworkId); dest.writeIntArray(mIncludedUids); dest.writeIntArray(mExcludedUids); @@ -422,6 +498,9 @@ public final class PreferentialNetworkServiceConfig implements Parcelable { } else if (TAG_ALLOW_FALLBACK_TO_DEFAULT_CONNECTION.equals(tagDAM)) { resultBuilder.setFallbackToDefaultConnectionAllowed(parser.getAttributeBoolean( null, ATTR_VALUE, true)); + } else if (TAG_BLOCK_NON_MATCHING_NETWORKS.equals(tagDAM)) { + resultBuilder.setShouldBlockNonMatchingNetworks(parser.getAttributeBoolean( + null, ATTR_VALUE, false)); } else if (TAG_INCLUDED_UIDS.equals(tagDAM)) { resultBuilder.setIncludedUids(readStringListToIntArray(parser, TAG_UID)); } else if (TAG_EXCLUDED_UIDS.equals(tagDAM)) { @@ -442,6 +521,8 @@ public final class PreferentialNetworkServiceConfig implements Parcelable { writeAttributeValueToXml(out, TAG_NETWORK_ID, getNetworkId()); writeAttributeValueToXml(out, TAG_ALLOW_FALLBACK_TO_DEFAULT_CONNECTION, isFallbackToDefaultConnectionAllowed()); + writeAttributeValueToXml(out, TAG_BLOCK_NON_MATCHING_NETWORKS, + shouldBlockNonMatchingNetworks()); writeAttributeValuesToXml(out, TAG_INCLUDED_UIDS, TAG_UID, intArrayToStringList(getIncludedUids())); writeAttributeValuesToXml(out, TAG_EXCLUDED_UIDS, TAG_UID, @@ -459,6 +540,8 @@ public final class PreferentialNetworkServiceConfig implements Parcelable { pw.println(mIsEnabled); pw.print("allowFallbackToDefaultConnection="); pw.println(mAllowFallbackToDefaultConnection); + pw.print("blockNonMatchingNetworks="); + pw.println(mShouldBlockNonMatchingNetworks); pw.print("includedUids="); pw.println(mIncludedUids); pw.print("excludedUids="); diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 20d9cce9a622..55fb5990b9b3 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -136,6 +136,7 @@ import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE; import static android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES; import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_DEFAULT; import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_ENTERPRISE; +import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_ENTERPRISE_BLOCKING; import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK; import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK; import static android.provider.Settings.Global.PRIVATE_DNS_SPECIFIER; @@ -18330,6 +18331,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { if (preferentialNetworkServiceConfig.isEnabled()) { if (preferentialNetworkServiceConfig.isFallbackToDefaultConnectionAllowed()) { preferenceBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE); + } else if (preferentialNetworkServiceConfig.shouldBlockNonMatchingNetworks()) { + preferenceBuilder.setPreference( + PROFILE_NETWORK_PREFERENCE_ENTERPRISE_BLOCKING); } else { preferenceBuilder.setPreference( PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK);