• 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     // TODO: Make this @NonNull after old data stack removed.
161     private final @Nullable DataConfigManager mDataConfigManager;
162 
163     /**
164      * The attached data network. Note that the data network could be in any state. {@code null}
165      * indicates this network request is not satisfied.
166      */
167     private @Nullable DataNetwork mAttachedDataNetwork;
168 
169     /**
170      * The state of the network request.
171      *
172      * @see #REQUEST_STATE_UNSATISFIED
173      * @see #REQUEST_STATE_SATISFIED
174      */
175     // This is not a boolean because there might be more states in the future.
176     private @RequestState int mState;
177 
178     /** The timestamp when this network request enters telephony. */
179     private final @ElapsedRealtimeLong long mCreatedTimeMillis;
180 
181     /** The data evaluation result. */
182     private @Nullable DataEvaluation mEvaluation;
183 
184     /**
185      * Constructor
186      *
187      * @param request The native network request from the clients.
188      * @param phone The phone instance
189      */
TelephonyNetworkRequest(NetworkRequest request, Phone phone)190     public TelephonyNetworkRequest(NetworkRequest request, Phone phone) {
191         mPhone = phone;
192         mNativeNetworkRequest = request;
193 
194         int capabilitiesAttributes = CAPABILITY_ATTRIBUTE_NONE;
195         for (int networkCapability : mNativeNetworkRequest.getCapabilities()) {
196             capabilitiesAttributes |= CAPABILITY_ATTRIBUTE_MAP.getOrDefault(
197                     networkCapability, CAPABILITY_ATTRIBUTE_NONE);
198         }
199         mCapabilitiesAttributes = capabilitiesAttributes;
200 
201         mPriority = 0;
202         mAttachedDataNetwork = null;
203         // When the request was first created, it is in active state so we can actively attempt
204         // to satisfy it.
205         mState = REQUEST_STATE_UNSATISFIED;
206         mCreatedTimeMillis = SystemClock.elapsedRealtime();
207         if (phone.isUsingNewDataStack()) {
208             mDataConfigManager = phone.getDataNetworkController().getDataConfigManager();
209             updatePriority();
210         } else {
211             mDataConfigManager = null;
212         }
213     }
214 
215     /**
216      * @see NetworkRequest#getNetworkSpecifier()
217      */
getNetworkSpecifier()218     public @Nullable NetworkSpecifier getNetworkSpecifier() {
219         return mNativeNetworkRequest.getNetworkSpecifier();
220     }
221 
222     /**
223      * @see NetworkRequest#getCapabilities()
224      */
getCapabilities()225     public @NonNull @NetCapability int[] getCapabilities() {
226         return mNativeNetworkRequest.getCapabilities();
227     }
228 
229     /**
230      * @see NetworkRequest#hasCapability(int)
231      */
hasCapability(@etCapability int capability)232     public boolean hasCapability(@NetCapability int capability) {
233         return mNativeNetworkRequest.hasCapability(capability);
234     }
235 
236     /**
237      * @see NetworkRequest#canBeSatisfiedBy(NetworkCapabilities)
238      */
canBeSatisfiedBy(@ullable NetworkCapabilities nc)239     public boolean canBeSatisfiedBy(@Nullable NetworkCapabilities nc) {
240         return mNativeNetworkRequest.canBeSatisfiedBy(nc);
241     }
242 
243 
244     /**
245      * Check if the request's capabilities have certain attributes.
246      *
247      * @param capabilitiesAttributes The attributes to check.
248      * @return {@code true} if the capabilities have provided attributes.
249      *
250      * @see NetCapabilityAttribute
251      */
hasAttribute(@etCapabilityAttribute int capabilitiesAttributes)252     public boolean hasAttribute(@NetCapabilityAttribute int capabilitiesAttributes) {
253         return (mCapabilitiesAttributes & capabilitiesAttributes) == capabilitiesAttributes;
254     }
255 
256     /**
257      * Check if this network request can be satisfied by a data profile.
258      *
259      * @param dataProfile The data profile to check.
260      * @return {@code true} if this network request can be satisfied by the data profile.
261      */
canBeSatisfiedBy(@onNull DataProfile dataProfile)262     public boolean canBeSatisfiedBy(@NonNull DataProfile dataProfile) {
263         // If the network request can be translated to OS/App id, then check if the data profile's
264         // OS/App id can satisfy it.
265         if (hasAttribute(CAPABILITY_ATTRIBUTE_TRAFFIC_DESCRIPTOR_OS_APP_ID)
266                 && getOsAppId() != null) {
267             // The network request has traffic descriptor type capabilities. Match the traffic
268             // descriptor.
269             if (dataProfile.getTrafficDescriptor() != null && Arrays.equals(getOsAppId().getBytes(),
270                     dataProfile.getTrafficDescriptor().getOsAppId())) {
271                 return true;
272             }
273         }
274 
275         // If the network request can be translated to APN setting or DNN in traffic descriptor,
276         // then check if the data profile's APN setting can satisfy it.
277         if ((hasAttribute(CAPABILITY_ATTRIBUTE_APN_SETTING)
278                 || hasAttribute(CAPABILITY_ATTRIBUTE_TRAFFIC_DESCRIPTOR_DNN))
279                 && dataProfile.getApnSetting() != null) {
280             // Fallback to the legacy APN type matching.
281             List<Integer> apnTypes = Arrays.stream(getCapabilities()).boxed()
282                     .map(DataUtils::networkCapabilityToApnType)
283                     .filter(apnType -> apnType != ApnSetting.TYPE_NONE)
284                     .collect(Collectors.toList());
285             // In case of enterprise network request, the network request will have internet,
286             // but APN type will not have default type as the enterprise apn should not be used
287             // as default network. Ignore default type of the network request if it
288             // has enterprise type as well. This will make sure the network request with
289             // internet and enterprise will be satisfied with data profile with enterprise at the
290             // same time default network request will not get satisfied with enterprise data
291             // profile.
292             // TODO b/232264746
293             if (apnTypes.contains(ApnSetting.TYPE_ENTERPRISE)) {
294                 apnTypes.remove((Integer) ApnSetting.TYPE_DEFAULT);
295             }
296 
297             return apnTypes.stream().allMatch(dataProfile.getApnSetting()::canHandleType);
298         }
299         return false;
300     }
301 
302     /**
303      * Get the priority of the network request.
304      *
305      * @return The priority from 0 to 100. 100 indicates the highest priority.
306      */
getPriority()307     public int getPriority() {
308         return mPriority;
309     }
310 
311     /**
312      * Update the priority from data config manager.
313      */
updatePriority()314     public void updatePriority() {
315         mPriority = Arrays.stream(mNativeNetworkRequest.getCapabilities())
316                 .map(mDataConfigManager::getNetworkCapabilityPriority)
317                 .max()
318                 .orElse(0);
319     }
320 
321     /**
322      * Get the network capability which is APN-type based from the network request. If there are
323      * multiple APN types capability, the highest priority one will be returned.
324      *
325      * @return The highest priority APN type based network capability from this network request. -1
326      * if there is no APN type capabilities in this network request.
327      */
getApnTypeNetworkCapability()328     public @NetCapability int getApnTypeNetworkCapability() {
329         if (!hasAttribute(CAPABILITY_ATTRIBUTE_APN_SETTING)) return -1;
330         return Arrays.stream(getCapabilities()).boxed()
331                 .filter(cap -> DataUtils.networkCapabilityToApnType(cap) != ApnSetting.TYPE_NONE)
332                 .max(Comparator.comparingInt(mDataConfigManager::getNetworkCapabilityPriority))
333                 .orElse(-1);
334     }
335     /**
336      * @return The native network request.
337      */
getNativeNetworkRequest()338     public @NonNull NetworkRequest getNativeNetworkRequest() {
339         return mNativeNetworkRequest;
340     }
341 
342     /**
343      * Set the attached data network.
344      *
345      * @param dataNetwork The data network.
346      */
setAttachedNetwork(@onNull DataNetwork dataNetwork)347     public void setAttachedNetwork(@NonNull DataNetwork dataNetwork) {
348         mAttachedDataNetwork = dataNetwork;
349     }
350 
351     /**
352      * @return The attached network. {@code null} indicates the request is not attached to any
353      * network (i.e. the request is unsatisfied).
354      */
getAttachedNetwork()355     public @Nullable DataNetwork getAttachedNetwork() {
356         return mAttachedDataNetwork;
357     }
358 
359     /**
360      * Set the state of the network request.
361      *
362      * @param state The state.
363      */
setState(@equestState int state)364     public void setState(@RequestState int state) {
365         mState = state;
366     }
367 
368     /**
369      * @return The state of the network request.
370      */
getState()371     public @RequestState int getState() {
372         return mState;
373     }
374 
375     /**
376      * Set the data evaluation result.
377      *
378      * @param evaluation The data evaluation result.
379      */
setEvaluation(@onNull DataEvaluation evaluation)380     public void setEvaluation(@NonNull DataEvaluation evaluation) {
381         mEvaluation = evaluation;
382     }
383 
384     /**
385      * Get the capability differentiator from the network request. Some capabilities
386      * (e.g. {@link NetworkCapabilities#NET_CAPABILITY_ENTERPRISE} could support more than one
387      * traffic (e.g. "ENTERPRISE2", "ENTERPRISE3"). This method returns that differentiator.
388      *
389      * @return The differentiator. 0 if not found.
390      */
getCapabilityDifferentiator()391     public int getCapabilityDifferentiator() {
392         if (hasCapability(NetworkCapabilities.NET_CAPABILITY_ENTERPRISE)) {
393             int[] ids = mNativeNetworkRequest.getEnterpriseIds();
394             // No need to verify the range of the id. It has been done in NetworkCapabilities.
395             if (ids.length > 0) return ids[0];
396         }
397         return 0;
398     }
399 
400     /**
401      * @return {@code true} if this network request can result in bringing up a metered network.
402      */
isMeteredRequest()403     public boolean isMeteredRequest() {
404         // TODO: Remove null check after old data stack removed.
405         return mDataConfigManager != null && mDataConfigManager.isAnyMeteredCapability(
406                 getCapabilities(), mPhone.getServiceState().getDataRoaming());
407     }
408 
409     /**
410      * Get Os/App id from the network request.
411      *
412      * @return Os/App id. {@code null} if the request does not have traffic descriptor based network
413      * capabilities.
414      */
getOsAppId()415     public @Nullable OsAppId getOsAppId() {
416         if (!hasAttribute(CAPABILITY_ATTRIBUTE_TRAFFIC_DESCRIPTOR_OS_APP_ID)) return null;
417 
418         // We do not support multiple network capabilities translated to Os/App id at this time.
419         // If someday this needs to be done, we need to expand TrafficDescriptor to support
420         // connection capabilities instead of using Os/App id to do the work.
421         int networkCapability = Arrays.stream(getCapabilities()).boxed()
422                 .filter(cap -> (CAPABILITY_ATTRIBUTE_MAP.getOrDefault(
423                         cap, CAPABILITY_ATTRIBUTE_NONE)
424                         & CAPABILITY_ATTRIBUTE_TRAFFIC_DESCRIPTOR_OS_APP_ID) != 0)
425                 .findFirst()
426                 .orElse(-1);
427 
428         if (networkCapability == -1) return null;
429 
430         int differentiator = getCapabilityDifferentiator();
431         if (differentiator > 0) {
432             return new OsAppId(OsAppId.ANDROID_OS_ID,
433                     DataUtils.networkCapabilityToString(networkCapability), differentiator);
434         } else {
435             return new OsAppId(OsAppId.ANDROID_OS_ID,
436                     DataUtils.networkCapabilityToString(networkCapability));
437         }
438     }
439 
440     /**
441      * Convert the telephony request state to string.
442      *
443      * @param state The request state.
444      * @return The request state in string format.
445      */
requestStateToString( @elephonyNetworkRequest.RequestState int state)446     private static @NonNull String requestStateToString(
447             @TelephonyNetworkRequest.RequestState int state) {
448         switch (state) {
449             case TelephonyNetworkRequest.REQUEST_STATE_UNSATISFIED: return "UNSATISFIED";
450             case TelephonyNetworkRequest.REQUEST_STATE_SATISFIED: return "SATISFIED";
451             default: return "UNKNOWN(" + state + ")";
452         }
453     }
454 
455     @Override
toString()456     public String toString() {
457         return "[" + mNativeNetworkRequest.toString() + ", mPriority=" + mPriority
458                 + ", state=" + requestStateToString(mState)
459                 + ", mAttachedDataNetwork=" + (mAttachedDataNetwork != null
460                 ? mAttachedDataNetwork.name() : null) + ", isMetered=" + isMeteredRequest()
461                 + ", created time=" + DataUtils.elapsedTimeToString(mCreatedTimeMillis)
462                 + ", evaluation result=" + mEvaluation + "]";
463     }
464 
465     @Override
equals(Object o)466     public boolean equals(Object o) {
467         if (this == o) return true;
468         if (o == null || getClass() != o.getClass()) return false;
469         TelephonyNetworkRequest that = (TelephonyNetworkRequest) o;
470         // Only compare the native network request.
471         return mNativeNetworkRequest.equals(that.mNativeNetworkRequest);
472     }
473 
474     @Override
hashCode()475     public int hashCode() {
476         // Only use the native network request's hash code.
477         return mNativeNetworkRequest.hashCode();
478     }
479 }
480