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