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