1 /* 2 * Copyright 2020 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.google.android.iwlan; 18 19 import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; 20 import static android.net.NetworkCapabilities.TRANSPORT_WIFI; 21 import static android.net.ipsec.ike.ike3gpp.Ike3gppParams.PDU_SESSION_ID_UNSET; 22 import static android.telephony.PreciseDataConnectionState.NetworkValidationStatus; 23 24 import static com.google.android.iwlan.epdg.EpdgTunnelManager.BRINGDOWN_REASON_DEACTIVATE_DATA_CALL; 25 import static com.google.android.iwlan.epdg.EpdgTunnelManager.BRINGDOWN_REASON_IN_DEACTIVATING_STATE; 26 import static com.google.android.iwlan.epdg.EpdgTunnelManager.BRINGDOWN_REASON_NETWORK_UPDATE_WHEN_TUNNEL_IN_BRINGUP; 27 import static com.google.android.iwlan.epdg.EpdgTunnelManager.BRINGDOWN_REASON_SERVICE_OUT_OF_SYNC; 28 29 import android.content.Context; 30 import android.content.Intent; 31 import android.net.ConnectivityManager; 32 import android.net.LinkAddress; 33 import android.net.LinkProperties; 34 import android.net.Network; 35 import android.net.NetworkCapabilities; 36 import android.net.NetworkSpecifier; 37 import android.net.TelephonyNetworkSpecifier; 38 import android.net.TransportInfo; 39 import android.net.vcn.VcnTransportInfo; 40 import android.net.wifi.WifiInfo; 41 import android.net.wifi.WifiManager; 42 import android.os.Handler; 43 import android.os.HandlerThread; 44 import android.os.IBinder; 45 import android.os.Looper; 46 import android.os.Message; 47 import android.support.annotation.IntRange; 48 import android.support.annotation.NonNull; 49 import android.support.annotation.Nullable; 50 import android.telephony.AccessNetworkConstants.AccessNetworkType; 51 import android.telephony.CarrierConfigManager; 52 import android.telephony.CellInfo; 53 import android.telephony.CellInfoGsm; 54 import android.telephony.CellInfoLte; 55 import android.telephony.CellInfoNr; 56 import android.telephony.CellInfoWcdma; 57 import android.telephony.DataFailCause; 58 import android.telephony.PreciseDataConnectionState; 59 import android.telephony.TelephonyManager; 60 import android.telephony.data.ApnSetting; 61 import android.telephony.data.DataCallResponse; 62 import android.telephony.data.DataProfile; 63 import android.telephony.data.DataService; 64 import android.telephony.data.DataServiceCallback; 65 import android.telephony.data.NetworkSliceInfo; 66 import android.telephony.data.TrafficDescriptor; 67 import android.util.Log; 68 69 import com.android.internal.annotations.VisibleForTesting; 70 71 import com.google.android.iwlan.TunnelMetricsInterface.OnClosedMetrics; 72 import com.google.android.iwlan.TunnelMetricsInterface.OnOpenedMetrics; 73 import com.google.android.iwlan.epdg.EpdgSelector; 74 import com.google.android.iwlan.epdg.EpdgTunnelManager; 75 import com.google.android.iwlan.epdg.TunnelLinkProperties; 76 import com.google.android.iwlan.epdg.TunnelSetupRequest; 77 import com.google.android.iwlan.flags.FeatureFlags; 78 import com.google.android.iwlan.flags.FeatureFlagsImpl; 79 import com.google.android.iwlan.proto.MetricsAtom; 80 81 import java.io.FileDescriptor; 82 import java.io.PrintWriter; 83 import java.net.Inet4Address; 84 import java.net.Inet6Address; 85 import java.net.InetAddress; 86 import java.net.UnknownHostException; 87 import java.util.ArrayList; 88 import java.util.Arrays; 89 import java.util.Calendar; 90 import java.util.Date; 91 import java.util.HashMap; 92 import java.util.List; 93 import java.util.LongSummaryStatistics; 94 import java.util.Map; 95 import java.util.Objects; 96 import java.util.concurrent.ConcurrentHashMap; 97 import java.util.concurrent.Executor; 98 import java.util.function.Consumer; 99 100 public class IwlanDataService extends DataService { 101 102 private final FeatureFlags mFeatureFlags; 103 private static final String TAG = IwlanDataService.class.getSimpleName(); 104 105 private static final String CONTEXT_ATTRIBUTION_TAG = "IWLAN"; 106 private static Context mContext; 107 private IwlanNetworkMonitorCallback mNetworkMonitorCallback; 108 private static boolean sNetworkConnected = false; 109 private static Network sNetwork = null; 110 private static LinkProperties sLinkProperties = null; 111 private static NetworkCapabilities sNetworkCapabilities; 112 @VisibleForTesting Handler mIwlanDataServiceHandler; 113 private HandlerThread mIwlanDataServiceHandlerThread; 114 private static final Map<Integer, IwlanDataServiceProvider> sIwlanDataServiceProviders = 115 new ConcurrentHashMap<>(); 116 private static final int INVALID_SUB_ID = -1; 117 118 // The current subscription with the active internet PDN. Need not be the default data sub. 119 // If internet is over WiFi, this value will be INVALID_SUB_ID. 120 private static int mConnectedDataSub = INVALID_SUB_ID; 121 122 private static final int EVENT_BASE = IwlanEventListener.DATA_SERVICE_INTERNAL_EVENT_BASE; 123 private static final int EVENT_TUNNEL_OPENED = EVENT_BASE; 124 private static final int EVENT_TUNNEL_CLOSED = EVENT_BASE + 1; 125 private static final int EVENT_SETUP_DATA_CALL = EVENT_BASE + 2; 126 private static final int EVENT_DEACTIVATE_DATA_CALL = EVENT_BASE + 3; 127 private static final int EVENT_DATA_CALL_LIST_REQUEST = EVENT_BASE + 4; 128 private static final int EVENT_FORCE_CLOSE_TUNNEL = EVENT_BASE + 5; 129 private static final int EVENT_ADD_DATA_SERVICE_PROVIDER = EVENT_BASE + 6; 130 private static final int EVENT_REMOVE_DATA_SERVICE_PROVIDER = EVENT_BASE + 7; 131 private static final int EVENT_TUNNEL_OPENED_METRICS = EVENT_BASE + 8; 132 private static final int EVENT_TUNNEL_CLOSED_METRICS = EVENT_BASE + 9; 133 private static final int EVENT_DEACTIVATE_DATA_CALL_WITH_DELAY = EVENT_BASE + 10; 134 private static final int EVENT_ON_LIVENESS_STATUS_CHANGED = EVENT_BASE + 11; 135 private static final int EVENT_REQUEST_NETWORK_VALIDATION = EVENT_BASE + 12; 136 137 @VisibleForTesting 138 enum Transport { 139 UNSPECIFIED_NETWORK, 140 MOBILE, 141 WIFI 142 } 143 144 private static Transport sDefaultDataTransport = Transport.UNSPECIFIED_NETWORK; 145 146 private boolean mIs5GEnabledOnUi; 147 IwlanDataService()148 public IwlanDataService() { 149 mFeatureFlags = new FeatureFlagsImpl(); 150 } 151 152 @VisibleForTesting IwlanDataService(FeatureFlags featureFlags)153 IwlanDataService(FeatureFlags featureFlags) { 154 mFeatureFlags = featureFlags; 155 } 156 157 // TODO: see if network monitor callback impl can be shared between dataservice and 158 // networkservice 159 // This callback runs in the same thread as IwlanDataServiceHandler 160 static class IwlanNetworkMonitorCallback extends ConnectivityManager.NetworkCallback { IwlanNetworkMonitorCallback()161 IwlanNetworkMonitorCallback() { 162 super(ConnectivityManager.NetworkCallback.FLAG_INCLUDE_LOCATION_INFO); 163 } 164 165 /** Called when the framework connects and has declared a new network ready for use. */ 166 @Override onAvailable(@onNull Network network)167 public void onAvailable(@NonNull Network network) { 168 Log.d(TAG, "onAvailable: " + network); 169 } 170 171 /** 172 * Called when the network is about to be lost, typically because there are no outstanding 173 * requests left for it. This may be paired with a {@link NetworkCallback#onAvailable} call 174 * with the new replacement network for graceful handover. This method is not guaranteed to 175 * be called before {@link NetworkCallback#onLost} is called, for example in case a network 176 * is suddenly disconnected. 177 */ 178 @Override onLosing(@onNull Network network, int maxMsToLive)179 public void onLosing(@NonNull Network network, int maxMsToLive) { 180 Log.d(TAG, "onLosing: maxMsToLive: " + maxMsToLive + " network: " + network); 181 } 182 183 /** 184 * Called when a network disconnects or otherwise no longer satisfies this request or 185 * callback. 186 */ 187 @Override onLost(@onNull Network network)188 public void onLost(@NonNull Network network) { 189 Log.d(TAG, "onLost: " + network); 190 IwlanDataService.setConnectedDataSub(INVALID_SUB_ID); 191 IwlanDataService.setNetworkConnected(false, network, Transport.UNSPECIFIED_NETWORK); 192 } 193 194 /** Called when the network corresponding to this request changes {@link LinkProperties}. */ 195 @Override onLinkPropertiesChanged( @onNull Network network, @NonNull LinkProperties linkProperties)196 public void onLinkPropertiesChanged( 197 @NonNull Network network, @NonNull LinkProperties linkProperties) { 198 Log.d(TAG, "onLinkPropertiesChanged: " + linkProperties); 199 200 if (!network.equals(sNetwork)) { 201 Log.d(TAG, "Ignore LinkProperties changes for unused Network."); 202 return; 203 } 204 205 if (!linkProperties.equals(sLinkProperties)) { 206 for (IwlanDataServiceProvider dp : sIwlanDataServiceProviders.values()) { 207 dp.dnsPrefetchCheck(); 208 sLinkProperties = linkProperties; 209 dp.updateNetwork(network, linkProperties); 210 } 211 } 212 } 213 214 /** Called when access to the specified network is blocked or unblocked. */ 215 @Override onBlockedStatusChanged(@onNull Network network, boolean blocked)216 public void onBlockedStatusChanged(@NonNull Network network, boolean blocked) { 217 // TODO: check if we need to handle this 218 Log.d(TAG, "onBlockedStatusChanged: " + network + " BLOCKED:" + blocked); 219 } 220 221 @Override onCapabilitiesChanged( @onNull Network network, @NonNull NetworkCapabilities networkCapabilities)222 public void onCapabilitiesChanged( 223 @NonNull Network network, @NonNull NetworkCapabilities networkCapabilities) { 224 // onCapabilitiesChanged is guaranteed to be called immediately after onAvailable per 225 // API 226 Log.d(TAG, "onCapabilitiesChanged: " + network + " " + networkCapabilities); 227 if (networkCapabilities != null) { 228 if (networkCapabilities.hasTransport(TRANSPORT_CELLULAR)) { 229 Log.d(TAG, "Network " + network + " connected using transport MOBILE"); 230 IwlanDataService.setConnectedDataSub(getConnectedDataSub(networkCapabilities)); 231 IwlanDataService.setNetworkConnected(true, network, Transport.MOBILE); 232 } else if (networkCapabilities.hasTransport(TRANSPORT_WIFI)) { 233 Log.d(TAG, "Network " + network + " connected using transport WIFI"); 234 IwlanDataService.setConnectedDataSub(INVALID_SUB_ID); 235 IwlanDataService.setNetworkCapabilities(networkCapabilities); 236 IwlanDataService.setNetworkConnected(true, network, Transport.WIFI); 237 } else { 238 Log.w(TAG, "Network does not have cellular or wifi capability"); 239 } 240 } 241 } 242 } 243 244 @VisibleForTesting 245 class IwlanDataServiceProvider extends DataService.DataServiceProvider { 246 private static final int CALLBACK_TYPE_SETUP_DATACALL_COMPLETE = 1; 247 private static final int CALLBACK_TYPE_DEACTIVATE_DATACALL_COMPLETE = 2; 248 private static final int CALLBACK_TYPE_GET_DATACALL_LIST_COMPLETE = 3; 249 250 private final String SUB_TAG; 251 private final IwlanDataService mIwlanDataService; 252 private final IwlanTunnelCallback mIwlanTunnelCallback; 253 private final IwlanTunnelMetricsImpl mIwlanTunnelMetrics; 254 private boolean mWfcEnabled = false; 255 private boolean mCarrierConfigReady = false; 256 private final EpdgSelector mEpdgSelector; 257 private final IwlanDataTunnelStats mTunnelStats; 258 private CellInfo mCellInfo = null; 259 private int mCallState = TelephonyManager.CALL_STATE_IDLE; 260 private long mProcessingStartTime = 0; 261 262 // apn to TunnelState 263 // Access should be serialized inside IwlanDataServiceHandler 264 private final Map<String, TunnelState> mTunnelStateForApn = new ConcurrentHashMap<>(); 265 private final Map<String, MetricsAtom> mMetricsAtomForApn = new ConcurrentHashMap<>(); 266 private Calendar mCalendar; 267 268 // Holds the state of a tunnel (for an APN) 269 @VisibleForTesting 270 class TunnelState { 271 272 // this should be ideally be based on path MTU discovery. 1280 is the minimum packet 273 // size ipv6 routers have to handle so setting it to 1280 is the safest approach. 274 // ideally it should be 1280 - tunnelling overhead ? 275 private static final int LINK_MTU = 1280; // TODO: need to subtract tunnelling overhead? 276 private static final int LINK_MTU_CST = 1200; // Reserve 80 bytes for VCN. 277 static final int TUNNEL_DOWN = 1; 278 static final int TUNNEL_IN_BRINGUP = 2; 279 static final int TUNNEL_UP = 3; 280 static final int TUNNEL_IN_BRINGDOWN = 4; 281 static final int TUNNEL_IN_FORCE_CLEAN_WAS_IN_BRINGUP = 5; 282 private DataServiceCallback dataServiceCallback; 283 private int mState; 284 private int mPduSessionId; 285 private TunnelLinkProperties mTunnelLinkProperties; 286 private boolean mIsHandover; 287 private Date mBringUpStateTime = null; 288 private Date mUpStateTime = null; 289 private boolean mIsImsOrEmergency; 290 private DeactivateDataCallData mPendingDeactivateDataCallData; 291 private boolean mIsDataCallWithN1; 292 private int mNetworkValidationStatus = 293 PreciseDataConnectionState.NETWORK_VALIDATION_SUCCESS; 294 private int mApnTypeBitmask; 295 getIsDataCallWithN1()296 public boolean getIsDataCallWithN1() { 297 return mIsDataCallWithN1; 298 } 299 setIsDataCallWithN1(boolean mIsDataCallWithN1)300 public void setIsDataCallWithN1(boolean mIsDataCallWithN1) { 301 this.mIsDataCallWithN1 = mIsDataCallWithN1; 302 } 303 getPduSessionId()304 public int getPduSessionId() { 305 return mPduSessionId; 306 } 307 setPduSessionId(int mPduSessionId)308 public void setPduSessionId(int mPduSessionId) { 309 this.mPduSessionId = mPduSessionId; 310 } 311 getLinkMtu()312 public int getLinkMtu() { 313 if ((sDefaultDataTransport == Transport.MOBILE) && sNetworkConnected) { 314 return LINK_MTU_CST; 315 } else { 316 return LINK_MTU; // TODO: need to subtract tunnelling overhead 317 } 318 } 319 getRequestedProtocolType()320 public @ApnSetting.ProtocolType int getRequestedProtocolType() { 321 return mProtocolType; 322 } 323 setProtocolType(int protocolType)324 public void setProtocolType(int protocolType) { 325 mProtocolType = protocolType; 326 } 327 328 private int mProtocolType; // from DataProfile 329 getTunnelLinkProperties()330 public TunnelLinkProperties getTunnelLinkProperties() { 331 return mTunnelLinkProperties; 332 } 333 setTunnelLinkProperties(TunnelLinkProperties tunnelLinkProperties)334 public void setTunnelLinkProperties(TunnelLinkProperties tunnelLinkProperties) { 335 mTunnelLinkProperties = tunnelLinkProperties; 336 } 337 getDataServiceCallback()338 public DataServiceCallback getDataServiceCallback() { 339 return dataServiceCallback; 340 } 341 setDataServiceCallback(DataServiceCallback dataServiceCallback)342 public void setDataServiceCallback(DataServiceCallback dataServiceCallback) { 343 this.dataServiceCallback = dataServiceCallback; 344 } 345 TunnelState(DataServiceCallback callback)346 public TunnelState(DataServiceCallback callback) { 347 dataServiceCallback = callback; 348 mState = TUNNEL_DOWN; 349 } 350 getState()351 public int getState() { 352 return mState; 353 } 354 getPendingDeactivateDataCallData()355 public DeactivateDataCallData getPendingDeactivateDataCallData() { 356 return mPendingDeactivateDataCallData; 357 } 358 hasPendingDeactivateDataCallData()359 public boolean hasPendingDeactivateDataCallData() { 360 return mPendingDeactivateDataCallData != null; 361 } 362 363 /** 364 * @param state (TunnelState.TUNNEL_DOWN|TUNNEL_UP|TUNNEL_DOWN) 365 */ setState(int state)366 public void setState(int state) { 367 mState = state; 368 if (mState == TunnelState.TUNNEL_IN_BRINGUP) { 369 mBringUpStateTime = mCalendar.getTime(); 370 } 371 if (mState == TunnelState.TUNNEL_UP) { 372 mUpStateTime = mCalendar.getTime(); 373 } 374 } 375 setIsHandover(boolean isHandover)376 public void setIsHandover(boolean isHandover) { 377 mIsHandover = isHandover; 378 } 379 getIsHandover()380 public boolean getIsHandover() { 381 return mIsHandover; 382 } 383 getBringUpStateTime()384 public Date getBringUpStateTime() { 385 return mBringUpStateTime; 386 } 387 getUpStateTime()388 public Date getUpStateTime() { 389 return mUpStateTime; 390 } 391 getCurrentTime()392 public Date getCurrentTime() { 393 return mCalendar.getTime(); 394 } 395 getIsImsOrEmergency()396 public boolean getIsImsOrEmergency() { 397 return mIsImsOrEmergency; 398 } 399 setIsImsOrEmergency(boolean isImsOrEmergency)400 public void setIsImsOrEmergency(boolean isImsOrEmergency) { 401 mIsImsOrEmergency = isImsOrEmergency; 402 } 403 setPendingDeactivateDataCallData( DeactivateDataCallData deactivateDataCallData)404 public void setPendingDeactivateDataCallData( 405 DeactivateDataCallData deactivateDataCallData) { 406 mPendingDeactivateDataCallData = deactivateDataCallData; 407 } 408 setNetworkValidationStatus(int networkValidationStatus)409 public void setNetworkValidationStatus(int networkValidationStatus) { 410 mNetworkValidationStatus = networkValidationStatus; 411 } 412 getNetworkValidationStatus()413 public int getNetworkValidationStatus() { 414 return mNetworkValidationStatus; 415 } 416 setApnTypeBitmask(int apnTypeBitmask)417 public void setApnTypeBitmask(int apnTypeBitmask) { 418 mApnTypeBitmask = apnTypeBitmask; 419 } 420 hasApnType(int apnType)421 public boolean hasApnType(int apnType) { 422 return (mApnTypeBitmask & apnType) != 0; 423 } 424 425 @Override toString()426 public String toString() { 427 StringBuilder sb = new StringBuilder(); 428 String tunnelState = "UNKNOWN"; 429 switch (mState) { 430 case TUNNEL_DOWN: 431 tunnelState = "DOWN"; 432 break; 433 case TUNNEL_IN_BRINGUP: 434 tunnelState = "IN BRINGUP"; 435 break; 436 case TUNNEL_UP: 437 tunnelState = "UP"; 438 break; 439 case TUNNEL_IN_BRINGDOWN: 440 tunnelState = "IN BRINGDOWN"; 441 break; 442 case TUNNEL_IN_FORCE_CLEAN_WAS_IN_BRINGUP: 443 tunnelState = "IN FORCE CLEAN WAS IN BRINGUP"; 444 break; 445 } 446 sb.append("\tCurrent State of this tunnel: ") 447 .append(mState) 448 .append(" ") 449 .append(tunnelState); 450 sb.append("\n\tTunnel state is in Handover: ").append(mIsHandover); 451 if (mBringUpStateTime != null) { 452 sb.append("\n\tTunnel bring up initiated at: ").append(mBringUpStateTime); 453 } else { 454 sb.append("\n\tPotential leak. Null mBringUpStateTime"); 455 } 456 if (mUpStateTime != null) { 457 sb.append("\n\tTunnel is up at: ").append(mUpStateTime); 458 } 459 if (mUpStateTime != null && mBringUpStateTime != null) { 460 long tunnelUpTime = mUpStateTime.getTime() - mBringUpStateTime.getTime(); 461 sb.append("\n\tTime taken for the tunnel to come up in ms: ") 462 .append(tunnelUpTime); 463 } 464 sb.append("\n\tCurrent network validation status: ") 465 .append(mNetworkValidationStatus); 466 return sb.toString(); 467 } 468 } 469 470 @VisibleForTesting 471 class IwlanTunnelCallback implements EpdgTunnelManager.TunnelCallback { 472 473 IwlanDataServiceProvider mIwlanDataServiceProvider; 474 IwlanTunnelCallback(IwlanDataServiceProvider dsp)475 public IwlanTunnelCallback(IwlanDataServiceProvider dsp) { 476 mIwlanDataServiceProvider = dsp; 477 } 478 479 // TODO: full implementation 480 onOpened(String apnName, TunnelLinkProperties linkProperties)481 public void onOpened(String apnName, TunnelLinkProperties linkProperties) { 482 Log.d( 483 SUB_TAG, 484 "Tunnel opened! APN: " + apnName + ", linkProperties: " + linkProperties); 485 getIwlanDataServiceHandler() 486 .sendMessage( 487 getIwlanDataServiceHandler() 488 .obtainMessage( 489 EVENT_TUNNEL_OPENED, 490 new TunnelOpenedData( 491 apnName, 492 linkProperties, 493 mIwlanDataServiceProvider))); 494 } 495 onClosed(String apnName, IwlanError error)496 public void onClosed(String apnName, IwlanError error) { 497 Log.d(SUB_TAG, "Tunnel closed! APN: " + apnName + ", Error: " + error); 498 // this is called, when a tunnel that is up, is closed. 499 // the expectation is error==NO_ERROR for user initiated/normal close. 500 getIwlanDataServiceHandler() 501 .sendMessage( 502 getIwlanDataServiceHandler() 503 .obtainMessage( 504 EVENT_TUNNEL_CLOSED, 505 new TunnelClosedData( 506 apnName, 507 error, 508 mIwlanDataServiceProvider))); 509 } 510 onNetworkValidationStatusChanged( String apnName, @NetworkValidationStatus int status)511 public void onNetworkValidationStatusChanged( 512 String apnName, @NetworkValidationStatus int status) { 513 Log.d( 514 SUB_TAG, 515 "Liveness status changed. APN: " 516 + apnName 517 + ", status: " 518 + PreciseDataConnectionState.networkValidationStatusToString( 519 status)); 520 getIwlanDataServiceHandler() 521 .obtainMessage( 522 EVENT_ON_LIVENESS_STATUS_CHANGED, 523 new TunnelValidationStatusData( 524 apnName, status, mIwlanDataServiceProvider)) 525 .sendToTarget(); 526 } 527 } 528 529 /** Holds all tunnel related time and count statistics for this IwlanDataServiceProvider */ 530 @VisibleForTesting 531 class IwlanDataTunnelStats { 532 533 // represents the start time from when the following events are recorded 534 private Date mStartTime; 535 536 // Stats for TunnelSetup Success time (BRING_UP -> UP state) 537 @VisibleForTesting 538 Map<String, LongSummaryStatistics> mTunnelSetupSuccessStats = 539 new HashMap<String, LongSummaryStatistics>(); 540 541 // Count for Tunnel Setup failures onClosed when in BRING_UP 542 @VisibleForTesting 543 Map<String, Long> mTunnelSetupFailureCounts = new HashMap<String, Long>(); 544 545 // Count for unsol tunnel down onClosed when in UP without deactivate 546 @VisibleForTesting 547 Map<String, Long> mUnsolTunnelDownCounts = new HashMap<String, Long>(); 548 549 // Stats for how long the tunnel is in up state onClosed when in UP 550 @VisibleForTesting 551 Map<String, LongSummaryStatistics> mTunnelUpStats = 552 new HashMap<String, LongSummaryStatistics>(); 553 554 private long statCount; 555 private final long COUNT_MAX = 1000; 556 IwlanDataTunnelStats()557 public IwlanDataTunnelStats() { 558 mStartTime = mCalendar.getTime(); 559 statCount = 0L; 560 } 561 reportTunnelSetupSuccess(String apn, TunnelState tunnelState)562 public void reportTunnelSetupSuccess(String apn, TunnelState tunnelState) { 563 if (statCount > COUNT_MAX || maxApnReached()) { 564 reset(); 565 } 566 statCount++; 567 568 Date bringUpTime = tunnelState.getBringUpStateTime(); 569 Date upTime = tunnelState.getUpStateTime(); 570 571 if (bringUpTime != null && upTime != null) { 572 long tunnelUpTime = upTime.getTime() - bringUpTime.getTime(); 573 if (!mTunnelSetupSuccessStats.containsKey(apn)) { 574 mTunnelSetupSuccessStats.put(apn, new LongSummaryStatistics()); 575 } 576 LongSummaryStatistics stats = mTunnelSetupSuccessStats.get(apn); 577 stats.accept(tunnelUpTime); 578 mTunnelSetupSuccessStats.put(apn, stats); 579 } 580 } 581 reportTunnelDown(String apn, TunnelState tunnelState)582 public void reportTunnelDown(String apn, TunnelState tunnelState) { 583 if (statCount > COUNT_MAX || maxApnReached()) { 584 reset(); 585 } 586 statCount++; 587 588 // Setup fail 589 if (tunnelState.getState() == TunnelState.TUNNEL_IN_BRINGUP) { 590 if (!mTunnelSetupFailureCounts.containsKey(apn)) { 591 mTunnelSetupFailureCounts.put(apn, 0L); 592 } 593 long count = mTunnelSetupFailureCounts.get(apn); 594 mTunnelSetupFailureCounts.put(apn, ++count); 595 return; 596 } 597 598 // Unsolicited tunnel down as tunnel has to be in BRINGDOWN if 599 // there is a deactivateDataCall() associated with this. 600 if (tunnelState.getState() == TunnelState.TUNNEL_UP) { 601 if (!mUnsolTunnelDownCounts.containsKey(apn)) { 602 mUnsolTunnelDownCounts.put(apn, 0L); 603 } 604 long count = mUnsolTunnelDownCounts.get(apn); 605 mUnsolTunnelDownCounts.put(apn, ++count); 606 } 607 Date currentTime = tunnelState.getCurrentTime(); 608 Date upTime = tunnelState.getUpStateTime(); 609 if (upTime != null) { 610 if (!mTunnelUpStats.containsKey(apn)) { 611 mTunnelUpStats.put(apn, new LongSummaryStatistics()); 612 } 613 LongSummaryStatistics stats = mTunnelUpStats.get(apn); 614 stats.accept(currentTime.getTime() - upTime.getTime()); 615 mTunnelUpStats.put(apn, stats); 616 } 617 } 618 maxApnReached()619 boolean maxApnReached() { 620 int APN_COUNT_MAX = 10; 621 return mTunnelSetupSuccessStats.size() >= APN_COUNT_MAX 622 || mTunnelSetupFailureCounts.size() >= APN_COUNT_MAX 623 || mUnsolTunnelDownCounts.size() >= APN_COUNT_MAX 624 || mTunnelUpStats.size() >= APN_COUNT_MAX; 625 } 626 627 @Override toString()628 public String toString() { 629 StringBuilder sb = new StringBuilder(); 630 sb.append("IwlanDataTunnelStats:"); 631 sb.append("\n\tmStartTime: ").append(mStartTime); 632 sb.append("\n\ttunnelSetupSuccessStats:"); 633 for (Map.Entry<String, LongSummaryStatistics> entry : 634 mTunnelSetupSuccessStats.entrySet()) { 635 sb.append("\n\t Apn: ").append(entry.getKey()); 636 sb.append("\n\t ").append(entry.getValue()); 637 } 638 sb.append("\n\ttunnelUpStats:"); 639 for (Map.Entry<String, LongSummaryStatistics> entry : mTunnelUpStats.entrySet()) { 640 sb.append("\n\t Apn: ").append(entry.getKey()); 641 sb.append("\n\t ").append(entry.getValue()); 642 } 643 644 sb.append("\n\ttunnelSetupFailureCounts: "); 645 for (Map.Entry<String, Long> entry : mTunnelSetupFailureCounts.entrySet()) { 646 sb.append("\n\t Apn: ").append(entry.getKey()); 647 sb.append("\n\t counts: ").append(entry.getValue()); 648 } 649 sb.append("\n\tunsolTunnelDownCounts: "); 650 for (Map.Entry<String, Long> entry : mTunnelSetupFailureCounts.entrySet()) { 651 sb.append("\n\t Apn: ").append(entry.getKey()); 652 sb.append("\n\t counts: ").append(entry.getValue()); 653 } 654 sb.append("\n\tendTime: ").append(mCalendar.getTime()); 655 return sb.toString(); 656 } 657 reset()658 private void reset() { 659 mStartTime = mCalendar.getTime(); 660 mTunnelSetupSuccessStats = new HashMap<String, LongSummaryStatistics>(); 661 mTunnelUpStats = new HashMap<String, LongSummaryStatistics>(); 662 mTunnelSetupFailureCounts = new HashMap<String, Long>(); 663 mUnsolTunnelDownCounts = new HashMap<String, Long>(); 664 statCount = 0L; 665 } 666 } 667 668 /** 669 * Constructor 670 * 671 * @param slotIndex SIM slot index the data service provider associated with. 672 */ IwlanDataServiceProvider(int slotIndex, IwlanDataService iwlanDataService)673 public IwlanDataServiceProvider(int slotIndex, IwlanDataService iwlanDataService) { 674 super(slotIndex); 675 SUB_TAG = TAG + "[" + slotIndex + "]"; 676 677 // TODO: 678 // get reference carrier config for this sub 679 // get reference to resolver 680 mIwlanDataService = iwlanDataService; 681 mIwlanTunnelCallback = new IwlanTunnelCallback(this); 682 mIwlanTunnelMetrics = new IwlanTunnelMetricsImpl(this, getIwlanDataServiceHandler()); 683 mEpdgSelector = EpdgSelector.getSelectorInstance(mContext, slotIndex); 684 mCalendar = Calendar.getInstance(); 685 mTunnelStats = new IwlanDataTunnelStats(); 686 687 // Register IwlanEventListener 688 List<Integer> events = new ArrayList<Integer>(); 689 events.add(IwlanEventListener.CARRIER_CONFIG_CHANGED_EVENT); 690 events.add(IwlanEventListener.CARRIER_CONFIG_UNKNOWN_CARRIER_EVENT); 691 events.add(IwlanEventListener.WIFI_CALLING_ENABLE_EVENT); 692 events.add(IwlanEventListener.WIFI_CALLING_DISABLE_EVENT); 693 events.add(IwlanEventListener.CROSS_SIM_CALLING_ENABLE_EVENT); 694 events.add(IwlanEventListener.CELLINFO_CHANGED_EVENT); 695 events.add(IwlanEventListener.CALL_STATE_CHANGED_EVENT); 696 events.add(IwlanEventListener.PREFERRED_NETWORK_TYPE_CHANGED_EVENT); 697 IwlanEventListener.getInstance(mContext, slotIndex) 698 .addEventListener(events, getIwlanDataServiceHandler()); 699 } 700 getTunnelManager()701 private EpdgTunnelManager getTunnelManager() { 702 return EpdgTunnelManager.getInstance(mContext, getSlotIndex()); 703 } 704 705 // creates a DataCallResponse for an apn irrespective of state apnTunnelStateToDataCallResponse(String apn)706 private DataCallResponse apnTunnelStateToDataCallResponse(String apn) { 707 TunnelState tunnelState = mTunnelStateForApn.get(apn); 708 if (tunnelState == null) { 709 return null; 710 } 711 712 DataCallResponse.Builder responseBuilder = new DataCallResponse.Builder(); 713 int state = tunnelState.getState(); 714 TunnelLinkProperties tunnelLinkProperties = tunnelState.getTunnelLinkProperties(); 715 if (tunnelLinkProperties == null) { 716 Log.d(TAG, "PDN with empty linkProperties. TunnelState : " + state); 717 return responseBuilder.build(); 718 } 719 responseBuilder 720 .setId(apn.hashCode()) 721 .setProtocolType(tunnelLinkProperties.getProtocolType()) 722 .setCause(DataFailCause.NONE) 723 .setLinkStatus( 724 state == TunnelState.TUNNEL_UP 725 ? DataCallResponse.LINK_STATUS_ACTIVE 726 : DataCallResponse.LINK_STATUS_INACTIVE); 727 728 // fill wildcard address for gatewayList (used by DataConnection to add routes) 729 List<InetAddress> gatewayList = new ArrayList<>(); 730 List<LinkAddress> linkAddrList = tunnelLinkProperties.internalAddresses(); 731 if (linkAddrList.stream().anyMatch(LinkAddress::isIpv4)) { 732 try { 733 gatewayList.add(Inet4Address.getByName("0.0.0.0")); 734 } catch (UnknownHostException e) { 735 // should never happen for static string 0.0.0.0 736 } 737 } 738 if (linkAddrList.stream().anyMatch(LinkAddress::isIpv6)) { 739 try { 740 gatewayList.add(Inet6Address.getByName("::")); 741 } catch (UnknownHostException e) { 742 // should never happen for static string :: 743 } 744 } 745 746 if (tunnelLinkProperties.sliceInfo().isPresent()) { 747 responseBuilder.setSliceInfo(tunnelLinkProperties.sliceInfo().get()); 748 } 749 750 return responseBuilder 751 .setAddresses(linkAddrList) 752 .setDnsAddresses(tunnelLinkProperties.dnsAddresses()) 753 .setPcscfAddresses(tunnelLinkProperties.pcscfAddresses()) 754 .setInterfaceName(tunnelLinkProperties.ifaceName()) 755 .setGatewayAddresses(gatewayList) 756 .setMtuV4(tunnelState.getLinkMtu()) 757 .setMtuV6(tunnelState.getLinkMtu()) 758 .setPduSessionId(tunnelState.getPduSessionId()) 759 .setNetworkValidationStatus(tunnelState.getNetworkValidationStatus()) 760 .build(); // underlying n/w is same 761 } 762 getCallList()763 private List<DataCallResponse> getCallList() { 764 List<DataCallResponse> dcList = new ArrayList<>(); 765 for (String key : mTunnelStateForApn.keySet()) { 766 DataCallResponse dcRsp = apnTunnelStateToDataCallResponse(key); 767 if (dcRsp != null) { 768 Log.d(SUB_TAG, "Apn: " + key + "Link state: " + dcRsp.getLinkStatus()); 769 dcList.add(dcRsp); 770 } 771 } 772 return dcList; 773 } 774 deliverCallback( int callbackType, int result, DataServiceCallback callback, DataCallResponse rsp)775 private void deliverCallback( 776 int callbackType, int result, DataServiceCallback callback, DataCallResponse rsp) { 777 if (callback == null) { 778 Log.d(SUB_TAG, "deliverCallback: callback is null. callbackType:" + callbackType); 779 return; 780 } 781 Log.d( 782 SUB_TAG, 783 "Delivering callbackType:" 784 + callbackType 785 + " result:" 786 + result 787 + " rsp:" 788 + rsp); 789 switch (callbackType) { 790 case CALLBACK_TYPE_DEACTIVATE_DATACALL_COMPLETE: 791 callback.onDeactivateDataCallComplete(result); 792 // always update current datacalllist 793 notifyDataCallListChanged(getCallList()); 794 break; 795 796 case CALLBACK_TYPE_SETUP_DATACALL_COMPLETE: 797 if (result == DataServiceCallback.RESULT_SUCCESS && rsp == null) { 798 Log.d(SUB_TAG, "Warning: null rsp for success case"); 799 } 800 callback.onSetupDataCallComplete(result, rsp); 801 // always update current datacalllist 802 notifyDataCallListChanged(getCallList()); 803 break; 804 805 case CALLBACK_TYPE_GET_DATACALL_LIST_COMPLETE: 806 callback.onRequestDataCallListComplete(result, getCallList()); 807 // TODO: add code for the rest of the cases 808 } 809 } 810 811 /** 812 * Setup a data connection. 813 * 814 * @param accessNetworkType Access network type that the data call will be established on. 815 * Must be one of {@link android.telephony.AccessNetworkConstants.AccessNetworkType}. 816 * @param dataProfile Data profile used for data call setup. See {@link DataProfile} 817 * @param isRoaming True if the device is data roaming. 818 * @param allowRoaming True if data roaming is allowed by the user. 819 * @param reason The reason for data setup. Must be {@link #REQUEST_REASON_NORMAL} or {@link 820 * #REQUEST_REASON_HANDOVER}. 821 * @param linkProperties If {@code reason} is {@link #REQUEST_REASON_HANDOVER}, this is the 822 * link properties of the existing data connection, otherwise null. 823 * @param pduSessionId The pdu session id to be used for this data call. The standard range 824 * of values are 1-15 while 0 means no pdu session id was attached to this call. 825 * Reference: 3GPP TS 24.007 section 11.2.3.1b. 826 * @param sliceInfo The slice info related to this data call. 827 * @param trafficDescriptor TrafficDescriptor for which data connection needs to be 828 * established. It is used for URSP traffic matching as described in 3GPP TS 24.526 829 * Section 4.2.2. It includes an optional DNN which, if present, must be used for 830 * traffic matching; it does not specify the end point to be used for the data call. 831 * @param matchAllRuleAllowed Indicates if using default match-all URSP rule for this 832 * request is allowed. If false, this request must not use the match-all URSP rule and 833 * if a non-match-all rule is not found (or if URSP rules are not available) then {@link 834 * DataCallResponse#getCause()} is {@link 835 * android.telephony.DataFailCause#MATCH_ALL_RULE_NOT_ALLOWED}. This is needed as some 836 * requests need to have a hard failure if the intention cannot be met, for example, a 837 * zero-rating slice. 838 * @param callback The result callback for this request. 839 */ 840 @Override setupDataCall( int accessNetworkType, @NonNull DataProfile dataProfile, boolean isRoaming, boolean allowRoaming, @SetupDataReason int reason, @Nullable LinkProperties linkProperties, @IntRange(from = 0, to = 15) int pduSessionId, @Nullable NetworkSliceInfo sliceInfo, @Nullable TrafficDescriptor trafficDescriptor, boolean matchAllRuleAllowed, @NonNull DataServiceCallback callback)841 public void setupDataCall( 842 int accessNetworkType, 843 @NonNull DataProfile dataProfile, 844 boolean isRoaming, 845 boolean allowRoaming, 846 @SetupDataReason int reason, 847 @Nullable LinkProperties linkProperties, 848 @IntRange(from = 0, to = 15) int pduSessionId, 849 @Nullable NetworkSliceInfo sliceInfo, 850 @Nullable TrafficDescriptor trafficDescriptor, 851 boolean matchAllRuleAllowed, 852 @NonNull DataServiceCallback callback) { 853 854 mProcessingStartTime = System.currentTimeMillis(); 855 Log.d( 856 SUB_TAG, 857 "Setup data call with network: " 858 + accessNetworkType 859 + ", reason: " 860 + requestReasonToString(reason) 861 + ", pduSessionId: " 862 + pduSessionId 863 + ", DataProfile: " 864 + dataProfile 865 + ", isRoaming:" 866 + isRoaming 867 + ", allowRoaming: " 868 + allowRoaming 869 + ", linkProperties: " 870 + linkProperties); 871 872 SetupDataCallData setupDataCallData = 873 new SetupDataCallData( 874 accessNetworkType, 875 dataProfile, 876 isRoaming, 877 allowRoaming, 878 reason, 879 linkProperties, 880 pduSessionId, 881 sliceInfo, 882 trafficDescriptor, 883 matchAllRuleAllowed, 884 callback, 885 this); 886 887 int networkTransport = -1; 888 if (sDefaultDataTransport == Transport.MOBILE) { 889 networkTransport = TRANSPORT_CELLULAR; 890 } else if (sDefaultDataTransport == Transport.WIFI) { 891 networkTransport = TRANSPORT_WIFI; 892 } 893 894 if (dataProfile != null) { 895 ApnSetting apnSetting = dataProfile.getApnSetting(); 896 this.setMetricsAtom( 897 // ApnName 898 apnSetting != null ? apnSetting.getApnName() : "", 899 // ApnType 900 apnSetting != null ? apnSetting.getApnTypeBitmask() : ApnSetting.TYPE_NONE, 901 // IsHandover 902 (reason == DataService.REQUEST_REASON_HANDOVER), 903 // Source Rat 904 getCurrentCellularRat(), 905 // IsRoaming 906 isRoaming, 907 // Is Network Connected 908 sNetworkConnected, 909 // Transport Type 910 networkTransport); 911 } 912 913 getIwlanDataServiceHandler() 914 .sendMessage( 915 getIwlanDataServiceHandler() 916 .obtainMessage(EVENT_SETUP_DATA_CALL, setupDataCallData)); 917 } 918 919 /** 920 * Deactivate a data connection. The data service provider must implement this method to 921 * support data connection tear down. When completed or error, the service must invoke the 922 * provided callback to notify the platform. 923 * 924 * <p>Note: For handovers, in compliance with 3GPP specs (TS 23.402 clause 8.6.1, TS 23.502 925 * clause 4.11.4.1), a {@link KEY_HANDOVER_TO_WWAN_RELEASE_DELAY_SECOND_INT} delay is 926 * implemented to allow the network to release the IKE tunnel. If the network fails to 927 * release it within this timeframe, the UE will take over the release process. 928 * 929 * @param cid Call id returned in the callback of {@link 930 * DataServiceProvider#setupDataCall(int, DataProfile, boolean, boolean, int, 931 * LinkProperties, DataServiceCallback)}. 932 * @param reason The reason for data deactivation. Must be {@link #REQUEST_REASON_NORMAL}, 933 * {@link #REQUEST_REASON_SHUTDOWN} or {@link #REQUEST_REASON_HANDOVER}. 934 * @param callback The result callback for this request. Null if the client does not care 935 */ 936 @Override deactivateDataCall( int cid, @DeactivateDataReason int reason, DataServiceCallback callback)937 public void deactivateDataCall( 938 int cid, @DeactivateDataReason int reason, DataServiceCallback callback) { 939 Log.d( 940 SUB_TAG, 941 "Deactivate data call with reason: " 942 + requestReasonToString(reason) 943 + ", cid: " 944 + cid 945 + ", callback: " 946 + callback); 947 948 boolean isRequestForHandoverToWWAN = (reason == REQUEST_REASON_HANDOVER); 949 950 int delayTimeSeconds = 0; 951 if (isRequestForHandoverToWWAN) { 952 delayTimeSeconds = 953 IwlanCarrierConfig.getConfigInt( 954 mContext, 955 getSlotIndex(), 956 IwlanCarrierConfig.KEY_HANDOVER_TO_WWAN_RELEASE_DELAY_SECOND_INT); 957 } 958 959 int event = 960 (delayTimeSeconds > 0) 961 ? EVENT_DEACTIVATE_DATA_CALL_WITH_DELAY 962 : EVENT_DEACTIVATE_DATA_CALL; 963 964 DeactivateDataCallData deactivateDataCallData = 965 new DeactivateDataCallData(cid, reason, callback, this, delayTimeSeconds); 966 967 getIwlanDataServiceHandler() 968 .obtainMessage(event, deactivateDataCallData) 969 .sendToTarget(); 970 } 971 972 /** 973 * Requests validation check to see if the network is working properly for a given data 974 * call. 975 * 976 * <p>This request is completed immediately after submitting the request to the data service 977 * provider and receiving {@link DataServiceCallback.ResultCode}, and progress status or 978 * validation results are notified through {@link 979 * DataCallResponse#getNetworkValidationStatus}. 980 * 981 * <p>If the network validation request is submitted successfully, {@link 982 * DataServiceCallback#RESULT_SUCCESS} is passed to {@code resultCodeCallback}. If the 983 * network validation feature is not supported by the data service provider itself, {@link 984 * DataServiceCallback#RESULT_ERROR_UNSUPPORTED} is passed to {@code resultCodeCallback}. 985 * See {@link DataServiceCallback.ResultCode} for the type of response that indicates 986 * whether the request was successfully submitted or had an error. 987 * 988 * <p>In response to this network validation request, providers can validate the data call 989 * in their own way. For example, in IWLAN, the DPD (Dead Peer Detection) can be used as a 990 * tool to check whether a data call is alive. 991 * 992 * @param cid The identifier of the data call which is provided in {@link DataCallResponse} 993 * @param executor The callback executor for the response. 994 * @param resultCodeCallback Listener for the {@link DataServiceCallback.ResultCode} that 995 * request validation to the DataService and checks if the request has been submitted. 996 */ 997 @Override requestNetworkValidation( int cid, Executor executor, Consumer<Integer> resultCodeCallback)998 public void requestNetworkValidation( 999 int cid, Executor executor, Consumer<Integer> resultCodeCallback) { 1000 Objects.requireNonNull(executor, "executor cannot be null"); 1001 Objects.requireNonNull(resultCodeCallback, "resultCodeCallback cannot be null"); 1002 Log.d(TAG, "request Network Validation: " + cid); 1003 1004 getIwlanDataServiceHandler() 1005 .obtainMessage( 1006 EVENT_REQUEST_NETWORK_VALIDATION, 1007 new NetworkValidationInfo(cid, executor, resultCodeCallback, this)) 1008 .sendToTarget(); 1009 } 1010 forceCloseTunnelsInDeactivatingState()1011 public void forceCloseTunnelsInDeactivatingState() { 1012 for (Map.Entry<String, TunnelState> entry : mTunnelStateForApn.entrySet()) { 1013 TunnelState tunnelState = entry.getValue(); 1014 if (tunnelState.getState() == TunnelState.TUNNEL_IN_BRINGDOWN) { 1015 getTunnelManager() 1016 .closeTunnel( 1017 entry.getKey(), 1018 true /* forceClose */, 1019 getIwlanTunnelCallback(), 1020 getIwlanTunnelMetrics(), 1021 BRINGDOWN_REASON_IN_DEACTIVATING_STATE); 1022 } 1023 } 1024 } 1025 1026 /** 1027 * Closes all tunnels forcefully for a specified reason. 1028 * 1029 * @param reason The reason for closing the tunnel. Must be {@link 1030 * EpdgTunnelManager.TunnelBringDownReason}. 1031 */ forceCloseTunnels(@pdgTunnelManager.TunnelBringDownReason int reason)1032 void forceCloseTunnels(@EpdgTunnelManager.TunnelBringDownReason int reason) { 1033 for (Map.Entry<String, TunnelState> entry : mTunnelStateForApn.entrySet()) { 1034 getTunnelManager() 1035 .closeTunnel( 1036 entry.getKey(), 1037 true /* forceClose */, 1038 getIwlanTunnelCallback(), 1039 getIwlanTunnelMetrics(), 1040 reason); 1041 } 1042 } 1043 1044 /** 1045 * Get the active data call list. 1046 * 1047 * @param callback The result callback for this request. 1048 */ 1049 @Override requestDataCallList(DataServiceCallback callback)1050 public void requestDataCallList(DataServiceCallback callback) { 1051 getIwlanDataServiceHandler() 1052 .sendMessage( 1053 getIwlanDataServiceHandler() 1054 .obtainMessage( 1055 EVENT_DATA_CALL_LIST_REQUEST, 1056 new DataCallRequestData( 1057 callback, IwlanDataServiceProvider.this))); 1058 } 1059 1060 @VisibleForTesting setTunnelState( DataProfile dataProfile, DataServiceCallback callback, int tunnelStatus, TunnelLinkProperties linkProperties, boolean isHandover, int pduSessionId, boolean isImsOrEmergency, boolean isDataCallSetupWithN1)1061 protected void setTunnelState( 1062 DataProfile dataProfile, 1063 DataServiceCallback callback, 1064 int tunnelStatus, 1065 TunnelLinkProperties linkProperties, 1066 boolean isHandover, 1067 int pduSessionId, 1068 boolean isImsOrEmergency, 1069 boolean isDataCallSetupWithN1) { 1070 TunnelState tunnelState = new TunnelState(callback); 1071 tunnelState.setState(tunnelStatus); 1072 tunnelState.setProtocolType(dataProfile.getApnSetting().getProtocol()); 1073 tunnelState.setTunnelLinkProperties(linkProperties); 1074 tunnelState.setIsHandover(isHandover); 1075 tunnelState.setPduSessionId(pduSessionId); 1076 tunnelState.setIsImsOrEmergency(isImsOrEmergency); 1077 tunnelState.setIsDataCallWithN1(isDataCallSetupWithN1); 1078 mTunnelStateForApn.put(dataProfile.getApnSetting().getApnName(), tunnelState); 1079 tunnelState.setApnTypeBitmask(dataProfile.getApnSetting().getApnTypeBitmask()); 1080 } 1081 1082 @VisibleForTesting setMetricsAtom( String apnName, int apnType, boolean isHandover, int sourceRat, boolean isRoaming, boolean isNetworkConnected, int transportType)1083 void setMetricsAtom( 1084 String apnName, 1085 int apnType, 1086 boolean isHandover, 1087 int sourceRat, 1088 boolean isRoaming, 1089 boolean isNetworkConnected, 1090 int transportType) { 1091 MetricsAtom metricsAtom = new MetricsAtom(); 1092 metricsAtom.setApnType(apnType); 1093 metricsAtom.setIsHandover(isHandover); 1094 metricsAtom.setSourceRat(sourceRat); 1095 metricsAtom.setIsCellularRoaming(isRoaming); 1096 metricsAtom.setIsNetworkConnected(isNetworkConnected); 1097 metricsAtom.setTransportType(transportType); 1098 mMetricsAtomForApn.put(apnName, metricsAtom); 1099 } 1100 1101 @VisibleForTesting 1102 @Nullable getMetricsAtomByApn(String apnName)1103 public MetricsAtom getMetricsAtomByApn(String apnName) { 1104 return mMetricsAtomForApn.get(apnName); 1105 } 1106 1107 @VisibleForTesting getIwlanTunnelCallback()1108 public IwlanTunnelCallback getIwlanTunnelCallback() { 1109 return mIwlanTunnelCallback; 1110 } 1111 1112 @VisibleForTesting getIwlanTunnelMetrics()1113 public IwlanTunnelMetricsImpl getIwlanTunnelMetrics() { 1114 return mIwlanTunnelMetrics; 1115 } 1116 1117 @VisibleForTesting getTunnelStats()1118 IwlanDataTunnelStats getTunnelStats() { 1119 return mTunnelStats; 1120 } 1121 updateNetwork( @ullable Network network, @Nullable LinkProperties linkProperties)1122 private void updateNetwork( 1123 @Nullable Network network, @Nullable LinkProperties linkProperties) { 1124 if (isNetworkConnected( 1125 isActiveDataOnOtherSub(getSlotIndex()), 1126 IwlanHelper.isCrossSimCallingEnabled(mContext, getSlotIndex()))) { 1127 getTunnelManager().updateNetwork(network, linkProperties); 1128 } 1129 1130 if (Objects.equals(network, sNetwork)) { 1131 return; 1132 } 1133 for (Map.Entry<String, TunnelState> entry : mTunnelStateForApn.entrySet()) { 1134 TunnelState tunnelState = entry.getValue(); 1135 if (tunnelState.getState() == TunnelState.TUNNEL_IN_BRINGUP) { 1136 // force close tunnels in bringup since IKE lib only supports 1137 // updating network for tunnels that are already up. 1138 // This may not result in actual closing of Ike Session since 1139 // epdg selection may not be complete yet. 1140 tunnelState.setState(TunnelState.TUNNEL_IN_FORCE_CLEAN_WAS_IN_BRINGUP); 1141 getTunnelManager() 1142 .closeTunnel( 1143 entry.getKey(), 1144 true /* forceClose */, 1145 getIwlanTunnelCallback(), 1146 getIwlanTunnelMetrics(), 1147 BRINGDOWN_REASON_NETWORK_UPDATE_WHEN_TUNNEL_IN_BRINGUP); 1148 } 1149 } 1150 } 1151 isRegisteredCellInfoChanged(List<CellInfo> cellInfoList)1152 private boolean isRegisteredCellInfoChanged(List<CellInfo> cellInfoList) { 1153 for (CellInfo cellInfo : cellInfoList) { 1154 if (!cellInfo.isRegistered()) { 1155 continue; 1156 } 1157 1158 if (mCellInfo == null || mCellInfo != cellInfo) { 1159 mCellInfo = cellInfo; 1160 Log.d(TAG, " Update cached cellinfo"); 1161 return true; 1162 } 1163 } 1164 return false; 1165 } 1166 dnsPrefetchCheck()1167 private void dnsPrefetchCheck() { 1168 boolean networkConnected = 1169 isNetworkConnected( 1170 isActiveDataOnOtherSub(getSlotIndex()), 1171 IwlanHelper.isCrossSimCallingEnabled(mContext, getSlotIndex())); 1172 /* Check if we need to do prefecting */ 1173 if (networkConnected 1174 && mCarrierConfigReady 1175 && mWfcEnabled 1176 && mTunnelStateForApn.isEmpty()) { 1177 1178 // Get roaming status 1179 TelephonyManager telephonyManager = 1180 mContext.getSystemService(TelephonyManager.class); 1181 telephonyManager = 1182 telephonyManager.createForSubscriptionId( 1183 IwlanHelper.getSubId(mContext, getSlotIndex())); 1184 boolean isRoaming = telephonyManager.isNetworkRoaming(); 1185 Log.d(TAG, "Trigger EPDG prefetch. Roaming=" + isRoaming); 1186 1187 prefetchEpdgServerList(sNetwork, isRoaming); 1188 } 1189 } 1190 prefetchEpdgServerList(Network network, boolean isRoaming)1191 private void prefetchEpdgServerList(Network network, boolean isRoaming) { 1192 mEpdgSelector.getValidatedServerList( 1193 0, 1194 EpdgSelector.PROTO_FILTER_IPV4V6, 1195 EpdgSelector.SYSTEM_PREFERRED, 1196 isRoaming, 1197 false, 1198 network, 1199 null); 1200 mEpdgSelector.getValidatedServerList( 1201 0, 1202 EpdgSelector.PROTO_FILTER_IPV4V6, 1203 EpdgSelector.SYSTEM_PREFERRED, 1204 isRoaming, 1205 true, 1206 network, 1207 null); 1208 } 1209 getCurrentCellularRat()1210 private int getCurrentCellularRat() { 1211 TelephonyManager telephonyManager = mContext.getSystemService(TelephonyManager.class); 1212 telephonyManager = 1213 telephonyManager.createForSubscriptionId( 1214 IwlanHelper.getSubId(mContext, getSlotIndex())); 1215 List<CellInfo> cellInfoList = telephonyManager.getAllCellInfo(); 1216 if (cellInfoList == null) { 1217 Log.e(TAG, "cellInfoList is NULL"); 1218 return 0; 1219 } 1220 1221 for (CellInfo cellInfo : cellInfoList) { 1222 if (!cellInfo.isRegistered()) { 1223 continue; 1224 } 1225 if (cellInfo instanceof CellInfoGsm) { 1226 return TelephonyManager.NETWORK_TYPE_GSM; 1227 } else if (cellInfo instanceof CellInfoWcdma) { 1228 return TelephonyManager.NETWORK_TYPE_UMTS; 1229 } else if (cellInfo instanceof CellInfoLte) { 1230 return TelephonyManager.NETWORK_TYPE_LTE; 1231 } else if (cellInfo instanceof CellInfoNr) { 1232 return TelephonyManager.NETWORK_TYPE_NR; 1233 } 1234 } 1235 return TelephonyManager.NETWORK_TYPE_UNKNOWN; 1236 } 1237 1238 /* Determines if this subscription is in an active call */ isOnCall()1239 private boolean isOnCall() { 1240 return mCallState != TelephonyManager.CALL_STATE_IDLE; 1241 } 1242 1243 /** 1244 * IMS and Emergency are not allowed to retry with initial attach during call to keep call 1245 * continuity. Other APNs like XCAP and MMS are allowed to retry with initial attach 1246 * regardless of the call state. 1247 */ shouldRetryWithInitialAttachForHandoverRequest( String apn, TunnelState tunnelState)1248 private boolean shouldRetryWithInitialAttachForHandoverRequest( 1249 String apn, TunnelState tunnelState) { 1250 boolean isOnImsOrEmergencyCall = tunnelState.getIsImsOrEmergency() && isOnCall(); 1251 return tunnelState.getIsHandover() 1252 && !isOnImsOrEmergencyCall 1253 && ErrorPolicyManager.getInstance(mContext, getSlotIndex()) 1254 .shouldRetryWithInitialAttach(apn); 1255 } 1256 1257 /** 1258 * Called when the instance of data service is destroyed (e.g. got unbind or binder died) or 1259 * when the data service provider is removed. 1260 */ 1261 @Override close()1262 public void close() { 1263 // TODO: call epdgtunnelmanager.releaseInstance or equivalent 1264 mIwlanDataService.removeDataServiceProvider(this); 1265 IwlanEventListener iwlanEventListener = 1266 IwlanEventListener.getInstance(mContext, getSlotIndex()); 1267 iwlanEventListener.removeEventListener(getIwlanDataServiceHandler()); 1268 iwlanEventListener.unregisterContentObserver(); 1269 } 1270 dump(FileDescriptor fd, PrintWriter pw, String[] args)1271 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 1272 pw.println("---- IwlanDataServiceProvider[" + getSlotIndex() + "] ----"); 1273 boolean isDDS = IwlanHelper.isDefaultDataSlot(mContext, getSlotIndex()); 1274 boolean isCSTEnabled = IwlanHelper.isCrossSimCallingEnabled(mContext, getSlotIndex()); 1275 pw.println( 1276 "isDefaultDataSlot: " 1277 + isDDS 1278 + "subID: " 1279 + IwlanHelper.getSubId(mContext, getSlotIndex()) 1280 + " mConnectedDataSub: " 1281 + mConnectedDataSub 1282 + " isCrossSimEnabled: " 1283 + isCSTEnabled); 1284 pw.println( 1285 "isNetworkConnected: " 1286 + isNetworkConnected( 1287 isActiveDataOnOtherSub(getSlotIndex()), isCSTEnabled) 1288 + " Wfc enabled: " 1289 + mWfcEnabled); 1290 for (Map.Entry<String, TunnelState> entry : mTunnelStateForApn.entrySet()) { 1291 pw.println("Tunnel state for APN: " + entry.getKey()); 1292 pw.println(entry.getValue()); 1293 } 1294 pw.println(mTunnelStats); 1295 EpdgTunnelManager.getInstance(mContext, getSlotIndex()).dump(pw); 1296 ErrorPolicyManager.getInstance(mContext, getSlotIndex()).dump(pw); 1297 pw.println("-------------------------------------"); 1298 } 1299 1300 @VisibleForTesting setCalendar(Calendar c)1301 public void setCalendar(Calendar c) { 1302 mCalendar = c; 1303 } 1304 isPdnReestablishNeededOnIdleN1Update()1305 private boolean isPdnReestablishNeededOnIdleN1Update() { 1306 return isN1ModeSupported() && (needIncludeN1ModeCapability() != mIs5GEnabledOnUi); 1307 } 1308 disconnectPdnForN1ModeUpdate()1309 private void disconnectPdnForN1ModeUpdate() { 1310 if (hasActiveOrInitiatingDataCall()) { 1311 Log.d(TAG, "Disconnect PDNs for N1 mode update"); 1312 forceCloseTunnels( 1313 mIs5GEnabledOnUi 1314 ? EpdgTunnelManager.BRINGDOWN_REASON_ENABLE_N1_MODE 1315 : EpdgTunnelManager.BRINGDOWN_REASON_DISABLE_N1_MODE); 1316 } 1317 } 1318 hasActiveOrInitiatingDataCall()1319 private boolean hasActiveOrInitiatingDataCall() { 1320 return mTunnelStateForApn.values().stream() 1321 .anyMatch( 1322 tunnelState -> 1323 tunnelState.getState() == TunnelState.TUNNEL_UP 1324 || tunnelState.getState() 1325 == TunnelState.TUNNEL_IN_BRINGUP); 1326 } 1327 1328 // TODO(b/309867756): Include N1_MODE_CAPABILITY inclusion status in metrics. needIncludeN1ModeCapability()1329 private boolean needIncludeN1ModeCapability() { 1330 if (!IwlanCarrierConfig.getConfigBoolean( 1331 mContext, 1332 getSlotIndex(), 1333 IwlanCarrierConfig.KEY_UPDATE_N1_MODE_ON_UI_CHANGE_BOOL)) { 1334 return isN1ModeSupported(); 1335 } 1336 if (!isN1ModeSupported()) { 1337 return false; 1338 } 1339 // Maintain uniform N1_MODE_CAPABILITY Notify inclusion for all PDNs. 1340 // Initiate PDN with current N1 inclusion in tunnel_up or tunnel_in_bringup states; 1341 // otherwise, use UI settings. 1342 return hasActiveOrInitiatingDataCall() ? isDataCallSetupWithN1() : mIs5GEnabledOnUi; 1343 } 1344 isDataCallSetupWithN1()1345 private boolean isDataCallSetupWithN1() { 1346 return mTunnelStateForApn.values().stream().anyMatch(TunnelState::getIsDataCallWithN1); 1347 } 1348 isN1ModeSupported()1349 protected boolean isN1ModeSupported() { 1350 int[] nrAvailabilities = 1351 IwlanCarrierConfig.getConfigIntArray( 1352 mContext, 1353 getSlotIndex(), 1354 CarrierConfigManager.KEY_CARRIER_NR_AVAILABILITIES_INT_ARRAY); 1355 Log.d( 1356 TAG, 1357 "KEY_CARRIER_NR_AVAILABILITIES_INT_ARRAY : " 1358 + Arrays.toString(nrAvailabilities)); 1359 return Arrays.stream(nrAvailabilities) 1360 .anyMatch(k -> k == CarrierConfigManager.CARRIER_NR_AVAILABILITY_SA); 1361 } 1362 } 1363 1364 private final class IwlanDataServiceHandler extends Handler { 1365 private final String TAG = IwlanDataServiceHandler.class.getSimpleName(); 1366 1367 @Override handleMessage(Message msg)1368 public void handleMessage(Message msg) { 1369 Log.d(TAG, "msg.what = " + eventToString(msg.what)); 1370 1371 String apnName; 1372 IwlanDataServiceProvider iwlanDataServiceProvider; 1373 IwlanDataServiceProvider.TunnelState tunnelState; 1374 DataServiceCallback callback; 1375 int reason; 1376 int slotId; 1377 int retryTimeMillis; 1378 int errorCause; 1379 MetricsAtom metricsAtom; 1380 1381 switch (msg.what) { 1382 case EVENT_TUNNEL_OPENED: 1383 TunnelOpenedData tunnelOpenedData = (TunnelOpenedData) msg.obj; 1384 iwlanDataServiceProvider = tunnelOpenedData.mIwlanDataServiceProvider; 1385 apnName = tunnelOpenedData.mApnName; 1386 TunnelLinkProperties tunnelLinkProperties = 1387 tunnelOpenedData.mTunnelLinkProperties; 1388 1389 tunnelState = iwlanDataServiceProvider.mTunnelStateForApn.get(apnName); 1390 // tunnelstate should not be null, design violation. 1391 // if its null, we should crash and debug. 1392 tunnelState.setTunnelLinkProperties(tunnelLinkProperties); 1393 tunnelState.setState(IwlanDataServiceProvider.TunnelState.TUNNEL_UP); 1394 iwlanDataServiceProvider.mTunnelStats.reportTunnelSetupSuccess( 1395 apnName, tunnelState); 1396 1397 iwlanDataServiceProvider.deliverCallback( 1398 IwlanDataServiceProvider.CALLBACK_TYPE_SETUP_DATACALL_COMPLETE, 1399 DataServiceCallback.RESULT_SUCCESS, 1400 tunnelState.getDataServiceCallback(), 1401 iwlanDataServiceProvider.apnTunnelStateToDataCallResponse(apnName)); 1402 break; 1403 1404 case EVENT_TUNNEL_CLOSED: 1405 TunnelClosedData tunnelClosedData = (TunnelClosedData) msg.obj; 1406 iwlanDataServiceProvider = tunnelClosedData.mIwlanDataServiceProvider; 1407 apnName = tunnelClosedData.mApnName; 1408 IwlanError iwlanError = tunnelClosedData.mIwlanError; 1409 1410 tunnelState = iwlanDataServiceProvider.mTunnelStateForApn.get(apnName); 1411 1412 if (tunnelState == null) { 1413 // On a successful handover to EUTRAN, the NW may initiate an IKE DEL before 1414 // the UE initiates a deactivateDataCall(). There may be a race condition 1415 // where the deactivateDataCall() arrives immediately before 1416 // IwlanDataService receives EVENT_TUNNEL_CLOSED (and clears TunnelState). 1417 // Even though there is no tunnel, EpdgTunnelManager will still process the 1418 // bringdown request and send back an onClosed() to ensure state coherence. 1419 if (iwlanError.getErrorType() != IwlanError.TUNNEL_NOT_FOUND) { 1420 Log.w( 1421 TAG, 1422 "Tunnel state does not exist! Unexpected IwlanError: " 1423 + iwlanError); 1424 } 1425 break; 1426 } 1427 1428 if (tunnelState.hasPendingDeactivateDataCallData()) { 1429 // Iwlan delays handling EVENT_DEACTIVATE_DATA_CALL to give the network time 1430 // to release the PDN. This allows for immediate response to Telephony if 1431 // the network releases the PDN before timeout. Otherwise, Telephony's PDN 1432 // state waits for Iwlan, blocking further actions on this PDN. 1433 cancelPendingDeactivationIfExists( 1434 tunnelState.getPendingDeactivateDataCallData()); 1435 } 1436 1437 iwlanDataServiceProvider.mTunnelStats.reportTunnelDown(apnName, tunnelState); 1438 iwlanDataServiceProvider.mTunnelStateForApn.remove(apnName); 1439 metricsAtom = iwlanDataServiceProvider.mMetricsAtomForApn.get(apnName); 1440 1441 if (tunnelState.getState() 1442 == IwlanDataServiceProvider.TunnelState.TUNNEL_IN_BRINGUP 1443 || tunnelState.getState() 1444 == IwlanDataServiceProvider.TunnelState 1445 .TUNNEL_IN_FORCE_CLEAN_WAS_IN_BRINGUP) { 1446 DataCallResponse.Builder respBuilder = new DataCallResponse.Builder(); 1447 respBuilder 1448 .setId(apnName.hashCode()) 1449 .setProtocolType(tunnelState.getRequestedProtocolType()); 1450 1451 if (iwlanDataServiceProvider.shouldRetryWithInitialAttachForHandoverRequest( 1452 apnName, tunnelState)) { 1453 respBuilder.setHandoverFailureMode( 1454 DataCallResponse 1455 .HANDOVER_FAILURE_MODE_NO_FALLBACK_RETRY_SETUP_NORMAL); 1456 metricsAtom.setHandoverFailureMode( 1457 DataCallResponse 1458 .HANDOVER_FAILURE_MODE_NO_FALLBACK_RETRY_SETUP_NORMAL); 1459 } else if (tunnelState.getIsHandover()) { 1460 respBuilder.setHandoverFailureMode( 1461 DataCallResponse 1462 .HANDOVER_FAILURE_MODE_NO_FALLBACK_RETRY_HANDOVER); 1463 metricsAtom.setHandoverFailureMode( 1464 DataCallResponse 1465 .HANDOVER_FAILURE_MODE_NO_FALLBACK_RETRY_HANDOVER); 1466 } 1467 1468 errorCause = 1469 ErrorPolicyManager.getInstance( 1470 mContext, iwlanDataServiceProvider.getSlotIndex()) 1471 .getDataFailCause(apnName); 1472 if (errorCause != DataFailCause.NONE) { 1473 respBuilder.setCause(errorCause); 1474 metricsAtom.setDataCallFailCause(errorCause); 1475 1476 retryTimeMillis = 1477 (int) 1478 ErrorPolicyManager.getInstance( 1479 mContext, 1480 iwlanDataServiceProvider.getSlotIndex()) 1481 .getRemainingRetryTimeMs(apnName); 1482 // TODO(b/343962773): Need to refactor into ErrorPolicyManager 1483 if (!tunnelState.getIsHandover() 1484 && tunnelState.hasApnType(ApnSetting.TYPE_EMERGENCY)) { 1485 retryTimeMillis = DataCallResponse.RETRY_DURATION_UNDEFINED; 1486 } 1487 respBuilder.setRetryDurationMillis(retryTimeMillis); 1488 metricsAtom.setRetryDurationMillis(retryTimeMillis); 1489 } else { 1490 // TODO(b/265215349): Use a different DataFailCause for scenario where 1491 // tunnel in bringup is closed or force-closed without error. 1492 respBuilder.setCause(DataFailCause.IWLAN_NETWORK_FAILURE); 1493 metricsAtom.setDataCallFailCause(DataFailCause.IWLAN_NETWORK_FAILURE); 1494 respBuilder.setRetryDurationMillis(5000); 1495 metricsAtom.setRetryDurationMillis(5000); 1496 } 1497 1498 // Record setup result for the Metrics 1499 metricsAtom.setSetupRequestResult(DataServiceCallback.RESULT_SUCCESS); 1500 metricsAtom.setIwlanError(iwlanError.getErrorType()); 1501 metricsAtom.setIwlanErrorWrappedClassnameAndStack(iwlanError); 1502 metricsAtom.setMessageId( 1503 IwlanStatsLog.IWLAN_SETUP_DATA_CALL_RESULT_REPORTED); 1504 metricsAtom.setErrorCountOfSameCause( 1505 ErrorPolicyManager.getInstance( 1506 mContext, iwlanDataServiceProvider.getSlotIndex()) 1507 .getLastErrorCountOfSameCause(apnName)); 1508 1509 iwlanDataServiceProvider.deliverCallback( 1510 IwlanDataServiceProvider.CALLBACK_TYPE_SETUP_DATACALL_COMPLETE, 1511 DataServiceCallback.RESULT_SUCCESS, 1512 tunnelState.getDataServiceCallback(), 1513 respBuilder.build()); 1514 return; 1515 } 1516 1517 // iwlan service triggered teardown 1518 if (tunnelState.getState() 1519 == IwlanDataServiceProvider.TunnelState.TUNNEL_IN_BRINGDOWN) { 1520 1521 // IO exception happens when IKE library fails to retransmit requests. 1522 // This can happen for multiple reasons: 1523 // 1. Network disconnection due to wifi off. 1524 // 2. Epdg server does not respond. 1525 // 3. Socket send/receive fails. 1526 // Ignore this during tunnel bring down. 1527 if (iwlanError.getErrorType() != IwlanError.NO_ERROR 1528 && iwlanError.getErrorType() 1529 != IwlanError.IKE_INTERNAL_IO_EXCEPTION) { 1530 Log.e(TAG, "Unexpected error during tunnel bring down: " + iwlanError); 1531 } 1532 1533 iwlanDataServiceProvider.deliverCallback( 1534 IwlanDataServiceProvider.CALLBACK_TYPE_DEACTIVATE_DATACALL_COMPLETE, 1535 DataServiceCallback.RESULT_SUCCESS, 1536 tunnelState.getDataServiceCallback(), 1537 null); 1538 1539 return; 1540 } 1541 1542 // just update list of data calls. No way to send error up 1543 iwlanDataServiceProvider.notifyDataCallListChanged( 1544 iwlanDataServiceProvider.getCallList()); 1545 1546 // Report IwlanPdnDisconnectedReason due to the disconnection is neither for 1547 // SETUP_DATA_CALL nor DEACTIVATE_DATA_CALL request. 1548 metricsAtom.setDataCallFailCause( 1549 ErrorPolicyManager.getInstance( 1550 mContext, iwlanDataServiceProvider.getSlotIndex()) 1551 .getDataFailCause(apnName)); 1552 1553 WifiManager wifiManager = mContext.getSystemService(WifiManager.class); 1554 if (wifiManager == null) { 1555 Log.e(TAG, "Could not find wifiManager"); 1556 return; 1557 } 1558 1559 WifiInfo wifiInfo = getWifiInfo(sNetworkCapabilities); 1560 if (wifiInfo == null) { 1561 Log.e(TAG, "wifiInfo is null"); 1562 return; 1563 } 1564 1565 metricsAtom.setWifiSignalValue(wifiInfo.getRssi()); 1566 metricsAtom.setMessageId(IwlanStatsLog.IWLAN_PDN_DISCONNECTED_REASON_REPORTED); 1567 break; 1568 1569 case IwlanEventListener.CARRIER_CONFIG_CHANGED_EVENT: 1570 iwlanDataServiceProvider = 1571 (IwlanDataServiceProvider) getDataServiceProvider(msg.arg1); 1572 1573 iwlanDataServiceProvider.mCarrierConfigReady = true; 1574 iwlanDataServiceProvider.dnsPrefetchCheck(); 1575 break; 1576 1577 case IwlanEventListener.CARRIER_CONFIG_UNKNOWN_CARRIER_EVENT: 1578 iwlanDataServiceProvider = 1579 (IwlanDataServiceProvider) getDataServiceProvider(msg.arg1); 1580 1581 iwlanDataServiceProvider.mCarrierConfigReady = false; 1582 break; 1583 1584 case IwlanEventListener.WIFI_CALLING_ENABLE_EVENT: 1585 iwlanDataServiceProvider = 1586 (IwlanDataServiceProvider) getDataServiceProvider(msg.arg1); 1587 1588 iwlanDataServiceProvider.mWfcEnabled = true; 1589 iwlanDataServiceProvider.dnsPrefetchCheck(); 1590 break; 1591 1592 case IwlanEventListener.WIFI_CALLING_DISABLE_EVENT: 1593 iwlanDataServiceProvider = 1594 (IwlanDataServiceProvider) getDataServiceProvider(msg.arg1); 1595 1596 iwlanDataServiceProvider.mWfcEnabled = false; 1597 break; 1598 1599 case IwlanEventListener.CROSS_SIM_CALLING_ENABLE_EVENT: 1600 iwlanDataServiceProvider = 1601 (IwlanDataServiceProvider) getDataServiceProvider(msg.arg1); 1602 iwlanDataServiceProvider.updateNetwork(sNetwork, sLinkProperties); 1603 break; 1604 1605 case IwlanEventListener.CELLINFO_CHANGED_EVENT: 1606 List<CellInfo> cellInfolist = (List<CellInfo>) msg.obj; 1607 iwlanDataServiceProvider = 1608 (IwlanDataServiceProvider) getDataServiceProvider(msg.arg1); 1609 1610 if (cellInfolist != null 1611 && iwlanDataServiceProvider.isRegisteredCellInfoChanged(cellInfolist)) { 1612 int[] addrResolutionMethods = 1613 IwlanCarrierConfig.getConfigIntArray( 1614 mContext, 1615 iwlanDataServiceProvider.getSlotIndex(), 1616 CarrierConfigManager.Iwlan 1617 .KEY_EPDG_ADDRESS_PRIORITY_INT_ARRAY); 1618 for (int addrResolutionMethod : addrResolutionMethods) { 1619 if (addrResolutionMethod 1620 == CarrierConfigManager.Iwlan.EPDG_ADDRESS_CELLULAR_LOC) { 1621 iwlanDataServiceProvider.dnsPrefetchCheck(); 1622 } 1623 } 1624 } 1625 break; 1626 1627 case IwlanEventListener.CALL_STATE_CHANGED_EVENT: 1628 iwlanDataServiceProvider = 1629 (IwlanDataServiceProvider) getDataServiceProvider(msg.arg1); 1630 1631 int previousCallState = iwlanDataServiceProvider.mCallState; 1632 int currentCallState = iwlanDataServiceProvider.mCallState = msg.arg2; 1633 1634 if (!IwlanCarrierConfig.getConfigBoolean( 1635 mContext, 1636 iwlanDataServiceProvider.getSlotIndex(), 1637 IwlanCarrierConfig.KEY_UPDATE_N1_MODE_ON_UI_CHANGE_BOOL)) { 1638 break; 1639 } 1640 1641 // Disconnect PDN if call ends and re-establishment needed. 1642 if (previousCallState != currentCallState 1643 && currentCallState == TelephonyManager.CALL_STATE_IDLE 1644 && iwlanDataServiceProvider.isPdnReestablishNeededOnIdleN1Update()) { 1645 iwlanDataServiceProvider.disconnectPdnForN1ModeUpdate(); 1646 } 1647 break; 1648 1649 case IwlanEventListener.PREFERRED_NETWORK_TYPE_CHANGED_EVENT: 1650 iwlanDataServiceProvider = 1651 (IwlanDataServiceProvider) getDataServiceProvider(msg.arg1); 1652 if (!IwlanCarrierConfig.getConfigBoolean( 1653 mContext, 1654 iwlanDataServiceProvider.getSlotIndex(), 1655 IwlanCarrierConfig.KEY_UPDATE_N1_MODE_ON_UI_CHANGE_BOOL)) { 1656 break; 1657 } 1658 long allowedNetworkType = (long) msg.obj; 1659 onPreferredNetworkTypeChanged(iwlanDataServiceProvider, allowedNetworkType); 1660 break; 1661 1662 case EVENT_SETUP_DATA_CALL: 1663 SetupDataCallData setupDataCallData = (SetupDataCallData) msg.obj; 1664 int accessNetworkType = setupDataCallData.mAccessNetworkType; 1665 @NonNull DataProfile dataProfile = setupDataCallData.mDataProfile; 1666 boolean isRoaming = setupDataCallData.mIsRoaming; 1667 reason = setupDataCallData.mReason; 1668 LinkProperties linkProperties = setupDataCallData.mLinkProperties; 1669 @IntRange(from = 0, to = 15) 1670 int pduSessionId = setupDataCallData.mPduSessionId; 1671 callback = setupDataCallData.mCallback; 1672 iwlanDataServiceProvider = setupDataCallData.mIwlanDataServiceProvider; 1673 1674 if ((accessNetworkType != AccessNetworkType.IWLAN) 1675 || (dataProfile == null) 1676 || (dataProfile.getApnSetting() == null) 1677 || (linkProperties == null 1678 && reason == DataService.REQUEST_REASON_HANDOVER)) { 1679 1680 iwlanDataServiceProvider.deliverCallback( 1681 IwlanDataServiceProvider.CALLBACK_TYPE_SETUP_DATACALL_COMPLETE, 1682 DataServiceCallback.RESULT_ERROR_INVALID_ARG, 1683 callback, 1684 null); 1685 return; 1686 } 1687 1688 slotId = iwlanDataServiceProvider.getSlotIndex(); 1689 boolean isCSTEnabled = IwlanHelper.isCrossSimCallingEnabled(mContext, slotId); 1690 boolean networkConnected = 1691 isNetworkConnected(isActiveDataOnOtherSub(slotId), isCSTEnabled); 1692 Log.d( 1693 TAG + "[" + slotId + "]", 1694 "isDds: " 1695 + IwlanHelper.isDefaultDataSlot(mContext, slotId) 1696 + ", isActiveDataOnOtherSub: " 1697 + isActiveDataOnOtherSub(slotId) 1698 + ", isCstEnabled: " 1699 + isCSTEnabled 1700 + ", transport: " 1701 + sDefaultDataTransport); 1702 1703 if (!networkConnected) { 1704 iwlanDataServiceProvider.deliverCallback( 1705 IwlanDataServiceProvider.CALLBACK_TYPE_SETUP_DATACALL_COMPLETE, 1706 5 /* DataServiceCallback.RESULT_ERROR_TEMPORARILY_UNAVAILABLE 1707 */, 1708 callback, 1709 null); 1710 return; 1711 } 1712 1713 // Update Network & LinkProperties to EpdgTunnelManager 1714 iwlanDataServiceProvider 1715 .getTunnelManager() 1716 .updateNetwork(sNetwork, sLinkProperties); 1717 Log.d(TAG, "Update Network for SetupDataCall request"); 1718 1719 tunnelState = 1720 iwlanDataServiceProvider.mTunnelStateForApn.get( 1721 dataProfile.getApnSetting().getApnName()); 1722 1723 // Return the existing PDN if the pduSessionId is the same and the tunnel 1724 // state is TUNNEL_UP. 1725 if (tunnelState != null) { 1726 if (tunnelState.getPduSessionId() == pduSessionId 1727 && tunnelState.getState() 1728 == IwlanDataServiceProvider.TunnelState.TUNNEL_UP) { 1729 Log.w( 1730 TAG + "[" + slotId + "]", 1731 "The tunnel for " 1732 + dataProfile.getApnSetting().getApnName() 1733 + " already exists."); 1734 iwlanDataServiceProvider.deliverCallback( 1735 IwlanDataServiceProvider.CALLBACK_TYPE_SETUP_DATACALL_COMPLETE, 1736 DataServiceCallback.RESULT_SUCCESS, 1737 callback, 1738 iwlanDataServiceProvider.apnTunnelStateToDataCallResponse( 1739 dataProfile.getApnSetting().getApnName())); 1740 } else { 1741 Log.e( 1742 TAG + "[" + slotId + "]", 1743 "Force close the existing PDN. pduSessionId = " 1744 + tunnelState.getPduSessionId() 1745 + " Tunnel State = " 1746 + tunnelState.getState()); 1747 iwlanDataServiceProvider 1748 .getTunnelManager() 1749 .closeTunnel( 1750 dataProfile.getApnSetting().getApnName(), 1751 true /* forceClose */, 1752 iwlanDataServiceProvider.getIwlanTunnelCallback(), 1753 iwlanDataServiceProvider.getIwlanTunnelMetrics(), 1754 BRINGDOWN_REASON_SERVICE_OUT_OF_SYNC); 1755 iwlanDataServiceProvider.deliverCallback( 1756 IwlanDataServiceProvider.CALLBACK_TYPE_SETUP_DATACALL_COMPLETE, 1757 5 /* DataServiceCallback 1758 .RESULT_ERROR_TEMPORARILY_UNAVAILABLE */, 1759 callback, 1760 null); 1761 } 1762 return; 1763 } 1764 1765 int apnTypeBitmask = dataProfile.getApnSetting().getApnTypeBitmask(); 1766 boolean isIms = hasApnTypes(apnTypeBitmask, ApnSetting.TYPE_IMS); 1767 boolean isEmergency = hasApnTypes(apnTypeBitmask, ApnSetting.TYPE_EMERGENCY); 1768 1769 boolean isDataCallSetupWithN1 = 1770 iwlanDataServiceProvider.needIncludeN1ModeCapability(); 1771 1772 // Override N1_MODE_CAPABILITY exclusion only for Emergency PDN due to carrier 1773 // network limitations 1774 if (IwlanCarrierConfig.getConfigBoolean( 1775 mContext, 1776 slotId, 1777 IwlanCarrierConfig 1778 .KEY_N1_MODE_EXCLUSION_FOR_EMERGENCY_SESSION_BOOL) 1779 && isEmergency) { 1780 isDataCallSetupWithN1 = false; 1781 } 1782 1783 TunnelSetupRequest.Builder tunnelReqBuilder = 1784 TunnelSetupRequest.builder() 1785 .setApnName(dataProfile.getApnSetting().getApnName()) 1786 .setIsRoaming(isRoaming) 1787 .setPduSessionId( 1788 isDataCallSetupWithN1 1789 ? pduSessionId 1790 : PDU_SESSION_ID_UNSET) 1791 .setApnIpProtocol( 1792 isRoaming 1793 ? dataProfile 1794 .getApnSetting() 1795 .getRoamingProtocol() 1796 : dataProfile.getApnSetting().getProtocol()) 1797 .setRequestPcscf(isIms || isEmergency) 1798 .setIsEmergency(isEmergency); 1799 1800 if (reason == DataService.REQUEST_REASON_HANDOVER) { 1801 // for now assume that, at max, only one address of each type (v4/v6). 1802 // TODO: Check if multiple ips can be sent in ike tunnel setup 1803 for (LinkAddress lAddr : linkProperties.getLinkAddresses()) { 1804 if (lAddr.isIpv4()) { 1805 tunnelReqBuilder.setSrcIpv4Address(lAddr.getAddress()); 1806 } else if (lAddr.isIpv6()) { 1807 tunnelReqBuilder.setSrcIpv6Address(lAddr.getAddress()); 1808 tunnelReqBuilder.setSrcIpv6AddressPrefixLength( 1809 lAddr.getPrefixLength()); 1810 } 1811 } 1812 } 1813 1814 iwlanDataServiceProvider.setTunnelState( 1815 dataProfile, 1816 callback, 1817 IwlanDataServiceProvider.TunnelState.TUNNEL_IN_BRINGUP, 1818 null, 1819 (reason == DataService.REQUEST_REASON_HANDOVER), 1820 pduSessionId, 1821 isIms || isEmergency, 1822 isDataCallSetupWithN1); 1823 1824 boolean result = 1825 iwlanDataServiceProvider 1826 .getTunnelManager() 1827 .bringUpTunnel( 1828 tunnelReqBuilder.build(), 1829 iwlanDataServiceProvider.getIwlanTunnelCallback(), 1830 iwlanDataServiceProvider.getIwlanTunnelMetrics()); 1831 Log.d(TAG + "[" + slotId + "]", "bringup Tunnel with result:" + result); 1832 if (!result) { 1833 iwlanDataServiceProvider.deliverCallback( 1834 IwlanDataServiceProvider.CALLBACK_TYPE_SETUP_DATACALL_COMPLETE, 1835 DataServiceCallback.RESULT_ERROR_INVALID_ARG, 1836 callback, 1837 null); 1838 return; 1839 } 1840 break; 1841 1842 case EVENT_DEACTIVATE_DATA_CALL: 1843 handleDeactivateDataCall((DeactivateDataCallData) msg.obj); 1844 break; 1845 1846 case EVENT_DEACTIVATE_DATA_CALL_WITH_DELAY: 1847 handleDeactivateDataCallWithDelay((DeactivateDataCallData) msg.obj); 1848 break; 1849 1850 case EVENT_DATA_CALL_LIST_REQUEST: 1851 DataCallRequestData dataCallRequestData = (DataCallRequestData) msg.obj; 1852 callback = dataCallRequestData.mCallback; 1853 iwlanDataServiceProvider = dataCallRequestData.mIwlanDataServiceProvider; 1854 1855 iwlanDataServiceProvider.deliverCallback( 1856 IwlanDataServiceProvider.CALLBACK_TYPE_GET_DATACALL_LIST_COMPLETE, 1857 DataServiceCallback.RESULT_SUCCESS, 1858 callback, 1859 null); 1860 break; 1861 1862 case EVENT_FORCE_CLOSE_TUNNEL: 1863 for (IwlanDataServiceProvider dp : sIwlanDataServiceProviders.values()) { 1864 dp.forceCloseTunnels(EpdgTunnelManager.BRINGDOWN_REASON_UNKNOWN); 1865 } 1866 break; 1867 1868 case EVENT_ADD_DATA_SERVICE_PROVIDER: 1869 iwlanDataServiceProvider = (IwlanDataServiceProvider) msg.obj; 1870 addIwlanDataServiceProvider(iwlanDataServiceProvider); 1871 break; 1872 1873 case EVENT_REMOVE_DATA_SERVICE_PROVIDER: 1874 iwlanDataServiceProvider = (IwlanDataServiceProvider) msg.obj; 1875 1876 slotId = iwlanDataServiceProvider.getSlotIndex(); 1877 IwlanDataServiceProvider dsp = sIwlanDataServiceProviders.remove(slotId); 1878 if (dsp == null) { 1879 Log.w(TAG + "[" + slotId + "]", "No DataServiceProvider exists for slot!"); 1880 } 1881 1882 if (sIwlanDataServiceProviders.isEmpty()) { 1883 deinitNetworkCallback(); 1884 } 1885 break; 1886 1887 case EVENT_TUNNEL_OPENED_METRICS: 1888 OnOpenedMetrics openedMetricsData = (OnOpenedMetrics) msg.obj; 1889 iwlanDataServiceProvider = openedMetricsData.getIwlanDataServiceProvider(); 1890 apnName = openedMetricsData.getApnName(); 1891 1892 // Record setup result for the Metrics 1893 metricsAtom = iwlanDataServiceProvider.mMetricsAtomForApn.get(apnName); 1894 metricsAtom.setSetupRequestResult(DataServiceCallback.RESULT_SUCCESS); 1895 metricsAtom.setIwlanError(IwlanError.NO_ERROR); 1896 metricsAtom.setDataCallFailCause(DataFailCause.NONE); 1897 metricsAtom.setHandoverFailureMode(-1); 1898 metricsAtom.setRetryDurationMillis(0); 1899 metricsAtom.setMessageId(IwlanStatsLog.IWLAN_SETUP_DATA_CALL_RESULT_REPORTED); 1900 metricsAtom.setEpdgServerAddress(openedMetricsData.getEpdgServerAddress()); 1901 metricsAtom.setProcessingDurationMillis( 1902 (int) 1903 (System.currentTimeMillis() 1904 - iwlanDataServiceProvider.mProcessingStartTime)); 1905 metricsAtom.setEpdgServerSelectionDurationMillis( 1906 openedMetricsData.getEpdgServerSelectionDuration()); 1907 metricsAtom.setIkeTunnelEstablishmentDurationMillis( 1908 openedMetricsData.getIkeTunnelEstablishmentDuration()); 1909 metricsAtom.setIsNetworkValidated(openedMetricsData.isNetworkValidated()); 1910 1911 metricsAtom.sendMetricsData(); 1912 metricsAtom.setMessageId(MetricsAtom.INVALID_MESSAGE_ID); 1913 break; 1914 1915 case EVENT_TUNNEL_CLOSED_METRICS: 1916 OnClosedMetrics closedMetricsData = (OnClosedMetrics) msg.obj; 1917 iwlanDataServiceProvider = closedMetricsData.getIwlanDataServiceProvider(); 1918 apnName = closedMetricsData.getApnName(); 1919 1920 metricsAtom = iwlanDataServiceProvider.mMetricsAtomForApn.get(apnName); 1921 if (metricsAtom == null) { 1922 Log.w(TAG, "EVENT_TUNNEL_CLOSED_METRICS: MetricsAtom is null!"); 1923 break; 1924 } 1925 metricsAtom.setEpdgServerAddress(closedMetricsData.getEpdgServerAddress()); 1926 metricsAtom.setProcessingDurationMillis( 1927 iwlanDataServiceProvider.mProcessingStartTime > 0 1928 ? (int) 1929 (System.currentTimeMillis() 1930 - iwlanDataServiceProvider.mProcessingStartTime) 1931 : 0); 1932 metricsAtom.setEpdgServerSelectionDurationMillis( 1933 closedMetricsData.getEpdgServerSelectionDuration()); 1934 metricsAtom.setIkeTunnelEstablishmentDurationMillis( 1935 closedMetricsData.getIkeTunnelEstablishmentDuration()); 1936 metricsAtom.setIsNetworkValidated(closedMetricsData.isNetworkValidated()); 1937 1938 metricsAtom.sendMetricsData(); 1939 metricsAtom.setMessageId(MetricsAtom.INVALID_MESSAGE_ID); 1940 iwlanDataServiceProvider.mMetricsAtomForApn.remove(apnName); 1941 break; 1942 1943 case EVENT_ON_LIVENESS_STATUS_CHANGED: 1944 handleLivenessStatusChange((TunnelValidationStatusData) msg.obj); 1945 break; 1946 1947 case EVENT_REQUEST_NETWORK_VALIDATION: 1948 handleNetworkValidationRequest((NetworkValidationInfo) msg.obj); 1949 break; 1950 1951 default: 1952 throw new IllegalStateException("Unexpected value: " + msg.what); 1953 } 1954 } 1955 handleDeactivateDataCall(DeactivateDataCallData data)1956 public void handleDeactivateDataCall(DeactivateDataCallData data) { 1957 handleDeactivateDataCall(data, false); 1958 } 1959 handleDeactivateDataCallWithDelay(DeactivateDataCallData data)1960 public void handleDeactivateDataCallWithDelay(DeactivateDataCallData data) { 1961 handleDeactivateDataCall(data, true); 1962 } 1963 handleDeactivateDataCall(DeactivateDataCallData data, boolean isWithDelay)1964 public void handleDeactivateDataCall(DeactivateDataCallData data, boolean isWithDelay) { 1965 IwlanDataServiceProvider serviceProvider = data.mIwlanDataServiceProvider; 1966 String matchingApn = findMatchingApn(serviceProvider, data.mCid); 1967 1968 if (matchingApn == null) { 1969 deliverDeactivationError(serviceProvider, data.mCallback); 1970 return; 1971 } 1972 1973 if (isWithDelay) { 1974 Log.d(TAG, "Delaying deactivation for APN: " + matchingApn); 1975 scheduleDelayedDeactivateDataCall(serviceProvider, data, matchingApn); 1976 return; 1977 } 1978 Log.d(TAG, "Processing deactivation for APN: " + matchingApn); 1979 processDeactivateDataCall(serviceProvider, data, matchingApn); 1980 } 1981 handleNetworkValidationRequest(NetworkValidationInfo networkValidationInfo)1982 private void handleNetworkValidationRequest(NetworkValidationInfo networkValidationInfo) { 1983 IwlanDataServiceProvider iwlanDataServiceProvider = 1984 networkValidationInfo.mIwlanDataServiceProvider; 1985 int cid = networkValidationInfo.mCid; 1986 Executor executor = networkValidationInfo.mExecutor; 1987 Consumer<Integer> resultCodeCallback = networkValidationInfo.mResultCodeCallback; 1988 IwlanDataServiceProvider.TunnelState tunnelState; 1989 1990 String apnName = findMatchingApn(iwlanDataServiceProvider, cid); 1991 int resultCode; 1992 if (apnName == null) { 1993 Log.w(TAG, "no matching APN name found for network validation."); 1994 resultCode = DataServiceCallback.RESULT_ERROR_UNSUPPORTED; 1995 } else { 1996 EpdgTunnelManager epdgTunnelManager = iwlanDataServiceProvider.getTunnelManager(); 1997 epdgTunnelManager.requestNetworkValidationForApn(apnName); 1998 resultCode = DataServiceCallback.RESULT_SUCCESS; 1999 tunnelState = iwlanDataServiceProvider.mTunnelStateForApn.get(apnName); 2000 if (tunnelState == null) { 2001 Log.w(TAG, "EVENT_REQUEST_NETWORK_VALIDATION: tunnel state is null."); 2002 } else { 2003 tunnelState.setNetworkValidationStatus( 2004 PreciseDataConnectionState.NETWORK_VALIDATION_IN_PROGRESS); 2005 } 2006 } 2007 executor.execute(() -> resultCodeCallback.accept(resultCode)); 2008 } 2009 handleLivenessStatusChange(TunnelValidationStatusData validationStatusData)2010 private void handleLivenessStatusChange(TunnelValidationStatusData validationStatusData) { 2011 IwlanDataServiceProvider iwlanDataServiceProvider = 2012 validationStatusData.mIwlanDataServiceProvider; 2013 String apnName = validationStatusData.mApnName; 2014 IwlanDataServiceProvider.TunnelState tunnelState = 2015 iwlanDataServiceProvider.mTunnelStateForApn.get(apnName); 2016 if (tunnelState == null) { 2017 Log.w(TAG, "EVENT_ON_LIVENESS_STATUS_CHANGED: tunnel state is null."); 2018 return; 2019 } 2020 tunnelState.setNetworkValidationStatus(validationStatusData.mStatus); 2021 iwlanDataServiceProvider.notifyDataCallListChanged( 2022 iwlanDataServiceProvider.getCallList()); 2023 } 2024 findMatchingApn(IwlanDataServiceProvider serviceProvider, int cid)2025 private String findMatchingApn(IwlanDataServiceProvider serviceProvider, int cid) { 2026 return serviceProvider.mTunnelStateForApn.keySet().stream() 2027 .filter(apn -> apn.hashCode() == cid) 2028 .findFirst() 2029 .orElse(null); 2030 } 2031 deliverDeactivationError( IwlanDataServiceProvider serviceProvider, DataServiceCallback callback)2032 private void deliverDeactivationError( 2033 IwlanDataServiceProvider serviceProvider, DataServiceCallback callback) { 2034 serviceProvider.deliverCallback( 2035 IwlanDataServiceProvider.CALLBACK_TYPE_DEACTIVATE_DATACALL_COMPLETE, 2036 DataServiceCallback.RESULT_ERROR_INVALID_ARG, 2037 callback, 2038 null); 2039 } 2040 scheduleDelayedDeactivateDataCall( IwlanDataServiceProvider serviceProvider, DeactivateDataCallData data, String matchingApn)2041 private void scheduleDelayedDeactivateDataCall( 2042 IwlanDataServiceProvider serviceProvider, 2043 DeactivateDataCallData data, 2044 String matchingApn) { 2045 IwlanDataServiceProvider.TunnelState tunnelState = 2046 serviceProvider.mTunnelStateForApn.get(matchingApn); 2047 tunnelState.setPendingDeactivateDataCallData(data); 2048 tunnelState.setState(IwlanDataServiceProvider.TunnelState.TUNNEL_IN_BRINGDOWN); 2049 Handler handler = getIwlanDataServiceHandler(); 2050 handler.sendMessageDelayed( 2051 handler.obtainMessage(EVENT_DEACTIVATE_DATA_CALL, data), 2052 data.mDelayTimeSeconds * 1000L); 2053 } 2054 processDeactivateDataCall( IwlanDataServiceProvider serviceProvider, DeactivateDataCallData data, String matchingApn)2055 private void processDeactivateDataCall( 2056 IwlanDataServiceProvider serviceProvider, 2057 DeactivateDataCallData data, 2058 String matchingApn) { 2059 int slotId = serviceProvider.getSlotIndex(); 2060 boolean isNetworkLost = 2061 !isNetworkConnected( 2062 isActiveDataOnOtherSub(slotId), 2063 IwlanHelper.isCrossSimCallingEnabled(mContext, slotId)); 2064 boolean isHandoverSuccessful = (data.mReason == REQUEST_REASON_HANDOVER); 2065 2066 IwlanDataServiceProvider.TunnelState tunnelState = 2067 serviceProvider.mTunnelStateForApn.get(matchingApn); 2068 tunnelState.setState(IwlanDataServiceProvider.TunnelState.TUNNEL_IN_BRINGDOWN); 2069 tunnelState.setDataServiceCallback(data.mCallback); 2070 2071 serviceProvider 2072 .getTunnelManager() 2073 .closeTunnel( 2074 matchingApn, 2075 isNetworkLost || isHandoverSuccessful, /* forceClose */ 2076 serviceProvider.getIwlanTunnelCallback(), 2077 serviceProvider.getIwlanTunnelMetrics(), 2078 BRINGDOWN_REASON_DEACTIVATE_DATA_CALL); 2079 } 2080 cancelPendingDeactivationIfExists( DeactivateDataCallData deactivateDataCallData)2081 private void cancelPendingDeactivationIfExists( 2082 DeactivateDataCallData deactivateDataCallData) { 2083 Handler handler = getIwlanDataServiceHandler(); 2084 if (handler.hasMessages(EVENT_DEACTIVATE_DATA_CALL, deactivateDataCallData)) { 2085 // Remove any existing deactivation messages and request a new one in the front 2086 handler.removeMessages(EVENT_DEACTIVATE_DATA_CALL, deactivateDataCallData); 2087 } 2088 } 2089 IwlanDataServiceHandler(Looper looper)2090 IwlanDataServiceHandler(Looper looper) { 2091 super(looper); 2092 } 2093 } 2094 2095 private static final class TunnelOpenedData { 2096 final String mApnName; 2097 final TunnelLinkProperties mTunnelLinkProperties; 2098 final IwlanDataServiceProvider mIwlanDataServiceProvider; 2099 TunnelOpenedData( String apnName, TunnelLinkProperties tunnelLinkProperties, IwlanDataServiceProvider dsp)2100 private TunnelOpenedData( 2101 String apnName, 2102 TunnelLinkProperties tunnelLinkProperties, 2103 IwlanDataServiceProvider dsp) { 2104 mApnName = apnName; 2105 mTunnelLinkProperties = tunnelLinkProperties; 2106 mIwlanDataServiceProvider = dsp; 2107 } 2108 } 2109 2110 private static final class TunnelClosedData { 2111 final String mApnName; 2112 final IwlanError mIwlanError; 2113 final IwlanDataServiceProvider mIwlanDataServiceProvider; 2114 TunnelClosedData( String apnName, IwlanError iwlanError, IwlanDataServiceProvider dsp)2115 private TunnelClosedData( 2116 String apnName, IwlanError iwlanError, IwlanDataServiceProvider dsp) { 2117 mApnName = apnName; 2118 mIwlanError = iwlanError; 2119 mIwlanDataServiceProvider = dsp; 2120 } 2121 } 2122 2123 private static final class TunnelValidationStatusData { 2124 final String mApnName; 2125 final int mStatus; 2126 final IwlanDataServiceProvider mIwlanDataServiceProvider; 2127 TunnelValidationStatusData( String apnName, int status, IwlanDataServiceProvider dsp)2128 private TunnelValidationStatusData( 2129 String apnName, int status, IwlanDataServiceProvider dsp) { 2130 mApnName = apnName; 2131 mStatus = status; 2132 mIwlanDataServiceProvider = dsp; 2133 } 2134 } 2135 2136 private static final class NetworkValidationInfo { 2137 final int mCid; 2138 final Executor mExecutor; 2139 final Consumer<Integer> mResultCodeCallback; 2140 final IwlanDataServiceProvider mIwlanDataServiceProvider; 2141 NetworkValidationInfo( int cid, Executor executor, Consumer<Integer> r, IwlanDataServiceProvider dsp)2142 private NetworkValidationInfo( 2143 int cid, Executor executor, Consumer<Integer> r, IwlanDataServiceProvider dsp) { 2144 mCid = cid; 2145 mExecutor = executor; 2146 mResultCodeCallback = r; 2147 mIwlanDataServiceProvider = dsp; 2148 } 2149 } 2150 2151 private static final class SetupDataCallData { 2152 final int mAccessNetworkType; 2153 @NonNull final DataProfile mDataProfile; 2154 final boolean mIsRoaming; 2155 final boolean mAllowRoaming; 2156 final int mReason; 2157 @Nullable final LinkProperties mLinkProperties; 2158 2159 @IntRange(from = 0, to = 15) 2160 final int mPduSessionId; 2161 2162 @Nullable final NetworkSliceInfo mSliceInfo; 2163 @Nullable final TrafficDescriptor mTrafficDescriptor; 2164 final boolean mMatchAllRuleAllowed; 2165 @NonNull final DataServiceCallback mCallback; 2166 final IwlanDataServiceProvider mIwlanDataServiceProvider; 2167 SetupDataCallData( int accessNetworkType, DataProfile dataProfile, boolean isRoaming, boolean allowRoaming, int reason, LinkProperties linkProperties, int pduSessionId, NetworkSliceInfo sliceInfo, TrafficDescriptor trafficDescriptor, boolean matchAllRuleAllowed, DataServiceCallback callback, IwlanDataServiceProvider dsp)2168 private SetupDataCallData( 2169 int accessNetworkType, 2170 DataProfile dataProfile, 2171 boolean isRoaming, 2172 boolean allowRoaming, 2173 int reason, 2174 LinkProperties linkProperties, 2175 int pduSessionId, 2176 NetworkSliceInfo sliceInfo, 2177 TrafficDescriptor trafficDescriptor, 2178 boolean matchAllRuleAllowed, 2179 DataServiceCallback callback, 2180 IwlanDataServiceProvider dsp) { 2181 mAccessNetworkType = accessNetworkType; 2182 mDataProfile = dataProfile; 2183 mIsRoaming = isRoaming; 2184 mAllowRoaming = allowRoaming; 2185 mReason = reason; 2186 mLinkProperties = linkProperties; 2187 mPduSessionId = pduSessionId; 2188 mSliceInfo = sliceInfo; 2189 mTrafficDescriptor = trafficDescriptor; 2190 mMatchAllRuleAllowed = matchAllRuleAllowed; 2191 mCallback = callback; 2192 mIwlanDataServiceProvider = dsp; 2193 } 2194 } 2195 2196 private static final class DeactivateDataCallData { 2197 final int mCid; 2198 final int mReason; 2199 final DataServiceCallback mCallback; 2200 final IwlanDataServiceProvider mIwlanDataServiceProvider; 2201 final int mDelayTimeSeconds; 2202 DeactivateDataCallData( int cid, int reason, DataServiceCallback callback, IwlanDataServiceProvider dsp, int delayTimeSeconds)2203 private DeactivateDataCallData( 2204 int cid, 2205 int reason, 2206 DataServiceCallback callback, 2207 IwlanDataServiceProvider dsp, 2208 int delayTimeSeconds) { 2209 mCid = cid; 2210 mReason = reason; 2211 mCallback = callback; 2212 mIwlanDataServiceProvider = dsp; 2213 mDelayTimeSeconds = delayTimeSeconds; 2214 } 2215 } 2216 2217 private static final class DataCallRequestData { 2218 final DataServiceCallback mCallback; 2219 final IwlanDataServiceProvider mIwlanDataServiceProvider; 2220 DataCallRequestData(DataServiceCallback callback, IwlanDataServiceProvider dsp)2221 private DataCallRequestData(DataServiceCallback callback, IwlanDataServiceProvider dsp) { 2222 mCallback = callback; 2223 mIwlanDataServiceProvider = dsp; 2224 } 2225 } 2226 getConnectedDataSub(NetworkCapabilities networkCapabilities)2227 static int getConnectedDataSub(NetworkCapabilities networkCapabilities) { 2228 int connectedDataSub = INVALID_SUB_ID; 2229 NetworkSpecifier specifier = networkCapabilities.getNetworkSpecifier(); 2230 TransportInfo transportInfo = networkCapabilities.getTransportInfo(); 2231 2232 if (specifier instanceof TelephonyNetworkSpecifier) { 2233 connectedDataSub = ((TelephonyNetworkSpecifier) specifier).getSubscriptionId(); 2234 } else if (transportInfo instanceof VcnTransportInfo) { 2235 connectedDataSub = ((VcnTransportInfo) transportInfo).getSubId(); 2236 } 2237 return connectedDataSub; 2238 } 2239 setConnectedDataSub(int subId)2240 static void setConnectedDataSub(int subId) { 2241 mConnectedDataSub = subId; 2242 } 2243 2244 @VisibleForTesting isActiveDataOnOtherSub(int slotId)2245 static boolean isActiveDataOnOtherSub(int slotId) { 2246 int subId = IwlanHelper.getSubId(mContext, slotId); 2247 return mConnectedDataSub != INVALID_SUB_ID && subId != mConnectedDataSub; 2248 } 2249 2250 @VisibleForTesting isNetworkConnected(boolean isActiveDataOnOtherSub, boolean isCstEnabled)2251 static boolean isNetworkConnected(boolean isActiveDataOnOtherSub, boolean isCstEnabled) { 2252 if (isActiveDataOnOtherSub && isCstEnabled) { 2253 // For cross-SIM IWLAN (Transport.MOBILE), an active data PDN must be maintained on the 2254 // other subscription. 2255 if (sNetworkConnected && (sDefaultDataTransport != Transport.MOBILE)) { 2256 Log.e(TAG, "Internet is on other slot, but default transport is not MOBILE!"); 2257 } 2258 return sNetworkConnected; 2259 } else { 2260 // For all other cases, only Transport.WIFI can be used. 2261 return ((sDefaultDataTransport == Transport.WIFI) && sNetworkConnected); 2262 } 2263 } 2264 2265 /* Note: this api should have valid transport if networkConnected==true */ setNetworkConnected( boolean networkConnected, @NonNull Network network, Transport transport)2266 static void setNetworkConnected( 2267 boolean networkConnected, @NonNull Network network, Transport transport) { 2268 2269 boolean hasNetworkChanged = false; 2270 boolean hasTransportChanged = false; 2271 boolean hasNetworkConnectedChanged = false; 2272 2273 if (sNetworkConnected == networkConnected 2274 && network.equals(sNetwork) 2275 && sDefaultDataTransport == transport) { 2276 // Nothing changed 2277 return; 2278 } 2279 2280 // safety check 2281 if (networkConnected && transport == Transport.UNSPECIFIED_NETWORK) { 2282 Log.e(TAG, "setNetworkConnected: Network connected but transport unspecified"); 2283 return; 2284 } 2285 2286 if (!network.equals(sNetwork)) { 2287 Log.e(TAG, "System default network changed from: " + sNetwork + " TO: " + network); 2288 hasNetworkChanged = true; 2289 } 2290 2291 if (transport != sDefaultDataTransport) { 2292 Log.d( 2293 TAG, 2294 "Transport was changed from " 2295 + sDefaultDataTransport.name() 2296 + " to " 2297 + transport.name()); 2298 hasTransportChanged = true; 2299 } 2300 2301 if (sNetworkConnected != networkConnected) { 2302 Log.d( 2303 TAG, 2304 "Network connected state change from " 2305 + sNetworkConnected 2306 + " to " 2307 + networkConnected); 2308 hasNetworkConnectedChanged = true; 2309 } 2310 2311 sDefaultDataTransport = transport; 2312 sNetworkConnected = networkConnected; 2313 2314 if (networkConnected) { 2315 if (hasTransportChanged) { 2316 // Perform forceClose for tunnels in bringdown. 2317 // let framework handle explicit teardown 2318 for (IwlanDataServiceProvider dp : sIwlanDataServiceProviders.values()) { 2319 dp.forceCloseTunnelsInDeactivatingState(); 2320 } 2321 } 2322 2323 if (transport == Transport.WIFI && hasNetworkConnectedChanged) { 2324 IwlanEventListener.onWifiConnected(getWifiInfo(sNetworkCapabilities)); 2325 } 2326 // only prefetch dns and updateNetwork if Network has changed 2327 if (hasNetworkChanged) { 2328 ConnectivityManager connectivityManager = 2329 mContext.getSystemService(ConnectivityManager.class); 2330 LinkProperties linkProperties = connectivityManager.getLinkProperties(network); 2331 sLinkProperties = linkProperties; 2332 for (IwlanDataServiceProvider dp : sIwlanDataServiceProviders.values()) { 2333 dp.dnsPrefetchCheck(); 2334 dp.updateNetwork(network, linkProperties); 2335 } 2336 IwlanHelper.updateCountryCodeWhenNetworkConnected(); 2337 } 2338 } else { 2339 for (IwlanDataServiceProvider dp : sIwlanDataServiceProviders.values()) { 2340 // once network is disconnected, even NAT KA offload fails 2341 // But we should still let framework do an explicit teardown 2342 // so as to not affect an ongoing handover 2343 // only force close tunnels in bring down state 2344 dp.forceCloseTunnelsInDeactivatingState(); 2345 } 2346 } 2347 sNetwork = network; 2348 } 2349 setNetworkCapabilities(NetworkCapabilities networkCapabilities)2350 private static void setNetworkCapabilities(NetworkCapabilities networkCapabilities) { 2351 sNetworkCapabilities = networkCapabilities; 2352 } 2353 2354 /** 2355 * Get the DataServiceProvider associated with the slotId 2356 * 2357 * @param slotId slot index 2358 * @return DataService.DataServiceProvider associated with the slot 2359 */ getDataServiceProvider(int slotId)2360 public static DataService.DataServiceProvider getDataServiceProvider(int slotId) { 2361 return sIwlanDataServiceProviders.get(slotId); 2362 } 2363 getContext()2364 public static Context getContext() { 2365 return mContext; 2366 } 2367 2368 @Override onCreateDataServiceProvider(int slotIndex)2369 public DataServiceProvider onCreateDataServiceProvider(int slotIndex) { 2370 // TODO: validity check on slot index 2371 Log.d(TAG, "Creating provider for " + slotIndex); 2372 2373 if (mNetworkMonitorCallback == null) { 2374 // start monitoring network and register for default network callback 2375 ConnectivityManager connectivityManager = 2376 mContext.getSystemService(ConnectivityManager.class); 2377 mNetworkMonitorCallback = new IwlanNetworkMonitorCallback(); 2378 if (connectivityManager != null) { 2379 connectivityManager.registerSystemDefaultNetworkCallback( 2380 mNetworkMonitorCallback, getIwlanDataServiceHandler()); 2381 } 2382 Log.d(TAG, "Registered with Connectivity Service"); 2383 } 2384 2385 IwlanDataServiceProvider dp = new IwlanDataServiceProvider(slotIndex, this); 2386 2387 getIwlanDataServiceHandler() 2388 .sendMessage( 2389 getIwlanDataServiceHandler() 2390 .obtainMessage(EVENT_ADD_DATA_SERVICE_PROVIDER, dp)); 2391 return dp; 2392 } 2393 removeDataServiceProvider(IwlanDataServiceProvider dp)2394 public void removeDataServiceProvider(IwlanDataServiceProvider dp) { 2395 getIwlanDataServiceHandler() 2396 .sendMessage( 2397 getIwlanDataServiceHandler() 2398 .obtainMessage(EVENT_REMOVE_DATA_SERVICE_PROVIDER, dp)); 2399 } 2400 2401 @VisibleForTesting addIwlanDataServiceProvider(IwlanDataServiceProvider dp)2402 void addIwlanDataServiceProvider(IwlanDataServiceProvider dp) { 2403 int slotIndex = dp.getSlotIndex(); 2404 if (sIwlanDataServiceProviders.containsKey(slotIndex)) { 2405 throw new IllegalStateException( 2406 "DataServiceProvider already exists for slot " + slotIndex); 2407 } 2408 sIwlanDataServiceProviders.put(slotIndex, dp); 2409 } 2410 deinitNetworkCallback()2411 void deinitNetworkCallback() { 2412 // deinit network related stuff 2413 ConnectivityManager connectivityManager = 2414 mContext.getSystemService(ConnectivityManager.class); 2415 if (connectivityManager != null) { 2416 connectivityManager.unregisterNetworkCallback(mNetworkMonitorCallback); 2417 } 2418 mNetworkMonitorCallback = null; 2419 } 2420 hasApnTypes(int apnTypeBitmask, int expectedApn)2421 boolean hasApnTypes(int apnTypeBitmask, int expectedApn) { 2422 return (apnTypeBitmask & expectedApn) != 0; 2423 } 2424 2425 @VisibleForTesting setAppContext(Context appContext)2426 void setAppContext(Context appContext) { 2427 mContext = appContext; 2428 } 2429 2430 @VisibleForTesting 2431 @NonNull getIwlanDataServiceHandler()2432 Handler getIwlanDataServiceHandler() { 2433 if (mIwlanDataServiceHandler == null) { 2434 mIwlanDataServiceHandler = new IwlanDataServiceHandler(getLooper()); 2435 } 2436 return mIwlanDataServiceHandler; 2437 } 2438 2439 @VisibleForTesting getLooper()2440 Looper getLooper() { 2441 mIwlanDataServiceHandlerThread = new HandlerThread("IwlanDataServiceThread"); 2442 mIwlanDataServiceHandlerThread.start(); 2443 return mIwlanDataServiceHandlerThread.getLooper(); 2444 } 2445 eventToString(int event)2446 private static String eventToString(int event) { 2447 switch (event) { 2448 case EVENT_TUNNEL_OPENED: 2449 return "EVENT_TUNNEL_OPENED"; 2450 case EVENT_TUNNEL_CLOSED: 2451 return "EVENT_TUNNEL_CLOSED"; 2452 case EVENT_SETUP_DATA_CALL: 2453 return "EVENT_SETUP_DATA_CALL"; 2454 case EVENT_DEACTIVATE_DATA_CALL: 2455 return "EVENT_DEACTIVATE_DATA_CALL"; 2456 case EVENT_DATA_CALL_LIST_REQUEST: 2457 return "EVENT_DATA_CALL_LIST_REQUEST"; 2458 case EVENT_FORCE_CLOSE_TUNNEL: 2459 return "EVENT_FORCE_CLOSE_TUNNEL"; 2460 case EVENT_ADD_DATA_SERVICE_PROVIDER: 2461 return "EVENT_ADD_DATA_SERVICE_PROVIDER"; 2462 case EVENT_REMOVE_DATA_SERVICE_PROVIDER: 2463 return "EVENT_REMOVE_DATA_SERVICE_PROVIDER"; 2464 case IwlanEventListener.CARRIER_CONFIG_CHANGED_EVENT: 2465 return "CARRIER_CONFIG_CHANGED_EVENT"; 2466 case IwlanEventListener.CARRIER_CONFIG_UNKNOWN_CARRIER_EVENT: 2467 return "CARRIER_CONFIG_UNKNOWN_CARRIER_EVENT"; 2468 case IwlanEventListener.WIFI_CALLING_ENABLE_EVENT: 2469 return "WIFI_CALLING_ENABLE_EVENT"; 2470 case IwlanEventListener.WIFI_CALLING_DISABLE_EVENT: 2471 return "WIFI_CALLING_DISABLE_EVENT"; 2472 case IwlanEventListener.CROSS_SIM_CALLING_ENABLE_EVENT: 2473 return "CROSS_SIM_CALLING_ENABLE_EVENT"; 2474 case IwlanEventListener.CELLINFO_CHANGED_EVENT: 2475 return "CELLINFO_CHANGED_EVENT"; 2476 case EVENT_TUNNEL_OPENED_METRICS: 2477 return "EVENT_TUNNEL_OPENED_METRICS"; 2478 case EVENT_TUNNEL_CLOSED_METRICS: 2479 return "EVENT_TUNNEL_CLOSED_METRICS"; 2480 case EVENT_DEACTIVATE_DATA_CALL_WITH_DELAY: 2481 return "EVENT_DEACTIVATE_DATA_CALL_WITH_DELAY"; 2482 case IwlanEventListener.CALL_STATE_CHANGED_EVENT: 2483 return "CALL_STATE_CHANGED_EVENT"; 2484 case IwlanEventListener.PREFERRED_NETWORK_TYPE_CHANGED_EVENT: 2485 return "PREFERRED_NETWORK_TYPE_CHANGED_EVENT"; 2486 case EVENT_ON_LIVENESS_STATUS_CHANGED: 2487 return "EVENT_ON_LIVENESS_STATUS_CHANGED"; 2488 case EVENT_REQUEST_NETWORK_VALIDATION: 2489 return "EVENT_REQUEST_NETWORK_VALIDATION"; 2490 default: 2491 return "Unknown(" + event + ")"; 2492 } 2493 } 2494 initAllowedNetworkType()2495 private void initAllowedNetworkType() { 2496 TelephonyManager mTelephonyManager = mContext.getSystemService(TelephonyManager.class); 2497 mIs5GEnabledOnUi = 2498 ((mTelephonyManager.getAllowedNetworkTypesBitmask() 2499 & TelephonyManager.NETWORK_TYPE_BITMASK_NR) 2500 != 0); 2501 } 2502 onPreferredNetworkTypeChanged( IwlanDataServiceProvider iwlanDataServiceProvider, long allowedNetworkType)2503 private void onPreferredNetworkTypeChanged( 2504 IwlanDataServiceProvider iwlanDataServiceProvider, long allowedNetworkType) { 2505 boolean isCurrentUiEnable5G = 2506 (allowedNetworkType & TelephonyManager.NETWORK_TYPE_BITMASK_NR) != 0; 2507 boolean isPreviousUiEnable5G = mIs5GEnabledOnUi; 2508 mIs5GEnabledOnUi = isCurrentUiEnable5G; 2509 if (!iwlanDataServiceProvider.isN1ModeSupported()) { 2510 return; 2511 } 2512 if (isPreviousUiEnable5G != isCurrentUiEnable5G) { 2513 if (!iwlanDataServiceProvider.isOnCall()) { 2514 iwlanDataServiceProvider.disconnectPdnForN1ModeUpdate(); 2515 } 2516 } 2517 } 2518 2519 @Nullable getWifiInfo(@ullable NetworkCapabilities networkCapabilities)2520 private static WifiInfo getWifiInfo(@Nullable NetworkCapabilities networkCapabilities) { 2521 if (networkCapabilities == null) { 2522 Log.d(TAG, "Cannot obtain wifi info, networkCapabilities is null"); 2523 return null; 2524 } 2525 return networkCapabilities.getTransportInfo() instanceof WifiInfo wifiInfo 2526 ? wifiInfo 2527 : null; 2528 } 2529 2530 @Override onCreate()2531 public void onCreate() { 2532 Context context = getApplicationContext().createAttributionContext(CONTEXT_ATTRIBUTION_TAG); 2533 setAppContext(context); 2534 IwlanBroadcastReceiver.startListening(mContext); 2535 IwlanCarrierConfigChangeListener.startListening(mContext); 2536 IwlanHelper.startCountryDetector(mContext); 2537 initAllowedNetworkType(); 2538 } 2539 2540 @Override onDestroy()2541 public void onDestroy() { 2542 IwlanCarrierConfigChangeListener.stopListening(mContext); 2543 IwlanBroadcastReceiver.stopListening(mContext); 2544 } 2545 2546 @Override onBind(Intent intent)2547 public IBinder onBind(Intent intent) { 2548 Log.d(TAG, "IwlanDataService onBind"); 2549 return super.onBind(intent); 2550 } 2551 2552 @Override onUnbind(Intent intent)2553 public boolean onUnbind(Intent intent) { 2554 Log.d(TAG, "IwlanDataService onUnbind"); 2555 getIwlanDataServiceHandler() 2556 .sendMessage(getIwlanDataServiceHandler().obtainMessage(EVENT_FORCE_CLOSE_TUNNEL)); 2557 return super.onUnbind(intent); 2558 } 2559 requestReasonToString(int reason)2560 private String requestReasonToString(int reason) { 2561 switch (reason) { 2562 case DataService.REQUEST_REASON_UNKNOWN: 2563 return "UNKNOWN"; 2564 case DataService.REQUEST_REASON_NORMAL: 2565 return "NORMAL"; 2566 case DataService.REQUEST_REASON_SHUTDOWN: 2567 return "SHUTDOWN"; 2568 case DataService.REQUEST_REASON_HANDOVER: 2569 return "HANDOVER"; 2570 default: 2571 return "UNKNOWN(" + reason + ")"; 2572 } 2573 } 2574 2575 @Override dump(FileDescriptor fd, PrintWriter pw, String[] args)2576 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 2577 String transport = "UNSPECIFIED"; 2578 if (sDefaultDataTransport == Transport.MOBILE) { 2579 transport = "CELLULAR"; 2580 } else if (sDefaultDataTransport == Transport.WIFI) { 2581 transport = "WIFI"; 2582 } 2583 pw.println("Default transport: " + transport); 2584 for (IwlanDataServiceProvider provider : sIwlanDataServiceProviders.values()) { 2585 pw.println(); 2586 provider.dump(fd, pw, args); 2587 pw.println(); 2588 pw.println(); 2589 } 2590 } 2591 } 2592