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