diff --git a/service/src/com/android/server/ConnectivityService.java b/service/src/com/android/server/ConnectivityService.java index a44494cabd..d547d838ae 100755 --- a/service/src/com/android/server/ConnectivityService.java +++ b/service/src/com/android/server/ConnectivityService.java @@ -279,9 +279,10 @@ import com.android.server.connectivity.NetworkDiagnostics; import com.android.server.connectivity.NetworkNotificationManager; import com.android.server.connectivity.NetworkNotificationManager.NotificationType; import com.android.server.connectivity.NetworkOffer; +import com.android.server.connectivity.NetworkPreferenceList; import com.android.server.connectivity.NetworkRanker; import com.android.server.connectivity.PermissionMonitor; -import com.android.server.connectivity.ProfileNetworkPreferenceList; +import com.android.server.connectivity.ProfileNetworkPreferenceInfo; import com.android.server.connectivity.ProxyTracker; import com.android.server.connectivity.QosCallbackTracker; import com.android.server.connectivity.UidRangeUtils; @@ -3413,7 +3414,7 @@ public class ConnectivityService extends IConnectivityManager.Stub if (!mProfileNetworkPreferences.isEmpty()) { pw.println("Profile preferences:"); pw.increaseIndent(); - pw.println(mProfileNetworkPreferences.preferences); + pw.println(mProfileNetworkPreferences); pw.decreaseIndent(); } if (!mOemNetworkPreferences.isEmpty()) { @@ -5498,10 +5499,8 @@ public class ConnectivityService extends IConnectivityManager.Stub break; } case EVENT_SET_PROFILE_NETWORK_PREFERENCE: { - final Pair, - IOnCompleteListener> arg = - (Pair, - IOnCompleteListener>) msg.obj; + final Pair, IOnCompleteListener> arg = + (Pair, IOnCompleteListener>) msg.obj; handleSetProfileNetworkPreference(arg.first, arg.second); break; } @@ -6142,7 +6141,7 @@ public class ConnectivityService extends IConnectivityManager.Stub private void onUserRemoved(@NonNull final UserHandle user) { // If there was a network preference for this user, remove it. handleSetProfileNetworkPreference( - List.of(new ProfileNetworkPreferenceList.Preference(user, null, true)), + List.of(new ProfileNetworkPreferenceInfo(user, null, true)), null /* listener */); if (mOemNetworkPreferences.getNetworkPreferences().size() > 0) { handleSetOemNetworkPreference(mOemNetworkPreferences, null); @@ -7112,8 +7111,8 @@ public class ConnectivityService extends IConnectivityManager.Stub // Current per-profile network preferences. This object follows the same threading rules as // the OEM network preferences above. @NonNull - private ProfileNetworkPreferenceList mProfileNetworkPreferences = - new ProfileNetworkPreferenceList(); + private NetworkPreferenceList + mProfileNetworkPreferences = new NetworkPreferenceList<>(); // A set of UIDs that should use mobile data preferentially if available. This object follows // the same threading rules as the OEM network preferences above. @@ -10816,7 +10815,7 @@ public class ConnectivityService extends IConnectivityManager.Stub + "or the device owner must be set. "); } - final List preferenceList = new ArrayList<>(); + final List preferenceList = new ArrayList<>(); boolean hasDefaultPreference = false; for (final ProfileNetworkPreference preference : preferences) { final NetworkCapabilities nc; @@ -10863,8 +10862,7 @@ public class ConnectivityService extends IConnectivityManager.Stub throw new IllegalArgumentException( "Invalid preference in setProfileNetworkPreferences"); } - preferenceList.add(new ProfileNetworkPreferenceList.Preference( - profile, nc, allowFallback)); + preferenceList.add(new ProfileNetworkPreferenceInfo(profile, nc, allowFallback)); if (hasDefaultPreference && preferenceList.size() > 1) { throw new IllegalArgumentException( "Default profile preference should not be set along with other preference"); @@ -10913,9 +10911,9 @@ public class ConnectivityService extends IConnectivityManager.Stub } private ArraySet createNrisFromProfileNetworkPreferences( - @NonNull final ProfileNetworkPreferenceList prefs) { + @NonNull final NetworkPreferenceList prefs) { final ArraySet result = new ArraySet<>(); - for (final ProfileNetworkPreferenceList.Preference pref : prefs.preferences) { + for (final ProfileNetworkPreferenceInfo pref : prefs) { // The NRI for a user should contain the request for capabilities. // If fallback to default network is needed then NRI should include // the request for the default network. Create an image of it to @@ -10945,12 +10943,12 @@ public class ConnectivityService extends IConnectivityManager.Stub * */ private boolean isRangeAlreadyInPreferenceList( - @NonNull List preferenceList, + @NonNull List preferenceList, @NonNull Set uidRangeSet) { if (uidRangeSet.size() == 0 || preferenceList.size() == 0) { return false; } - for (ProfileNetworkPreferenceList.Preference pref : preferenceList) { + for (ProfileNetworkPreferenceInfo pref : preferenceList) { if (UidRangeUtils.doesRangeSetOverlap( UidRange.fromIntRanges(pref.capabilities.getUids()), uidRangeSet)) { return true; @@ -10960,7 +10958,7 @@ public class ConnectivityService extends IConnectivityManager.Stub } private void handleSetProfileNetworkPreference( - @NonNull final List preferenceList, + @NonNull final List preferenceList, @Nullable final IOnCompleteListener listener) { /* * handleSetProfileNetworkPreference is always called for single user. @@ -10969,9 +10967,8 @@ public class ConnectivityService extends IConnectivityManager.Stub * Clear all the existing preferences for the user before applying new preferences. * */ - mProfileNetworkPreferences = mProfileNetworkPreferences.withoutUser( - preferenceList.get(0).user); - for (final ProfileNetworkPreferenceList.Preference preference : preferenceList) { + mProfileNetworkPreferences = mProfileNetworkPreferences.minus(preferenceList.get(0).user); + for (final ProfileNetworkPreferenceInfo preference : preferenceList) { mProfileNetworkPreferences = mProfileNetworkPreferences.plus(preference); } diff --git a/service/src/com/android/server/connectivity/NetworkPreferenceList.java b/service/src/com/android/server/connectivity/NetworkPreferenceList.java new file mode 100644 index 0000000000..fa6d157bff --- /dev/null +++ b/service/src/com/android/server/connectivity/NetworkPreferenceList.java @@ -0,0 +1,100 @@ +/* + * 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 java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +/** + * A generic data class containing network preferences. + * @param The type of key in T + * @param The type of preference stored in this preference list + */ +public class NetworkPreferenceList> + implements Iterable { + /** + * A network preference + * @param the type of key by which this preference is indexed. A NetworkPreferenceList + * can have multiple preferences associated with this key, but has methods to + * work on the keys. + */ + public interface NetworkPreference { + /** + * Whether this preference codes for cancelling the preference for this key + * + * A preference that codes for cancelling is removed from the list of preferences, since + * it means the behavior should be the same as if there was no preference for this key. + */ + boolean isCancel(); + /** The key */ + K getKey(); + } + + @NonNull private final List mPreferences; + + public NetworkPreferenceList() { + mPreferences = Collections.EMPTY_LIST; + } + + private NetworkPreferenceList(@NonNull final List list) { + mPreferences = Collections.unmodifiableList(list); + } + + /** + * Returns a new object consisting of this object plus the passed preference. + * + * If the passed preference is a cancel preference (see {@link NetworkPreference#isCancel()} + * then it is not added. + */ + public NetworkPreferenceList plus(@NonNull final T pref) { + final ArrayList newPrefs = new ArrayList<>(mPreferences); + if (!pref.isCancel()) { + newPrefs.add(pref); + } + return new NetworkPreferenceList<>(newPrefs); + } + + /** + * Remove all preferences corresponding to a key. + */ + public NetworkPreferenceList minus(@NonNull final K key) { + final ArrayList newPrefs = new ArrayList<>(); + for (final T existingPref : mPreferences) { + if (!existingPref.getKey().equals(key)) { + newPrefs.add(existingPref); + } + } + return new NetworkPreferenceList<>(newPrefs); + } + + public boolean isEmpty() { + return mPreferences.isEmpty(); + } + + @Override + public Iterator iterator() { + return mPreferences.iterator(); + } + + @Override public String toString() { + return "NetworkPreferenceList : " + mPreferences; + } +} diff --git a/service/src/com/android/server/connectivity/ProfileNetworkPreferenceInfo.java b/service/src/com/android/server/connectivity/ProfileNetworkPreferenceInfo.java new file mode 100644 index 0000000000..10f3886eb4 --- /dev/null +++ b/service/src/com/android/server/connectivity/ProfileNetworkPreferenceInfo.java @@ -0,0 +1,62 @@ +/* + * 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.annotation.Nullable; +import android.net.NetworkCapabilities; +import android.os.UserHandle; + +/** + * A single profile preference, as it applies to a given user profile. + */ +public class ProfileNetworkPreferenceInfo + implements NetworkPreferenceList.NetworkPreference { + @NonNull + public final UserHandle user; + // Capabilities are only null when sending an object to remove the setting for a user + @Nullable + public final NetworkCapabilities capabilities; + public final boolean allowFallback; + + public ProfileNetworkPreferenceInfo(@NonNull final UserHandle user, + @Nullable final NetworkCapabilities capabilities, + final boolean allowFallback) { + this.user = user; + this.capabilities = null == capabilities ? null : new NetworkCapabilities(capabilities); + this.allowFallback = allowFallback; + } + + @Override + public boolean isCancel() { + return null == capabilities; + } + + @Override + @NonNull + public UserHandle getKey() { + return user; + } + + /** toString */ + public String toString() { + return "[ProfileNetworkPreference user=" + user + + " caps=" + capabilities + + " allowFallback=" + allowFallback + + "]"; + } +} diff --git a/service/src/com/android/server/connectivity/ProfileNetworkPreferenceList.java b/service/src/com/android/server/connectivity/ProfileNetworkPreferenceList.java deleted file mode 100644 index 5bafef9868..0000000000 --- a/service/src/com/android/server/connectivity/ProfileNetworkPreferenceList.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (C) 2021 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.annotation.Nullable; -import android.net.NetworkCapabilities; -import android.os.UserHandle; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -/** - * A data class containing all the per-profile network preferences. - * - * A given profile can only have one preference. - */ -public class ProfileNetworkPreferenceList { - /** - * A single preference, as it applies to a given user profile. - */ - public static class Preference { - @NonNull public final UserHandle user; - // Capabilities are only null when sending an object to remove the setting for a user - @Nullable public final NetworkCapabilities capabilities; - public final boolean allowFallback; - - public Preference(@NonNull final UserHandle user, - @Nullable final NetworkCapabilities capabilities, - final boolean allowFallback) { - this.user = user; - this.capabilities = null == capabilities ? null : new NetworkCapabilities(capabilities); - this.allowFallback = allowFallback; - } - - /** toString */ - public String toString() { - return "[ProfileNetworkPreference user=" + user - + " caps=" + capabilities - + " allowFallback=" + allowFallback - + "]"; - } - } - - @NonNull public final List preferences; - - public ProfileNetworkPreferenceList() { - preferences = Collections.EMPTY_LIST; - } - - private ProfileNetworkPreferenceList(@NonNull final List list) { - preferences = Collections.unmodifiableList(list); - } - - /** - * Returns a new object consisting of this object plus the passed preference. - * - * It is not expected that unwanted preference already exists for the same user. - * All preferences for the user that were previously configured should be cleared before - * adding a new preference. - * Passing a Preference object containing a null capabilities object is equivalent - * to removing the preference for this user. - */ - public ProfileNetworkPreferenceList plus(@NonNull final Preference pref) { - final ArrayList newPrefs = new ArrayList<>(preferences); - if (null != pref.capabilities) { - newPrefs.add(pref); - } - return new ProfileNetworkPreferenceList(newPrefs); - } - - /** - * Remove all preferences corresponding to a user. - */ - public ProfileNetworkPreferenceList withoutUser(UserHandle user) { - final ArrayList newPrefs = new ArrayList<>(); - for (final Preference existingPref : preferences) { - if (!existingPref.user.equals(user)) { - newPrefs.add(existingPref); - } - } - return new ProfileNetworkPreferenceList(newPrefs); - } - - public boolean isEmpty() { - return preferences.isEmpty(); - } -}