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