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