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