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