Ability to specify which all applications fall under enterprise slice.
Bug: 194332512 Test: unit test Change-Id: I94549a41aaa717add22b0a3e5035beacf6f1b8f2
This commit is contained in:
@@ -262,6 +262,7 @@ import com.android.server.connectivity.PermissionMonitor;
|
||||
import com.android.server.connectivity.ProfileNetworkPreferenceList;
|
||||
import com.android.server.connectivity.ProxyTracker;
|
||||
import com.android.server.connectivity.QosCallbackTracker;
|
||||
import com.android.server.connectivity.UidRangeUtils;
|
||||
|
||||
import libcore.io.IoUtils;
|
||||
|
||||
@@ -1489,16 +1490,17 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
}
|
||||
|
||||
private static NetworkCapabilities createDefaultNetworkCapabilitiesForUid(int uid) {
|
||||
return createDefaultNetworkCapabilitiesForUidRange(new UidRange(uid, uid));
|
||||
return createDefaultNetworkCapabilitiesForUidRangeSet(Collections.singleton(
|
||||
new UidRange(uid, uid)));
|
||||
}
|
||||
|
||||
private static NetworkCapabilities createDefaultNetworkCapabilitiesForUidRange(
|
||||
@NonNull final UidRange uids) {
|
||||
private static NetworkCapabilities createDefaultNetworkCapabilitiesForUidRangeSet(
|
||||
@NonNull final Set<UidRange> uidRangeSet) {
|
||||
final NetworkCapabilities netCap = new NetworkCapabilities();
|
||||
netCap.addCapability(NET_CAPABILITY_INTERNET);
|
||||
netCap.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED);
|
||||
netCap.removeCapability(NET_CAPABILITY_NOT_VPN);
|
||||
netCap.setUids(UidRange.toIntRanges(Collections.singleton(uids)));
|
||||
netCap.setUids(UidRange.toIntRanges(uidRangeSet));
|
||||
return netCap;
|
||||
}
|
||||
|
||||
@@ -10150,8 +10152,14 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
allowFallback = false;
|
||||
// continue to process the enterprise preference.
|
||||
case ConnectivityManager.PROFILE_NETWORK_PREFERENCE_ENTERPRISE:
|
||||
final UidRange uids = UidRange.createForUser(profile);
|
||||
nc = createDefaultNetworkCapabilitiesForUidRange(uids);
|
||||
final Set<UidRange> uidRangeSet =
|
||||
getUidListToBeAppliedForNetworkPreference(profile, preference);
|
||||
if (!isRangeAlreadyInPreferenceList(preferenceList, uidRangeSet)) {
|
||||
nc = createDefaultNetworkCapabilitiesForUidRangeSet(uidRangeSet);
|
||||
} else {
|
||||
throw new IllegalArgumentException(
|
||||
"Overlapping uid range in setProfileNetworkPreferences");
|
||||
}
|
||||
nc.addCapability(NET_CAPABILITY_ENTERPRISE);
|
||||
nc.removeCapability(NET_CAPABILITY_NOT_RESTRICTED);
|
||||
break;
|
||||
@@ -10166,6 +10174,35 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
new Pair<>(preferenceList, listener)));
|
||||
}
|
||||
|
||||
private Set<UidRange> getUidListToBeAppliedForNetworkPreference(
|
||||
@NonNull final UserHandle profile,
|
||||
@NonNull final ProfileNetworkPreference profileNetworkPreference) {
|
||||
final UidRange profileUids = UidRange.createForUser(profile);
|
||||
Set<UidRange> uidRangeSet = UidRangeUtils.convertListToUidRange(
|
||||
profileNetworkPreference.getIncludedUids());
|
||||
if (uidRangeSet.size() > 0) {
|
||||
if (!UidRangeUtils.isRangeSetInUidRange(profileUids, uidRangeSet)) {
|
||||
throw new IllegalArgumentException(
|
||||
"Allow uid range is outside the uid range of profile.");
|
||||
}
|
||||
} else {
|
||||
ArraySet<UidRange> disallowUidRangeSet = UidRangeUtils.convertListToUidRange(
|
||||
profileNetworkPreference.getExcludedUids());
|
||||
if (disallowUidRangeSet.size() > 0) {
|
||||
if (!UidRangeUtils.isRangeSetInUidRange(profileUids, disallowUidRangeSet)) {
|
||||
throw new IllegalArgumentException(
|
||||
"disallow uid range is outside the uid range of profile.");
|
||||
}
|
||||
uidRangeSet = UidRangeUtils.removeRangeSetFromUidRange(profileUids,
|
||||
disallowUidRangeSet);
|
||||
} else {
|
||||
uidRangeSet = new ArraySet<UidRange>();
|
||||
uidRangeSet.add(profileUids);
|
||||
}
|
||||
}
|
||||
return uidRangeSet;
|
||||
}
|
||||
|
||||
private void validateNetworkCapabilitiesOfProfileNetworkPreference(
|
||||
@Nullable final NetworkCapabilities nc) {
|
||||
if (null == nc) return; // Null caps are always allowed. It means to remove the setting.
|
||||
@@ -10187,6 +10224,11 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
nrs.add(createDefaultInternetRequestForTransport(
|
||||
TYPE_NONE, NetworkRequest.Type.TRACK_DEFAULT));
|
||||
}
|
||||
if (VDBG) {
|
||||
loge("pref.capabilities.getUids():" + UidRange.fromIntRanges(
|
||||
pref.capabilities.getUids()));
|
||||
}
|
||||
|
||||
setNetworkRequestUids(nrs, UidRange.fromIntRanges(pref.capabilities.getUids()));
|
||||
final NetworkRequestInfo nri = new NetworkRequestInfo(Process.myUid(), nrs,
|
||||
PREFERENCE_ORDER_PROFILE);
|
||||
@@ -10195,6 +10237,25 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare if the given UID range sets have the same UIDs.
|
||||
*
|
||||
*/
|
||||
private boolean isRangeAlreadyInPreferenceList(
|
||||
@NonNull List<ProfileNetworkPreferenceList.Preference> preferenceList,
|
||||
@NonNull Set<UidRange> uidRangeSet) {
|
||||
if (uidRangeSet.size() == 0 || preferenceList.size() == 0) {
|
||||
return false;
|
||||
}
|
||||
for (ProfileNetworkPreferenceList.Preference pref : preferenceList) {
|
||||
if (UidRangeUtils.doesRangeSetOverlap(
|
||||
UidRange.fromIntRanges(pref.capabilities.getUids()), uidRangeSet)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void handleSetProfileNetworkPreference(
|
||||
@NonNull final List<ProfileNetworkPreferenceList.Preference> preferenceList,
|
||||
@Nullable final IOnCompleteListener listener) {
|
||||
|
||||
156
service/src/com/android/server/connectivity/UidRangeUtils.java
Normal file
156
service/src/com/android/server/connectivity/UidRangeUtils.java
Normal file
@@ -0,0 +1,156 @@
|
||||
/*
|
||||
* 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.connectivity;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.net.UidRange;
|
||||
import android.util.ArraySet;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Utility class for UidRange
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public final class UidRangeUtils {
|
||||
/**
|
||||
* Check if given uid range set is within the uid range
|
||||
* @param uids uid range in which uidRangeSet is checked to be in range.
|
||||
* @param uidRangeSet uid range set to be be checked if it is in range of uids
|
||||
* @return true uidRangeSet is in the range of uids
|
||||
* @hide
|
||||
*/
|
||||
public static boolean isRangeSetInUidRange(@NonNull UidRange uids,
|
||||
@NonNull Set<UidRange> uidRangeSet) {
|
||||
Objects.requireNonNull(uids);
|
||||
Objects.requireNonNull(uidRangeSet);
|
||||
if (uidRangeSet.size() == 0) {
|
||||
return true;
|
||||
}
|
||||
for (UidRange range : uidRangeSet) {
|
||||
if (!uids.contains(range.start) || !uids.contains(range.stop)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove given uid ranges set from a uid range
|
||||
* @param uids uid range from which uidRangeSet will be removed
|
||||
* @param uidRangeSet uid range set to be removed from uids.
|
||||
* WARNING : This function requires the UidRanges in uidRangeSet to be disjoint
|
||||
* WARNING : This function requires the arrayset to be iterated in increasing order of the
|
||||
* ranges. Today this is provided by the iteration order stability of
|
||||
* ArraySet, and the fact that the code creating this ArraySet always
|
||||
* creates it in increasing order.
|
||||
* Note : if any of the above is not satisfied this function throws IllegalArgumentException
|
||||
* TODO : remove these limitations
|
||||
* @hide
|
||||
*/
|
||||
public static ArraySet<UidRange> removeRangeSetFromUidRange(@NonNull UidRange uids,
|
||||
@NonNull ArraySet<UidRange> uidRangeSet) {
|
||||
Objects.requireNonNull(uids);
|
||||
Objects.requireNonNull(uidRangeSet);
|
||||
final ArraySet<UidRange> filteredRangeSet = new ArraySet<UidRange>();
|
||||
if (uidRangeSet.size() == 0) {
|
||||
filteredRangeSet.add(uids);
|
||||
return filteredRangeSet;
|
||||
}
|
||||
|
||||
int start = uids.start;
|
||||
UidRange previousRange = null;
|
||||
for (UidRange uidRange : uidRangeSet) {
|
||||
if (previousRange != null) {
|
||||
if (previousRange.stop > uidRange.start) {
|
||||
throw new IllegalArgumentException("UID ranges are not increasing order");
|
||||
}
|
||||
}
|
||||
if (uidRange.start > start) {
|
||||
filteredRangeSet.add(new UidRange(start, uidRange.start - 1));
|
||||
start = uidRange.stop + 1;
|
||||
} else if (uidRange.start == start) {
|
||||
start = uidRange.stop + 1;
|
||||
}
|
||||
previousRange = uidRange;
|
||||
}
|
||||
if (start < uids.stop) {
|
||||
filteredRangeSet.add(new UidRange(start, uids.stop));
|
||||
}
|
||||
return filteredRangeSet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare if the given UID range sets have overlapping uids
|
||||
* @param uidRangeSet1 first uid range set to check for overlap
|
||||
* @param uidRangeSet2 second uid range set to check for overlap
|
||||
* @hide
|
||||
*/
|
||||
public static boolean doesRangeSetOverlap(@NonNull Set<UidRange> uidRangeSet1,
|
||||
@NonNull Set<UidRange> uidRangeSet2) {
|
||||
Objects.requireNonNull(uidRangeSet1);
|
||||
Objects.requireNonNull(uidRangeSet2);
|
||||
|
||||
if (uidRangeSet1.size() == 0 || uidRangeSet2.size() == 0) {
|
||||
return false;
|
||||
}
|
||||
for (UidRange range1 : uidRangeSet1) {
|
||||
for (UidRange range2 : uidRangeSet2) {
|
||||
if (range1.contains(range2.start) || range1.contains(range2.stop)
|
||||
|| range2.contains(range1.start) || range2.contains(range1.stop)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a list of uid to set of UidRanges.
|
||||
* @param uids list of uids
|
||||
* @return set of UidRanges
|
||||
* @hide
|
||||
*/
|
||||
public static ArraySet<UidRange> convertListToUidRange(@NonNull List<Integer> uids) {
|
||||
Objects.requireNonNull(uids);
|
||||
final ArraySet<UidRange> uidRangeSet = new ArraySet<UidRange>();
|
||||
if (uids.size() == 0) {
|
||||
return uidRangeSet;
|
||||
}
|
||||
List<Integer> uidsNew = new ArrayList<>(uids);
|
||||
Collections.sort(uidsNew);
|
||||
int start = uidsNew.get(0);
|
||||
int stop = start;
|
||||
|
||||
for (Integer i : uidsNew) {
|
||||
if (i <= stop + 1) {
|
||||
stop = i;
|
||||
} else {
|
||||
uidRangeSet.add(new UidRange(start, stop));
|
||||
start = i;
|
||||
stop = i;
|
||||
}
|
||||
}
|
||||
uidRangeSet.add(new UidRange(start, stop));
|
||||
return uidRangeSet;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user