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