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