• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 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.internal.telephony.data;
18 
19 import android.annotation.ElapsedRealtimeLong;
20 import android.annotation.IntDef;
21 import android.annotation.NonNull;
22 import android.annotation.Nullable;
23 import android.net.NetworkCapabilities;
24 import android.net.NetworkRequest;
25 import android.net.NetworkSpecifier;
26 import android.os.SystemClock;
27 import android.telephony.Annotation.NetCapability;
28 import android.telephony.data.ApnSetting;
29 import android.telephony.data.DataProfile;
30 import android.telephony.data.TrafficDescriptor;
31 import android.telephony.data.TrafficDescriptor.OsAppId;
32 
33 import com.android.internal.telephony.Phone;
34 
35 import java.lang.annotation.Retention;
36 import java.lang.annotation.RetentionPolicy;
37 import java.util.AbstractMap.SimpleImmutableEntry;
38 import java.util.Arrays;
39 import java.util.Comparator;
40 import java.util.List;
41 import java.util.Map;
42 import java.util.stream.Collectors;
43 
44 /**
45  * TelephonyNetworkRequest is a wrapper class on top of {@link NetworkRequest}, which is originated
46  * from the apps to request network. This class is intended to track supplemental information
47  * related to this request, for example priority, evaluation result, whether this request is
48  * actively being satisfied, timestamp, etc...
49  *
50  */
51 public class TelephonyNetworkRequest {
52     @Retention(RetentionPolicy.SOURCE)
53     @IntDef(prefix = {"REQUEST_STATE_"},
54             value = {
55                     REQUEST_STATE_UNSATISFIED,
56                     REQUEST_STATE_SATISFIED})
57     public @interface RequestState {}
58 
59     /**
60      * Indicating currently no data networks can satisfy this network request.
61      */
62     public static final int REQUEST_STATE_UNSATISFIED = 0;
63 
64     /**
65      * Indicating this request is already satisfied. It must have an attached network (which could
66      * be in any state, including disconnecting). Also note this does not mean the network request
67      * is satisfied in telephony layer. Whether the network request is finally satisfied or not is
68      * determined at the connectivity service layer.
69      */
70     public static final int REQUEST_STATE_SATISFIED = 1;
71 
72     /** @hide */
73     @IntDef(flag = true, prefix = { "CAPABILITY_ATTRIBUTE_" }, value = {
74             CAPABILITY_ATTRIBUTE_NONE,
75             CAPABILITY_ATTRIBUTE_APN_SETTING,
76             CAPABILITY_ATTRIBUTE_TRAFFIC_DESCRIPTOR_DNN,
77             CAPABILITY_ATTRIBUTE_TRAFFIC_DESCRIPTOR_OS_APP_ID,
78     })
79     @Retention(RetentionPolicy.SOURCE)
80     public @interface NetCapabilityAttribute {}
81 
82     /** Network capability attribute none. */
83     public static final int CAPABILITY_ATTRIBUTE_NONE = 0;
84 
85     /**
86      * The network capability should result in filling {@link ApnSetting} in {@link DataProfile}.
87      */
88     public static final int CAPABILITY_ATTRIBUTE_APN_SETTING = 1;
89 
90     /** The network capability should result in filling DNN in {@link TrafficDescriptor}. */
91     public static final int CAPABILITY_ATTRIBUTE_TRAFFIC_DESCRIPTOR_DNN = 1 << 1;
92 
93     /** The network capability should result in filling OS/APP id in {@link TrafficDescriptor}. */
94     public static final int CAPABILITY_ATTRIBUTE_TRAFFIC_DESCRIPTOR_OS_APP_ID = 1 << 2;
95 
96     /**
97      * Describes the attributes of network capabilities. Different capabilities can be translated
98      * to different fields in {@link DataProfile}, or might be expanded to support special actions
99      * in telephony in the future.
100      */
101     private static final Map<Integer, Integer> CAPABILITY_ATTRIBUTE_MAP = Map.ofEntries(
102             new SimpleImmutableEntry<>(NetworkCapabilities.NET_CAPABILITY_MMS,
103                     CAPABILITY_ATTRIBUTE_APN_SETTING | CAPABILITY_ATTRIBUTE_TRAFFIC_DESCRIPTOR_DNN),
104             new SimpleImmutableEntry<>(NetworkCapabilities.NET_CAPABILITY_SUPL,
105                     CAPABILITY_ATTRIBUTE_APN_SETTING | CAPABILITY_ATTRIBUTE_TRAFFIC_DESCRIPTOR_DNN),
106             new SimpleImmutableEntry<>(NetworkCapabilities.NET_CAPABILITY_DUN,
107                     CAPABILITY_ATTRIBUTE_APN_SETTING | CAPABILITY_ATTRIBUTE_TRAFFIC_DESCRIPTOR_DNN),
108             new SimpleImmutableEntry<>(NetworkCapabilities.NET_CAPABILITY_FOTA,
109                     CAPABILITY_ATTRIBUTE_APN_SETTING | CAPABILITY_ATTRIBUTE_TRAFFIC_DESCRIPTOR_DNN),
110             new SimpleImmutableEntry<>(NetworkCapabilities.NET_CAPABILITY_IMS,
111                     CAPABILITY_ATTRIBUTE_APN_SETTING | CAPABILITY_ATTRIBUTE_TRAFFIC_DESCRIPTOR_DNN),
112             new SimpleImmutableEntry<>(NetworkCapabilities.NET_CAPABILITY_CBS,
113                     CAPABILITY_ATTRIBUTE_APN_SETTING | CAPABILITY_ATTRIBUTE_TRAFFIC_DESCRIPTOR_DNN
114                             | CAPABILITY_ATTRIBUTE_TRAFFIC_DESCRIPTOR_OS_APP_ID),
115             new SimpleImmutableEntry<>(NetworkCapabilities.NET_CAPABILITY_XCAP,
116                     CAPABILITY_ATTRIBUTE_APN_SETTING | CAPABILITY_ATTRIBUTE_TRAFFIC_DESCRIPTOR_DNN),
117             new SimpleImmutableEntry<>(NetworkCapabilities.NET_CAPABILITY_EIMS,
118                     CAPABILITY_ATTRIBUTE_APN_SETTING | CAPABILITY_ATTRIBUTE_TRAFFIC_DESCRIPTOR_DNN),
119             new SimpleImmutableEntry<>(NetworkCapabilities.NET_CAPABILITY_INTERNET,
120                     CAPABILITY_ATTRIBUTE_APN_SETTING | CAPABILITY_ATTRIBUTE_TRAFFIC_DESCRIPTOR_DNN),
121             new SimpleImmutableEntry<>(NetworkCapabilities.NET_CAPABILITY_MCX,
122                     CAPABILITY_ATTRIBUTE_APN_SETTING | CAPABILITY_ATTRIBUTE_TRAFFIC_DESCRIPTOR_DNN),
123             new SimpleImmutableEntry<>(NetworkCapabilities.NET_CAPABILITY_ENTERPRISE,
124                     CAPABILITY_ATTRIBUTE_APN_SETTING | CAPABILITY_ATTRIBUTE_TRAFFIC_DESCRIPTOR_DNN
125                             | CAPABILITY_ATTRIBUTE_TRAFFIC_DESCRIPTOR_OS_APP_ID),
126             new SimpleImmutableEntry<>(NetworkCapabilities.NET_CAPABILITY_VSIM,
127                     CAPABILITY_ATTRIBUTE_APN_SETTING | CAPABILITY_ATTRIBUTE_TRAFFIC_DESCRIPTOR_DNN),
128             new SimpleImmutableEntry<>(NetworkCapabilities.NET_CAPABILITY_BIP,
129                     CAPABILITY_ATTRIBUTE_APN_SETTING | CAPABILITY_ATTRIBUTE_TRAFFIC_DESCRIPTOR_DNN),
130             new SimpleImmutableEntry<>(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY,
131                     CAPABILITY_ATTRIBUTE_TRAFFIC_DESCRIPTOR_OS_APP_ID),
132             new SimpleImmutableEntry<>(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_BANDWIDTH,
133                     CAPABILITY_ATTRIBUTE_TRAFFIC_DESCRIPTOR_OS_APP_ID)
134     );
135 
136     /** The phone instance. */
137     private final @NonNull Phone mPhone;
138 
139     /**
140      * Native network request from the clients. See {@link NetworkRequest};
141      */
142     private final @NonNull NetworkRequest mNativeNetworkRequest;
143 
144     /**
145      * The attributes of the network capabilities in this network request. This describes how this
146      * network request can be translated to different fields in {@link DataProfile} or perform
147      * special actions in telephony.
148      */
149     private final @NetCapabilityAttribute int mCapabilitiesAttributes;
150 
151     /**
152      * Priority of the network request. The network request has higher priority will be satisfied
153      * first than lower priority ones.
154      */
155     private int mPriority;
156 
157     /**
158      * Data config manager for retrieving data config.
159      */
160     private final @NonNull DataConfigManager mDataConfigManager;
161 
162     /**
163      * The attached data network. Note that the data network could be in any state. {@code null}
164      * indicates this network request is not satisfied.
165      */
166     private @Nullable DataNetwork mAttachedDataNetwork;
167 
168     /**
169      * The state of the network request.
170      *
171      * @see #REQUEST_STATE_UNSATISFIED
172      * @see #REQUEST_STATE_SATISFIED
173      */
174     // This is not a boolean because there might be more states in the future.
175     private @RequestState int mState;
176 
177     /** The timestamp when this network request enters telephony. */
178     private final @ElapsedRealtimeLong long mCreatedTimeMillis;
179 
180     /** The data evaluation result. */
181     private @Nullable DataEvaluation mEvaluation;
182 
183     /**
184      * Constructor
185      *
186      * @param request The native network request from the clients.
187      * @param phone The phone instance
188      */
TelephonyNetworkRequest(NetworkRequest request, Phone phone)189     public TelephonyNetworkRequest(NetworkRequest request, Phone phone) {
190         mPhone = phone;
191         mNativeNetworkRequest = request;
192 
193         int capabilitiesAttributes = CAPABILITY_ATTRIBUTE_NONE;
194         for (int networkCapability : mNativeNetworkRequest.getCapabilities()) {
195             capabilitiesAttributes |= CAPABILITY_ATTRIBUTE_MAP.getOrDefault(
196                     networkCapability, CAPABILITY_ATTRIBUTE_NONE);
197         }
198         mCapabilitiesAttributes = capabilitiesAttributes;
199 
200         mPriority = 0;
201         mAttachedDataNetwork = null;
202         // When the request was first created, it is in active state so we can actively attempt
203         // to satisfy it.
204         mState = REQUEST_STATE_UNSATISFIED;
205         mCreatedTimeMillis = SystemClock.elapsedRealtime();
206         mDataConfigManager = phone.getDataNetworkController().getDataConfigManager();
207         updatePriority();
208     }
209 
210     /**
211      * @see NetworkRequest#getNetworkSpecifier()
212      */
getNetworkSpecifier()213     public @Nullable NetworkSpecifier getNetworkSpecifier() {
214         return mNativeNetworkRequest.getNetworkSpecifier();
215     }
216 
217     /**
218      * @see NetworkRequest#getCapabilities()
219      */
getCapabilities()220     public @NonNull @NetCapability int[] getCapabilities() {
221         return mNativeNetworkRequest.getCapabilities();
222     }
223 
224     /**
225      * @see NetworkRequest#hasCapability(int)
226      */
hasCapability(@etCapability int capability)227     public boolean hasCapability(@NetCapability int capability) {
228         return mNativeNetworkRequest.hasCapability(capability);
229     }
230 
231     /**
232      * @see NetworkRequest#canBeSatisfiedBy(NetworkCapabilities)
233      */
canBeSatisfiedBy(@ullable NetworkCapabilities nc)234     public boolean canBeSatisfiedBy(@Nullable NetworkCapabilities nc) {
235         return mNativeNetworkRequest.canBeSatisfiedBy(nc);
236     }
237 
238 
239     /**
240      * Check if the request's capabilities have certain attributes.
241      *
242      * @param capabilitiesAttributes The attributes to check.
243      * @return {@code true} if the capabilities have provided attributes.
244      *
245      * @see NetCapabilityAttribute
246      */
hasAttribute(@etCapabilityAttribute int capabilitiesAttributes)247     public boolean hasAttribute(@NetCapabilityAttribute int capabilitiesAttributes) {
248         return (mCapabilitiesAttributes & capabilitiesAttributes) == capabilitiesAttributes;
249     }
250 
251     /**
252      * Check if this network request can be satisfied by a data profile.
253      *
254      * @param dataProfile The data profile to check.
255      * @return {@code true} if this network request can be satisfied by the data profile.
256      */
canBeSatisfiedBy(@onNull DataProfile dataProfile)257     public boolean canBeSatisfiedBy(@NonNull DataProfile dataProfile) {
258         // If the network request can be translated to OS/App id, then check if the data profile's
259         // OS/App id can satisfy it.
260         if (hasAttribute(CAPABILITY_ATTRIBUTE_TRAFFIC_DESCRIPTOR_OS_APP_ID)
261                 && getOsAppId() != null) {
262             // The network request has traffic descriptor type capabilities. Match the traffic
263             // descriptor.
264             if (dataProfile.getTrafficDescriptor() != null && Arrays.equals(getOsAppId().getBytes(),
265                     dataProfile.getTrafficDescriptor().getOsAppId())) {
266                 return true;
267             }
268         }
269 
270         // If the network request can be translated to APN setting or DNN in traffic descriptor,
271         // then check if the data profile's APN setting can satisfy it.
272         if ((hasAttribute(CAPABILITY_ATTRIBUTE_APN_SETTING)
273                 || hasAttribute(CAPABILITY_ATTRIBUTE_TRAFFIC_DESCRIPTOR_DNN))
274                 && dataProfile.getApnSetting() != null) {
275             // Fallback to the legacy APN type matching.
276             List<Integer> apnTypes = Arrays.stream(getCapabilities()).boxed()
277                     .map(DataUtils::networkCapabilityToApnType)
278                     .filter(apnType -> apnType != ApnSetting.TYPE_NONE)
279                     .collect(Collectors.toList());
280             // In case of enterprise network request, the network request will have internet,
281             // but APN type will not have default type as the enterprise apn should not be used
282             // as default network. Ignore default type of the network request if it
283             // has enterprise type as well. This will make sure the network request with
284             // internet and enterprise will be satisfied with data profile with enterprise at the
285             // same time default network request will not get satisfied with enterprise data
286             // profile.
287             // TODO b/232264746
288             if (apnTypes.contains(ApnSetting.TYPE_ENTERPRISE)) {
289                 apnTypes.remove((Integer) ApnSetting.TYPE_DEFAULT);
290             }
291 
292             return apnTypes.stream().allMatch(dataProfile.getApnSetting()::canHandleType);
293         }
294         return false;
295     }
296 
297     /**
298      * Get the priority of the network request.
299      *
300      * @return The priority from 0 to 100. 100 indicates the highest priority.
301      */
getPriority()302     public int getPriority() {
303         return mPriority;
304     }
305 
306     /**
307      * Update the priority from data config manager.
308      */
updatePriority()309     public void updatePriority() {
310         mPriority = Arrays.stream(mNativeNetworkRequest.getCapabilities())
311                 .map(mDataConfigManager::getNetworkCapabilityPriority)
312                 .max()
313                 .orElse(0);
314     }
315 
316     /**
317      * Get the network capability which is APN-type based from the network request. If there are
318      * multiple APN types capability, the highest priority one will be returned.
319      *
320      * @return The highest priority APN type based network capability from this network request. -1
321      * if there is no APN type capabilities in this network request.
322      */
getApnTypeNetworkCapability()323     public @NetCapability int getApnTypeNetworkCapability() {
324         if (!hasAttribute(CAPABILITY_ATTRIBUTE_APN_SETTING)) return -1;
325         return Arrays.stream(getCapabilities()).boxed()
326                 .filter(cap -> DataUtils.networkCapabilityToApnType(cap) != ApnSetting.TYPE_NONE)
327                 .max(Comparator.comparingInt(mDataConfigManager::getNetworkCapabilityPriority))
328                 .orElse(-1);
329     }
330     /**
331      * @return The native network request.
332      */
getNativeNetworkRequest()333     public @NonNull NetworkRequest getNativeNetworkRequest() {
334         return mNativeNetworkRequest;
335     }
336 
337     /**
338      * Set the attached data network.
339      *
340      * @param dataNetwork The data network.
341      */
setAttachedNetwork(@onNull DataNetwork dataNetwork)342     public void setAttachedNetwork(@NonNull DataNetwork dataNetwork) {
343         mAttachedDataNetwork = dataNetwork;
344     }
345 
346     /**
347      * @return The attached network. {@code null} indicates the request is not attached to any
348      * network (i.e. the request is unsatisfied).
349      */
getAttachedNetwork()350     public @Nullable DataNetwork getAttachedNetwork() {
351         return mAttachedDataNetwork;
352     }
353 
354     /**
355      * Set the state of the network request.
356      *
357      * @param state The state.
358      */
setState(@equestState int state)359     public void setState(@RequestState int state) {
360         mState = state;
361     }
362 
363     /**
364      * @return The state of the network request.
365      */
getState()366     public @RequestState int getState() {
367         return mState;
368     }
369 
370     /**
371      * Set the data evaluation result.
372      *
373      * @param evaluation The data evaluation result.
374      */
setEvaluation(@onNull DataEvaluation evaluation)375     public void setEvaluation(@NonNull DataEvaluation evaluation) {
376         mEvaluation = evaluation;
377     }
378 
379     /**
380      * Get the capability differentiator from the network request. Some capabilities
381      * (e.g. {@link NetworkCapabilities#NET_CAPABILITY_ENTERPRISE} could support more than one
382      * traffic (e.g. "ENTERPRISE2", "ENTERPRISE3"). This method returns that differentiator.
383      *
384      * @return The differentiator. 0 if not found.
385      */
getCapabilityDifferentiator()386     public int getCapabilityDifferentiator() {
387         if (hasCapability(NetworkCapabilities.NET_CAPABILITY_ENTERPRISE)) {
388             int[] ids = mNativeNetworkRequest.getEnterpriseIds();
389             // No need to verify the range of the id. It has been done in NetworkCapabilities.
390             if (ids.length > 0) return ids[0];
391         }
392         return 0;
393     }
394 
395     /**
396      * @return {@code true} if this network request can result in bringing up a metered network.
397      */
isMeteredRequest()398     public boolean isMeteredRequest() {
399         return mDataConfigManager.isAnyMeteredCapability(
400                 getCapabilities(), mPhone.getServiceState().getDataRoaming());
401     }
402 
403     /**
404      * Get Os/App id from the network request.
405      *
406      * @return Os/App id. {@code null} if the request does not have traffic descriptor based network
407      * capabilities.
408      */
getOsAppId()409     public @Nullable OsAppId getOsAppId() {
410         if (!hasAttribute(CAPABILITY_ATTRIBUTE_TRAFFIC_DESCRIPTOR_OS_APP_ID)) return null;
411 
412         // We do not support multiple network capabilities translated to Os/App id at this time.
413         // If someday this needs to be done, we need to expand TrafficDescriptor to support
414         // connection capabilities instead of using Os/App id to do the work.
415         int networkCapability = Arrays.stream(getCapabilities()).boxed()
416                 .filter(cap -> (CAPABILITY_ATTRIBUTE_MAP.getOrDefault(
417                         cap, CAPABILITY_ATTRIBUTE_NONE)
418                         & CAPABILITY_ATTRIBUTE_TRAFFIC_DESCRIPTOR_OS_APP_ID) != 0)
419                 .findFirst()
420                 .orElse(-1);
421 
422         if (networkCapability == -1) return null;
423 
424         int differentiator = getCapabilityDifferentiator();
425         if (differentiator > 0) {
426             return new OsAppId(OsAppId.ANDROID_OS_ID,
427                     DataUtils.networkCapabilityToString(networkCapability), differentiator);
428         } else {
429             return new OsAppId(OsAppId.ANDROID_OS_ID,
430                     DataUtils.networkCapabilityToString(networkCapability));
431         }
432     }
433 
434     /**
435      * Convert the telephony request state to string.
436      *
437      * @param state The request state.
438      * @return The request state in string format.
439      */
requestStateToString( @elephonyNetworkRequest.RequestState int state)440     private static @NonNull String requestStateToString(
441             @TelephonyNetworkRequest.RequestState int state) {
442         switch (state) {
443             case TelephonyNetworkRequest.REQUEST_STATE_UNSATISFIED: return "UNSATISFIED";
444             case TelephonyNetworkRequest.REQUEST_STATE_SATISFIED: return "SATISFIED";
445             default: return "UNKNOWN(" + state + ")";
446         }
447     }
448 
449     @Override
toString()450     public String toString() {
451         return "[" + mNativeNetworkRequest.toString() + ", mPriority=" + mPriority
452                 + ", state=" + requestStateToString(mState)
453                 + ", mAttachedDataNetwork=" + (mAttachedDataNetwork != null
454                 ? mAttachedDataNetwork.name() : null) + ", isMetered=" + isMeteredRequest()
455                 + ", created time=" + DataUtils.elapsedTimeToString(mCreatedTimeMillis)
456                 + ", evaluation result=" + mEvaluation + "]";
457     }
458 
459     @Override
equals(Object o)460     public boolean equals(Object o) {
461         if (this == o) return true;
462         if (o == null || getClass() != o.getClass()) return false;
463         TelephonyNetworkRequest that = (TelephonyNetworkRequest) o;
464         // Only compare the native network request.
465         return mNativeNetworkRequest.equals(that.mNativeNetworkRequest);
466     }
467 
468     @Override
hashCode()469     public int hashCode() {
470         // Only use the native network request's hash code.
471         return mNativeNetworkRequest.hashCode();
472     }
473 }
474