• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.vcn.routeselection;
18 
19 import static com.android.server.vcn.util.PersistableBundleUtils.PersistableBundleWrapper;
20 
21 import android.annotation.NonNull;
22 import android.annotation.Nullable;
23 import android.net.LinkProperties;
24 import android.net.Network;
25 import android.net.NetworkCapabilities;
26 import android.net.vcn.VcnUnderlyingNetworkTemplate;
27 import android.os.ParcelUuid;
28 
29 import com.android.internal.annotations.VisibleForTesting;
30 import com.android.internal.annotations.VisibleForTesting.Visibility;
31 import com.android.internal.util.IndentingPrintWriter;
32 import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot;
33 import com.android.server.vcn.VcnContext;
34 
35 import java.util.Comparator;
36 import java.util.List;
37 import java.util.Objects;
38 
39 /**
40  * A record of a single underlying network, caching relevant fields.
41  *
42  * @hide
43  */
44 public class UnderlyingNetworkRecord {
45     @NonNull public final Network network;
46     @NonNull public final NetworkCapabilities networkCapabilities;
47     @NonNull public final LinkProperties linkProperties;
48     public final boolean isBlocked;
49     public final boolean isSelected;
50     public final int priorityClass;
51 
52     @VisibleForTesting(visibility = Visibility.PRIVATE)
UnderlyingNetworkRecord( @onNull Network network, @NonNull NetworkCapabilities networkCapabilities, @NonNull LinkProperties linkProperties, boolean isBlocked, VcnContext vcnContext, List<VcnUnderlyingNetworkTemplate> underlyingNetworkTemplates, ParcelUuid subscriptionGroup, TelephonySubscriptionSnapshot snapshot, UnderlyingNetworkRecord currentlySelected, PersistableBundleWrapper carrierConfig)53     public UnderlyingNetworkRecord(
54             @NonNull Network network,
55             @NonNull NetworkCapabilities networkCapabilities,
56             @NonNull LinkProperties linkProperties,
57             boolean isBlocked,
58             VcnContext vcnContext,
59             List<VcnUnderlyingNetworkTemplate> underlyingNetworkTemplates,
60             ParcelUuid subscriptionGroup,
61             TelephonySubscriptionSnapshot snapshot,
62             UnderlyingNetworkRecord currentlySelected,
63             PersistableBundleWrapper carrierConfig) {
64         this.network = network;
65         this.networkCapabilities = networkCapabilities;
66         this.linkProperties = linkProperties;
67         this.isBlocked = isBlocked;
68 
69         this.isSelected = isSelected(this.network, currentlySelected);
70 
71         priorityClass =
72                 NetworkPriorityClassifier.calculatePriorityClass(
73                         vcnContext,
74                         this,
75                         underlyingNetworkTemplates,
76                         subscriptionGroup,
77                         snapshot,
78                         currentlySelected,
79                         carrierConfig);
80     }
81 
82     @VisibleForTesting(visibility = Visibility.PRIVATE)
UnderlyingNetworkRecord( @onNull Network network, @NonNull NetworkCapabilities networkCapabilities, @NonNull LinkProperties linkProperties, boolean isBlocked, boolean isSelected, int priorityClass)83     public UnderlyingNetworkRecord(
84             @NonNull Network network,
85             @NonNull NetworkCapabilities networkCapabilities,
86             @NonNull LinkProperties linkProperties,
87             boolean isBlocked,
88             boolean isSelected,
89             int priorityClass) {
90         this.network = network;
91         this.networkCapabilities = networkCapabilities;
92         this.linkProperties = linkProperties;
93         this.isBlocked = isBlocked;
94         this.isSelected = isSelected;
95 
96         this.priorityClass = priorityClass;
97     }
98 
99     @Override
equals(Object o)100     public boolean equals(Object o) {
101         if (this == o) return true;
102         if (!(o instanceof UnderlyingNetworkRecord)) return false;
103         final UnderlyingNetworkRecord that = (UnderlyingNetworkRecord) o;
104 
105         return network.equals(that.network)
106                 && networkCapabilities.equals(that.networkCapabilities)
107                 && linkProperties.equals(that.linkProperties)
108                 && isBlocked == that.isBlocked;
109     }
110 
111     @Override
hashCode()112     public int hashCode() {
113         return Objects.hash(network, networkCapabilities, linkProperties, isBlocked);
114     }
115 
116     /** Returns if two records are equal including their priority classes. */
isEqualIncludingPriorities( UnderlyingNetworkRecord left, UnderlyingNetworkRecord right)117     public static boolean isEqualIncludingPriorities(
118             UnderlyingNetworkRecord left, UnderlyingNetworkRecord right) {
119         if (left != null && right != null) {
120             return left.equals(right)
121                     && left.isSelected == right.isSelected
122                     && left.priorityClass == right.priorityClass;
123         }
124 
125         return left == right;
126     }
127 
getComparator()128     static Comparator<UnderlyingNetworkRecord> getComparator() {
129         return (left, right) -> {
130             final int leftIndex = left.priorityClass;
131             final int rightIndex = right.priorityClass;
132 
133             // In the case of networks in the same priority class, prioritize based on other
134             // criteria (eg. actively selected network, link metrics, etc)
135             if (leftIndex == rightIndex) {
136                 // TODO: Improve the strategy of network selection when both UnderlyingNetworkRecord
137                 // fall into the same priority class.
138                 if (left.isSelected) {
139                     return -1;
140                 }
141                 if (right.isSelected) {
142                     return 1;
143                 }
144             }
145             return Integer.compare(leftIndex, rightIndex);
146         };
147     }
148 
isSelected( Network networkToCheck, UnderlyingNetworkRecord currentlySelected)149     private static boolean isSelected(
150             Network networkToCheck, UnderlyingNetworkRecord currentlySelected) {
151         if (currentlySelected == null) {
152             return false;
153         }
154         if (currentlySelected.network.equals(networkToCheck)) {
155             return true;
156         }
157         return false;
158     }
159 
160     /** Dumps the state of this record for logging and debugging purposes. */
dump( VcnContext vcnContext, IndentingPrintWriter pw, List<VcnUnderlyingNetworkTemplate> underlyingNetworkTemplates, ParcelUuid subscriptionGroup, TelephonySubscriptionSnapshot snapshot, UnderlyingNetworkRecord currentlySelected, PersistableBundleWrapper carrierConfig)161     void dump(
162             VcnContext vcnContext,
163             IndentingPrintWriter pw,
164             List<VcnUnderlyingNetworkTemplate> underlyingNetworkTemplates,
165             ParcelUuid subscriptionGroup,
166             TelephonySubscriptionSnapshot snapshot,
167             UnderlyingNetworkRecord currentlySelected,
168             PersistableBundleWrapper carrierConfig) {
169         pw.println("UnderlyingNetworkRecord:");
170         pw.increaseIndent();
171 
172         pw.println("priorityClass: " + priorityClass);
173         pw.println("isSelected: " + isSelected);
174         pw.println("mNetwork: " + network);
175         pw.println("mNetworkCapabilities: " + networkCapabilities);
176         pw.println("mLinkProperties: " + linkProperties);
177 
178         pw.decreaseIndent();
179     }
180 
181     /** Builder to incrementally construct an UnderlyingNetworkRecord. */
182     static class Builder {
183         @NonNull private final Network mNetwork;
184 
185         @Nullable private NetworkCapabilities mNetworkCapabilities;
186         @Nullable private LinkProperties mLinkProperties;
187         boolean mIsBlocked;
188         boolean mWasIsBlockedSet;
189 
Builder(@onNull Network network)190         Builder(@NonNull Network network) {
191             mNetwork = network;
192         }
193 
194         @NonNull
getNetwork()195         Network getNetwork() {
196             return mNetwork;
197         }
198 
setNetworkCapabilities(@onNull NetworkCapabilities networkCapabilities)199         void setNetworkCapabilities(@NonNull NetworkCapabilities networkCapabilities) {
200             mNetworkCapabilities = networkCapabilities;
201         }
202 
203         @Nullable
getNetworkCapabilities()204         NetworkCapabilities getNetworkCapabilities() {
205             return mNetworkCapabilities;
206         }
207 
setLinkProperties(@onNull LinkProperties linkProperties)208         void setLinkProperties(@NonNull LinkProperties linkProperties) {
209             mLinkProperties = linkProperties;
210         }
211 
setIsBlocked(boolean isBlocked)212         void setIsBlocked(boolean isBlocked) {
213             mIsBlocked = isBlocked;
214             mWasIsBlockedSet = true;
215         }
216 
isValid()217         boolean isValid() {
218             return mNetworkCapabilities != null && mLinkProperties != null && mWasIsBlockedSet;
219         }
220 
build( VcnContext vcnContext, List<VcnUnderlyingNetworkTemplate> underlyingNetworkTemplates, ParcelUuid subscriptionGroup, TelephonySubscriptionSnapshot snapshot, UnderlyingNetworkRecord currentlySelected, PersistableBundleWrapper carrierConfig)221         UnderlyingNetworkRecord build(
222                 VcnContext vcnContext,
223                 List<VcnUnderlyingNetworkTemplate> underlyingNetworkTemplates,
224                 ParcelUuid subscriptionGroup,
225                 TelephonySubscriptionSnapshot snapshot,
226                 UnderlyingNetworkRecord currentlySelected,
227                 PersistableBundleWrapper carrierConfig) {
228             if (!isValid()) {
229                 throw new IllegalArgumentException(
230                         "Called build before UnderlyingNetworkRecord was valid");
231             }
232 
233             return new UnderlyingNetworkRecord(
234                     mNetwork,
235                     mNetworkCapabilities,
236                     mLinkProperties,
237                     mIsBlocked,
238                     vcnContext,
239                     underlyingNetworkTemplates,
240                     subscriptionGroup,
241                     snapshot,
242                     currentlySelected,
243                     carrierConfig);
244         }
245     }
246 }
247