1 /* 2 * Copyright (C) 2006 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.internal.telephony.dataconnection; 18 19 import static android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE; 20 import static android.net.NetworkPolicyManager.SUBSCRIPTION_OVERRIDE_CONGESTED; 21 import static android.net.NetworkPolicyManager.SUBSCRIPTION_OVERRIDE_UNMETERED; 22 import static android.telephony.TelephonyManager.NETWORK_TYPE_LTE; 23 import static android.telephony.TelephonyManager.NETWORK_TYPE_NR; 24 import static android.telephony.data.DataCallResponse.HANDOVER_FAILURE_MODE_DO_FALLBACK; 25 import static android.telephony.data.DataCallResponse.HANDOVER_FAILURE_MODE_LEGACY; 26 import static android.telephony.data.DataCallResponse.HANDOVER_FAILURE_MODE_NO_FALLBACK_RETRY_SETUP_NORMAL; 27 28 import static com.android.internal.telephony.RILConstants.DATA_PROFILE_DEFAULT; 29 import static com.android.internal.telephony.RILConstants.DATA_PROFILE_INVALID; 30 31 import android.annotation.IntDef; 32 import android.annotation.NonNull; 33 import android.annotation.Nullable; 34 import android.app.AlarmManager; 35 import android.app.Notification; 36 import android.app.NotificationManager; 37 import android.app.PendingIntent; 38 import android.app.ProgressDialog; 39 import android.content.ActivityNotFoundException; 40 import android.content.BroadcastReceiver; 41 import android.content.ContentResolver; 42 import android.content.ContentValues; 43 import android.content.Context; 44 import android.content.Intent; 45 import android.content.IntentFilter; 46 import android.content.SharedPreferences; 47 import android.content.res.Resources; 48 import android.database.ContentObserver; 49 import android.database.Cursor; 50 import android.net.ConnectivityManager; 51 import android.net.LinkProperties; 52 import android.net.NetworkAgent; 53 import android.net.NetworkCapabilities; 54 import android.net.NetworkPolicyManager; 55 import android.net.NetworkRequest; 56 import android.net.TrafficStats; 57 import android.net.Uri; 58 import android.os.AsyncResult; 59 import android.os.Bundle; 60 import android.os.Handler; 61 import android.os.HandlerThread; 62 import android.os.Message; 63 import android.os.PersistableBundle; 64 import android.os.RegistrantList; 65 import android.os.SystemClock; 66 import android.os.SystemProperties; 67 import android.os.UserHandle; 68 import android.preference.PreferenceManager; 69 import android.provider.Settings; 70 import android.provider.Settings.SettingNotFoundException; 71 import android.provider.Telephony; 72 import android.telephony.AccessNetworkConstants; 73 import android.telephony.AccessNetworkConstants.TransportType; 74 import android.telephony.Annotation.ApnType; 75 import android.telephony.Annotation.DataFailureCause; 76 import android.telephony.Annotation.NetworkType; 77 import android.telephony.CarrierConfigManager; 78 import android.telephony.CellLocation; 79 import android.telephony.DataFailCause; 80 import android.telephony.NetworkRegistrationInfo; 81 import android.telephony.PcoData; 82 import android.telephony.PreciseDataConnectionState; 83 import android.telephony.ServiceState; 84 import android.telephony.ServiceState.RilRadioTechnology; 85 import android.telephony.SubscriptionManager; 86 import android.telephony.SubscriptionPlan; 87 import android.telephony.TelephonyDisplayInfo; 88 import android.telephony.TelephonyFrameworkInitializer; 89 import android.telephony.TelephonyManager; 90 import android.telephony.TelephonyManager.SimState; 91 import android.telephony.cdma.CdmaCellLocation; 92 import android.telephony.data.ApnSetting; 93 import android.telephony.data.DataCallResponse; 94 import android.telephony.data.DataCallResponse.HandoverFailureMode; 95 import android.telephony.data.DataProfile; 96 import android.telephony.data.ThrottleStatus; 97 import android.telephony.gsm.GsmCellLocation; 98 import android.text.TextUtils; 99 import android.util.EventLog; 100 import android.util.LocalLog; 101 import android.util.Log; 102 import android.util.Pair; 103 import android.util.SparseArray; 104 import android.view.WindowManager; 105 106 import com.android.internal.R; 107 import com.android.internal.annotations.VisibleForTesting; 108 import com.android.internal.telephony.DctConstants; 109 import com.android.internal.telephony.EventLogTags; 110 import com.android.internal.telephony.GsmCdmaPhone; 111 import com.android.internal.telephony.ITelephony; 112 import com.android.internal.telephony.Phone; 113 import com.android.internal.telephony.PhoneConstants; 114 import com.android.internal.telephony.PhoneFactory; 115 import com.android.internal.telephony.RILConstants; 116 import com.android.internal.telephony.RetryManager; 117 import com.android.internal.telephony.SettingsObserver; 118 import com.android.internal.telephony.SubscriptionInfoUpdater; 119 import com.android.internal.telephony.data.DataConfigManager; 120 import com.android.internal.telephony.data.PhoneSwitcher; 121 import com.android.internal.telephony.dataconnection.DataConnectionReasons.DataAllowedReasonType; 122 import com.android.internal.telephony.dataconnection.DataConnectionReasons.DataDisallowedReasonType; 123 import com.android.internal.telephony.dataconnection.DataEnabledSettings.DataEnabledChangedReason; 124 import com.android.internal.telephony.metrics.DataStallRecoveryStats; 125 import com.android.internal.telephony.metrics.TelephonyMetrics; 126 import com.android.internal.telephony.util.ArrayUtils; 127 import com.android.internal.telephony.util.NotificationChannelController; 128 import com.android.internal.telephony.util.TelephonyUtils; 129 import com.android.internal.util.AsyncChannel; 130 import com.android.telephony.Rlog; 131 132 import java.io.FileDescriptor; 133 import java.io.PrintWriter; 134 import java.lang.annotation.Retention; 135 import java.lang.annotation.RetentionPolicy; 136 import java.util.ArrayList; 137 import java.util.Arrays; 138 import java.util.Collection; 139 import java.util.Collections; 140 import java.util.HashMap; 141 import java.util.List; 142 import java.util.Map; 143 import java.util.Map.Entry; 144 import java.util.Set; 145 import java.util.concurrent.ConcurrentHashMap; 146 import java.util.concurrent.atomic.AtomicBoolean; 147 import java.util.concurrent.atomic.AtomicInteger; 148 import java.util.stream.Collectors; 149 150 /** 151 * {@hide} 152 */ 153 public class DcTracker extends Handler { 154 protected static final boolean DBG = true; 155 private static final boolean VDBG = false; // STOPSHIP if true 156 private static final boolean VDBG_STALL = false; // STOPSHIP if true 157 private static final boolean RADIO_TESTS = false; 158 private static final String NOTIFICATION_TAG = DcTracker.class.getSimpleName(); 159 160 @IntDef(value = { 161 REQUEST_TYPE_NORMAL, 162 REQUEST_TYPE_HANDOVER, 163 }) 164 @Retention(RetentionPolicy.SOURCE) 165 public @interface RequestNetworkType {} 166 167 /** 168 * Normal request for {@link #requestNetwork(NetworkRequest, int, Message)}. For request 169 * network, this adds the request to the {@link ApnContext}. If there were no network request 170 * attached to the {@link ApnContext} earlier, this request setups a data connection. 171 */ 172 public static final int REQUEST_TYPE_NORMAL = 1; 173 174 /** 175 * Handover request for {@link #requestNetwork(NetworkRequest, int, Message)} or 176 * {@link #releaseNetwork(NetworkRequest, int)}. For request network, this 177 * initiates the handover data setup process. The existing data connection will be seamlessly 178 * handover to the new network. For release network, this performs a data connection softly 179 * clean up at the underlying layer (versus normal data release). 180 */ 181 public static final int REQUEST_TYPE_HANDOVER = 2; 182 183 @IntDef(value = { 184 RELEASE_TYPE_NORMAL, 185 RELEASE_TYPE_DETACH, 186 RELEASE_TYPE_HANDOVER, 187 }) 188 @Retention(RetentionPolicy.SOURCE) 189 public @interface ReleaseNetworkType {} 190 191 /** 192 * For release network, this is just removing the network request from the {@link ApnContext}. 193 * Note this does not tear down the physical data connection. Normally the data connection is 194 * torn down by connectivity service directly calling {@link NetworkAgent#unwanted()}. 195 */ 196 public static final int RELEASE_TYPE_NORMAL = 1; 197 198 /** 199 * Detach request for {@link #releaseNetwork(NetworkRequest, int)} only. This 200 * forces the APN context detach from the data connection. If this {@link ApnContext} is the 201 * last one attached to the data connection, the data connection will be torn down, otherwise 202 * the data connection remains active. 203 */ 204 public static final int RELEASE_TYPE_DETACH = 2; 205 206 /** 207 * Handover request for {@link #releaseNetwork(NetworkRequest, int)}. For release 208 * network, this performs a data connection softly clean up at the underlying layer (versus 209 * normal data release). 210 */ 211 public static final int RELEASE_TYPE_HANDOVER = 3; 212 213 /** The extras for handover completion message */ 214 public static final String DATA_COMPLETE_MSG_EXTRA_NETWORK_REQUEST = "extra_network_request"; 215 public static final String DATA_COMPLETE_MSG_EXTRA_TRANSPORT_TYPE = "extra_transport_type"; 216 public static final String DATA_COMPLETE_MSG_EXTRA_SUCCESS = "extra_success"; 217 /** 218 * The flag indicates whether after handover failure, the data connection should remain on the 219 * original transport. 220 */ 221 public static final String DATA_COMPLETE_MSG_EXTRA_HANDOVER_FAILURE_FALLBACK = 222 "extra_handover_failure_fallback"; 223 224 private final String mLogTag; 225 226 public AtomicBoolean isCleanupRequired = new AtomicBoolean(false); 227 228 private final TelephonyManager mTelephonyManager; 229 230 private final AlarmManager mAlarmManager; 231 232 /* Currently requested APN type (TODO: This should probably be a parameter not a member) */ 233 private int mRequestedApnType = ApnSetting.TYPE_DEFAULT; 234 235 // All data enabling/disabling related settings 236 private final DataEnabledSettings mDataEnabledSettings; 237 238 /** 239 * After detecting a potential connection problem, this is the max number 240 * of subsequent polls before attempting recovery. 241 */ 242 // 1 sec. default polling interval when screen is on. 243 private static final int POLL_NETSTAT_MILLIS = 1000; 244 // 10 min. default polling interval when screen is off. 245 private static final int POLL_NETSTAT_SCREEN_OFF_MILLIS = 1000*60*10; 246 // Default sent packets without ack which triggers initial recovery steps 247 private static final int NUMBER_SENT_PACKETS_OF_HANG = 10; 248 249 // Default for the data stall alarm while non-aggressive stall detection 250 private static final int DATA_STALL_ALARM_NON_AGGRESSIVE_DELAY_IN_MS_DEFAULT = 1000 * 60 * 6; 251 // Default for the data stall alarm for aggressive stall detection 252 private static final int DATA_STALL_ALARM_AGGRESSIVE_DELAY_IN_MS_DEFAULT = 1000 * 60; 253 254 private static final boolean DATA_STALL_SUSPECTED = true; 255 protected static final boolean DATA_STALL_NOT_SUSPECTED = false; 256 257 private static final String INTENT_DATA_STALL_ALARM = 258 "com.android.internal.telephony.data-stall"; 259 // Tag for tracking stale alarms 260 private static final String INTENT_DATA_STALL_ALARM_EXTRA_TAG = "data_stall_alarm_extra_tag"; 261 private static final String INTENT_DATA_STALL_ALARM_EXTRA_TRANSPORT_TYPE = 262 "data_stall_alarm_extra_transport_type"; 263 264 // Unique id for no data notification on setup data permanently failed. 265 private static final int NO_DATA_NOTIFICATION = 1001; 266 267 /** The higher index has higher priority. */ 268 private static final DctConstants.State[] DATA_CONNECTION_STATE_PRIORITIES = { 269 DctConstants.State.IDLE, 270 DctConstants.State.DISCONNECTING, 271 DctConstants.State.CONNECTING, 272 DctConstants.State.CONNECTED, 273 }; 274 275 private DcTesterFailBringUpAll mDcTesterFailBringUpAll; 276 private DcController mDcc; 277 278 /** kept in sync with mApnContexts 279 * Higher numbers are higher priority and sorted so highest priority is first */ 280 private ArrayList<ApnContext> mPrioritySortedApnContexts = new ArrayList<>(); 281 282 /** all APN settings applicable to the current carrier */ 283 private ArrayList<ApnSetting> mAllApnSettings = new ArrayList<>(); 284 285 /** preferred apn */ 286 private ApnSetting mPreferredApn = null; 287 288 /** Is packet service restricted by network */ 289 private boolean mIsPsRestricted = false; 290 291 /** emergency apn Setting*/ 292 private ApnSetting mEmergencyApn = null; 293 294 /* Once disposed dont handle any messages */ 295 private boolean mIsDisposed = false; 296 297 private ContentResolver mResolver; 298 299 /* Set to true with CMD_ENABLE_MOBILE_PROVISIONING */ 300 private boolean mIsProvisioning = false; 301 302 /* The Url passed as object parameter in CMD_ENABLE_MOBILE_PROVISIONING */ 303 private String mProvisioningUrl = null; 304 305 /* Indicating data service is bound or not */ 306 private boolean mDataServiceBound = false; 307 308 /* Intent to hide/show the sign-in error notification for provisioning */ 309 private static final String INTENT_PROVISION = "com.android.internal.telephony.PROVISION"; 310 311 /** 312 * Extra containing the phone ID for INTENT_PROVISION 313 * Must be kept consistent with NetworkNotificationManager#setProvNotificationVisible. 314 * TODO: refactor the deprecated API to prevent hardcoding values. 315 */ 316 private static final String EXTRA_PROVISION_PHONE_ID = "provision.phone.id"; 317 318 /* Intent for the provisioning apn alarm */ 319 private static final String INTENT_PROVISIONING_APN_ALARM = 320 "com.android.internal.telephony.provisioning_apn_alarm"; 321 322 /* Tag for tracking stale alarms */ 323 private static final String PROVISIONING_APN_ALARM_TAG_EXTRA = "provisioning.apn.alarm.tag"; 324 325 /* Debug property for overriding the PROVISIONING_APN_ALARM_DELAY_IN_MS */ 326 private static final String DEBUG_PROV_APN_ALARM = "persist.debug.prov_apn_alarm"; 327 328 /* Default for the provisioning apn alarm timeout */ 329 private static final int PROVISIONING_APN_ALARM_DELAY_IN_MS_DEFAULT = 1000 * 60 * 15; 330 331 /* The provision apn alarm intent used to disable the provisioning apn */ 332 private PendingIntent mProvisioningApnAlarmIntent = null; 333 334 /* Used to track stale provisioning apn alarms */ 335 private int mProvisioningApnAlarmTag = (int) SystemClock.elapsedRealtime(); 336 337 private AsyncChannel mReplyAc = new AsyncChannel(); 338 339 private final LocalLog mDataRoamingLeakageLog = new LocalLog(32); 340 private final LocalLog mApnSettingsInitializationLog = new LocalLog(32); 341 342 /* 5G connection reevaluation watchdog alarm constants */ 343 private long mWatchdogTimeMs = 1000 * 60 * 60; 344 private boolean mWatchdog = false; 345 346 /* Default for whether 5G frequencies are considered unmetered */ 347 private boolean mNrNsaAllUnmetered = false; 348 private boolean mNrNsaMmwaveUnmetered = false; 349 private boolean mNrNsaSub6Unmetered = false; 350 private boolean mNrSaAllUnmetered = false; 351 private boolean mNrSaMmwaveUnmetered = false; 352 private boolean mNrSaSub6Unmetered = false; 353 private boolean mNrNsaRoamingUnmetered = false; 354 355 // it effect the PhysicalLinkStatusChanged 356 private boolean mLteEndcUsingUserDataForRrcDetection = false; 357 358 /* List of SubscriptionPlans, updated when initialized and when plans are changed. */ 359 private List<SubscriptionPlan> mSubscriptionPlans = new ArrayList<>(); 360 /* List of network types an unmetered override applies to, set by onSubscriptionOverride 361 * and cleared when the device is rebooted or the override expires. */ 362 private List<Integer> mUnmeteredNetworkTypes = null; 363 /* List of network types a congested override applies to, set by onSubscriptionOverride 364 * and cleared when the device is rebooted or the override expires. */ 365 private List<Integer> mCongestedNetworkTypes = null; 366 /* Whether an unmetered override is currently active. */ 367 private boolean mUnmeteredOverride = false; 368 /* Whether a congested override is currently active. */ 369 private boolean mCongestedOverride = false; 370 371 @SimState 372 private int mSimState = TelephonyManager.SIM_STATE_UNKNOWN; 373 374 private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver () { 375 @Override 376 public void onReceive(Context context, Intent intent) { 377 String action = intent.getAction(); 378 379 if (action.equals(Intent.ACTION_SCREEN_ON)) { 380 // TODO: Evaluate hooking this up with DeviceStateMonitor 381 if (DBG) log("screen on"); 382 mIsScreenOn = true; 383 stopNetStatPoll(); 384 startNetStatPoll(); 385 restartDataStallAlarm(); 386 } else if (action.equals(Intent.ACTION_SCREEN_OFF)) { 387 if (DBG) log("screen off"); 388 mIsScreenOn = false; 389 stopNetStatPoll(); 390 startNetStatPoll(); 391 restartDataStallAlarm(); 392 } else if (action.equals(INTENT_DATA_STALL_ALARM)) { 393 onActionIntentDataStallAlarm(intent); 394 } else if (action.equals(INTENT_PROVISIONING_APN_ALARM)) { 395 if (DBG) log("Provisioning apn alarm"); 396 onActionIntentProvisioningApnAlarm(intent); 397 } else if (action.equals(TelephonyManager.ACTION_SIM_CARD_STATE_CHANGED) 398 || action.equals(TelephonyManager.ACTION_SIM_APPLICATION_STATE_CHANGED)) { 399 if (mPhone.getPhoneId() == intent.getIntExtra(SubscriptionManager.EXTRA_SLOT_INDEX, 400 SubscriptionManager.INVALID_SIM_SLOT_INDEX)) { 401 int simState = intent.getIntExtra(TelephonyManager.EXTRA_SIM_STATE, 402 TelephonyManager.SIM_STATE_UNKNOWN); 403 sendMessage(obtainMessage(DctConstants.EVENT_SIM_STATE_UPDATED, simState, 0)); 404 } 405 } else if (action.equals(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED)) { 406 if (mPhone.getPhoneId() == intent.getIntExtra(CarrierConfigManager.EXTRA_SLOT_INDEX, 407 SubscriptionManager.INVALID_SIM_SLOT_INDEX)) { 408 if (intent.getBooleanExtra( 409 CarrierConfigManager.EXTRA_REBROADCAST_ON_UNLOCK, false)) { 410 // Ignore the rebroadcast one to prevent multiple carrier config changed 411 // event during boot up. 412 return; 413 } 414 int subId = intent.getIntExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, 415 SubscriptionManager.INVALID_SUBSCRIPTION_ID); 416 if (SubscriptionManager.isValidSubscriptionId(subId)) { 417 sendEmptyMessage(DctConstants.EVENT_CARRIER_CONFIG_CHANGED); 418 } 419 } 420 } else { 421 if (DBG) log("onReceive: Unknown action=" + action); 422 } 423 } 424 }; 425 426 private final Runnable mPollNetStat = new Runnable() { 427 @Override 428 public void run() { 429 updateDataActivity(); 430 431 if (mIsScreenOn) { 432 mNetStatPollPeriod = Settings.Global.getInt(mResolver, 433 Settings.Global.PDP_WATCHDOG_POLL_INTERVAL_MS, POLL_NETSTAT_MILLIS); 434 } else { 435 mNetStatPollPeriod = Settings.Global.getInt(mResolver, 436 Settings.Global.PDP_WATCHDOG_LONG_POLL_INTERVAL_MS, 437 POLL_NETSTAT_SCREEN_OFF_MILLIS); 438 } 439 440 if (mNetStatPollEnabled) { 441 mDataConnectionTracker.postDelayed(this, mNetStatPollPeriod); 442 } 443 } 444 }; 445 446 private class ThrottleStatusChangedCallback implements DataThrottler.Callback { 447 @Override onThrottleStatusChanged(List<ThrottleStatus> throttleStatuses)448 public void onThrottleStatusChanged(List<ThrottleStatus> throttleStatuses) { 449 for (ThrottleStatus status : throttleStatuses) { 450 if (status.getThrottleType() == ThrottleStatus.THROTTLE_TYPE_NONE) { 451 setupDataOnConnectableApn(mApnContextsByType.get(status.getApnType()), 452 Phone.REASON_DATA_UNTHROTTLED, 453 RetryFailures.ALWAYS); 454 } 455 } 456 } 457 } 458 459 private NetworkPolicyManager mNetworkPolicyManager; 460 private final NetworkPolicyManager.SubscriptionCallback mSubscriptionCallback = 461 new NetworkPolicyManager.SubscriptionCallback() { 462 @Override 463 public void onSubscriptionOverride(int subId, int overrideMask, int overrideValue, 464 int[] networkTypes) { 465 if (mPhone == null || mPhone.getSubId() != subId) return; 466 467 List<Integer> tempList = new ArrayList<>(); 468 for (int networkType : networkTypes) { 469 tempList.add(networkType); 470 } 471 472 log("Subscription override: overrideMask=" + overrideMask 473 + ", overrideValue=" + overrideValue + ", networkTypes=" + tempList); 474 475 if (overrideMask == SUBSCRIPTION_OVERRIDE_UNMETERED) { 476 mUnmeteredNetworkTypes = tempList; 477 mUnmeteredOverride = overrideValue != 0; 478 reevaluateUnmeteredConnections(); 479 } else if (overrideMask == SUBSCRIPTION_OVERRIDE_CONGESTED) { 480 mCongestedNetworkTypes = tempList; 481 mCongestedOverride = overrideValue != 0; 482 reevaluateCongestedConnections(); 483 } 484 } 485 486 @Override 487 public void onSubscriptionPlansChanged(int subId, SubscriptionPlan[] plans) { 488 if (mPhone == null || mPhone.getSubId() != subId) return; 489 490 mSubscriptionPlans = Arrays.asList(plans); 491 if (DBG) log("SubscriptionPlans changed: " + mSubscriptionPlans); 492 reevaluateUnmeteredConnections(); 493 } 494 }; 495 496 private final SettingsObserver mSettingsObserver; 497 registerSettingsObserver()498 private void registerSettingsObserver() { 499 mSettingsObserver.unobserve(); 500 String simSuffix = ""; 501 if (TelephonyManager.getDefault().getSimCount() > 1) { 502 simSuffix = Integer.toString(mPhone.getSubId()); 503 } 504 505 mSettingsObserver.observe( 506 Settings.Global.getUriFor(Settings.Global.DATA_ROAMING + simSuffix), 507 DctConstants.EVENT_ROAMING_SETTING_CHANGE); 508 mSettingsObserver.observe( 509 Settings.Global.getUriFor(Settings.Global.DEVICE_PROVISIONED), 510 DctConstants.EVENT_DEVICE_PROVISIONED_CHANGE); 511 } 512 513 /** 514 * Maintain the sum of transmit and receive packets. 515 * 516 * The packet counts are initialized and reset to -1 and 517 * remain -1 until they can be updated. 518 */ 519 public static class TxRxSum { 520 public long txPkts; 521 public long rxPkts; 522 TxRxSum()523 public TxRxSum() { 524 reset(); 525 } 526 TxRxSum(long txPkts, long rxPkts)527 public TxRxSum(long txPkts, long rxPkts) { 528 this.txPkts = txPkts; 529 this.rxPkts = rxPkts; 530 } 531 TxRxSum(TxRxSum sum)532 public TxRxSum(TxRxSum sum) { 533 txPkts = sum.txPkts; 534 rxPkts = sum.rxPkts; 535 } 536 reset()537 public void reset() { 538 txPkts = -1; 539 rxPkts = -1; 540 } 541 542 @Override toString()543 public String toString() { 544 return "{txSum=" + txPkts + " rxSum=" + rxPkts + "}"; 545 } 546 547 /** 548 * Get total Tx/Rx packet count from TrafficStats 549 */ updateTotalTxRxSum()550 public void updateTotalTxRxSum() { 551 this.txPkts = TrafficStats.getMobileTxPackets(); 552 this.rxPkts = TrafficStats.getMobileRxPackets(); 553 } 554 } 555 onDataReconnect(ApnContext apnContextforRetry, int subId, @RequestNetworkType int requestType)556 private void onDataReconnect(ApnContext apnContextforRetry, int subId, 557 @RequestNetworkType int requestType) { 558 int phoneSubId = mPhone.getSubId(); 559 String apnType = apnContextforRetry.getApnType(); 560 String reason = apnContextforRetry.getReason(); 561 562 if (!SubscriptionManager.isValidSubscriptionId(subId) || (subId != phoneSubId)) { 563 log("onDataReconnect: invalid subId"); 564 return; 565 } 566 567 ApnContext apnContext = mApnContexts.get(apnType); 568 569 if (DBG) { 570 log("onDataReconnect: mState=" + mState + " reason=" + reason + " apnType=" + apnType 571 + " apnContext=" + apnContext); 572 } 573 574 if ((apnContext != null) && (apnContext.isEnabled())) { 575 apnContext.setReason(reason); 576 DctConstants.State apnContextState = apnContext.getState(); 577 if (DBG) { 578 log("onDataReconnect: apnContext state=" + apnContextState); 579 } 580 if ((apnContextState == DctConstants.State.FAILED) 581 || (apnContextState == DctConstants.State.IDLE)) { 582 if (DBG) { 583 log("onDataReconnect: state is FAILED|IDLE, disassociate"); 584 } 585 apnContext.releaseDataConnection(""); 586 } else { 587 if (DBG) log("onDataReconnect: keep associated"); 588 } 589 // TODO: IF already associated should we send the EVENT_TRY_SETUP_DATA??? 590 sendMessage(obtainMessage(DctConstants.EVENT_TRY_SETUP_DATA, requestType, 591 0, apnContext)); 592 } 593 } 594 onActionIntentDataStallAlarm(Intent intent)595 private void onActionIntentDataStallAlarm(Intent intent) { 596 if (VDBG_STALL) log("onActionIntentDataStallAlarm: action=" + intent.getAction()); 597 598 int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY, 599 SubscriptionManager.INVALID_SUBSCRIPTION_ID); 600 if (!SubscriptionManager.isValidSubscriptionId(subId) || (subId != mPhone.getSubId())) { 601 return; 602 } 603 604 int transportType = intent.getIntExtra(INTENT_DATA_STALL_ALARM_EXTRA_TRANSPORT_TYPE, 0); 605 if (transportType != mTransportType) { 606 return; 607 } 608 609 Message msg = obtainMessage(DctConstants.EVENT_DATA_STALL_ALARM, 610 intent.getAction()); 611 msg.arg1 = intent.getIntExtra(INTENT_DATA_STALL_ALARM_EXTRA_TAG, 0); 612 sendMessage(msg); 613 } 614 615 private RegistrantList mAllDataDisconnectedRegistrants = new RegistrantList(); 616 617 // member variables 618 protected final Phone mPhone; 619 private DctConstants.Activity mActivity = DctConstants.Activity.NONE; 620 private DctConstants.State mState = DctConstants.State.IDLE; 621 private final Handler mDataConnectionTracker; 622 623 private long mTxPkts; 624 private long mRxPkts; 625 private int mNetStatPollPeriod; 626 private boolean mNetStatPollEnabled = false; 627 628 private TxRxSum mDataStallTxRxSum = new TxRxSum(0, 0); 629 // Used to track stale data stall alarms. 630 private int mDataStallAlarmTag = (int) SystemClock.elapsedRealtime(); 631 // The current data stall alarm intent 632 private PendingIntent mDataStallAlarmIntent = null; 633 // Number of packets sent since the last received packet 634 private long mSentSinceLastRecv; 635 // Controls when a simple recovery attempt it to be tried 636 private int mNoRecvPollCount = 0; 637 // Reference counter for enabling fail fast 638 private static int sEnableFailFastRefCounter = 0; 639 // True if data stall detection is enabled 640 private volatile boolean mDataStallNoRxEnabled = true; 641 642 protected volatile boolean mFailFast = false; 643 644 // True when in voice call 645 protected boolean mInVoiceCall = false; 646 647 /** Intent sent when the reconnect alarm fires. */ 648 private PendingIntent mReconnectIntent = null; 649 650 // When false we will not auto attach and manually attaching is required. 651 protected boolean mAutoAttachOnCreationConfig = false; 652 private AtomicBoolean mAutoAttachEnabled = new AtomicBoolean(false); 653 654 // State of screen 655 // (TODO: Reconsider tying directly to screen, maybe this is 656 // really a lower power mode") 657 private boolean mIsScreenOn = true; 658 659 /** Allows the generation of unique Id's for DataConnection objects */ 660 private AtomicInteger mUniqueIdGenerator = new AtomicInteger(0); 661 662 /** The data connections. */ 663 private HashMap<Integer, DataConnection> mDataConnections = 664 new HashMap<Integer, DataConnection>(); 665 666 /** Convert an ApnType string to Id (TODO: Use "enumeration" instead of String for ApnType) */ 667 private HashMap<String, Integer> mApnToDataConnectionId = new HashMap<String, Integer>(); 668 669 /** Phone.APN_TYPE_* ===> ApnContext */ 670 protected ConcurrentHashMap<String, ApnContext> mApnContexts = 671 new ConcurrentHashMap<String, ApnContext>(); 672 673 private SparseArray<ApnContext> mApnContextsByType = new SparseArray<ApnContext>(); 674 675 private ArrayList<DataProfile> mLastDataProfileList = new ArrayList<>(); 676 677 /** RAT name ===> (downstream, upstream) bandwidth values from carrier config. */ 678 private ConcurrentHashMap<String, Pair<Integer, Integer>> mBandwidths = 679 new ConcurrentHashMap<>(); 680 681 private boolean mConfigReady = false; 682 683 /** 684 * Handles changes to the APN db. 685 */ 686 private class ApnChangeObserver extends ContentObserver { ApnChangeObserver()687 public ApnChangeObserver () { 688 super(mDataConnectionTracker); 689 } 690 691 @Override onChange(boolean selfChange)692 public void onChange(boolean selfChange) { 693 sendMessage(obtainMessage(DctConstants.EVENT_APN_CHANGED)); 694 } 695 } 696 697 //***** Instance Variables 698 699 private boolean mReregisterOnReconnectFailure = false; 700 701 702 //***** Constants 703 704 private static final int PROVISIONING_SPINNER_TIMEOUT_MILLIS = 120 * 1000; 705 706 static final Uri PREFERAPN_NO_UPDATE_URI_USING_SUBID = 707 Uri.parse("content://telephony/carriers/preferapn_no_update/subId/"); 708 static final String APN_ID = "apn_id"; 709 710 private boolean mCanSetPreferApn = false; 711 712 private AtomicBoolean mAttached = new AtomicBoolean(false); 713 714 /** Watches for changes to the APN db. */ 715 private ApnChangeObserver mApnObserver; 716 717 private BroadcastReceiver mProvisionBroadcastReceiver; 718 private ProgressDialog mProvisioningSpinner; 719 720 private final DataServiceManager mDataServiceManager; 721 722 @AccessNetworkConstants.TransportType 723 private final int mTransportType; 724 725 private DataStallRecoveryHandler mDsRecoveryHandler; 726 private HandlerThread mHandlerThread; 727 728 private final DataThrottler mDataThrottler; 729 730 private final ThrottleStatusChangedCallback mThrottleStatusCallback; 731 732 /** 733 * Request network completion message map. Key is the APN type, value is the list of completion 734 * messages to be sent. Using a list because there might be multiple network requests for 735 * the same APN type. 736 */ 737 private final Map<Integer, List<Message>> mHandoverCompletionMsgs = new HashMap<>(); 738 739 //***** Constructor DcTracker(Phone phone, @TransportType int transportType)740 public DcTracker(Phone phone, @TransportType int transportType) { 741 super(); 742 mPhone = phone; 743 if (DBG) log("DCT.constructor"); 744 mTelephonyManager = TelephonyManager.from(phone.getContext()) 745 .createForSubscriptionId(phone.getSubId()); 746 // The 'C' in tag indicates cellular, and 'I' indicates IWLAN. This is to distinguish 747 // between two DcTrackers, one for each. 748 String tagSuffix = "-" + ((transportType == AccessNetworkConstants.TRANSPORT_TYPE_WWAN) 749 ? "C" : "I"); 750 tagSuffix += "-" + mPhone.getPhoneId(); 751 mLogTag = "DCT" + tagSuffix; 752 753 mTransportType = transportType; 754 mDataServiceManager = new DataServiceManager(phone, transportType, tagSuffix); 755 mDataThrottler = new DataThrottler(mPhone, transportType); 756 757 mResolver = mPhone.getContext().getContentResolver(); 758 mAlarmManager = 759 (AlarmManager) mPhone.getContext().getSystemService(Context.ALARM_SERVICE); 760 761 mDsRecoveryHandler = new DataStallRecoveryHandler(); 762 763 IntentFilter filter = new IntentFilter(); 764 filter.addAction(Intent.ACTION_SCREEN_ON); 765 filter.addAction(Intent.ACTION_SCREEN_OFF); 766 filter.addAction(INTENT_DATA_STALL_ALARM); 767 filter.addAction(INTENT_PROVISIONING_APN_ALARM); 768 filter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED); 769 filter.addAction(TelephonyManager.ACTION_SIM_CARD_STATE_CHANGED); 770 filter.addAction(TelephonyManager.ACTION_SIM_APPLICATION_STATE_CHANGED); 771 772 mDataEnabledSettings = mPhone.getDataEnabledSettings(); 773 774 mDataEnabledSettings.registerForDataEnabledChanged(this, 775 DctConstants.EVENT_DATA_ENABLED_CHANGED, null); 776 mDataEnabledSettings.registerForDataEnabledOverrideChanged(this, 777 DctConstants.EVENT_DATA_ENABLED_OVERRIDE_RULES_CHANGED); 778 779 mPhone.getContext().registerReceiver(mIntentReceiver, filter, null, mPhone); 780 781 SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mPhone.getContext()); 782 mAutoAttachEnabled.set(sp.getBoolean(Phone.DATA_DISABLED_ON_BOOT_KEY, false)); 783 784 mNetworkPolicyManager = (NetworkPolicyManager) mPhone.getContext() 785 .getSystemService(Context.NETWORK_POLICY_SERVICE); 786 mNetworkPolicyManager.registerSubscriptionCallback(mSubscriptionCallback); 787 788 mHandlerThread = new HandlerThread("DcHandlerThread"); 789 mHandlerThread.start(); 790 Handler dcHandler = new Handler(mHandlerThread.getLooper()); 791 mDcc = DcController.makeDcc(mPhone, this, mDataServiceManager, dcHandler.getLooper(), 792 tagSuffix); 793 mDcTesterFailBringUpAll = new DcTesterFailBringUpAll(mPhone, dcHandler); 794 795 mDataConnectionTracker = this; 796 registerForAllEvents(); 797 mApnObserver = new ApnChangeObserver(); 798 phone.getContext().getContentResolver().registerContentObserver( 799 Telephony.Carriers.CONTENT_URI, true, mApnObserver); 800 801 initApnContexts(); 802 803 addDefaultApnSettingsAsNeeded(); 804 805 mSettingsObserver = new SettingsObserver(mPhone.getContext(), this); 806 registerSettingsObserver(); 807 808 mThrottleStatusCallback = new ThrottleStatusChangedCallback(); 809 mDataThrottler.registerForThrottleStatusChanges(mThrottleStatusCallback); 810 } 811 812 @VisibleForTesting DcTracker()813 public DcTracker() { 814 mLogTag = "DCT"; 815 mTelephonyManager = null; 816 mAlarmManager = null; 817 mPhone = null; 818 mDataConnectionTracker = null; 819 mSettingsObserver = new SettingsObserver(null, this); 820 mDataEnabledSettings = null; 821 mTransportType = 0; 822 mDataServiceManager = null; 823 mDataThrottler = null; 824 mThrottleStatusCallback = null; 825 } 826 registerServiceStateTrackerEvents()827 public void registerServiceStateTrackerEvents() { 828 mPhone.getServiceStateTracker().registerForDataConnectionAttached(mTransportType, this, 829 DctConstants.EVENT_DATA_CONNECTION_ATTACHED, null); 830 mPhone.getServiceStateTracker().registerForDataConnectionDetached(mTransportType, this, 831 DctConstants.EVENT_DATA_CONNECTION_DETACHED, null); 832 mPhone.getServiceStateTracker().registerForDataRoamingOn(this, 833 DctConstants.EVENT_ROAMING_ON, null); 834 mPhone.getServiceStateTracker().registerForDataRoamingOff(this, 835 DctConstants.EVENT_ROAMING_OFF, null, true); 836 mPhone.getServiceStateTracker().registerForPsRestrictedEnabled(this, 837 DctConstants.EVENT_PS_RESTRICT_ENABLED, null); 838 mPhone.getServiceStateTracker().registerForPsRestrictedDisabled(this, 839 DctConstants.EVENT_PS_RESTRICT_DISABLED, null); 840 mPhone.getServiceStateTracker().registerForDataRegStateOrRatChanged(mTransportType, this, 841 DctConstants.EVENT_DATA_RAT_CHANGED, null); 842 } 843 unregisterServiceStateTrackerEvents()844 public void unregisterServiceStateTrackerEvents() { 845 mPhone.getServiceStateTracker().unregisterForDataConnectionAttached(mTransportType, this); 846 mPhone.getServiceStateTracker().unregisterForDataConnectionDetached(mTransportType, this); 847 mPhone.getServiceStateTracker().unregisterForDataRoamingOn(this); 848 mPhone.getServiceStateTracker().unregisterForDataRoamingOff(this); 849 mPhone.getServiceStateTracker().unregisterForPsRestrictedEnabled(this); 850 mPhone.getServiceStateTracker().unregisterForPsRestrictedDisabled(this); 851 mPhone.getServiceStateTracker().unregisterForDataRegStateOrRatChanged(mTransportType, this); 852 mPhone.getServiceStateTracker().unregisterForAirplaneModeChanged(this); 853 } 854 registerForAllEvents()855 private void registerForAllEvents() { 856 if (mTransportType == AccessNetworkConstants.TRANSPORT_TYPE_WWAN) { 857 mPhone.mCi.registerForAvailable(this, DctConstants.EVENT_RADIO_AVAILABLE, null); 858 mPhone.mCi.registerForOffOrNotAvailable(this, 859 DctConstants.EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null); 860 mPhone.mCi.registerForPcoData(this, DctConstants.EVENT_PCO_DATA_RECEIVED, null); 861 } 862 863 // Note, this is fragile - the Phone is now presenting a merged picture 864 // of PS (volte) & CS and by diving into its internals you're just seeing 865 // the CS data. This works well for the purposes this is currently used for 866 // but that may not always be the case. Should probably be redesigned to 867 // accurately reflect what we're really interested in (registerForCSVoiceCallEnded). 868 mPhone.getCallTracker().registerForVoiceCallEnded(this, 869 DctConstants.EVENT_VOICE_CALL_ENDED, null); 870 mPhone.getCallTracker().registerForVoiceCallStarted(this, 871 DctConstants.EVENT_VOICE_CALL_STARTED, null); 872 mPhone.getDisplayInfoController().registerForTelephonyDisplayInfoChanged(this, 873 DctConstants.EVENT_TELEPHONY_DISPLAY_INFO_CHANGED, null); 874 registerServiceStateTrackerEvents(); 875 mDataServiceManager.registerForServiceBindingChanged(this, 876 DctConstants.EVENT_DATA_SERVICE_BINDING_CHANGED, null); 877 mDataServiceManager.registerForApnUnthrottled(this, DctConstants.EVENT_APN_UNTHROTTLED); 878 } 879 dispose()880 public void dispose() { 881 if (DBG) log("DCT.dispose"); 882 883 if (mProvisionBroadcastReceiver != null) { 884 mPhone.getContext().unregisterReceiver(mProvisionBroadcastReceiver); 885 mProvisionBroadcastReceiver = null; 886 } 887 if (mProvisioningSpinner != null) { 888 mProvisioningSpinner.dismiss(); 889 mProvisioningSpinner = null; 890 } 891 892 cleanUpAllConnectionsInternal(true, null); 893 894 mIsDisposed = true; 895 mPhone.getContext().unregisterReceiver(mIntentReceiver); 896 mSettingsObserver.unobserve(); 897 898 mNetworkPolicyManager.unregisterSubscriptionCallback(mSubscriptionCallback); 899 mDcTesterFailBringUpAll.dispose(); 900 901 mPhone.getContext().getContentResolver().unregisterContentObserver(mApnObserver); 902 mApnContexts.clear(); 903 mApnContextsByType.clear(); 904 mPrioritySortedApnContexts.clear(); 905 unregisterForAllEvents(); 906 907 destroyDataConnections(); 908 } 909 910 /** 911 * Stop the internal handler thread 912 * 913 * TESTING ONLY 914 */ 915 @VisibleForTesting stopHandlerThread()916 public void stopHandlerThread() { 917 mHandlerThread.quit(); 918 } 919 unregisterForAllEvents()920 private void unregisterForAllEvents() { 921 //Unregister for all events 922 if (mTransportType == AccessNetworkConstants.TRANSPORT_TYPE_WWAN) { 923 mPhone.mCi.unregisterForAvailable(this); 924 mPhone.mCi.unregisterForOffOrNotAvailable(this); 925 mPhone.mCi.unregisterForPcoData(this); 926 } 927 928 mPhone.getCallTracker().unregisterForVoiceCallEnded(this); 929 mPhone.getCallTracker().unregisterForVoiceCallStarted(this); 930 mPhone.getDisplayInfoController().unregisterForTelephonyDisplayInfoChanged(this); 931 unregisterServiceStateTrackerEvents(); 932 mDataServiceManager.unregisterForServiceBindingChanged(this); 933 mDataEnabledSettings.unregisterForDataEnabledChanged(this); 934 mDataEnabledSettings.unregisterForDataEnabledOverrideChanged(this); 935 mDataServiceManager.unregisterForApnUnthrottled(this); 936 } 937 938 /** 939 * Reevaluate existing data connections when conditions change. 940 * 941 * For example, handle reverting restricted networks back to unrestricted. If we're changing 942 * user data to enabled and this makes data truly enabled (not disabled by other factors) we 943 * need to reevaluate and possibly add NET_CAPABILITY_NOT_RESTRICTED capability to the data 944 * connection. This allows non-privilege apps to use the network. 945 * 946 * Or when we brought up a unmetered data connection while data is off, we only limit this 947 * data connection for unmetered use only. When data is turned back on, we need to tear that 948 * down so a full capable data connection can be re-established. 949 */ reevaluateDataConnections()950 private void reevaluateDataConnections() { 951 for (DataConnection dataConnection : mDataConnections.values()) { 952 dataConnection.reevaluateRestrictedState(); 953 } 954 } 955 getSubId()956 public long getSubId() { 957 return mPhone.getSubId(); 958 } 959 getActivity()960 public DctConstants.Activity getActivity() { 961 return mActivity; 962 } 963 setActivity(DctConstants.Activity activity)964 private void setActivity(DctConstants.Activity activity) { 965 log("setActivity = " + activity); 966 mActivity = activity; 967 mPhone.notifyDataActivity(); 968 } 969 970 /** 971 * Request a network 972 * 973 * @param networkRequest Network request from clients 974 * @param type The request type 975 * @param onHandoverCompleteMsg When request type is handover, this message will be sent when 976 * handover is completed. For normal request, this should be null. 977 */ requestNetwork(NetworkRequest networkRequest, @RequestNetworkType int type, Message onHandoverCompleteMsg)978 public void requestNetwork(NetworkRequest networkRequest, @RequestNetworkType int type, 979 Message onHandoverCompleteMsg) { 980 if (type != REQUEST_TYPE_HANDOVER && onHandoverCompleteMsg != null) { 981 throw new RuntimeException("request network with normal type request type but passing " 982 + "handover complete message."); 983 } 984 final int apnType = ApnContext.getApnTypeFromNetworkRequest(networkRequest); 985 final ApnContext apnContext = mApnContextsByType.get(apnType); 986 if (apnContext != null) { 987 apnContext.requestNetwork(networkRequest, type, onHandoverCompleteMsg); 988 } 989 } 990 releaseNetwork(NetworkRequest networkRequest, @ReleaseNetworkType int type)991 public void releaseNetwork(NetworkRequest networkRequest, @ReleaseNetworkType int type) { 992 final int apnType = ApnContext.getApnTypeFromNetworkRequest(networkRequest); 993 final ApnContext apnContext = mApnContextsByType.get(apnType); 994 if (apnContext != null) { 995 apnContext.releaseNetwork(networkRequest, type); 996 } 997 } 998 999 // Turn telephony radio on or off. setRadio(boolean on)1000 private void setRadio(boolean on) { 1001 final ITelephony phone = ITelephony.Stub.asInterface( 1002 TelephonyFrameworkInitializer 1003 .getTelephonyServiceManager() 1004 .getTelephonyServiceRegisterer() 1005 .get()); 1006 try { 1007 phone.setRadio(on); 1008 } catch (Exception e) { 1009 // Ignore. 1010 } 1011 } 1012 1013 // Class to handle Intent dispatched with user selects the "Sign-in to network" 1014 // notification. 1015 private class ProvisionNotificationBroadcastReceiver extends BroadcastReceiver { 1016 private final String mNetworkOperator; 1017 // Mobile provisioning URL. Valid while provisioning notification is up. 1018 // Set prior to notification being posted as URL contains ICCID which 1019 // disappears when radio is off (which is the case when notification is up). 1020 private final String mProvisionUrl; 1021 ProvisionNotificationBroadcastReceiver(String provisionUrl, String networkOperator)1022 public ProvisionNotificationBroadcastReceiver(String provisionUrl, String networkOperator) { 1023 mNetworkOperator = networkOperator; 1024 mProvisionUrl = provisionUrl; 1025 } 1026 setEnableFailFastMobileData(int enabled)1027 private void setEnableFailFastMobileData(int enabled) { 1028 sendMessage(obtainMessage(DctConstants.CMD_SET_ENABLE_FAIL_FAST_MOBILE_DATA, enabled, 0)); 1029 } 1030 enableMobileProvisioning()1031 private void enableMobileProvisioning() { 1032 final Message msg = obtainMessage(DctConstants.CMD_ENABLE_MOBILE_PROVISIONING); 1033 Bundle bundle = new Bundle(1); 1034 bundle.putString(DctConstants.PROVISIONING_URL_KEY, mProvisionUrl); 1035 msg.setData(bundle); 1036 sendMessage(msg); 1037 } 1038 1039 @Override onReceive(Context context, Intent intent)1040 public void onReceive(Context context, Intent intent) { 1041 if (mPhone.getPhoneId() != intent.getIntExtra(EXTRA_PROVISION_PHONE_ID, 1042 SubscriptionManager.INVALID_PHONE_INDEX)) { 1043 return; 1044 } 1045 // Turning back on the radio can take time on the order of a minute, so show user a 1046 // spinner so they know something is going on. 1047 log("onReceive : ProvisionNotificationBroadcastReceiver"); 1048 mProvisioningSpinner = new ProgressDialog(context); 1049 mProvisioningSpinner.setTitle(mNetworkOperator); 1050 mProvisioningSpinner.setMessage( 1051 // TODO: Don't borrow "Connecting..." i18n string; give Telephony a version. 1052 context.getText(com.android.internal.R.string.media_route_status_connecting)); 1053 mProvisioningSpinner.setIndeterminate(true); 1054 mProvisioningSpinner.setCancelable(true); 1055 // Allow non-Activity Service Context to create a View. 1056 mProvisioningSpinner.getWindow().setType( 1057 WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG); 1058 mProvisioningSpinner.show(); 1059 // After timeout, hide spinner so user can at least use their device. 1060 // TODO: Indicate to user that it is taking an unusually long time to connect? 1061 sendMessageDelayed(obtainMessage(DctConstants.CMD_CLEAR_PROVISIONING_SPINNER, 1062 mProvisioningSpinner), PROVISIONING_SPINNER_TIMEOUT_MILLIS); 1063 // This code is almost identical to the old 1064 // ConnectivityService.handleMobileProvisioningAction code. 1065 setRadio(true); 1066 setEnableFailFastMobileData(DctConstants.ENABLED); 1067 enableMobileProvisioning(); 1068 } 1069 } 1070 1071 @Override finalize()1072 protected void finalize() { 1073 if(DBG && mPhone != null) log("finalize"); 1074 } 1075 initApnContexts()1076 private void initApnContexts() { 1077 PersistableBundle carrierConfig; 1078 CarrierConfigManager configManager = (CarrierConfigManager) mPhone.getContext() 1079 .getSystemService(Context.CARRIER_CONFIG_SERVICE); 1080 if (configManager != null) { 1081 carrierConfig = configManager.getConfigForSubId(mPhone.getSubId()); 1082 } else { 1083 carrierConfig = null; 1084 } 1085 initApnContexts(carrierConfig); 1086 } 1087 1088 //Blows away any existing apncontexts that may exist, only use in ctor. initApnContexts(PersistableBundle carrierConfig)1089 private void initApnContexts(PersistableBundle carrierConfig) { 1090 if (!mTelephonyManager.isDataCapable()) { 1091 log("initApnContexts: isDataCapable == false. No Apn Contexts loaded"); 1092 return; 1093 } 1094 1095 log("initApnContexts: E"); 1096 // Load device network attributes from resources 1097 final Collection<ApnConfigType> types = 1098 new ApnConfigTypeRepository(carrierConfig).getTypes(); 1099 1100 for (ApnConfigType apnConfigType : types) { 1101 ApnContext apnContext = new ApnContext(mPhone, apnConfigType.getType(), mLogTag, this, 1102 apnConfigType.getPriority()); 1103 int bitmask = ApnSetting.getApnTypesBitmaskFromString(apnContext.getApnType()); 1104 mPrioritySortedApnContexts.add(apnContext); 1105 mApnContexts.put(apnContext.getApnType(), apnContext); 1106 mApnContextsByType.put(bitmask, apnContext); 1107 // Notify listeners that all data is disconnected when DCT is initialized. 1108 // Once connections are established, DC will then notify that data is connected. 1109 // This is to prevent the case where the phone process crashed but we don't notify 1110 // listeners that data was disconnected, so they may be stuck in a connected state. 1111 mPhone.notifyDataConnection(new PreciseDataConnectionState.Builder() 1112 .setTransportType(mTransportType) 1113 .setState(TelephonyManager.DATA_DISCONNECTED) 1114 .setApnSetting(new ApnSetting.Builder() 1115 .setApnTypeBitmask(bitmask).buildWithoutCheck()) 1116 .setNetworkType(getDataRat()) 1117 .build()); 1118 log("initApnContexts: apnContext=" + ApnSetting.getApnTypeString( 1119 apnConfigType.getType())); 1120 } 1121 mPrioritySortedApnContexts.sort((c1, c2) -> c2.getPriority() - c1.getPriority()); 1122 logSortedApnContexts(); 1123 } 1124 sortApnContextByPriority()1125 private void sortApnContextByPriority() { 1126 if (!mTelephonyManager.isDataCapable()) { 1127 log("sortApnContextByPriority: isDataCapable == false. No Apn Contexts loaded"); 1128 return; 1129 } 1130 1131 PersistableBundle carrierConfig; 1132 CarrierConfigManager configManager = (CarrierConfigManager) mPhone.getContext() 1133 .getSystemService(Context.CARRIER_CONFIG_SERVICE); 1134 if (configManager != null) { 1135 carrierConfig = configManager.getConfigForSubId(mPhone.getSubId()); 1136 } else { 1137 carrierConfig = null; 1138 } 1139 1140 log("sortApnContextByPriority: E"); 1141 // Load device network attributes from resources 1142 final Collection<ApnConfigType> types = 1143 new ApnConfigTypeRepository(carrierConfig).getTypes(); 1144 for (ApnConfigType apnConfigType : types) { 1145 if (mApnContextsByType.contains(apnConfigType.getType())) { 1146 ApnContext apnContext = mApnContextsByType.get(apnConfigType.getType()); 1147 apnContext.setPriority(apnConfigType.getPriority()); 1148 } 1149 } 1150 1151 //Doing sorted in a different list to keep thread safety 1152 ArrayList<ApnContext> prioritySortedApnContexts = 1153 new ArrayList<>(mPrioritySortedApnContexts); 1154 prioritySortedApnContexts.sort((c1, c2) -> c2.getPriority() - c1.getPriority()); 1155 mPrioritySortedApnContexts = prioritySortedApnContexts; 1156 logSortedApnContexts(); 1157 } 1158 getLinkProperties(String apnType)1159 public LinkProperties getLinkProperties(String apnType) { 1160 ApnContext apnContext = mApnContexts.get(apnType); 1161 if (apnContext != null) { 1162 DataConnection dataConnection = apnContext.getDataConnection(); 1163 if (dataConnection != null) { 1164 if (DBG) log("return link properties for " + apnType); 1165 return dataConnection.getLinkProperties(); 1166 } 1167 } 1168 if (DBG) log("return new LinkProperties"); 1169 return new LinkProperties(); 1170 } 1171 getNetworkCapabilities(String apnType)1172 public NetworkCapabilities getNetworkCapabilities(String apnType) { 1173 ApnContext apnContext = mApnContexts.get(apnType); 1174 if (apnContext!=null) { 1175 DataConnection dataConnection = apnContext.getDataConnection(); 1176 if (dataConnection != null) { 1177 if (DBG) { 1178 log("get active pdp is not null, return NetworkCapabilities for " + apnType); 1179 } 1180 return dataConnection.getNetworkCapabilities(); 1181 } 1182 } 1183 if (DBG) log("return new NetworkCapabilities"); 1184 return new NetworkCapabilities(); 1185 } 1186 1187 // Return all active apn types getActiveApnTypes()1188 public String[] getActiveApnTypes() { 1189 if (DBG) log("get all active apn types"); 1190 ArrayList<String> result = new ArrayList<String>(); 1191 1192 for (ApnContext apnContext : mApnContexts.values()) { 1193 if (mAttached.get() && apnContext.isReady()) { 1194 result.add(apnContext.getApnType()); 1195 } 1196 } 1197 1198 return result.toArray(new String[0]); 1199 } 1200 1201 /** 1202 * Get ApnTypes with connected data connections. This is different than getActiveApnTypes() 1203 * which returns apn types that with active apn contexts. 1204 * @return apn types 1205 */ getConnectedApnTypes()1206 public String[] getConnectedApnTypes() { 1207 return mApnContexts.values().stream() 1208 .filter(ac -> ac.getState() == DctConstants.State.CONNECTED) 1209 .map(ApnContext::getApnType) 1210 .toArray(String[]::new); 1211 } 1212 1213 @VisibleForTesting getApnContexts()1214 public Collection<ApnContext> getApnContexts() { 1215 return mPrioritySortedApnContexts; 1216 } 1217 1218 /** Return active ApnSetting of a specific apnType */ getActiveApnSetting(String apnType)1219 public ApnSetting getActiveApnSetting(String apnType) { 1220 if (VDBG) log("get active ApnSetting for type:" + apnType); 1221 ApnContext apnContext = mApnContexts.get(apnType); 1222 return (apnContext != null) ? apnContext.getApnSetting() : null; 1223 } 1224 1225 // Return active apn of specific apn type getActiveApnString(String apnType)1226 public String getActiveApnString(String apnType) { 1227 if (VDBG) log( "get active apn string for type:" + apnType); 1228 ApnSetting setting = getActiveApnSetting(apnType); 1229 return (setting != null) ? setting.getApnName() : null; 1230 } 1231 1232 /** 1233 * Returns {@link DctConstants.State} based on the state of the {@link DataConnection} that 1234 * contains a {@link ApnSetting} that supported the given apn type {@code anpType}. 1235 * 1236 * <p> 1237 * Assumes there is less than one {@link ApnSetting} can support the given apn type. 1238 */ 1239 // TODO: for enterprise this always returns IDLE, which is ok for now since it is never called 1240 // for enterprise getState(String apnType)1241 public DctConstants.State getState(String apnType) { 1242 DctConstants.State state = DctConstants.State.IDLE; 1243 final int apnTypeBitmask = ApnSetting.getApnTypesBitmaskFromString(apnType); 1244 for (DataConnection dc : mDataConnections.values()) { 1245 ApnSetting apnSetting = dc.getApnSetting(); 1246 if (apnSetting != null && apnSetting.canHandleType(apnTypeBitmask)) { 1247 if (dc.isActive()) { 1248 state = getBetterConnectionState(state, DctConstants.State.CONNECTED); 1249 } else if (dc.isActivating()) { 1250 state = getBetterConnectionState(state, DctConstants.State.CONNECTING); 1251 } else if (dc.isInactive()) { 1252 state = getBetterConnectionState(state, DctConstants.State.IDLE); 1253 } else if (dc.isDisconnecting()) { 1254 state = getBetterConnectionState(state, DctConstants.State.DISCONNECTING); 1255 } 1256 } 1257 } 1258 return state; 1259 } 1260 1261 /** 1262 * Return a better connection state between {@code stateA} and {@code stateB}. Check 1263 * {@link #DATA_CONNECTION_STATE_PRIORITIES} for the details. 1264 * @return the better connection state between {@code stateA} and {@code stateB}. 1265 */ getBetterConnectionState( DctConstants.State stateA, DctConstants.State stateB)1266 private static DctConstants.State getBetterConnectionState( 1267 DctConstants.State stateA, DctConstants.State stateB) { 1268 int idxA = ArrayUtils.indexOf(DATA_CONNECTION_STATE_PRIORITIES, stateA); 1269 int idxB = ArrayUtils.indexOf(DATA_CONNECTION_STATE_PRIORITIES, stateB); 1270 return idxA >= idxB ? stateA : stateB; 1271 } 1272 1273 // Return if apn type is a provisioning apn. isProvisioningApn(String apnType)1274 private boolean isProvisioningApn(String apnType) { 1275 ApnContext apnContext = mApnContexts.get(apnType); 1276 if (apnContext != null) { 1277 return apnContext.isProvisioningApn(); 1278 } 1279 return false; 1280 } 1281 1282 //****** Called from ServiceStateTracker 1283 /** 1284 * Invoked when ServiceStateTracker observes a transition from GPRS 1285 * attach to detach. 1286 */ onDataConnectionDetached()1287 private void onDataConnectionDetached() { 1288 /* 1289 * We presently believe it is unnecessary to tear down the PDP context 1290 * when GPRS detaches, but we should stop the network polling. 1291 */ 1292 if (DBG) log ("onDataConnectionDetached: stop polling and notify detached"); 1293 stopNetStatPoll(); 1294 stopDataStallAlarm(); 1295 mAttached.set(false); 1296 } 1297 onDataConnectionAttached()1298 private void onDataConnectionAttached() { 1299 if (DBG) log("onDataConnectionAttached"); 1300 mAttached.set(true); 1301 if (isAnyDataConnected()) { 1302 if (DBG) log("onDataConnectionAttached: start polling notify attached"); 1303 startNetStatPoll(); 1304 startDataStallAlarm(DATA_STALL_NOT_SUSPECTED); 1305 } 1306 if (mAutoAttachOnCreationConfig) { 1307 mAutoAttachEnabled.set(true); 1308 } 1309 setupDataOnAllConnectableApns(Phone.REASON_DATA_ATTACHED, RetryFailures.ALWAYS); 1310 } 1311 1312 /** 1313 * Check if it is allowed to make a data connection (without checking APN context specific 1314 * conditions). 1315 * 1316 * @param dataConnectionReasons Data connection allowed or disallowed reasons as the output 1317 * param. It's okay to pass null here and no reasons will be 1318 * provided. 1319 * @return True if data connection is allowed, otherwise false. 1320 */ isDataAllowed(DataConnectionReasons dataConnectionReasons)1321 public boolean isDataAllowed(DataConnectionReasons dataConnectionReasons) { 1322 return isDataAllowed(null, REQUEST_TYPE_NORMAL, dataConnectionReasons); 1323 } 1324 1325 /** 1326 * Check if it is allowed to make a data connection for a given APN type. 1327 * 1328 * @param apnContext APN context. If passing null, then will only check general but not APN 1329 * specific conditions (e.g. APN state, metered/unmetered APN). 1330 * @param requestType Setup data request type. 1331 * @param dataConnectionReasons Data connection allowed or disallowed reasons as the output 1332 * param. It's okay to pass null here and no reasons will be 1333 * provided. 1334 * @return True if data connection is allowed, otherwise false. 1335 */ isDataAllowed(ApnContext apnContext, @RequestNetworkType int requestType, DataConnectionReasons dataConnectionReasons)1336 public boolean isDataAllowed(ApnContext apnContext, @RequestNetworkType int requestType, 1337 DataConnectionReasons dataConnectionReasons) { 1338 // Step 1: Get all environment conditions. 1339 // Step 2: Special handling for emergency APN. 1340 // Step 3. Build disallowed reasons. 1341 // Step 4: Determine if data should be allowed in some special conditions. 1342 1343 DataConnectionReasons reasons = new DataConnectionReasons(); 1344 1345 int requestApnType = 0; 1346 if (apnContext != null) { 1347 requestApnType = apnContext.getApnTypeBitmask(); 1348 } 1349 1350 // Step 1: Get all environment conditions. 1351 final boolean internalDataEnabled = mDataEnabledSettings.isInternalDataEnabled(); 1352 boolean attachedState = mAttached.get(); 1353 boolean desiredPowerState = mPhone.getServiceStateTracker().getDesiredPowerState(); 1354 boolean radioStateFromCarrier = mPhone.getServiceStateTracker().getPowerStateFromCarrier(); 1355 // TODO: Remove this hack added by ag/641832. 1356 int dataRat = getDataRat(); 1357 if (dataRat == ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN) { 1358 desiredPowerState = true; 1359 radioStateFromCarrier = true; 1360 } 1361 1362 boolean defaultDataSelected = SubscriptionManager.isValidSubscriptionId( 1363 SubscriptionManager.getDefaultDataSubscriptionId()); 1364 1365 boolean isMeteredApnType = apnContext == null 1366 || ApnSettingUtils.isMeteredApnType(requestApnType, mPhone); 1367 1368 PhoneConstants.State phoneState = PhoneConstants.State.IDLE; 1369 // Note this is explicitly not using mPhone.getState. See b/19090488. 1370 // mPhone.getState reports the merge of CS and PS (volte) voice call state 1371 // but we only care about CS calls here for data/voice concurrency issues. 1372 // Calling getCallTracker currently gives you just the CS side where the 1373 // ImsCallTracker is held internally where applicable. 1374 // This should be redesigned to ask explicitly what we want: 1375 // voiceCallStateAllowDataCall, or dataCallAllowed or something similar. 1376 if (mPhone.getCallTracker() != null) { 1377 phoneState = mPhone.getCallTracker().getState(); 1378 } 1379 1380 // Step 2: Special handling for emergency APN. 1381 if (apnContext != null 1382 && requestApnType == ApnSetting.TYPE_EMERGENCY 1383 && apnContext.isConnectable()) { 1384 // If this is an emergency APN, as long as the APN is connectable, we 1385 // should allow it. 1386 if (dataConnectionReasons != null) { 1387 dataConnectionReasons.add(DataAllowedReasonType.EMERGENCY_APN); 1388 } 1389 // Bail out without further checks. 1390 return true; 1391 } 1392 1393 // Step 3. Build disallowed reasons. 1394 if (apnContext != null && !apnContext.isConnectable()) { 1395 DctConstants.State state = apnContext.getState(); 1396 if (state == DctConstants.State.CONNECTED) { 1397 reasons.add(DataDisallowedReasonType.DATA_ALREADY_CONNECTED); 1398 } else if (state == DctConstants.State.DISCONNECTING) { 1399 reasons.add(DataDisallowedReasonType.DATA_IS_DISCONNECTING); 1400 } else if (state == DctConstants.State.CONNECTING) { 1401 reasons.add(DataDisallowedReasonType.DATA_IS_CONNECTING); 1402 } else { 1403 reasons.add(DataDisallowedReasonType.APN_NOT_CONNECTABLE); 1404 } 1405 } 1406 1407 // In legacy mode, if RAT is IWLAN then don't allow default/IA PDP at all. 1408 // Rest of APN types can be evaluated for remaining conditions. 1409 if ((apnContext != null && requestApnType == ApnSetting.TYPE_DEFAULT 1410 || requestApnType == ApnSetting.TYPE_ENTERPRISE 1411 || requestApnType == ApnSetting.TYPE_IA) 1412 && mPhone.getAccessNetworksManager().isInLegacyMode() 1413 && dataRat == ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN) { 1414 reasons.add(DataDisallowedReasonType.ON_IWLAN); 1415 } 1416 1417 // If device is not on NR, don't allow enterprise 1418 if (apnContext != null && requestApnType == ApnSetting.TYPE_ENTERPRISE 1419 && dataRat != ServiceState.RIL_RADIO_TECHNOLOGY_NR) { 1420 reasons.add(DataDisallowedReasonType.NOT_ON_NR); 1421 } 1422 1423 if (shouldRestrictDataForEcbm() || mPhone.isInEmergencyCall()) { 1424 reasons.add(DataDisallowedReasonType.IN_ECBM); 1425 } 1426 1427 if (!attachedState && !shouldAutoAttach() && requestType != REQUEST_TYPE_HANDOVER) { 1428 reasons.add(DataDisallowedReasonType.NOT_ATTACHED); 1429 } 1430 if (mPhone.getSubId() == SubscriptionManager.INVALID_SUBSCRIPTION_ID) { 1431 reasons.add(DataDisallowedReasonType.SIM_NOT_READY); 1432 } 1433 if (phoneState != PhoneConstants.State.IDLE 1434 && !mPhone.getServiceStateTracker().isConcurrentVoiceAndDataAllowed()) { 1435 reasons.add(DataDisallowedReasonType.INVALID_PHONE_STATE); 1436 reasons.add(DataDisallowedReasonType.CONCURRENT_VOICE_DATA_NOT_ALLOWED); 1437 } 1438 if (!internalDataEnabled) { 1439 reasons.add(DataDisallowedReasonType.INTERNAL_DATA_DISABLED); 1440 } 1441 if (!defaultDataSelected) { 1442 reasons.add(DataDisallowedReasonType.DEFAULT_DATA_UNSELECTED); 1443 } 1444 if (mPhone.getServiceState().getDataRoaming() && !getDataRoamingEnabled()) { 1445 reasons.add(DataDisallowedReasonType.ROAMING_DISABLED); 1446 } 1447 if (mIsPsRestricted) { 1448 reasons.add(DataDisallowedReasonType.PS_RESTRICTED); 1449 } 1450 if (!desiredPowerState) { 1451 reasons.add(DataDisallowedReasonType.UNDESIRED_POWER_STATE); 1452 } 1453 if (!radioStateFromCarrier) { 1454 reasons.add(DataDisallowedReasonType.RADIO_DISABLED_BY_CARRIER); 1455 } 1456 if (!mDataServiceBound) { 1457 reasons.add(DataDisallowedReasonType.DATA_SERVICE_NOT_READY); 1458 } 1459 1460 if (apnContext != null) { 1461 if (mPhone.getAccessNetworksManager().getPreferredTransport( 1462 apnContext.getApnTypeBitmask()) 1463 == AccessNetworkConstants.TRANSPORT_TYPE_INVALID) { 1464 // If QNS explicitly specified this APN type is not allowed on either cellular or 1465 // IWLAN, we should not allow data setup. 1466 reasons.add(DataDisallowedReasonType.DISABLED_BY_QNS); 1467 } else if (mTransportType != mPhone.getAccessNetworksManager().getPreferredTransport( 1468 apnContext.getApnTypeBitmask())) { 1469 // If the latest preference has already switched to other transport, we should not 1470 // allow data setup. 1471 reasons.add(DataDisallowedReasonType.ON_OTHER_TRANSPORT); 1472 } 1473 1474 // If the transport has been already switched to the other transport, we should not 1475 // allow the data setup. The only exception is the handover case, where we setup 1476 // handover data connection before switching the transport. 1477 if (mTransportType != mPhone.getAccessNetworksManager().getCurrentTransport( 1478 apnContext.getApnTypeBitmask()) && requestType != REQUEST_TYPE_HANDOVER) { 1479 reasons.add(DataDisallowedReasonType.ON_OTHER_TRANSPORT); 1480 } 1481 1482 // Check if the device is under data throttling. 1483 long retryTime = mDataThrottler.getRetryTime(apnContext.getApnTypeBitmask()); 1484 if (retryTime > SystemClock.elapsedRealtime()) { 1485 reasons.add(DataDisallowedReasonType.DATA_THROTTLED); 1486 } 1487 } 1488 1489 boolean isDataEnabled = apnContext == null ? mDataEnabledSettings.isDataEnabled() 1490 : mDataEnabledSettings.isDataEnabled(requestApnType); 1491 1492 if (!isDataEnabled) { 1493 reasons.add(DataDisallowedReasonType.DATA_DISABLED); 1494 } 1495 1496 // If there are hard disallowed reasons, we should not allow data connection no matter what. 1497 if (reasons.containsHardDisallowedReasons()) { 1498 if (dataConnectionReasons != null) { 1499 dataConnectionReasons.copyFrom(reasons); 1500 } 1501 return false; 1502 } 1503 1504 // Step 4: Determine if data should be allowed in some special conditions. 1505 1506 // At this point, if data is not allowed, it must be because of the soft reasons. We 1507 // should start to check some special conditions that data will be allowed. 1508 if (!reasons.allowed()) { 1509 // Check if the transport is WLAN ie wifi (for AP-assisted mode devices) 1510 if (mTransportType == AccessNetworkConstants.TRANSPORT_TYPE_WLAN) { 1511 reasons.add(DataAllowedReasonType.UNMETERED_APN); 1512 // Or if the data is on cellular, and the APN type is determined unmetered by the 1513 // configuration. 1514 } else if (mTransportType == AccessNetworkConstants.TRANSPORT_TYPE_WWAN 1515 && !isMeteredApnType && requestApnType != ApnSetting.TYPE_DEFAULT 1516 && requestApnType != ApnSetting.TYPE_ENTERPRISE) { 1517 reasons.add(DataAllowedReasonType.UNMETERED_APN); 1518 } 1519 1520 // If the request is restricted and there are only soft disallowed reasons (e.g. data 1521 // disabled, data roaming disabled) existing, we should allow the data. ENTERPRISE is 1522 // an exception and should not be treated as restricted for this purpose; it should be 1523 // treated same as DEFAULT. 1524 if (apnContext != null 1525 && apnContext.hasRestrictedRequests(true) 1526 && !apnContext.getApnType().equals(ApnSetting.TYPE_ENTERPRISE_STRING) 1527 && !reasons.allowed()) { 1528 reasons.add(DataAllowedReasonType.RESTRICTED_REQUEST); 1529 } 1530 } else { 1531 // If there is no disallowed reasons, then we should allow the data request with 1532 // normal reason. 1533 reasons.add(DataAllowedReasonType.NORMAL); 1534 } 1535 1536 if (dataConnectionReasons != null) { 1537 dataConnectionReasons.copyFrom(reasons); 1538 } 1539 1540 return reasons.allowed(); 1541 } 1542 1543 // arg for setupDataOnAllConnectableApns 1544 protected enum RetryFailures { 1545 // retry failed networks always (the old default) 1546 ALWAYS, 1547 // retry only when a substantial change has occurred. Either: 1548 // 1) we were restricted by voice/data concurrency and aren't anymore 1549 // 2) our apn list has change 1550 ONLY_ON_CHANGE 1551 }; 1552 setupDataOnAllConnectableApns(String reason, RetryFailures retryFailures)1553 protected void setupDataOnAllConnectableApns(String reason, RetryFailures retryFailures) { 1554 if (VDBG) log("setupDataOnAllConnectableApns: " + reason); 1555 1556 if (DBG && !VDBG) { 1557 StringBuilder sb = new StringBuilder(120); 1558 for (ApnContext apnContext : mPrioritySortedApnContexts) { 1559 sb.append(apnContext.getApnType()); 1560 sb.append(":[state="); 1561 sb.append(apnContext.getState()); 1562 sb.append(",enabled="); 1563 sb.append(apnContext.isEnabled()); 1564 sb.append("] "); 1565 } 1566 log("setupDataOnAllConnectableApns: " + reason + " " + sb); 1567 } 1568 1569 for (ApnContext apnContext : mPrioritySortedApnContexts) { 1570 setupDataOnConnectableApn(apnContext, reason, retryFailures); 1571 } 1572 } 1573 setupDataOnConnectableApn(ApnContext apnContext, String reason, RetryFailures retryFailures)1574 protected void setupDataOnConnectableApn(ApnContext apnContext, String reason, 1575 RetryFailures retryFailures) { 1576 if (VDBG) log("setupDataOnAllConnectableApns: apnContext " + apnContext); 1577 1578 if (apnContext.getState() == DctConstants.State.FAILED 1579 || apnContext.getState() == DctConstants.State.RETRYING) { 1580 if (retryFailures == RetryFailures.ALWAYS) { 1581 apnContext.releaseDataConnection(reason); 1582 } else if (!apnContext.isConcurrentVoiceAndDataAllowed() 1583 && mPhone.getServiceStateTracker().isConcurrentVoiceAndDataAllowed()) { 1584 // RetryFailures.ONLY_ON_CHANGE - check if voice concurrency has changed 1585 apnContext.releaseDataConnection(reason); 1586 } 1587 } 1588 if (apnContext.isConnectable()) { 1589 log("isConnectable() call trySetupData"); 1590 apnContext.setReason(reason); 1591 trySetupData(apnContext, REQUEST_TYPE_NORMAL, null); 1592 } 1593 } 1594 shouldRestrictDataForEcbm()1595 private boolean shouldRestrictDataForEcbm() { 1596 boolean isInEcm = mPhone.isInEcm(); 1597 boolean isInImsEcm = mPhone.getImsPhone() != null && mPhone.getImsPhone().isInImsEcm(); 1598 log("shouldRestrictDataForEcbm: isInEcm=" + isInEcm + " isInImsEcm=" + isInImsEcm); 1599 return isInEcm && !isInImsEcm; 1600 } 1601 isHandoverPending(@pnType int apnType)1602 private boolean isHandoverPending(@ApnType int apnType) { 1603 List<Message> messageList = mHandoverCompletionMsgs.get(apnType); 1604 return messageList != null && messageList.size() > 0; 1605 } 1606 trySetupData(ApnContext apnContext, @RequestNetworkType int requestType, @Nullable Message onHandoverCompleteMsg)1607 private void trySetupData(ApnContext apnContext, @RequestNetworkType int requestType, 1608 @Nullable Message onHandoverCompleteMsg) { 1609 if (onHandoverCompleteMsg != null) { 1610 addHandoverCompleteMsg(onHandoverCompleteMsg, apnContext.getApnTypeBitmask()); 1611 } 1612 1613 if (mPhone.getSimulatedRadioControl() != null) { 1614 // Assume data is connected on the simulator 1615 log("trySetupData: X We're on the simulator; assuming connected retValue=true"); 1616 return; 1617 } 1618 1619 DataConnectionReasons dataConnectionReasons = new DataConnectionReasons(); 1620 boolean isDataAllowed = isDataAllowed(apnContext, requestType, dataConnectionReasons); 1621 String logStr = "trySetupData for APN type " + apnContext.getApnType() + ", reason: " 1622 + apnContext.getReason() + ", requestType=" + requestTypeToString(requestType) 1623 + ". " + dataConnectionReasons.toString(); 1624 if (dataConnectionReasons.contains(DataDisallowedReasonType.DISABLED_BY_QNS) 1625 || dataConnectionReasons.contains(DataDisallowedReasonType.ON_OTHER_TRANSPORT)) { 1626 logStr += ", current transport=" + AccessNetworkConstants.transportTypeToString( 1627 mPhone.getAccessNetworksManager().getCurrentTransport( 1628 apnContext.getApnTypeBitmask())); 1629 logStr += ", preferred transport=" + AccessNetworkConstants.transportTypeToString( 1630 mPhone.getAccessNetworksManager().getPreferredTransport( 1631 apnContext.getApnTypeBitmask())); 1632 } 1633 if (DBG) log(logStr); 1634 ApnContext.requestLog(apnContext, logStr); 1635 if (!isDataAllowed) { 1636 StringBuilder str = new StringBuilder(); 1637 1638 str.append("trySetupData failed. apnContext = [type=" + apnContext.getApnType() 1639 + ", mState=" + apnContext.getState() + ", apnEnabled=" 1640 + apnContext.isEnabled() + ", mDependencyMet=" 1641 + apnContext.isDependencyMet() + "] "); 1642 1643 if (!mDataEnabledSettings.isDataEnabled()) { 1644 str.append("isDataEnabled() = false. " + mDataEnabledSettings); 1645 } 1646 1647 // Check if it fails because of the existing data is still disconnecting. 1648 if (dataConnectionReasons.contains(DataDisallowedReasonType.DATA_IS_DISCONNECTING) 1649 && isHandoverPending(apnContext.getApnTypeBitmask())) { 1650 // Normally we don't retry when isDataAllow() returns false, because that's consider 1651 // pre-condition not met, for example, data not enabled by the user, or airplane 1652 // mode is on. If we retry in those cases, there will be significant power impact. 1653 // DATA_IS_DISCONNECTING is a special case we want to retry, and for the handover 1654 // case only. 1655 log("Data is disconnecting. Will retry handover later."); 1656 return; 1657 } 1658 1659 // If this is a data retry, we should set the APN state to FAILED so it won't stay 1660 // in RETRYING forever. 1661 if (apnContext.getState() == DctConstants.State.RETRYING) { 1662 apnContext.setState(DctConstants.State.FAILED); 1663 str.append(" Stop retrying."); 1664 } 1665 1666 if (DBG) log(str.toString()); 1667 ApnContext.requestLog(apnContext, str.toString()); 1668 if (requestType == REQUEST_TYPE_HANDOVER) { 1669 // If fails due to latest preference already changed back to source transport, then 1670 // just fallback (will not attempt handover anymore, and will not tear down the 1671 // data connection on source transport. 1672 boolean fallback = dataConnectionReasons.contains( 1673 DataDisallowedReasonType.ON_OTHER_TRANSPORT); 1674 sendHandoverCompleteMessages(apnContext.getApnTypeBitmask(), false, fallback); 1675 } 1676 return; 1677 } 1678 1679 if (apnContext.getState() == DctConstants.State.FAILED) { 1680 String str = "trySetupData: make a FAILED ApnContext IDLE so its reusable"; 1681 if (DBG) log(str); 1682 ApnContext.requestLog(apnContext, str); 1683 apnContext.setState(DctConstants.State.IDLE); 1684 } 1685 int radioTech = getDataRat(); 1686 if (radioTech == ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN && mPhone.getServiceState() 1687 .getState() == ServiceState.STATE_IN_SERVICE) { 1688 radioTech = getVoiceRat(); 1689 } 1690 log("service state=" + mPhone.getServiceState()); 1691 apnContext.setConcurrentVoiceAndDataAllowed(mPhone.getServiceStateTracker() 1692 .isConcurrentVoiceAndDataAllowed()); 1693 if (apnContext.getState() == DctConstants.State.IDLE) { 1694 ArrayList<ApnSetting> waitingApns = 1695 buildWaitingApns(apnContext.getApnType(), radioTech); 1696 if (waitingApns.isEmpty()) { 1697 String str = "trySetupData: X No APN found retValue=false"; 1698 if (DBG) log(str); 1699 ApnContext.requestLog(apnContext, str); 1700 if (requestType == REQUEST_TYPE_HANDOVER) { 1701 sendHandoverCompleteMessages(apnContext.getApnTypeBitmask(), false, 1702 false); 1703 } 1704 return; 1705 } else { 1706 apnContext.setWaitingApns(waitingApns); 1707 if (DBG) { 1708 log("trySetupData: Create from mAllApnSettings : " 1709 + apnListToString(mAllApnSettings)); 1710 } 1711 } 1712 } 1713 1714 if (!setupData(apnContext, radioTech, requestType) 1715 && requestType == REQUEST_TYPE_HANDOVER) { 1716 sendHandoverCompleteMessages(apnContext.getApnTypeBitmask(), false, false); 1717 } 1718 } 1719 1720 /** 1721 * Clean up all data connections. Note this is just detach the APN context from the data 1722 * connection. After all APN contexts are detached from the data connection, the data 1723 * connection will be torn down. 1724 * 1725 * @param reason Reason for the clean up. 1726 */ cleanUpAllConnections(String reason)1727 public void cleanUpAllConnections(String reason) { 1728 log("cleanUpAllConnections"); 1729 Message msg = obtainMessage(DctConstants.EVENT_CLEAN_UP_ALL_CONNECTIONS); 1730 msg.obj = reason; 1731 sendMessage(msg); 1732 } 1733 1734 /** 1735 * Clean up all data connections by detaching the APN contexts from the data connections, which 1736 * eventually tearing down all data connections after all APN contexts are detached from the 1737 * data connections. 1738 * 1739 * @param detach {@code true} if detaching APN context from the underlying data connection (when 1740 * no other APN context is attached to the data connection, the data connection will be torn 1741 * down.) {@code false} to only reset the data connection's state machine. 1742 * 1743 * @param reason reason for the clean up. 1744 * @return boolean - true if we did cleanup any connections, false if they 1745 * were already all disconnected. 1746 */ cleanUpAllConnectionsInternal(boolean detach, String reason)1747 private boolean cleanUpAllConnectionsInternal(boolean detach, String reason) { 1748 if (DBG) log("cleanUpAllConnectionsInternal: detach=" + detach + " reason=" + reason); 1749 boolean didDisconnect = false; 1750 boolean disableMeteredOnly = false; 1751 1752 // reasons that only metered apn will be torn down 1753 if (!TextUtils.isEmpty(reason)) { 1754 disableMeteredOnly = reason.equals(Phone.REASON_DATA_SPECIFIC_DISABLED) || 1755 reason.equals(Phone.REASON_ROAMING_ON) || 1756 reason.equals(Phone.REASON_CARRIER_ACTION_DISABLE_METERED_APN); 1757 } 1758 1759 for (ApnContext apnContext : mApnContexts.values()) { 1760 // Exclude the IMS APN from single data connection case. 1761 if (reason.equals(Phone.REASON_SINGLE_PDN_ARBITRATION) 1762 && apnContext.getApnType().equals(ApnSetting.TYPE_IMS_STRING)) { 1763 continue; 1764 } 1765 1766 if (shouldCleanUpConnection(apnContext, disableMeteredOnly, 1767 reason.equals(Phone.REASON_SINGLE_PDN_ARBITRATION))) { 1768 // TODO - only do cleanup if not disconnected 1769 if (apnContext.isDisconnected() == false) didDisconnect = true; 1770 apnContext.setReason(reason); 1771 cleanUpConnectionInternal(detach, RELEASE_TYPE_DETACH, apnContext); 1772 } else if (DBG) { 1773 log("cleanUpAllConnectionsInternal: APN type " + apnContext.getApnType() 1774 + " shouldn't be cleaned up."); 1775 } 1776 } 1777 1778 stopNetStatPoll(); 1779 stopDataStallAlarm(); 1780 1781 // TODO: Do we need mRequestedApnType? 1782 mRequestedApnType = ApnSetting.TYPE_DEFAULT; 1783 1784 if (areAllDataDisconnected()) { 1785 notifyAllDataDisconnected(); 1786 } 1787 1788 return didDisconnect; 1789 } 1790 shouldCleanUpConnection(ApnContext apnContext, boolean disableMeteredOnly, boolean singlePdn)1791 boolean shouldCleanUpConnection(ApnContext apnContext, boolean disableMeteredOnly, 1792 boolean singlePdn) { 1793 if (apnContext == null) return false; 1794 1795 // If APN setting is not null and the reason is single PDN arbitration, clean up connection. 1796 ApnSetting apnSetting = apnContext.getApnSetting(); 1797 if (apnSetting != null && singlePdn) return true; 1798 1799 // If meteredOnly is false, clean up all connections. 1800 if (!disableMeteredOnly) return true; 1801 1802 // If meteredOnly is true, and apnSetting is null or it's un-metered, no need to clean up. 1803 if (apnSetting == null || !ApnSettingUtils.isMetered(apnSetting, mPhone)) return false; 1804 1805 boolean isRoaming = mPhone.getServiceState().getDataRoaming(); 1806 boolean isDataRoamingDisabled = !getDataRoamingEnabled(); 1807 boolean isDataDisabled = !mDataEnabledSettings.isDataEnabled( 1808 apnSetting.getApnTypeBitmask()); 1809 1810 // Should clean up if its data is disabled, or data roaming is disabled while roaming. 1811 return isDataDisabled || (isRoaming && isDataRoamingDisabled); 1812 } 1813 1814 /** 1815 * Detach the APN context from the associated data connection. This data connection might be 1816 * torn down if no other APN context is attached to it. 1817 * 1818 * @param apnContext The APN context to be detached 1819 */ cleanUpConnection(ApnContext apnContext)1820 void cleanUpConnection(ApnContext apnContext) { 1821 if (DBG) log("cleanUpConnection: apnContext=" + apnContext); 1822 Message msg = obtainMessage(DctConstants.EVENT_CLEAN_UP_CONNECTION); 1823 msg.arg2 = 0; 1824 msg.obj = apnContext; 1825 sendMessage(msg); 1826 } 1827 1828 /** 1829 * Detach the APN context from the associated data connection. This data connection will be 1830 * torn down if no other APN context is attached to it. 1831 * 1832 * @param detach {@code true} if detaching APN context from the underlying data connection (when 1833 * no other APN context is attached to the data connection, the data connection will be torn 1834 * down.) {@code false} to only reset the data connection's state machine. 1835 * @param releaseType Data release type. 1836 * @param apnContext The APN context to be detached. 1837 */ cleanUpConnectionInternal(boolean detach, @ReleaseNetworkType int releaseType, ApnContext apnContext)1838 private void cleanUpConnectionInternal(boolean detach, @ReleaseNetworkType int releaseType, 1839 ApnContext apnContext) { 1840 if (apnContext == null) { 1841 if (DBG) log("cleanUpConnectionInternal: apn context is null"); 1842 return; 1843 } 1844 1845 DataConnection dataConnection = apnContext.getDataConnection(); 1846 String str = "cleanUpConnectionInternal: detach=" + detach + " reason=" 1847 + apnContext.getReason(); 1848 if (VDBG) log(str + " apnContext=" + apnContext); 1849 ApnContext.requestLog(apnContext, str); 1850 if (detach) { 1851 if (apnContext.isDisconnected()) { 1852 // The request is detach and but ApnContext is not connected. 1853 // If apnContext is not enabled anymore, break the linkage to the data connection. 1854 apnContext.releaseDataConnection(""); 1855 } else { 1856 // Connection is still there. Try to clean up. 1857 if (dataConnection != null) { 1858 if (apnContext.getState() != DctConstants.State.DISCONNECTING) { 1859 boolean disconnectAll = false; 1860 if (ApnSetting.TYPE_DUN_STRING.equals(apnContext.getApnType()) 1861 && ServiceState.isCdma(getDataRat())) { 1862 if (DBG) { 1863 log("cleanUpConnectionInternal: disconnectAll DUN connection"); 1864 } 1865 // For CDMA DUN, we need to tear it down immediately. A new data 1866 // connection will be reestablished with correct profile id. 1867 disconnectAll = true; 1868 } 1869 final int generation = apnContext.getConnectionGeneration(); 1870 str = "cleanUpConnectionInternal: tearing down" 1871 + (disconnectAll ? " all" : "") + " using gen#" + generation; 1872 if (DBG) log(str + "apnContext=" + apnContext); 1873 ApnContext.requestLog(apnContext, str); 1874 Pair<ApnContext, Integer> pair = new Pair<>(apnContext, generation); 1875 Message msg = obtainMessage(DctConstants.EVENT_DISCONNECT_DONE, pair); 1876 1877 if (disconnectAll || releaseType == RELEASE_TYPE_HANDOVER) { 1878 dataConnection.tearDownAll(apnContext.getReason(), releaseType, msg); 1879 } else { 1880 dataConnection.tearDown(apnContext, apnContext.getReason(), msg); 1881 } 1882 1883 apnContext.setState(DctConstants.State.DISCONNECTING); 1884 } 1885 } else { 1886 // apn is connected but no reference to the data connection. 1887 // Should not be happen, but reset the state in case. 1888 apnContext.setState(DctConstants.State.IDLE); 1889 ApnContext.requestLog( 1890 apnContext, "cleanUpConnectionInternal: connected, bug no dc"); 1891 } 1892 } 1893 } else { 1894 // force clean up the data connection. 1895 if (dataConnection != null) dataConnection.reset(); 1896 apnContext.setState(DctConstants.State.IDLE); 1897 apnContext.setDataConnection(null); 1898 } 1899 1900 // If there is any outstanding handover request, we need to respond it. 1901 sendHandoverCompleteMessages(apnContext.getApnTypeBitmask(), false, false); 1902 1903 // Make sure reconnection alarm is cleaned up if there is no ApnContext 1904 // associated to the connection. 1905 if (dataConnection != null) { 1906 cancelReconnect(apnContext); 1907 } 1908 str = "cleanUpConnectionInternal: X detach=" + detach + " reason=" 1909 + apnContext.getReason(); 1910 if (DBG) log(str + " apnContext=" + apnContext + " dc=" + apnContext.getDataConnection()); 1911 } 1912 getPreferredApnCursor(int subId)1913 private Cursor getPreferredApnCursor(int subId) { 1914 Cursor cursor = null; 1915 if (subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) { 1916 cursor = mPhone.getContext().getContentResolver().query( 1917 Uri.withAppendedPath(PREFERAPN_NO_UPDATE_URI_USING_SUBID, 1918 String.valueOf(subId)), null, null, null, 1919 Telephony.Carriers.DEFAULT_SORT_ORDER); 1920 } 1921 return cursor; 1922 } 1923 getPreferredApnFromDB()1924 private ApnSetting getPreferredApnFromDB() { 1925 ApnSetting preferredApn = null; 1926 Cursor cursor = getPreferredApnCursor(mPhone.getSubId()); 1927 if (cursor != null) { 1928 if (cursor.getCount() > 0) { 1929 cursor.moveToFirst(); 1930 preferredApn = ApnSetting.makeApnSetting(cursor); 1931 } 1932 cursor.close(); 1933 } 1934 if (VDBG) log("getPreferredApnFromDB: preferredApn=" + preferredApn); 1935 return preferredApn; 1936 } 1937 setDefaultPreferredApnIfNeeded()1938 private void setDefaultPreferredApnIfNeeded() { 1939 ApnSetting defaultPreferredApn = null; 1940 PersistableBundle bundle = getCarrierConfig(); 1941 String defaultPreferredApnName = bundle.getString(CarrierConfigManager 1942 .KEY_DEFAULT_PREFERRED_APN_NAME_STRING); 1943 1944 if (TextUtils.isEmpty(defaultPreferredApnName) || getPreferredApnFromDB() != null) { 1945 return; 1946 } 1947 1948 String selection = Telephony.Carriers.APN + " = \"" + defaultPreferredApnName + "\" AND " 1949 + Telephony.Carriers.EDITED_STATUS + " = " + Telephony.Carriers.UNEDITED; 1950 Cursor cursor = mPhone.getContext().getContentResolver().query( 1951 Uri.withAppendedPath(Telephony.Carriers.SIM_APN_URI, 1952 "filtered/subId/" + mPhone.getSubId()), 1953 null, selection, null, Telephony.Carriers._ID); 1954 1955 if (cursor != null) { 1956 if (cursor.getCount() > 0) { 1957 if (cursor.moveToFirst()) { 1958 defaultPreferredApn = ApnSetting.makeApnSetting(cursor); 1959 } 1960 } 1961 cursor.close(); 1962 } 1963 1964 if (defaultPreferredApn != null 1965 && defaultPreferredApn.canHandleType(mRequestedApnType)) { 1966 log("setDefaultPreferredApnIfNeeded: For APN type " 1967 + ApnSetting.getApnTypeString(mRequestedApnType) 1968 + " found default apnSetting " 1969 + defaultPreferredApn); 1970 1971 setPreferredApn(defaultPreferredApn.getId(), true); 1972 } 1973 1974 return; 1975 } 1976 1977 /** 1978 * Check if preferred apn is allowed to edit by user. 1979 * @return {@code true} if it is allowed to edit. 1980 */ 1981 @VisibleForTesting isPreferredApnUserEdited()1982 public boolean isPreferredApnUserEdited() { 1983 boolean isUserEdited = false; 1984 Cursor cursor = getPreferredApnCursor(mPhone.getSubId()); 1985 if (cursor != null) { 1986 if (cursor.getCount() > 0) { 1987 if (cursor.moveToFirst()) { 1988 isUserEdited = cursor.getInt( 1989 cursor.getColumnIndexOrThrow(Telephony.Carriers.EDITED_STATUS)) 1990 == Telephony.Carriers.USER_EDITED; 1991 } 1992 } 1993 cursor.close(); 1994 } 1995 if (VDBG) log("isPreferredApnUserEdited: isUserEdited=" + isUserEdited); 1996 return isUserEdited; 1997 } 1998 1999 /** 2000 * Fetch the DUN apns 2001 * @return a list of DUN ApnSetting objects 2002 */ 2003 @VisibleForTesting fetchDunApns()2004 public @NonNull ArrayList<ApnSetting> fetchDunApns() { 2005 if (mPhone.getServiceState().getRoaming() && !isPreferredApnUserEdited() 2006 && getCarrierConfig().getBoolean(CarrierConfigManager 2007 .KEY_DISABLE_DUN_APN_WHILE_ROAMING_WITH_PRESET_APN_BOOL)) { 2008 if (VDBG) log("fetchDunApns: Dun apn is not used in roaming network"); 2009 return new ArrayList<ApnSetting>(0); 2010 } 2011 2012 int bearer = getDataRat(); 2013 ArrayList<ApnSetting> dunCandidates = new ArrayList<ApnSetting>(); 2014 ArrayList<ApnSetting> retDunSettings = new ArrayList<ApnSetting>(); 2015 2016 if (dunCandidates.isEmpty()) { 2017 if (!ArrayUtils.isEmpty(mAllApnSettings)) { 2018 for (ApnSetting apn : mAllApnSettings) { 2019 if (apn.canHandleType(ApnSetting.TYPE_DUN)) { 2020 dunCandidates.add(apn); 2021 } 2022 } 2023 if (VDBG) log("fetchDunApns: dunCandidates from database: " + dunCandidates); 2024 } 2025 } 2026 2027 int preferredApnSetId = getPreferredApnSetId(); 2028 ApnSetting preferredApn = getPreferredApnFromDB(); 2029 for (ApnSetting dunSetting : dunCandidates) { 2030 if (dunSetting.canSupportNetworkType( 2031 ServiceState.rilRadioTechnologyToNetworkType(bearer))) { 2032 if (preferredApnSetId == dunSetting.getApnSetId()) { 2033 if (preferredApn != null && preferredApn.equals(dunSetting)) { 2034 // If there is a preferred APN can handled DUN type, prepend it to list to 2035 // use it preferred. 2036 retDunSettings.add(0, dunSetting); 2037 } else { 2038 retDunSettings.add(dunSetting); 2039 } 2040 } 2041 } 2042 } 2043 2044 if (VDBG) log("fetchDunApns: dunSettings=" + retDunSettings); 2045 return retDunSettings; 2046 } 2047 getPreferredApnSetId()2048 private int getPreferredApnSetId() { 2049 // preferapnset uri returns all APNs for the current carrier which have an apn_set_id 2050 // equal to the preferred APN (if no preferred APN, or if the preferred APN has no set id, 2051 // the query will return null) 2052 Cursor c = mPhone.getContext().getContentResolver() 2053 .query(Uri.withAppendedPath(Telephony.Carriers.CONTENT_URI, 2054 "preferapnset/subId/" + mPhone.getSubId()), 2055 new String[] {Telephony.Carriers.APN_SET_ID}, null, null, null); 2056 if (c == null) { 2057 loge("getPreferredApnSetId: cursor is null"); 2058 return Telephony.Carriers.NO_APN_SET_ID; 2059 } 2060 2061 int setId; 2062 if (c.getCount() < 1) { 2063 loge("getPreferredApnSetId: no APNs found"); 2064 setId = Telephony.Carriers.NO_APN_SET_ID; 2065 } else { 2066 c.moveToFirst(); 2067 setId = c.getInt(0 /* index of Telephony.Carriers.APN_SET_ID */); 2068 } 2069 2070 if (!c.isClosed()) { 2071 c.close(); 2072 } 2073 return setId; 2074 } 2075 hasMatchedTetherApnSetting()2076 public boolean hasMatchedTetherApnSetting() { 2077 ArrayList<ApnSetting> matches = fetchDunApns(); 2078 log("hasMatchedTetherApnSetting: APNs=" + matches); 2079 return matches.size() > 0; 2080 } 2081 2082 /** 2083 * @return the {@link DataConnection} with the given context id {@code cid}. 2084 */ getDataConnectionByContextId(int cid)2085 public DataConnection getDataConnectionByContextId(int cid) { 2086 return mDcc.getActiveDcByCid(cid); 2087 } 2088 2089 /** 2090 * @return the {@link DataConnection} with the given APN context. Null if no data connection 2091 * is found. 2092 */ getDataConnectionByApnType(String apnType)2093 public @Nullable DataConnection getDataConnectionByApnType(String apnType) { 2094 // TODO: Clean up all APN type in string usage 2095 ApnContext apnContext = mApnContexts.get(apnType); 2096 if (apnContext != null) { 2097 return apnContext.getDataConnection(); 2098 } 2099 return null; 2100 } 2101 2102 /** 2103 * Check if the data fail cause is a permanent failure (i.e. Frameworks will not retry data 2104 * setup). 2105 * 2106 * @param dcFailCause The data fail cause 2107 * @return {@code true} if the data fail cause is a permanent failure. 2108 */ 2109 @VisibleForTesting isPermanentFailure(@ataFailureCause int dcFailCause)2110 public boolean isPermanentFailure(@DataFailureCause int dcFailCause) { 2111 return (DataFailCause.isPermanentFailure(mPhone.getContext(), dcFailCause, 2112 mPhone.getSubId()) 2113 && (mAttached.get() == false || dcFailCause != DataFailCause.SIGNAL_LOST)); 2114 } 2115 findFreeDataConnection()2116 private DataConnection findFreeDataConnection() { 2117 for (DataConnection dataConnection : mDataConnections.values()) { 2118 boolean inUse = false; 2119 for (ApnContext apnContext : mApnContexts.values()) { 2120 if (apnContext.getDataConnection() == dataConnection) { 2121 inUse = true; 2122 break; 2123 } 2124 } 2125 if (!inUse) { 2126 if (DBG) { 2127 log("findFreeDataConnection: found free DataConnection=" + dataConnection); 2128 } 2129 return dataConnection; 2130 } 2131 } 2132 log("findFreeDataConnection: NO free DataConnection"); 2133 return null; 2134 } 2135 2136 /** 2137 * Setup a data connection based on given APN type. 2138 * 2139 * @param apnContext APN context 2140 * @param radioTech RAT of the data connection 2141 * @param requestType Data request type 2142 * @return True if successful, otherwise false. 2143 */ setupData(ApnContext apnContext, int radioTech, @RequestNetworkType int requestType)2144 private boolean setupData(ApnContext apnContext, int radioTech, 2145 @RequestNetworkType int requestType) { 2146 if (DBG) { 2147 log("setupData: apnContext=" + apnContext + ", requestType=" 2148 + requestTypeToString(requestType)); 2149 } 2150 ApnContext.requestLog( 2151 apnContext, "setupData. requestType=" + requestTypeToString(requestType)); 2152 ApnSetting apnSetting; 2153 DataConnection dataConnection = null; 2154 2155 apnSetting = apnContext.getNextApnSetting(); 2156 2157 if (apnSetting == null) { 2158 if (DBG) log("setupData: return for no apn found!"); 2159 return false; 2160 } 2161 2162 // profile id is only meaningful when the profile is persistent on the modem. 2163 int profileId = DATA_PROFILE_INVALID; 2164 if (apnSetting.isPersistent()) { 2165 profileId = apnSetting.getProfileId(); 2166 if (profileId == DATA_PROFILE_DEFAULT) { 2167 profileId = getApnProfileID(apnContext.getApnType()); 2168 } 2169 } 2170 2171 // On CDMA, if we're explicitly asking for DUN, we need have 2172 // a dun-profiled connection so we can't share an existing one 2173 // On GSM/LTE we can share existing apn connections provided they support 2174 // this type. 2175 // If asking for ENTERPRISE, there are no compatible data connections, so skip this check 2176 if ((apnContext.getApnTypeBitmask() != ApnSetting.TYPE_DUN 2177 || ServiceState.isGsm(getDataRat())) 2178 && apnContext.getApnTypeBitmask() != ApnSetting.TYPE_ENTERPRISE) { 2179 dataConnection = checkForCompatibleDataConnection(apnContext, apnSetting); 2180 if (dataConnection != null) { 2181 // Get the apn setting used by the data connection 2182 ApnSetting dataConnectionApnSetting = dataConnection.getApnSetting(); 2183 if (dataConnectionApnSetting != null) { 2184 // Setting is good, so use it. 2185 apnSetting = dataConnectionApnSetting; 2186 } 2187 } 2188 } 2189 if (dataConnection == null) { 2190 if (isOnlySingleDcAllowed(radioTech)) { 2191 if (isHigherPriorityApnContextActive(apnContext)) { 2192 if (DBG) { 2193 log("setupData: Higher priority ApnContext active. Ignoring call"); 2194 } 2195 return false; 2196 } 2197 2198 // Should not start cleanUp if the setupData is for IMS APN 2199 // or retry of same APN(State==RETRYING). 2200 if (!apnContext.getApnType().equals(ApnSetting.TYPE_IMS_STRING) 2201 && (apnContext.getState() != DctConstants.State.RETRYING)) { 2202 // Only lower priority calls left. Disconnect them all in this single PDP case 2203 // so that we can bring up the requested higher priority call (once we receive 2204 // response for deactivate request for the calls we are about to disconnect 2205 if (cleanUpAllConnectionsInternal(true, Phone.REASON_SINGLE_PDN_ARBITRATION)) { 2206 // If any call actually requested to be disconnected, means we can't 2207 // bring up this connection yet as we need to wait for those data calls 2208 // to be disconnected. 2209 if (DBG) log("setupData: Some calls are disconnecting first." 2210 + " Wait and retry"); 2211 return false; 2212 } 2213 } 2214 2215 // No other calls are active, so proceed 2216 if (DBG) log("setupData: Single pdp. Continue setting up data call."); 2217 } 2218 2219 dataConnection = findFreeDataConnection(); 2220 2221 if (dataConnection == null) { 2222 dataConnection = createDataConnection(); 2223 } 2224 2225 if (dataConnection == null) { 2226 if (DBG) log("setupData: No free DataConnection and couldn't create one, WEIRD"); 2227 return false; 2228 } 2229 } 2230 final int generation = apnContext.incAndGetConnectionGeneration(); 2231 if (DBG) { 2232 log("setupData: dc=" + dataConnection + " apnSetting=" + apnSetting + " gen#=" 2233 + generation); 2234 } 2235 2236 apnContext.setDataConnection(dataConnection); 2237 apnContext.setApnSetting(apnSetting); 2238 apnContext.setState(DctConstants.State.CONNECTING); 2239 2240 Message msg = obtainMessage(); 2241 msg.what = DctConstants.EVENT_DATA_SETUP_COMPLETE; 2242 msg.obj = new Pair<ApnContext, Integer>(apnContext, generation); 2243 2244 ApnSetting preferredApn = getPreferredApn(); 2245 boolean isPreferredApn = apnSetting.equals(preferredApn); 2246 dataConnection.bringUp(apnContext, profileId, radioTech, msg, generation, requestType, 2247 mPhone.getSubId(), isPreferredApn); 2248 2249 if (DBG) { 2250 if (isPreferredApn) { 2251 log("setupData: initing! isPreferredApn=" + isPreferredApn 2252 + ", apnSetting={" + apnSetting.toString() + "}"); 2253 } else { 2254 String preferredApnStr = preferredApn == null ? "null" : preferredApn.toString(); 2255 log("setupData: initing! isPreferredApn=" + isPreferredApn 2256 + ", apnSetting={" + apnSetting + "}" 2257 + ", preferredApn={" + preferredApnStr + "}"); 2258 } 2259 } 2260 return true; 2261 } 2262 2263 // Get the allowed APN types for initial attach. The order in the returned list represent 2264 // the order of APN types that should be used for initial attach. getAllowedInitialAttachApnTypes()2265 private @NonNull @ApnType List<Integer> getAllowedInitialAttachApnTypes() { 2266 PersistableBundle bundle = getCarrierConfig(); 2267 if (bundle != null) { 2268 String[] apnTypesArray = bundle.getStringArray( 2269 CarrierConfigManager.KEY_ALLOWED_INITIAL_ATTACH_APN_TYPES_STRING_ARRAY); 2270 if (apnTypesArray != null) { 2271 return Arrays.stream(apnTypesArray) 2272 .map(ApnSetting::getApnTypesBitmaskFromString) 2273 .collect(Collectors.toList()); 2274 } 2275 } 2276 2277 return Collections.emptyList(); 2278 } 2279 setInitialAttachApn()2280 protected void setInitialAttachApn() { 2281 ApnSetting apnSetting = null; 2282 int preferredApnSetId = getPreferredApnSetId(); 2283 ArrayList<ApnSetting> allApnSettings = new ArrayList<>(); 2284 if (mPreferredApn != null) { 2285 // Put the preferred apn at the beginning of the list. It's okay to have a duplicate 2286 // when later on mAllApnSettings get added. That would not change the selection result. 2287 allApnSettings.add(mPreferredApn); 2288 } 2289 allApnSettings.addAll(mAllApnSettings); 2290 2291 // Get the allowed APN types for initial attach. Note that if none of the APNs has the 2292 // allowed APN types, then the initial attach will not be performed. 2293 List<Integer> allowedApnTypes = getAllowedInitialAttachApnTypes(); 2294 for (int allowedApnType : allowedApnTypes) { 2295 apnSetting = allApnSettings.stream() 2296 .filter(apn -> apn.canHandleType(allowedApnType)) 2297 .filter(apn -> (apn.getApnSetId() == preferredApnSetId 2298 || apn.getApnSetId() == Telephony.Carriers.MATCH_ALL_APN_SET_ID)) 2299 .findFirst() 2300 .orElse(null); 2301 if (apnSetting != null) break; 2302 } 2303 2304 if (DBG) { 2305 log("setInitialAttachApn: Allowed APN types=" + allowedApnTypes.stream() 2306 .map(ApnSetting::getApnTypeString) 2307 .collect(Collectors.joining(","))); 2308 } 2309 2310 if (apnSetting == null) { 2311 if (DBG) log("setInitialAttachApn: X There in no available apn."); 2312 } else { 2313 if (DBG) log("setInitialAttachApn: X selected APN=" + apnSetting); 2314 mDataServiceManager.setInitialAttachApn(new DataProfile.Builder() 2315 .setApnSetting(apnSetting) 2316 .setPreferred(apnSetting.equals(getPreferredApn())) 2317 .build(), 2318 mPhone.getServiceState().getDataRoamingFromRegistration(), null); 2319 } 2320 } 2321 2322 /** 2323 * Handles changes to the APN database. 2324 */ onApnChanged()2325 private void onApnChanged() { 2326 if (mPhone instanceof GsmCdmaPhone) { 2327 // The "current" may no longer be valid. MMS depends on this to send properly. TBD 2328 ((GsmCdmaPhone)mPhone).updateCurrentCarrierInProvider(); 2329 } 2330 2331 // TODO: It'd be nice to only do this if the changed entrie(s) 2332 // match the current operator. 2333 if (DBG) log("onApnChanged: createAllApnList and cleanUpAllConnections"); 2334 mDataThrottler.reset(); 2335 setDefaultPreferredApnIfNeeded(); 2336 createAllApnList(); 2337 setDataProfilesAsNeeded(); 2338 setInitialAttachApn(); 2339 cleanUpConnectionsOnUpdatedApns(isAnyDataConnected(), Phone.REASON_APN_CHANGED); 2340 2341 // FIXME: See bug 17426028 maybe no conditional is needed. 2342 if (mPhone.getSubId() == SubscriptionManager.getDefaultDataSubscriptionId()) { 2343 setupDataOnAllConnectableApns(Phone.REASON_APN_CHANGED, RetryFailures.ALWAYS); 2344 } 2345 } 2346 2347 /** 2348 * "Active" here means ApnContext isEnabled() and not in FAILED state 2349 * @param apnContext to compare with 2350 * @return true if higher priority active apn found 2351 */ isHigherPriorityApnContextActive(ApnContext apnContext)2352 private boolean isHigherPriorityApnContextActive(ApnContext apnContext) { 2353 if (apnContext.getApnType().equals(ApnSetting.TYPE_IMS_STRING)) { 2354 return false; 2355 } 2356 2357 for (ApnContext otherContext : mPrioritySortedApnContexts) { 2358 if (otherContext.getApnType().equals(ApnSetting.TYPE_IMS_STRING)) { 2359 continue; 2360 } 2361 if (apnContext.getApnType().equalsIgnoreCase(otherContext.getApnType())) return false; 2362 if (otherContext.isEnabled() && otherContext.getState() != DctConstants.State.FAILED) { 2363 return true; 2364 } 2365 } 2366 return false; 2367 } 2368 2369 /** 2370 * Reports if we support multiple connections or not. 2371 * This is a combination of factors, based on carrier and RAT. 2372 * @param rilRadioTech the RIL Radio Tech currently in use 2373 * @return true if only single DataConnection is allowed 2374 */ isOnlySingleDcAllowed(int rilRadioTech)2375 private boolean isOnlySingleDcAllowed(int rilRadioTech) { 2376 int networkType = ServiceState.rilRadioTechnologyToNetworkType(rilRadioTech); 2377 // Default single dc rats with no knowledge of carrier 2378 int[] singleDcRats = null; 2379 // get the carrier specific value, if it exists, from CarrierConfigManager. 2380 // generally configManager and bundle should not be null, but if they are it should be okay 2381 // to leave singleDcRats null as well 2382 CarrierConfigManager configManager = (CarrierConfigManager) 2383 mPhone.getContext().getSystemService(Context.CARRIER_CONFIG_SERVICE); 2384 if (configManager != null) { 2385 PersistableBundle bundle = configManager.getConfigForSubId(mPhone.getSubId()); 2386 if (bundle != null) { 2387 singleDcRats = bundle.getIntArray( 2388 CarrierConfigManager.KEY_ONLY_SINGLE_DC_ALLOWED_INT_ARRAY); 2389 } 2390 } 2391 boolean onlySingleDcAllowed = false; 2392 if (TelephonyUtils.IS_DEBUGGABLE 2393 && SystemProperties.getBoolean("persist.telephony.test.singleDc", false)) { 2394 onlySingleDcAllowed = true; 2395 } 2396 if (singleDcRats != null) { 2397 for (int i = 0; i < singleDcRats.length && !onlySingleDcAllowed; i++) { 2398 if (networkType == singleDcRats[i]) { 2399 onlySingleDcAllowed = true; 2400 } 2401 } 2402 } 2403 2404 if (DBG) { 2405 log("isOnlySingleDcAllowed(" + TelephonyManager.getNetworkTypeName(networkType) + "): " 2406 + onlySingleDcAllowed); 2407 } 2408 return onlySingleDcAllowed; 2409 } 2410 sendRestartRadio()2411 void sendRestartRadio() { 2412 if (DBG)log("sendRestartRadio:"); 2413 Message msg = obtainMessage(DctConstants.EVENT_RESTART_RADIO); 2414 sendMessage(msg); 2415 } 2416 restartRadio()2417 private void restartRadio() { 2418 if (DBG) log("restartRadio: ************TURN OFF RADIO**************"); 2419 cleanUpAllConnectionsInternal(true, Phone.REASON_RADIO_TURNED_OFF); 2420 mPhone.getServiceStateTracker().powerOffRadioSafely(); 2421 /* Note: no need to call setRadioPower(true). Assuming the desired 2422 * radio power state is still ON (as tracked by ServiceStateTracker), 2423 * ServiceStateTracker will call setRadioPower when it receives the 2424 * RADIO_STATE_CHANGED notification for the power off. And if the 2425 * desired power state has changed in the interim, we don't want to 2426 * override it with an unconditional power on. 2427 */ 2428 } 2429 2430 /** 2431 * Return true if data connection need to be setup after disconnected due to 2432 * reason. 2433 * 2434 * @param apnContext APN context 2435 * @return true if try setup data connection is need for this reason 2436 */ retryAfterDisconnected(ApnContext apnContext)2437 private boolean retryAfterDisconnected(ApnContext apnContext) { 2438 boolean retry = true; 2439 String reason = apnContext.getReason(); 2440 2441 if (Phone.REASON_RADIO_TURNED_OFF.equals(reason) || (isOnlySingleDcAllowed(getDataRat()) 2442 && isHigherPriorityApnContextActive(apnContext))) { 2443 retry = false; 2444 } 2445 return retry; 2446 } 2447 startReconnect(long delay, ApnContext apnContext, @RequestNetworkType int requestType)2448 protected void startReconnect(long delay, ApnContext apnContext, 2449 @RequestNetworkType int requestType) { 2450 apnContext.setState(DctConstants.State.RETRYING); 2451 Message msg = obtainMessage(DctConstants.EVENT_DATA_RECONNECT, 2452 mPhone.getSubId(), requestType, apnContext); 2453 cancelReconnect(apnContext); 2454 2455 // Wait a bit before trying the next APN, so that 2456 // we're not tying up the RIL command channel 2457 sendMessageDelayed(msg, delay); 2458 2459 if (DBG) { 2460 log("startReconnect: delay=" + delay + ", apn=" 2461 + apnContext + ", reason=" + apnContext.getReason() 2462 + ", subId=" + mPhone.getSubId() + ", request type=" 2463 + requestTypeToString(requestType)); 2464 } 2465 } 2466 2467 /** 2468 * Cancels the alarm associated with apnContext. 2469 * 2470 * @param apnContext on which the alarm should be stopped. 2471 */ cancelReconnect(ApnContext apnContext)2472 protected void cancelReconnect(ApnContext apnContext) { 2473 if (apnContext == null) return; 2474 2475 if (DBG) { 2476 log("cancelReconnect: apn=" + apnContext); 2477 } 2478 removeMessages(DctConstants.EVENT_DATA_RECONNECT, apnContext); 2479 } 2480 2481 /** 2482 * Read configuration. Note this must be called after carrier config is ready. 2483 */ readConfiguration()2484 private void readConfiguration() { 2485 log("readConfiguration"); 2486 if (mTransportType == AccessNetworkConstants.TRANSPORT_TYPE_WWAN) { 2487 // Auto attach is for cellular only. 2488 mAutoAttachOnCreationConfig = mPhone.getContext().getResources() 2489 .getBoolean(com.android.internal.R.bool.config_auto_attach_data_on_creation); 2490 } 2491 2492 mAutoAttachEnabled.set(false); 2493 setDefaultPreferredApnIfNeeded(); 2494 read5GConfiguration(); 2495 registerSettingsObserver(); 2496 SubscriptionPlan[] plans = mNetworkPolicyManager.getSubscriptionPlans( 2497 mPhone.getSubId(), mPhone.getContext().getOpPackageName()); 2498 mSubscriptionPlans = plans == null ? Collections.emptyList() : Arrays.asList(plans); 2499 if (DBG) log("SubscriptionPlans initialized: " + mSubscriptionPlans); 2500 reevaluateUnmeteredConnections(); 2501 mConfigReady = true; 2502 } 2503 2504 /** 2505 * @return {@code true} if carrier config has been applied. 2506 */ isCarrierConfigApplied()2507 private boolean isCarrierConfigApplied() { 2508 CarrierConfigManager configManager = (CarrierConfigManager) mPhone.getContext() 2509 .getSystemService(Context.CARRIER_CONFIG_SERVICE); 2510 if (configManager != null) { 2511 PersistableBundle b = configManager.getConfigForSubId(mPhone.getSubId()); 2512 if (b != null) { 2513 return CarrierConfigManager.isConfigForIdentifiedCarrier(b); 2514 } 2515 } 2516 return false; 2517 } 2518 onCarrierConfigChanged()2519 private void onCarrierConfigChanged() { 2520 if (DBG) log("onCarrierConfigChanged"); 2521 2522 if (!isCarrierConfigApplied()) { 2523 log("onCarrierConfigChanged: Carrier config is not ready yet."); 2524 return; 2525 } 2526 2527 readConfiguration(); 2528 2529 if (mSimState == TelephonyManager.SIM_STATE_LOADED) { 2530 setDefaultDataRoamingEnabled(); 2531 createAllApnList(); 2532 setDataProfilesAsNeeded(); 2533 setInitialAttachApn(); 2534 sortApnContextByPriority(); 2535 cleanUpConnectionsOnUpdatedApns(true, Phone.REASON_CARRIER_CHANGE); 2536 setupDataOnAllConnectableApns(Phone.REASON_CARRIER_CHANGE, RetryFailures.ALWAYS); 2537 } else { 2538 log("onCarrierConfigChanged: SIM is not loaded yet."); 2539 } 2540 } 2541 onSimAbsent()2542 private void onSimAbsent() { 2543 if (DBG) log("onSimAbsent"); 2544 2545 mConfigReady = false; 2546 cleanUpAllConnectionsInternal(true, Phone.REASON_SIM_NOT_READY); 2547 mAllApnSettings.clear(); 2548 mAutoAttachOnCreationConfig = false; 2549 // Clear auto attach as modem is expected to do a new attach once SIM is ready 2550 mAutoAttachEnabled.set(false); 2551 // In no-sim case, we should still send the emergency APN to the modem, if there is any. 2552 createAllApnList(); 2553 setDataProfilesAsNeeded(); 2554 } 2555 onSimStateUpdated(@imState int simState)2556 private void onSimStateUpdated(@SimState int simState) { 2557 mSimState = simState; 2558 2559 if (DBG) { 2560 log("onSimStateUpdated: state=" + SubscriptionInfoUpdater.simStateString(mSimState)); 2561 } 2562 2563 if (mSimState == TelephonyManager.SIM_STATE_ABSENT) { 2564 onSimAbsent(); 2565 } else if (mSimState == TelephonyManager.SIM_STATE_LOADED) { 2566 mDataThrottler.reset(); 2567 if (mConfigReady) { 2568 createAllApnList(); 2569 setDataProfilesAsNeeded(); 2570 setInitialAttachApn(); 2571 setupDataOnAllConnectableApns(Phone.REASON_SIM_LOADED, RetryFailures.ALWAYS); 2572 } else { 2573 log("onSimStateUpdated: config not ready yet."); 2574 } 2575 } 2576 } 2577 onApnUnthrottled(String apn)2578 private void onApnUnthrottled(String apn) { 2579 if (apn != null) { 2580 ApnSetting apnSetting = mAllApnSettings.stream() 2581 .filter(as -> apn.equals(as.getApnName())) 2582 .findFirst() 2583 .orElse(null); 2584 if (apnSetting != null) { 2585 @ApnType int apnTypes = apnSetting.getApnTypeBitmask(); 2586 mDataThrottler.setRetryTime(apnTypes, RetryManager.NO_SUGGESTED_RETRY_DELAY, 2587 REQUEST_TYPE_NORMAL); 2588 } else { 2589 loge("EVENT_APN_UNTHROTTLED: Invalid APN passed: " + apn); 2590 } 2591 } else { 2592 loge("EVENT_APN_UNTHROTTLED: apn is null"); 2593 } 2594 } 2595 onTrafficDescriptorsUpdated()2596 private void onTrafficDescriptorsUpdated() { 2597 for (ApnContext apnContext : mPrioritySortedApnContexts) { 2598 if (apnContext.getApnTypeBitmask() == ApnSetting.TYPE_ENTERPRISE 2599 && apnContext.getApnSetting().getPermanentFailed()) { 2600 setupDataOnConnectableApn( 2601 apnContext, Phone.REASON_TRAFFIC_DESCRIPTORS_UPDATED, RetryFailures.ALWAYS); 2602 } 2603 } 2604 } 2605 checkForCompatibleDataConnection(ApnContext apnContext, ApnSetting nextApn)2606 private DataConnection checkForCompatibleDataConnection(ApnContext apnContext, 2607 ApnSetting nextApn) { 2608 int apnType = apnContext.getApnTypeBitmask(); 2609 ArrayList<ApnSetting> dunSettings = null; 2610 2611 if (ApnSetting.TYPE_DUN == apnType) { 2612 dunSettings = fetchDunApns(); 2613 } 2614 if (DBG) { 2615 log("checkForCompatibleDataConnection: apnContext=" + apnContext); 2616 } 2617 2618 DataConnection potentialDc = null; 2619 for (DataConnection curDc : mDataConnections.values()) { 2620 if (curDc != null) { 2621 ApnSetting apnSetting = curDc.getApnSetting(); 2622 log("apnSetting: " + apnSetting); 2623 if (dunSettings != null && dunSettings.size() > 0) { 2624 for (ApnSetting dunSetting : dunSettings) { 2625 //This ignore network type as a check which is ok because that's checked 2626 //when calculating dun candidates. 2627 if (areCompatible(dunSetting, apnSetting)) { 2628 if (curDc.isActive()) { 2629 if (DBG) { 2630 log("checkForCompatibleDataConnection:" 2631 + " found dun conn=" + curDc); 2632 } 2633 return curDc; 2634 } else if (curDc.isActivating()) { 2635 potentialDc = curDc; 2636 } 2637 } 2638 } 2639 } else if (isApnSettingCompatible(curDc, apnType)) { 2640 if (curDc.isActive()) { 2641 if (DBG) { 2642 log("checkForCompatibleDataConnection:" 2643 + " found canHandle conn=" + curDc); 2644 } 2645 return curDc; 2646 } else if (curDc.isActivating() 2647 || (apnSetting != null && apnSetting.equals(nextApn))) { 2648 potentialDc = curDc; 2649 } 2650 } 2651 } 2652 } 2653 2654 if (DBG) { 2655 log("checkForCompatibleDataConnection: potential dc=" + potentialDc); 2656 } 2657 return potentialDc; 2658 } 2659 isApnSettingCompatible(DataConnection dc, int apnType)2660 private boolean isApnSettingCompatible(DataConnection dc, int apnType) { 2661 ApnSetting apnSetting = dc.getApnSetting(); 2662 if (apnSetting == null) return false; 2663 2664 // Nothing can be compatible with type ENTERPRISE 2665 for (ApnContext apnContext : dc.getApnContexts()) { 2666 if (apnContext.getApnTypeBitmask() == ApnSetting.TYPE_ENTERPRISE) { 2667 return false; 2668 } 2669 } 2670 2671 return apnSetting.canHandleType(apnType); 2672 } 2673 addHandoverCompleteMsg(Message onCompleteMsg, @ApnType int apnType)2674 private void addHandoverCompleteMsg(Message onCompleteMsg, 2675 @ApnType int apnType) { 2676 if (onCompleteMsg != null) { 2677 List<Message> messageList = mHandoverCompletionMsgs.get(apnType); 2678 if (messageList == null) messageList = new ArrayList<>(); 2679 messageList.add(onCompleteMsg); 2680 mHandoverCompletionMsgs.put(apnType, messageList); 2681 } 2682 } 2683 sendHandoverCompleteMessages(@pnType int apnType, boolean success, boolean fallbackOnFailedHandover)2684 private void sendHandoverCompleteMessages(@ApnType int apnType, boolean success, 2685 boolean fallbackOnFailedHandover) { 2686 List<Message> messageList = mHandoverCompletionMsgs.get(apnType); 2687 if (messageList != null) { 2688 for (Message msg : messageList) { 2689 sendHandoverCompleteMsg(msg, success, mTransportType, fallbackOnFailedHandover); 2690 } 2691 messageList.clear(); 2692 } 2693 } 2694 sendHandoverCompleteMsg(Message message, boolean success, @TransportType int transport, boolean doFallbackOnFailedHandover)2695 private void sendHandoverCompleteMsg(Message message, boolean success, 2696 @TransportType int transport, boolean doFallbackOnFailedHandover) { 2697 if (message == null) return; 2698 2699 Bundle b = message.getData(); 2700 b.putBoolean(DATA_COMPLETE_MSG_EXTRA_SUCCESS, success); 2701 b.putInt(DATA_COMPLETE_MSG_EXTRA_TRANSPORT_TYPE, transport); 2702 b.putBoolean(DATA_COMPLETE_MSG_EXTRA_HANDOVER_FAILURE_FALLBACK, doFallbackOnFailedHandover); 2703 message.sendToTarget(); 2704 } 2705 shouldFallbackOnFailedHandover( @andoverFailureMode int handoverFailureMode, @RequestNetworkType int requestType, @DataFailureCause int cause)2706 private static boolean shouldFallbackOnFailedHandover( 2707 @HandoverFailureMode int handoverFailureMode, 2708 @RequestNetworkType int requestType, 2709 @DataFailureCause int cause) { 2710 if (requestType != REQUEST_TYPE_HANDOVER) { 2711 //The fallback is only relevant if the request is a handover 2712 return false; 2713 } else if (handoverFailureMode == HANDOVER_FAILURE_MODE_DO_FALLBACK) { 2714 return true; 2715 } else if (handoverFailureMode == HANDOVER_FAILURE_MODE_LEGACY) { 2716 return cause == DataFailCause.HANDOFF_PREFERENCE_CHANGED; 2717 } else { 2718 return false; 2719 } 2720 } 2721 2722 /** 2723 * Calculates the new request type that will be used the next time a data connection retries 2724 * after a failed data call attempt. 2725 */ 2726 @RequestNetworkType calculateNewRetryRequestType(@andoverFailureMode int handoverFailureMode, @RequestNetworkType int requestType, @DataFailureCause int cause)2727 public static int calculateNewRetryRequestType(@HandoverFailureMode int handoverFailureMode, 2728 @RequestNetworkType int requestType, 2729 @DataFailureCause int cause) { 2730 boolean fallbackOnFailedHandover = 2731 shouldFallbackOnFailedHandover(handoverFailureMode, requestType, cause); 2732 if (requestType != REQUEST_TYPE_HANDOVER) { 2733 //The fallback is only relevant if the request is a handover 2734 return requestType; 2735 } 2736 2737 if (fallbackOnFailedHandover) { 2738 // Since fallback is happening, the request type is really "NONE". 2739 return REQUEST_TYPE_NORMAL; 2740 } 2741 2742 if (handoverFailureMode == HANDOVER_FAILURE_MODE_NO_FALLBACK_RETRY_SETUP_NORMAL) { 2743 return REQUEST_TYPE_NORMAL; 2744 } 2745 2746 return REQUEST_TYPE_HANDOVER; 2747 } 2748 enableApn(@pnType int apnType, @RequestNetworkType int requestType, Message onHandoverCompleteMsg)2749 public void enableApn(@ApnType int apnType, @RequestNetworkType int requestType, 2750 Message onHandoverCompleteMsg) { 2751 sendMessage(obtainMessage(DctConstants.EVENT_ENABLE_APN, apnType, requestType, 2752 onHandoverCompleteMsg)); 2753 } 2754 onEnableApn(@pnType int apnType, @RequestNetworkType int requestType, Message onHandoverCompleteMsg)2755 private void onEnableApn(@ApnType int apnType, @RequestNetworkType int requestType, 2756 Message onHandoverCompleteMsg) { 2757 ApnContext apnContext = mApnContextsByType.get(apnType); 2758 if (apnContext == null) { 2759 loge("onEnableApn(" + apnType + "): NO ApnContext"); 2760 if (onHandoverCompleteMsg != null) { 2761 sendHandoverCompleteMsg(onHandoverCompleteMsg, false, mTransportType, false); 2762 } 2763 return; 2764 } 2765 2766 String str = "onEnableApn: apnType=" + ApnSetting.getApnTypeString(apnType) 2767 + ", request type=" + requestTypeToString(requestType); 2768 if (DBG) log(str); 2769 ApnContext.requestLog(apnContext, str); 2770 2771 if (!apnContext.isDependencyMet()) { 2772 apnContext.setReason(Phone.REASON_DATA_DEPENDENCY_UNMET); 2773 apnContext.setEnabled(true); 2774 str = "onEnableApn: dependency is not met."; 2775 if (DBG) log(str); 2776 ApnContext.requestLog(apnContext, str); 2777 if (onHandoverCompleteMsg != null) { 2778 sendHandoverCompleteMsg(onHandoverCompleteMsg, false, mTransportType, false); 2779 } 2780 return; 2781 } 2782 2783 if (apnContext.isReady()) { 2784 DctConstants.State state = apnContext.getState(); 2785 switch(state) { 2786 case CONNECTING: 2787 if (onHandoverCompleteMsg != null) { 2788 if (DBG) { 2789 log("onEnableApn: already in CONNECTING state. Handover request " 2790 + "will be responded after connected."); 2791 } 2792 addHandoverCompleteMsg(onHandoverCompleteMsg, apnType); 2793 } else { 2794 if (DBG) log("onEnableApn: in CONNECTING state. Exit now."); 2795 } 2796 return; 2797 case CONNECTED: 2798 if (onHandoverCompleteMsg != null) { 2799 sendHandoverCompleteMsg(onHandoverCompleteMsg, true, mTransportType, 2800 false); 2801 if (DBG) { 2802 log("onEnableApn: already in CONNECTED state. Consider as handover " 2803 + "succeeded"); 2804 } 2805 } else { 2806 if (DBG) log("onEnableApn: APN in CONNECTED state. Exit now."); 2807 } 2808 return; 2809 case IDLE: 2810 case FAILED: 2811 case RETRYING: 2812 // We're "READY" but not active so disconnect (cleanup = true) and 2813 // connect (trySetup = true) to be sure we retry the connection. 2814 apnContext.setReason(Phone.REASON_DATA_ENABLED); 2815 break; 2816 } 2817 } else { 2818 if (apnContext.isEnabled()) { 2819 apnContext.setReason(Phone.REASON_DATA_DEPENDENCY_MET); 2820 } else { 2821 apnContext.setReason(Phone.REASON_DATA_ENABLED); 2822 } 2823 if (apnContext.getState() == DctConstants.State.FAILED) { 2824 apnContext.setState(DctConstants.State.IDLE); 2825 } 2826 } 2827 apnContext.setEnabled(true); 2828 apnContext.resetErrorCodeRetries(); 2829 2830 if (mConfigReady || apnContext.getApnTypeBitmask() == ApnSetting.TYPE_EMERGENCY) { 2831 trySetupData(apnContext, requestType, onHandoverCompleteMsg); 2832 } else { 2833 log("onEnableApn: config not ready yet."); 2834 } 2835 } 2836 disableApn(@pnType int apnType, @ReleaseNetworkType int releaseType)2837 public void disableApn(@ApnType int apnType, @ReleaseNetworkType int releaseType) { 2838 sendMessage(obtainMessage(DctConstants.EVENT_DISABLE_APN, apnType, releaseType)); 2839 } 2840 onDisableApn(@pnType int apnType, @ReleaseNetworkType int releaseType)2841 private void onDisableApn(@ApnType int apnType, 2842 @ReleaseNetworkType int releaseType) { 2843 ApnContext apnContext = mApnContextsByType.get(apnType); 2844 if (apnContext == null) { 2845 loge("disableApn(" + apnType + "): NO ApnContext"); 2846 return; 2847 } 2848 2849 boolean cleanup = false; 2850 String str = "onDisableApn: apnType=" + ApnSetting.getApnTypeString(apnType) 2851 + ", release type=" + releaseTypeToString(releaseType); 2852 if (DBG) log(str); 2853 ApnContext.requestLog(apnContext, str); 2854 2855 if (apnContext.isReady()) { 2856 cleanup = (releaseType == RELEASE_TYPE_DETACH 2857 || releaseType == RELEASE_TYPE_HANDOVER); 2858 if (apnContext.isDependencyMet()) { 2859 apnContext.setReason(Phone.REASON_DATA_DISABLED_INTERNAL); 2860 // If ConnectivityService has disabled this network, stop trying to bring 2861 // it up, but do not tear it down - ConnectivityService will do that 2862 // directly by talking with the DataConnection. 2863 // 2864 // This doesn't apply to DUN. When the user disable tethering, we would like to 2865 // detach the APN context from the data connection so the data connection can be 2866 // torn down if no other APN context attached to it. 2867 if (ApnSetting.TYPE_DUN_STRING.equals(apnContext.getApnType()) 2868 || apnContext.getState() != DctConstants.State.CONNECTED) { 2869 str = "Clean up the connection. Apn type = " + apnContext.getApnType() 2870 + ", state = " + apnContext.getState(); 2871 if (DBG) log(str); 2872 ApnContext.requestLog(apnContext, str); 2873 cleanup = true; 2874 } 2875 } else { 2876 apnContext.setReason(Phone.REASON_DATA_DEPENDENCY_UNMET); 2877 } 2878 } 2879 2880 apnContext.setEnabled(false); 2881 if (cleanup) { 2882 cleanUpConnectionInternal(true, releaseType, apnContext); 2883 } 2884 2885 if (isOnlySingleDcAllowed(getDataRat()) && !isHigherPriorityApnContextActive(apnContext)) { 2886 if (DBG) log("disableApn:isOnlySingleDcAllowed true & higher priority APN disabled"); 2887 // If the highest priority APN is disabled and only single 2888 // data call is allowed, try to setup data call on other connectable APN. 2889 setupDataOnAllConnectableApns(Phone.REASON_SINGLE_PDN_ARBITRATION, 2890 RetryFailures.ALWAYS); 2891 } 2892 } 2893 2894 /** 2895 * Modify {@link android.provider.Settings.Global#DATA_ROAMING} value for user modification only 2896 */ setDataRoamingEnabledByUser(boolean enabled)2897 public void setDataRoamingEnabledByUser(boolean enabled) { 2898 mDataEnabledSettings.setDataRoamingEnabled(enabled); 2899 setDataRoamingFromUserAction(true); 2900 if (DBG) { 2901 log("setDataRoamingEnabledByUser: set phoneSubId=" + mPhone.getSubId() 2902 + " isRoaming=" + enabled); 2903 } 2904 } 2905 2906 /** 2907 * Return current {@link android.provider.Settings.Global#DATA_ROAMING} value. 2908 */ getDataRoamingEnabled()2909 public boolean getDataRoamingEnabled() { 2910 boolean isDataRoamingEnabled = mDataEnabledSettings.getDataRoamingEnabled(); 2911 2912 if (VDBG) { 2913 log("getDataRoamingEnabled: phoneSubId=" + mPhone.getSubId() 2914 + " isDataRoamingEnabled=" + isDataRoamingEnabled); 2915 } 2916 return isDataRoamingEnabled; 2917 } 2918 2919 /** 2920 * Set default value for {@link android.provider.Settings.Global#DATA_ROAMING} 2921 * if the setting is not from user actions. default value is based on carrier config and system 2922 * properties. 2923 */ setDefaultDataRoamingEnabled()2924 private void setDefaultDataRoamingEnabled() { 2925 // For single SIM phones, this is a per phone property. 2926 String setting = Settings.Global.DATA_ROAMING; 2927 boolean useCarrierSpecificDefault = false; 2928 if (mTelephonyManager.getSimCount() != 1) { 2929 setting = setting + mPhone.getSubId(); 2930 try { 2931 Settings.Global.getInt(mResolver, setting); 2932 } catch (SettingNotFoundException ex) { 2933 // For msim, update to carrier default if uninitialized. 2934 useCarrierSpecificDefault = true; 2935 } 2936 } else if (!isDataRoamingFromUserAction()) { 2937 // for single sim device, update to carrier default if user action is not set 2938 useCarrierSpecificDefault = true; 2939 } 2940 log("setDefaultDataRoamingEnabled: useCarrierSpecificDefault " 2941 + useCarrierSpecificDefault); 2942 if (useCarrierSpecificDefault) { 2943 boolean defaultVal = mDataEnabledSettings.getDefaultDataRoamingEnabled(); 2944 mDataEnabledSettings.setDataRoamingEnabled(defaultVal); 2945 } 2946 } 2947 isDataRoamingFromUserAction()2948 private boolean isDataRoamingFromUserAction() { 2949 final SharedPreferences sp = PreferenceManager 2950 .getDefaultSharedPreferences(mPhone.getContext()); 2951 // since we don't want to unset user preference from system update, pass true as the default 2952 // value if shared pref does not exist and set shared pref to false explicitly from factory 2953 // reset. 2954 if (!sp.contains(Phone.DATA_ROAMING_IS_USER_SETTING_KEY)) { 2955 sp.edit().putBoolean(Phone.DATA_ROAMING_IS_USER_SETTING_KEY, false).commit(); 2956 } 2957 return sp.getBoolean(Phone.DATA_ROAMING_IS_USER_SETTING_KEY, true); 2958 } 2959 setDataRoamingFromUserAction(boolean isUserAction)2960 private void setDataRoamingFromUserAction(boolean isUserAction) { 2961 final SharedPreferences.Editor sp = PreferenceManager 2962 .getDefaultSharedPreferences(mPhone.getContext()).edit(); 2963 sp.putBoolean(Phone.DATA_ROAMING_IS_USER_SETTING_KEY, isUserAction).commit(); 2964 } 2965 2966 // When the data roaming status changes from roaming to non-roaming. onDataRoamingOff()2967 private void onDataRoamingOff() { 2968 if (DBG) log("onDataRoamingOff"); 2969 2970 reevaluateDataConnections(); 2971 2972 if (!getDataRoamingEnabled()) { 2973 // TODO: Remove this once all old vendor RILs are gone. We don't need to set initial apn 2974 // attach and send the data profile again as the modem should have both roaming and 2975 // non-roaming protocol in place. Modem should choose the right protocol based on the 2976 // roaming condition. 2977 setDataProfilesAsNeeded(); 2978 setInitialAttachApn(); 2979 2980 // If the user did not enable data roaming, now when we transit from roaming to 2981 // non-roaming, we should try to reestablish the data connection. 2982 2983 setupDataOnAllConnectableApns(Phone.REASON_ROAMING_OFF, RetryFailures.ALWAYS); 2984 } 2985 } 2986 2987 // This method is called 2988 // 1. When the data roaming status changes from non-roaming to roaming. 2989 // 2. When allowed data roaming settings is changed by the user. onDataRoamingOnOrSettingsChanged(int messageType)2990 private void onDataRoamingOnOrSettingsChanged(int messageType) { 2991 if (DBG) log("onDataRoamingOnOrSettingsChanged"); 2992 // Used to differentiate data roaming turned on vs settings changed. 2993 boolean settingChanged = (messageType == DctConstants.EVENT_ROAMING_SETTING_CHANGE); 2994 2995 // Check if the device is actually data roaming 2996 if (!mPhone.getServiceState().getDataRoaming()) { 2997 if (DBG) log("device is not roaming. ignored the request."); 2998 return; 2999 } 3000 3001 checkDataRoamingStatus(settingChanged); 3002 3003 if (getDataRoamingEnabled()) { 3004 // If the restricted data was brought up when data roaming is disabled, and now users 3005 // enable data roaming, we need to re-evaluate the conditions and possibly change the 3006 // network's capability. 3007 if (settingChanged) { 3008 reevaluateDataConnections(); 3009 } 3010 3011 if (DBG) log("onDataRoamingOnOrSettingsChanged: setup data on roaming"); 3012 3013 setupDataOnAllConnectableApns(Phone.REASON_ROAMING_ON, RetryFailures.ALWAYS); 3014 } else { 3015 // If the user does not turn on data roaming, when we transit from non-roaming to 3016 // roaming, we need to tear down the data connection otherwise the user might be 3017 // charged for data roaming usage. 3018 if (DBG) log("onDataRoamingOnOrSettingsChanged: Tear down data connection on roaming."); 3019 cleanUpAllConnectionsInternal(true, Phone.REASON_ROAMING_ON); 3020 } 3021 } 3022 3023 // We want to track possible roaming data leakage. Which is, if roaming setting 3024 // is disabled, yet we still setup a roaming data connection or have a connected ApnContext 3025 // switched to roaming. When this happens, we log it in a local log. checkDataRoamingStatus(boolean settingChanged)3026 private void checkDataRoamingStatus(boolean settingChanged) { 3027 if (!settingChanged && !getDataRoamingEnabled() 3028 && mPhone.getServiceState().getDataRoaming()) { 3029 for (ApnContext apnContext : mApnContexts.values()) { 3030 if (apnContext.getState() == DctConstants.State.CONNECTED) { 3031 mDataRoamingLeakageLog.log("PossibleRoamingLeakage " 3032 + " connection params: " + (apnContext.getDataConnection() != null 3033 ? apnContext.getDataConnection().getConnectionParams() : "")); 3034 } 3035 } 3036 } 3037 } 3038 onRadioAvailable()3039 private void onRadioAvailable() { 3040 if (DBG) log("onRadioAvailable"); 3041 if (!areAllDataDisconnected()) { 3042 cleanUpConnectionInternal(true, RELEASE_TYPE_DETACH, null); 3043 } 3044 } 3045 onRadioOffOrNotAvailable()3046 private void onRadioOffOrNotAvailable() { 3047 // Make sure our reconnect delay starts at the initial value 3048 // next time the radio comes on 3049 3050 mReregisterOnReconnectFailure = false; 3051 3052 // Clear auto attach as modem is expected to do a new attach 3053 mAutoAttachEnabled.set(false); 3054 3055 if (mPhone.getSimulatedRadioControl() != null) { 3056 // Assume data is connected on the simulator 3057 // FIXME this can be improved 3058 log("We're on the simulator; assuming radio off is meaningless"); 3059 } else { 3060 if (DBG) log("onRadioOffOrNotAvailable: is off and clean up all connections"); 3061 cleanUpAllConnectionsInternal(false, Phone.REASON_RADIO_TURNED_OFF); 3062 } 3063 } 3064 completeConnection(ApnContext apnContext, @RequestNetworkType int type)3065 private void completeConnection(ApnContext apnContext, @RequestNetworkType int type) { 3066 3067 if (DBG) log("completeConnection: successful, notify the world apnContext=" + apnContext); 3068 3069 if (mIsProvisioning && !TextUtils.isEmpty(mProvisioningUrl)) { 3070 if (DBG) { 3071 log("completeConnection: MOBILE_PROVISIONING_ACTION url=" 3072 + mProvisioningUrl); 3073 } 3074 Intent newIntent = Intent.makeMainSelectorActivity(Intent.ACTION_MAIN, 3075 Intent.CATEGORY_APP_BROWSER); 3076 newIntent.setData(Uri.parse(mProvisioningUrl)); 3077 newIntent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT | 3078 Intent.FLAG_ACTIVITY_NEW_TASK); 3079 try { 3080 mPhone.getContext().startActivity(newIntent); 3081 } catch (ActivityNotFoundException e) { 3082 loge("completeConnection: startActivityAsUser failed" + e); 3083 } 3084 } 3085 mIsProvisioning = false; 3086 mProvisioningUrl = null; 3087 if (mProvisioningSpinner != null) { 3088 sendMessage(obtainMessage(DctConstants.CMD_CLEAR_PROVISIONING_SPINNER, 3089 mProvisioningSpinner)); 3090 } 3091 3092 startNetStatPoll(); 3093 startDataStallAlarm(DATA_STALL_NOT_SUSPECTED); 3094 3095 PersistableBundle b = getCarrierConfig(); 3096 if (apnContext.getApnTypeBitmask() == ApnSetting.TYPE_DEFAULT 3097 && b.getBoolean(CarrierConfigManager 3098 .KEY_DISPLAY_NO_DATA_NOTIFICATION_ON_PERMANENT_FAILURE_BOOL)) { 3099 NotificationManager notificationManager = (NotificationManager) 3100 mPhone.getContext().getSystemService(Context.NOTIFICATION_SERVICE); 3101 notificationManager.cancel(Integer.toString(mPhone.getSubId()), 3102 NO_DATA_NOTIFICATION); 3103 } 3104 } 3105 3106 /** 3107 * A SETUP (aka bringUp) has completed, possibly with an error. If 3108 * there is an error this method will call {@link #onDataSetupCompleteError}. 3109 */ onDataSetupComplete(ApnContext apnContext, boolean success, @DataFailureCause int cause, @RequestNetworkType int requestType, @HandoverFailureMode int handoverFailureMode)3110 protected void onDataSetupComplete(ApnContext apnContext, boolean success, 3111 @DataFailureCause int cause, @RequestNetworkType int requestType, 3112 @HandoverFailureMode int handoverFailureMode) { 3113 boolean fallbackOnFailedHandover = shouldFallbackOnFailedHandover( 3114 handoverFailureMode, requestType, cause); 3115 3116 if (success && (handoverFailureMode != DataCallResponse.HANDOVER_FAILURE_MODE_UNKNOWN 3117 && handoverFailureMode != DataCallResponse.HANDOVER_FAILURE_MODE_LEGACY)) { 3118 Log.wtf(mLogTag, "bad failure mode: " 3119 + DataCallResponse.failureModeToString(handoverFailureMode)); 3120 } else if (handoverFailureMode 3121 != DataCallResponse.HANDOVER_FAILURE_MODE_NO_FALLBACK_RETRY_HANDOVER 3122 && cause != DataFailCause.SERVICE_TEMPORARILY_UNAVAILABLE) { 3123 sendHandoverCompleteMessages(apnContext.getApnTypeBitmask(), success, 3124 fallbackOnFailedHandover); 3125 } 3126 3127 if (success) { 3128 DataConnection dataConnection = apnContext.getDataConnection(); 3129 3130 if (RADIO_TESTS) { 3131 // Note: To change radio.test.onDSC.null.dcac from command line you need to 3132 // adb root and adb remount and from the command line you can only change the 3133 // value to 1 once. To change it a second time you can reboot or execute 3134 // adb shell stop and then adb shell start. The command line to set the value is: 3135 // adb shell sqlite3 /data/data/com.android.providers.settings/databases/settings.db "insert into system (name,value) values ('radio.test.onDSC.null.dcac', '1');" 3136 ContentResolver cr = mPhone.getContext().getContentResolver(); 3137 String radioTestProperty = "radio.test.onDSC.null.dcac"; 3138 if (Settings.System.getInt(cr, radioTestProperty, 0) == 1) { 3139 log("onDataSetupComplete: " + radioTestProperty + 3140 " is true, set dcac to null and reset property to false"); 3141 dataConnection = null; 3142 Settings.System.putInt(cr, radioTestProperty, 0); 3143 log("onDataSetupComplete: " + radioTestProperty + "=" + 3144 Settings.System.getInt(mPhone.getContext().getContentResolver(), 3145 radioTestProperty, -1)); 3146 } 3147 } 3148 if (dataConnection == null) { 3149 log("onDataSetupComplete: no connection to DC, handle as error"); 3150 onDataSetupCompleteError(apnContext, requestType, false); 3151 } else { 3152 ApnSetting apn = apnContext.getApnSetting(); 3153 if (DBG) { 3154 log("onDataSetupComplete: success apn=" + (apn == null ? "unknown" 3155 : apn.getApnName())); 3156 } 3157 3158 // everything is setup 3159 if (TextUtils.equals(apnContext.getApnType(), ApnSetting.TYPE_DEFAULT_STRING) 3160 && mCanSetPreferApn && mPreferredApn == null) { 3161 if (DBG) log("onDataSetupComplete: PREFERRED APN is null"); 3162 mPreferredApn = apn; 3163 if (mPreferredApn != null) { 3164 setPreferredApn(mPreferredApn.getId()); 3165 } 3166 } 3167 3168 // A connection is setup 3169 apnContext.setState(DctConstants.State.CONNECTED); 3170 3171 checkDataRoamingStatus(false); 3172 3173 boolean isProvApn = apnContext.isProvisioningApn(); 3174 final ConnectivityManager cm = (ConnectivityManager) mPhone.getContext() 3175 .getSystemService(Context.CONNECTIVITY_SERVICE); 3176 if (mProvisionBroadcastReceiver != null) { 3177 mPhone.getContext().unregisterReceiver(mProvisionBroadcastReceiver); 3178 mProvisionBroadcastReceiver = null; 3179 } 3180 3181 if ((!isProvApn) || mIsProvisioning) { 3182 if (mIsProvisioning) { 3183 // Hide any notification that was showing previously 3184 hideProvisioningNotification(); 3185 } 3186 3187 // Complete the connection normally notifying the world we're connected. 3188 // We do this if this isn't a special provisioning apn or if we've been 3189 // told its time to provision. 3190 completeConnection(apnContext, requestType); 3191 } else { 3192 // This is a provisioning APN that we're reporting as connected. Later 3193 // when the user desires to upgrade this to a "default" connection, 3194 // mIsProvisioning == true, we'll go through the code path above. 3195 // mIsProvisioning becomes true when CMD_ENABLE_MOBILE_PROVISIONING 3196 // is sent to the DCT. 3197 if (DBG) { 3198 log("onDataSetupComplete: successful, BUT send connected to prov apn as" 3199 + " mIsProvisioning:" + mIsProvisioning + " == false" 3200 + " && (isProvisioningApn:" + isProvApn + " == true"); 3201 } 3202 3203 // While radio is up, grab provisioning URL. The URL contains ICCID which 3204 // disappears when radio is off. 3205 mProvisionBroadcastReceiver = new ProvisionNotificationBroadcastReceiver( 3206 mPhone.getMobileProvisioningUrl(), 3207 mTelephonyManager.getNetworkOperatorName()); 3208 mPhone.getContext().registerReceiver(mProvisionBroadcastReceiver, 3209 new IntentFilter(INTENT_PROVISION)); 3210 3211 // Put up user notification that sign-in is required. 3212 showProvisioningNotification(); 3213 3214 // Turn off radio to save battery and avoid wasting carrier resources. 3215 // The network isn't usable and network validation will just fail anyhow. 3216 setRadio(false); 3217 } 3218 if (DBG) { 3219 log("onDataSetupComplete: SETUP complete type=" + apnContext.getApnType()); 3220 } 3221 if (TelephonyUtils.IS_DEBUGGABLE) { 3222 // adb shell setprop persist.radio.test.pco [pco_val] 3223 String radioTestProperty = "persist.radio.test.pco"; 3224 int pcoVal = SystemProperties.getInt(radioTestProperty, -1); 3225 if (pcoVal != -1) { 3226 log("PCO testing: read pco value from persist.radio.test.pco " + pcoVal); 3227 final byte[] value = new byte[1]; 3228 value[0] = (byte) pcoVal; 3229 final Intent intent = 3230 new Intent(TelephonyManager.ACTION_CARRIER_SIGNAL_PCO_VALUE); 3231 intent.putExtra(TelephonyManager.EXTRA_APN_TYPE, ApnSetting.TYPE_DEFAULT); 3232 intent.putExtra(TelephonyManager.EXTRA_APN_PROTOCOL, 3233 ApnSetting.PROTOCOL_IPV4V6); 3234 intent.putExtra(TelephonyManager.EXTRA_PCO_ID, 0xFF00); 3235 intent.putExtra(TelephonyManager.EXTRA_PCO_VALUE, value); 3236 mPhone.getCarrierSignalAgent().notifyCarrierSignalReceivers(intent); 3237 } 3238 } 3239 } 3240 } else { 3241 if (DBG) { 3242 ApnSetting apn = apnContext.getApnSetting(); 3243 log("onDataSetupComplete: error apn=" + apn.getApnName() + ", cause=" 3244 + DataFailCause.toString(cause) + ", requestType=" 3245 + requestTypeToString(requestType)); 3246 } 3247 if (DataFailCause.isEventLoggable(cause)) { 3248 // Log this failure to the Event Logs. 3249 int cid = getCellLocationId(); 3250 EventLog.writeEvent(EventLogTags.PDP_SETUP_FAIL, 3251 cause, cid, mTelephonyManager.getNetworkType()); 3252 } 3253 ApnSetting apn = apnContext.getApnSetting(); 3254 3255 // Compose broadcast intent send to the specific carrier signaling receivers 3256 Intent intent = new Intent(TelephonyManager 3257 .ACTION_CARRIER_SIGNAL_REQUEST_NETWORK_FAILED); 3258 intent.putExtra(TelephonyManager.EXTRA_DATA_FAIL_CAUSE, cause); 3259 intent.putExtra(TelephonyManager.EXTRA_APN_TYPE, 3260 ApnSetting.getApnTypesBitmaskFromString(apnContext.getApnType())); 3261 mPhone.getCarrierSignalAgent().notifyCarrierSignalReceivers(intent); 3262 3263 if (DataFailCause.isRadioRestartFailure(mPhone.getContext(), cause, mPhone.getSubId()) 3264 || apnContext.restartOnError(cause)) { 3265 if (DBG) log("Modem restarted."); 3266 sendRestartRadio(); 3267 } 3268 3269 // If the data call failure cause is a permanent failure, we mark the APN as permanent 3270 // failed. 3271 if (isPermanentFailure(cause)) { 3272 log("cause=" + DataFailCause.toString(cause) 3273 + ", mark apn as permanent failed. apn = " + apn); 3274 apnContext.markApnPermanentFailed(apn); 3275 3276 PersistableBundle b = getCarrierConfig(); 3277 if (apnContext.getApnTypeBitmask() == ApnSetting.TYPE_DEFAULT 3278 && b.getBoolean(CarrierConfigManager 3279 .KEY_DISPLAY_NO_DATA_NOTIFICATION_ON_PERMANENT_FAILURE_BOOL)) { 3280 NotificationManager notificationManager = (NotificationManager) 3281 mPhone.getContext().getSystemService(Context.NOTIFICATION_SERVICE); 3282 3283 CharSequence title = mPhone.getContext().getText( 3284 com.android.internal.R.string.RestrictedOnDataTitle); 3285 CharSequence details = mPhone.getContext().getText( 3286 com.android.internal.R.string.RestrictedStateContent); 3287 3288 Notification notification = new Notification.Builder(mPhone.getContext(), 3289 NotificationChannelController.CHANNEL_ID_MOBILE_DATA_STATUS) 3290 .setWhen(System.currentTimeMillis()) 3291 .setAutoCancel(true) 3292 .setSmallIcon(com.android.internal.R.drawable.stat_sys_warning) 3293 .setTicker(title) 3294 .setColor(mPhone.getContext().getResources().getColor( 3295 com.android.internal.R.color.system_notification_accent_color)) 3296 .setContentTitle(title) 3297 .setStyle(new Notification.BigTextStyle().bigText(details)) 3298 .setContentText(details) 3299 .build(); 3300 notificationManager.notify(Integer.toString(mPhone.getSubId()), 3301 NO_DATA_NOTIFICATION, notification); 3302 } 3303 } 3304 3305 int newRequestType = calculateNewRetryRequestType(handoverFailureMode, requestType, 3306 cause); 3307 onDataSetupCompleteError(apnContext, newRequestType, fallbackOnFailedHandover); 3308 } 3309 } 3310 3311 3312 3313 /** 3314 * Error has occurred during the SETUP {aka bringUP} request and the DCT 3315 * should either try the next waiting APN or start over from the 3316 * beginning if the list is empty. Between each SETUP request there will 3317 * be a delay defined by {@link ApnContext#getDelayForNextApn(boolean)}. 3318 */ onDataSetupCompleteError(ApnContext apnContext, @RequestNetworkType int requestType, boolean fallbackOnFailedHandover)3319 protected void onDataSetupCompleteError(ApnContext apnContext, 3320 @RequestNetworkType int requestType, boolean fallbackOnFailedHandover) { 3321 long delay = apnContext.getDelayForNextApn(mFailFast); 3322 // Check if we need to retry or not. 3323 if (delay >= 0 && delay != RetryManager.NO_RETRY && !fallbackOnFailedHandover) { 3324 if (DBG) { 3325 log("onDataSetupCompleteError: APN type=" + apnContext.getApnType() 3326 + ". Request type=" + requestTypeToString(requestType) + ", Retry in " 3327 + delay + "ms."); 3328 } 3329 startReconnect(delay, apnContext, requestType); 3330 } else { 3331 // If we are not going to retry any APN, set this APN context to failed state. 3332 // This would be the final state of a data connection. 3333 apnContext.setState(DctConstants.State.FAILED); 3334 apnContext.setDataConnection(null); 3335 log("onDataSetupCompleteError: Stop retrying APNs. delay=" + delay 3336 + ", requestType=" + requestTypeToString(requestType)); 3337 //send request network complete messages as needed 3338 sendHandoverCompleteMessages(apnContext.getApnTypeBitmask(), false, 3339 fallbackOnFailedHandover); 3340 } 3341 } 3342 3343 /** 3344 * Called when EVENT_NETWORK_STATUS_CHANGED is received. 3345 * 3346 * @param status One of {@code NetworkAgent.VALID_NETWORK} or 3347 * {@code NetworkAgent.INVALID_NETWORK}. 3348 * @param cid context id {@code cid} 3349 * @param redirectUrl If the Internet probe was redirected, this 3350 * is the destination it was redirected to, otherwise {@code null} 3351 */ onNetworkStatusChanged(int status, int cid, String redirectUrl)3352 private void onNetworkStatusChanged(int status, int cid, String redirectUrl) { 3353 if (!TextUtils.isEmpty(redirectUrl)) { 3354 Intent intent = new Intent(TelephonyManager.ACTION_CARRIER_SIGNAL_REDIRECTED); 3355 intent.putExtra(TelephonyManager.EXTRA_REDIRECTION_URL, redirectUrl); 3356 mPhone.getCarrierSignalAgent().notifyCarrierSignalReceivers(intent); 3357 log("Notify carrier signal receivers with redirectUrl: " + redirectUrl); 3358 } else { 3359 final boolean isValid = status == NetworkAgent.VALIDATION_STATUS_VALID; 3360 final DataConnection dc = getDataConnectionByContextId(cid); 3361 if (!mDsRecoveryHandler.isRecoveryOnBadNetworkEnabled()) { 3362 if (DBG) log("Skip data stall recovery on network status change with in threshold"); 3363 return; 3364 } 3365 if (mTransportType != AccessNetworkConstants.TRANSPORT_TYPE_WWAN) { 3366 if (DBG) log("Skip data stall recovery on non WWAN"); 3367 return; 3368 } 3369 if (dc != null && dc.isValidationRequired()) { 3370 mDsRecoveryHandler.processNetworkStatusChanged(isValid); 3371 } 3372 } 3373 } 3374 3375 /** 3376 * Called when EVENT_DISCONNECT_DONE is received. 3377 */ onDisconnectDone(ApnContext apnContext)3378 private void onDisconnectDone(ApnContext apnContext) { 3379 if(DBG) log("onDisconnectDone: EVENT_DISCONNECT_DONE apnContext=" + apnContext); 3380 apnContext.setState(DctConstants.State.IDLE); 3381 // If all data connection are gone, check whether Airplane mode request was pending. 3382 if (areAllDataDisconnected() 3383 && mPhone.getServiceStateTracker().processPendingRadioPowerOffAfterDataOff()) { 3384 if (DBG) log("onDisconnectDone: radio will be turned off, no retries"); 3385 // Radio will be turned off. No need to retry data setup 3386 apnContext.setApnSetting(null); 3387 apnContext.setDataConnection(null); 3388 3389 // Need to notify disconnect as well, in the case of switching Airplane mode. 3390 // Otherwise, it would cause 30s delayed to turn on Airplane mode. 3391 notifyAllDataDisconnected(); 3392 return; 3393 } 3394 // If APN is still enabled, try to bring it back up automatically 3395 if (mAttached.get() && apnContext.isReady() && retryAfterDisconnected(apnContext)) { 3396 // Wait a bit before trying the next APN, so that 3397 // we're not tying up the RIL command channel. 3398 // This also helps in any external dependency to turn off the context. 3399 if (DBG) log("onDisconnectDone: attached, ready and retry after disconnect"); 3400 3401 // See if there are still handover request pending that we need to retry handover 3402 // after previous data gets disconnected. 3403 if (isHandoverPending(apnContext.getApnTypeBitmask())) { 3404 if (DBG) log("Handover request pending. Retry handover immediately."); 3405 startReconnect(0, apnContext, REQUEST_TYPE_HANDOVER); 3406 } else { 3407 long delay = apnContext.getRetryAfterDisconnectDelay(); 3408 if (delay > 0) { 3409 // Data connection is in IDLE state, so when we reconnect later, we'll rebuild 3410 // the waiting APN list, which will also reset/reconfigure the retry manager. 3411 startReconnect(delay, apnContext, REQUEST_TYPE_NORMAL); 3412 } 3413 } 3414 } else { 3415 boolean restartRadioAfterProvisioning = mPhone.getContext().getResources().getBoolean( 3416 com.android.internal.R.bool.config_restartRadioAfterProvisioning); 3417 3418 if (apnContext.isProvisioningApn() && restartRadioAfterProvisioning) { 3419 log("onDisconnectDone: restartRadio after provisioning"); 3420 restartRadio(); 3421 } 3422 apnContext.setApnSetting(null); 3423 apnContext.setDataConnection(null); 3424 if (isOnlySingleDcAllowed(getDataRat())) { 3425 if(DBG) log("onDisconnectDone: isOnlySigneDcAllowed true so setup single apn"); 3426 setupDataOnAllConnectableApns(Phone.REASON_SINGLE_PDN_ARBITRATION, 3427 RetryFailures.ALWAYS); 3428 } else { 3429 if(DBG) log("onDisconnectDone: not retrying"); 3430 } 3431 } 3432 3433 if (areAllDataDisconnected()) { 3434 apnContext.setConcurrentVoiceAndDataAllowed( 3435 mPhone.getServiceStateTracker().isConcurrentVoiceAndDataAllowed()); 3436 notifyAllDataDisconnected(); 3437 } 3438 3439 } 3440 onVoiceCallStarted()3441 private void onVoiceCallStarted() { 3442 if (DBG) log("onVoiceCallStarted"); 3443 mInVoiceCall = true; 3444 if (isAnyDataConnected() 3445 && !mPhone.getServiceStateTracker().isConcurrentVoiceAndDataAllowed()) { 3446 if (DBG) log("onVoiceCallStarted stop polling"); 3447 stopNetStatPoll(); 3448 stopDataStallAlarm(); 3449 } 3450 } 3451 onVoiceCallEnded()3452 protected void onVoiceCallEnded() { 3453 if (DBG) log("onVoiceCallEnded"); 3454 mInVoiceCall = false; 3455 if (isAnyDataConnected()) { 3456 if (!mPhone.getServiceStateTracker().isConcurrentVoiceAndDataAllowed()) { 3457 startNetStatPoll(); 3458 startDataStallAlarm(DATA_STALL_NOT_SUSPECTED); 3459 } else { 3460 // clean slate after call end. 3461 resetPollStats(); 3462 } 3463 } 3464 // reset reconnect timer 3465 setupDataOnAllConnectableApns(Phone.REASON_VOICE_CALL_ENDED, RetryFailures.ALWAYS); 3466 } 3467 /** 3468 * @return {@code true} if there is any data in connected state. 3469 */ 3470 @VisibleForTesting isAnyDataConnected()3471 public boolean isAnyDataConnected() { 3472 for (DataConnection dc : mDataConnections.values()) { 3473 if (dc.isActive()) { 3474 return true; 3475 } 3476 } 3477 return false; 3478 } 3479 3480 /** 3481 * @return {@code true} if all data connections are in disconnected state. 3482 */ areAllDataDisconnected()3483 public boolean areAllDataDisconnected() { 3484 for (DataConnection dc : mDataConnections.values()) { 3485 if (!dc.isInactive()) { 3486 if (DBG) log("areAllDataDisconnected false due to DC: " + dc.getName()); 3487 return false; 3488 } 3489 } 3490 return true; 3491 } 3492 setDataProfilesAsNeeded()3493 protected void setDataProfilesAsNeeded() { 3494 if (DBG) log("setDataProfilesAsNeeded"); 3495 3496 ArrayList<DataProfile> dataProfileList = new ArrayList<>(); 3497 3498 int preferredApnSetId = getPreferredApnSetId(); 3499 for (ApnSetting apn : mAllApnSettings) { 3500 if (apn.getApnSetId() == Telephony.Carriers.MATCH_ALL_APN_SET_ID 3501 || preferredApnSetId == apn.getApnSetId()) { 3502 DataProfile dp = new DataProfile.Builder() 3503 .setApnSetting(apn) 3504 .setPreferred(apn.equals(getPreferredApn())) 3505 .build(); 3506 if (!dataProfileList.contains(dp)) { 3507 dataProfileList.add(dp); 3508 } 3509 } else { 3510 if (VDBG) { 3511 log("setDataProfilesAsNeeded: APN set id " + apn.getApnSetId() 3512 + " does not match the preferred set id " + preferredApnSetId); 3513 } 3514 } 3515 } 3516 3517 // Check if the data profiles we are sending are same as we did last time. We don't want to 3518 // send the redundant profiles to the modem. Also if there the list is empty, we don't 3519 // send it to the modem. 3520 if (!dataProfileList.isEmpty() 3521 && (dataProfileList.size() != mLastDataProfileList.size() 3522 || !mLastDataProfileList.containsAll(dataProfileList))) { 3523 mDataServiceManager.setDataProfile(dataProfileList, 3524 mPhone.getServiceState().getDataRoamingFromRegistration(), null); 3525 } 3526 } 3527 3528 /** 3529 * Based on the sim operator numeric, create a list for all possible 3530 * Data Connections and setup the preferredApn. 3531 */ createAllApnList()3532 protected void createAllApnList() { 3533 mAllApnSettings.clear(); 3534 String operator = mPhone.getOperatorNumeric(); 3535 3536 // ORDER BY Telephony.Carriers._ID ("_id") 3537 Cursor cursor = mPhone.getContext().getContentResolver().query( 3538 Uri.withAppendedPath(Telephony.Carriers.SIM_APN_URI, "filtered/subId/" 3539 + mPhone.getSubId()), null, null, null, Telephony.Carriers._ID); 3540 3541 if (cursor != null) { 3542 while (cursor.moveToNext()) { 3543 ApnSetting apn = ApnSetting.makeApnSetting(cursor); 3544 if (apn == null) { 3545 continue; 3546 } 3547 mAllApnSettings.add(apn); 3548 } 3549 cursor.close(); 3550 } else { 3551 if (DBG) log("createAllApnList: cursor is null"); 3552 mApnSettingsInitializationLog.log("cursor is null for carrier, operator: " 3553 + operator); 3554 } 3555 3556 dedupeApnSettings(); 3557 3558 if (mAllApnSettings.isEmpty()) { 3559 log("createAllApnList: No APN found for carrier, operator: " + operator); 3560 mApnSettingsInitializationLog.log("no APN found for carrier, operator: " 3561 + operator); 3562 mPreferredApn = null; 3563 } else { 3564 mPreferredApn = getPreferredApn(); 3565 if (DBG) log("createAllApnList: mPreferredApn=" + mPreferredApn); 3566 } 3567 3568 addDefaultApnSettingsAsNeeded(); 3569 if (DBG) log("createAllApnList: X mAllApnSettings=" + mAllApnSettings); 3570 } 3571 dedupeApnSettings()3572 private void dedupeApnSettings() { 3573 ArrayList<ApnSetting> resultApns = new ArrayList<ApnSetting>(); 3574 3575 // coalesce APNs if they are similar enough to prevent 3576 // us from bringing up two data calls with the same interface 3577 int i = 0; 3578 while (i < mAllApnSettings.size() - 1) { 3579 ApnSetting first = mAllApnSettings.get(i); 3580 ApnSetting second = null; 3581 int j = i + 1; 3582 while (j < mAllApnSettings.size()) { 3583 second = mAllApnSettings.get(j); 3584 if (first.similar(second)) { 3585 ApnSetting newApn = mergeApns(first, second); 3586 mAllApnSettings.set(i, newApn); 3587 first = newApn; 3588 mAllApnSettings.remove(j); 3589 } else { 3590 j++; 3591 } 3592 } 3593 i++; 3594 } 3595 } 3596 mergeApns(ApnSetting dest, ApnSetting src)3597 private ApnSetting mergeApns(ApnSetting dest, ApnSetting src) { 3598 int id = dest.getId(); 3599 if ((src.getApnTypeBitmask() & ApnSetting.TYPE_DEFAULT) == ApnSetting.TYPE_DEFAULT) { 3600 id = src.getId(); 3601 } 3602 final int resultApnType = src.getApnTypeBitmask() | dest.getApnTypeBitmask(); 3603 Uri mmsc = (dest.getMmsc() == null ? src.getMmsc() : dest.getMmsc()); 3604 String mmsProxy = TextUtils.isEmpty(dest.getMmsProxyAddressAsString()) 3605 ? src.getMmsProxyAddressAsString() : dest.getMmsProxyAddressAsString(); 3606 int mmsPort = dest.getMmsProxyPort() == -1 ? src.getMmsProxyPort() : dest.getMmsProxyPort(); 3607 String proxy = TextUtils.isEmpty(dest.getProxyAddressAsString()) 3608 ? src.getProxyAddressAsString() : dest.getProxyAddressAsString(); 3609 int port = dest.getProxyPort() == -1 ? src.getProxyPort() : dest.getProxyPort(); 3610 int protocol = src.getProtocol() == ApnSetting.PROTOCOL_IPV4V6 ? src.getProtocol() 3611 : dest.getProtocol(); 3612 int roamingProtocol = src.getRoamingProtocol() == ApnSetting.PROTOCOL_IPV4V6 3613 ? src.getRoamingProtocol() : dest.getRoamingProtocol(); 3614 int networkTypeBitmask = (dest.getNetworkTypeBitmask() == 0 3615 || src.getNetworkTypeBitmask() == 0) 3616 ? 0 : (dest.getNetworkTypeBitmask() | src.getNetworkTypeBitmask()); 3617 return new ApnSetting.Builder() 3618 .setId(id) 3619 .setOperatorNumeric(dest.getOperatorNumeric()) 3620 .setEntryName(dest.getEntryName()) 3621 .setApnName(dest.getApnName()) 3622 .setProxyAddress(proxy) 3623 .setProxyPort(port) 3624 .setMmsc(mmsc) 3625 .setMmsProxyAddress(mmsProxy) 3626 .setMmsProxyPort(mmsPort) 3627 .setUser(dest.getUser()) 3628 .setPassword(dest.getPassword()) 3629 .setAuthType(dest.getAuthType()) 3630 .setApnTypeBitmask(resultApnType) 3631 .setProtocol(protocol) 3632 .setRoamingProtocol(roamingProtocol) 3633 .setCarrierEnabled(dest.isEnabled()) 3634 .setNetworkTypeBitmask(networkTypeBitmask) 3635 .setProfileId(dest.getProfileId()) 3636 .setModemCognitive(dest.isPersistent() || src.isPersistent()) 3637 .setMaxConns(dest.getMaxConns()) 3638 .setWaitTime(dest.getWaitTime()) 3639 .setMaxConnsTime(dest.getMaxConnsTime()) 3640 .setMtuV4(dest.getMtuV4()) 3641 .setMtuV6(dest.getMtuV6()) 3642 .setMvnoType(dest.getMvnoType()) 3643 .setMvnoMatchData(dest.getMvnoMatchData()) 3644 .setApnSetId(dest.getApnSetId()) 3645 .setCarrierId(dest.getCarrierId()) 3646 .setSkip464Xlat(dest.getSkip464Xlat()) 3647 .build(); 3648 } 3649 createDataConnection()3650 private DataConnection createDataConnection() { 3651 if (DBG) log("createDataConnection E"); 3652 3653 int id = mUniqueIdGenerator.getAndIncrement(); 3654 DataConnection dataConnection = DataConnection.makeDataConnection(mPhone, id, this, 3655 mDataServiceManager, mDcTesterFailBringUpAll, mDcc); 3656 mDataConnections.put(id, dataConnection); 3657 if (DBG) log("createDataConnection() X id=" + id + " dc=" + dataConnection); 3658 return dataConnection; 3659 } 3660 destroyDataConnections()3661 private void destroyDataConnections() { 3662 if(mDataConnections != null) { 3663 if (DBG) log("destroyDataConnections: clear mDataConnectionList"); 3664 mDataConnections.clear(); 3665 } else { 3666 if (DBG) log("destroyDataConnections: mDataConnecitonList is empty, ignore"); 3667 } 3668 } 3669 3670 /** 3671 * Build a list of APNs to be used to create PDP's. 3672 * 3673 * @param requestedApnType 3674 * @return waitingApns list to be used to create PDP 3675 * error when waitingApns.isEmpty() 3676 */ buildWaitingApns(String requestedApnType, int radioTech)3677 private @NonNull ArrayList<ApnSetting> buildWaitingApns(String requestedApnType, 3678 int radioTech) { 3679 if (DBG) log("buildWaitingApns: E requestedApnType=" + requestedApnType); 3680 ArrayList<ApnSetting> apnList = new ArrayList<ApnSetting>(); 3681 3682 int requestedApnTypeBitmask = ApnSetting.getApnTypesBitmaskFromString(requestedApnType); 3683 if (requestedApnTypeBitmask == ApnSetting.TYPE_ENTERPRISE) { 3684 requestedApnTypeBitmask = ApnSetting.TYPE_DEFAULT; 3685 } 3686 if (requestedApnTypeBitmask == ApnSetting.TYPE_DUN) { 3687 ArrayList<ApnSetting> dunApns = fetchDunApns(); 3688 if (dunApns.size() > 0) { 3689 for (ApnSetting dun : dunApns) { 3690 apnList.add(dun); 3691 if (DBG) log("buildWaitingApns: X added APN_TYPE_DUN apnList=" + apnList); 3692 } 3693 return apnList; 3694 } 3695 } 3696 3697 String operator = mPhone.getOperatorNumeric(); 3698 3699 // This is a workaround for a bug (7305641) where we don't failover to other 3700 // suitable APNs if our preferred APN fails. On prepaid ATT sims we need to 3701 // failover to a provisioning APN, but once we've used their default data 3702 // connection we are locked to it for life. This change allows ATT devices 3703 // to say they don't want to use preferred at all. 3704 boolean usePreferred = true; 3705 try { 3706 usePreferred = !mPhone.getContext().getResources().getBoolean(com.android 3707 .internal.R.bool.config_dontPreferApn); 3708 } catch (Resources.NotFoundException e) { 3709 if (DBG) log("buildWaitingApns: usePreferred NotFoundException set to true"); 3710 usePreferred = true; 3711 } 3712 if (usePreferred) { 3713 mPreferredApn = getPreferredApn(); 3714 } 3715 if (DBG) { 3716 log("buildWaitingApns: usePreferred=" + usePreferred 3717 + " canSetPreferApn=" + mCanSetPreferApn 3718 + " mPreferredApn=" + mPreferredApn 3719 + " operator=" + operator + " radioTech=" + radioTech); 3720 } 3721 3722 if (usePreferred && mCanSetPreferApn && mPreferredApn != null && 3723 mPreferredApn.canHandleType(requestedApnTypeBitmask)) { 3724 if (DBG) { 3725 log("buildWaitingApns: Preferred APN:" + operator + ":" 3726 + mPreferredApn.getOperatorNumeric() + ":" + mPreferredApn); 3727 } 3728 3729 if (TextUtils.equals(mPreferredApn.getOperatorNumeric(), operator) 3730 || mPreferredApn.getCarrierId() == mPhone.getCarrierId()) { 3731 if (mPreferredApn.canSupportNetworkType( 3732 ServiceState.rilRadioTechnologyToNetworkType(radioTech))) { 3733 // Create a new instance of ApnSetting for ENTERPRISE because each 3734 // DataConnection should have its own ApnSetting. ENTERPRISE uses the same 3735 // APN as DEFAULT but is a separate DataConnection 3736 if (ApnSetting.getApnTypesBitmaskFromString(requestedApnType) 3737 == ApnSetting.TYPE_ENTERPRISE) { 3738 apnList.add(ApnSetting.makeApnSetting(mPreferredApn)); 3739 } else { 3740 apnList.add(mPreferredApn); 3741 } 3742 if (DBG) log("buildWaitingApns: X added preferred apnList=" + apnList); 3743 return apnList; 3744 } 3745 } 3746 if (DBG) log("buildWaitingApns: no preferred APN"); 3747 setPreferredApn(-1); 3748 mPreferredApn = null; 3749 } 3750 3751 if (DBG) log("buildWaitingApns: mAllApnSettings=" + mAllApnSettings); 3752 int preferredApnSetId = getPreferredApnSetId(); 3753 for (ApnSetting apn : mAllApnSettings) { 3754 if (apn.canHandleType(requestedApnTypeBitmask)) { 3755 if (apn.canSupportNetworkType( 3756 ServiceState.rilRadioTechnologyToNetworkType(radioTech))) { 3757 if (apn.getApnSetId() == Telephony.Carriers.MATCH_ALL_APN_SET_ID 3758 || preferredApnSetId == apn.getApnSetId()) { 3759 if (VDBG) log("buildWaitingApns: adding apn=" + apn); 3760 // Create a new instance of ApnSetting for ENTERPRISE because each 3761 // DataConnection should have its own ApnSetting. ENTERPRISE uses the same 3762 // APN as DEFAULT but is a separate DataConnection 3763 if (ApnSetting.getApnTypesBitmaskFromString(requestedApnType) 3764 == ApnSetting.TYPE_ENTERPRISE) { 3765 apnList.add(ApnSetting.makeApnSetting(apn)); 3766 } else { 3767 apnList.add(apn); 3768 } 3769 } else { 3770 log("buildWaitingApns: APN set id " + apn.getApnSetId() 3771 + " does not match the preferred set id " + preferredApnSetId); 3772 } 3773 } else { 3774 if (DBG) { 3775 log("buildWaitingApns: networkTypeBitmask:" 3776 + apn.getNetworkTypeBitmask() 3777 + " does not include radioTech:" 3778 + ServiceState.rilRadioTechnologyToString(radioTech)); 3779 } 3780 } 3781 } else if (VDBG) { 3782 log("buildWaitingApns: couldn't handle requested ApnType=" 3783 + requestedApnType); 3784 } 3785 } 3786 3787 if (DBG) log("buildWaitingApns: " + apnList.size() + " APNs in the list: " + apnList); 3788 return apnList; 3789 } 3790 apnListToString(ArrayList<ApnSetting> apns)3791 private String apnListToString (ArrayList<ApnSetting> apns) { 3792 StringBuilder result = new StringBuilder(); 3793 for (int i = 0, size = apns.size(); i < size; i++) { 3794 result.append('[') 3795 .append(apns.get(i).toString()) 3796 .append(']'); 3797 } 3798 return result.toString(); 3799 } 3800 setPreferredApn(int pos)3801 private void setPreferredApn(int pos) { 3802 setPreferredApn(pos, false); 3803 } 3804 setPreferredApn(int pos, boolean force)3805 private void setPreferredApn(int pos, boolean force) { 3806 if (!force && !mCanSetPreferApn) { 3807 log("setPreferredApn: X !canSEtPreferApn"); 3808 return; 3809 } 3810 3811 String subId = Long.toString(mPhone.getSubId()); 3812 Uri uri = Uri.withAppendedPath(PREFERAPN_NO_UPDATE_URI_USING_SUBID, subId); 3813 log("setPreferredApn: delete"); 3814 ContentResolver resolver = mPhone.getContext().getContentResolver(); 3815 resolver.delete(uri, null, null); 3816 3817 if (pos >= 0) { 3818 log("setPreferredApn: insert"); 3819 ContentValues values = new ContentValues(); 3820 values.put(APN_ID, pos); 3821 resolver.insert(uri, values); 3822 } 3823 } 3824 3825 @Nullable getPreferredApn()3826 ApnSetting getPreferredApn() { 3827 //Only call this method from main thread 3828 if (mAllApnSettings == null || mAllApnSettings.isEmpty()) { 3829 log("getPreferredApn: mAllApnSettings is empty"); 3830 return null; 3831 } 3832 3833 String subId = Long.toString(mPhone.getSubId()); 3834 Uri uri = Uri.withAppendedPath(PREFERAPN_NO_UPDATE_URI_USING_SUBID, subId); 3835 Cursor cursor = mPhone.getContext().getContentResolver().query( 3836 uri, new String[] { "_id", "name", "apn" }, 3837 null, null, Telephony.Carriers.DEFAULT_SORT_ORDER); 3838 3839 if (cursor != null) { 3840 mCanSetPreferApn = true; 3841 } else { 3842 mCanSetPreferApn = false; 3843 } 3844 3845 if (VDBG) { 3846 log("getPreferredApn: mRequestedApnType=" + mRequestedApnType + " cursor=" + cursor 3847 + " cursor.count=" + ((cursor != null) ? cursor.getCount() : 0)); 3848 } 3849 3850 if (mCanSetPreferApn && cursor.getCount() > 0) { 3851 int pos; 3852 cursor.moveToFirst(); 3853 pos = cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers._ID)); 3854 for(ApnSetting p : mAllApnSettings) { 3855 if (p.getId() == pos && p.canHandleType(mRequestedApnType)) { 3856 log("getPreferredApn: For APN type " 3857 + ApnSetting.getApnTypeString(mRequestedApnType) 3858 + " found apnSetting " + p); 3859 cursor.close(); 3860 return p; 3861 } 3862 } 3863 } 3864 3865 if (cursor != null) { 3866 cursor.close(); 3867 } 3868 3869 log("getPreferredApn: X not found"); 3870 return null; 3871 } 3872 3873 @Override handleMessage(Message msg)3874 public void handleMessage (Message msg) { 3875 if (VDBG) log("handleMessage msg=" + msg); 3876 3877 AsyncResult ar; 3878 Pair<ApnContext, Integer> pair; 3879 ApnContext apnContext; 3880 int generation; 3881 int requestType; 3882 int handoverFailureMode; 3883 switch (msg.what) { 3884 case DctConstants.EVENT_DATA_CONNECTION_DETACHED: 3885 onDataConnectionDetached(); 3886 break; 3887 3888 case DctConstants.EVENT_DATA_CONNECTION_ATTACHED: 3889 onDataConnectionAttached(); 3890 break; 3891 3892 case DctConstants.EVENT_DO_RECOVERY: 3893 mDsRecoveryHandler.doRecovery(); 3894 break; 3895 3896 case DctConstants.EVENT_APN_CHANGED: 3897 onApnChanged(); 3898 break; 3899 3900 case DctConstants.EVENT_PS_RESTRICT_ENABLED: 3901 /** 3902 * We don't need to explicitly to tear down the PDP context 3903 * when PS restricted is enabled. The base band will deactive 3904 * PDP context and notify us with PDP_CONTEXT_CHANGED. 3905 * But we should stop the network polling and prevent reset PDP. 3906 */ 3907 if (DBG) log("EVENT_PS_RESTRICT_ENABLED " + mIsPsRestricted); 3908 stopNetStatPoll(); 3909 stopDataStallAlarm(); 3910 mIsPsRestricted = true; 3911 break; 3912 3913 case DctConstants.EVENT_PS_RESTRICT_DISABLED: 3914 /** 3915 * When PS restrict is removed, we need setup PDP connection if 3916 * PDP connection is down. 3917 */ 3918 if (DBG) log("EVENT_PS_RESTRICT_DISABLED " + mIsPsRestricted); 3919 mIsPsRestricted = false; 3920 if (isAnyDataConnected()) { 3921 startNetStatPoll(); 3922 startDataStallAlarm(DATA_STALL_NOT_SUSPECTED); 3923 } else { 3924 // TODO: Should all PDN states be checked to fail? 3925 if (mState == DctConstants.State.FAILED) { 3926 cleanUpAllConnectionsInternal(false, Phone.REASON_PS_RESTRICT_ENABLED); 3927 mReregisterOnReconnectFailure = false; 3928 } 3929 apnContext = mApnContextsByType.get(ApnSetting.TYPE_DEFAULT); 3930 if (apnContext != null) { 3931 apnContext.setReason(Phone.REASON_PS_RESTRICT_ENABLED); 3932 trySetupData(apnContext, REQUEST_TYPE_NORMAL, null); 3933 } else { 3934 loge("**** Default ApnContext not found ****"); 3935 if (TelephonyUtils.IS_DEBUGGABLE) { 3936 throw new RuntimeException("Default ApnContext not found"); 3937 } 3938 } 3939 } 3940 break; 3941 3942 case DctConstants.EVENT_TRY_SETUP_DATA: 3943 apnContext = (ApnContext) msg.obj; 3944 requestType = msg.arg1; 3945 trySetupData(apnContext, requestType, null); 3946 break; 3947 case DctConstants.EVENT_CLEAN_UP_CONNECTION: 3948 if (DBG) log("EVENT_CLEAN_UP_CONNECTION"); 3949 cleanUpConnectionInternal(true, RELEASE_TYPE_DETACH, (ApnContext) msg.obj); 3950 break; 3951 case DctConstants.EVENT_CLEAN_UP_ALL_CONNECTIONS: 3952 if ((msg.obj != null) && (msg.obj instanceof String == false)) { 3953 msg.obj = null; 3954 } 3955 cleanUpAllConnectionsInternal(true, (String) msg.obj); 3956 break; 3957 3958 case DctConstants.EVENT_DATA_RAT_CHANGED: 3959 if (getDataRat() == ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN) { 3960 // unknown rat is an exception for data rat change. It's only received when out 3961 // of service and is not applicable for apn bearer bitmask. We should bypass the 3962 // check of waiting apn list and keep the data connection on, and no need to 3963 // setup a new one. 3964 break; 3965 } 3966 cleanUpConnectionsOnUpdatedApns(false, Phone.REASON_NW_TYPE_CHANGED); 3967 //May new Network allow setupData, so try it here 3968 setupDataOnAllConnectableApns(Phone.REASON_NW_TYPE_CHANGED, 3969 RetryFailures.ONLY_ON_CHANGE); 3970 break; 3971 3972 case DctConstants.CMD_CLEAR_PROVISIONING_SPINNER: 3973 // Check message sender intended to clear the current spinner. 3974 if (mProvisioningSpinner == msg.obj) { 3975 mProvisioningSpinner.dismiss(); 3976 mProvisioningSpinner = null; 3977 } 3978 break; 3979 3980 case DctConstants.EVENT_ENABLE_APN: 3981 onEnableApn(msg.arg1, msg.arg2, (Message) msg.obj); 3982 break; 3983 3984 case DctConstants.EVENT_DISABLE_APN: 3985 onDisableApn(msg.arg1, msg.arg2); 3986 break; 3987 3988 case DctConstants.EVENT_DATA_STALL_ALARM: 3989 onDataStallAlarm(msg.arg1); 3990 break; 3991 3992 case DctConstants.EVENT_ROAMING_OFF: 3993 onDataRoamingOff(); 3994 break; 3995 3996 case DctConstants.EVENT_ROAMING_ON: 3997 case DctConstants.EVENT_ROAMING_SETTING_CHANGE: 3998 onDataRoamingOnOrSettingsChanged(msg.what); 3999 break; 4000 4001 case DctConstants.EVENT_DEVICE_PROVISIONED_CHANGE: 4002 // Update sharedPreference to false when exits new device provisioning, indicating 4003 // no users modifications on the settings for new devices. Thus carrier specific 4004 // default roaming settings can be applied for new devices till user modification. 4005 final SharedPreferences sp = PreferenceManager 4006 .getDefaultSharedPreferences(mPhone.getContext()); 4007 if (!sp.contains(Phone.DATA_ROAMING_IS_USER_SETTING_KEY)) { 4008 sp.edit().putBoolean(Phone.DATA_ROAMING_IS_USER_SETTING_KEY, false).commit(); 4009 } 4010 break; 4011 4012 case DctConstants.EVENT_NETWORK_STATUS_CHANGED: 4013 int status = msg.arg1; 4014 int cid = msg.arg2; 4015 String url = (String) msg.obj; 4016 onNetworkStatusChanged(status, cid, url); 4017 break; 4018 4019 case DctConstants.EVENT_RADIO_AVAILABLE: 4020 onRadioAvailable(); 4021 break; 4022 4023 case DctConstants.EVENT_RADIO_OFF_OR_NOT_AVAILABLE: 4024 onRadioOffOrNotAvailable(); 4025 break; 4026 4027 case DctConstants.EVENT_DATA_SETUP_COMPLETE: 4028 ar = (AsyncResult) msg.obj; 4029 pair = (Pair<ApnContext, Integer>) ar.userObj; 4030 apnContext = pair.first; 4031 generation = pair.second; 4032 requestType = msg.arg1; 4033 handoverFailureMode = msg.arg2; 4034 if (apnContext.getConnectionGeneration() == generation) { 4035 boolean success = true; 4036 int cause = DataFailCause.UNKNOWN; 4037 if (ar.exception != null) { 4038 success = false; 4039 cause = (int) ar.result; 4040 } 4041 onDataSetupComplete(apnContext, success, cause, requestType, 4042 handoverFailureMode); 4043 } else { 4044 loge("EVENT_DATA_SETUP_COMPLETE: Dropped the event because generation " 4045 + "did not match."); 4046 } 4047 break; 4048 4049 case DctConstants.EVENT_DATA_SETUP_COMPLETE_ERROR: 4050 ar = (AsyncResult) msg.obj; 4051 pair = (Pair<ApnContext, Integer>) ar.userObj; 4052 apnContext = pair.first; 4053 generation = pair.second; 4054 handoverFailureMode = msg.arg2; 4055 if (apnContext.getConnectionGeneration() == generation) { 4056 onDataSetupCompleteError(apnContext, handoverFailureMode, false); 4057 } else { 4058 loge("EVENT_DATA_SETUP_COMPLETE_ERROR: Dropped the event because generation " 4059 + "did not match."); 4060 } 4061 break; 4062 4063 case DctConstants.EVENT_DISCONNECT_DONE: 4064 log("EVENT_DISCONNECT_DONE msg=" + msg); 4065 ar = (AsyncResult) msg.obj; 4066 pair = (Pair<ApnContext, Integer>) ar.userObj; 4067 apnContext = pair.first; 4068 generation = pair.second; 4069 if (apnContext.getConnectionGeneration() == generation) { 4070 onDisconnectDone(apnContext); 4071 } else { 4072 loge("EVENT_DISCONNECT_DONE: Dropped the event because generation " 4073 + "did not match."); 4074 } 4075 break; 4076 4077 case DctConstants.EVENT_VOICE_CALL_STARTED: 4078 onVoiceCallStarted(); 4079 break; 4080 4081 case DctConstants.EVENT_VOICE_CALL_ENDED: 4082 onVoiceCallEnded(); 4083 break; 4084 case DctConstants.CMD_SET_ENABLE_FAIL_FAST_MOBILE_DATA: { 4085 sEnableFailFastRefCounter += (msg.arg1 == DctConstants.ENABLED) ? 1 : -1; 4086 if (DBG) { 4087 log("CMD_SET_ENABLE_FAIL_FAST_MOBILE_DATA: " 4088 + " sEnableFailFastRefCounter=" + sEnableFailFastRefCounter); 4089 } 4090 if (sEnableFailFastRefCounter < 0) { 4091 final String s = "CMD_SET_ENABLE_FAIL_FAST_MOBILE_DATA: " 4092 + "sEnableFailFastRefCounter:" + sEnableFailFastRefCounter + " < 0"; 4093 loge(s); 4094 sEnableFailFastRefCounter = 0; 4095 } 4096 final boolean enabled = sEnableFailFastRefCounter > 0; 4097 if (DBG) { 4098 log("CMD_SET_ENABLE_FAIL_FAST_MOBILE_DATA: enabled=" + enabled 4099 + " sEnableFailFastRefCounter=" + sEnableFailFastRefCounter); 4100 } 4101 if (mFailFast != enabled) { 4102 mFailFast = enabled; 4103 4104 mDataStallNoRxEnabled = !enabled; 4105 if (mDsRecoveryHandler.isNoRxDataStallDetectionEnabled() 4106 && isAnyDataConnected() 4107 && (!mInVoiceCall || 4108 mPhone.getServiceStateTracker() 4109 .isConcurrentVoiceAndDataAllowed())) { 4110 if (DBG) log("CMD_SET_ENABLE_FAIL_FAST_MOBILE_DATA: start data stall"); 4111 stopDataStallAlarm(); 4112 startDataStallAlarm(DATA_STALL_NOT_SUSPECTED); 4113 } else { 4114 if (DBG) log("CMD_SET_ENABLE_FAIL_FAST_MOBILE_DATA: stop data stall"); 4115 stopDataStallAlarm(); 4116 } 4117 } 4118 4119 break; 4120 } 4121 case DctConstants.CMD_ENABLE_MOBILE_PROVISIONING: { 4122 Bundle bundle = msg.getData(); 4123 if (bundle != null) { 4124 try { 4125 mProvisioningUrl = (String)bundle.get(DctConstants.PROVISIONING_URL_KEY); 4126 } catch(ClassCastException e) { 4127 loge("CMD_ENABLE_MOBILE_PROVISIONING: provisioning url not a string" + e); 4128 mProvisioningUrl = null; 4129 } 4130 } 4131 if (TextUtils.isEmpty(mProvisioningUrl)) { 4132 loge("CMD_ENABLE_MOBILE_PROVISIONING: provisioning url is empty, ignoring"); 4133 mIsProvisioning = false; 4134 mProvisioningUrl = null; 4135 } else { 4136 loge("CMD_ENABLE_MOBILE_PROVISIONING: provisioningUrl=" + mProvisioningUrl); 4137 mIsProvisioning = true; 4138 startProvisioningApnAlarm(); 4139 } 4140 break; 4141 } 4142 case DctConstants.EVENT_PROVISIONING_APN_ALARM: { 4143 if (DBG) log("EVENT_PROVISIONING_APN_ALARM"); 4144 ApnContext apnCtx = mApnContextsByType.get(ApnSetting.TYPE_DEFAULT); 4145 if (apnCtx.isProvisioningApn() && apnCtx.isConnectedOrConnecting()) { 4146 if (mProvisioningApnAlarmTag == msg.arg1) { 4147 if (DBG) log("EVENT_PROVISIONING_APN_ALARM: Disconnecting"); 4148 mIsProvisioning = false; 4149 mProvisioningUrl = null; 4150 stopProvisioningApnAlarm(); 4151 cleanUpConnectionInternal(true, RELEASE_TYPE_DETACH, apnCtx); 4152 } else { 4153 if (DBG) { 4154 log("EVENT_PROVISIONING_APN_ALARM: ignore stale tag," 4155 + " mProvisioningApnAlarmTag:" + mProvisioningApnAlarmTag 4156 + " != arg1:" + msg.arg1); 4157 } 4158 } 4159 } else { 4160 if (DBG) log("EVENT_PROVISIONING_APN_ALARM: Not connected ignore"); 4161 } 4162 break; 4163 } 4164 case DctConstants.CMD_IS_PROVISIONING_APN: { 4165 if (DBG) log("CMD_IS_PROVISIONING_APN"); 4166 boolean isProvApn; 4167 try { 4168 String apnType = null; 4169 Bundle bundle = msg.getData(); 4170 if (bundle != null) { 4171 apnType = (String)bundle.get(DctConstants.APN_TYPE_KEY); 4172 } 4173 if (TextUtils.isEmpty(apnType)) { 4174 loge("CMD_IS_PROVISIONING_APN: apnType is empty"); 4175 isProvApn = false; 4176 } else { 4177 isProvApn = isProvisioningApn(apnType); 4178 } 4179 } catch (ClassCastException e) { 4180 loge("CMD_IS_PROVISIONING_APN: NO provisioning url ignoring"); 4181 isProvApn = false; 4182 } 4183 if (DBG) log("CMD_IS_PROVISIONING_APN: ret=" + isProvApn); 4184 mReplyAc.replyToMessage(msg, DctConstants.CMD_IS_PROVISIONING_APN, 4185 isProvApn ? DctConstants.ENABLED : DctConstants.DISABLED); 4186 break; 4187 } 4188 case DctConstants.EVENT_RESTART_RADIO: { 4189 restartRadio(); 4190 break; 4191 } 4192 case DctConstants.CMD_NET_STAT_POLL: { 4193 if (msg.arg1 == DctConstants.ENABLED) { 4194 handleStartNetStatPoll((DctConstants.Activity)msg.obj); 4195 } else if (msg.arg1 == DctConstants.DISABLED) { 4196 handleStopNetStatPoll((DctConstants.Activity)msg.obj); 4197 } 4198 break; 4199 } 4200 case DctConstants.EVENT_PCO_DATA_RECEIVED: { 4201 handlePcoData((AsyncResult)msg.obj); 4202 break; 4203 } 4204 case DctConstants.EVENT_DATA_RECONNECT: 4205 if (DBG) { 4206 log("EVENT_DATA_RECONNECT: subId=" + msg.arg1 + ", type=" 4207 + requestTypeToString(msg.arg2)); 4208 } 4209 onDataReconnect((ApnContext) msg.obj, msg.arg1, msg.arg2); 4210 break; 4211 case DctConstants.EVENT_DATA_SERVICE_BINDING_CHANGED: 4212 onDataServiceBindingChanged((Boolean) ((AsyncResult) msg.obj).result); 4213 break; 4214 case DctConstants.EVENT_DATA_ENABLED_CHANGED: 4215 ar = (AsyncResult) msg.obj; 4216 if (ar.result instanceof Pair) { 4217 Pair<Boolean, Integer> p = (Pair<Boolean, Integer>) ar.result; 4218 boolean enabled = p.first; 4219 int reason = p.second; 4220 onDataEnabledChanged(enabled, reason); 4221 } 4222 break; 4223 case DctConstants.EVENT_DATA_ENABLED_OVERRIDE_RULES_CHANGED: 4224 onDataEnabledOverrideRulesChanged(); 4225 break; 4226 case DctConstants.EVENT_NR_TIMER_WATCHDOG: 4227 mWatchdog = false; 4228 reevaluateUnmeteredConnections(); 4229 break; 4230 case DctConstants.EVENT_TELEPHONY_DISPLAY_INFO_CHANGED: 4231 reevaluateCongestedConnections(); 4232 reevaluateUnmeteredConnections(); 4233 break; 4234 case DctConstants.EVENT_CARRIER_CONFIG_CHANGED: 4235 onCarrierConfigChanged(); 4236 break; 4237 case DctConstants.EVENT_SIM_STATE_UPDATED: 4238 int simState = msg.arg1; 4239 onSimStateUpdated(simState); 4240 break; 4241 case DctConstants.EVENT_APN_UNTHROTTLED: 4242 ar = (AsyncResult) msg.obj; 4243 String apn = (String) ar.result; 4244 onApnUnthrottled(apn); 4245 break; 4246 case DctConstants.EVENT_TRAFFIC_DESCRIPTORS_UPDATED: 4247 onTrafficDescriptorsUpdated(); 4248 break; 4249 default: 4250 Rlog.e("DcTracker", "Unhandled event=" + msg); 4251 break; 4252 4253 } 4254 } 4255 getApnProfileID(String apnType)4256 private int getApnProfileID(String apnType) { 4257 if (TextUtils.equals(apnType, ApnSetting.TYPE_IMS_STRING)) { 4258 return RILConstants.DATA_PROFILE_IMS; 4259 } else if (TextUtils.equals(apnType, ApnSetting.TYPE_FOTA_STRING)) { 4260 return RILConstants.DATA_PROFILE_FOTA; 4261 } else if (TextUtils.equals(apnType, ApnSetting.TYPE_CBS_STRING)) { 4262 return RILConstants.DATA_PROFILE_CBS; 4263 } else if (TextUtils.equals(apnType, ApnSetting.TYPE_IA_STRING)) { 4264 return RILConstants.DATA_PROFILE_DEFAULT; // DEFAULT for now 4265 } else if (TextUtils.equals(apnType, ApnSetting.TYPE_DUN_STRING)) { 4266 return RILConstants.DATA_PROFILE_TETHERED; 4267 } else { 4268 return RILConstants.DATA_PROFILE_DEFAULT; 4269 } 4270 } 4271 getCellLocationId()4272 private int getCellLocationId() { 4273 int cid = -1; 4274 CellLocation loc = mPhone.getCurrentCellIdentity().asCellLocation(); 4275 4276 if (loc != null) { 4277 if (loc instanceof GsmCellLocation) { 4278 cid = ((GsmCellLocation)loc).getCid(); 4279 } else if (loc instanceof CdmaCellLocation) { 4280 cid = ((CdmaCellLocation)loc).getBaseStationId(); 4281 } 4282 } 4283 return cid; 4284 } 4285 4286 /** 4287 * Update link bandwidth estimate default values from carrier config. 4288 * @param bandwidths String array of "RAT:upstream,downstream" for each RAT 4289 * @param useLte For NR NSA, whether to use LTE value for upstream or not 4290 */ updateLinkBandwidths(String[] bandwidths, boolean useLte)4291 private void updateLinkBandwidths(String[] bandwidths, boolean useLte) { 4292 ConcurrentHashMap<String, Pair<Integer, Integer>> temp = new ConcurrentHashMap<>(); 4293 for (String config : bandwidths) { 4294 int downstream = 14; 4295 int upstream = 14; 4296 String[] kv = config.split(":"); 4297 if (kv.length == 2) { 4298 String[] split = kv[1].split(","); 4299 if (split.length == 2) { 4300 try { 4301 downstream = Integer.parseInt(split[0]); 4302 upstream = Integer.parseInt(split[1]); 4303 } catch (NumberFormatException ignored) { 4304 } 4305 } 4306 temp.put(kv[0], new Pair<>(downstream, upstream)); 4307 } 4308 } 4309 if (useLte) { 4310 Pair<Integer, Integer> ltePair = 4311 temp.get(DataConfigManager.DATA_CONFIG_NETWORK_TYPE_LTE); 4312 if (ltePair != null) { 4313 if (temp.containsKey(DataConfigManager.DATA_CONFIG_NETWORK_TYPE_NR_NSA)) { 4314 temp.put(DataConfigManager.DATA_CONFIG_NETWORK_TYPE_NR_NSA, new Pair<>( 4315 temp.get(DataConfigManager.DATA_CONFIG_NETWORK_TYPE_NR_NSA).first, 4316 ltePair.second)); 4317 } 4318 if (temp.containsKey(DataConfigManager.DATA_CONFIG_NETWORK_TYPE_NR_NSA_MMWAVE)) { 4319 temp.put(DataConfigManager.DATA_CONFIG_NETWORK_TYPE_NR_NSA_MMWAVE, new Pair<>( 4320 temp.get(DataConfigManager.DATA_CONFIG_NETWORK_TYPE_NR_NSA_MMWAVE) 4321 .first, ltePair.second)); 4322 } 4323 } 4324 } 4325 mBandwidths = temp; 4326 for (DataConnection dc : mDataConnections.values()) { 4327 dc.sendMessage(DataConnection.EVENT_CARRIER_CONFIG_LINK_BANDWIDTHS_CHANGED); 4328 } 4329 } 4330 4331 /** 4332 * Return the link upstream/downstream values from CarrierConfig for the given RAT name. 4333 * @param ratName RAT name from ServiceState#rilRadioTechnologyToString. 4334 * @return pair of downstream/upstream values (kbps), or null if the config is not defined. 4335 */ getLinkBandwidthsFromCarrierConfig(String ratName)4336 public Pair<Integer, Integer> getLinkBandwidthsFromCarrierConfig(String ratName) { 4337 return mBandwidths.get(ratName); 4338 } 4339 4340 @VisibleForTesting shouldAutoAttach()4341 public boolean shouldAutoAttach() { 4342 if (mAutoAttachEnabled.get()) return true; 4343 4344 PhoneSwitcher phoneSwitcher = PhoneSwitcher.getInstance(); 4345 ServiceState serviceState = mPhone.getServiceState(); 4346 4347 if (phoneSwitcher == null || serviceState == null) return false; 4348 4349 // If voice is also not in service, don't auto attach. 4350 if (serviceState.getState() != ServiceState.STATE_IN_SERVICE) return false; 4351 4352 // If voice is on LTE or NR, don't auto attach as for LTE / NR data would be attached. 4353 if (serviceState.getVoiceNetworkType() == NETWORK_TYPE_LTE 4354 || serviceState.getVoiceNetworkType() == NETWORK_TYPE_NR) return false; 4355 4356 // If phone is non default phone, modem may have detached from data for optimization. 4357 // If phone is in voice call, for DSDS case DDS switch may be limited so we do try our 4358 // best to setup data connection and allow auto-attach. 4359 return (mPhone.getPhoneId() != phoneSwitcher.getPreferredDataPhoneId() 4360 || mPhone.getState() != PhoneConstants.State.IDLE); 4361 } 4362 notifyAllDataDisconnected()4363 private void notifyAllDataDisconnected() { 4364 sEnableFailFastRefCounter = 0; 4365 mFailFast = false; 4366 log("notify all data disconnected"); 4367 mAllDataDisconnectedRegistrants.notifyRegistrants(); 4368 } 4369 registerForAllDataDisconnected(Handler h, int what)4370 public void registerForAllDataDisconnected(Handler h, int what) { 4371 mAllDataDisconnectedRegistrants.addUnique(h, what, null); 4372 4373 if (areAllDataDisconnected()) { 4374 notifyAllDataDisconnected(); 4375 } 4376 } 4377 unregisterForAllDataDisconnected(Handler h)4378 public void unregisterForAllDataDisconnected(Handler h) { 4379 mAllDataDisconnectedRegistrants.remove(h); 4380 } 4381 onDataEnabledChanged(boolean enable, @DataEnabledChangedReason int enabledChangedReason)4382 private void onDataEnabledChanged(boolean enable, 4383 @DataEnabledChangedReason int enabledChangedReason) { 4384 if (DBG) { 4385 log("onDataEnabledChanged: enable=" + enable + ", enabledChangedReason=" 4386 + enabledChangedReason); 4387 } 4388 4389 if (enable) { 4390 reevaluateDataConnections(); 4391 setupDataOnAllConnectableApns(Phone.REASON_DATA_ENABLED, RetryFailures.ALWAYS); 4392 } else { 4393 String cleanupReason; 4394 switch (enabledChangedReason) { 4395 case DataEnabledSettings.REASON_INTERNAL_DATA_ENABLED: 4396 cleanupReason = Phone.REASON_DATA_DISABLED_INTERNAL; 4397 break; 4398 case DataEnabledSettings.REASON_DATA_ENABLED_BY_CARRIER: 4399 cleanupReason = Phone.REASON_CARRIER_ACTION_DISABLE_METERED_APN; 4400 break; 4401 case DataEnabledSettings.REASON_USER_DATA_ENABLED: 4402 case DataEnabledSettings.REASON_POLICY_DATA_ENABLED: 4403 case DataEnabledSettings.REASON_PROVISIONED_CHANGED: 4404 case DataEnabledSettings.REASON_PROVISIONING_DATA_ENABLED_CHANGED: 4405 default: 4406 cleanupReason = Phone.REASON_DATA_SPECIFIC_DISABLED; 4407 break; 4408 4409 } 4410 cleanUpAllConnectionsInternal(true, cleanupReason); 4411 } 4412 } 4413 reevaluateCongestedConnections()4414 private void reevaluateCongestedConnections() { 4415 log("reevaluateCongestedConnections"); 4416 int rat = mPhone.getDisplayInfoController().getTelephonyDisplayInfo().getNetworkType(); 4417 // congested override and either network is specified or unknown and all networks specified 4418 boolean isCongested = mCongestedOverride && (mCongestedNetworkTypes.contains(rat) 4419 || mCongestedNetworkTypes.containsAll(Arrays.stream( 4420 TelephonyManager.getAllNetworkTypes()).boxed().collect(Collectors.toSet()))); 4421 for (DataConnection dataConnection : mDataConnections.values()) { 4422 dataConnection.onCongestednessChanged(isCongested); 4423 } 4424 } 4425 reevaluateUnmeteredConnections()4426 private void reevaluateUnmeteredConnections() { 4427 log("reevaluateUnmeteredConnections"); 4428 int rat = mPhone.getDisplayInfoController().getTelephonyDisplayInfo().getNetworkType(); 4429 if (isNrUnmetered() && (!mPhone.getServiceState().getRoaming() || mNrNsaRoamingUnmetered)) { 4430 setDataConnectionUnmetered(true); 4431 if (!mWatchdog) { 4432 startWatchdogAlarm(); 4433 } 4434 } else { 4435 stopWatchdogAlarm(); 4436 setDataConnectionUnmetered(isNetworkTypeUnmetered(rat)); 4437 } 4438 } 4439 setDataConnectionUnmetered(boolean isUnmetered)4440 private void setDataConnectionUnmetered(boolean isUnmetered) { 4441 if (!isUnmetered || isTempNotMeteredSupportedByCarrier()) { 4442 for (DataConnection dataConnection : mDataConnections.values()) { 4443 dataConnection.onMeterednessChanged(isUnmetered); 4444 } 4445 } 4446 } 4447 isNetworkTypeUnmetered(@etworkType int networkType)4448 private boolean isNetworkTypeUnmetered(@NetworkType int networkType) { 4449 boolean isUnmetered; 4450 if (mUnmeteredNetworkTypes == null || !mUnmeteredOverride) { 4451 // check SubscriptionPlans if override is not defined 4452 isUnmetered = isNetworkTypeUnmeteredViaSubscriptionPlan(networkType); 4453 log("isNetworkTypeUnmeteredViaSubscriptionPlan: networkType=" + networkType 4454 + ", isUnmetered=" + isUnmetered); 4455 return isUnmetered; 4456 } 4457 // unmetered override and either network is specified or unknown and all networks specified 4458 isUnmetered = mUnmeteredNetworkTypes.contains(networkType) 4459 || mUnmeteredNetworkTypes.containsAll(Arrays.stream( 4460 TelephonyManager.getAllNetworkTypes()).boxed().collect(Collectors.toSet())); 4461 if (DBG) { 4462 log("isNetworkTypeUnmetered: networkType=" + networkType 4463 + ", isUnmetered=" + isUnmetered); 4464 } 4465 return isUnmetered; 4466 } 4467 isNetworkTypeUnmeteredViaSubscriptionPlan(@etworkType int networkType)4468 private boolean isNetworkTypeUnmeteredViaSubscriptionPlan(@NetworkType int networkType) { 4469 if (mSubscriptionPlans.isEmpty()) { 4470 // safe return false if unable to get subscription plans or plans don't exist 4471 return false; 4472 } 4473 4474 boolean isGeneralUnmetered = true; 4475 Set<Integer> allNetworkTypes = Arrays.stream(TelephonyManager.getAllNetworkTypes()) 4476 .boxed().collect(Collectors.toSet()); 4477 for (SubscriptionPlan plan : mSubscriptionPlans) { 4478 // check plan is general (applies to all network types) or specific 4479 if (Arrays.stream(plan.getNetworkTypes()).boxed().collect(Collectors.toSet()) 4480 .containsAll(allNetworkTypes)) { 4481 if (!isPlanUnmetered(plan)) { 4482 // metered takes precedence over unmetered for safety 4483 isGeneralUnmetered = false; 4484 } 4485 } else { 4486 // check plan applies to given network type 4487 if (networkType != TelephonyManager.NETWORK_TYPE_UNKNOWN) { 4488 for (int planNetworkType : plan.getNetworkTypes()) { 4489 if (planNetworkType == networkType) { 4490 return isPlanUnmetered(plan); 4491 } 4492 } 4493 } 4494 } 4495 } 4496 return isGeneralUnmetered; 4497 } 4498 isPlanUnmetered(SubscriptionPlan plan)4499 private boolean isPlanUnmetered(SubscriptionPlan plan) { 4500 return plan.getDataLimitBytes() == SubscriptionPlan.BYTES_UNLIMITED; 4501 } 4502 isNrUnmetered()4503 private boolean isNrUnmetered() { 4504 int rat = mPhone.getDisplayInfoController().getTelephonyDisplayInfo().getNetworkType(); 4505 int override = mPhone.getDisplayInfoController().getTelephonyDisplayInfo() 4506 .getOverrideNetworkType(); 4507 4508 if (isNetworkTypeUnmetered(NETWORK_TYPE_NR)) { 4509 if (mNrNsaMmwaveUnmetered) { 4510 if (override == TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED) { 4511 if (DBG) log("NR unmetered for mmwave only"); 4512 return true; 4513 } 4514 return false; 4515 } else if (mNrNsaSub6Unmetered) { 4516 if (override == TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA) { 4517 if (DBG) log("NR unmetered for sub6 only"); 4518 return true; 4519 } 4520 return false; 4521 } 4522 if (override == TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED 4523 || override == TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA 4524 || rat == NETWORK_TYPE_NR) { 4525 if (DBG) log("NR unmetered for all frequencies"); 4526 return true; 4527 } 4528 return false; 4529 } 4530 4531 if (mNrNsaAllUnmetered) { 4532 if (mNrNsaMmwaveUnmetered) { 4533 if (override == TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED) { 4534 if (DBG) log("NR NSA unmetered for mmwave only via carrier configs"); 4535 return true; 4536 } 4537 return false; 4538 } else if (mNrNsaSub6Unmetered) { 4539 if (override == TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA) { 4540 if (DBG) log("NR NSA unmetered for sub6 only via carrier configs"); 4541 return true; 4542 } 4543 return false; 4544 } 4545 if (override == TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED 4546 || override == TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA) { 4547 if (DBG) log("NR NSA unmetered for all frequencies via carrier configs"); 4548 return true; 4549 } 4550 return false; 4551 } 4552 4553 if (mNrSaAllUnmetered) { 4554 // TODO: add logic for mNrSaMmwaveUnmetered and mNrSaSub6Unmetered once it's defined 4555 // in TelephonyDisplayInfo 4556 if (rat == NETWORK_TYPE_NR) { 4557 if (DBG) log("NR SA unmetered for all frequencies via carrier configs"); 4558 return true; 4559 } 4560 return false; 4561 } 4562 4563 return false; 4564 } 4565 isTempNotMeteredSupportedByCarrier()4566 private boolean isTempNotMeteredSupportedByCarrier() { 4567 CarrierConfigManager configManager = 4568 mPhone.getContext().getSystemService(CarrierConfigManager.class); 4569 if (configManager != null) { 4570 PersistableBundle bundle = configManager.getConfigForSubId(mPhone.getSubId()); 4571 if (bundle != null) { 4572 return bundle.getBoolean( 4573 CarrierConfigManager.KEY_NETWORK_TEMP_NOT_METERED_SUPPORTED_BOOL); 4574 } 4575 } 4576 4577 return false; 4578 } 4579 log(String s)4580 protected void log(String s) { 4581 Rlog.d(mLogTag, s); 4582 } 4583 loge(String s)4584 private void loge(String s) { 4585 Rlog.e(mLogTag, s); 4586 } 4587 logSortedApnContexts()4588 private void logSortedApnContexts() { 4589 if (VDBG) { 4590 log("initApnContexts: X mApnContexts=" + mApnContexts); 4591 4592 StringBuilder sb = new StringBuilder(); 4593 sb.append("sorted apncontexts -> ["); 4594 for (ApnContext apnContext : mPrioritySortedApnContexts) { 4595 sb.append(apnContext); 4596 sb.append(", "); 4597 4598 log("sorted list"); 4599 } 4600 sb.append("]"); 4601 log(sb.toString()); 4602 } 4603 } 4604 dump(FileDescriptor fd, PrintWriter pw, String[] args)4605 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 4606 pw.println("DcTracker:"); 4607 pw.println(" RADIO_TESTS=" + RADIO_TESTS); 4608 pw.println(" mDataEnabledSettings=" + mDataEnabledSettings); 4609 pw.println(" isDataAllowed=" + isDataAllowed(null)); 4610 pw.flush(); 4611 pw.println(" mRequestedApnType=" + mRequestedApnType); 4612 pw.println(" mPhone=" + mPhone.getPhoneName()); 4613 pw.println(" mConfigReady=" + mConfigReady); 4614 pw.println(" mSimState=" + SubscriptionInfoUpdater.simStateString(mSimState)); 4615 pw.println(" mActivity=" + mActivity); 4616 pw.println(" mState=" + mState); 4617 pw.println(" mTxPkts=" + mTxPkts); 4618 pw.println(" mRxPkts=" + mRxPkts); 4619 pw.println(" mNetStatPollPeriod=" + mNetStatPollPeriod); 4620 pw.println(" mNetStatPollEnabled=" + mNetStatPollEnabled); 4621 pw.println(" mDataStallTxRxSum=" + mDataStallTxRxSum); 4622 pw.println(" mDataStallAlarmTag=" + mDataStallAlarmTag); 4623 pw.println(" mDataStallNoRxEnabled=" + mDataStallNoRxEnabled); 4624 pw.println(" mEmergencyApn=" + mEmergencyApn); 4625 pw.println(" mSentSinceLastRecv=" + mSentSinceLastRecv); 4626 pw.println(" mNoRecvPollCount=" + mNoRecvPollCount); 4627 pw.println(" mResolver=" + mResolver); 4628 pw.println(" mReconnectIntent=" + mReconnectIntent); 4629 pw.println(" mAutoAttachEnabled=" + mAutoAttachEnabled.get()); 4630 pw.println(" mIsScreenOn=" + mIsScreenOn); 4631 pw.println(" mUniqueIdGenerator=" + mUniqueIdGenerator); 4632 pw.println(" mDataServiceBound=" + mDataServiceBound); 4633 pw.println(" mDataRoamingLeakageLog= "); 4634 mDataRoamingLeakageLog.dump(fd, pw, args); 4635 pw.println(" mApnSettingsInitializationLog= "); 4636 mApnSettingsInitializationLog.dump(fd, pw, args); 4637 pw.flush(); 4638 pw.println(" ***************************************"); 4639 DcController dcc = mDcc; 4640 if (dcc != null) { 4641 if (mDataServiceBound) { 4642 dcc.dump(fd, pw, args); 4643 } else { 4644 pw.println(" Can't dump mDcc because data service is not bound."); 4645 } 4646 } else { 4647 pw.println(" mDcc=null"); 4648 } 4649 pw.println(" ***************************************"); 4650 HashMap<Integer, DataConnection> dcs = mDataConnections; 4651 if (dcs != null) { 4652 Set<Entry<Integer, DataConnection> > mDcSet = mDataConnections.entrySet(); 4653 pw.println(" mDataConnections: count=" + mDcSet.size()); 4654 for (Entry<Integer, DataConnection> entry : mDcSet) { 4655 pw.printf(" *** mDataConnection[%d] \n", entry.getKey()); 4656 entry.getValue().dump(fd, pw, args); 4657 } 4658 } else { 4659 pw.println("mDataConnections=null"); 4660 } 4661 pw.println(" ***************************************"); 4662 pw.flush(); 4663 HashMap<String, Integer> apnToDcId = mApnToDataConnectionId; 4664 if (apnToDcId != null) { 4665 Set<Entry<String, Integer>> apnToDcIdSet = apnToDcId.entrySet(); 4666 pw.println(" mApnToDataConnectonId size=" + apnToDcIdSet.size()); 4667 for (Entry<String, Integer> entry : apnToDcIdSet) { 4668 pw.printf(" mApnToDataConnectonId[%s]=%d\n", entry.getKey(), entry.getValue()); 4669 } 4670 } else { 4671 pw.println("mApnToDataConnectionId=null"); 4672 } 4673 pw.println(" ***************************************"); 4674 pw.flush(); 4675 ConcurrentHashMap<String, ApnContext> apnCtxs = mApnContexts; 4676 if (apnCtxs != null) { 4677 Set<Entry<String, ApnContext>> apnCtxsSet = apnCtxs.entrySet(); 4678 pw.println(" mApnContexts size=" + apnCtxsSet.size()); 4679 for (Entry<String, ApnContext> entry : apnCtxsSet) { 4680 entry.getValue().dump(fd, pw, args); 4681 } 4682 ApnContext.dumpLocalLog(fd, pw, args); 4683 pw.println(" ***************************************"); 4684 } else { 4685 pw.println(" mApnContexts=null"); 4686 } 4687 pw.flush(); 4688 4689 pw.println(" mAllApnSettings size=" + mAllApnSettings.size()); 4690 for (int i = 0; i < mAllApnSettings.size(); i++) { 4691 pw.printf(" mAllApnSettings[%d]: %s\n", i, mAllApnSettings.get(i)); 4692 } 4693 pw.flush(); 4694 4695 pw.println(" mPreferredApn=" + mPreferredApn); 4696 pw.println(" mIsPsRestricted=" + mIsPsRestricted); 4697 pw.println(" mIsDisposed=" + mIsDisposed); 4698 pw.println(" mIntentReceiver=" + mIntentReceiver); 4699 pw.println(" mReregisterOnReconnectFailure=" + mReregisterOnReconnectFailure); 4700 pw.println(" canSetPreferApn=" + mCanSetPreferApn); 4701 pw.println(" mApnObserver=" + mApnObserver); 4702 pw.println(" isAnyDataConnected=" + isAnyDataConnected()); 4703 pw.println(" mAttached=" + mAttached.get()); 4704 mDataEnabledSettings.dump(fd, pw, args); 4705 pw.flush(); 4706 } 4707 getPcscfAddress(String apnType)4708 public String[] getPcscfAddress(String apnType) { 4709 log("getPcscfAddress()"); 4710 ApnContext apnContext = null; 4711 4712 if(apnType == null){ 4713 log("apnType is null, return null"); 4714 return null; 4715 } 4716 4717 if (TextUtils.equals(apnType, ApnSetting.TYPE_EMERGENCY_STRING)) { 4718 apnContext = mApnContextsByType.get(ApnSetting.TYPE_EMERGENCY); 4719 } else if (TextUtils.equals(apnType, ApnSetting.TYPE_IMS_STRING)) { 4720 apnContext = mApnContextsByType.get(ApnSetting.TYPE_IMS); 4721 } else { 4722 log("apnType is invalid, return null"); 4723 return null; 4724 } 4725 4726 if (apnContext == null) { 4727 log("apnContext is null, return null"); 4728 return null; 4729 } 4730 4731 DataConnection dataConnection = apnContext.getDataConnection(); 4732 String[] result = null; 4733 4734 if (dataConnection != null) { 4735 result = dataConnection.getPcscfAddresses(); 4736 4737 if (result != null) { 4738 for (int i = 0; i < result.length; i++) { 4739 log("Pcscf[" + i + "]: " + result[i]); 4740 } 4741 } 4742 return result; 4743 } 4744 return null; 4745 } 4746 4747 /** 4748 * Create default apn settings for the apn type like emergency, and ims 4749 */ buildDefaultApnSetting(@onNull String entry, @NonNull String apn, @ApnType int apnTypeBitmask)4750 private ApnSetting buildDefaultApnSetting(@NonNull String entry, 4751 @NonNull String apn, @ApnType int apnTypeBitmask) { 4752 return new ApnSetting.Builder() 4753 .setEntryName(entry) 4754 .setProtocol(ApnSetting.PROTOCOL_IPV4V6) 4755 .setRoamingProtocol(ApnSetting.PROTOCOL_IPV4V6) 4756 .setApnName(apn) 4757 .setApnTypeBitmask(apnTypeBitmask) 4758 .setCarrierEnabled(true) 4759 .setApnSetId(Telephony.Carriers.MATCH_ALL_APN_SET_ID) 4760 .build(); 4761 } 4762 4763 /** 4764 * Add default APN settings to APN settings list as needed 4765 */ addDefaultApnSettingsAsNeeded()4766 private void addDefaultApnSettingsAsNeeded() { 4767 boolean isEmergencyApnConfigured = false; 4768 boolean isImsApnConfigured = false; 4769 4770 for (ApnSetting apn : mAllApnSettings) { 4771 if (apn.canHandleType(ApnSetting.TYPE_EMERGENCY)) { 4772 isEmergencyApnConfigured = true; 4773 } 4774 if (apn.canHandleType(ApnSetting.TYPE_IMS)) { 4775 isImsApnConfigured = true; 4776 } 4777 if (isEmergencyApnConfigured && isImsApnConfigured) { 4778 log("Both emergency and ims apn setting are already present"); 4779 return; 4780 } 4781 } 4782 4783 // Add default apn setting for emergency service if it is not present 4784 if (!isEmergencyApnConfigured) { 4785 mAllApnSettings.add(buildDefaultApnSetting( 4786 "DEFAULT EIMS", "sos", ApnSetting.TYPE_EMERGENCY)); 4787 log("default emergency apn is created"); 4788 } 4789 4790 // Only add default apn setting for ims when it is not present and sim is loaded 4791 if (!isImsApnConfigured && mSimState == TelephonyManager.SIM_STATE_LOADED) { 4792 mAllApnSettings.add(buildDefaultApnSetting( 4793 "DEFAULT IMS", "ims", ApnSetting.TYPE_IMS)); 4794 log("default ims apn is created"); 4795 } 4796 } 4797 cleanUpConnectionsOnUpdatedApns(boolean detach, String reason)4798 private void cleanUpConnectionsOnUpdatedApns(boolean detach, String reason) { 4799 if (DBG) log("cleanUpConnectionsOnUpdatedApns: detach=" + detach); 4800 if (mAllApnSettings.isEmpty()) { 4801 cleanUpAllConnectionsInternal(detach, Phone.REASON_APN_CHANGED); 4802 } else { 4803 if (getDataRat() == ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN) { 4804 // unknown rat is an exception for data rat change. Its only received when out of 4805 // service and is not applicable for apn bearer bitmask. We should bypass the check 4806 // of waiting apn list and keep the data connection on. 4807 return; 4808 } 4809 for (ApnContext apnContext : mApnContexts.values()) { 4810 boolean cleanupRequired = true; 4811 if (!apnContext.isDisconnected()) { 4812 ArrayList<ApnSetting> waitingApns = buildWaitingApns( 4813 apnContext.getApnType(), getDataRat()); 4814 if (apnContext.getWaitingApns().size() != waitingApns.size() 4815 || !apnContext.getWaitingApns().containsAll(waitingApns)) { 4816 apnContext.setWaitingApns(waitingApns); 4817 } 4818 for (ApnSetting apnSetting : waitingApns) { 4819 if (areCompatible(apnSetting, apnContext.getApnSetting())) { 4820 cleanupRequired = false; 4821 break; 4822 } 4823 } 4824 4825 if (cleanupRequired) { 4826 if (DBG) { 4827 log("cleanUpConnectionsOnUpdatedApns: APN type " 4828 + apnContext.getApnType() + " clean up is required. The new " 4829 + "waiting APN list " + waitingApns + " does not cover " 4830 + apnContext.getApnSetting()); 4831 } 4832 apnContext.setReason(reason); 4833 cleanUpConnectionInternal(true, RELEASE_TYPE_DETACH, apnContext); 4834 } 4835 } 4836 } 4837 } 4838 4839 if (!isAnyDataConnected()) { 4840 stopNetStatPoll(); 4841 stopDataStallAlarm(); 4842 } 4843 4844 mRequestedApnType = ApnSetting.TYPE_DEFAULT; 4845 4846 if (areAllDataDisconnected()) { 4847 notifyAllDataDisconnected(); 4848 } 4849 } 4850 4851 /** 4852 * Polling stuff 4853 */ resetPollStats()4854 protected void resetPollStats() { 4855 mTxPkts = -1; 4856 mRxPkts = -1; 4857 mNetStatPollPeriod = POLL_NETSTAT_MILLIS; 4858 } 4859 startNetStatPoll()4860 protected void startNetStatPoll() { 4861 if (isAnyDataConnected() && !mNetStatPollEnabled) { 4862 if (DBG) { 4863 log("startNetStatPoll"); 4864 } 4865 resetPollStats(); 4866 mNetStatPollEnabled = true; 4867 mPollNetStat.run(); 4868 } 4869 if (mPhone != null) { 4870 mPhone.notifyDataActivity(); 4871 } 4872 } 4873 stopNetStatPoll()4874 protected void stopNetStatPoll() { 4875 mNetStatPollEnabled = false; 4876 removeCallbacks(mPollNetStat); 4877 if (DBG) { 4878 log("stopNetStatPoll"); 4879 } 4880 4881 // To sync data activity icon in the case of switching data connection to send MMS. 4882 if (mPhone != null) { 4883 mPhone.notifyDataActivity(); 4884 } 4885 } 4886 sendStartNetStatPoll(DctConstants.Activity activity)4887 public void sendStartNetStatPoll(DctConstants.Activity activity) { 4888 Message msg = obtainMessage(DctConstants.CMD_NET_STAT_POLL); 4889 msg.arg1 = DctConstants.ENABLED; 4890 msg.obj = activity; 4891 sendMessage(msg); 4892 } 4893 handleStartNetStatPoll(DctConstants.Activity activity)4894 private void handleStartNetStatPoll(DctConstants.Activity activity) { 4895 startNetStatPoll(); 4896 startDataStallAlarm(DATA_STALL_NOT_SUSPECTED); 4897 setActivity(activity); 4898 } 4899 sendStopNetStatPoll(DctConstants.Activity activity)4900 public void sendStopNetStatPoll(DctConstants.Activity activity) { 4901 Message msg = obtainMessage(DctConstants.CMD_NET_STAT_POLL); 4902 msg.arg1 = DctConstants.DISABLED; 4903 msg.obj = activity; 4904 sendMessage(msg); 4905 } 4906 handleStopNetStatPoll(DctConstants.Activity activity)4907 private void handleStopNetStatPoll(DctConstants.Activity activity) { 4908 stopNetStatPoll(); 4909 stopDataStallAlarm(); 4910 setActivity(activity); 4911 } 4912 onDataEnabledOverrideRulesChanged()4913 private void onDataEnabledOverrideRulesChanged() { 4914 if (DBG) { 4915 log("onDataEnabledOverrideRulesChanged"); 4916 } 4917 4918 for (ApnContext apnContext : mPrioritySortedApnContexts) { 4919 if (isDataAllowed(apnContext, REQUEST_TYPE_NORMAL, null)) { 4920 if (apnContext.getDataConnection() != null) { 4921 apnContext.getDataConnection().reevaluateRestrictedState(); 4922 } 4923 setupDataOnConnectableApn(apnContext, Phone.REASON_DATA_ENABLED_OVERRIDE, 4924 RetryFailures.ALWAYS); 4925 } else if (shouldCleanUpConnection(apnContext, true, false)) { 4926 apnContext.setReason(Phone.REASON_DATA_ENABLED_OVERRIDE); 4927 cleanUpConnectionInternal(true, RELEASE_TYPE_DETACH, apnContext); 4928 } 4929 } 4930 } 4931 updateDataActivity()4932 private void updateDataActivity() { 4933 long sent, received; 4934 4935 DctConstants.Activity newActivity; 4936 4937 TxRxSum preTxRxSum = new TxRxSum(mTxPkts, mRxPkts); 4938 TxRxSum curTxRxSum = new TxRxSum(); 4939 curTxRxSum.updateTotalTxRxSum(); 4940 mTxPkts = curTxRxSum.txPkts; 4941 mRxPkts = curTxRxSum.rxPkts; 4942 4943 if (VDBG) { 4944 log("updateDataActivity: curTxRxSum=" + curTxRxSum + " preTxRxSum=" + preTxRxSum); 4945 } 4946 4947 if (mNetStatPollEnabled && (preTxRxSum.txPkts > 0 || preTxRxSum.rxPkts > 0)) { 4948 sent = mTxPkts - preTxRxSum.txPkts; 4949 received = mRxPkts - preTxRxSum.rxPkts; 4950 4951 if (VDBG) 4952 log("updateDataActivity: sent=" + sent + " received=" + received); 4953 if (sent > 0 && received > 0) { 4954 newActivity = DctConstants.Activity.DATAINANDOUT; 4955 } else if (sent > 0 && received == 0) { 4956 newActivity = DctConstants.Activity.DATAOUT; 4957 } else if (sent == 0 && received > 0) { 4958 newActivity = DctConstants.Activity.DATAIN; 4959 } else { 4960 newActivity = (mActivity == DctConstants.Activity.DORMANT) ? 4961 mActivity : DctConstants.Activity.NONE; 4962 } 4963 4964 if (mActivity != newActivity && mIsScreenOn) { 4965 if (VDBG) 4966 log("updateDataActivity: newActivity=" + newActivity); 4967 mActivity = newActivity; 4968 mPhone.notifyDataActivity(); 4969 } 4970 } 4971 } 4972 handlePcoData(AsyncResult ar)4973 private void handlePcoData(AsyncResult ar) { 4974 if (ar.exception != null) { 4975 loge("PCO_DATA exception: " + ar.exception); 4976 return; 4977 } 4978 PcoData pcoData = (PcoData)(ar.result); 4979 ArrayList<DataConnection> dcList = new ArrayList<>(); 4980 DataConnection temp = mDcc.getActiveDcByCid(pcoData.cid); 4981 if (temp != null) { 4982 dcList.add(temp); 4983 } 4984 if (dcList.size() == 0) { 4985 loge("PCO_DATA for unknown cid: " + pcoData.cid + ", inferring"); 4986 for (DataConnection dc : mDataConnections.values()) { 4987 final int cid = dc.getCid(); 4988 if (cid == pcoData.cid) { 4989 if (VDBG) log(" found " + dc); 4990 dcList.clear(); 4991 dcList.add(dc); 4992 break; 4993 } 4994 // check if this dc is still connecting 4995 if (cid == -1) { 4996 for (ApnContext apnContext : dc.getApnContexts()) { 4997 if (apnContext.getState() == DctConstants.State.CONNECTING) { 4998 if (VDBG) log(" found potential " + dc); 4999 dcList.add(dc); 5000 break; 5001 } 5002 } 5003 } 5004 } 5005 } 5006 if (dcList.size() == 0) { 5007 loge("PCO_DATA - couldn't infer cid"); 5008 return; 5009 } 5010 for (DataConnection dc : dcList) { 5011 List<ApnContext> apnContextList = dc.getApnContexts(); 5012 if (apnContextList.size() == 0) { 5013 break; 5014 } 5015 // send one out for each apn type in play 5016 for (ApnContext apnContext : apnContextList) { 5017 String apnType = apnContext.getApnType(); 5018 5019 final Intent intent = new Intent(TelephonyManager.ACTION_CARRIER_SIGNAL_PCO_VALUE); 5020 intent.putExtra(TelephonyManager.EXTRA_APN_TYPE, 5021 ApnSetting.getApnTypesBitmaskFromString(apnType)); 5022 intent.putExtra(TelephonyManager.EXTRA_APN_PROTOCOL, 5023 ApnSetting.getProtocolIntFromString(pcoData.bearerProto)); 5024 intent.putExtra(TelephonyManager.EXTRA_PCO_ID, pcoData.pcoId); 5025 intent.putExtra(TelephonyManager.EXTRA_PCO_VALUE, pcoData.contents); 5026 mPhone.getCarrierSignalAgent().notifyCarrierSignalReceivers(intent); 5027 } 5028 } 5029 } 5030 5031 /** 5032 * Data-Stall 5033 */ 5034 5035 // Recovery action taken in case of data stall 5036 @IntDef( 5037 value = { 5038 RECOVERY_ACTION_GET_DATA_CALL_LIST, 5039 RECOVERY_ACTION_CLEANUP, 5040 RECOVERY_ACTION_REREGISTER, 5041 RECOVERY_ACTION_RADIO_RESTART 5042 }) 5043 @Retention(RetentionPolicy.SOURCE) 5044 public @interface RecoveryAction {}; 5045 private static final int RECOVERY_ACTION_GET_DATA_CALL_LIST = 0; 5046 private static final int RECOVERY_ACTION_CLEANUP = 1; 5047 private static final int RECOVERY_ACTION_REREGISTER = 2; 5048 private static final int RECOVERY_ACTION_RADIO_RESTART = 3; 5049 5050 // Recovery handler class for cellular data stall 5051 private class DataStallRecoveryHandler { 5052 // Default minimum duration between each recovery steps 5053 private static final int 5054 DEFAULT_MIN_DURATION_BETWEEN_RECOVERY_STEPS_IN_MS = (3 * 60 * 1000); // 3 mins 5055 5056 // The elapsed real time of last recovery attempted 5057 private long mTimeLastRecoveryStartMs; 5058 // Whether current network good or not 5059 private boolean mIsValidNetwork; 5060 // Whether data stall happened or not. 5061 private boolean mWasDataStall; 5062 // Whether the result of last action(RADIO_RESTART) reported. 5063 private boolean mLastActionReported; 5064 // The real time for data stall start. 5065 private long mDataStallStartMs; 5066 // Last data stall action. 5067 private @RecoveryAction int mLastAction; 5068 DataStallRecoveryHandler()5069 public DataStallRecoveryHandler() { 5070 reset(); 5071 } 5072 reset()5073 public void reset() { 5074 mTimeLastRecoveryStartMs = 0; 5075 putRecoveryAction(RECOVERY_ACTION_GET_DATA_CALL_LIST); 5076 } 5077 setNetworkValidationState(boolean isValid)5078 private void setNetworkValidationState(boolean isValid) { 5079 // Validation status is true and was not data stall. 5080 if (isValid && !mWasDataStall) { 5081 return; 5082 } 5083 5084 if (!mWasDataStall) { 5085 mWasDataStall = true; 5086 mDataStallStartMs = SystemClock.elapsedRealtime(); 5087 if (DBG) log("data stall: start time = " + mDataStallStartMs); 5088 return; 5089 } 5090 5091 if (!mLastActionReported) { 5092 int timeDuration = (int) (SystemClock.elapsedRealtime() - mDataStallStartMs); 5093 if (DBG) { 5094 log("data stall: lastaction = " + mLastAction + ", isRecovered = " 5095 + isValid + ", mTimeDuration = " + timeDuration); 5096 } 5097 DataStallRecoveryStats.onDataStallEvent(mLastAction, mPhone, isValid, 5098 timeDuration); 5099 mLastActionReported = true; 5100 } 5101 5102 if (isValid) { 5103 mLastActionReported = false; 5104 mWasDataStall = false; 5105 } 5106 } 5107 isAggressiveRecovery()5108 public boolean isAggressiveRecovery() { 5109 @RecoveryAction int action = getRecoveryAction(); 5110 5111 return ((action == RECOVERY_ACTION_CLEANUP) 5112 || (action == RECOVERY_ACTION_REREGISTER) 5113 || (action == RECOVERY_ACTION_RADIO_RESTART)); 5114 } 5115 getMinDurationBetweenRecovery()5116 private long getMinDurationBetweenRecovery() { 5117 return Settings.Global.getLong(mResolver, 5118 Settings.Global.MIN_DURATION_BETWEEN_RECOVERY_STEPS_IN_MS, 5119 DEFAULT_MIN_DURATION_BETWEEN_RECOVERY_STEPS_IN_MS); 5120 } 5121 getElapsedTimeSinceRecoveryMs()5122 private long getElapsedTimeSinceRecoveryMs() { 5123 return (SystemClock.elapsedRealtime() - mTimeLastRecoveryStartMs); 5124 } 5125 5126 @RecoveryAction getRecoveryAction()5127 private int getRecoveryAction() { 5128 @RecoveryAction int action = Settings.System.getInt(mResolver, 5129 "radio.data.stall.recovery.action", RECOVERY_ACTION_GET_DATA_CALL_LIST); 5130 if (VDBG_STALL) log("getRecoveryAction: " + action); 5131 return action; 5132 } 5133 putRecoveryAction(@ecoveryAction int action)5134 private void putRecoveryAction(@RecoveryAction int action) { 5135 Settings.System.putInt(mResolver, "radio.data.stall.recovery.action", action); 5136 if (VDBG_STALL) log("putRecoveryAction: " + action); 5137 } 5138 broadcastDataStallDetected(@ecoveryAction int recoveryAction)5139 private void broadcastDataStallDetected(@RecoveryAction int recoveryAction) { 5140 Intent intent = new Intent(TelephonyManager.ACTION_DATA_STALL_DETECTED); 5141 SubscriptionManager.putPhoneIdAndSubIdExtra(intent, mPhone.getPhoneId()); 5142 intent.putExtra(TelephonyManager.EXTRA_RECOVERY_ACTION, recoveryAction); 5143 mPhone.getContext().sendBroadcast(intent, READ_PRIVILEGED_PHONE_STATE); 5144 } 5145 isRecoveryAlreadyStarted()5146 private boolean isRecoveryAlreadyStarted() { 5147 return getRecoveryAction() != RECOVERY_ACTION_GET_DATA_CALL_LIST; 5148 } 5149 checkRecovery()5150 private boolean checkRecovery() { 5151 // To avoid back to back recovery wait for a grace period 5152 if (getElapsedTimeSinceRecoveryMs() < getMinDurationBetweenRecovery()) { 5153 if (VDBG_STALL) log("skip back to back data stall recovery"); 5154 return false; 5155 } 5156 5157 // Skip recovery if it can cause a call to drop 5158 if (mPhone.getState() != PhoneConstants.State.IDLE 5159 && getRecoveryAction() > RECOVERY_ACTION_CLEANUP) { 5160 if (VDBG_STALL) log("skip data stall recovery as there is an active call"); 5161 return false; 5162 } 5163 5164 // Allow recovery if data is expected to work 5165 return mAttached.get() && isDataAllowed(null); 5166 } 5167 triggerRecovery()5168 private void triggerRecovery() { 5169 // Updating the recovery start time early to avoid race when 5170 // the message is being processed in the Queue 5171 mTimeLastRecoveryStartMs = SystemClock.elapsedRealtime(); 5172 sendMessage(obtainMessage(DctConstants.EVENT_DO_RECOVERY)); 5173 } 5174 doRecovery()5175 public void doRecovery() { 5176 if (isAnyDataConnected()) { 5177 // Go through a series of recovery steps, each action transitions to the next action 5178 @RecoveryAction final int recoveryAction = getRecoveryAction(); 5179 final int signalStrength = mPhone.getSignalStrength().getLevel(); 5180 TelephonyMetrics.getInstance().writeSignalStrengthEvent( 5181 mPhone.getPhoneId(), signalStrength); 5182 TelephonyMetrics.getInstance().writeDataStallEvent( 5183 mPhone.getPhoneId(), recoveryAction); 5184 mLastAction = recoveryAction; 5185 mLastActionReported = false; 5186 broadcastDataStallDetected(recoveryAction); 5187 5188 switch (recoveryAction) { 5189 case RECOVERY_ACTION_GET_DATA_CALL_LIST: 5190 EventLog.writeEvent(EventLogTags.DATA_STALL_RECOVERY_GET_DATA_CALL_LIST, 5191 mSentSinceLastRecv); 5192 if (DBG) log("doRecovery() get data call list"); 5193 mDataServiceManager.requestDataCallList(obtainMessage()); 5194 putRecoveryAction(RECOVERY_ACTION_CLEANUP); 5195 break; 5196 case RECOVERY_ACTION_CLEANUP: 5197 EventLog.writeEvent(EventLogTags.DATA_STALL_RECOVERY_CLEANUP, 5198 mSentSinceLastRecv); 5199 if (DBG) log("doRecovery() cleanup all connections"); 5200 cleanUpConnection(mApnContexts.get(ApnSetting.getApnTypeString( 5201 ApnSetting.TYPE_DEFAULT))); 5202 cleanUpConnection(mApnContexts.get(ApnSetting.getApnTypeString( 5203 ApnSetting.TYPE_ENTERPRISE))); 5204 putRecoveryAction(RECOVERY_ACTION_REREGISTER); 5205 break; 5206 case RECOVERY_ACTION_REREGISTER: 5207 EventLog.writeEvent(EventLogTags.DATA_STALL_RECOVERY_REREGISTER, 5208 mSentSinceLastRecv); 5209 if (DBG) log("doRecovery() re-register"); 5210 mPhone.getServiceStateTracker().reRegisterNetwork(null); 5211 putRecoveryAction(RECOVERY_ACTION_RADIO_RESTART); 5212 break; 5213 case RECOVERY_ACTION_RADIO_RESTART: 5214 EventLog.writeEvent(EventLogTags.DATA_STALL_RECOVERY_RADIO_RESTART, 5215 mSentSinceLastRecv); 5216 if (DBG) log("restarting radio"); 5217 restartRadio(); 5218 reset(); 5219 break; 5220 default: 5221 throw new RuntimeException("doRecovery: Invalid recoveryAction=" 5222 + recoveryAction); 5223 } 5224 mSentSinceLastRecv = 0; 5225 } 5226 } 5227 processNetworkStatusChanged(boolean isValid)5228 public void processNetworkStatusChanged(boolean isValid) { 5229 setNetworkValidationState(isValid); 5230 if (isValid) { 5231 mIsValidNetwork = true; 5232 reset(); 5233 } else { 5234 if (mIsValidNetwork || isRecoveryAlreadyStarted()) { 5235 mIsValidNetwork = false; 5236 // Check and trigger a recovery if network switched from good 5237 // to bad or recovery is already started before. 5238 if (checkRecovery()) { 5239 if (DBG) log("trigger data stall recovery"); 5240 triggerRecovery(); 5241 } 5242 } 5243 } 5244 } 5245 isRecoveryOnBadNetworkEnabled()5246 public boolean isRecoveryOnBadNetworkEnabled() { 5247 return Settings.Global.getInt(mResolver, 5248 Settings.Global.DATA_STALL_RECOVERY_ON_BAD_NETWORK, 1) == 1; 5249 } 5250 isNoRxDataStallDetectionEnabled()5251 public boolean isNoRxDataStallDetectionEnabled() { 5252 return mDataStallNoRxEnabled && !isRecoveryOnBadNetworkEnabled(); 5253 } 5254 } 5255 updateDataStallInfo()5256 private void updateDataStallInfo() { 5257 long sent, received; 5258 5259 TxRxSum preTxRxSum = new TxRxSum(mDataStallTxRxSum); 5260 mDataStallTxRxSum.updateTotalTxRxSum(); 5261 5262 if (VDBG_STALL) { 5263 log("updateDataStallInfo: mDataStallTxRxSum=" + mDataStallTxRxSum + 5264 " preTxRxSum=" + preTxRxSum); 5265 } 5266 5267 sent = mDataStallTxRxSum.txPkts - preTxRxSum.txPkts; 5268 received = mDataStallTxRxSum.rxPkts - preTxRxSum.rxPkts; 5269 5270 if (RADIO_TESTS) { 5271 if (SystemProperties.getBoolean("radio.test.data.stall", false)) { 5272 log("updateDataStallInfo: radio.test.data.stall true received = 0;"); 5273 received = 0; 5274 } 5275 } 5276 if ( sent > 0 && received > 0 ) { 5277 if (VDBG_STALL) log("updateDataStallInfo: IN/OUT"); 5278 mSentSinceLastRecv = 0; 5279 mDsRecoveryHandler.reset(); 5280 } else if (sent > 0 && received == 0) { 5281 if (isPhoneStateIdle()) { 5282 mSentSinceLastRecv += sent; 5283 } else { 5284 mSentSinceLastRecv = 0; 5285 } 5286 if (DBG) { 5287 log("updateDataStallInfo: OUT sent=" + sent + 5288 " mSentSinceLastRecv=" + mSentSinceLastRecv); 5289 } 5290 } else if (sent == 0 && received > 0) { 5291 if (VDBG_STALL) log("updateDataStallInfo: IN"); 5292 mSentSinceLastRecv = 0; 5293 mDsRecoveryHandler.reset(); 5294 } else { 5295 if (VDBG_STALL) log("updateDataStallInfo: NONE"); 5296 } 5297 } 5298 isPhoneStateIdle()5299 private boolean isPhoneStateIdle() { 5300 for (int i = 0; i < mTelephonyManager.getPhoneCount(); i++) { 5301 Phone phone = PhoneFactory.getPhone(i); 5302 if (phone != null && phone.getState() != PhoneConstants.State.IDLE) { 5303 log("isPhoneStateIdle false: Voice call active on phone " + i); 5304 return false; 5305 } 5306 } 5307 return true; 5308 } 5309 onDataStallAlarm(int tag)5310 private void onDataStallAlarm(int tag) { 5311 if (mDataStallAlarmTag != tag) { 5312 if (DBG) { 5313 log("onDataStallAlarm: ignore, tag=" + tag + " expecting " + mDataStallAlarmTag); 5314 } 5315 return; 5316 } 5317 5318 if (DBG) log("Data stall alarm"); 5319 updateDataStallInfo(); 5320 5321 int hangWatchdogTrigger = Settings.Global.getInt(mResolver, 5322 Settings.Global.PDP_WATCHDOG_TRIGGER_PACKET_COUNT, 5323 NUMBER_SENT_PACKETS_OF_HANG); 5324 5325 boolean suspectedStall = DATA_STALL_NOT_SUSPECTED; 5326 if (mSentSinceLastRecv >= hangWatchdogTrigger) { 5327 if (DBG) { 5328 log("onDataStallAlarm: tag=" + tag + " do recovery action=" 5329 + mDsRecoveryHandler.getRecoveryAction()); 5330 } 5331 suspectedStall = DATA_STALL_SUSPECTED; 5332 sendMessage(obtainMessage(DctConstants.EVENT_DO_RECOVERY)); 5333 } else { 5334 if (VDBG_STALL) { 5335 log("onDataStallAlarm: tag=" + tag + " Sent " + String.valueOf(mSentSinceLastRecv) + 5336 " pkts since last received, < watchdogTrigger=" + hangWatchdogTrigger); 5337 } 5338 } 5339 startDataStallAlarm(suspectedStall); 5340 } 5341 startDataStallAlarm(boolean suspectedStall)5342 protected void startDataStallAlarm(boolean suspectedStall) { 5343 int delayInMs; 5344 5345 if (mDsRecoveryHandler.isNoRxDataStallDetectionEnabled() && isAnyDataConnected()) { 5346 // If screen is on or data stall is currently suspected, set the alarm 5347 // with an aggressive timeout. 5348 if (mIsScreenOn || suspectedStall || mDsRecoveryHandler.isAggressiveRecovery()) { 5349 delayInMs = Settings.Global.getInt(mResolver, 5350 Settings.Global.DATA_STALL_ALARM_AGGRESSIVE_DELAY_IN_MS, 5351 DATA_STALL_ALARM_AGGRESSIVE_DELAY_IN_MS_DEFAULT); 5352 } else { 5353 delayInMs = Settings.Global.getInt(mResolver, 5354 Settings.Global.DATA_STALL_ALARM_NON_AGGRESSIVE_DELAY_IN_MS, 5355 DATA_STALL_ALARM_NON_AGGRESSIVE_DELAY_IN_MS_DEFAULT); 5356 } 5357 5358 mDataStallAlarmTag += 1; 5359 if (VDBG_STALL) { 5360 log("startDataStallAlarm: tag=" + mDataStallAlarmTag + 5361 " delay=" + (delayInMs / 1000) + "s"); 5362 } 5363 Intent intent = new Intent(INTENT_DATA_STALL_ALARM); 5364 intent.putExtra(INTENT_DATA_STALL_ALARM_EXTRA_TAG, mDataStallAlarmTag); 5365 intent.putExtra(INTENT_DATA_STALL_ALARM_EXTRA_TRANSPORT_TYPE, mTransportType); 5366 SubscriptionManager.putPhoneIdAndSubIdExtra(intent, mPhone.getPhoneId()); 5367 mDataStallAlarmIntent = PendingIntent.getBroadcast(mPhone.getContext(), 0, intent, 5368 PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE); 5369 mAlarmManager.set(AlarmManager.ELAPSED_REALTIME, 5370 SystemClock.elapsedRealtime() + delayInMs, mDataStallAlarmIntent); 5371 } else { 5372 if (VDBG_STALL) { 5373 log("startDataStallAlarm: NOT started, no connection tag=" + mDataStallAlarmTag); 5374 } 5375 } 5376 } 5377 stopDataStallAlarm()5378 private void stopDataStallAlarm() { 5379 if (VDBG_STALL) { 5380 log("stopDataStallAlarm: current tag=" + mDataStallAlarmTag + 5381 " mDataStallAlarmIntent=" + mDataStallAlarmIntent); 5382 } 5383 mDataStallAlarmTag += 1; 5384 if (mDataStallAlarmIntent != null) { 5385 mAlarmManager.cancel(mDataStallAlarmIntent); 5386 mDataStallAlarmIntent = null; 5387 } 5388 } 5389 restartDataStallAlarm()5390 private void restartDataStallAlarm() { 5391 if (!isAnyDataConnected()) return; 5392 // To be called on screen status change. 5393 // Do not cancel the alarm if it is set with aggressive timeout. 5394 if (mDsRecoveryHandler.isAggressiveRecovery()) { 5395 if (DBG) log("restartDataStallAlarm: action is pending. not resetting the alarm."); 5396 return; 5397 } 5398 if (VDBG_STALL) log("restartDataStallAlarm: stop then start."); 5399 stopDataStallAlarm(); 5400 startDataStallAlarm(DATA_STALL_NOT_SUSPECTED); 5401 } 5402 5403 /** 5404 * Provisioning APN 5405 */ onActionIntentProvisioningApnAlarm(Intent intent)5406 private void onActionIntentProvisioningApnAlarm(Intent intent) { 5407 if (DBG) log("onActionIntentProvisioningApnAlarm: action=" + intent.getAction()); 5408 Message msg = obtainMessage(DctConstants.EVENT_PROVISIONING_APN_ALARM, 5409 intent.getAction()); 5410 msg.arg1 = intent.getIntExtra(PROVISIONING_APN_ALARM_TAG_EXTRA, 0); 5411 sendMessage(msg); 5412 } 5413 startProvisioningApnAlarm()5414 private void startProvisioningApnAlarm() { 5415 int delayInMs = Settings.Global.getInt(mResolver, 5416 Settings.Global.PROVISIONING_APN_ALARM_DELAY_IN_MS, 5417 PROVISIONING_APN_ALARM_DELAY_IN_MS_DEFAULT); 5418 if (TelephonyUtils.IS_DEBUGGABLE) { 5419 // Allow debug code to use a system property to provide another value 5420 String delayInMsStrg = Integer.toString(delayInMs); 5421 delayInMsStrg = System.getProperty(DEBUG_PROV_APN_ALARM, delayInMsStrg); 5422 try { 5423 delayInMs = Integer.parseInt(delayInMsStrg); 5424 } catch (NumberFormatException e) { 5425 loge("startProvisioningApnAlarm: e=" + e); 5426 } 5427 } 5428 mProvisioningApnAlarmTag += 1; 5429 if (DBG) { 5430 log("startProvisioningApnAlarm: tag=" + mProvisioningApnAlarmTag + 5431 " delay=" + (delayInMs / 1000) + "s"); 5432 } 5433 Intent intent = new Intent(INTENT_PROVISIONING_APN_ALARM); 5434 intent.putExtra(PROVISIONING_APN_ALARM_TAG_EXTRA, mProvisioningApnAlarmTag); 5435 mProvisioningApnAlarmIntent = PendingIntent.getBroadcast(mPhone.getContext(), 0, intent, 5436 PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE); 5437 mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, 5438 SystemClock.elapsedRealtime() + delayInMs, mProvisioningApnAlarmIntent); 5439 } 5440 stopProvisioningApnAlarm()5441 private void stopProvisioningApnAlarm() { 5442 if (DBG) { 5443 log("stopProvisioningApnAlarm: current tag=" + mProvisioningApnAlarmTag + 5444 " mProvsioningApnAlarmIntent=" + mProvisioningApnAlarmIntent); 5445 } 5446 mProvisioningApnAlarmTag += 1; 5447 if (mProvisioningApnAlarmIntent != null) { 5448 mAlarmManager.cancel(mProvisioningApnAlarmIntent); 5449 mProvisioningApnAlarmIntent = null; 5450 } 5451 } 5452 5453 /** 5454 * 5G connection reevaluation alarm 5455 */ startWatchdogAlarm()5456 private void startWatchdogAlarm() { 5457 sendMessageDelayed(obtainMessage(DctConstants.EVENT_NR_TIMER_WATCHDOG), mWatchdogTimeMs); 5458 mWatchdog = true; 5459 } 5460 stopWatchdogAlarm()5461 private void stopWatchdogAlarm() { 5462 removeMessages(DctConstants.EVENT_NR_TIMER_WATCHDOG); 5463 mWatchdog = false; 5464 } 5465 onDataServiceBindingChanged(boolean bound)5466 private void onDataServiceBindingChanged(boolean bound) { 5467 if (!bound) { 5468 if (mTransportType == AccessNetworkConstants.TRANSPORT_TYPE_WLAN) { 5469 boolean connPersistenceOnRestart = mPhone.getContext().getResources() 5470 .getBoolean(com.android 5471 .internal.R.bool.config_wlan_data_service_conn_persistence_on_restart); 5472 if (!connPersistenceOnRestart) { 5473 cleanUpAllConnectionsInternal(false, Phone.REASON_IWLAN_DATA_SERVICE_DIED); 5474 } 5475 } 5476 } else { 5477 //reset throttling after binding to data service 5478 mDataThrottler.reset(); 5479 } 5480 mDataServiceBound = bound; 5481 } 5482 requestTypeToString(@equestNetworkType int type)5483 public static String requestTypeToString(@RequestNetworkType int type) { 5484 switch (type) { 5485 case REQUEST_TYPE_NORMAL: return "NORMAL"; 5486 case REQUEST_TYPE_HANDOVER: return "HANDOVER"; 5487 } 5488 return "UNKNOWN"; 5489 } 5490 releaseTypeToString(@eleaseNetworkType int type)5491 public static String releaseTypeToString(@ReleaseNetworkType int type) { 5492 switch (type) { 5493 case RELEASE_TYPE_NORMAL: return "NORMAL"; 5494 case RELEASE_TYPE_DETACH: return "DETACH"; 5495 case RELEASE_TYPE_HANDOVER: return "HANDOVER"; 5496 } 5497 return "UNKNOWN"; 5498 } 5499 5500 @RilRadioTechnology getDataRat()5501 protected int getDataRat() { 5502 ServiceState ss = mPhone.getServiceState(); 5503 NetworkRegistrationInfo nrs = ss.getNetworkRegistrationInfo( 5504 NetworkRegistrationInfo.DOMAIN_PS, mTransportType); 5505 if (nrs != null) { 5506 return ServiceState.networkTypeToRilRadioTechnology(nrs.getAccessNetworkTechnology()); 5507 } 5508 return ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN; 5509 } 5510 5511 @RilRadioTechnology getVoiceRat()5512 private int getVoiceRat() { 5513 ServiceState ss = mPhone.getServiceState(); 5514 NetworkRegistrationInfo nrs = ss.getNetworkRegistrationInfo( 5515 NetworkRegistrationInfo.DOMAIN_CS, mTransportType); 5516 if (nrs != null) { 5517 return ServiceState.networkTypeToRilRadioTechnology(nrs.getAccessNetworkTechnology()); 5518 } 5519 return ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN; 5520 } 5521 read5GConfiguration()5522 private void read5GConfiguration() { 5523 if (DBG) log("read5GConfiguration"); 5524 String[] bandwidths = CarrierConfigManager.getDefaultConfig().getStringArray( 5525 CarrierConfigManager.KEY_BANDWIDTH_STRING_ARRAY); 5526 boolean useLte = false; 5527 CarrierConfigManager configManager = (CarrierConfigManager) mPhone.getContext() 5528 .getSystemService(Context.CARRIER_CONFIG_SERVICE); 5529 if (configManager != null) { 5530 PersistableBundle b = configManager.getConfigForSubId(mPhone.getSubId()); 5531 if (b != null) { 5532 if (b.getStringArray(CarrierConfigManager.KEY_BANDWIDTH_STRING_ARRAY) != null) { 5533 bandwidths = b.getStringArray(CarrierConfigManager.KEY_BANDWIDTH_STRING_ARRAY); 5534 } 5535 useLte = b.getBoolean(CarrierConfigManager 5536 .KEY_BANDWIDTH_NR_NSA_USE_LTE_VALUE_FOR_UPLINK_BOOL); 5537 mWatchdogTimeMs = b.getLong(CarrierConfigManager.KEY_5G_WATCHDOG_TIME_MS_LONG); 5538 mNrNsaAllUnmetered = b.getBoolean(CarrierConfigManager.KEY_UNMETERED_NR_NSA_BOOL); 5539 mNrNsaMmwaveUnmetered = b.getBoolean( 5540 CarrierConfigManager.KEY_UNMETERED_NR_NSA_MMWAVE_BOOL); 5541 mNrNsaSub6Unmetered = b.getBoolean( 5542 CarrierConfigManager.KEY_UNMETERED_NR_NSA_SUB6_BOOL); 5543 mNrSaAllUnmetered = b.getBoolean(CarrierConfigManager.KEY_UNMETERED_NR_SA_BOOL); 5544 mNrSaMmwaveUnmetered = b.getBoolean( 5545 CarrierConfigManager.KEY_UNMETERED_NR_SA_MMWAVE_BOOL); 5546 mNrSaSub6Unmetered = b.getBoolean( 5547 CarrierConfigManager.KEY_UNMETERED_NR_SA_SUB6_BOOL); 5548 mNrNsaRoamingUnmetered = b.getBoolean( 5549 CarrierConfigManager.KEY_UNMETERED_NR_NSA_WHEN_ROAMING_BOOL); 5550 mLteEndcUsingUserDataForRrcDetection = b.getBoolean( 5551 CarrierConfigManager.KEY_LTE_ENDC_USING_USER_DATA_FOR_RRC_DETECTION_BOOL); 5552 } 5553 } 5554 updateLinkBandwidths(bandwidths, useLte); 5555 } 5556 getLteEndcUsingUserDataForIdleDetection()5557 public boolean getLteEndcUsingUserDataForIdleDetection() { 5558 return mLteEndcUsingUserDataForRrcDetection; 5559 } 5560 5561 /** 5562 * Register for physical link status (i.e. RRC state) changed event. 5563 * if {@link CarrierConfigManager.KEY_LTE_ENDC_USING_USER_DATA_FOR_RRC_DETECTION_BOOL} is true, 5564 * then physical link state is focusing on "internet data connection" instead of RRC state. 5565 * 5566 * @param h The handler 5567 * @param what The event 5568 */ registerForPhysicalLinkStatusChanged(Handler h, int what)5569 public void registerForPhysicalLinkStatusChanged(Handler h, int what) { 5570 mDcc.registerForPhysicalLinkStatusChanged(h, what); 5571 } 5572 5573 /** 5574 * Unregister from physical link status (i.e. RRC state) changed event. 5575 * 5576 * @param h The previously registered handler 5577 */ unregisterForPhysicalLinkStatusChanged(Handler h)5578 public void unregisterForPhysicalLinkStatusChanged(Handler h) { 5579 mDcc.unregisterForPhysicalLinkStatusChanged(h); 5580 } 5581 5582 // We use a specialized equals function in Apn setting when checking if an active 5583 // data connection is still legitimate to use against a different apn setting. 5584 // This method is extracted to a function to ensure that any future changes to this check will 5585 // be applied to both cleanUpConnectionsOnUpdatedApns and checkForCompatibleDataConnection. 5586 // Fix for b/158908392. areCompatible(ApnSetting apnSetting1, ApnSetting apnSetting2)5587 private boolean areCompatible(ApnSetting apnSetting1, ApnSetting apnSetting2) { 5588 return apnSetting1.equals(apnSetting2, 5589 mPhone.getServiceState().getDataRoamingFromRegistration()); 5590 } 5591 5592 @NonNull getCarrierConfig()5593 private PersistableBundle getCarrierConfig() { 5594 CarrierConfigManager configManager = (CarrierConfigManager) mPhone.getContext() 5595 .getSystemService(Context.CARRIER_CONFIG_SERVICE); 5596 if (configManager != null) { 5597 // If an invalid subId is used, this bundle will contain default values. 5598 PersistableBundle config = configManager.getConfigForSubId(mPhone.getSubId()); 5599 if (config != null) { 5600 return config; 5601 } 5602 } 5603 // Return static default defined in CarrierConfigManager. 5604 return CarrierConfigManager.getDefaultConfig(); 5605 } 5606 5607 /** 5608 * @return The data service manager. 5609 */ getDataServiceManager()5610 public @NonNull DataServiceManager getDataServiceManager() { 5611 return mDataServiceManager; 5612 } 5613 5614 /** 5615 * @return The data throttler 5616 */ getDataThrottler()5617 public @NonNull DataThrottler getDataThrottler() { 5618 return mDataThrottler; 5619 } 5620 showProvisioningNotification()5621 private void showProvisioningNotification() { 5622 final Intent intent = new Intent(DcTracker.INTENT_PROVISION); 5623 intent.putExtra(DcTracker.EXTRA_PROVISION_PHONE_ID, mPhone.getPhoneId()); 5624 final PendingIntent pendingIntent = PendingIntent.getBroadcast( 5625 mPhone.getContext(), 0 /* requestCode */, intent, PendingIntent.FLAG_IMMUTABLE); 5626 5627 final Resources r = mPhone.getContext().getResources(); 5628 final String title = r.getString(R.string.network_available_sign_in, 0); 5629 final String details = mTelephonyManager.getNetworkOperator(mPhone.getSubId()); 5630 final Notification.Builder builder = new Notification.Builder(mPhone.getContext()) 5631 .setWhen(System.currentTimeMillis()) 5632 .setSmallIcon(R.drawable.stat_notify_rssi_in_range) 5633 .setChannelId(NotificationChannelController.CHANNEL_ID_MOBILE_DATA_STATUS) 5634 .setAutoCancel(true) 5635 .setTicker(title) 5636 .setColor(mPhone.getContext().getColor( 5637 com.android.internal.R.color.system_notification_accent_color)) 5638 .setContentTitle(title) 5639 .setContentText(details) 5640 .setContentIntent(pendingIntent) 5641 .setLocalOnly(true) 5642 .setOnlyAlertOnce(true); 5643 5644 final Notification notification = builder.build(); 5645 try { 5646 getNotificationManager().notify(NOTIFICATION_TAG, mPhone.getPhoneId(), notification); 5647 } catch (final NullPointerException npe) { 5648 Log.e(mLogTag, "showProvisioningNotification: error showing notification", npe); 5649 } 5650 } 5651 hideProvisioningNotification()5652 private void hideProvisioningNotification() { 5653 try { 5654 getNotificationManager().cancel(NOTIFICATION_TAG, mPhone.getPhoneId()); 5655 } catch (final NullPointerException npe) { 5656 Log.e(mLogTag, "hideProvisioningNotification: error hiding notification", npe); 5657 } 5658 } 5659 getNotificationManager()5660 private NotificationManager getNotificationManager() { 5661 return (NotificationManager) mPhone.getContext() 5662 .createContextAsUser(UserHandle.ALL, 0 /* flags */) 5663 .getSystemService(Context.NOTIFICATION_SERVICE); 5664 } 5665 } 5666