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